]> git.proxmox.com Git - mirror_qemu.git/blame - target/arm/translate.c
Merge remote-tracking branch 'remotes/vivier2/tags/trivial-branch-pull-request' into...
[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"
36a71934 28#include "tcg-op-gvec.h"
1de7afc9 29#include "qemu/log.h"
534df156 30#include "qemu/bitops.h"
1d854765 31#include "arm_ldst.h"
f1672e6f 32#include "hw/semihosting/semihost.h"
1497c961 33
2ef6175a
RH
34#include "exec/helper-proto.h"
35#include "exec/helper-gen.h"
2c0262af 36
a7e30d84 37#include "trace-tcg.h"
508127e2 38#include "exec/log.h"
a7e30d84
LV
39
40
2b51668f
PM
41#define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T)
42#define ENABLE_ARCH_5 arm_dc_feature(s, ARM_FEATURE_V5)
be5e7a76 43/* currently all emulated v5 cores are also v5TE, so don't bother */
2b51668f 44#define ENABLE_ARCH_5TE arm_dc_feature(s, ARM_FEATURE_V5)
09cbd501 45#define ENABLE_ARCH_5J dc_isar_feature(jazelle, s)
2b51668f
PM
46#define ENABLE_ARCH_6 arm_dc_feature(s, ARM_FEATURE_V6)
47#define ENABLE_ARCH_6K arm_dc_feature(s, ARM_FEATURE_V6K)
48#define ENABLE_ARCH_6T2 arm_dc_feature(s, ARM_FEATURE_THUMB2)
49#define ENABLE_ARCH_7 arm_dc_feature(s, ARM_FEATURE_V7)
50#define ENABLE_ARCH_8 arm_dc_feature(s, ARM_FEATURE_V8)
b5ff1b31 51
86753403 52#define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
b5ff1b31 53
f570c61e 54#include "translate.h"
e12ce78d 55
b5ff1b31
FB
56#if defined(CONFIG_USER_ONLY)
57#define IS_USER(s) 1
58#else
59#define IS_USER(s) (s->user)
60#endif
61
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
022c62cb 69#include "exec/gen-icount.h"
2e70f6ef 70
308e5636 71static const char * const regnames[] =
155c3eac
FN
72 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
73 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
74
61adacc8
RH
75/* Function prototypes for gen_ functions calling Neon helpers. */
76typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32,
77 TCGv_i32, TCGv_i32);
c253dd78
PM
78/* Function prototypes for gen_ functions for fix point conversions */
79typedef void VFPGenFixPointFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
61adacc8 80
b26eefb6
PB
81/* initialize TCG globals. */
82void arm_translate_init(void)
83{
155c3eac
FN
84 int i;
85
155c3eac 86 for (i = 0; i < 16; i++) {
e1ccc054 87 cpu_R[i] = tcg_global_mem_new_i32(cpu_env,
0ecb72a5 88 offsetof(CPUARMState, regs[i]),
155c3eac
FN
89 regnames[i]);
90 }
e1ccc054
RH
91 cpu_CF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, CF), "CF");
92 cpu_NF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, NF), "NF");
93 cpu_VF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, VF), "VF");
94 cpu_ZF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, ZF), "ZF");
66c374de 95
e1ccc054 96 cpu_exclusive_addr = tcg_global_mem_new_i64(cpu_env,
0ecb72a5 97 offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
e1ccc054 98 cpu_exclusive_val = tcg_global_mem_new_i64(cpu_env,
0ecb72a5 99 offsetof(CPUARMState, exclusive_val), "exclusive_val");
155c3eac 100
14ade10f 101 a64_translate_init();
b26eefb6
PB
102}
103
9bb6558a
PM
104/* Flags for the disas_set_da_iss info argument:
105 * lower bits hold the Rt register number, higher bits are flags.
106 */
107typedef enum ISSInfo {
108 ISSNone = 0,
109 ISSRegMask = 0x1f,
110 ISSInvalid = (1 << 5),
111 ISSIsAcqRel = (1 << 6),
112 ISSIsWrite = (1 << 7),
113 ISSIs16Bit = (1 << 8),
114} ISSInfo;
115
116/* Save the syndrome information for a Data Abort */
117static void disas_set_da_iss(DisasContext *s, TCGMemOp memop, ISSInfo issinfo)
118{
119 uint32_t syn;
120 int sas = memop & MO_SIZE;
121 bool sse = memop & MO_SIGN;
122 bool is_acqrel = issinfo & ISSIsAcqRel;
123 bool is_write = issinfo & ISSIsWrite;
124 bool is_16bit = issinfo & ISSIs16Bit;
125 int srt = issinfo & ISSRegMask;
126
127 if (issinfo & ISSInvalid) {
128 /* Some callsites want to conditionally provide ISS info,
129 * eg "only if this was not a writeback"
130 */
131 return;
132 }
133
134 if (srt == 15) {
135 /* For AArch32, insns where the src/dest is R15 never generate
136 * ISS information. Catching that here saves checking at all
137 * the call sites.
138 */
139 return;
140 }
141
142 syn = syn_data_abort_with_iss(0, sas, sse, srt, 0, is_acqrel,
143 0, 0, 0, is_write, 0, is_16bit);
144 disas_set_insn_syndrome(s, syn);
145}
146
8bd5c820 147static inline int get_a32_user_mem_index(DisasContext *s)
579d21cc 148{
8bd5c820 149 /* Return the core mmu_idx to use for A32/T32 "unprivileged load/store"
579d21cc
PM
150 * insns:
151 * if PL2, UNPREDICTABLE (we choose to implement as if PL0)
152 * otherwise, access as if at PL0.
153 */
154 switch (s->mmu_idx) {
155 case ARMMMUIdx_S1E2: /* this one is UNPREDICTABLE */
156 case ARMMMUIdx_S12NSE0:
157 case ARMMMUIdx_S12NSE1:
8bd5c820 158 return arm_to_core_mmu_idx(ARMMMUIdx_S12NSE0);
579d21cc
PM
159 case ARMMMUIdx_S1E3:
160 case ARMMMUIdx_S1SE0:
161 case ARMMMUIdx_S1SE1:
8bd5c820 162 return arm_to_core_mmu_idx(ARMMMUIdx_S1SE0);
e7b921c2
PM
163 case ARMMMUIdx_MUser:
164 case ARMMMUIdx_MPriv:
165 return arm_to_core_mmu_idx(ARMMMUIdx_MUser);
62593718
PM
166 case ARMMMUIdx_MUserNegPri:
167 case ARMMMUIdx_MPrivNegPri:
168 return arm_to_core_mmu_idx(ARMMMUIdx_MUserNegPri);
b9f587d6
PM
169 case ARMMMUIdx_MSUser:
170 case ARMMMUIdx_MSPriv:
b9f587d6 171 return arm_to_core_mmu_idx(ARMMMUIdx_MSUser);
62593718
PM
172 case ARMMMUIdx_MSUserNegPri:
173 case ARMMMUIdx_MSPrivNegPri:
174 return arm_to_core_mmu_idx(ARMMMUIdx_MSUserNegPri);
579d21cc
PM
175 case ARMMMUIdx_S2NS:
176 default:
177 g_assert_not_reached();
178 }
179}
180
39d5492a 181static inline TCGv_i32 load_cpu_offset(int offset)
d9ba4830 182{
39d5492a 183 TCGv_i32 tmp = tcg_temp_new_i32();
d9ba4830
PB
184 tcg_gen_ld_i32(tmp, cpu_env, offset);
185 return tmp;
186}
187
0ecb72a5 188#define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
d9ba4830 189
39d5492a 190static inline void store_cpu_offset(TCGv_i32 var, int offset)
d9ba4830
PB
191{
192 tcg_gen_st_i32(var, cpu_env, offset);
7d1b0095 193 tcg_temp_free_i32(var);
d9ba4830
PB
194}
195
196#define store_cpu_field(var, name) \
0ecb72a5 197 store_cpu_offset(var, offsetof(CPUARMState, name))
d9ba4830 198
b26eefb6 199/* Set a variable to the value of a CPU register. */
39d5492a 200static void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
b26eefb6
PB
201{
202 if (reg == 15) {
203 uint32_t addr;
b90372ad 204 /* normally, since we updated PC, we need only to add one insn */
b26eefb6
PB
205 if (s->thumb)
206 addr = (long)s->pc + 2;
207 else
208 addr = (long)s->pc + 4;
209 tcg_gen_movi_i32(var, addr);
210 } else {
155c3eac 211 tcg_gen_mov_i32(var, cpu_R[reg]);
b26eefb6
PB
212 }
213}
214
215/* Create a new temporary and set it to the value of a CPU register. */
39d5492a 216static inline TCGv_i32 load_reg(DisasContext *s, int reg)
b26eefb6 217{
39d5492a 218 TCGv_i32 tmp = tcg_temp_new_i32();
b26eefb6
PB
219 load_reg_var(s, tmp, reg);
220 return tmp;
221}
222
223/* Set a CPU register. The source must be a temporary and will be
224 marked as dead. */
39d5492a 225static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
b26eefb6
PB
226{
227 if (reg == 15) {
9b6a3ea7
PM
228 /* In Thumb mode, we must ignore bit 0.
229 * In ARM mode, for ARMv4 and ARMv5, it is UNPREDICTABLE if bits [1:0]
230 * are not 0b00, but for ARMv6 and above, we must ignore bits [1:0].
231 * We choose to ignore [1:0] in ARM mode for all architecture versions.
232 */
233 tcg_gen_andi_i32(var, var, s->thumb ? ~1 : ~3);
dcba3a8d 234 s->base.is_jmp = DISAS_JUMP;
b26eefb6 235 }
155c3eac 236 tcg_gen_mov_i32(cpu_R[reg], var);
7d1b0095 237 tcg_temp_free_i32(var);
b26eefb6
PB
238}
239
55203189
PM
240/*
241 * Variant of store_reg which applies v8M stack-limit checks before updating
242 * SP. If the check fails this will result in an exception being taken.
243 * We disable the stack checks for CONFIG_USER_ONLY because we have
244 * no idea what the stack limits should be in that case.
245 * If stack checking is not being done this just acts like store_reg().
246 */
247static void store_sp_checked(DisasContext *s, TCGv_i32 var)
248{
249#ifndef CONFIG_USER_ONLY
250 if (s->v8m_stackcheck) {
251 gen_helper_v8m_stackcheck(cpu_env, var);
252 }
253#endif
254 store_reg(s, 13, var);
255}
256
b26eefb6 257/* Value extensions. */
86831435
PB
258#define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
259#define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
b26eefb6
PB
260#define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
261#define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
262
1497c961
PB
263#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
264#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
8f01245e 265
b26eefb6 266
39d5492a 267static inline void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
b75263d6 268{
39d5492a 269 TCGv_i32 tmp_mask = tcg_const_i32(mask);
1ce94f81 270 gen_helper_cpsr_write(cpu_env, var, tmp_mask);
b75263d6
JR
271 tcg_temp_free_i32(tmp_mask);
272}
d9ba4830
PB
273/* Set NZCV flags from the high 4 bits of var. */
274#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
275
d4a2dc67 276static void gen_exception_internal(int excp)
d9ba4830 277{
d4a2dc67
PM
278 TCGv_i32 tcg_excp = tcg_const_i32(excp);
279
280 assert(excp_is_internal(excp));
281 gen_helper_exception_internal(cpu_env, tcg_excp);
282 tcg_temp_free_i32(tcg_excp);
283}
284
73710361 285static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el)
d4a2dc67
PM
286{
287 TCGv_i32 tcg_excp = tcg_const_i32(excp);
288 TCGv_i32 tcg_syn = tcg_const_i32(syndrome);
73710361 289 TCGv_i32 tcg_el = tcg_const_i32(target_el);
d4a2dc67 290
73710361
GB
291 gen_helper_exception_with_syndrome(cpu_env, tcg_excp,
292 tcg_syn, tcg_el);
293
294 tcg_temp_free_i32(tcg_el);
d4a2dc67
PM
295 tcg_temp_free_i32(tcg_syn);
296 tcg_temp_free_i32(tcg_excp);
d9ba4830
PB
297}
298
50225ad0
PM
299static void gen_step_complete_exception(DisasContext *s)
300{
301 /* We just completed step of an insn. Move from Active-not-pending
302 * to Active-pending, and then also take the swstep exception.
303 * This corresponds to making the (IMPDEF) choice to prioritize
304 * swstep exceptions over asynchronous exceptions taken to an exception
305 * level where debug is disabled. This choice has the advantage that
306 * we do not need to maintain internal state corresponding to the
307 * ISV/EX syndrome bits between completion of the step and generation
308 * of the exception, and our syndrome information is always correct.
309 */
310 gen_ss_advance(s);
73710361
GB
311 gen_exception(EXCP_UDEF, syn_swstep(s->ss_same_el, 1, s->is_ldex),
312 default_exception_el(s));
dcba3a8d 313 s->base.is_jmp = DISAS_NORETURN;
50225ad0
PM
314}
315
5425415e
PM
316static void gen_singlestep_exception(DisasContext *s)
317{
318 /* Generate the right kind of exception for singlestep, which is
319 * either the architectural singlestep or EXCP_DEBUG for QEMU's
320 * gdb singlestepping.
321 */
322 if (s->ss_active) {
323 gen_step_complete_exception(s);
324 } else {
325 gen_exception_internal(EXCP_DEBUG);
326 }
327}
328
b636649f
PM
329static inline bool is_singlestepping(DisasContext *s)
330{
331 /* Return true if we are singlestepping either because of
332 * architectural singlestep or QEMU gdbstub singlestep. This does
333 * not include the command line '-singlestep' mode which is rather
334 * misnamed as it only means "one instruction per TB" and doesn't
335 * affect the code we generate.
336 */
dcba3a8d 337 return s->base.singlestep_enabled || s->ss_active;
b636649f
PM
338}
339
39d5492a 340static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
3670669c 341{
39d5492a
PM
342 TCGv_i32 tmp1 = tcg_temp_new_i32();
343 TCGv_i32 tmp2 = tcg_temp_new_i32();
22478e79
AZ
344 tcg_gen_ext16s_i32(tmp1, a);
345 tcg_gen_ext16s_i32(tmp2, b);
3670669c 346 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
7d1b0095 347 tcg_temp_free_i32(tmp2);
3670669c
PB
348 tcg_gen_sari_i32(a, a, 16);
349 tcg_gen_sari_i32(b, b, 16);
350 tcg_gen_mul_i32(b, b, a);
351 tcg_gen_mov_i32(a, tmp1);
7d1b0095 352 tcg_temp_free_i32(tmp1);
3670669c
PB
353}
354
355/* Byteswap each halfword. */
39d5492a 356static void gen_rev16(TCGv_i32 var)
3670669c 357{
39d5492a 358 TCGv_i32 tmp = tcg_temp_new_i32();
68cedf73 359 TCGv_i32 mask = tcg_const_i32(0x00ff00ff);
3670669c 360 tcg_gen_shri_i32(tmp, var, 8);
68cedf73
AJ
361 tcg_gen_and_i32(tmp, tmp, mask);
362 tcg_gen_and_i32(var, var, mask);
3670669c 363 tcg_gen_shli_i32(var, var, 8);
3670669c 364 tcg_gen_or_i32(var, var, tmp);
68cedf73 365 tcg_temp_free_i32(mask);
7d1b0095 366 tcg_temp_free_i32(tmp);
3670669c
PB
367}
368
369/* Byteswap low halfword and sign extend. */
39d5492a 370static void gen_revsh(TCGv_i32 var)
3670669c 371{
1a855029
AJ
372 tcg_gen_ext16u_i32(var, var);
373 tcg_gen_bswap16_i32(var, var);
374 tcg_gen_ext16s_i32(var, var);
3670669c
PB
375}
376
838fa72d 377/* Return (b << 32) + a. Mark inputs as dead */
39d5492a 378static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv_i32 b)
3670669c 379{
838fa72d
AJ
380 TCGv_i64 tmp64 = tcg_temp_new_i64();
381
382 tcg_gen_extu_i32_i64(tmp64, b);
7d1b0095 383 tcg_temp_free_i32(b);
838fa72d
AJ
384 tcg_gen_shli_i64(tmp64, tmp64, 32);
385 tcg_gen_add_i64(a, tmp64, a);
386
387 tcg_temp_free_i64(tmp64);
388 return a;
389}
390
391/* Return (b << 32) - a. Mark inputs as dead. */
39d5492a 392static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv_i32 b)
838fa72d
AJ
393{
394 TCGv_i64 tmp64 = tcg_temp_new_i64();
395
396 tcg_gen_extu_i32_i64(tmp64, b);
7d1b0095 397 tcg_temp_free_i32(b);
838fa72d
AJ
398 tcg_gen_shli_i64(tmp64, tmp64, 32);
399 tcg_gen_sub_i64(a, tmp64, a);
400
401 tcg_temp_free_i64(tmp64);
402 return a;
3670669c
PB
403}
404
5e3f878a 405/* 32x32->64 multiply. Marks inputs as dead. */
39d5492a 406static TCGv_i64 gen_mulu_i64_i32(TCGv_i32 a, TCGv_i32 b)
5e3f878a 407{
39d5492a
PM
408 TCGv_i32 lo = tcg_temp_new_i32();
409 TCGv_i32 hi = tcg_temp_new_i32();
831d7fe8 410 TCGv_i64 ret;
5e3f878a 411
831d7fe8 412 tcg_gen_mulu2_i32(lo, hi, a, b);
7d1b0095 413 tcg_temp_free_i32(a);
7d1b0095 414 tcg_temp_free_i32(b);
831d7fe8
RH
415
416 ret = tcg_temp_new_i64();
417 tcg_gen_concat_i32_i64(ret, lo, hi);
39d5492a
PM
418 tcg_temp_free_i32(lo);
419 tcg_temp_free_i32(hi);
831d7fe8
RH
420
421 return ret;
5e3f878a
PB
422}
423
39d5492a 424static TCGv_i64 gen_muls_i64_i32(TCGv_i32 a, TCGv_i32 b)
5e3f878a 425{
39d5492a
PM
426 TCGv_i32 lo = tcg_temp_new_i32();
427 TCGv_i32 hi = tcg_temp_new_i32();
831d7fe8 428 TCGv_i64 ret;
5e3f878a 429
831d7fe8 430 tcg_gen_muls2_i32(lo, hi, a, b);
7d1b0095 431 tcg_temp_free_i32(a);
7d1b0095 432 tcg_temp_free_i32(b);
831d7fe8
RH
433
434 ret = tcg_temp_new_i64();
435 tcg_gen_concat_i32_i64(ret, lo, hi);
39d5492a
PM
436 tcg_temp_free_i32(lo);
437 tcg_temp_free_i32(hi);
831d7fe8
RH
438
439 return ret;
5e3f878a
PB
440}
441
8f01245e 442/* Swap low and high halfwords. */
39d5492a 443static void gen_swap_half(TCGv_i32 var)
8f01245e 444{
39d5492a 445 TCGv_i32 tmp = tcg_temp_new_i32();
8f01245e
PB
446 tcg_gen_shri_i32(tmp, var, 16);
447 tcg_gen_shli_i32(var, var, 16);
448 tcg_gen_or_i32(var, var, tmp);
7d1b0095 449 tcg_temp_free_i32(tmp);
8f01245e
PB
450}
451
b26eefb6
PB
452/* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
453 tmp = (t0 ^ t1) & 0x8000;
454 t0 &= ~0x8000;
455 t1 &= ~0x8000;
456 t0 = (t0 + t1) ^ tmp;
457 */
458
39d5492a 459static void gen_add16(TCGv_i32 t0, TCGv_i32 t1)
b26eefb6 460{
39d5492a 461 TCGv_i32 tmp = tcg_temp_new_i32();
b26eefb6
PB
462 tcg_gen_xor_i32(tmp, t0, t1);
463 tcg_gen_andi_i32(tmp, tmp, 0x8000);
464 tcg_gen_andi_i32(t0, t0, ~0x8000);
465 tcg_gen_andi_i32(t1, t1, ~0x8000);
466 tcg_gen_add_i32(t0, t0, t1);
467 tcg_gen_xor_i32(t0, t0, tmp);
7d1b0095
PM
468 tcg_temp_free_i32(tmp);
469 tcg_temp_free_i32(t1);
b26eefb6
PB
470}
471
472/* Set CF to the top bit of var. */
39d5492a 473static void gen_set_CF_bit31(TCGv_i32 var)
b26eefb6 474{
66c374de 475 tcg_gen_shri_i32(cpu_CF, var, 31);
b26eefb6
PB
476}
477
478/* Set N and Z flags from var. */
39d5492a 479static inline void gen_logic_CC(TCGv_i32 var)
b26eefb6 480{
66c374de
AJ
481 tcg_gen_mov_i32(cpu_NF, var);
482 tcg_gen_mov_i32(cpu_ZF, var);
b26eefb6
PB
483}
484
485/* T0 += T1 + CF. */
39d5492a 486static void gen_adc(TCGv_i32 t0, TCGv_i32 t1)
b26eefb6 487{
396e467c 488 tcg_gen_add_i32(t0, t0, t1);
66c374de 489 tcg_gen_add_i32(t0, t0, cpu_CF);
b26eefb6
PB
490}
491
e9bb4aa9 492/* dest = T0 + T1 + CF. */
39d5492a 493static void gen_add_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
e9bb4aa9 494{
e9bb4aa9 495 tcg_gen_add_i32(dest, t0, t1);
66c374de 496 tcg_gen_add_i32(dest, dest, cpu_CF);
e9bb4aa9
JR
497}
498
3670669c 499/* dest = T0 - T1 + CF - 1. */
39d5492a 500static void gen_sub_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
3670669c 501{
3670669c 502 tcg_gen_sub_i32(dest, t0, t1);
66c374de 503 tcg_gen_add_i32(dest, dest, cpu_CF);
3670669c 504 tcg_gen_subi_i32(dest, dest, 1);
3670669c
PB
505}
506
72485ec4 507/* dest = T0 + T1. Compute C, N, V and Z flags */
39d5492a 508static void gen_add_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
72485ec4 509{
39d5492a 510 TCGv_i32 tmp = tcg_temp_new_i32();
e3482cb8
RH
511 tcg_gen_movi_i32(tmp, 0);
512 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, t1, tmp);
72485ec4 513 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
72485ec4 514 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
72485ec4
AJ
515 tcg_gen_xor_i32(tmp, t0, t1);
516 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
517 tcg_temp_free_i32(tmp);
518 tcg_gen_mov_i32(dest, cpu_NF);
519}
520
49b4c31e 521/* dest = T0 + T1 + CF. Compute C, N, V and Z flags */
39d5492a 522static void gen_adc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
49b4c31e 523{
39d5492a 524 TCGv_i32 tmp = tcg_temp_new_i32();
49b4c31e
RH
525 if (TCG_TARGET_HAS_add2_i32) {
526 tcg_gen_movi_i32(tmp, 0);
527 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp);
8c3ac601 528 tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1, tmp);
49b4c31e
RH
529 } else {
530 TCGv_i64 q0 = tcg_temp_new_i64();
531 TCGv_i64 q1 = tcg_temp_new_i64();
532 tcg_gen_extu_i32_i64(q0, t0);
533 tcg_gen_extu_i32_i64(q1, t1);
534 tcg_gen_add_i64(q0, q0, q1);
535 tcg_gen_extu_i32_i64(q1, cpu_CF);
536 tcg_gen_add_i64(q0, q0, q1);
537 tcg_gen_extr_i64_i32(cpu_NF, cpu_CF, q0);
538 tcg_temp_free_i64(q0);
539 tcg_temp_free_i64(q1);
540 }
541 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
542 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
543 tcg_gen_xor_i32(tmp, t0, t1);
544 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
545 tcg_temp_free_i32(tmp);
546 tcg_gen_mov_i32(dest, cpu_NF);
547}
548
72485ec4 549/* dest = T0 - T1. Compute C, N, V and Z flags */
39d5492a 550static void gen_sub_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
72485ec4 551{
39d5492a 552 TCGv_i32 tmp;
72485ec4
AJ
553 tcg_gen_sub_i32(cpu_NF, t0, t1);
554 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
555 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0, t1);
556 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
557 tmp = tcg_temp_new_i32();
558 tcg_gen_xor_i32(tmp, t0, t1);
559 tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
560 tcg_temp_free_i32(tmp);
561 tcg_gen_mov_i32(dest, cpu_NF);
562}
563
e77f0832 564/* dest = T0 + ~T1 + CF. Compute C, N, V and Z flags */
39d5492a 565static void gen_sbc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
2de68a49 566{
39d5492a 567 TCGv_i32 tmp = tcg_temp_new_i32();
e77f0832
RH
568 tcg_gen_not_i32(tmp, t1);
569 gen_adc_CC(dest, t0, tmp);
39d5492a 570 tcg_temp_free_i32(tmp);
2de68a49
RH
571}
572
365af80e 573#define GEN_SHIFT(name) \
39d5492a 574static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \
365af80e 575{ \
39d5492a 576 TCGv_i32 tmp1, tmp2, tmp3; \
365af80e
AJ
577 tmp1 = tcg_temp_new_i32(); \
578 tcg_gen_andi_i32(tmp1, t1, 0xff); \
579 tmp2 = tcg_const_i32(0); \
580 tmp3 = tcg_const_i32(0x1f); \
581 tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
582 tcg_temp_free_i32(tmp3); \
583 tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
584 tcg_gen_##name##_i32(dest, tmp2, tmp1); \
585 tcg_temp_free_i32(tmp2); \
586 tcg_temp_free_i32(tmp1); \
587}
588GEN_SHIFT(shl)
589GEN_SHIFT(shr)
590#undef GEN_SHIFT
591
39d5492a 592static void gen_sar(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
365af80e 593{
39d5492a 594 TCGv_i32 tmp1, tmp2;
365af80e
AJ
595 tmp1 = tcg_temp_new_i32();
596 tcg_gen_andi_i32(tmp1, t1, 0xff);
597 tmp2 = tcg_const_i32(0x1f);
598 tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1);
599 tcg_temp_free_i32(tmp2);
600 tcg_gen_sar_i32(dest, t0, tmp1);
601 tcg_temp_free_i32(tmp1);
602}
603
39d5492a 604static void shifter_out_im(TCGv_i32 var, int shift)
b26eefb6 605{
9a119ff6 606 if (shift == 0) {
66c374de 607 tcg_gen_andi_i32(cpu_CF, var, 1);
b26eefb6 608 } else {
66c374de
AJ
609 tcg_gen_shri_i32(cpu_CF, var, shift);
610 if (shift != 31) {
611 tcg_gen_andi_i32(cpu_CF, cpu_CF, 1);
612 }
9a119ff6 613 }
9a119ff6 614}
b26eefb6 615
9a119ff6 616/* Shift by immediate. Includes special handling for shift == 0. */
39d5492a
PM
617static inline void gen_arm_shift_im(TCGv_i32 var, int shiftop,
618 int shift, int flags)
9a119ff6
PB
619{
620 switch (shiftop) {
621 case 0: /* LSL */
622 if (shift != 0) {
623 if (flags)
624 shifter_out_im(var, 32 - shift);
625 tcg_gen_shli_i32(var, var, shift);
626 }
627 break;
628 case 1: /* LSR */
629 if (shift == 0) {
630 if (flags) {
66c374de 631 tcg_gen_shri_i32(cpu_CF, var, 31);
9a119ff6
PB
632 }
633 tcg_gen_movi_i32(var, 0);
634 } else {
635 if (flags)
636 shifter_out_im(var, shift - 1);
637 tcg_gen_shri_i32(var, var, shift);
638 }
639 break;
640 case 2: /* ASR */
641 if (shift == 0)
642 shift = 32;
643 if (flags)
644 shifter_out_im(var, shift - 1);
645 if (shift == 32)
646 shift = 31;
647 tcg_gen_sari_i32(var, var, shift);
648 break;
649 case 3: /* ROR/RRX */
650 if (shift != 0) {
651 if (flags)
652 shifter_out_im(var, shift - 1);
f669df27 653 tcg_gen_rotri_i32(var, var, shift); break;
9a119ff6 654 } else {
39d5492a 655 TCGv_i32 tmp = tcg_temp_new_i32();
b6348f29 656 tcg_gen_shli_i32(tmp, cpu_CF, 31);
9a119ff6
PB
657 if (flags)
658 shifter_out_im(var, 0);
659 tcg_gen_shri_i32(var, var, 1);
b26eefb6 660 tcg_gen_or_i32(var, var, tmp);
7d1b0095 661 tcg_temp_free_i32(tmp);
b26eefb6
PB
662 }
663 }
664};
665
39d5492a
PM
666static inline void gen_arm_shift_reg(TCGv_i32 var, int shiftop,
667 TCGv_i32 shift, int flags)
8984bd2e
PB
668{
669 if (flags) {
670 switch (shiftop) {
9ef39277
BS
671 case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break;
672 case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break;
673 case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break;
674 case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break;
8984bd2e
PB
675 }
676 } else {
677 switch (shiftop) {
365af80e
AJ
678 case 0:
679 gen_shl(var, var, shift);
680 break;
681 case 1:
682 gen_shr(var, var, shift);
683 break;
684 case 2:
685 gen_sar(var, var, shift);
686 break;
f669df27
AJ
687 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
688 tcg_gen_rotr_i32(var, var, shift); break;
8984bd2e
PB
689 }
690 }
7d1b0095 691 tcg_temp_free_i32(shift);
8984bd2e
PB
692}
693
6ddbc6e4
PB
694#define PAS_OP(pfx) \
695 switch (op2) { \
696 case 0: gen_pas_helper(glue(pfx,add16)); break; \
697 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
698 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
699 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
700 case 4: gen_pas_helper(glue(pfx,add8)); break; \
701 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
702 }
39d5492a 703static void gen_arm_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
6ddbc6e4 704{
a7812ae4 705 TCGv_ptr tmp;
6ddbc6e4
PB
706
707 switch (op1) {
708#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
709 case 1:
a7812ae4 710 tmp = tcg_temp_new_ptr();
0ecb72a5 711 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 712 PAS_OP(s)
b75263d6 713 tcg_temp_free_ptr(tmp);
6ddbc6e4
PB
714 break;
715 case 5:
a7812ae4 716 tmp = tcg_temp_new_ptr();
0ecb72a5 717 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 718 PAS_OP(u)
b75263d6 719 tcg_temp_free_ptr(tmp);
6ddbc6e4
PB
720 break;
721#undef gen_pas_helper
722#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
723 case 2:
724 PAS_OP(q);
725 break;
726 case 3:
727 PAS_OP(sh);
728 break;
729 case 6:
730 PAS_OP(uq);
731 break;
732 case 7:
733 PAS_OP(uh);
734 break;
735#undef gen_pas_helper
736 }
737}
9ee6e8bb
PB
738#undef PAS_OP
739
6ddbc6e4
PB
740/* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
741#define PAS_OP(pfx) \
ed89a2f1 742 switch (op1) { \
6ddbc6e4
PB
743 case 0: gen_pas_helper(glue(pfx,add8)); break; \
744 case 1: gen_pas_helper(glue(pfx,add16)); break; \
745 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
746 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
747 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
748 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
749 }
39d5492a 750static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
6ddbc6e4 751{
a7812ae4 752 TCGv_ptr tmp;
6ddbc6e4 753
ed89a2f1 754 switch (op2) {
6ddbc6e4
PB
755#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
756 case 0:
a7812ae4 757 tmp = tcg_temp_new_ptr();
0ecb72a5 758 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 759 PAS_OP(s)
b75263d6 760 tcg_temp_free_ptr(tmp);
6ddbc6e4
PB
761 break;
762 case 4:
a7812ae4 763 tmp = tcg_temp_new_ptr();
0ecb72a5 764 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 765 PAS_OP(u)
b75263d6 766 tcg_temp_free_ptr(tmp);
6ddbc6e4
PB
767 break;
768#undef gen_pas_helper
769#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
770 case 1:
771 PAS_OP(q);
772 break;
773 case 2:
774 PAS_OP(sh);
775 break;
776 case 5:
777 PAS_OP(uq);
778 break;
779 case 6:
780 PAS_OP(uh);
781 break;
782#undef gen_pas_helper
783 }
784}
9ee6e8bb
PB
785#undef PAS_OP
786
39fb730a 787/*
6c2c63d3 788 * Generate a conditional based on ARM condition code cc.
39fb730a
AG
789 * This is common between ARM and Aarch64 targets.
790 */
6c2c63d3 791void arm_test_cc(DisasCompare *cmp, int cc)
d9ba4830 792{
6c2c63d3
RH
793 TCGv_i32 value;
794 TCGCond cond;
795 bool global = true;
d9ba4830 796
d9ba4830
PB
797 switch (cc) {
798 case 0: /* eq: Z */
d9ba4830 799 case 1: /* ne: !Z */
6c2c63d3
RH
800 cond = TCG_COND_EQ;
801 value = cpu_ZF;
d9ba4830 802 break;
6c2c63d3 803
d9ba4830 804 case 2: /* cs: C */
d9ba4830 805 case 3: /* cc: !C */
6c2c63d3
RH
806 cond = TCG_COND_NE;
807 value = cpu_CF;
d9ba4830 808 break;
6c2c63d3 809
d9ba4830 810 case 4: /* mi: N */
d9ba4830 811 case 5: /* pl: !N */
6c2c63d3
RH
812 cond = TCG_COND_LT;
813 value = cpu_NF;
d9ba4830 814 break;
6c2c63d3 815
d9ba4830 816 case 6: /* vs: V */
d9ba4830 817 case 7: /* vc: !V */
6c2c63d3
RH
818 cond = TCG_COND_LT;
819 value = cpu_VF;
d9ba4830 820 break;
6c2c63d3 821
d9ba4830 822 case 8: /* hi: C && !Z */
6c2c63d3
RH
823 case 9: /* ls: !C || Z -> !(C && !Z) */
824 cond = TCG_COND_NE;
825 value = tcg_temp_new_i32();
826 global = false;
827 /* CF is 1 for C, so -CF is an all-bits-set mask for C;
828 ZF is non-zero for !Z; so AND the two subexpressions. */
829 tcg_gen_neg_i32(value, cpu_CF);
830 tcg_gen_and_i32(value, value, cpu_ZF);
d9ba4830 831 break;
6c2c63d3 832
d9ba4830 833 case 10: /* ge: N == V -> N ^ V == 0 */
d9ba4830 834 case 11: /* lt: N != V -> N ^ V != 0 */
6c2c63d3
RH
835 /* Since we're only interested in the sign bit, == 0 is >= 0. */
836 cond = TCG_COND_GE;
837 value = tcg_temp_new_i32();
838 global = false;
839 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
d9ba4830 840 break;
6c2c63d3 841
d9ba4830 842 case 12: /* gt: !Z && N == V */
d9ba4830 843 case 13: /* le: Z || N != V */
6c2c63d3
RH
844 cond = TCG_COND_NE;
845 value = tcg_temp_new_i32();
846 global = false;
847 /* (N == V) is equal to the sign bit of ~(NF ^ VF). Propagate
848 * the sign bit then AND with ZF to yield the result. */
849 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
850 tcg_gen_sari_i32(value, value, 31);
851 tcg_gen_andc_i32(value, cpu_ZF, value);
d9ba4830 852 break;
6c2c63d3 853
9305eac0
RH
854 case 14: /* always */
855 case 15: /* always */
856 /* Use the ALWAYS condition, which will fold early.
857 * It doesn't matter what we use for the value. */
858 cond = TCG_COND_ALWAYS;
859 value = cpu_ZF;
860 goto no_invert;
861
d9ba4830
PB
862 default:
863 fprintf(stderr, "Bad condition code 0x%x\n", cc);
864 abort();
865 }
6c2c63d3
RH
866
867 if (cc & 1) {
868 cond = tcg_invert_cond(cond);
869 }
870
9305eac0 871 no_invert:
6c2c63d3
RH
872 cmp->cond = cond;
873 cmp->value = value;
874 cmp->value_global = global;
875}
876
877void arm_free_cc(DisasCompare *cmp)
878{
879 if (!cmp->value_global) {
880 tcg_temp_free_i32(cmp->value);
881 }
882}
883
884void arm_jump_cc(DisasCompare *cmp, TCGLabel *label)
885{
886 tcg_gen_brcondi_i32(cmp->cond, cmp->value, 0, label);
887}
888
889void arm_gen_test_cc(int cc, TCGLabel *label)
890{
891 DisasCompare cmp;
892 arm_test_cc(&cmp, cc);
893 arm_jump_cc(&cmp, label);
894 arm_free_cc(&cmp);
d9ba4830 895}
2c0262af 896
b1d8e52e 897static const uint8_t table_logic_cc[16] = {
2c0262af
FB
898 1, /* and */
899 1, /* xor */
900 0, /* sub */
901 0, /* rsb */
902 0, /* add */
903 0, /* adc */
904 0, /* sbc */
905 0, /* rsc */
906 1, /* andl */
907 1, /* xorl */
908 0, /* cmp */
909 0, /* cmn */
910 1, /* orr */
911 1, /* mov */
912 1, /* bic */
913 1, /* mvn */
914};
3b46e624 915
4d5e8c96
PM
916static inline void gen_set_condexec(DisasContext *s)
917{
918 if (s->condexec_mask) {
919 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
920 TCGv_i32 tmp = tcg_temp_new_i32();
921 tcg_gen_movi_i32(tmp, val);
922 store_cpu_field(tmp, condexec_bits);
923 }
924}
925
926static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
927{
928 tcg_gen_movi_i32(cpu_R[15], val);
929}
930
d9ba4830
PB
931/* Set PC and Thumb state from an immediate address. */
932static inline void gen_bx_im(DisasContext *s, uint32_t addr)
99c475ab 933{
39d5492a 934 TCGv_i32 tmp;
99c475ab 935
dcba3a8d 936 s->base.is_jmp = DISAS_JUMP;
d9ba4830 937 if (s->thumb != (addr & 1)) {
7d1b0095 938 tmp = tcg_temp_new_i32();
d9ba4830 939 tcg_gen_movi_i32(tmp, addr & 1);
0ecb72a5 940 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, thumb));
7d1b0095 941 tcg_temp_free_i32(tmp);
d9ba4830 942 }
155c3eac 943 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
d9ba4830
PB
944}
945
946/* Set PC and Thumb state from var. var is marked as dead. */
39d5492a 947static inline void gen_bx(DisasContext *s, TCGv_i32 var)
d9ba4830 948{
dcba3a8d 949 s->base.is_jmp = DISAS_JUMP;
155c3eac
FN
950 tcg_gen_andi_i32(cpu_R[15], var, ~1);
951 tcg_gen_andi_i32(var, var, 1);
952 store_cpu_field(var, thumb);
d9ba4830
PB
953}
954
3bb8a96f
PM
955/* Set PC and Thumb state from var. var is marked as dead.
956 * For M-profile CPUs, include logic to detect exception-return
957 * branches and handle them. This is needed for Thumb POP/LDM to PC, LDR to PC,
958 * and BX reg, and no others, and happens only for code in Handler mode.
959 */
960static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var)
961{
962 /* Generate the same code here as for a simple bx, but flag via
dcba3a8d 963 * s->base.is_jmp that we need to do the rest of the work later.
3bb8a96f
PM
964 */
965 gen_bx(s, var);
d02a8698
PM
966 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY) ||
967 (s->v7m_handler_mode && arm_dc_feature(s, ARM_FEATURE_M))) {
dcba3a8d 968 s->base.is_jmp = DISAS_BX_EXCRET;
3bb8a96f
PM
969 }
970}
971
972static inline void gen_bx_excret_final_code(DisasContext *s)
973{
974 /* Generate the code to finish possible exception return and end the TB */
975 TCGLabel *excret_label = gen_new_label();
d02a8698
PM
976 uint32_t min_magic;
977
978 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY)) {
979 /* Covers FNC_RETURN and EXC_RETURN magic */
980 min_magic = FNC_RETURN_MIN_MAGIC;
981 } else {
982 /* EXC_RETURN magic only */
983 min_magic = EXC_RETURN_MIN_MAGIC;
984 }
3bb8a96f
PM
985
986 /* Is the new PC value in the magic range indicating exception return? */
d02a8698 987 tcg_gen_brcondi_i32(TCG_COND_GEU, cpu_R[15], min_magic, excret_label);
3bb8a96f
PM
988 /* No: end the TB as we would for a DISAS_JMP */
989 if (is_singlestepping(s)) {
990 gen_singlestep_exception(s);
991 } else {
07ea28b4 992 tcg_gen_exit_tb(NULL, 0);
3bb8a96f
PM
993 }
994 gen_set_label(excret_label);
995 /* Yes: this is an exception return.
996 * At this point in runtime env->regs[15] and env->thumb will hold
997 * the exception-return magic number, which do_v7m_exception_exit()
998 * will read. Nothing else will be able to see those values because
999 * the cpu-exec main loop guarantees that we will always go straight
1000 * from raising the exception to the exception-handling code.
1001 *
1002 * gen_ss_advance(s) does nothing on M profile currently but
1003 * calling it is conceptually the right thing as we have executed
1004 * this instruction (compare SWI, HVC, SMC handling).
1005 */
1006 gen_ss_advance(s);
1007 gen_exception_internal(EXCP_EXCEPTION_EXIT);
1008}
1009
fb602cb7
PM
1010static inline void gen_bxns(DisasContext *s, int rm)
1011{
1012 TCGv_i32 var = load_reg(s, rm);
1013
1014 /* The bxns helper may raise an EXCEPTION_EXIT exception, so in theory
1015 * we need to sync state before calling it, but:
1016 * - we don't need to do gen_set_pc_im() because the bxns helper will
1017 * always set the PC itself
1018 * - we don't need to do gen_set_condexec() because BXNS is UNPREDICTABLE
1019 * unless it's outside an IT block or the last insn in an IT block,
1020 * so we know that condexec == 0 (already set at the top of the TB)
1021 * is correct in the non-UNPREDICTABLE cases, and we can choose
1022 * "zeroes the IT bits" as our UNPREDICTABLE behaviour otherwise.
1023 */
1024 gen_helper_v7m_bxns(cpu_env, var);
1025 tcg_temp_free_i32(var);
ef475b5d 1026 s->base.is_jmp = DISAS_EXIT;
fb602cb7
PM
1027}
1028
3e3fa230
PM
1029static inline void gen_blxns(DisasContext *s, int rm)
1030{
1031 TCGv_i32 var = load_reg(s, rm);
1032
1033 /* We don't need to sync condexec state, for the same reason as bxns.
1034 * We do however need to set the PC, because the blxns helper reads it.
1035 * The blxns helper may throw an exception.
1036 */
1037 gen_set_pc_im(s, s->pc);
1038 gen_helper_v7m_blxns(cpu_env, var);
1039 tcg_temp_free_i32(var);
1040 s->base.is_jmp = DISAS_EXIT;
1041}
1042
21aeb343
JR
1043/* Variant of store_reg which uses branch&exchange logic when storing
1044 to r15 in ARM architecture v7 and above. The source must be a temporary
1045 and will be marked as dead. */
7dcc1f89 1046static inline void store_reg_bx(DisasContext *s, int reg, TCGv_i32 var)
21aeb343
JR
1047{
1048 if (reg == 15 && ENABLE_ARCH_7) {
1049 gen_bx(s, var);
1050 } else {
1051 store_reg(s, reg, var);
1052 }
1053}
1054
be5e7a76
DES
1055/* Variant of store_reg which uses branch&exchange logic when storing
1056 * to r15 in ARM architecture v5T and above. This is used for storing
1057 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
1058 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
7dcc1f89 1059static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
be5e7a76
DES
1060{
1061 if (reg == 15 && ENABLE_ARCH_5) {
3bb8a96f 1062 gen_bx_excret(s, var);
be5e7a76
DES
1063 } else {
1064 store_reg(s, reg, var);
1065 }
1066}
1067
e334bd31
PB
1068#ifdef CONFIG_USER_ONLY
1069#define IS_USER_ONLY 1
1070#else
1071#define IS_USER_ONLY 0
1072#endif
1073
08307563
PM
1074/* Abstractions of "generate code to do a guest load/store for
1075 * AArch32", where a vaddr is always 32 bits (and is zero
1076 * extended if we're a 64 bit core) and data is also
1077 * 32 bits unless specifically doing a 64 bit access.
1078 * These functions work like tcg_gen_qemu_{ld,st}* except
09f78135 1079 * that the address argument is TCGv_i32 rather than TCGv.
08307563 1080 */
08307563 1081
7f5616f5 1082static inline TCGv gen_aa32_addr(DisasContext *s, TCGv_i32 a32, TCGMemOp op)
08307563 1083{
7f5616f5
RH
1084 TCGv addr = tcg_temp_new();
1085 tcg_gen_extu_i32_tl(addr, a32);
1086
e334bd31 1087 /* Not needed for user-mode BE32, where we use MO_BE instead. */
7f5616f5
RH
1088 if (!IS_USER_ONLY && s->sctlr_b && (op & MO_SIZE) < MO_32) {
1089 tcg_gen_xori_tl(addr, addr, 4 - (1 << (op & MO_SIZE)));
e334bd31 1090 }
7f5616f5 1091 return addr;
08307563
PM
1092}
1093
7f5616f5
RH
1094static void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
1095 int index, TCGMemOp opc)
08307563 1096{
2aeba0d0
JS
1097 TCGv addr;
1098
1099 if (arm_dc_feature(s, ARM_FEATURE_M) &&
1100 !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
1101 opc |= MO_ALIGN;
1102 }
1103
1104 addr = gen_aa32_addr(s, a32, opc);
7f5616f5
RH
1105 tcg_gen_qemu_ld_i32(val, addr, index, opc);
1106 tcg_temp_free(addr);
08307563
PM
1107}
1108
7f5616f5
RH
1109static void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
1110 int index, TCGMemOp opc)
1111{
2aeba0d0
JS
1112 TCGv addr;
1113
1114 if (arm_dc_feature(s, ARM_FEATURE_M) &&
1115 !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
1116 opc |= MO_ALIGN;
1117 }
1118
1119 addr = gen_aa32_addr(s, a32, opc);
7f5616f5
RH
1120 tcg_gen_qemu_st_i32(val, addr, index, opc);
1121 tcg_temp_free(addr);
1122}
08307563 1123
7f5616f5 1124#define DO_GEN_LD(SUFF, OPC) \
12dcc321 1125static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
7f5616f5 1126 TCGv_i32 a32, int index) \
08307563 1127{ \
7f5616f5 1128 gen_aa32_ld_i32(s, val, a32, index, OPC | s->be_data); \
9bb6558a
PM
1129} \
1130static inline void gen_aa32_ld##SUFF##_iss(DisasContext *s, \
1131 TCGv_i32 val, \
1132 TCGv_i32 a32, int index, \
1133 ISSInfo issinfo) \
1134{ \
1135 gen_aa32_ld##SUFF(s, val, a32, index); \
1136 disas_set_da_iss(s, OPC, issinfo); \
08307563
PM
1137}
1138
7f5616f5 1139#define DO_GEN_ST(SUFF, OPC) \
12dcc321 1140static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
7f5616f5 1141 TCGv_i32 a32, int index) \
08307563 1142{ \
7f5616f5 1143 gen_aa32_st_i32(s, val, a32, index, OPC | s->be_data); \
9bb6558a
PM
1144} \
1145static inline void gen_aa32_st##SUFF##_iss(DisasContext *s, \
1146 TCGv_i32 val, \
1147 TCGv_i32 a32, int index, \
1148 ISSInfo issinfo) \
1149{ \
1150 gen_aa32_st##SUFF(s, val, a32, index); \
1151 disas_set_da_iss(s, OPC, issinfo | ISSIsWrite); \
08307563
PM
1152}
1153
7f5616f5 1154static inline void gen_aa32_frob64(DisasContext *s, TCGv_i64 val)
08307563 1155{
e334bd31
PB
1156 /* Not needed for user-mode BE32, where we use MO_BE instead. */
1157 if (!IS_USER_ONLY && s->sctlr_b) {
1158 tcg_gen_rotri_i64(val, val, 32);
1159 }
08307563
PM
1160}
1161
7f5616f5
RH
1162static void gen_aa32_ld_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
1163 int index, TCGMemOp opc)
08307563 1164{
7f5616f5
RH
1165 TCGv addr = gen_aa32_addr(s, a32, opc);
1166 tcg_gen_qemu_ld_i64(val, addr, index, opc);
1167 gen_aa32_frob64(s, val);
1168 tcg_temp_free(addr);
1169}
1170
1171static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
1172 TCGv_i32 a32, int index)
1173{
1174 gen_aa32_ld_i64(s, val, a32, index, MO_Q | s->be_data);
1175}
1176
1177static void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
1178 int index, TCGMemOp opc)
1179{
1180 TCGv addr = gen_aa32_addr(s, a32, opc);
e334bd31
PB
1181
1182 /* Not needed for user-mode BE32, where we use MO_BE instead. */
1183 if (!IS_USER_ONLY && s->sctlr_b) {
7f5616f5 1184 TCGv_i64 tmp = tcg_temp_new_i64();
e334bd31 1185 tcg_gen_rotri_i64(tmp, val, 32);
7f5616f5
RH
1186 tcg_gen_qemu_st_i64(tmp, addr, index, opc);
1187 tcg_temp_free_i64(tmp);
e334bd31 1188 } else {
7f5616f5 1189 tcg_gen_qemu_st_i64(val, addr, index, opc);
e334bd31 1190 }
7f5616f5 1191 tcg_temp_free(addr);
08307563
PM
1192}
1193
7f5616f5
RH
1194static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
1195 TCGv_i32 a32, int index)
1196{
1197 gen_aa32_st_i64(s, val, a32, index, MO_Q | s->be_data);
1198}
08307563 1199
7f5616f5
RH
1200DO_GEN_LD(8s, MO_SB)
1201DO_GEN_LD(8u, MO_UB)
1202DO_GEN_LD(16s, MO_SW)
1203DO_GEN_LD(16u, MO_UW)
1204DO_GEN_LD(32u, MO_UL)
7f5616f5
RH
1205DO_GEN_ST(8, MO_UB)
1206DO_GEN_ST(16, MO_UW)
1207DO_GEN_ST(32, MO_UL)
08307563 1208
37e6456e
PM
1209static inline void gen_hvc(DisasContext *s, int imm16)
1210{
1211 /* The pre HVC helper handles cases when HVC gets trapped
1212 * as an undefined insn by runtime configuration (ie before
1213 * the insn really executes).
1214 */
1215 gen_set_pc_im(s, s->pc - 4);
1216 gen_helper_pre_hvc(cpu_env);
1217 /* Otherwise we will treat this as a real exception which
1218 * happens after execution of the insn. (The distinction matters
1219 * for the PC value reported to the exception handler and also
1220 * for single stepping.)
1221 */
1222 s->svc_imm = imm16;
1223 gen_set_pc_im(s, s->pc);
dcba3a8d 1224 s->base.is_jmp = DISAS_HVC;
37e6456e
PM
1225}
1226
1227static inline void gen_smc(DisasContext *s)
1228{
1229 /* As with HVC, we may take an exception either before or after
1230 * the insn executes.
1231 */
1232 TCGv_i32 tmp;
1233
1234 gen_set_pc_im(s, s->pc - 4);
1235 tmp = tcg_const_i32(syn_aa32_smc());
1236 gen_helper_pre_smc(cpu_env, tmp);
1237 tcg_temp_free_i32(tmp);
1238 gen_set_pc_im(s, s->pc);
dcba3a8d 1239 s->base.is_jmp = DISAS_SMC;
37e6456e
PM
1240}
1241
d4a2dc67
PM
1242static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
1243{
1244 gen_set_condexec(s);
1245 gen_set_pc_im(s, s->pc - offset);
1246 gen_exception_internal(excp);
dcba3a8d 1247 s->base.is_jmp = DISAS_NORETURN;
d4a2dc67
PM
1248}
1249
73710361
GB
1250static void gen_exception_insn(DisasContext *s, int offset, int excp,
1251 int syn, uint32_t target_el)
d4a2dc67
PM
1252{
1253 gen_set_condexec(s);
1254 gen_set_pc_im(s, s->pc - offset);
73710361 1255 gen_exception(excp, syn, target_el);
dcba3a8d 1256 s->base.is_jmp = DISAS_NORETURN;
d4a2dc67
PM
1257}
1258
c900a2e6
PM
1259static void gen_exception_bkpt_insn(DisasContext *s, int offset, uint32_t syn)
1260{
1261 TCGv_i32 tcg_syn;
1262
1263 gen_set_condexec(s);
1264 gen_set_pc_im(s, s->pc - offset);
1265 tcg_syn = tcg_const_i32(syn);
1266 gen_helper_exception_bkpt_insn(cpu_env, tcg_syn);
1267 tcg_temp_free_i32(tcg_syn);
1268 s->base.is_jmp = DISAS_NORETURN;
1269}
1270
b5ff1b31
FB
1271/* Force a TB lookup after an instruction that changes the CPU state. */
1272static inline void gen_lookup_tb(DisasContext *s)
1273{
a6445c52 1274 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
dcba3a8d 1275 s->base.is_jmp = DISAS_EXIT;
b5ff1b31
FB
1276}
1277
19a6e31c
PM
1278static inline void gen_hlt(DisasContext *s, int imm)
1279{
1280 /* HLT. This has two purposes.
1281 * Architecturally, it is an external halting debug instruction.
1282 * Since QEMU doesn't implement external debug, we treat this as
1283 * it is required for halting debug disabled: it will UNDEF.
1284 * Secondly, "HLT 0x3C" is a T32 semihosting trap instruction,
1285 * and "HLT 0xF000" is an A32 semihosting syscall. These traps
1286 * must trigger semihosting even for ARMv7 and earlier, where
1287 * HLT was an undefined encoding.
1288 * In system mode, we don't allow userspace access to
1289 * semihosting, to provide some semblance of security
1290 * (and for consistency with our 32-bit semihosting).
1291 */
1292 if (semihosting_enabled() &&
1293#ifndef CONFIG_USER_ONLY
1294 s->current_el != 0 &&
1295#endif
1296 (imm == (s->thumb ? 0x3c : 0xf000))) {
1297 gen_exception_internal_insn(s, 0, EXCP_SEMIHOST);
1298 return;
1299 }
1300
1301 gen_exception_insn(s, s->thumb ? 2 : 4, EXCP_UDEF, syn_uncategorized(),
1302 default_exception_el(s));
1303}
1304
b0109805 1305static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
39d5492a 1306 TCGv_i32 var)
2c0262af 1307{
1e8d4eec 1308 int val, rm, shift, shiftop;
39d5492a 1309 TCGv_i32 offset;
2c0262af
FB
1310
1311 if (!(insn & (1 << 25))) {
1312 /* immediate */
1313 val = insn & 0xfff;
1314 if (!(insn & (1 << 23)))
1315 val = -val;
537730b9 1316 if (val != 0)
b0109805 1317 tcg_gen_addi_i32(var, var, val);
2c0262af
FB
1318 } else {
1319 /* shift/register */
1320 rm = (insn) & 0xf;
1321 shift = (insn >> 7) & 0x1f;
1e8d4eec 1322 shiftop = (insn >> 5) & 3;
b26eefb6 1323 offset = load_reg(s, rm);
9a119ff6 1324 gen_arm_shift_im(offset, shiftop, shift, 0);
2c0262af 1325 if (!(insn & (1 << 23)))
b0109805 1326 tcg_gen_sub_i32(var, var, offset);
2c0262af 1327 else
b0109805 1328 tcg_gen_add_i32(var, var, offset);
7d1b0095 1329 tcg_temp_free_i32(offset);
2c0262af
FB
1330 }
1331}
1332
191f9a93 1333static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
39d5492a 1334 int extra, TCGv_i32 var)
2c0262af
FB
1335{
1336 int val, rm;
39d5492a 1337 TCGv_i32 offset;
3b46e624 1338
2c0262af
FB
1339 if (insn & (1 << 22)) {
1340 /* immediate */
1341 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
1342 if (!(insn & (1 << 23)))
1343 val = -val;
18acad92 1344 val += extra;
537730b9 1345 if (val != 0)
b0109805 1346 tcg_gen_addi_i32(var, var, val);
2c0262af
FB
1347 } else {
1348 /* register */
191f9a93 1349 if (extra)
b0109805 1350 tcg_gen_addi_i32(var, var, extra);
2c0262af 1351 rm = (insn) & 0xf;
b26eefb6 1352 offset = load_reg(s, rm);
2c0262af 1353 if (!(insn & (1 << 23)))
b0109805 1354 tcg_gen_sub_i32(var, var, offset);
2c0262af 1355 else
b0109805 1356 tcg_gen_add_i32(var, var, offset);
7d1b0095 1357 tcg_temp_free_i32(offset);
2c0262af
FB
1358 }
1359}
1360
5aaebd13
PM
1361static TCGv_ptr get_fpstatus_ptr(int neon)
1362{
1363 TCGv_ptr statusptr = tcg_temp_new_ptr();
1364 int offset;
1365 if (neon) {
0ecb72a5 1366 offset = offsetof(CPUARMState, vfp.standard_fp_status);
5aaebd13 1367 } else {
0ecb72a5 1368 offset = offsetof(CPUARMState, vfp.fp_status);
5aaebd13
PM
1369 }
1370 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
1371 return statusptr;
1372}
1373
c39c2b90 1374static inline long vfp_reg_offset(bool dp, unsigned reg)
8e96005d 1375{
9a2b5256 1376 if (dp) {
c39c2b90 1377 return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]);
8e96005d 1378 } else {
c39c2b90 1379 long ofs = offsetof(CPUARMState, vfp.zregs[reg >> 2].d[(reg >> 1) & 1]);
9a2b5256
RH
1380 if (reg & 1) {
1381 ofs += offsetof(CPU_DoubleU, l.upper);
1382 } else {
1383 ofs += offsetof(CPU_DoubleU, l.lower);
1384 }
1385 return ofs;
8e96005d
FB
1386 }
1387}
9ee6e8bb
PB
1388
1389/* Return the offset of a 32-bit piece of a NEON register.
1390 zero is the least significant end of the register. */
1391static inline long
1392neon_reg_offset (int reg, int n)
1393{
1394 int sreg;
1395 sreg = reg * 2 + n;
1396 return vfp_reg_offset(0, sreg);
1397}
1398
32f91fb7
RH
1399/* Return the offset of a 2**SIZE piece of a NEON register, at index ELE,
1400 * where 0 is the least significant end of the register.
1401 */
1402static inline long
1403neon_element_offset(int reg, int element, TCGMemOp size)
1404{
1405 int element_size = 1 << size;
1406 int ofs = element * element_size;
1407#ifdef HOST_WORDS_BIGENDIAN
1408 /* Calculate the offset assuming fully little-endian,
1409 * then XOR to account for the order of the 8-byte units.
1410 */
1411 if (element_size < 8) {
1412 ofs ^= 8 - element_size;
1413 }
1414#endif
1415 return neon_reg_offset(reg, 0) + ofs;
1416}
1417
39d5492a 1418static TCGv_i32 neon_load_reg(int reg, int pass)
8f8e3aa4 1419{
39d5492a 1420 TCGv_i32 tmp = tcg_temp_new_i32();
8f8e3aa4
PB
1421 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1422 return tmp;
1423}
1424
2d6ac920
RH
1425static void neon_load_element(TCGv_i32 var, int reg, int ele, TCGMemOp mop)
1426{
1427 long offset = neon_element_offset(reg, ele, mop & MO_SIZE);
1428
1429 switch (mop) {
1430 case MO_UB:
1431 tcg_gen_ld8u_i32(var, cpu_env, offset);
1432 break;
1433 case MO_UW:
1434 tcg_gen_ld16u_i32(var, cpu_env, offset);
1435 break;
1436 case MO_UL:
1437 tcg_gen_ld_i32(var, cpu_env, offset);
1438 break;
1439 default:
1440 g_assert_not_reached();
1441 }
1442}
1443
ac55d007
RH
1444static void neon_load_element64(TCGv_i64 var, int reg, int ele, TCGMemOp mop)
1445{
1446 long offset = neon_element_offset(reg, ele, mop & MO_SIZE);
1447
1448 switch (mop) {
1449 case MO_UB:
1450 tcg_gen_ld8u_i64(var, cpu_env, offset);
1451 break;
1452 case MO_UW:
1453 tcg_gen_ld16u_i64(var, cpu_env, offset);
1454 break;
1455 case MO_UL:
1456 tcg_gen_ld32u_i64(var, cpu_env, offset);
1457 break;
1458 case MO_Q:
1459 tcg_gen_ld_i64(var, cpu_env, offset);
1460 break;
1461 default:
1462 g_assert_not_reached();
1463 }
1464}
1465
39d5492a 1466static void neon_store_reg(int reg, int pass, TCGv_i32 var)
8f8e3aa4
PB
1467{
1468 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
7d1b0095 1469 tcg_temp_free_i32(var);
8f8e3aa4
PB
1470}
1471
2d6ac920
RH
1472static void neon_store_element(int reg, int ele, TCGMemOp size, TCGv_i32 var)
1473{
1474 long offset = neon_element_offset(reg, ele, size);
1475
1476 switch (size) {
1477 case MO_8:
1478 tcg_gen_st8_i32(var, cpu_env, offset);
1479 break;
1480 case MO_16:
1481 tcg_gen_st16_i32(var, cpu_env, offset);
1482 break;
1483 case MO_32:
1484 tcg_gen_st_i32(var, cpu_env, offset);
1485 break;
1486 default:
1487 g_assert_not_reached();
1488 }
1489}
1490
ac55d007
RH
1491static void neon_store_element64(int reg, int ele, TCGMemOp size, TCGv_i64 var)
1492{
1493 long offset = neon_element_offset(reg, ele, size);
1494
1495 switch (size) {
1496 case MO_8:
1497 tcg_gen_st8_i64(var, cpu_env, offset);
1498 break;
1499 case MO_16:
1500 tcg_gen_st16_i64(var, cpu_env, offset);
1501 break;
1502 case MO_32:
1503 tcg_gen_st32_i64(var, cpu_env, offset);
1504 break;
1505 case MO_64:
1506 tcg_gen_st_i64(var, cpu_env, offset);
1507 break;
1508 default:
1509 g_assert_not_reached();
1510 }
1511}
1512
a7812ae4 1513static inline void neon_load_reg64(TCGv_i64 var, int reg)
ad69471c
PB
1514{
1515 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1516}
1517
a7812ae4 1518static inline void neon_store_reg64(TCGv_i64 var, int reg)
ad69471c
PB
1519{
1520 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1521}
1522
160f3b64
PM
1523static inline void neon_load_reg32(TCGv_i32 var, int reg)
1524{
1525 tcg_gen_ld_i32(var, cpu_env, vfp_reg_offset(false, reg));
1526}
1527
1528static inline void neon_store_reg32(TCGv_i32 var, int reg)
1529{
1530 tcg_gen_st_i32(var, cpu_env, vfp_reg_offset(false, reg));
1531}
1532
1a66ac61
RH
1533static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
1534{
1535 TCGv_ptr ret = tcg_temp_new_ptr();
1536 tcg_gen_addi_ptr(ret, cpu_env, vfp_reg_offset(dp, reg));
1537 return ret;
1538}
1539
d00584b7 1540#define ARM_CP_RW_BIT (1 << 20)
18c9b560 1541
78e138bc
PM
1542/* Include the VFP decoder */
1543#include "translate-vfp.inc.c"
1544
a7812ae4 1545static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
e677137d 1546{
0ecb72a5 1547 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
e677137d
PB
1548}
1549
a7812ae4 1550static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
e677137d 1551{
0ecb72a5 1552 tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
e677137d
PB
1553}
1554
39d5492a 1555static inline TCGv_i32 iwmmxt_load_creg(int reg)
e677137d 1556{
39d5492a 1557 TCGv_i32 var = tcg_temp_new_i32();
0ecb72a5 1558 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
da6b5335 1559 return var;
e677137d
PB
1560}
1561
39d5492a 1562static inline void iwmmxt_store_creg(int reg, TCGv_i32 var)
e677137d 1563{
0ecb72a5 1564 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
7d1b0095 1565 tcg_temp_free_i32(var);
e677137d
PB
1566}
1567
1568static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1569{
1570 iwmmxt_store_reg(cpu_M0, rn);
1571}
1572
1573static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1574{
1575 iwmmxt_load_reg(cpu_M0, rn);
1576}
1577
1578static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1579{
1580 iwmmxt_load_reg(cpu_V1, rn);
1581 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1582}
1583
1584static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1585{
1586 iwmmxt_load_reg(cpu_V1, rn);
1587 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1588}
1589
1590static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1591{
1592 iwmmxt_load_reg(cpu_V1, rn);
1593 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1594}
1595
1596#define IWMMXT_OP(name) \
1597static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1598{ \
1599 iwmmxt_load_reg(cpu_V1, rn); \
1600 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1601}
1602
477955bd
PM
1603#define IWMMXT_OP_ENV(name) \
1604static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1605{ \
1606 iwmmxt_load_reg(cpu_V1, rn); \
1607 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1608}
1609
1610#define IWMMXT_OP_ENV_SIZE(name) \
1611IWMMXT_OP_ENV(name##b) \
1612IWMMXT_OP_ENV(name##w) \
1613IWMMXT_OP_ENV(name##l)
e677137d 1614
477955bd 1615#define IWMMXT_OP_ENV1(name) \
e677137d
PB
1616static inline void gen_op_iwmmxt_##name##_M0(void) \
1617{ \
477955bd 1618 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
e677137d
PB
1619}
1620
1621IWMMXT_OP(maddsq)
1622IWMMXT_OP(madduq)
1623IWMMXT_OP(sadb)
1624IWMMXT_OP(sadw)
1625IWMMXT_OP(mulslw)
1626IWMMXT_OP(mulshw)
1627IWMMXT_OP(mululw)
1628IWMMXT_OP(muluhw)
1629IWMMXT_OP(macsw)
1630IWMMXT_OP(macuw)
1631
477955bd
PM
1632IWMMXT_OP_ENV_SIZE(unpackl)
1633IWMMXT_OP_ENV_SIZE(unpackh)
1634
1635IWMMXT_OP_ENV1(unpacklub)
1636IWMMXT_OP_ENV1(unpackluw)
1637IWMMXT_OP_ENV1(unpacklul)
1638IWMMXT_OP_ENV1(unpackhub)
1639IWMMXT_OP_ENV1(unpackhuw)
1640IWMMXT_OP_ENV1(unpackhul)
1641IWMMXT_OP_ENV1(unpacklsb)
1642IWMMXT_OP_ENV1(unpacklsw)
1643IWMMXT_OP_ENV1(unpacklsl)
1644IWMMXT_OP_ENV1(unpackhsb)
1645IWMMXT_OP_ENV1(unpackhsw)
1646IWMMXT_OP_ENV1(unpackhsl)
1647
1648IWMMXT_OP_ENV_SIZE(cmpeq)
1649IWMMXT_OP_ENV_SIZE(cmpgtu)
1650IWMMXT_OP_ENV_SIZE(cmpgts)
1651
1652IWMMXT_OP_ENV_SIZE(mins)
1653IWMMXT_OP_ENV_SIZE(minu)
1654IWMMXT_OP_ENV_SIZE(maxs)
1655IWMMXT_OP_ENV_SIZE(maxu)
1656
1657IWMMXT_OP_ENV_SIZE(subn)
1658IWMMXT_OP_ENV_SIZE(addn)
1659IWMMXT_OP_ENV_SIZE(subu)
1660IWMMXT_OP_ENV_SIZE(addu)
1661IWMMXT_OP_ENV_SIZE(subs)
1662IWMMXT_OP_ENV_SIZE(adds)
1663
1664IWMMXT_OP_ENV(avgb0)
1665IWMMXT_OP_ENV(avgb1)
1666IWMMXT_OP_ENV(avgw0)
1667IWMMXT_OP_ENV(avgw1)
e677137d 1668
477955bd
PM
1669IWMMXT_OP_ENV(packuw)
1670IWMMXT_OP_ENV(packul)
1671IWMMXT_OP_ENV(packuq)
1672IWMMXT_OP_ENV(packsw)
1673IWMMXT_OP_ENV(packsl)
1674IWMMXT_OP_ENV(packsq)
e677137d 1675
e677137d
PB
1676static void gen_op_iwmmxt_set_mup(void)
1677{
39d5492a 1678 TCGv_i32 tmp;
e677137d
PB
1679 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1680 tcg_gen_ori_i32(tmp, tmp, 2);
1681 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1682}
1683
1684static void gen_op_iwmmxt_set_cup(void)
1685{
39d5492a 1686 TCGv_i32 tmp;
e677137d
PB
1687 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1688 tcg_gen_ori_i32(tmp, tmp, 1);
1689 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1690}
1691
1692static void gen_op_iwmmxt_setpsr_nz(void)
1693{
39d5492a 1694 TCGv_i32 tmp = tcg_temp_new_i32();
e677137d
PB
1695 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1696 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1697}
1698
1699static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1700{
1701 iwmmxt_load_reg(cpu_V1, rn);
86831435 1702 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
e677137d
PB
1703 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1704}
1705
39d5492a
PM
1706static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn,
1707 TCGv_i32 dest)
18c9b560
AZ
1708{
1709 int rd;
1710 uint32_t offset;
39d5492a 1711 TCGv_i32 tmp;
18c9b560
AZ
1712
1713 rd = (insn >> 16) & 0xf;
da6b5335 1714 tmp = load_reg(s, rd);
18c9b560
AZ
1715
1716 offset = (insn & 0xff) << ((insn >> 7) & 2);
1717 if (insn & (1 << 24)) {
1718 /* Pre indexed */
1719 if (insn & (1 << 23))
da6b5335 1720 tcg_gen_addi_i32(tmp, tmp, offset);
18c9b560 1721 else
da6b5335
FN
1722 tcg_gen_addi_i32(tmp, tmp, -offset);
1723 tcg_gen_mov_i32(dest, tmp);
18c9b560 1724 if (insn & (1 << 21))
da6b5335
FN
1725 store_reg(s, rd, tmp);
1726 else
7d1b0095 1727 tcg_temp_free_i32(tmp);
18c9b560
AZ
1728 } else if (insn & (1 << 21)) {
1729 /* Post indexed */
da6b5335 1730 tcg_gen_mov_i32(dest, tmp);
18c9b560 1731 if (insn & (1 << 23))
da6b5335 1732 tcg_gen_addi_i32(tmp, tmp, offset);
18c9b560 1733 else
da6b5335
FN
1734 tcg_gen_addi_i32(tmp, tmp, -offset);
1735 store_reg(s, rd, tmp);
18c9b560
AZ
1736 } else if (!(insn & (1 << 23)))
1737 return 1;
1738 return 0;
1739}
1740
39d5492a 1741static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest)
18c9b560
AZ
1742{
1743 int rd = (insn >> 0) & 0xf;
39d5492a 1744 TCGv_i32 tmp;
18c9b560 1745
da6b5335
FN
1746 if (insn & (1 << 8)) {
1747 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
18c9b560 1748 return 1;
da6b5335
FN
1749 } else {
1750 tmp = iwmmxt_load_creg(rd);
1751 }
1752 } else {
7d1b0095 1753 tmp = tcg_temp_new_i32();
da6b5335 1754 iwmmxt_load_reg(cpu_V0, rd);
ecc7b3aa 1755 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
da6b5335
FN
1756 }
1757 tcg_gen_andi_i32(tmp, tmp, mask);
1758 tcg_gen_mov_i32(dest, tmp);
7d1b0095 1759 tcg_temp_free_i32(tmp);
18c9b560
AZ
1760 return 0;
1761}
1762
a1c7273b 1763/* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
18c9b560 1764 (ie. an undefined instruction). */
7dcc1f89 1765static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
18c9b560
AZ
1766{
1767 int rd, wrd;
1768 int rdhi, rdlo, rd0, rd1, i;
39d5492a
PM
1769 TCGv_i32 addr;
1770 TCGv_i32 tmp, tmp2, tmp3;
18c9b560
AZ
1771
1772 if ((insn & 0x0e000e00) == 0x0c000000) {
1773 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1774 wrd = insn & 0xf;
1775 rdlo = (insn >> 12) & 0xf;
1776 rdhi = (insn >> 16) & 0xf;
d00584b7 1777 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
da6b5335 1778 iwmmxt_load_reg(cpu_V0, wrd);
ecc7b3aa 1779 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
da6b5335 1780 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
ecc7b3aa 1781 tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
d00584b7 1782 } else { /* TMCRR */
da6b5335
FN
1783 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1784 iwmmxt_store_reg(cpu_V0, wrd);
18c9b560
AZ
1785 gen_op_iwmmxt_set_mup();
1786 }
1787 return 0;
1788 }
1789
1790 wrd = (insn >> 12) & 0xf;
7d1b0095 1791 addr = tcg_temp_new_i32();
da6b5335 1792 if (gen_iwmmxt_address(s, insn, addr)) {
7d1b0095 1793 tcg_temp_free_i32(addr);
18c9b560 1794 return 1;
da6b5335 1795 }
18c9b560 1796 if (insn & ARM_CP_RW_BIT) {
d00584b7 1797 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
7d1b0095 1798 tmp = tcg_temp_new_i32();
12dcc321 1799 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
da6b5335 1800 iwmmxt_store_creg(wrd, tmp);
18c9b560 1801 } else {
e677137d
PB
1802 i = 1;
1803 if (insn & (1 << 8)) {
d00584b7 1804 if (insn & (1 << 22)) { /* WLDRD */
12dcc321 1805 gen_aa32_ld64(s, cpu_M0, addr, get_mem_index(s));
e677137d 1806 i = 0;
d00584b7 1807 } else { /* WLDRW wRd */
29531141 1808 tmp = tcg_temp_new_i32();
12dcc321 1809 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
e677137d
PB
1810 }
1811 } else {
29531141 1812 tmp = tcg_temp_new_i32();
d00584b7 1813 if (insn & (1 << 22)) { /* WLDRH */
12dcc321 1814 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
d00584b7 1815 } else { /* WLDRB */
12dcc321 1816 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
e677137d
PB
1817 }
1818 }
1819 if (i) {
1820 tcg_gen_extu_i32_i64(cpu_M0, tmp);
7d1b0095 1821 tcg_temp_free_i32(tmp);
e677137d 1822 }
18c9b560
AZ
1823 gen_op_iwmmxt_movq_wRn_M0(wrd);
1824 }
1825 } else {
d00584b7 1826 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
da6b5335 1827 tmp = iwmmxt_load_creg(wrd);
12dcc321 1828 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
18c9b560
AZ
1829 } else {
1830 gen_op_iwmmxt_movq_M0_wRn(wrd);
7d1b0095 1831 tmp = tcg_temp_new_i32();
e677137d 1832 if (insn & (1 << 8)) {
d00584b7 1833 if (insn & (1 << 22)) { /* WSTRD */
12dcc321 1834 gen_aa32_st64(s, cpu_M0, addr, get_mem_index(s));
d00584b7 1835 } else { /* WSTRW wRd */
ecc7b3aa 1836 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
12dcc321 1837 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
e677137d
PB
1838 }
1839 } else {
d00584b7 1840 if (insn & (1 << 22)) { /* WSTRH */
ecc7b3aa 1841 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
12dcc321 1842 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
d00584b7 1843 } else { /* WSTRB */
ecc7b3aa 1844 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
12dcc321 1845 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
e677137d
PB
1846 }
1847 }
18c9b560 1848 }
29531141 1849 tcg_temp_free_i32(tmp);
18c9b560 1850 }
7d1b0095 1851 tcg_temp_free_i32(addr);
18c9b560
AZ
1852 return 0;
1853 }
1854
1855 if ((insn & 0x0f000000) != 0x0e000000)
1856 return 1;
1857
1858 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
d00584b7 1859 case 0x000: /* WOR */
18c9b560
AZ
1860 wrd = (insn >> 12) & 0xf;
1861 rd0 = (insn >> 0) & 0xf;
1862 rd1 = (insn >> 16) & 0xf;
1863 gen_op_iwmmxt_movq_M0_wRn(rd0);
1864 gen_op_iwmmxt_orq_M0_wRn(rd1);
1865 gen_op_iwmmxt_setpsr_nz();
1866 gen_op_iwmmxt_movq_wRn_M0(wrd);
1867 gen_op_iwmmxt_set_mup();
1868 gen_op_iwmmxt_set_cup();
1869 break;
d00584b7 1870 case 0x011: /* TMCR */
18c9b560
AZ
1871 if (insn & 0xf)
1872 return 1;
1873 rd = (insn >> 12) & 0xf;
1874 wrd = (insn >> 16) & 0xf;
1875 switch (wrd) {
1876 case ARM_IWMMXT_wCID:
1877 case ARM_IWMMXT_wCASF:
1878 break;
1879 case ARM_IWMMXT_wCon:
1880 gen_op_iwmmxt_set_cup();
1881 /* Fall through. */
1882 case ARM_IWMMXT_wCSSF:
da6b5335
FN
1883 tmp = iwmmxt_load_creg(wrd);
1884 tmp2 = load_reg(s, rd);
f669df27 1885 tcg_gen_andc_i32(tmp, tmp, tmp2);
7d1b0095 1886 tcg_temp_free_i32(tmp2);
da6b5335 1887 iwmmxt_store_creg(wrd, tmp);
18c9b560
AZ
1888 break;
1889 case ARM_IWMMXT_wCGR0:
1890 case ARM_IWMMXT_wCGR1:
1891 case ARM_IWMMXT_wCGR2:
1892 case ARM_IWMMXT_wCGR3:
1893 gen_op_iwmmxt_set_cup();
da6b5335
FN
1894 tmp = load_reg(s, rd);
1895 iwmmxt_store_creg(wrd, tmp);
18c9b560
AZ
1896 break;
1897 default:
1898 return 1;
1899 }
1900 break;
d00584b7 1901 case 0x100: /* WXOR */
18c9b560
AZ
1902 wrd = (insn >> 12) & 0xf;
1903 rd0 = (insn >> 0) & 0xf;
1904 rd1 = (insn >> 16) & 0xf;
1905 gen_op_iwmmxt_movq_M0_wRn(rd0);
1906 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1907 gen_op_iwmmxt_setpsr_nz();
1908 gen_op_iwmmxt_movq_wRn_M0(wrd);
1909 gen_op_iwmmxt_set_mup();
1910 gen_op_iwmmxt_set_cup();
1911 break;
d00584b7 1912 case 0x111: /* TMRC */
18c9b560
AZ
1913 if (insn & 0xf)
1914 return 1;
1915 rd = (insn >> 12) & 0xf;
1916 wrd = (insn >> 16) & 0xf;
da6b5335
FN
1917 tmp = iwmmxt_load_creg(wrd);
1918 store_reg(s, rd, tmp);
18c9b560 1919 break;
d00584b7 1920 case 0x300: /* WANDN */
18c9b560
AZ
1921 wrd = (insn >> 12) & 0xf;
1922 rd0 = (insn >> 0) & 0xf;
1923 rd1 = (insn >> 16) & 0xf;
1924 gen_op_iwmmxt_movq_M0_wRn(rd0);
e677137d 1925 tcg_gen_neg_i64(cpu_M0, cpu_M0);
18c9b560
AZ
1926 gen_op_iwmmxt_andq_M0_wRn(rd1);
1927 gen_op_iwmmxt_setpsr_nz();
1928 gen_op_iwmmxt_movq_wRn_M0(wrd);
1929 gen_op_iwmmxt_set_mup();
1930 gen_op_iwmmxt_set_cup();
1931 break;
d00584b7 1932 case 0x200: /* WAND */
18c9b560
AZ
1933 wrd = (insn >> 12) & 0xf;
1934 rd0 = (insn >> 0) & 0xf;
1935 rd1 = (insn >> 16) & 0xf;
1936 gen_op_iwmmxt_movq_M0_wRn(rd0);
1937 gen_op_iwmmxt_andq_M0_wRn(rd1);
1938 gen_op_iwmmxt_setpsr_nz();
1939 gen_op_iwmmxt_movq_wRn_M0(wrd);
1940 gen_op_iwmmxt_set_mup();
1941 gen_op_iwmmxt_set_cup();
1942 break;
d00584b7 1943 case 0x810: case 0xa10: /* WMADD */
18c9b560
AZ
1944 wrd = (insn >> 12) & 0xf;
1945 rd0 = (insn >> 0) & 0xf;
1946 rd1 = (insn >> 16) & 0xf;
1947 gen_op_iwmmxt_movq_M0_wRn(rd0);
1948 if (insn & (1 << 21))
1949 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1950 else
1951 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1952 gen_op_iwmmxt_movq_wRn_M0(wrd);
1953 gen_op_iwmmxt_set_mup();
1954 break;
d00584b7 1955 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
18c9b560
AZ
1956 wrd = (insn >> 12) & 0xf;
1957 rd0 = (insn >> 16) & 0xf;
1958 rd1 = (insn >> 0) & 0xf;
1959 gen_op_iwmmxt_movq_M0_wRn(rd0);
1960 switch ((insn >> 22) & 3) {
1961 case 0:
1962 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1963 break;
1964 case 1:
1965 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1966 break;
1967 case 2:
1968 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1969 break;
1970 case 3:
1971 return 1;
1972 }
1973 gen_op_iwmmxt_movq_wRn_M0(wrd);
1974 gen_op_iwmmxt_set_mup();
1975 gen_op_iwmmxt_set_cup();
1976 break;
d00584b7 1977 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
18c9b560
AZ
1978 wrd = (insn >> 12) & 0xf;
1979 rd0 = (insn >> 16) & 0xf;
1980 rd1 = (insn >> 0) & 0xf;
1981 gen_op_iwmmxt_movq_M0_wRn(rd0);
1982 switch ((insn >> 22) & 3) {
1983 case 0:
1984 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1985 break;
1986 case 1:
1987 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1988 break;
1989 case 2:
1990 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1991 break;
1992 case 3:
1993 return 1;
1994 }
1995 gen_op_iwmmxt_movq_wRn_M0(wrd);
1996 gen_op_iwmmxt_set_mup();
1997 gen_op_iwmmxt_set_cup();
1998 break;
d00584b7 1999 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
18c9b560
AZ
2000 wrd = (insn >> 12) & 0xf;
2001 rd0 = (insn >> 16) & 0xf;
2002 rd1 = (insn >> 0) & 0xf;
2003 gen_op_iwmmxt_movq_M0_wRn(rd0);
2004 if (insn & (1 << 22))
2005 gen_op_iwmmxt_sadw_M0_wRn(rd1);
2006 else
2007 gen_op_iwmmxt_sadb_M0_wRn(rd1);
2008 if (!(insn & (1 << 20)))
2009 gen_op_iwmmxt_addl_M0_wRn(wrd);
2010 gen_op_iwmmxt_movq_wRn_M0(wrd);
2011 gen_op_iwmmxt_set_mup();
2012 break;
d00584b7 2013 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
18c9b560
AZ
2014 wrd = (insn >> 12) & 0xf;
2015 rd0 = (insn >> 16) & 0xf;
2016 rd1 = (insn >> 0) & 0xf;
2017 gen_op_iwmmxt_movq_M0_wRn(rd0);
e677137d
PB
2018 if (insn & (1 << 21)) {
2019 if (insn & (1 << 20))
2020 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
2021 else
2022 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
2023 } else {
2024 if (insn & (1 << 20))
2025 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
2026 else
2027 gen_op_iwmmxt_mululw_M0_wRn(rd1);
2028 }
18c9b560
AZ
2029 gen_op_iwmmxt_movq_wRn_M0(wrd);
2030 gen_op_iwmmxt_set_mup();
2031 break;
d00584b7 2032 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
18c9b560
AZ
2033 wrd = (insn >> 12) & 0xf;
2034 rd0 = (insn >> 16) & 0xf;
2035 rd1 = (insn >> 0) & 0xf;
2036 gen_op_iwmmxt_movq_M0_wRn(rd0);
2037 if (insn & (1 << 21))
2038 gen_op_iwmmxt_macsw_M0_wRn(rd1);
2039 else
2040 gen_op_iwmmxt_macuw_M0_wRn(rd1);
2041 if (!(insn & (1 << 20))) {
e677137d
PB
2042 iwmmxt_load_reg(cpu_V1, wrd);
2043 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
18c9b560
AZ
2044 }
2045 gen_op_iwmmxt_movq_wRn_M0(wrd);
2046 gen_op_iwmmxt_set_mup();
2047 break;
d00584b7 2048 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
18c9b560
AZ
2049 wrd = (insn >> 12) & 0xf;
2050 rd0 = (insn >> 16) & 0xf;
2051 rd1 = (insn >> 0) & 0xf;
2052 gen_op_iwmmxt_movq_M0_wRn(rd0);
2053 switch ((insn >> 22) & 3) {
2054 case 0:
2055 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
2056 break;
2057 case 1:
2058 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
2059 break;
2060 case 2:
2061 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
2062 break;
2063 case 3:
2064 return 1;
2065 }
2066 gen_op_iwmmxt_movq_wRn_M0(wrd);
2067 gen_op_iwmmxt_set_mup();
2068 gen_op_iwmmxt_set_cup();
2069 break;
d00584b7 2070 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
18c9b560
AZ
2071 wrd = (insn >> 12) & 0xf;
2072 rd0 = (insn >> 16) & 0xf;
2073 rd1 = (insn >> 0) & 0xf;
2074 gen_op_iwmmxt_movq_M0_wRn(rd0);
e677137d
PB
2075 if (insn & (1 << 22)) {
2076 if (insn & (1 << 20))
2077 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
2078 else
2079 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
2080 } else {
2081 if (insn & (1 << 20))
2082 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
2083 else
2084 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
2085 }
18c9b560
AZ
2086 gen_op_iwmmxt_movq_wRn_M0(wrd);
2087 gen_op_iwmmxt_set_mup();
2088 gen_op_iwmmxt_set_cup();
2089 break;
d00584b7 2090 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
18c9b560
AZ
2091 wrd = (insn >> 12) & 0xf;
2092 rd0 = (insn >> 16) & 0xf;
2093 rd1 = (insn >> 0) & 0xf;
2094 gen_op_iwmmxt_movq_M0_wRn(rd0);
da6b5335
FN
2095 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
2096 tcg_gen_andi_i32(tmp, tmp, 7);
2097 iwmmxt_load_reg(cpu_V1, rd1);
2098 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
7d1b0095 2099 tcg_temp_free_i32(tmp);
18c9b560
AZ
2100 gen_op_iwmmxt_movq_wRn_M0(wrd);
2101 gen_op_iwmmxt_set_mup();
2102 break;
d00584b7 2103 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
da6b5335
FN
2104 if (((insn >> 6) & 3) == 3)
2105 return 1;
18c9b560
AZ
2106 rd = (insn >> 12) & 0xf;
2107 wrd = (insn >> 16) & 0xf;
da6b5335 2108 tmp = load_reg(s, rd);
18c9b560
AZ
2109 gen_op_iwmmxt_movq_M0_wRn(wrd);
2110 switch ((insn >> 6) & 3) {
2111 case 0:
da6b5335
FN
2112 tmp2 = tcg_const_i32(0xff);
2113 tmp3 = tcg_const_i32((insn & 7) << 3);
18c9b560
AZ
2114 break;
2115 case 1:
da6b5335
FN
2116 tmp2 = tcg_const_i32(0xffff);
2117 tmp3 = tcg_const_i32((insn & 3) << 4);
18c9b560
AZ
2118 break;
2119 case 2:
da6b5335
FN
2120 tmp2 = tcg_const_i32(0xffffffff);
2121 tmp3 = tcg_const_i32((insn & 1) << 5);
18c9b560 2122 break;
da6b5335 2123 default:
f764718d
RH
2124 tmp2 = NULL;
2125 tmp3 = NULL;
18c9b560 2126 }
da6b5335 2127 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
39d5492a
PM
2128 tcg_temp_free_i32(tmp3);
2129 tcg_temp_free_i32(tmp2);
7d1b0095 2130 tcg_temp_free_i32(tmp);
18c9b560
AZ
2131 gen_op_iwmmxt_movq_wRn_M0(wrd);
2132 gen_op_iwmmxt_set_mup();
2133 break;
d00584b7 2134 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
18c9b560
AZ
2135 rd = (insn >> 12) & 0xf;
2136 wrd = (insn >> 16) & 0xf;
da6b5335 2137 if (rd == 15 || ((insn >> 22) & 3) == 3)
18c9b560
AZ
2138 return 1;
2139 gen_op_iwmmxt_movq_M0_wRn(wrd);
7d1b0095 2140 tmp = tcg_temp_new_i32();
18c9b560
AZ
2141 switch ((insn >> 22) & 3) {
2142 case 0:
da6b5335 2143 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
ecc7b3aa 2144 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
da6b5335
FN
2145 if (insn & 8) {
2146 tcg_gen_ext8s_i32(tmp, tmp);
2147 } else {
2148 tcg_gen_andi_i32(tmp, tmp, 0xff);
18c9b560
AZ
2149 }
2150 break;
2151 case 1:
da6b5335 2152 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
ecc7b3aa 2153 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
da6b5335
FN
2154 if (insn & 8) {
2155 tcg_gen_ext16s_i32(tmp, tmp);
2156 } else {
2157 tcg_gen_andi_i32(tmp, tmp, 0xffff);
18c9b560
AZ
2158 }
2159 break;
2160 case 2:
da6b5335 2161 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
ecc7b3aa 2162 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
18c9b560 2163 break;
18c9b560 2164 }
da6b5335 2165 store_reg(s, rd, tmp);
18c9b560 2166 break;
d00584b7 2167 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
da6b5335 2168 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
18c9b560 2169 return 1;
da6b5335 2170 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
18c9b560
AZ
2171 switch ((insn >> 22) & 3) {
2172 case 0:
da6b5335 2173 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
18c9b560
AZ
2174 break;
2175 case 1:
da6b5335 2176 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
18c9b560
AZ
2177 break;
2178 case 2:
da6b5335 2179 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
18c9b560 2180 break;
18c9b560 2181 }
da6b5335
FN
2182 tcg_gen_shli_i32(tmp, tmp, 28);
2183 gen_set_nzcv(tmp);
7d1b0095 2184 tcg_temp_free_i32(tmp);
18c9b560 2185 break;
d00584b7 2186 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
da6b5335
FN
2187 if (((insn >> 6) & 3) == 3)
2188 return 1;
18c9b560
AZ
2189 rd = (insn >> 12) & 0xf;
2190 wrd = (insn >> 16) & 0xf;
da6b5335 2191 tmp = load_reg(s, rd);
18c9b560
AZ
2192 switch ((insn >> 6) & 3) {
2193 case 0:
da6b5335 2194 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
18c9b560
AZ
2195 break;
2196 case 1:
da6b5335 2197 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
18c9b560
AZ
2198 break;
2199 case 2:
da6b5335 2200 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
18c9b560 2201 break;
18c9b560 2202 }
7d1b0095 2203 tcg_temp_free_i32(tmp);
18c9b560
AZ
2204 gen_op_iwmmxt_movq_wRn_M0(wrd);
2205 gen_op_iwmmxt_set_mup();
2206 break;
d00584b7 2207 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
da6b5335 2208 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
18c9b560 2209 return 1;
da6b5335 2210 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
7d1b0095 2211 tmp2 = tcg_temp_new_i32();
da6b5335 2212 tcg_gen_mov_i32(tmp2, tmp);
18c9b560
AZ
2213 switch ((insn >> 22) & 3) {
2214 case 0:
2215 for (i = 0; i < 7; i ++) {
da6b5335
FN
2216 tcg_gen_shli_i32(tmp2, tmp2, 4);
2217 tcg_gen_and_i32(tmp, tmp, tmp2);
18c9b560
AZ
2218 }
2219 break;
2220 case 1:
2221 for (i = 0; i < 3; i ++) {
da6b5335
FN
2222 tcg_gen_shli_i32(tmp2, tmp2, 8);
2223 tcg_gen_and_i32(tmp, tmp, tmp2);
18c9b560
AZ
2224 }
2225 break;
2226 case 2:
da6b5335
FN
2227 tcg_gen_shli_i32(tmp2, tmp2, 16);
2228 tcg_gen_and_i32(tmp, tmp, tmp2);
18c9b560 2229 break;
18c9b560 2230 }
da6b5335 2231 gen_set_nzcv(tmp);
7d1b0095
PM
2232 tcg_temp_free_i32(tmp2);
2233 tcg_temp_free_i32(tmp);
18c9b560 2234 break;
d00584b7 2235 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
18c9b560
AZ
2236 wrd = (insn >> 12) & 0xf;
2237 rd0 = (insn >> 16) & 0xf;
2238 gen_op_iwmmxt_movq_M0_wRn(rd0);
2239 switch ((insn >> 22) & 3) {
2240 case 0:
e677137d 2241 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
18c9b560
AZ
2242 break;
2243 case 1:
e677137d 2244 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
18c9b560
AZ
2245 break;
2246 case 2:
e677137d 2247 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
18c9b560
AZ
2248 break;
2249 case 3:
2250 return 1;
2251 }
2252 gen_op_iwmmxt_movq_wRn_M0(wrd);
2253 gen_op_iwmmxt_set_mup();
2254 break;
d00584b7 2255 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
da6b5335 2256 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
18c9b560 2257 return 1;
da6b5335 2258 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
7d1b0095 2259 tmp2 = tcg_temp_new_i32();
da6b5335 2260 tcg_gen_mov_i32(tmp2, tmp);
18c9b560
AZ
2261 switch ((insn >> 22) & 3) {
2262 case 0:
2263 for (i = 0; i < 7; i ++) {
da6b5335
FN
2264 tcg_gen_shli_i32(tmp2, tmp2, 4);
2265 tcg_gen_or_i32(tmp, tmp, tmp2);
18c9b560
AZ
2266 }
2267 break;
2268 case 1:
2269 for (i = 0; i < 3; i ++) {
da6b5335
FN
2270 tcg_gen_shli_i32(tmp2, tmp2, 8);
2271 tcg_gen_or_i32(tmp, tmp, tmp2);
18c9b560
AZ
2272 }
2273 break;
2274 case 2:
da6b5335
FN
2275 tcg_gen_shli_i32(tmp2, tmp2, 16);
2276 tcg_gen_or_i32(tmp, tmp, tmp2);
18c9b560 2277 break;
18c9b560 2278 }
da6b5335 2279 gen_set_nzcv(tmp);
7d1b0095
PM
2280 tcg_temp_free_i32(tmp2);
2281 tcg_temp_free_i32(tmp);
18c9b560 2282 break;
d00584b7 2283 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
18c9b560
AZ
2284 rd = (insn >> 12) & 0xf;
2285 rd0 = (insn >> 16) & 0xf;
da6b5335 2286 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
18c9b560
AZ
2287 return 1;
2288 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2289 tmp = tcg_temp_new_i32();
18c9b560
AZ
2290 switch ((insn >> 22) & 3) {
2291 case 0:
da6b5335 2292 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
18c9b560
AZ
2293 break;
2294 case 1:
da6b5335 2295 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
18c9b560
AZ
2296 break;
2297 case 2:
da6b5335 2298 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
18c9b560 2299 break;
18c9b560 2300 }
da6b5335 2301 store_reg(s, rd, tmp);
18c9b560 2302 break;
d00584b7 2303 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
18c9b560
AZ
2304 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2305 wrd = (insn >> 12) & 0xf;
2306 rd0 = (insn >> 16) & 0xf;
2307 rd1 = (insn >> 0) & 0xf;
2308 gen_op_iwmmxt_movq_M0_wRn(rd0);
2309 switch ((insn >> 22) & 3) {
2310 case 0:
2311 if (insn & (1 << 21))
2312 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2313 else
2314 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2315 break;
2316 case 1:
2317 if (insn & (1 << 21))
2318 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2319 else
2320 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2321 break;
2322 case 2:
2323 if (insn & (1 << 21))
2324 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2325 else
2326 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2327 break;
2328 case 3:
2329 return 1;
2330 }
2331 gen_op_iwmmxt_movq_wRn_M0(wrd);
2332 gen_op_iwmmxt_set_mup();
2333 gen_op_iwmmxt_set_cup();
2334 break;
d00584b7 2335 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
18c9b560
AZ
2336 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2337 wrd = (insn >> 12) & 0xf;
2338 rd0 = (insn >> 16) & 0xf;
2339 gen_op_iwmmxt_movq_M0_wRn(rd0);
2340 switch ((insn >> 22) & 3) {
2341 case 0:
2342 if (insn & (1 << 21))
2343 gen_op_iwmmxt_unpacklsb_M0();
2344 else
2345 gen_op_iwmmxt_unpacklub_M0();
2346 break;
2347 case 1:
2348 if (insn & (1 << 21))
2349 gen_op_iwmmxt_unpacklsw_M0();
2350 else
2351 gen_op_iwmmxt_unpackluw_M0();
2352 break;
2353 case 2:
2354 if (insn & (1 << 21))
2355 gen_op_iwmmxt_unpacklsl_M0();
2356 else
2357 gen_op_iwmmxt_unpacklul_M0();
2358 break;
2359 case 3:
2360 return 1;
2361 }
2362 gen_op_iwmmxt_movq_wRn_M0(wrd);
2363 gen_op_iwmmxt_set_mup();
2364 gen_op_iwmmxt_set_cup();
2365 break;
d00584b7 2366 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
18c9b560
AZ
2367 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2368 wrd = (insn >> 12) & 0xf;
2369 rd0 = (insn >> 16) & 0xf;
2370 gen_op_iwmmxt_movq_M0_wRn(rd0);
2371 switch ((insn >> 22) & 3) {
2372 case 0:
2373 if (insn & (1 << 21))
2374 gen_op_iwmmxt_unpackhsb_M0();
2375 else
2376 gen_op_iwmmxt_unpackhub_M0();
2377 break;
2378 case 1:
2379 if (insn & (1 << 21))
2380 gen_op_iwmmxt_unpackhsw_M0();
2381 else
2382 gen_op_iwmmxt_unpackhuw_M0();
2383 break;
2384 case 2:
2385 if (insn & (1 << 21))
2386 gen_op_iwmmxt_unpackhsl_M0();
2387 else
2388 gen_op_iwmmxt_unpackhul_M0();
2389 break;
2390 case 3:
2391 return 1;
2392 }
2393 gen_op_iwmmxt_movq_wRn_M0(wrd);
2394 gen_op_iwmmxt_set_mup();
2395 gen_op_iwmmxt_set_cup();
2396 break;
d00584b7 2397 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
18c9b560 2398 case 0x214: case 0x614: case 0xa14: case 0xe14:
da6b5335
FN
2399 if (((insn >> 22) & 3) == 0)
2400 return 1;
18c9b560
AZ
2401 wrd = (insn >> 12) & 0xf;
2402 rd0 = (insn >> 16) & 0xf;
2403 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2404 tmp = tcg_temp_new_i32();
da6b5335 2405 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
7d1b0095 2406 tcg_temp_free_i32(tmp);
18c9b560 2407 return 1;
da6b5335 2408 }
18c9b560 2409 switch ((insn >> 22) & 3) {
18c9b560 2410 case 1:
477955bd 2411 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2412 break;
2413 case 2:
477955bd 2414 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2415 break;
2416 case 3:
477955bd 2417 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2418 break;
2419 }
7d1b0095 2420 tcg_temp_free_i32(tmp);
18c9b560
AZ
2421 gen_op_iwmmxt_movq_wRn_M0(wrd);
2422 gen_op_iwmmxt_set_mup();
2423 gen_op_iwmmxt_set_cup();
2424 break;
d00584b7 2425 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
18c9b560 2426 case 0x014: case 0x414: case 0x814: case 0xc14:
da6b5335
FN
2427 if (((insn >> 22) & 3) == 0)
2428 return 1;
18c9b560
AZ
2429 wrd = (insn >> 12) & 0xf;
2430 rd0 = (insn >> 16) & 0xf;
2431 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2432 tmp = tcg_temp_new_i32();
da6b5335 2433 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
7d1b0095 2434 tcg_temp_free_i32(tmp);
18c9b560 2435 return 1;
da6b5335 2436 }
18c9b560 2437 switch ((insn >> 22) & 3) {
18c9b560 2438 case 1:
477955bd 2439 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2440 break;
2441 case 2:
477955bd 2442 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2443 break;
2444 case 3:
477955bd 2445 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2446 break;
2447 }
7d1b0095 2448 tcg_temp_free_i32(tmp);
18c9b560
AZ
2449 gen_op_iwmmxt_movq_wRn_M0(wrd);
2450 gen_op_iwmmxt_set_mup();
2451 gen_op_iwmmxt_set_cup();
2452 break;
d00584b7 2453 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
18c9b560 2454 case 0x114: case 0x514: case 0x914: case 0xd14:
da6b5335
FN
2455 if (((insn >> 22) & 3) == 0)
2456 return 1;
18c9b560
AZ
2457 wrd = (insn >> 12) & 0xf;
2458 rd0 = (insn >> 16) & 0xf;
2459 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2460 tmp = tcg_temp_new_i32();
da6b5335 2461 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
7d1b0095 2462 tcg_temp_free_i32(tmp);
18c9b560 2463 return 1;
da6b5335 2464 }
18c9b560 2465 switch ((insn >> 22) & 3) {
18c9b560 2466 case 1:
477955bd 2467 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2468 break;
2469 case 2:
477955bd 2470 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2471 break;
2472 case 3:
477955bd 2473 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2474 break;
2475 }
7d1b0095 2476 tcg_temp_free_i32(tmp);
18c9b560
AZ
2477 gen_op_iwmmxt_movq_wRn_M0(wrd);
2478 gen_op_iwmmxt_set_mup();
2479 gen_op_iwmmxt_set_cup();
2480 break;
d00584b7 2481 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
18c9b560 2482 case 0x314: case 0x714: case 0xb14: case 0xf14:
da6b5335
FN
2483 if (((insn >> 22) & 3) == 0)
2484 return 1;
18c9b560
AZ
2485 wrd = (insn >> 12) & 0xf;
2486 rd0 = (insn >> 16) & 0xf;
2487 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2488 tmp = tcg_temp_new_i32();
18c9b560 2489 switch ((insn >> 22) & 3) {
18c9b560 2490 case 1:
da6b5335 2491 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
7d1b0095 2492 tcg_temp_free_i32(tmp);
18c9b560 2493 return 1;
da6b5335 2494 }
477955bd 2495 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2496 break;
2497 case 2:
da6b5335 2498 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
7d1b0095 2499 tcg_temp_free_i32(tmp);
18c9b560 2500 return 1;
da6b5335 2501 }
477955bd 2502 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2503 break;
2504 case 3:
da6b5335 2505 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
7d1b0095 2506 tcg_temp_free_i32(tmp);
18c9b560 2507 return 1;
da6b5335 2508 }
477955bd 2509 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2510 break;
2511 }
7d1b0095 2512 tcg_temp_free_i32(tmp);
18c9b560
AZ
2513 gen_op_iwmmxt_movq_wRn_M0(wrd);
2514 gen_op_iwmmxt_set_mup();
2515 gen_op_iwmmxt_set_cup();
2516 break;
d00584b7 2517 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
18c9b560
AZ
2518 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2519 wrd = (insn >> 12) & 0xf;
2520 rd0 = (insn >> 16) & 0xf;
2521 rd1 = (insn >> 0) & 0xf;
2522 gen_op_iwmmxt_movq_M0_wRn(rd0);
2523 switch ((insn >> 22) & 3) {
2524 case 0:
2525 if (insn & (1 << 21))
2526 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2527 else
2528 gen_op_iwmmxt_minub_M0_wRn(rd1);
2529 break;
2530 case 1:
2531 if (insn & (1 << 21))
2532 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2533 else
2534 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2535 break;
2536 case 2:
2537 if (insn & (1 << 21))
2538 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2539 else
2540 gen_op_iwmmxt_minul_M0_wRn(rd1);
2541 break;
2542 case 3:
2543 return 1;
2544 }
2545 gen_op_iwmmxt_movq_wRn_M0(wrd);
2546 gen_op_iwmmxt_set_mup();
2547 break;
d00584b7 2548 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
18c9b560
AZ
2549 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2550 wrd = (insn >> 12) & 0xf;
2551 rd0 = (insn >> 16) & 0xf;
2552 rd1 = (insn >> 0) & 0xf;
2553 gen_op_iwmmxt_movq_M0_wRn(rd0);
2554 switch ((insn >> 22) & 3) {
2555 case 0:
2556 if (insn & (1 << 21))
2557 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2558 else
2559 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2560 break;
2561 case 1:
2562 if (insn & (1 << 21))
2563 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2564 else
2565 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2566 break;
2567 case 2:
2568 if (insn & (1 << 21))
2569 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2570 else
2571 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2572 break;
2573 case 3:
2574 return 1;
2575 }
2576 gen_op_iwmmxt_movq_wRn_M0(wrd);
2577 gen_op_iwmmxt_set_mup();
2578 break;
d00584b7 2579 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
18c9b560
AZ
2580 case 0x402: case 0x502: case 0x602: case 0x702:
2581 wrd = (insn >> 12) & 0xf;
2582 rd0 = (insn >> 16) & 0xf;
2583 rd1 = (insn >> 0) & 0xf;
2584 gen_op_iwmmxt_movq_M0_wRn(rd0);
da6b5335
FN
2585 tmp = tcg_const_i32((insn >> 20) & 3);
2586 iwmmxt_load_reg(cpu_V1, rd1);
2587 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
39d5492a 2588 tcg_temp_free_i32(tmp);
18c9b560
AZ
2589 gen_op_iwmmxt_movq_wRn_M0(wrd);
2590 gen_op_iwmmxt_set_mup();
2591 break;
d00584b7 2592 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
18c9b560
AZ
2593 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2594 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2595 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2596 wrd = (insn >> 12) & 0xf;
2597 rd0 = (insn >> 16) & 0xf;
2598 rd1 = (insn >> 0) & 0xf;
2599 gen_op_iwmmxt_movq_M0_wRn(rd0);
2600 switch ((insn >> 20) & 0xf) {
2601 case 0x0:
2602 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2603 break;
2604 case 0x1:
2605 gen_op_iwmmxt_subub_M0_wRn(rd1);
2606 break;
2607 case 0x3:
2608 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2609 break;
2610 case 0x4:
2611 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2612 break;
2613 case 0x5:
2614 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2615 break;
2616 case 0x7:
2617 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2618 break;
2619 case 0x8:
2620 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2621 break;
2622 case 0x9:
2623 gen_op_iwmmxt_subul_M0_wRn(rd1);
2624 break;
2625 case 0xb:
2626 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2627 break;
2628 default:
2629 return 1;
2630 }
2631 gen_op_iwmmxt_movq_wRn_M0(wrd);
2632 gen_op_iwmmxt_set_mup();
2633 gen_op_iwmmxt_set_cup();
2634 break;
d00584b7 2635 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
18c9b560
AZ
2636 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2637 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2638 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2639 wrd = (insn >> 12) & 0xf;
2640 rd0 = (insn >> 16) & 0xf;
2641 gen_op_iwmmxt_movq_M0_wRn(rd0);
da6b5335 2642 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
477955bd 2643 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
39d5492a 2644 tcg_temp_free_i32(tmp);
18c9b560
AZ
2645 gen_op_iwmmxt_movq_wRn_M0(wrd);
2646 gen_op_iwmmxt_set_mup();
2647 gen_op_iwmmxt_set_cup();
2648 break;
d00584b7 2649 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
18c9b560
AZ
2650 case 0x418: case 0x518: case 0x618: case 0x718:
2651 case 0x818: case 0x918: case 0xa18: case 0xb18:
2652 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2653 wrd = (insn >> 12) & 0xf;
2654 rd0 = (insn >> 16) & 0xf;
2655 rd1 = (insn >> 0) & 0xf;
2656 gen_op_iwmmxt_movq_M0_wRn(rd0);
2657 switch ((insn >> 20) & 0xf) {
2658 case 0x0:
2659 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2660 break;
2661 case 0x1:
2662 gen_op_iwmmxt_addub_M0_wRn(rd1);
2663 break;
2664 case 0x3:
2665 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2666 break;
2667 case 0x4:
2668 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2669 break;
2670 case 0x5:
2671 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2672 break;
2673 case 0x7:
2674 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2675 break;
2676 case 0x8:
2677 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2678 break;
2679 case 0x9:
2680 gen_op_iwmmxt_addul_M0_wRn(rd1);
2681 break;
2682 case 0xb:
2683 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2684 break;
2685 default:
2686 return 1;
2687 }
2688 gen_op_iwmmxt_movq_wRn_M0(wrd);
2689 gen_op_iwmmxt_set_mup();
2690 gen_op_iwmmxt_set_cup();
2691 break;
d00584b7 2692 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
18c9b560
AZ
2693 case 0x408: case 0x508: case 0x608: case 0x708:
2694 case 0x808: case 0x908: case 0xa08: case 0xb08:
2695 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
da6b5335
FN
2696 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2697 return 1;
18c9b560
AZ
2698 wrd = (insn >> 12) & 0xf;
2699 rd0 = (insn >> 16) & 0xf;
2700 rd1 = (insn >> 0) & 0xf;
2701 gen_op_iwmmxt_movq_M0_wRn(rd0);
18c9b560 2702 switch ((insn >> 22) & 3) {
18c9b560
AZ
2703 case 1:
2704 if (insn & (1 << 21))
2705 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2706 else
2707 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2708 break;
2709 case 2:
2710 if (insn & (1 << 21))
2711 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2712 else
2713 gen_op_iwmmxt_packul_M0_wRn(rd1);
2714 break;
2715 case 3:
2716 if (insn & (1 << 21))
2717 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2718 else
2719 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2720 break;
2721 }
2722 gen_op_iwmmxt_movq_wRn_M0(wrd);
2723 gen_op_iwmmxt_set_mup();
2724 gen_op_iwmmxt_set_cup();
2725 break;
2726 case 0x201: case 0x203: case 0x205: case 0x207:
2727 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2728 case 0x211: case 0x213: case 0x215: case 0x217:
2729 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2730 wrd = (insn >> 5) & 0xf;
2731 rd0 = (insn >> 12) & 0xf;
2732 rd1 = (insn >> 0) & 0xf;
2733 if (rd0 == 0xf || rd1 == 0xf)
2734 return 1;
2735 gen_op_iwmmxt_movq_M0_wRn(wrd);
da6b5335
FN
2736 tmp = load_reg(s, rd0);
2737 tmp2 = load_reg(s, rd1);
18c9b560 2738 switch ((insn >> 16) & 0xf) {
d00584b7 2739 case 0x0: /* TMIA */
da6b5335 2740 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560 2741 break;
d00584b7 2742 case 0x8: /* TMIAPH */
da6b5335 2743 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560 2744 break;
d00584b7 2745 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
18c9b560 2746 if (insn & (1 << 16))
da6b5335 2747 tcg_gen_shri_i32(tmp, tmp, 16);
18c9b560 2748 if (insn & (1 << 17))
da6b5335
FN
2749 tcg_gen_shri_i32(tmp2, tmp2, 16);
2750 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2751 break;
2752 default:
7d1b0095
PM
2753 tcg_temp_free_i32(tmp2);
2754 tcg_temp_free_i32(tmp);
18c9b560
AZ
2755 return 1;
2756 }
7d1b0095
PM
2757 tcg_temp_free_i32(tmp2);
2758 tcg_temp_free_i32(tmp);
18c9b560
AZ
2759 gen_op_iwmmxt_movq_wRn_M0(wrd);
2760 gen_op_iwmmxt_set_mup();
2761 break;
2762 default:
2763 return 1;
2764 }
2765
2766 return 0;
2767}
2768
a1c7273b 2769/* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
18c9b560 2770 (ie. an undefined instruction). */
7dcc1f89 2771static int disas_dsp_insn(DisasContext *s, uint32_t insn)
18c9b560
AZ
2772{
2773 int acc, rd0, rd1, rdhi, rdlo;
39d5492a 2774 TCGv_i32 tmp, tmp2;
18c9b560
AZ
2775
2776 if ((insn & 0x0ff00f10) == 0x0e200010) {
2777 /* Multiply with Internal Accumulate Format */
2778 rd0 = (insn >> 12) & 0xf;
2779 rd1 = insn & 0xf;
2780 acc = (insn >> 5) & 7;
2781
2782 if (acc != 0)
2783 return 1;
2784
3a554c0f
FN
2785 tmp = load_reg(s, rd0);
2786 tmp2 = load_reg(s, rd1);
18c9b560 2787 switch ((insn >> 16) & 0xf) {
d00584b7 2788 case 0x0: /* MIA */
3a554c0f 2789 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560 2790 break;
d00584b7 2791 case 0x8: /* MIAPH */
3a554c0f 2792 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560 2793 break;
d00584b7
PM
2794 case 0xc: /* MIABB */
2795 case 0xd: /* MIABT */
2796 case 0xe: /* MIATB */
2797 case 0xf: /* MIATT */
18c9b560 2798 if (insn & (1 << 16))
3a554c0f 2799 tcg_gen_shri_i32(tmp, tmp, 16);
18c9b560 2800 if (insn & (1 << 17))
3a554c0f
FN
2801 tcg_gen_shri_i32(tmp2, tmp2, 16);
2802 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2803 break;
2804 default:
2805 return 1;
2806 }
7d1b0095
PM
2807 tcg_temp_free_i32(tmp2);
2808 tcg_temp_free_i32(tmp);
18c9b560
AZ
2809
2810 gen_op_iwmmxt_movq_wRn_M0(acc);
2811 return 0;
2812 }
2813
2814 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2815 /* Internal Accumulator Access Format */
2816 rdhi = (insn >> 16) & 0xf;
2817 rdlo = (insn >> 12) & 0xf;
2818 acc = insn & 7;
2819
2820 if (acc != 0)
2821 return 1;
2822
d00584b7 2823 if (insn & ARM_CP_RW_BIT) { /* MRA */
3a554c0f 2824 iwmmxt_load_reg(cpu_V0, acc);
ecc7b3aa 2825 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
3a554c0f 2826 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
ecc7b3aa 2827 tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
3a554c0f 2828 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
d00584b7 2829 } else { /* MAR */
3a554c0f
FN
2830 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2831 iwmmxt_store_reg(cpu_V0, acc);
18c9b560
AZ
2832 }
2833 return 0;
2834 }
2835
2836 return 1;
2837}
2838
9ee6e8bb
PB
2839#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2840#define VFP_SREG(insn, bigbit, smallbit) \
2841 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2842#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
d614a513 2843 if (arm_dc_feature(s, ARM_FEATURE_VFP3)) { \
9ee6e8bb
PB
2844 reg = (((insn) >> (bigbit)) & 0x0f) \
2845 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2846 } else { \
2847 if (insn & (1 << (smallbit))) \
2848 return 1; \
2849 reg = ((insn) >> (bigbit)) & 0x0f; \
2850 }} while (0)
2851
2852#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2853#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2854#define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2855#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2856#define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2857#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2858
39d5492a 2859static void gen_neon_dup_low16(TCGv_i32 var)
ad69471c 2860{
39d5492a 2861 TCGv_i32 tmp = tcg_temp_new_i32();
86831435 2862 tcg_gen_ext16u_i32(var, var);
ad69471c
PB
2863 tcg_gen_shli_i32(tmp, var, 16);
2864 tcg_gen_or_i32(var, var, tmp);
7d1b0095 2865 tcg_temp_free_i32(tmp);
ad69471c
PB
2866}
2867
39d5492a 2868static void gen_neon_dup_high16(TCGv_i32 var)
ad69471c 2869{
39d5492a 2870 TCGv_i32 tmp = tcg_temp_new_i32();
ad69471c
PB
2871 tcg_gen_andi_i32(var, var, 0xffff0000);
2872 tcg_gen_shri_i32(tmp, var, 16);
2873 tcg_gen_or_i32(var, var, tmp);
7d1b0095 2874 tcg_temp_free_i32(tmp);
ad69471c
PB
2875}
2876
06db8196
PM
2877/*
2878 * Disassemble a VFP instruction. Returns nonzero if an error occurred
2879 * (ie. an undefined instruction).
2880 */
7dcc1f89 2881static int disas_vfp_insn(DisasContext *s, uint32_t insn)
b7bcbe95 2882{
d614a513 2883 if (!arm_dc_feature(s, ARM_FEATURE_VFP)) {
40f137e1 2884 return 1;
d614a513 2885 }
40f137e1 2886
78e138bc
PM
2887 /*
2888 * If the decodetree decoder handles this insn it will always
2889 * emit code to either execute the insn or generate an appropriate
2890 * exception; so we don't need to ever return non-zero to tell
2891 * the calling code to emit an UNDEF exception.
2892 */
2893 if (extract32(insn, 28, 4) == 0xf) {
2894 if (disas_vfp_uncond(s, insn)) {
2895 return 0;
2896 }
2897 } else {
2898 if (disas_vfp(s, insn)) {
2899 return 0;
2900 }
2901 }
3111bfc2
PM
2902 /* If the decodetree decoder didn't handle this insn, it must be UNDEF */
2903 return 1;
b7bcbe95
FB
2904}
2905
90aa39a1 2906static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
c53be334 2907{
90aa39a1 2908#ifndef CONFIG_USER_ONLY
dcba3a8d 2909 return (s->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
90aa39a1
SF
2910 ((s->pc - 1) & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
2911#else
2912 return true;
2913#endif
2914}
6e256c93 2915
8a6b28c7
EC
2916static void gen_goto_ptr(void)
2917{
7f11636d 2918 tcg_gen_lookup_and_goto_ptr();
8a6b28c7
EC
2919}
2920
4cae8f56
AB
2921/* This will end the TB but doesn't guarantee we'll return to
2922 * cpu_loop_exec. Any live exit_requests will be processed as we
2923 * enter the next TB.
2924 */
8a6b28c7 2925static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
90aa39a1
SF
2926{
2927 if (use_goto_tb(s, dest)) {
57fec1fe 2928 tcg_gen_goto_tb(n);
eaed129d 2929 gen_set_pc_im(s, dest);
07ea28b4 2930 tcg_gen_exit_tb(s->base.tb, n);
6e256c93 2931 } else {
eaed129d 2932 gen_set_pc_im(s, dest);
8a6b28c7 2933 gen_goto_ptr();
6e256c93 2934 }
dcba3a8d 2935 s->base.is_jmp = DISAS_NORETURN;
c53be334
FB
2936}
2937
8aaca4c0
FB
2938static inline void gen_jmp (DisasContext *s, uint32_t dest)
2939{
b636649f 2940 if (unlikely(is_singlestepping(s))) {
8aaca4c0 2941 /* An indirect jump so that we still trigger the debug exception. */
5899f386 2942 if (s->thumb)
d9ba4830
PB
2943 dest |= 1;
2944 gen_bx_im(s, dest);
8aaca4c0 2945 } else {
6e256c93 2946 gen_goto_tb(s, 0, dest);
8aaca4c0
FB
2947 }
2948}
2949
39d5492a 2950static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
b5ff1b31 2951{
ee097184 2952 if (x)
d9ba4830 2953 tcg_gen_sari_i32(t0, t0, 16);
b5ff1b31 2954 else
d9ba4830 2955 gen_sxth(t0);
ee097184 2956 if (y)
d9ba4830 2957 tcg_gen_sari_i32(t1, t1, 16);
b5ff1b31 2958 else
d9ba4830
PB
2959 gen_sxth(t1);
2960 tcg_gen_mul_i32(t0, t0, t1);
b5ff1b31
FB
2961}
2962
2963/* Return the mask of PSR bits set by a MSR instruction. */
7dcc1f89
PM
2964static uint32_t msr_mask(DisasContext *s, int flags, int spsr)
2965{
b5ff1b31
FB
2966 uint32_t mask;
2967
2968 mask = 0;
2969 if (flags & (1 << 0))
2970 mask |= 0xff;
2971 if (flags & (1 << 1))
2972 mask |= 0xff00;
2973 if (flags & (1 << 2))
2974 mask |= 0xff0000;
2975 if (flags & (1 << 3))
2976 mask |= 0xff000000;
9ee6e8bb 2977
2ae23e75 2978 /* Mask out undefined bits. */
9ee6e8bb 2979 mask &= ~CPSR_RESERVED;
d614a513 2980 if (!arm_dc_feature(s, ARM_FEATURE_V4T)) {
be5e7a76 2981 mask &= ~CPSR_T;
d614a513
PM
2982 }
2983 if (!arm_dc_feature(s, ARM_FEATURE_V5)) {
be5e7a76 2984 mask &= ~CPSR_Q; /* V5TE in reality*/
d614a513
PM
2985 }
2986 if (!arm_dc_feature(s, ARM_FEATURE_V6)) {
e160c51c 2987 mask &= ~(CPSR_E | CPSR_GE);
d614a513
PM
2988 }
2989 if (!arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
e160c51c 2990 mask &= ~CPSR_IT;
d614a513 2991 }
4051e12c
PM
2992 /* Mask out execution state and reserved bits. */
2993 if (!spsr) {
2994 mask &= ~(CPSR_EXEC | CPSR_RESERVED);
2995 }
b5ff1b31
FB
2996 /* Mask out privileged bits. */
2997 if (IS_USER(s))
9ee6e8bb 2998 mask &= CPSR_USER;
b5ff1b31
FB
2999 return mask;
3000}
3001
2fbac54b 3002/* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
39d5492a 3003static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
b5ff1b31 3004{
39d5492a 3005 TCGv_i32 tmp;
b5ff1b31
FB
3006 if (spsr) {
3007 /* ??? This is also undefined in system mode. */
3008 if (IS_USER(s))
3009 return 1;
d9ba4830
PB
3010
3011 tmp = load_cpu_field(spsr);
3012 tcg_gen_andi_i32(tmp, tmp, ~mask);
2fbac54b
FN
3013 tcg_gen_andi_i32(t0, t0, mask);
3014 tcg_gen_or_i32(tmp, tmp, t0);
d9ba4830 3015 store_cpu_field(tmp, spsr);
b5ff1b31 3016 } else {
2fbac54b 3017 gen_set_cpsr(t0, mask);
b5ff1b31 3018 }
7d1b0095 3019 tcg_temp_free_i32(t0);
b5ff1b31
FB
3020 gen_lookup_tb(s);
3021 return 0;
3022}
3023
2fbac54b
FN
3024/* Returns nonzero if access to the PSR is not permitted. */
3025static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3026{
39d5492a 3027 TCGv_i32 tmp;
7d1b0095 3028 tmp = tcg_temp_new_i32();
2fbac54b
FN
3029 tcg_gen_movi_i32(tmp, val);
3030 return gen_set_psr(s, mask, spsr, tmp);
3031}
3032
8bfd0550
PM
3033static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
3034 int *tgtmode, int *regno)
3035{
3036 /* Decode the r and sysm fields of MSR/MRS banked accesses into
3037 * the target mode and register number, and identify the various
3038 * unpredictable cases.
3039 * MSR (banked) and MRS (banked) are CONSTRAINED UNPREDICTABLE if:
3040 * + executed in user mode
3041 * + using R15 as the src/dest register
3042 * + accessing an unimplemented register
3043 * + accessing a register that's inaccessible at current PL/security state*
3044 * + accessing a register that you could access with a different insn
3045 * We choose to UNDEF in all these cases.
3046 * Since we don't know which of the various AArch32 modes we are in
3047 * we have to defer some checks to runtime.
3048 * Accesses to Monitor mode registers from Secure EL1 (which implies
3049 * that EL3 is AArch64) must trap to EL3.
3050 *
3051 * If the access checks fail this function will emit code to take
3052 * an exception and return false. Otherwise it will return true,
3053 * and set *tgtmode and *regno appropriately.
3054 */
3055 int exc_target = default_exception_el(s);
3056
3057 /* These instructions are present only in ARMv8, or in ARMv7 with the
3058 * Virtualization Extensions.
3059 */
3060 if (!arm_dc_feature(s, ARM_FEATURE_V8) &&
3061 !arm_dc_feature(s, ARM_FEATURE_EL2)) {
3062 goto undef;
3063 }
3064
3065 if (IS_USER(s) || rn == 15) {
3066 goto undef;
3067 }
3068
3069 /* The table in the v8 ARM ARM section F5.2.3 describes the encoding
3070 * of registers into (r, sysm).
3071 */
3072 if (r) {
3073 /* SPSRs for other modes */
3074 switch (sysm) {
3075 case 0xe: /* SPSR_fiq */
3076 *tgtmode = ARM_CPU_MODE_FIQ;
3077 break;
3078 case 0x10: /* SPSR_irq */
3079 *tgtmode = ARM_CPU_MODE_IRQ;
3080 break;
3081 case 0x12: /* SPSR_svc */
3082 *tgtmode = ARM_CPU_MODE_SVC;
3083 break;
3084 case 0x14: /* SPSR_abt */
3085 *tgtmode = ARM_CPU_MODE_ABT;
3086 break;
3087 case 0x16: /* SPSR_und */
3088 *tgtmode = ARM_CPU_MODE_UND;
3089 break;
3090 case 0x1c: /* SPSR_mon */
3091 *tgtmode = ARM_CPU_MODE_MON;
3092 break;
3093 case 0x1e: /* SPSR_hyp */
3094 *tgtmode = ARM_CPU_MODE_HYP;
3095 break;
3096 default: /* unallocated */
3097 goto undef;
3098 }
3099 /* We arbitrarily assign SPSR a register number of 16. */
3100 *regno = 16;
3101 } else {
3102 /* general purpose registers for other modes */
3103 switch (sysm) {
3104 case 0x0 ... 0x6: /* 0b00xxx : r8_usr ... r14_usr */
3105 *tgtmode = ARM_CPU_MODE_USR;
3106 *regno = sysm + 8;
3107 break;
3108 case 0x8 ... 0xe: /* 0b01xxx : r8_fiq ... r14_fiq */
3109 *tgtmode = ARM_CPU_MODE_FIQ;
3110 *regno = sysm;
3111 break;
3112 case 0x10 ... 0x11: /* 0b1000x : r14_irq, r13_irq */
3113 *tgtmode = ARM_CPU_MODE_IRQ;
3114 *regno = sysm & 1 ? 13 : 14;
3115 break;
3116 case 0x12 ... 0x13: /* 0b1001x : r14_svc, r13_svc */
3117 *tgtmode = ARM_CPU_MODE_SVC;
3118 *regno = sysm & 1 ? 13 : 14;
3119 break;
3120 case 0x14 ... 0x15: /* 0b1010x : r14_abt, r13_abt */
3121 *tgtmode = ARM_CPU_MODE_ABT;
3122 *regno = sysm & 1 ? 13 : 14;
3123 break;
3124 case 0x16 ... 0x17: /* 0b1011x : r14_und, r13_und */
3125 *tgtmode = ARM_CPU_MODE_UND;
3126 *regno = sysm & 1 ? 13 : 14;
3127 break;
3128 case 0x1c ... 0x1d: /* 0b1110x : r14_mon, r13_mon */
3129 *tgtmode = ARM_CPU_MODE_MON;
3130 *regno = sysm & 1 ? 13 : 14;
3131 break;
3132 case 0x1e ... 0x1f: /* 0b1111x : elr_hyp, r13_hyp */
3133 *tgtmode = ARM_CPU_MODE_HYP;
3134 /* Arbitrarily pick 17 for ELR_Hyp (which is not a banked LR!) */
3135 *regno = sysm & 1 ? 13 : 17;
3136 break;
3137 default: /* unallocated */
3138 goto undef;
3139 }
3140 }
3141
3142 /* Catch the 'accessing inaccessible register' cases we can detect
3143 * at translate time.
3144 */
3145 switch (*tgtmode) {
3146 case ARM_CPU_MODE_MON:
3147 if (!arm_dc_feature(s, ARM_FEATURE_EL3) || s->ns) {
3148 goto undef;
3149 }
3150 if (s->current_el == 1) {
3151 /* If we're in Secure EL1 (which implies that EL3 is AArch64)
3152 * then accesses to Mon registers trap to EL3
3153 */
3154 exc_target = 3;
3155 goto undef;
3156 }
3157 break;
3158 case ARM_CPU_MODE_HYP:
aec4dd09
PM
3159 /*
3160 * SPSR_hyp and r13_hyp can only be accessed from Monitor mode
3161 * (and so we can forbid accesses from EL2 or below). elr_hyp
3162 * can be accessed also from Hyp mode, so forbid accesses from
3163 * EL0 or EL1.
8bfd0550 3164 */
aec4dd09
PM
3165 if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el < 2 ||
3166 (s->current_el < 3 && *regno != 17)) {
8bfd0550
PM
3167 goto undef;
3168 }
3169 break;
3170 default:
3171 break;
3172 }
3173
3174 return true;
3175
3176undef:
3177 /* If we get here then some access check did not pass */
3178 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), exc_target);
3179 return false;
3180}
3181
3182static void gen_msr_banked(DisasContext *s, int r, int sysm, int rn)
3183{
3184 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
3185 int tgtmode = 0, regno = 0;
3186
3187 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
3188 return;
3189 }
3190
3191 /* Sync state because msr_banked() can raise exceptions */
3192 gen_set_condexec(s);
3193 gen_set_pc_im(s, s->pc - 4);
3194 tcg_reg = load_reg(s, rn);
3195 tcg_tgtmode = tcg_const_i32(tgtmode);
3196 tcg_regno = tcg_const_i32(regno);
3197 gen_helper_msr_banked(cpu_env, tcg_reg, tcg_tgtmode, tcg_regno);
3198 tcg_temp_free_i32(tcg_tgtmode);
3199 tcg_temp_free_i32(tcg_regno);
3200 tcg_temp_free_i32(tcg_reg);
dcba3a8d 3201 s->base.is_jmp = DISAS_UPDATE;
8bfd0550
PM
3202}
3203
3204static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn)
3205{
3206 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
3207 int tgtmode = 0, regno = 0;
3208
3209 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
3210 return;
3211 }
3212
3213 /* Sync state because mrs_banked() can raise exceptions */
3214 gen_set_condexec(s);
3215 gen_set_pc_im(s, s->pc - 4);
3216 tcg_reg = tcg_temp_new_i32();
3217 tcg_tgtmode = tcg_const_i32(tgtmode);
3218 tcg_regno = tcg_const_i32(regno);
3219 gen_helper_mrs_banked(tcg_reg, cpu_env, tcg_tgtmode, tcg_regno);
3220 tcg_temp_free_i32(tcg_tgtmode);
3221 tcg_temp_free_i32(tcg_regno);
3222 store_reg(s, rn, tcg_reg);
dcba3a8d 3223 s->base.is_jmp = DISAS_UPDATE;
8bfd0550
PM
3224}
3225
fb0e8e79
PM
3226/* Store value to PC as for an exception return (ie don't
3227 * mask bits). The subsequent call to gen_helper_cpsr_write_eret()
3228 * will do the masking based on the new value of the Thumb bit.
3229 */
3230static void store_pc_exc_ret(DisasContext *s, TCGv_i32 pc)
b5ff1b31 3231{
fb0e8e79
PM
3232 tcg_gen_mov_i32(cpu_R[15], pc);
3233 tcg_temp_free_i32(pc);
b5ff1b31
FB
3234}
3235
b0109805 3236/* Generate a v6 exception return. Marks both values as dead. */
39d5492a 3237static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
2c0262af 3238{
fb0e8e79
PM
3239 store_pc_exc_ret(s, pc);
3240 /* The cpsr_write_eret helper will mask the low bits of PC
3241 * appropriately depending on the new Thumb bit, so it must
3242 * be called after storing the new PC.
3243 */
e69ad9df
AL
3244 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
3245 gen_io_start();
3246 }
235ea1f5 3247 gen_helper_cpsr_write_eret(cpu_env, cpsr);
e69ad9df
AL
3248 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
3249 gen_io_end();
3250 }
7d1b0095 3251 tcg_temp_free_i32(cpsr);
b29fd33d 3252 /* Must exit loop to check un-masked IRQs */
dcba3a8d 3253 s->base.is_jmp = DISAS_EXIT;
9ee6e8bb 3254}
3b46e624 3255
fb0e8e79
PM
3256/* Generate an old-style exception return. Marks pc as dead. */
3257static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
3258{
3259 gen_rfe(s, pc, load_cpu_field(spsr));
3260}
3261
c22edfeb
AB
3262/*
3263 * For WFI we will halt the vCPU until an IRQ. For WFE and YIELD we
3264 * only call the helper when running single threaded TCG code to ensure
3265 * the next round-robin scheduled vCPU gets a crack. In MTTCG mode we
3266 * just skip this instruction. Currently the SEV/SEVL instructions
3267 * which are *one* of many ways to wake the CPU from WFE are not
3268 * implemented so we can't sleep like WFI does.
3269 */
9ee6e8bb
PB
3270static void gen_nop_hint(DisasContext *s, int val)
3271{
3272 switch (val) {
2399d4e7
EC
3273 /* When running in MTTCG we don't generate jumps to the yield and
3274 * WFE helpers as it won't affect the scheduling of other vCPUs.
3275 * If we wanted to more completely model WFE/SEV so we don't busy
3276 * spin unnecessarily we would need to do something more involved.
3277 */
c87e5a61 3278 case 1: /* yield */
2399d4e7 3279 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
c22edfeb 3280 gen_set_pc_im(s, s->pc);
dcba3a8d 3281 s->base.is_jmp = DISAS_YIELD;
c22edfeb 3282 }
c87e5a61 3283 break;
9ee6e8bb 3284 case 3: /* wfi */
eaed129d 3285 gen_set_pc_im(s, s->pc);
dcba3a8d 3286 s->base.is_jmp = DISAS_WFI;
9ee6e8bb
PB
3287 break;
3288 case 2: /* wfe */
2399d4e7 3289 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
c22edfeb 3290 gen_set_pc_im(s, s->pc);
dcba3a8d 3291 s->base.is_jmp = DISAS_WFE;
c22edfeb 3292 }
72c1d3af 3293 break;
9ee6e8bb 3294 case 4: /* sev */
12b10571
MR
3295 case 5: /* sevl */
3296 /* TODO: Implement SEV, SEVL and WFE. May help SMP performance. */
9ee6e8bb
PB
3297 default: /* nop */
3298 break;
3299 }
3300}
99c475ab 3301
ad69471c 3302#define CPU_V001 cpu_V0, cpu_V0, cpu_V1
9ee6e8bb 3303
39d5492a 3304static inline void gen_neon_add(int size, TCGv_i32 t0, TCGv_i32 t1)
9ee6e8bb
PB
3305{
3306 switch (size) {
dd8fbd78
FN
3307 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
3308 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
3309 case 2: tcg_gen_add_i32(t0, t0, t1); break;
62698be3 3310 default: abort();
9ee6e8bb 3311 }
9ee6e8bb
PB
3312}
3313
39d5492a 3314static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
ad69471c
PB
3315{
3316 switch (size) {
dd8fbd78
FN
3317 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
3318 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
3319 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
ad69471c
PB
3320 default: return;
3321 }
3322}
3323
3324/* 32-bit pairwise ops end up the same as the elementwise versions. */
9ecd3c5c
RH
3325#define gen_helper_neon_pmax_s32 tcg_gen_smax_i32
3326#define gen_helper_neon_pmax_u32 tcg_gen_umax_i32
3327#define gen_helper_neon_pmin_s32 tcg_gen_smin_i32
3328#define gen_helper_neon_pmin_u32 tcg_gen_umin_i32
ad69471c 3329
ad69471c
PB
3330#define GEN_NEON_INTEGER_OP_ENV(name) do { \
3331 switch ((size << 1) | u) { \
3332 case 0: \
dd8fbd78 3333 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
3334 break; \
3335 case 1: \
dd8fbd78 3336 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
3337 break; \
3338 case 2: \
dd8fbd78 3339 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
3340 break; \
3341 case 3: \
dd8fbd78 3342 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
3343 break; \
3344 case 4: \
dd8fbd78 3345 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
3346 break; \
3347 case 5: \
dd8fbd78 3348 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
3349 break; \
3350 default: return 1; \
3351 }} while (0)
9ee6e8bb
PB
3352
3353#define GEN_NEON_INTEGER_OP(name) do { \
3354 switch ((size << 1) | u) { \
ad69471c 3355 case 0: \
dd8fbd78 3356 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
ad69471c
PB
3357 break; \
3358 case 1: \
dd8fbd78 3359 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
ad69471c
PB
3360 break; \
3361 case 2: \
dd8fbd78 3362 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
ad69471c
PB
3363 break; \
3364 case 3: \
dd8fbd78 3365 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
ad69471c
PB
3366 break; \
3367 case 4: \
dd8fbd78 3368 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
ad69471c
PB
3369 break; \
3370 case 5: \
dd8fbd78 3371 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
ad69471c 3372 break; \
9ee6e8bb
PB
3373 default: return 1; \
3374 }} while (0)
3375
39d5492a 3376static TCGv_i32 neon_load_scratch(int scratch)
9ee6e8bb 3377{
39d5492a 3378 TCGv_i32 tmp = tcg_temp_new_i32();
dd8fbd78
FN
3379 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3380 return tmp;
9ee6e8bb
PB
3381}
3382
39d5492a 3383static void neon_store_scratch(int scratch, TCGv_i32 var)
9ee6e8bb 3384{
dd8fbd78 3385 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
7d1b0095 3386 tcg_temp_free_i32(var);
9ee6e8bb
PB
3387}
3388
39d5492a 3389static inline TCGv_i32 neon_get_scalar(int size, int reg)
9ee6e8bb 3390{
39d5492a 3391 TCGv_i32 tmp;
9ee6e8bb 3392 if (size == 1) {
0fad6efc
PM
3393 tmp = neon_load_reg(reg & 7, reg >> 4);
3394 if (reg & 8) {
dd8fbd78 3395 gen_neon_dup_high16(tmp);
0fad6efc
PM
3396 } else {
3397 gen_neon_dup_low16(tmp);
dd8fbd78 3398 }
0fad6efc
PM
3399 } else {
3400 tmp = neon_load_reg(reg & 15, reg >> 4);
9ee6e8bb 3401 }
dd8fbd78 3402 return tmp;
9ee6e8bb
PB
3403}
3404
02acedf9 3405static int gen_neon_unzip(int rd, int rm, int size, int q)
19457615 3406{
b13708bb
RH
3407 TCGv_ptr pd, pm;
3408
600b828c 3409 if (!q && size == 2) {
02acedf9
PM
3410 return 1;
3411 }
b13708bb
RH
3412 pd = vfp_reg_ptr(true, rd);
3413 pm = vfp_reg_ptr(true, rm);
02acedf9
PM
3414 if (q) {
3415 switch (size) {
3416 case 0:
b13708bb 3417 gen_helper_neon_qunzip8(pd, pm);
02acedf9
PM
3418 break;
3419 case 1:
b13708bb 3420 gen_helper_neon_qunzip16(pd, pm);
02acedf9
PM
3421 break;
3422 case 2:
b13708bb 3423 gen_helper_neon_qunzip32(pd, pm);
02acedf9
PM
3424 break;
3425 default:
3426 abort();
3427 }
3428 } else {
3429 switch (size) {
3430 case 0:
b13708bb 3431 gen_helper_neon_unzip8(pd, pm);
02acedf9
PM
3432 break;
3433 case 1:
b13708bb 3434 gen_helper_neon_unzip16(pd, pm);
02acedf9
PM
3435 break;
3436 default:
3437 abort();
3438 }
3439 }
b13708bb
RH
3440 tcg_temp_free_ptr(pd);
3441 tcg_temp_free_ptr(pm);
02acedf9 3442 return 0;
19457615
FN
3443}
3444
d68a6f3a 3445static int gen_neon_zip(int rd, int rm, int size, int q)
19457615 3446{
b13708bb
RH
3447 TCGv_ptr pd, pm;
3448
600b828c 3449 if (!q && size == 2) {
d68a6f3a
PM
3450 return 1;
3451 }
b13708bb
RH
3452 pd = vfp_reg_ptr(true, rd);
3453 pm = vfp_reg_ptr(true, rm);
d68a6f3a
PM
3454 if (q) {
3455 switch (size) {
3456 case 0:
b13708bb 3457 gen_helper_neon_qzip8(pd, pm);
d68a6f3a
PM
3458 break;
3459 case 1:
b13708bb 3460 gen_helper_neon_qzip16(pd, pm);
d68a6f3a
PM
3461 break;
3462 case 2:
b13708bb 3463 gen_helper_neon_qzip32(pd, pm);
d68a6f3a
PM
3464 break;
3465 default:
3466 abort();
3467 }
3468 } else {
3469 switch (size) {
3470 case 0:
b13708bb 3471 gen_helper_neon_zip8(pd, pm);
d68a6f3a
PM
3472 break;
3473 case 1:
b13708bb 3474 gen_helper_neon_zip16(pd, pm);
d68a6f3a
PM
3475 break;
3476 default:
3477 abort();
3478 }
3479 }
b13708bb
RH
3480 tcg_temp_free_ptr(pd);
3481 tcg_temp_free_ptr(pm);
d68a6f3a 3482 return 0;
19457615
FN
3483}
3484
39d5492a 3485static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
19457615 3486{
39d5492a 3487 TCGv_i32 rd, tmp;
19457615 3488
7d1b0095
PM
3489 rd = tcg_temp_new_i32();
3490 tmp = tcg_temp_new_i32();
19457615
FN
3491
3492 tcg_gen_shli_i32(rd, t0, 8);
3493 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3494 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3495 tcg_gen_or_i32(rd, rd, tmp);
3496
3497 tcg_gen_shri_i32(t1, t1, 8);
3498 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3499 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3500 tcg_gen_or_i32(t1, t1, tmp);
3501 tcg_gen_mov_i32(t0, rd);
3502
7d1b0095
PM
3503 tcg_temp_free_i32(tmp);
3504 tcg_temp_free_i32(rd);
19457615
FN
3505}
3506
39d5492a 3507static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
19457615 3508{
39d5492a 3509 TCGv_i32 rd, tmp;
19457615 3510
7d1b0095
PM
3511 rd = tcg_temp_new_i32();
3512 tmp = tcg_temp_new_i32();
19457615
FN
3513
3514 tcg_gen_shli_i32(rd, t0, 16);
3515 tcg_gen_andi_i32(tmp, t1, 0xffff);
3516 tcg_gen_or_i32(rd, rd, tmp);
3517 tcg_gen_shri_i32(t1, t1, 16);
3518 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3519 tcg_gen_or_i32(t1, t1, tmp);
3520 tcg_gen_mov_i32(t0, rd);
3521
7d1b0095
PM
3522 tcg_temp_free_i32(tmp);
3523 tcg_temp_free_i32(rd);
19457615
FN
3524}
3525
3526
9ee6e8bb
PB
3527static struct {
3528 int nregs;
3529 int interleave;
3530 int spacing;
308e5636 3531} const neon_ls_element_type[11] = {
ac55d007
RH
3532 {1, 4, 1},
3533 {1, 4, 2},
9ee6e8bb 3534 {4, 1, 1},
ac55d007
RH
3535 {2, 2, 2},
3536 {1, 3, 1},
3537 {1, 3, 2},
9ee6e8bb
PB
3538 {3, 1, 1},
3539 {1, 1, 1},
ac55d007
RH
3540 {1, 2, 1},
3541 {1, 2, 2},
9ee6e8bb
PB
3542 {2, 1, 1}
3543};
3544
3545/* Translate a NEON load/store element instruction. Return nonzero if the
3546 instruction is invalid. */
7dcc1f89 3547static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
9ee6e8bb
PB
3548{
3549 int rd, rn, rm;
3550 int op;
3551 int nregs;
3552 int interleave;
84496233 3553 int spacing;
9ee6e8bb
PB
3554 int stride;
3555 int size;
3556 int reg;
9ee6e8bb 3557 int load;
9ee6e8bb 3558 int n;
7377c2c9 3559 int vec_size;
ac55d007
RH
3560 int mmu_idx;
3561 TCGMemOp endian;
39d5492a
PM
3562 TCGv_i32 addr;
3563 TCGv_i32 tmp;
3564 TCGv_i32 tmp2;
84496233 3565 TCGv_i64 tmp64;
9ee6e8bb 3566
2c7ffc41
PM
3567 /* FIXME: this access check should not take precedence over UNDEF
3568 * for invalid encodings; we will generate incorrect syndrome information
3569 * for attempts to execute invalid vfp/neon encodings with FP disabled.
3570 */
9dbbc748 3571 if (s->fp_excp_el) {
2c7ffc41 3572 gen_exception_insn(s, 4, EXCP_UDEF,
4be42f40 3573 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
2c7ffc41
PM
3574 return 0;
3575 }
3576
5df8bac1 3577 if (!s->vfp_enabled)
9ee6e8bb
PB
3578 return 1;
3579 VFP_DREG_D(rd, insn);
3580 rn = (insn >> 16) & 0xf;
3581 rm = insn & 0xf;
3582 load = (insn & (1 << 21)) != 0;
ac55d007
RH
3583 endian = s->be_data;
3584 mmu_idx = get_mem_index(s);
9ee6e8bb
PB
3585 if ((insn & (1 << 23)) == 0) {
3586 /* Load store all elements. */
3587 op = (insn >> 8) & 0xf;
3588 size = (insn >> 6) & 3;
84496233 3589 if (op > 10)
9ee6e8bb 3590 return 1;
f2dd89d0
PM
3591 /* Catch UNDEF cases for bad values of align field */
3592 switch (op & 0xc) {
3593 case 4:
3594 if (((insn >> 5) & 1) == 1) {
3595 return 1;
3596 }
3597 break;
3598 case 8:
3599 if (((insn >> 4) & 3) == 3) {
3600 return 1;
3601 }
3602 break;
3603 default:
3604 break;
3605 }
9ee6e8bb
PB
3606 nregs = neon_ls_element_type[op].nregs;
3607 interleave = neon_ls_element_type[op].interleave;
84496233 3608 spacing = neon_ls_element_type[op].spacing;
ac55d007 3609 if (size == 3 && (interleave | spacing) != 1) {
84496233 3610 return 1;
ac55d007 3611 }
e23f12b3
RH
3612 /* For our purposes, bytes are always little-endian. */
3613 if (size == 0) {
3614 endian = MO_LE;
3615 }
3616 /* Consecutive little-endian elements from a single register
3617 * can be promoted to a larger little-endian operation.
3618 */
3619 if (interleave == 1 && endian == MO_LE) {
3620 size = 3;
3621 }
ac55d007 3622 tmp64 = tcg_temp_new_i64();
e318a60b 3623 addr = tcg_temp_new_i32();
ac55d007 3624 tmp2 = tcg_const_i32(1 << size);
dcc65026 3625 load_reg_var(s, addr, rn);
9ee6e8bb 3626 for (reg = 0; reg < nregs; reg++) {
ac55d007
RH
3627 for (n = 0; n < 8 >> size; n++) {
3628 int xs;
3629 for (xs = 0; xs < interleave; xs++) {
3630 int tt = rd + reg + spacing * xs;
3631
3632 if (load) {
3633 gen_aa32_ld_i64(s, tmp64, addr, mmu_idx, endian | size);
3634 neon_store_element64(tt, n, size, tmp64);
3635 } else {
3636 neon_load_element64(tmp64, tt, n, size);
3637 gen_aa32_st_i64(s, tmp64, addr, mmu_idx, endian | size);
9ee6e8bb 3638 }
ac55d007 3639 tcg_gen_add_i32(addr, addr, tmp2);
9ee6e8bb
PB
3640 }
3641 }
9ee6e8bb 3642 }
e318a60b 3643 tcg_temp_free_i32(addr);
ac55d007
RH
3644 tcg_temp_free_i32(tmp2);
3645 tcg_temp_free_i64(tmp64);
3646 stride = nregs * interleave * 8;
9ee6e8bb
PB
3647 } else {
3648 size = (insn >> 10) & 3;
3649 if (size == 3) {
3650 /* Load single element to all lanes. */
8e18cde3
PM
3651 int a = (insn >> 4) & 1;
3652 if (!load) {
9ee6e8bb 3653 return 1;
8e18cde3 3654 }
9ee6e8bb
PB
3655 size = (insn >> 6) & 3;
3656 nregs = ((insn >> 8) & 3) + 1;
8e18cde3
PM
3657
3658 if (size == 3) {
3659 if (nregs != 4 || a == 0) {
9ee6e8bb 3660 return 1;
99c475ab 3661 }
8e18cde3
PM
3662 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
3663 size = 2;
3664 }
3665 if (nregs == 1 && a == 1 && size == 0) {
3666 return 1;
3667 }
3668 if (nregs == 3 && a == 1) {
3669 return 1;
3670 }
e318a60b 3671 addr = tcg_temp_new_i32();
8e18cde3 3672 load_reg_var(s, addr, rn);
7377c2c9
RH
3673
3674 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write.
3675 * VLD2/3/4 to all lanes: bit 5 indicates register stride.
3676 */
3677 stride = (insn & (1 << 5)) ? 2 : 1;
3678 vec_size = nregs == 1 ? stride * 8 : 8;
3679
3680 tmp = tcg_temp_new_i32();
3681 for (reg = 0; reg < nregs; reg++) {
3682 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
3683 s->be_data | size);
3684 if ((rd & 1) && vec_size == 16) {
3685 /* We cannot write 16 bytes at once because the
3686 * destination is unaligned.
3687 */
3688 tcg_gen_gvec_dup_i32(size, neon_reg_offset(rd, 0),
3689 8, 8, tmp);
3690 tcg_gen_gvec_mov(0, neon_reg_offset(rd + 1, 0),
3691 neon_reg_offset(rd, 0), 8, 8);
3692 } else {
3693 tcg_gen_gvec_dup_i32(size, neon_reg_offset(rd, 0),
3694 vec_size, vec_size, tmp);
8e18cde3 3695 }
7377c2c9
RH
3696 tcg_gen_addi_i32(addr, addr, 1 << size);
3697 rd += stride;
9ee6e8bb 3698 }
7377c2c9 3699 tcg_temp_free_i32(tmp);
e318a60b 3700 tcg_temp_free_i32(addr);
9ee6e8bb
PB
3701 stride = (1 << size) * nregs;
3702 } else {
3703 /* Single element. */
93262b16 3704 int idx = (insn >> 4) & 0xf;
2d6ac920 3705 int reg_idx;
9ee6e8bb
PB
3706 switch (size) {
3707 case 0:
2d6ac920 3708 reg_idx = (insn >> 5) & 7;
9ee6e8bb
PB
3709 stride = 1;
3710 break;
3711 case 1:
2d6ac920 3712 reg_idx = (insn >> 6) & 3;
9ee6e8bb
PB
3713 stride = (insn & (1 << 5)) ? 2 : 1;
3714 break;
3715 case 2:
2d6ac920 3716 reg_idx = (insn >> 7) & 1;
9ee6e8bb
PB
3717 stride = (insn & (1 << 6)) ? 2 : 1;
3718 break;
3719 default:
3720 abort();
3721 }
3722 nregs = ((insn >> 8) & 3) + 1;
93262b16
PM
3723 /* Catch the UNDEF cases. This is unavoidably a bit messy. */
3724 switch (nregs) {
3725 case 1:
3726 if (((idx & (1 << size)) != 0) ||
3727 (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
3728 return 1;
3729 }
3730 break;
3731 case 3:
3732 if ((idx & 1) != 0) {
3733 return 1;
3734 }
3735 /* fall through */
3736 case 2:
3737 if (size == 2 && (idx & 2) != 0) {
3738 return 1;
3739 }
3740 break;
3741 case 4:
3742 if ((size == 2) && ((idx & 3) == 3)) {
3743 return 1;
3744 }
3745 break;
3746 default:
3747 abort();
3748 }
3749 if ((rd + stride * (nregs - 1)) > 31) {
3750 /* Attempts to write off the end of the register file
3751 * are UNPREDICTABLE; we choose to UNDEF because otherwise
3752 * the neon_load_reg() would write off the end of the array.
3753 */
3754 return 1;
3755 }
2d6ac920 3756 tmp = tcg_temp_new_i32();
e318a60b 3757 addr = tcg_temp_new_i32();
dcc65026 3758 load_reg_var(s, addr, rn);
9ee6e8bb
PB
3759 for (reg = 0; reg < nregs; reg++) {
3760 if (load) {
2d6ac920
RH
3761 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
3762 s->be_data | size);
3763 neon_store_element(rd, reg_idx, size, tmp);
9ee6e8bb 3764 } else { /* Store */
2d6ac920
RH
3765 neon_load_element(tmp, rd, reg_idx, size);
3766 gen_aa32_st_i32(s, tmp, addr, get_mem_index(s),
3767 s->be_data | size);
99c475ab 3768 }
9ee6e8bb 3769 rd += stride;
1b2b1e54 3770 tcg_gen_addi_i32(addr, addr, 1 << size);
99c475ab 3771 }
e318a60b 3772 tcg_temp_free_i32(addr);
2d6ac920 3773 tcg_temp_free_i32(tmp);
9ee6e8bb 3774 stride = nregs * (1 << size);
99c475ab 3775 }
9ee6e8bb
PB
3776 }
3777 if (rm != 15) {
39d5492a 3778 TCGv_i32 base;
b26eefb6
PB
3779
3780 base = load_reg(s, rn);
9ee6e8bb 3781 if (rm == 13) {
b26eefb6 3782 tcg_gen_addi_i32(base, base, stride);
9ee6e8bb 3783 } else {
39d5492a 3784 TCGv_i32 index;
b26eefb6
PB
3785 index = load_reg(s, rm);
3786 tcg_gen_add_i32(base, base, index);
7d1b0095 3787 tcg_temp_free_i32(index);
9ee6e8bb 3788 }
b26eefb6 3789 store_reg(s, rn, base);
9ee6e8bb
PB
3790 }
3791 return 0;
3792}
3b46e624 3793
39d5492a 3794static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src)
ad69471c
PB
3795{
3796 switch (size) {
3797 case 0: gen_helper_neon_narrow_u8(dest, src); break;
3798 case 1: gen_helper_neon_narrow_u16(dest, src); break;
ecc7b3aa 3799 case 2: tcg_gen_extrl_i64_i32(dest, src); break;
ad69471c
PB
3800 default: abort();
3801 }
3802}
3803
39d5492a 3804static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
ad69471c
PB
3805{
3806 switch (size) {
02da0b2d
PM
3807 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
3808 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
3809 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
ad69471c
PB
3810 default: abort();
3811 }
3812}
3813
39d5492a 3814static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src)
ad69471c
PB
3815{
3816 switch (size) {
02da0b2d
PM
3817 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
3818 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
3819 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
ad69471c
PB
3820 default: abort();
3821 }
3822}
3823
39d5492a 3824static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
af1bbf30
JR
3825{
3826 switch (size) {
02da0b2d
PM
3827 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
3828 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
3829 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
af1bbf30
JR
3830 default: abort();
3831 }
3832}
3833
39d5492a 3834static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift,
ad69471c
PB
3835 int q, int u)
3836{
3837 if (q) {
3838 if (u) {
3839 switch (size) {
3840 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3841 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3842 default: abort();
3843 }
3844 } else {
3845 switch (size) {
3846 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
3847 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
3848 default: abort();
3849 }
3850 }
3851 } else {
3852 if (u) {
3853 switch (size) {
b408a9b0
CL
3854 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
3855 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
ad69471c
PB
3856 default: abort();
3857 }
3858 } else {
3859 switch (size) {
3860 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
3861 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
3862 default: abort();
3863 }
3864 }
3865 }
3866}
3867
39d5492a 3868static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
ad69471c
PB
3869{
3870 if (u) {
3871 switch (size) {
3872 case 0: gen_helper_neon_widen_u8(dest, src); break;
3873 case 1: gen_helper_neon_widen_u16(dest, src); break;
3874 case 2: tcg_gen_extu_i32_i64(dest, src); break;
3875 default: abort();
3876 }
3877 } else {
3878 switch (size) {
3879 case 0: gen_helper_neon_widen_s8(dest, src); break;
3880 case 1: gen_helper_neon_widen_s16(dest, src); break;
3881 case 2: tcg_gen_ext_i32_i64(dest, src); break;
3882 default: abort();
3883 }
3884 }
7d1b0095 3885 tcg_temp_free_i32(src);
ad69471c
PB
3886}
3887
3888static inline void gen_neon_addl(int size)
3889{
3890 switch (size) {
3891 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
3892 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
3893 case 2: tcg_gen_add_i64(CPU_V001); break;
3894 default: abort();
3895 }
3896}
3897
3898static inline void gen_neon_subl(int size)
3899{
3900 switch (size) {
3901 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
3902 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
3903 case 2: tcg_gen_sub_i64(CPU_V001); break;
3904 default: abort();
3905 }
3906}
3907
a7812ae4 3908static inline void gen_neon_negl(TCGv_i64 var, int size)
ad69471c
PB
3909{
3910 switch (size) {
3911 case 0: gen_helper_neon_negl_u16(var, var); break;
3912 case 1: gen_helper_neon_negl_u32(var, var); break;
ee6fa559
PM
3913 case 2:
3914 tcg_gen_neg_i64(var, var);
3915 break;
ad69471c
PB
3916 default: abort();
3917 }
3918}
3919
a7812ae4 3920static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
ad69471c
PB
3921{
3922 switch (size) {
02da0b2d
PM
3923 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
3924 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
ad69471c
PB
3925 default: abort();
3926 }
3927}
3928
39d5492a
PM
3929static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b,
3930 int size, int u)
ad69471c 3931{
a7812ae4 3932 TCGv_i64 tmp;
ad69471c
PB
3933
3934 switch ((size << 1) | u) {
3935 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
3936 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
3937 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
3938 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
3939 case 4:
3940 tmp = gen_muls_i64_i32(a, b);
3941 tcg_gen_mov_i64(dest, tmp);
7d2aabe2 3942 tcg_temp_free_i64(tmp);
ad69471c
PB
3943 break;
3944 case 5:
3945 tmp = gen_mulu_i64_i32(a, b);
3946 tcg_gen_mov_i64(dest, tmp);
7d2aabe2 3947 tcg_temp_free_i64(tmp);
ad69471c
PB
3948 break;
3949 default: abort();
3950 }
c6067f04
CL
3951
3952 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
3953 Don't forget to clean them now. */
3954 if (size < 2) {
7d1b0095
PM
3955 tcg_temp_free_i32(a);
3956 tcg_temp_free_i32(b);
c6067f04 3957 }
ad69471c
PB
3958}
3959
39d5492a
PM
3960static void gen_neon_narrow_op(int op, int u, int size,
3961 TCGv_i32 dest, TCGv_i64 src)
c33171c7
PM
3962{
3963 if (op) {
3964 if (u) {
3965 gen_neon_unarrow_sats(size, dest, src);
3966 } else {
3967 gen_neon_narrow(size, dest, src);
3968 }
3969 } else {
3970 if (u) {
3971 gen_neon_narrow_satu(size, dest, src);
3972 } else {
3973 gen_neon_narrow_sats(size, dest, src);
3974 }
3975 }
3976}
3977
62698be3
PM
3978/* Symbolic constants for op fields for Neon 3-register same-length.
3979 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
3980 * table A7-9.
3981 */
3982#define NEON_3R_VHADD 0
3983#define NEON_3R_VQADD 1
3984#define NEON_3R_VRHADD 2
3985#define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
3986#define NEON_3R_VHSUB 4
3987#define NEON_3R_VQSUB 5
3988#define NEON_3R_VCGT 6
3989#define NEON_3R_VCGE 7
3990#define NEON_3R_VSHL 8
3991#define NEON_3R_VQSHL 9
3992#define NEON_3R_VRSHL 10
3993#define NEON_3R_VQRSHL 11
3994#define NEON_3R_VMAX 12
3995#define NEON_3R_VMIN 13
3996#define NEON_3R_VABD 14
3997#define NEON_3R_VABA 15
3998#define NEON_3R_VADD_VSUB 16
3999#define NEON_3R_VTST_VCEQ 17
4a7832b0 4000#define NEON_3R_VML 18 /* VMLA, VMLS */
62698be3
PM
4001#define NEON_3R_VMUL 19
4002#define NEON_3R_VPMAX 20
4003#define NEON_3R_VPMIN 21
4004#define NEON_3R_VQDMULH_VQRDMULH 22
36a71934 4005#define NEON_3R_VPADD_VQRDMLAH 23
f1ecb913 4006#define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */
36a71934 4007#define NEON_3R_VFM_VQRDMLSH 25 /* VFMA, VFMS, VQRDMLSH */
62698be3
PM
4008#define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
4009#define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
4010#define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
4011#define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
4012#define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
505935fc 4013#define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */
62698be3
PM
4014
4015static const uint8_t neon_3r_sizes[] = {
4016 [NEON_3R_VHADD] = 0x7,
4017 [NEON_3R_VQADD] = 0xf,
4018 [NEON_3R_VRHADD] = 0x7,
4019 [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
4020 [NEON_3R_VHSUB] = 0x7,
4021 [NEON_3R_VQSUB] = 0xf,
4022 [NEON_3R_VCGT] = 0x7,
4023 [NEON_3R_VCGE] = 0x7,
4024 [NEON_3R_VSHL] = 0xf,
4025 [NEON_3R_VQSHL] = 0xf,
4026 [NEON_3R_VRSHL] = 0xf,
4027 [NEON_3R_VQRSHL] = 0xf,
4028 [NEON_3R_VMAX] = 0x7,
4029 [NEON_3R_VMIN] = 0x7,
4030 [NEON_3R_VABD] = 0x7,
4031 [NEON_3R_VABA] = 0x7,
4032 [NEON_3R_VADD_VSUB] = 0xf,
4033 [NEON_3R_VTST_VCEQ] = 0x7,
4034 [NEON_3R_VML] = 0x7,
4035 [NEON_3R_VMUL] = 0x7,
4036 [NEON_3R_VPMAX] = 0x7,
4037 [NEON_3R_VPMIN] = 0x7,
4038 [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
36a71934 4039 [NEON_3R_VPADD_VQRDMLAH] = 0x7,
f1ecb913 4040 [NEON_3R_SHA] = 0xf, /* size field encodes op type */
36a71934 4041 [NEON_3R_VFM_VQRDMLSH] = 0x7, /* For VFM, size bit 1 encodes op */
62698be3
PM
4042 [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
4043 [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
4044 [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
4045 [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
4046 [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
505935fc 4047 [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */
62698be3
PM
4048};
4049
600b828c
PM
4050/* Symbolic constants for op fields for Neon 2-register miscellaneous.
4051 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
4052 * table A7-13.
4053 */
4054#define NEON_2RM_VREV64 0
4055#define NEON_2RM_VREV32 1
4056#define NEON_2RM_VREV16 2
4057#define NEON_2RM_VPADDL 4
4058#define NEON_2RM_VPADDL_U 5
9d935509
AB
4059#define NEON_2RM_AESE 6 /* Includes AESD */
4060#define NEON_2RM_AESMC 7 /* Includes AESIMC */
600b828c
PM
4061#define NEON_2RM_VCLS 8
4062#define NEON_2RM_VCLZ 9
4063#define NEON_2RM_VCNT 10
4064#define NEON_2RM_VMVN 11
4065#define NEON_2RM_VPADAL 12
4066#define NEON_2RM_VPADAL_U 13
4067#define NEON_2RM_VQABS 14
4068#define NEON_2RM_VQNEG 15
4069#define NEON_2RM_VCGT0 16
4070#define NEON_2RM_VCGE0 17
4071#define NEON_2RM_VCEQ0 18
4072#define NEON_2RM_VCLE0 19
4073#define NEON_2RM_VCLT0 20
f1ecb913 4074#define NEON_2RM_SHA1H 21
600b828c
PM
4075#define NEON_2RM_VABS 22
4076#define NEON_2RM_VNEG 23
4077#define NEON_2RM_VCGT0_F 24
4078#define NEON_2RM_VCGE0_F 25
4079#define NEON_2RM_VCEQ0_F 26
4080#define NEON_2RM_VCLE0_F 27
4081#define NEON_2RM_VCLT0_F 28
4082#define NEON_2RM_VABS_F 30
4083#define NEON_2RM_VNEG_F 31
4084#define NEON_2RM_VSWP 32
4085#define NEON_2RM_VTRN 33
4086#define NEON_2RM_VUZP 34
4087#define NEON_2RM_VZIP 35
4088#define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
4089#define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
4090#define NEON_2RM_VSHLL 38
f1ecb913 4091#define NEON_2RM_SHA1SU1 39 /* Includes SHA256SU0 */
34f7b0a2 4092#define NEON_2RM_VRINTN 40
2ce70625 4093#define NEON_2RM_VRINTX 41
34f7b0a2
WN
4094#define NEON_2RM_VRINTA 42
4095#define NEON_2RM_VRINTZ 43
600b828c 4096#define NEON_2RM_VCVT_F16_F32 44
34f7b0a2 4097#define NEON_2RM_VRINTM 45
600b828c 4098#define NEON_2RM_VCVT_F32_F16 46
34f7b0a2 4099#define NEON_2RM_VRINTP 47
901ad525
WN
4100#define NEON_2RM_VCVTAU 48
4101#define NEON_2RM_VCVTAS 49
4102#define NEON_2RM_VCVTNU 50
4103#define NEON_2RM_VCVTNS 51
4104#define NEON_2RM_VCVTPU 52
4105#define NEON_2RM_VCVTPS 53
4106#define NEON_2RM_VCVTMU 54
4107#define NEON_2RM_VCVTMS 55
600b828c
PM
4108#define NEON_2RM_VRECPE 56
4109#define NEON_2RM_VRSQRTE 57
4110#define NEON_2RM_VRECPE_F 58
4111#define NEON_2RM_VRSQRTE_F 59
4112#define NEON_2RM_VCVT_FS 60
4113#define NEON_2RM_VCVT_FU 61
4114#define NEON_2RM_VCVT_SF 62
4115#define NEON_2RM_VCVT_UF 63
4116
fe8fcf3d
PM
4117static bool neon_2rm_is_v8_op(int op)
4118{
4119 /* Return true if this neon 2reg-misc op is ARMv8 and up */
4120 switch (op) {
4121 case NEON_2RM_VRINTN:
4122 case NEON_2RM_VRINTA:
4123 case NEON_2RM_VRINTM:
4124 case NEON_2RM_VRINTP:
4125 case NEON_2RM_VRINTZ:
4126 case NEON_2RM_VRINTX:
4127 case NEON_2RM_VCVTAU:
4128 case NEON_2RM_VCVTAS:
4129 case NEON_2RM_VCVTNU:
4130 case NEON_2RM_VCVTNS:
4131 case NEON_2RM_VCVTPU:
4132 case NEON_2RM_VCVTPS:
4133 case NEON_2RM_VCVTMU:
4134 case NEON_2RM_VCVTMS:
4135 return true;
4136 default:
4137 return false;
4138 }
4139}
4140
600b828c
PM
4141/* Each entry in this array has bit n set if the insn allows
4142 * size value n (otherwise it will UNDEF). Since unallocated
4143 * op values will have no bits set they always UNDEF.
4144 */
4145static const uint8_t neon_2rm_sizes[] = {
4146 [NEON_2RM_VREV64] = 0x7,
4147 [NEON_2RM_VREV32] = 0x3,
4148 [NEON_2RM_VREV16] = 0x1,
4149 [NEON_2RM_VPADDL] = 0x7,
4150 [NEON_2RM_VPADDL_U] = 0x7,
9d935509
AB
4151 [NEON_2RM_AESE] = 0x1,
4152 [NEON_2RM_AESMC] = 0x1,
600b828c
PM
4153 [NEON_2RM_VCLS] = 0x7,
4154 [NEON_2RM_VCLZ] = 0x7,
4155 [NEON_2RM_VCNT] = 0x1,
4156 [NEON_2RM_VMVN] = 0x1,
4157 [NEON_2RM_VPADAL] = 0x7,
4158 [NEON_2RM_VPADAL_U] = 0x7,
4159 [NEON_2RM_VQABS] = 0x7,
4160 [NEON_2RM_VQNEG] = 0x7,
4161 [NEON_2RM_VCGT0] = 0x7,
4162 [NEON_2RM_VCGE0] = 0x7,
4163 [NEON_2RM_VCEQ0] = 0x7,
4164 [NEON_2RM_VCLE0] = 0x7,
4165 [NEON_2RM_VCLT0] = 0x7,
f1ecb913 4166 [NEON_2RM_SHA1H] = 0x4,
600b828c
PM
4167 [NEON_2RM_VABS] = 0x7,
4168 [NEON_2RM_VNEG] = 0x7,
4169 [NEON_2RM_VCGT0_F] = 0x4,
4170 [NEON_2RM_VCGE0_F] = 0x4,
4171 [NEON_2RM_VCEQ0_F] = 0x4,
4172 [NEON_2RM_VCLE0_F] = 0x4,
4173 [NEON_2RM_VCLT0_F] = 0x4,
4174 [NEON_2RM_VABS_F] = 0x4,
4175 [NEON_2RM_VNEG_F] = 0x4,
4176 [NEON_2RM_VSWP] = 0x1,
4177 [NEON_2RM_VTRN] = 0x7,
4178 [NEON_2RM_VUZP] = 0x7,
4179 [NEON_2RM_VZIP] = 0x7,
4180 [NEON_2RM_VMOVN] = 0x7,
4181 [NEON_2RM_VQMOVN] = 0x7,
4182 [NEON_2RM_VSHLL] = 0x7,
f1ecb913 4183 [NEON_2RM_SHA1SU1] = 0x4,
34f7b0a2 4184 [NEON_2RM_VRINTN] = 0x4,
2ce70625 4185 [NEON_2RM_VRINTX] = 0x4,
34f7b0a2
WN
4186 [NEON_2RM_VRINTA] = 0x4,
4187 [NEON_2RM_VRINTZ] = 0x4,
600b828c 4188 [NEON_2RM_VCVT_F16_F32] = 0x2,
34f7b0a2 4189 [NEON_2RM_VRINTM] = 0x4,
600b828c 4190 [NEON_2RM_VCVT_F32_F16] = 0x2,
34f7b0a2 4191 [NEON_2RM_VRINTP] = 0x4,
901ad525
WN
4192 [NEON_2RM_VCVTAU] = 0x4,
4193 [NEON_2RM_VCVTAS] = 0x4,
4194 [NEON_2RM_VCVTNU] = 0x4,
4195 [NEON_2RM_VCVTNS] = 0x4,
4196 [NEON_2RM_VCVTPU] = 0x4,
4197 [NEON_2RM_VCVTPS] = 0x4,
4198 [NEON_2RM_VCVTMU] = 0x4,
4199 [NEON_2RM_VCVTMS] = 0x4,
600b828c
PM
4200 [NEON_2RM_VRECPE] = 0x4,
4201 [NEON_2RM_VRSQRTE] = 0x4,
4202 [NEON_2RM_VRECPE_F] = 0x4,
4203 [NEON_2RM_VRSQRTE_F] = 0x4,
4204 [NEON_2RM_VCVT_FS] = 0x4,
4205 [NEON_2RM_VCVT_FU] = 0x4,
4206 [NEON_2RM_VCVT_SF] = 0x4,
4207 [NEON_2RM_VCVT_UF] = 0x4,
4208};
4209
36a71934
RH
4210
4211/* Expand v8.1 simd helper. */
4212static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
4213 int q, int rd, int rn, int rm)
4214{
962fcbf2 4215 if (dc_isar_feature(aa32_rdm, s)) {
36a71934
RH
4216 int opr_sz = (1 + q) * 8;
4217 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
4218 vfp_reg_offset(1, rn),
4219 vfp_reg_offset(1, rm), cpu_env,
4220 opr_sz, opr_sz, 0, fn);
4221 return 0;
4222 }
4223 return 1;
4224}
4225
41f6c113
RH
4226static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4227{
4228 tcg_gen_vec_sar8i_i64(a, a, shift);
4229 tcg_gen_vec_add8_i64(d, d, a);
4230}
4231
4232static void gen_ssra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4233{
4234 tcg_gen_vec_sar16i_i64(a, a, shift);
4235 tcg_gen_vec_add16_i64(d, d, a);
4236}
4237
4238static void gen_ssra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
4239{
4240 tcg_gen_sari_i32(a, a, shift);
4241 tcg_gen_add_i32(d, d, a);
4242}
4243
4244static void gen_ssra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4245{
4246 tcg_gen_sari_i64(a, a, shift);
4247 tcg_gen_add_i64(d, d, a);
4248}
4249
4250static void gen_ssra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
4251{
4252 tcg_gen_sari_vec(vece, a, a, sh);
4253 tcg_gen_add_vec(vece, d, d, a);
4254}
4255
53229a77
RH
4256static const TCGOpcode vecop_list_ssra[] = {
4257 INDEX_op_sari_vec, INDEX_op_add_vec, 0
4258};
4259
41f6c113
RH
4260const GVecGen2i ssra_op[4] = {
4261 { .fni8 = gen_ssra8_i64,
4262 .fniv = gen_ssra_vec,
4263 .load_dest = true,
53229a77 4264 .opt_opc = vecop_list_ssra,
41f6c113
RH
4265 .vece = MO_8 },
4266 { .fni8 = gen_ssra16_i64,
4267 .fniv = gen_ssra_vec,
4268 .load_dest = true,
53229a77 4269 .opt_opc = vecop_list_ssra,
41f6c113
RH
4270 .vece = MO_16 },
4271 { .fni4 = gen_ssra32_i32,
4272 .fniv = gen_ssra_vec,
4273 .load_dest = true,
53229a77 4274 .opt_opc = vecop_list_ssra,
41f6c113
RH
4275 .vece = MO_32 },
4276 { .fni8 = gen_ssra64_i64,
4277 .fniv = gen_ssra_vec,
4278 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
53229a77 4279 .opt_opc = vecop_list_ssra,
41f6c113 4280 .load_dest = true,
41f6c113
RH
4281 .vece = MO_64 },
4282};
4283
4284static void gen_usra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4285{
4286 tcg_gen_vec_shr8i_i64(a, a, shift);
4287 tcg_gen_vec_add8_i64(d, d, a);
4288}
4289
4290static void gen_usra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4291{
4292 tcg_gen_vec_shr16i_i64(a, a, shift);
4293 tcg_gen_vec_add16_i64(d, d, a);
4294}
4295
4296static void gen_usra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
4297{
4298 tcg_gen_shri_i32(a, a, shift);
4299 tcg_gen_add_i32(d, d, a);
4300}
4301
4302static void gen_usra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4303{
4304 tcg_gen_shri_i64(a, a, shift);
4305 tcg_gen_add_i64(d, d, a);
4306}
4307
4308static void gen_usra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
4309{
4310 tcg_gen_shri_vec(vece, a, a, sh);
4311 tcg_gen_add_vec(vece, d, d, a);
4312}
4313
53229a77
RH
4314static const TCGOpcode vecop_list_usra[] = {
4315 INDEX_op_shri_vec, INDEX_op_add_vec, 0
4316};
4317
41f6c113
RH
4318const GVecGen2i usra_op[4] = {
4319 { .fni8 = gen_usra8_i64,
4320 .fniv = gen_usra_vec,
4321 .load_dest = true,
53229a77 4322 .opt_opc = vecop_list_usra,
41f6c113
RH
4323 .vece = MO_8, },
4324 { .fni8 = gen_usra16_i64,
4325 .fniv = gen_usra_vec,
4326 .load_dest = true,
53229a77 4327 .opt_opc = vecop_list_usra,
41f6c113
RH
4328 .vece = MO_16, },
4329 { .fni4 = gen_usra32_i32,
4330 .fniv = gen_usra_vec,
4331 .load_dest = true,
53229a77 4332 .opt_opc = vecop_list_usra,
41f6c113
RH
4333 .vece = MO_32, },
4334 { .fni8 = gen_usra64_i64,
4335 .fniv = gen_usra_vec,
4336 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4337 .load_dest = true,
53229a77 4338 .opt_opc = vecop_list_usra,
41f6c113
RH
4339 .vece = MO_64, },
4340};
eabcd6fa 4341
f3cd8218
RH
4342static void gen_shr8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4343{
4344 uint64_t mask = dup_const(MO_8, 0xff >> shift);
4345 TCGv_i64 t = tcg_temp_new_i64();
4346
4347 tcg_gen_shri_i64(t, a, shift);
4348 tcg_gen_andi_i64(t, t, mask);
4349 tcg_gen_andi_i64(d, d, ~mask);
4350 tcg_gen_or_i64(d, d, t);
4351 tcg_temp_free_i64(t);
4352}
4353
4354static void gen_shr16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4355{
4356 uint64_t mask = dup_const(MO_16, 0xffff >> shift);
4357 TCGv_i64 t = tcg_temp_new_i64();
4358
4359 tcg_gen_shri_i64(t, a, shift);
4360 tcg_gen_andi_i64(t, t, mask);
4361 tcg_gen_andi_i64(d, d, ~mask);
4362 tcg_gen_or_i64(d, d, t);
4363 tcg_temp_free_i64(t);
4364}
4365
4366static void gen_shr32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
4367{
4368 tcg_gen_shri_i32(a, a, shift);
4369 tcg_gen_deposit_i32(d, d, a, 0, 32 - shift);
4370}
4371
4372static void gen_shr64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4373{
4374 tcg_gen_shri_i64(a, a, shift);
4375 tcg_gen_deposit_i64(d, d, a, 0, 64 - shift);
4376}
4377
4378static void gen_shr_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
4379{
4380 if (sh == 0) {
4381 tcg_gen_mov_vec(d, a);
4382 } else {
4383 TCGv_vec t = tcg_temp_new_vec_matching(d);
4384 TCGv_vec m = tcg_temp_new_vec_matching(d);
4385
4386 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK((8 << vece) - sh, sh));
4387 tcg_gen_shri_vec(vece, t, a, sh);
4388 tcg_gen_and_vec(vece, d, d, m);
4389 tcg_gen_or_vec(vece, d, d, t);
4390
4391 tcg_temp_free_vec(t);
4392 tcg_temp_free_vec(m);
4393 }
4394}
4395
53229a77
RH
4396static const TCGOpcode vecop_list_sri[] = { INDEX_op_shri_vec, 0 };
4397
f3cd8218
RH
4398const GVecGen2i sri_op[4] = {
4399 { .fni8 = gen_shr8_ins_i64,
4400 .fniv = gen_shr_ins_vec,
4401 .load_dest = true,
53229a77 4402 .opt_opc = vecop_list_sri,
f3cd8218
RH
4403 .vece = MO_8 },
4404 { .fni8 = gen_shr16_ins_i64,
4405 .fniv = gen_shr_ins_vec,
4406 .load_dest = true,
53229a77 4407 .opt_opc = vecop_list_sri,
f3cd8218
RH
4408 .vece = MO_16 },
4409 { .fni4 = gen_shr32_ins_i32,
4410 .fniv = gen_shr_ins_vec,
4411 .load_dest = true,
53229a77 4412 .opt_opc = vecop_list_sri,
f3cd8218
RH
4413 .vece = MO_32 },
4414 { .fni8 = gen_shr64_ins_i64,
4415 .fniv = gen_shr_ins_vec,
4416 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4417 .load_dest = true,
53229a77 4418 .opt_opc = vecop_list_sri,
f3cd8218
RH
4419 .vece = MO_64 },
4420};
4421
4422static void gen_shl8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4423{
4424 uint64_t mask = dup_const(MO_8, 0xff << shift);
4425 TCGv_i64 t = tcg_temp_new_i64();
4426
4427 tcg_gen_shli_i64(t, a, shift);
4428 tcg_gen_andi_i64(t, t, mask);
4429 tcg_gen_andi_i64(d, d, ~mask);
4430 tcg_gen_or_i64(d, d, t);
4431 tcg_temp_free_i64(t);
4432}
4433
4434static void gen_shl16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4435{
4436 uint64_t mask = dup_const(MO_16, 0xffff << shift);
4437 TCGv_i64 t = tcg_temp_new_i64();
4438
4439 tcg_gen_shli_i64(t, a, shift);
4440 tcg_gen_andi_i64(t, t, mask);
4441 tcg_gen_andi_i64(d, d, ~mask);
4442 tcg_gen_or_i64(d, d, t);
4443 tcg_temp_free_i64(t);
4444}
4445
4446static void gen_shl32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
4447{
4448 tcg_gen_deposit_i32(d, d, a, shift, 32 - shift);
4449}
4450
4451static void gen_shl64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4452{
4453 tcg_gen_deposit_i64(d, d, a, shift, 64 - shift);
4454}
4455
4456static void gen_shl_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
4457{
4458 if (sh == 0) {
4459 tcg_gen_mov_vec(d, a);
4460 } else {
4461 TCGv_vec t = tcg_temp_new_vec_matching(d);
4462 TCGv_vec m = tcg_temp_new_vec_matching(d);
4463
4464 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK(0, sh));
4465 tcg_gen_shli_vec(vece, t, a, sh);
4466 tcg_gen_and_vec(vece, d, d, m);
4467 tcg_gen_or_vec(vece, d, d, t);
4468
4469 tcg_temp_free_vec(t);
4470 tcg_temp_free_vec(m);
4471 }
4472}
4473
53229a77
RH
4474static const TCGOpcode vecop_list_sli[] = { INDEX_op_shli_vec, 0 };
4475
f3cd8218
RH
4476const GVecGen2i sli_op[4] = {
4477 { .fni8 = gen_shl8_ins_i64,
4478 .fniv = gen_shl_ins_vec,
4479 .load_dest = true,
53229a77 4480 .opt_opc = vecop_list_sli,
f3cd8218
RH
4481 .vece = MO_8 },
4482 { .fni8 = gen_shl16_ins_i64,
4483 .fniv = gen_shl_ins_vec,
4484 .load_dest = true,
53229a77 4485 .opt_opc = vecop_list_sli,
f3cd8218
RH
4486 .vece = MO_16 },
4487 { .fni4 = gen_shl32_ins_i32,
4488 .fniv = gen_shl_ins_vec,
4489 .load_dest = true,
53229a77 4490 .opt_opc = vecop_list_sli,
f3cd8218
RH
4491 .vece = MO_32 },
4492 { .fni8 = gen_shl64_ins_i64,
4493 .fniv = gen_shl_ins_vec,
4494 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4495 .load_dest = true,
53229a77 4496 .opt_opc = vecop_list_sli,
f3cd8218
RH
4497 .vece = MO_64 },
4498};
4499
4a7832b0
RH
4500static void gen_mla8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4501{
4502 gen_helper_neon_mul_u8(a, a, b);
4503 gen_helper_neon_add_u8(d, d, a);
4504}
4505
4506static void gen_mls8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4507{
4508 gen_helper_neon_mul_u8(a, a, b);
4509 gen_helper_neon_sub_u8(d, d, a);
4510}
4511
4512static void gen_mla16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4513{
4514 gen_helper_neon_mul_u16(a, a, b);
4515 gen_helper_neon_add_u16(d, d, a);
4516}
4517
4518static void gen_mls16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4519{
4520 gen_helper_neon_mul_u16(a, a, b);
4521 gen_helper_neon_sub_u16(d, d, a);
4522}
4523
4524static void gen_mla32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4525{
4526 tcg_gen_mul_i32(a, a, b);
4527 tcg_gen_add_i32(d, d, a);
4528}
4529
4530static void gen_mls32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4531{
4532 tcg_gen_mul_i32(a, a, b);
4533 tcg_gen_sub_i32(d, d, a);
4534}
4535
4536static void gen_mla64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4537{
4538 tcg_gen_mul_i64(a, a, b);
4539 tcg_gen_add_i64(d, d, a);
4540}
4541
4542static void gen_mls64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4543{
4544 tcg_gen_mul_i64(a, a, b);
4545 tcg_gen_sub_i64(d, d, a);
4546}
4547
4548static void gen_mla_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4549{
4550 tcg_gen_mul_vec(vece, a, a, b);
4551 tcg_gen_add_vec(vece, d, d, a);
4552}
4553
4554static void gen_mls_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4555{
4556 tcg_gen_mul_vec(vece, a, a, b);
4557 tcg_gen_sub_vec(vece, d, d, a);
4558}
4559
4560/* Note that while NEON does not support VMLA and VMLS as 64-bit ops,
4561 * these tables are shared with AArch64 which does support them.
4562 */
53229a77
RH
4563
4564static const TCGOpcode vecop_list_mla[] = {
4565 INDEX_op_mul_vec, INDEX_op_add_vec, 0
4566};
4567
4568static const TCGOpcode vecop_list_mls[] = {
4569 INDEX_op_mul_vec, INDEX_op_sub_vec, 0
4570};
4571
4a7832b0
RH
4572const GVecGen3 mla_op[4] = {
4573 { .fni4 = gen_mla8_i32,
4574 .fniv = gen_mla_vec,
4a7832b0 4575 .load_dest = true,
53229a77 4576 .opt_opc = vecop_list_mla,
4a7832b0
RH
4577 .vece = MO_8 },
4578 { .fni4 = gen_mla16_i32,
4579 .fniv = gen_mla_vec,
4a7832b0 4580 .load_dest = true,
53229a77 4581 .opt_opc = vecop_list_mla,
4a7832b0
RH
4582 .vece = MO_16 },
4583 { .fni4 = gen_mla32_i32,
4584 .fniv = gen_mla_vec,
4a7832b0 4585 .load_dest = true,
53229a77 4586 .opt_opc = vecop_list_mla,
4a7832b0
RH
4587 .vece = MO_32 },
4588 { .fni8 = gen_mla64_i64,
4589 .fniv = gen_mla_vec,
4a7832b0
RH
4590 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4591 .load_dest = true,
53229a77 4592 .opt_opc = vecop_list_mla,
4a7832b0
RH
4593 .vece = MO_64 },
4594};
4595
4596const GVecGen3 mls_op[4] = {
4597 { .fni4 = gen_mls8_i32,
4598 .fniv = gen_mls_vec,
4a7832b0 4599 .load_dest = true,
53229a77 4600 .opt_opc = vecop_list_mls,
4a7832b0
RH
4601 .vece = MO_8 },
4602 { .fni4 = gen_mls16_i32,
4603 .fniv = gen_mls_vec,
4a7832b0 4604 .load_dest = true,
53229a77 4605 .opt_opc = vecop_list_mls,
4a7832b0
RH
4606 .vece = MO_16 },
4607 { .fni4 = gen_mls32_i32,
4608 .fniv = gen_mls_vec,
4a7832b0 4609 .load_dest = true,
53229a77 4610 .opt_opc = vecop_list_mls,
4a7832b0
RH
4611 .vece = MO_32 },
4612 { .fni8 = gen_mls64_i64,
4613 .fniv = gen_mls_vec,
4a7832b0
RH
4614 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4615 .load_dest = true,
53229a77 4616 .opt_opc = vecop_list_mls,
4a7832b0
RH
4617 .vece = MO_64 },
4618};
4619
ea580fa3
RH
4620/* CMTST : test is "if (X & Y != 0)". */
4621static void gen_cmtst_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4622{
4623 tcg_gen_and_i32(d, a, b);
4624 tcg_gen_setcondi_i32(TCG_COND_NE, d, d, 0);
4625 tcg_gen_neg_i32(d, d);
4626}
4627
4628void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4629{
4630 tcg_gen_and_i64(d, a, b);
4631 tcg_gen_setcondi_i64(TCG_COND_NE, d, d, 0);
4632 tcg_gen_neg_i64(d, d);
4633}
4634
4635static void gen_cmtst_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4636{
4637 tcg_gen_and_vec(vece, d, a, b);
4638 tcg_gen_dupi_vec(vece, a, 0);
4639 tcg_gen_cmp_vec(TCG_COND_NE, vece, d, d, a);
4640}
4641
53229a77
RH
4642static const TCGOpcode vecop_list_cmtst[] = { INDEX_op_cmp_vec, 0 };
4643
ea580fa3
RH
4644const GVecGen3 cmtst_op[4] = {
4645 { .fni4 = gen_helper_neon_tst_u8,
4646 .fniv = gen_cmtst_vec,
53229a77 4647 .opt_opc = vecop_list_cmtst,
ea580fa3
RH
4648 .vece = MO_8 },
4649 { .fni4 = gen_helper_neon_tst_u16,
4650 .fniv = gen_cmtst_vec,
53229a77 4651 .opt_opc = vecop_list_cmtst,
ea580fa3
RH
4652 .vece = MO_16 },
4653 { .fni4 = gen_cmtst_i32,
4654 .fniv = gen_cmtst_vec,
53229a77 4655 .opt_opc = vecop_list_cmtst,
ea580fa3
RH
4656 .vece = MO_32 },
4657 { .fni8 = gen_cmtst_i64,
4658 .fniv = gen_cmtst_vec,
4659 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
53229a77 4660 .opt_opc = vecop_list_cmtst,
ea580fa3
RH
4661 .vece = MO_64 },
4662};
4663
89e68b57
RH
4664static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4665 TCGv_vec a, TCGv_vec b)
4666{
4667 TCGv_vec x = tcg_temp_new_vec_matching(t);
4668 tcg_gen_add_vec(vece, x, a, b);
4669 tcg_gen_usadd_vec(vece, t, a, b);
4670 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4671 tcg_gen_or_vec(vece, sat, sat, x);
4672 tcg_temp_free_vec(x);
4673}
4674
53229a77
RH
4675static const TCGOpcode vecop_list_uqadd[] = {
4676 INDEX_op_usadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
4677};
4678
89e68b57
RH
4679const GVecGen4 uqadd_op[4] = {
4680 { .fniv = gen_uqadd_vec,
4681 .fno = gen_helper_gvec_uqadd_b,
89e68b57 4682 .write_aofs = true,
53229a77 4683 .opt_opc = vecop_list_uqadd,
89e68b57
RH
4684 .vece = MO_8 },
4685 { .fniv = gen_uqadd_vec,
4686 .fno = gen_helper_gvec_uqadd_h,
89e68b57 4687 .write_aofs = true,
53229a77 4688 .opt_opc = vecop_list_uqadd,
89e68b57
RH
4689 .vece = MO_16 },
4690 { .fniv = gen_uqadd_vec,
4691 .fno = gen_helper_gvec_uqadd_s,
89e68b57 4692 .write_aofs = true,
53229a77 4693 .opt_opc = vecop_list_uqadd,
89e68b57
RH
4694 .vece = MO_32 },
4695 { .fniv = gen_uqadd_vec,
4696 .fno = gen_helper_gvec_uqadd_d,
89e68b57 4697 .write_aofs = true,
53229a77 4698 .opt_opc = vecop_list_uqadd,
89e68b57
RH
4699 .vece = MO_64 },
4700};
4701
4702static void gen_sqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4703 TCGv_vec a, TCGv_vec b)
4704{
4705 TCGv_vec x = tcg_temp_new_vec_matching(t);
4706 tcg_gen_add_vec(vece, x, a, b);
4707 tcg_gen_ssadd_vec(vece, t, a, b);
4708 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4709 tcg_gen_or_vec(vece, sat, sat, x);
4710 tcg_temp_free_vec(x);
4711}
4712
53229a77
RH
4713static const TCGOpcode vecop_list_sqadd[] = {
4714 INDEX_op_ssadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
4715};
4716
89e68b57
RH
4717const GVecGen4 sqadd_op[4] = {
4718 { .fniv = gen_sqadd_vec,
4719 .fno = gen_helper_gvec_sqadd_b,
53229a77 4720 .opt_opc = vecop_list_sqadd,
89e68b57
RH
4721 .write_aofs = true,
4722 .vece = MO_8 },
4723 { .fniv = gen_sqadd_vec,
4724 .fno = gen_helper_gvec_sqadd_h,
53229a77 4725 .opt_opc = vecop_list_sqadd,
89e68b57
RH
4726 .write_aofs = true,
4727 .vece = MO_16 },
4728 { .fniv = gen_sqadd_vec,
4729 .fno = gen_helper_gvec_sqadd_s,
53229a77 4730 .opt_opc = vecop_list_sqadd,
89e68b57
RH
4731 .write_aofs = true,
4732 .vece = MO_32 },
4733 { .fniv = gen_sqadd_vec,
4734 .fno = gen_helper_gvec_sqadd_d,
53229a77 4735 .opt_opc = vecop_list_sqadd,
89e68b57
RH
4736 .write_aofs = true,
4737 .vece = MO_64 },
4738};
4739
4740static void gen_uqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4741 TCGv_vec a, TCGv_vec b)
4742{
4743 TCGv_vec x = tcg_temp_new_vec_matching(t);
4744 tcg_gen_sub_vec(vece, x, a, b);
4745 tcg_gen_ussub_vec(vece, t, a, b);
4746 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4747 tcg_gen_or_vec(vece, sat, sat, x);
4748 tcg_temp_free_vec(x);
4749}
4750
53229a77
RH
4751static const TCGOpcode vecop_list_uqsub[] = {
4752 INDEX_op_ussub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
4753};
4754
89e68b57
RH
4755const GVecGen4 uqsub_op[4] = {
4756 { .fniv = gen_uqsub_vec,
4757 .fno = gen_helper_gvec_uqsub_b,
53229a77 4758 .opt_opc = vecop_list_uqsub,
89e68b57
RH
4759 .write_aofs = true,
4760 .vece = MO_8 },
4761 { .fniv = gen_uqsub_vec,
4762 .fno = gen_helper_gvec_uqsub_h,
53229a77 4763 .opt_opc = vecop_list_uqsub,
89e68b57
RH
4764 .write_aofs = true,
4765 .vece = MO_16 },
4766 { .fniv = gen_uqsub_vec,
4767 .fno = gen_helper_gvec_uqsub_s,
53229a77 4768 .opt_opc = vecop_list_uqsub,
89e68b57
RH
4769 .write_aofs = true,
4770 .vece = MO_32 },
4771 { .fniv = gen_uqsub_vec,
4772 .fno = gen_helper_gvec_uqsub_d,
53229a77 4773 .opt_opc = vecop_list_uqsub,
89e68b57
RH
4774 .write_aofs = true,
4775 .vece = MO_64 },
4776};
4777
4778static void gen_sqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4779 TCGv_vec a, TCGv_vec b)
4780{
4781 TCGv_vec x = tcg_temp_new_vec_matching(t);
4782 tcg_gen_sub_vec(vece, x, a, b);
4783 tcg_gen_sssub_vec(vece, t, a, b);
4784 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4785 tcg_gen_or_vec(vece, sat, sat, x);
4786 tcg_temp_free_vec(x);
4787}
4788
53229a77
RH
4789static const TCGOpcode vecop_list_sqsub[] = {
4790 INDEX_op_sssub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
4791};
4792
89e68b57
RH
4793const GVecGen4 sqsub_op[4] = {
4794 { .fniv = gen_sqsub_vec,
4795 .fno = gen_helper_gvec_sqsub_b,
53229a77 4796 .opt_opc = vecop_list_sqsub,
89e68b57
RH
4797 .write_aofs = true,
4798 .vece = MO_8 },
4799 { .fniv = gen_sqsub_vec,
4800 .fno = gen_helper_gvec_sqsub_h,
53229a77 4801 .opt_opc = vecop_list_sqsub,
89e68b57
RH
4802 .write_aofs = true,
4803 .vece = MO_16 },
4804 { .fniv = gen_sqsub_vec,
4805 .fno = gen_helper_gvec_sqsub_s,
53229a77 4806 .opt_opc = vecop_list_sqsub,
89e68b57
RH
4807 .write_aofs = true,
4808 .vece = MO_32 },
4809 { .fniv = gen_sqsub_vec,
4810 .fno = gen_helper_gvec_sqsub_d,
53229a77 4811 .opt_opc = vecop_list_sqsub,
89e68b57
RH
4812 .write_aofs = true,
4813 .vece = MO_64 },
4814};
4815
9ee6e8bb
PB
4816/* Translate a NEON data processing instruction. Return nonzero if the
4817 instruction is invalid.
ad69471c
PB
4818 We process data in a mixture of 32-bit and 64-bit chunks.
4819 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
2c0262af 4820
7dcc1f89 4821static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
9ee6e8bb
PB
4822{
4823 int op;
4824 int q;
eabcd6fa 4825 int rd, rn, rm, rd_ofs, rn_ofs, rm_ofs;
9ee6e8bb
PB
4826 int size;
4827 int shift;
4828 int pass;
4829 int count;
4830 int pairwise;
4831 int u;
eabcd6fa 4832 int vec_size;
f3cd8218 4833 uint32_t imm;
39d5492a 4834 TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
1a66ac61 4835 TCGv_ptr ptr1, ptr2, ptr3;
a7812ae4 4836 TCGv_i64 tmp64;
9ee6e8bb 4837
2c7ffc41
PM
4838 /* FIXME: this access check should not take precedence over UNDEF
4839 * for invalid encodings; we will generate incorrect syndrome information
4840 * for attempts to execute invalid vfp/neon encodings with FP disabled.
4841 */
9dbbc748 4842 if (s->fp_excp_el) {
2c7ffc41 4843 gen_exception_insn(s, 4, EXCP_UDEF,
4be42f40 4844 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
2c7ffc41
PM
4845 return 0;
4846 }
4847
5df8bac1 4848 if (!s->vfp_enabled)
9ee6e8bb
PB
4849 return 1;
4850 q = (insn & (1 << 6)) != 0;
4851 u = (insn >> 24) & 1;
4852 VFP_DREG_D(rd, insn);
4853 VFP_DREG_N(rn, insn);
4854 VFP_DREG_M(rm, insn);
4855 size = (insn >> 20) & 3;
eabcd6fa
RH
4856 vec_size = q ? 16 : 8;
4857 rd_ofs = neon_reg_offset(rd, 0);
4858 rn_ofs = neon_reg_offset(rn, 0);
4859 rm_ofs = neon_reg_offset(rm, 0);
4860
9ee6e8bb
PB
4861 if ((insn & (1 << 23)) == 0) {
4862 /* Three register same length. */
4863 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
62698be3
PM
4864 /* Catch invalid op and bad size combinations: UNDEF */
4865 if ((neon_3r_sizes[op] & (1 << size)) == 0) {
4866 return 1;
4867 }
25f84f79
PM
4868 /* All insns of this form UNDEF for either this condition or the
4869 * superset of cases "Q==1"; we catch the latter later.
4870 */
4871 if (q && ((rd | rn | rm) & 1)) {
4872 return 1;
4873 }
36a71934
RH
4874 switch (op) {
4875 case NEON_3R_SHA:
4876 /* The SHA-1/SHA-256 3-register instructions require special
4877 * treatment here, as their size field is overloaded as an
4878 * op type selector, and they all consume their input in a
4879 * single pass.
4880 */
f1ecb913
AB
4881 if (!q) {
4882 return 1;
4883 }
4884 if (!u) { /* SHA-1 */
962fcbf2 4885 if (!dc_isar_feature(aa32_sha1, s)) {
f1ecb913
AB
4886 return 1;
4887 }
1a66ac61
RH
4888 ptr1 = vfp_reg_ptr(true, rd);
4889 ptr2 = vfp_reg_ptr(true, rn);
4890 ptr3 = vfp_reg_ptr(true, rm);
f1ecb913 4891 tmp4 = tcg_const_i32(size);
1a66ac61 4892 gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp4);
f1ecb913
AB
4893 tcg_temp_free_i32(tmp4);
4894 } else { /* SHA-256 */
962fcbf2 4895 if (!dc_isar_feature(aa32_sha2, s) || size == 3) {
f1ecb913
AB
4896 return 1;
4897 }
1a66ac61
RH
4898 ptr1 = vfp_reg_ptr(true, rd);
4899 ptr2 = vfp_reg_ptr(true, rn);
4900 ptr3 = vfp_reg_ptr(true, rm);
f1ecb913
AB
4901 switch (size) {
4902 case 0:
1a66ac61 4903 gen_helper_crypto_sha256h(ptr1, ptr2, ptr3);
f1ecb913
AB
4904 break;
4905 case 1:
1a66ac61 4906 gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3);
f1ecb913
AB
4907 break;
4908 case 2:
1a66ac61 4909 gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3);
f1ecb913
AB
4910 break;
4911 }
4912 }
1a66ac61
RH
4913 tcg_temp_free_ptr(ptr1);
4914 tcg_temp_free_ptr(ptr2);
4915 tcg_temp_free_ptr(ptr3);
f1ecb913 4916 return 0;
36a71934
RH
4917
4918 case NEON_3R_VPADD_VQRDMLAH:
4919 if (!u) {
4920 break; /* VPADD */
4921 }
4922 /* VQRDMLAH */
4923 switch (size) {
4924 case 1:
4925 return do_v81_helper(s, gen_helper_gvec_qrdmlah_s16,
4926 q, rd, rn, rm);
4927 case 2:
4928 return do_v81_helper(s, gen_helper_gvec_qrdmlah_s32,
4929 q, rd, rn, rm);
4930 }
4931 return 1;
4932
4933 case NEON_3R_VFM_VQRDMLSH:
4934 if (!u) {
4935 /* VFM, VFMS */
4936 if (size == 1) {
4937 return 1;
4938 }
4939 break;
4940 }
4941 /* VQRDMLSH */
4942 switch (size) {
4943 case 1:
4944 return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s16,
4945 q, rd, rn, rm);
4946 case 2:
4947 return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s32,
4948 q, rd, rn, rm);
4949 }
4950 return 1;
eabcd6fa
RH
4951
4952 case NEON_3R_LOGIC: /* Logic ops. */
4953 switch ((u << 2) | size) {
4954 case 0: /* VAND */
4955 tcg_gen_gvec_and(0, rd_ofs, rn_ofs, rm_ofs,
4956 vec_size, vec_size);
4957 break;
4958 case 1: /* VBIC */
4959 tcg_gen_gvec_andc(0, rd_ofs, rn_ofs, rm_ofs,
4960 vec_size, vec_size);
4961 break;
2900847f
RH
4962 case 2: /* VORR */
4963 tcg_gen_gvec_or(0, rd_ofs, rn_ofs, rm_ofs,
4964 vec_size, vec_size);
eabcd6fa
RH
4965 break;
4966 case 3: /* VORN */
4967 tcg_gen_gvec_orc(0, rd_ofs, rn_ofs, rm_ofs,
4968 vec_size, vec_size);
4969 break;
4970 case 4: /* VEOR */
4971 tcg_gen_gvec_xor(0, rd_ofs, rn_ofs, rm_ofs,
4972 vec_size, vec_size);
4973 break;
4974 case 5: /* VBSL */
3a7a2b4e
RH
4975 tcg_gen_gvec_bitsel(MO_8, rd_ofs, rd_ofs, rn_ofs, rm_ofs,
4976 vec_size, vec_size);
eabcd6fa
RH
4977 break;
4978 case 6: /* VBIT */
3a7a2b4e
RH
4979 tcg_gen_gvec_bitsel(MO_8, rd_ofs, rm_ofs, rn_ofs, rd_ofs,
4980 vec_size, vec_size);
eabcd6fa
RH
4981 break;
4982 case 7: /* VBIF */
3a7a2b4e
RH
4983 tcg_gen_gvec_bitsel(MO_8, rd_ofs, rm_ofs, rd_ofs, rn_ofs,
4984 vec_size, vec_size);
eabcd6fa
RH
4985 break;
4986 }
4987 return 0;
e4717ae0
RH
4988
4989 case NEON_3R_VADD_VSUB:
4990 if (u) {
4991 tcg_gen_gvec_sub(size, rd_ofs, rn_ofs, rm_ofs,
4992 vec_size, vec_size);
4993 } else {
4994 tcg_gen_gvec_add(size, rd_ofs, rn_ofs, rm_ofs,
4995 vec_size, vec_size);
4996 }
4997 return 0;
82083184 4998
89e68b57
RH
4999 case NEON_3R_VQADD:
5000 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
5001 rn_ofs, rm_ofs, vec_size, vec_size,
5002 (u ? uqadd_op : sqadd_op) + size);
2f143d3a 5003 return 0;
89e68b57
RH
5004
5005 case NEON_3R_VQSUB:
5006 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
5007 rn_ofs, rm_ofs, vec_size, vec_size,
5008 (u ? uqsub_op : sqsub_op) + size);
2f143d3a 5009 return 0;
89e68b57 5010
82083184
RH
5011 case NEON_3R_VMUL: /* VMUL */
5012 if (u) {
5013 /* Polynomial case allows only P8 and is handled below. */
5014 if (size != 0) {
5015 return 1;
5016 }
5017 } else {
5018 tcg_gen_gvec_mul(size, rd_ofs, rn_ofs, rm_ofs,
5019 vec_size, vec_size);
5020 return 0;
5021 }
5022 break;
4a7832b0
RH
5023
5024 case NEON_3R_VML: /* VMLA, VMLS */
5025 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size,
5026 u ? &mls_op[size] : &mla_op[size]);
5027 return 0;
ea580fa3
RH
5028
5029 case NEON_3R_VTST_VCEQ:
5030 if (u) { /* VCEQ */
5031 tcg_gen_gvec_cmp(TCG_COND_EQ, size, rd_ofs, rn_ofs, rm_ofs,
5032 vec_size, vec_size);
5033 } else { /* VTST */
5034 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
5035 vec_size, vec_size, &cmtst_op[size]);
5036 }
5037 return 0;
5038
5039 case NEON_3R_VCGT:
5040 tcg_gen_gvec_cmp(u ? TCG_COND_GTU : TCG_COND_GT, size,
5041 rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
5042 return 0;
5043
5044 case NEON_3R_VCGE:
5045 tcg_gen_gvec_cmp(u ? TCG_COND_GEU : TCG_COND_GE, size,
5046 rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
5047 return 0;
6f278221
RH
5048
5049 case NEON_3R_VMAX:
5050 if (u) {
5051 tcg_gen_gvec_umax(size, rd_ofs, rn_ofs, rm_ofs,
5052 vec_size, vec_size);
5053 } else {
5054 tcg_gen_gvec_smax(size, rd_ofs, rn_ofs, rm_ofs,
5055 vec_size, vec_size);
5056 }
5057 return 0;
5058 case NEON_3R_VMIN:
5059 if (u) {
5060 tcg_gen_gvec_umin(size, rd_ofs, rn_ofs, rm_ofs,
5061 vec_size, vec_size);
5062 } else {
5063 tcg_gen_gvec_smin(size, rd_ofs, rn_ofs, rm_ofs,
5064 vec_size, vec_size);
5065 }
5066 return 0;
f1ecb913 5067 }
4a7832b0 5068
eabcd6fa 5069 if (size == 3) {
62698be3 5070 /* 64-bit element instructions. */
9ee6e8bb 5071 for (pass = 0; pass < (q ? 2 : 1); pass++) {
ad69471c
PB
5072 neon_load_reg64(cpu_V0, rn + pass);
5073 neon_load_reg64(cpu_V1, rm + pass);
9ee6e8bb 5074 switch (op) {
62698be3 5075 case NEON_3R_VSHL:
ad69471c
PB
5076 if (u) {
5077 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
5078 } else {
5079 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
5080 }
5081 break;
62698be3 5082 case NEON_3R_VQSHL:
ad69471c 5083 if (u) {
02da0b2d
PM
5084 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
5085 cpu_V1, cpu_V0);
ad69471c 5086 } else {
02da0b2d
PM
5087 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
5088 cpu_V1, cpu_V0);
ad69471c
PB
5089 }
5090 break;
62698be3 5091 case NEON_3R_VRSHL:
ad69471c
PB
5092 if (u) {
5093 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
1e8d4eec 5094 } else {
ad69471c
PB
5095 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
5096 }
5097 break;
62698be3 5098 case NEON_3R_VQRSHL:
ad69471c 5099 if (u) {
02da0b2d
PM
5100 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
5101 cpu_V1, cpu_V0);
ad69471c 5102 } else {
02da0b2d
PM
5103 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
5104 cpu_V1, cpu_V0);
1e8d4eec 5105 }
9ee6e8bb 5106 break;
9ee6e8bb
PB
5107 default:
5108 abort();
2c0262af 5109 }
ad69471c 5110 neon_store_reg64(cpu_V0, rd + pass);
2c0262af 5111 }
9ee6e8bb 5112 return 0;
2c0262af 5113 }
25f84f79 5114 pairwise = 0;
9ee6e8bb 5115 switch (op) {
62698be3
PM
5116 case NEON_3R_VSHL:
5117 case NEON_3R_VQSHL:
5118 case NEON_3R_VRSHL:
5119 case NEON_3R_VQRSHL:
9ee6e8bb 5120 {
ad69471c
PB
5121 int rtmp;
5122 /* Shift instruction operands are reversed. */
5123 rtmp = rn;
9ee6e8bb 5124 rn = rm;
ad69471c 5125 rm = rtmp;
9ee6e8bb 5126 }
2c0262af 5127 break;
36a71934 5128 case NEON_3R_VPADD_VQRDMLAH:
62698be3
PM
5129 case NEON_3R_VPMAX:
5130 case NEON_3R_VPMIN:
9ee6e8bb 5131 pairwise = 1;
2c0262af 5132 break;
25f84f79
PM
5133 case NEON_3R_FLOAT_ARITH:
5134 pairwise = (u && size < 2); /* if VPADD (float) */
5135 break;
5136 case NEON_3R_FLOAT_MINMAX:
5137 pairwise = u; /* if VPMIN/VPMAX (float) */
5138 break;
5139 case NEON_3R_FLOAT_CMP:
5140 if (!u && size) {
5141 /* no encoding for U=0 C=1x */
5142 return 1;
5143 }
5144 break;
5145 case NEON_3R_FLOAT_ACMP:
5146 if (!u) {
5147 return 1;
5148 }
5149 break;
505935fc
WN
5150 case NEON_3R_FLOAT_MISC:
5151 /* VMAXNM/VMINNM in ARMv8 */
d614a513 5152 if (u && !arm_dc_feature(s, ARM_FEATURE_V8)) {
25f84f79
PM
5153 return 1;
5154 }
2c0262af 5155 break;
36a71934
RH
5156 case NEON_3R_VFM_VQRDMLSH:
5157 if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
da97f52c
PM
5158 return 1;
5159 }
5160 break;
9ee6e8bb 5161 default:
2c0262af 5162 break;
9ee6e8bb 5163 }
dd8fbd78 5164
25f84f79
PM
5165 if (pairwise && q) {
5166 /* All the pairwise insns UNDEF if Q is set */
5167 return 1;
5168 }
5169
9ee6e8bb
PB
5170 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5171
5172 if (pairwise) {
5173 /* Pairwise. */
a5a14945
JR
5174 if (pass < 1) {
5175 tmp = neon_load_reg(rn, 0);
5176 tmp2 = neon_load_reg(rn, 1);
9ee6e8bb 5177 } else {
a5a14945
JR
5178 tmp = neon_load_reg(rm, 0);
5179 tmp2 = neon_load_reg(rm, 1);
9ee6e8bb
PB
5180 }
5181 } else {
5182 /* Elementwise. */
dd8fbd78
FN
5183 tmp = neon_load_reg(rn, pass);
5184 tmp2 = neon_load_reg(rm, pass);
9ee6e8bb
PB
5185 }
5186 switch (op) {
62698be3 5187 case NEON_3R_VHADD:
9ee6e8bb
PB
5188 GEN_NEON_INTEGER_OP(hadd);
5189 break;
62698be3 5190 case NEON_3R_VRHADD:
9ee6e8bb 5191 GEN_NEON_INTEGER_OP(rhadd);
2c0262af 5192 break;
62698be3 5193 case NEON_3R_VHSUB:
9ee6e8bb
PB
5194 GEN_NEON_INTEGER_OP(hsub);
5195 break;
62698be3 5196 case NEON_3R_VSHL:
ad69471c 5197 GEN_NEON_INTEGER_OP(shl);
2c0262af 5198 break;
62698be3 5199 case NEON_3R_VQSHL:
02da0b2d 5200 GEN_NEON_INTEGER_OP_ENV(qshl);
2c0262af 5201 break;
62698be3 5202 case NEON_3R_VRSHL:
ad69471c 5203 GEN_NEON_INTEGER_OP(rshl);
2c0262af 5204 break;
62698be3 5205 case NEON_3R_VQRSHL:
02da0b2d 5206 GEN_NEON_INTEGER_OP_ENV(qrshl);
9ee6e8bb 5207 break;
62698be3 5208 case NEON_3R_VABD:
9ee6e8bb
PB
5209 GEN_NEON_INTEGER_OP(abd);
5210 break;
62698be3 5211 case NEON_3R_VABA:
9ee6e8bb 5212 GEN_NEON_INTEGER_OP(abd);
7d1b0095 5213 tcg_temp_free_i32(tmp2);
dd8fbd78
FN
5214 tmp2 = neon_load_reg(rd, pass);
5215 gen_neon_add(size, tmp, tmp2);
9ee6e8bb 5216 break;
62698be3 5217 case NEON_3R_VMUL:
82083184
RH
5218 /* VMUL.P8; other cases already eliminated. */
5219 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
9ee6e8bb 5220 break;
62698be3 5221 case NEON_3R_VPMAX:
9ee6e8bb
PB
5222 GEN_NEON_INTEGER_OP(pmax);
5223 break;
62698be3 5224 case NEON_3R_VPMIN:
9ee6e8bb
PB
5225 GEN_NEON_INTEGER_OP(pmin);
5226 break;
62698be3 5227 case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
9ee6e8bb
PB
5228 if (!u) { /* VQDMULH */
5229 switch (size) {
02da0b2d
PM
5230 case 1:
5231 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5232 break;
5233 case 2:
5234 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5235 break;
62698be3 5236 default: abort();
9ee6e8bb 5237 }
62698be3 5238 } else { /* VQRDMULH */
9ee6e8bb 5239 switch (size) {
02da0b2d
PM
5240 case 1:
5241 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5242 break;
5243 case 2:
5244 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5245 break;
62698be3 5246 default: abort();
9ee6e8bb
PB
5247 }
5248 }
5249 break;
36a71934 5250 case NEON_3R_VPADD_VQRDMLAH:
9ee6e8bb 5251 switch (size) {
dd8fbd78
FN
5252 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
5253 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
5254 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
62698be3 5255 default: abort();
9ee6e8bb
PB
5256 }
5257 break;
62698be3 5258 case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
aa47cfdd
PM
5259 {
5260 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
9ee6e8bb
PB
5261 switch ((u << 2) | size) {
5262 case 0: /* VADD */
aa47cfdd
PM
5263 case 4: /* VPADD */
5264 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
9ee6e8bb
PB
5265 break;
5266 case 2: /* VSUB */
aa47cfdd 5267 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
9ee6e8bb
PB
5268 break;
5269 case 6: /* VABD */
aa47cfdd 5270 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
9ee6e8bb
PB
5271 break;
5272 default:
62698be3 5273 abort();
9ee6e8bb 5274 }
aa47cfdd 5275 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 5276 break;
aa47cfdd 5277 }
62698be3 5278 case NEON_3R_FLOAT_MULTIPLY:
aa47cfdd
PM
5279 {
5280 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5281 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
9ee6e8bb 5282 if (!u) {
7d1b0095 5283 tcg_temp_free_i32(tmp2);
dd8fbd78 5284 tmp2 = neon_load_reg(rd, pass);
9ee6e8bb 5285 if (size == 0) {
aa47cfdd 5286 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
9ee6e8bb 5287 } else {
aa47cfdd 5288 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
9ee6e8bb
PB
5289 }
5290 }
aa47cfdd 5291 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 5292 break;
aa47cfdd 5293 }
62698be3 5294 case NEON_3R_FLOAT_CMP:
aa47cfdd
PM
5295 {
5296 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
9ee6e8bb 5297 if (!u) {
aa47cfdd 5298 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
b5ff1b31 5299 } else {
aa47cfdd
PM
5300 if (size == 0) {
5301 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
5302 } else {
5303 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
5304 }
b5ff1b31 5305 }
aa47cfdd 5306 tcg_temp_free_ptr(fpstatus);
2c0262af 5307 break;
aa47cfdd 5308 }
62698be3 5309 case NEON_3R_FLOAT_ACMP:
aa47cfdd
PM
5310 {
5311 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5312 if (size == 0) {
5313 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
5314 } else {
5315 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
5316 }
5317 tcg_temp_free_ptr(fpstatus);
2c0262af 5318 break;
aa47cfdd 5319 }
62698be3 5320 case NEON_3R_FLOAT_MINMAX:
aa47cfdd
PM
5321 {
5322 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5323 if (size == 0) {
f71a2ae5 5324 gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus);
aa47cfdd 5325 } else {
f71a2ae5 5326 gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus);
aa47cfdd
PM
5327 }
5328 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 5329 break;
aa47cfdd 5330 }
505935fc
WN
5331 case NEON_3R_FLOAT_MISC:
5332 if (u) {
5333 /* VMAXNM/VMINNM */
5334 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5335 if (size == 0) {
f71a2ae5 5336 gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus);
505935fc 5337 } else {
f71a2ae5 5338 gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus);
505935fc
WN
5339 }
5340 tcg_temp_free_ptr(fpstatus);
5341 } else {
5342 if (size == 0) {
5343 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
5344 } else {
5345 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
5346 }
5347 }
2c0262af 5348 break;
36a71934 5349 case NEON_3R_VFM_VQRDMLSH:
da97f52c
PM
5350 {
5351 /* VFMA, VFMS: fused multiply-add */
5352 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5353 TCGv_i32 tmp3 = neon_load_reg(rd, pass);
5354 if (size) {
5355 /* VFMS */
5356 gen_helper_vfp_negs(tmp, tmp);
5357 }
5358 gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus);
5359 tcg_temp_free_i32(tmp3);
5360 tcg_temp_free_ptr(fpstatus);
5361 break;
5362 }
9ee6e8bb
PB
5363 default:
5364 abort();
2c0262af 5365 }
7d1b0095 5366 tcg_temp_free_i32(tmp2);
dd8fbd78 5367
9ee6e8bb
PB
5368 /* Save the result. For elementwise operations we can put it
5369 straight into the destination register. For pairwise operations
5370 we have to be careful to avoid clobbering the source operands. */
5371 if (pairwise && rd == rm) {
dd8fbd78 5372 neon_store_scratch(pass, tmp);
9ee6e8bb 5373 } else {
dd8fbd78 5374 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
5375 }
5376
5377 } /* for pass */
5378 if (pairwise && rd == rm) {
5379 for (pass = 0; pass < (q ? 4 : 2); pass++) {
dd8fbd78
FN
5380 tmp = neon_load_scratch(pass);
5381 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
5382 }
5383 }
ad69471c 5384 /* End of 3 register same size operations. */
9ee6e8bb
PB
5385 } else if (insn & (1 << 4)) {
5386 if ((insn & 0x00380080) != 0) {
5387 /* Two registers and shift. */
5388 op = (insn >> 8) & 0xf;
5389 if (insn & (1 << 7)) {
cc13115b
PM
5390 /* 64-bit shift. */
5391 if (op > 7) {
5392 return 1;
5393 }
9ee6e8bb
PB
5394 size = 3;
5395 } else {
5396 size = 2;
5397 while ((insn & (1 << (size + 19))) == 0)
5398 size--;
5399 }
5400 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
9ee6e8bb
PB
5401 if (op < 8) {
5402 /* Shift by immediate:
5403 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
cc13115b
PM
5404 if (q && ((rd | rm) & 1)) {
5405 return 1;
5406 }
5407 if (!u && (op == 4 || op == 6)) {
5408 return 1;
5409 }
9ee6e8bb
PB
5410 /* Right shifts are encoded as N - shift, where N is the
5411 element size in bits. */
1dc8425e 5412 if (op <= 4) {
9ee6e8bb 5413 shift = shift - (1 << (size + 3));
1dc8425e
RH
5414 }
5415
5416 switch (op) {
5417 case 0: /* VSHR */
5418 /* Right shift comes here negative. */
5419 shift = -shift;
5420 /* Shifts larger than the element size are architecturally
5421 * valid. Unsigned results in all zeros; signed results
5422 * in all sign bits.
5423 */
5424 if (!u) {
5425 tcg_gen_gvec_sari(size, rd_ofs, rm_ofs,
5426 MIN(shift, (8 << size) - 1),
5427 vec_size, vec_size);
5428 } else if (shift >= 8 << size) {
5429 tcg_gen_gvec_dup8i(rd_ofs, vec_size, vec_size, 0);
5430 } else {
5431 tcg_gen_gvec_shri(size, rd_ofs, rm_ofs, shift,
5432 vec_size, vec_size);
5433 }
5434 return 0;
5435
41f6c113
RH
5436 case 1: /* VSRA */
5437 /* Right shift comes here negative. */
5438 shift = -shift;
5439 /* Shifts larger than the element size are architecturally
5440 * valid. Unsigned results in all zeros; signed results
5441 * in all sign bits.
5442 */
5443 if (!u) {
5444 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
5445 MIN(shift, (8 << size) - 1),
5446 &ssra_op[size]);
5447 } else if (shift >= 8 << size) {
5448 /* rd += 0 */
5449 } else {
5450 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
5451 shift, &usra_op[size]);
5452 }
5453 return 0;
5454
f3cd8218
RH
5455 case 4: /* VSRI */
5456 if (!u) {
5457 return 1;
5458 }
5459 /* Right shift comes here negative. */
5460 shift = -shift;
5461 /* Shift out of range leaves destination unchanged. */
5462 if (shift < 8 << size) {
5463 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
5464 shift, &sri_op[size]);
5465 }
5466 return 0;
5467
1dc8425e 5468 case 5: /* VSHL, VSLI */
f3cd8218
RH
5469 if (u) { /* VSLI */
5470 /* Shift out of range leaves destination unchanged. */
5471 if (shift < 8 << size) {
5472 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size,
5473 vec_size, shift, &sli_op[size]);
5474 }
5475 } else { /* VSHL */
1dc8425e
RH
5476 /* Shifts larger than the element size are
5477 * architecturally valid and results in zero.
5478 */
5479 if (shift >= 8 << size) {
5480 tcg_gen_gvec_dup8i(rd_ofs, vec_size, vec_size, 0);
5481 } else {
5482 tcg_gen_gvec_shli(size, rd_ofs, rm_ofs, shift,
5483 vec_size, vec_size);
5484 }
1dc8425e 5485 }
f3cd8218 5486 return 0;
1dc8425e
RH
5487 }
5488
9ee6e8bb
PB
5489 if (size == 3) {
5490 count = q + 1;
5491 } else {
5492 count = q ? 4: 2;
5493 }
1dc8425e
RH
5494
5495 /* To avoid excessive duplication of ops we implement shift
5496 * by immediate using the variable shift operations.
5497 */
5498 imm = dup_const(size, shift);
9ee6e8bb
PB
5499
5500 for (pass = 0; pass < count; pass++) {
ad69471c
PB
5501 if (size == 3) {
5502 neon_load_reg64(cpu_V0, rm + pass);
5503 tcg_gen_movi_i64(cpu_V1, imm);
5504 switch (op) {
ad69471c
PB
5505 case 2: /* VRSHR */
5506 case 3: /* VRSRA */
5507 if (u)
5508 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
9ee6e8bb 5509 else
ad69471c 5510 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
9ee6e8bb 5511 break;
0322b26e 5512 case 6: /* VQSHLU */
02da0b2d
PM
5513 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
5514 cpu_V0, cpu_V1);
ad69471c 5515 break;
0322b26e
PM
5516 case 7: /* VQSHL */
5517 if (u) {
02da0b2d 5518 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
0322b26e
PM
5519 cpu_V0, cpu_V1);
5520 } else {
02da0b2d 5521 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
0322b26e
PM
5522 cpu_V0, cpu_V1);
5523 }
9ee6e8bb 5524 break;
1dc8425e
RH
5525 default:
5526 g_assert_not_reached();
9ee6e8bb 5527 }
41f6c113 5528 if (op == 3) {
ad69471c 5529 /* Accumulate. */
5371cb81 5530 neon_load_reg64(cpu_V1, rd + pass);
ad69471c 5531 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
ad69471c
PB
5532 }
5533 neon_store_reg64(cpu_V0, rd + pass);
5534 } else { /* size < 3 */
5535 /* Operands in T0 and T1. */
dd8fbd78 5536 tmp = neon_load_reg(rm, pass);
7d1b0095 5537 tmp2 = tcg_temp_new_i32();
dd8fbd78 5538 tcg_gen_movi_i32(tmp2, imm);
ad69471c 5539 switch (op) {
ad69471c
PB
5540 case 2: /* VRSHR */
5541 case 3: /* VRSRA */
5542 GEN_NEON_INTEGER_OP(rshl);
5543 break;
0322b26e 5544 case 6: /* VQSHLU */
ad69471c 5545 switch (size) {
0322b26e 5546 case 0:
02da0b2d
PM
5547 gen_helper_neon_qshlu_s8(tmp, cpu_env,
5548 tmp, tmp2);
0322b26e
PM
5549 break;
5550 case 1:
02da0b2d
PM
5551 gen_helper_neon_qshlu_s16(tmp, cpu_env,
5552 tmp, tmp2);
0322b26e
PM
5553 break;
5554 case 2:
02da0b2d
PM
5555 gen_helper_neon_qshlu_s32(tmp, cpu_env,
5556 tmp, tmp2);
0322b26e
PM
5557 break;
5558 default:
cc13115b 5559 abort();
ad69471c
PB
5560 }
5561 break;
0322b26e 5562 case 7: /* VQSHL */
02da0b2d 5563 GEN_NEON_INTEGER_OP_ENV(qshl);
0322b26e 5564 break;
1dc8425e
RH
5565 default:
5566 g_assert_not_reached();
ad69471c 5567 }
7d1b0095 5568 tcg_temp_free_i32(tmp2);
ad69471c 5569
41f6c113 5570 if (op == 3) {
ad69471c 5571 /* Accumulate. */
dd8fbd78 5572 tmp2 = neon_load_reg(rd, pass);
5371cb81 5573 gen_neon_add(size, tmp, tmp2);
7d1b0095 5574 tcg_temp_free_i32(tmp2);
ad69471c 5575 }
dd8fbd78 5576 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
5577 }
5578 } /* for pass */
5579 } else if (op < 10) {
ad69471c 5580 /* Shift by immediate and narrow:
9ee6e8bb 5581 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
0b36f4cd 5582 int input_unsigned = (op == 8) ? !u : u;
cc13115b
PM
5583 if (rm & 1) {
5584 return 1;
5585 }
9ee6e8bb
PB
5586 shift = shift - (1 << (size + 3));
5587 size++;
92cdfaeb 5588 if (size == 3) {
a7812ae4 5589 tmp64 = tcg_const_i64(shift);
92cdfaeb
PM
5590 neon_load_reg64(cpu_V0, rm);
5591 neon_load_reg64(cpu_V1, rm + 1);
5592 for (pass = 0; pass < 2; pass++) {
5593 TCGv_i64 in;
5594 if (pass == 0) {
5595 in = cpu_V0;
5596 } else {
5597 in = cpu_V1;
5598 }
ad69471c 5599 if (q) {
0b36f4cd 5600 if (input_unsigned) {
92cdfaeb 5601 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
0b36f4cd 5602 } else {
92cdfaeb 5603 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
0b36f4cd 5604 }
ad69471c 5605 } else {
0b36f4cd 5606 if (input_unsigned) {
92cdfaeb 5607 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
0b36f4cd 5608 } else {
92cdfaeb 5609 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
0b36f4cd 5610 }
ad69471c 5611 }
7d1b0095 5612 tmp = tcg_temp_new_i32();
92cdfaeb
PM
5613 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5614 neon_store_reg(rd, pass, tmp);
5615 } /* for pass */
5616 tcg_temp_free_i64(tmp64);
5617 } else {
5618 if (size == 1) {
5619 imm = (uint16_t)shift;
5620 imm |= imm << 16;
2c0262af 5621 } else {
92cdfaeb
PM
5622 /* size == 2 */
5623 imm = (uint32_t)shift;
5624 }
5625 tmp2 = tcg_const_i32(imm);
5626 tmp4 = neon_load_reg(rm + 1, 0);
5627 tmp5 = neon_load_reg(rm + 1, 1);
5628 for (pass = 0; pass < 2; pass++) {
5629 if (pass == 0) {
5630 tmp = neon_load_reg(rm, 0);
5631 } else {
5632 tmp = tmp4;
5633 }
0b36f4cd
CL
5634 gen_neon_shift_narrow(size, tmp, tmp2, q,
5635 input_unsigned);
92cdfaeb
PM
5636 if (pass == 0) {
5637 tmp3 = neon_load_reg(rm, 1);
5638 } else {
5639 tmp3 = tmp5;
5640 }
0b36f4cd
CL
5641 gen_neon_shift_narrow(size, tmp3, tmp2, q,
5642 input_unsigned);
36aa55dc 5643 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
7d1b0095
PM
5644 tcg_temp_free_i32(tmp);
5645 tcg_temp_free_i32(tmp3);
5646 tmp = tcg_temp_new_i32();
92cdfaeb
PM
5647 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5648 neon_store_reg(rd, pass, tmp);
5649 } /* for pass */
c6067f04 5650 tcg_temp_free_i32(tmp2);
b75263d6 5651 }
9ee6e8bb 5652 } else if (op == 10) {
cc13115b
PM
5653 /* VSHLL, VMOVL */
5654 if (q || (rd & 1)) {
9ee6e8bb 5655 return 1;
cc13115b 5656 }
ad69471c
PB
5657 tmp = neon_load_reg(rm, 0);
5658 tmp2 = neon_load_reg(rm, 1);
9ee6e8bb 5659 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
5660 if (pass == 1)
5661 tmp = tmp2;
5662
5663 gen_neon_widen(cpu_V0, tmp, size, u);
9ee6e8bb 5664
9ee6e8bb
PB
5665 if (shift != 0) {
5666 /* The shift is less than the width of the source
ad69471c
PB
5667 type, so we can just shift the whole register. */
5668 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
acdf01ef
CL
5669 /* Widen the result of shift: we need to clear
5670 * the potential overflow bits resulting from
5671 * left bits of the narrow input appearing as
5672 * right bits of left the neighbour narrow
5673 * input. */
ad69471c
PB
5674 if (size < 2 || !u) {
5675 uint64_t imm64;
5676 if (size == 0) {
5677 imm = (0xffu >> (8 - shift));
5678 imm |= imm << 16;
acdf01ef 5679 } else if (size == 1) {
ad69471c 5680 imm = 0xffff >> (16 - shift);
acdf01ef
CL
5681 } else {
5682 /* size == 2 */
5683 imm = 0xffffffff >> (32 - shift);
5684 }
5685 if (size < 2) {
5686 imm64 = imm | (((uint64_t)imm) << 32);
5687 } else {
5688 imm64 = imm;
9ee6e8bb 5689 }
acdf01ef 5690 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
9ee6e8bb
PB
5691 }
5692 }
ad69471c 5693 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb 5694 }
f73534a5 5695 } else if (op >= 14) {
9ee6e8bb 5696 /* VCVT fixed-point. */
c253dd78
PM
5697 TCGv_ptr fpst;
5698 TCGv_i32 shiftv;
5699 VFPGenFixPointFn *fn;
5700
cc13115b
PM
5701 if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
5702 return 1;
5703 }
c253dd78
PM
5704
5705 if (!(op & 1)) {
5706 if (u) {
5707 fn = gen_helper_vfp_ultos;
5708 } else {
5709 fn = gen_helper_vfp_sltos;
5710 }
5711 } else {
5712 if (u) {
5713 fn = gen_helper_vfp_touls_round_to_zero;
5714 } else {
5715 fn = gen_helper_vfp_tosls_round_to_zero;
5716 }
5717 }
5718
f73534a5
PM
5719 /* We have already masked out the must-be-1 top bit of imm6,
5720 * hence this 32-shift where the ARM ARM has 64-imm6.
5721 */
5722 shift = 32 - shift;
c253dd78
PM
5723 fpst = get_fpstatus_ptr(1);
5724 shiftv = tcg_const_i32(shift);
9ee6e8bb 5725 for (pass = 0; pass < (q ? 4 : 2); pass++) {
c253dd78
PM
5726 TCGv_i32 tmpf = neon_load_reg(rm, pass);
5727 fn(tmpf, tmpf, shiftv, fpst);
5728 neon_store_reg(rd, pass, tmpf);
2c0262af 5729 }
c253dd78
PM
5730 tcg_temp_free_ptr(fpst);
5731 tcg_temp_free_i32(shiftv);
2c0262af 5732 } else {
9ee6e8bb
PB
5733 return 1;
5734 }
5735 } else { /* (insn & 0x00380080) == 0 */
246fa4ac
RH
5736 int invert, reg_ofs, vec_size;
5737
7d80fee5
PM
5738 if (q && (rd & 1)) {
5739 return 1;
5740 }
9ee6e8bb
PB
5741
5742 op = (insn >> 8) & 0xf;
5743 /* One register and immediate. */
5744 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
5745 invert = (insn & (1 << 5)) != 0;
7d80fee5
PM
5746 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
5747 * We choose to not special-case this and will behave as if a
5748 * valid constant encoding of 0 had been given.
5749 */
9ee6e8bb
PB
5750 switch (op) {
5751 case 0: case 1:
5752 /* no-op */
5753 break;
5754 case 2: case 3:
5755 imm <<= 8;
5756 break;
5757 case 4: case 5:
5758 imm <<= 16;
5759 break;
5760 case 6: case 7:
5761 imm <<= 24;
5762 break;
5763 case 8: case 9:
5764 imm |= imm << 16;
5765 break;
5766 case 10: case 11:
5767 imm = (imm << 8) | (imm << 24);
5768 break;
5769 case 12:
8e31209e 5770 imm = (imm << 8) | 0xff;
9ee6e8bb
PB
5771 break;
5772 case 13:
5773 imm = (imm << 16) | 0xffff;
5774 break;
5775 case 14:
5776 imm |= (imm << 8) | (imm << 16) | (imm << 24);
246fa4ac 5777 if (invert) {
9ee6e8bb 5778 imm = ~imm;
246fa4ac 5779 }
9ee6e8bb
PB
5780 break;
5781 case 15:
7d80fee5
PM
5782 if (invert) {
5783 return 1;
5784 }
9ee6e8bb
PB
5785 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
5786 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
5787 break;
5788 }
246fa4ac 5789 if (invert) {
9ee6e8bb 5790 imm = ~imm;
246fa4ac 5791 }
9ee6e8bb 5792
246fa4ac
RH
5793 reg_ofs = neon_reg_offset(rd, 0);
5794 vec_size = q ? 16 : 8;
5795
5796 if (op & 1 && op < 12) {
5797 if (invert) {
5798 /* The immediate value has already been inverted,
5799 * so BIC becomes AND.
5800 */
5801 tcg_gen_gvec_andi(MO_32, reg_ofs, reg_ofs, imm,
5802 vec_size, vec_size);
9ee6e8bb 5803 } else {
246fa4ac
RH
5804 tcg_gen_gvec_ori(MO_32, reg_ofs, reg_ofs, imm,
5805 vec_size, vec_size);
5806 }
5807 } else {
5808 /* VMOV, VMVN. */
5809 if (op == 14 && invert) {
5810 TCGv_i64 t64 = tcg_temp_new_i64();
5811
5812 for (pass = 0; pass <= q; ++pass) {
5813 uint64_t val = 0;
a5a14945 5814 int n;
246fa4ac
RH
5815
5816 for (n = 0; n < 8; n++) {
5817 if (imm & (1 << (n + pass * 8))) {
5818 val |= 0xffull << (n * 8);
5819 }
9ee6e8bb 5820 }
246fa4ac
RH
5821 tcg_gen_movi_i64(t64, val);
5822 neon_store_reg64(t64, rd + pass);
9ee6e8bb 5823 }
246fa4ac
RH
5824 tcg_temp_free_i64(t64);
5825 } else {
5826 tcg_gen_gvec_dup32i(reg_ofs, vec_size, vec_size, imm);
9ee6e8bb
PB
5827 }
5828 }
5829 }
e4b3861d 5830 } else { /* (insn & 0x00800010 == 0x00800000) */
9ee6e8bb
PB
5831 if (size != 3) {
5832 op = (insn >> 8) & 0xf;
5833 if ((insn & (1 << 6)) == 0) {
5834 /* Three registers of different lengths. */
5835 int src1_wide;
5836 int src2_wide;
5837 int prewiden;
526d0096
PM
5838 /* undefreq: bit 0 : UNDEF if size == 0
5839 * bit 1 : UNDEF if size == 1
5840 * bit 2 : UNDEF if size == 2
5841 * bit 3 : UNDEF if U == 1
5842 * Note that [2:0] set implies 'always UNDEF'
695272dc
PM
5843 */
5844 int undefreq;
5845 /* prewiden, src1_wide, src2_wide, undefreq */
5846 static const int neon_3reg_wide[16][4] = {
5847 {1, 0, 0, 0}, /* VADDL */
5848 {1, 1, 0, 0}, /* VADDW */
5849 {1, 0, 0, 0}, /* VSUBL */
5850 {1, 1, 0, 0}, /* VSUBW */
5851 {0, 1, 1, 0}, /* VADDHN */
5852 {0, 0, 0, 0}, /* VABAL */
5853 {0, 1, 1, 0}, /* VSUBHN */
5854 {0, 0, 0, 0}, /* VABDL */
5855 {0, 0, 0, 0}, /* VMLAL */
526d0096 5856 {0, 0, 0, 9}, /* VQDMLAL */
695272dc 5857 {0, 0, 0, 0}, /* VMLSL */
526d0096 5858 {0, 0, 0, 9}, /* VQDMLSL */
695272dc 5859 {0, 0, 0, 0}, /* Integer VMULL */
526d0096 5860 {0, 0, 0, 1}, /* VQDMULL */
4e624eda 5861 {0, 0, 0, 0xa}, /* Polynomial VMULL */
526d0096 5862 {0, 0, 0, 7}, /* Reserved: always UNDEF */
9ee6e8bb
PB
5863 };
5864
5865 prewiden = neon_3reg_wide[op][0];
5866 src1_wide = neon_3reg_wide[op][1];
5867 src2_wide = neon_3reg_wide[op][2];
695272dc 5868 undefreq = neon_3reg_wide[op][3];
9ee6e8bb 5869
526d0096
PM
5870 if ((undefreq & (1 << size)) ||
5871 ((undefreq & 8) && u)) {
695272dc
PM
5872 return 1;
5873 }
5874 if ((src1_wide && (rn & 1)) ||
5875 (src2_wide && (rm & 1)) ||
5876 (!src2_wide && (rd & 1))) {
ad69471c 5877 return 1;
695272dc 5878 }
ad69471c 5879
4e624eda
PM
5880 /* Handle VMULL.P64 (Polynomial 64x64 to 128 bit multiply)
5881 * outside the loop below as it only performs a single pass.
5882 */
5883 if (op == 14 && size == 2) {
5884 TCGv_i64 tcg_rn, tcg_rm, tcg_rd;
5885
962fcbf2 5886 if (!dc_isar_feature(aa32_pmull, s)) {
4e624eda
PM
5887 return 1;
5888 }
5889 tcg_rn = tcg_temp_new_i64();
5890 tcg_rm = tcg_temp_new_i64();
5891 tcg_rd = tcg_temp_new_i64();
5892 neon_load_reg64(tcg_rn, rn);
5893 neon_load_reg64(tcg_rm, rm);
5894 gen_helper_neon_pmull_64_lo(tcg_rd, tcg_rn, tcg_rm);
5895 neon_store_reg64(tcg_rd, rd);
5896 gen_helper_neon_pmull_64_hi(tcg_rd, tcg_rn, tcg_rm);
5897 neon_store_reg64(tcg_rd, rd + 1);
5898 tcg_temp_free_i64(tcg_rn);
5899 tcg_temp_free_i64(tcg_rm);
5900 tcg_temp_free_i64(tcg_rd);
5901 return 0;
5902 }
5903
9ee6e8bb
PB
5904 /* Avoid overlapping operands. Wide source operands are
5905 always aligned so will never overlap with wide
5906 destinations in problematic ways. */
8f8e3aa4 5907 if (rd == rm && !src2_wide) {
dd8fbd78
FN
5908 tmp = neon_load_reg(rm, 1);
5909 neon_store_scratch(2, tmp);
8f8e3aa4 5910 } else if (rd == rn && !src1_wide) {
dd8fbd78
FN
5911 tmp = neon_load_reg(rn, 1);
5912 neon_store_scratch(2, tmp);
9ee6e8bb 5913 }
f764718d 5914 tmp3 = NULL;
9ee6e8bb 5915 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
5916 if (src1_wide) {
5917 neon_load_reg64(cpu_V0, rn + pass);
f764718d 5918 tmp = NULL;
9ee6e8bb 5919 } else {
ad69471c 5920 if (pass == 1 && rd == rn) {
dd8fbd78 5921 tmp = neon_load_scratch(2);
9ee6e8bb 5922 } else {
ad69471c
PB
5923 tmp = neon_load_reg(rn, pass);
5924 }
5925 if (prewiden) {
5926 gen_neon_widen(cpu_V0, tmp, size, u);
9ee6e8bb
PB
5927 }
5928 }
ad69471c
PB
5929 if (src2_wide) {
5930 neon_load_reg64(cpu_V1, rm + pass);
f764718d 5931 tmp2 = NULL;
9ee6e8bb 5932 } else {
ad69471c 5933 if (pass == 1 && rd == rm) {
dd8fbd78 5934 tmp2 = neon_load_scratch(2);
9ee6e8bb 5935 } else {
ad69471c
PB
5936 tmp2 = neon_load_reg(rm, pass);
5937 }
5938 if (prewiden) {
5939 gen_neon_widen(cpu_V1, tmp2, size, u);
9ee6e8bb 5940 }
9ee6e8bb
PB
5941 }
5942 switch (op) {
5943 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
ad69471c 5944 gen_neon_addl(size);
9ee6e8bb 5945 break;
79b0e534 5946 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
ad69471c 5947 gen_neon_subl(size);
9ee6e8bb
PB
5948 break;
5949 case 5: case 7: /* VABAL, VABDL */
5950 switch ((size << 1) | u) {
ad69471c
PB
5951 case 0:
5952 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
5953 break;
5954 case 1:
5955 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
5956 break;
5957 case 2:
5958 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
5959 break;
5960 case 3:
5961 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
5962 break;
5963 case 4:
5964 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
5965 break;
5966 case 5:
5967 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
5968 break;
9ee6e8bb
PB
5969 default: abort();
5970 }
7d1b0095
PM
5971 tcg_temp_free_i32(tmp2);
5972 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
5973 break;
5974 case 8: case 9: case 10: case 11: case 12: case 13:
5975 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
ad69471c 5976 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
9ee6e8bb
PB
5977 break;
5978 case 14: /* Polynomial VMULL */
e5ca24cb 5979 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
7d1b0095
PM
5980 tcg_temp_free_i32(tmp2);
5981 tcg_temp_free_i32(tmp);
e5ca24cb 5982 break;
695272dc
PM
5983 default: /* 15 is RESERVED: caught earlier */
5984 abort();
9ee6e8bb 5985 }
ebcd88ce
PM
5986 if (op == 13) {
5987 /* VQDMULL */
5988 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5989 neon_store_reg64(cpu_V0, rd + pass);
5990 } else if (op == 5 || (op >= 8 && op <= 11)) {
9ee6e8bb 5991 /* Accumulate. */
ebcd88ce 5992 neon_load_reg64(cpu_V1, rd + pass);
9ee6e8bb 5993 switch (op) {
4dc064e6
PM
5994 case 10: /* VMLSL */
5995 gen_neon_negl(cpu_V0, size);
5996 /* Fall through */
5997 case 5: case 8: /* VABAL, VMLAL */
ad69471c 5998 gen_neon_addl(size);
9ee6e8bb
PB
5999 break;
6000 case 9: case 11: /* VQDMLAL, VQDMLSL */
ad69471c 6001 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4dc064e6
PM
6002 if (op == 11) {
6003 gen_neon_negl(cpu_V0, size);
6004 }
ad69471c
PB
6005 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
6006 break;
9ee6e8bb
PB
6007 default:
6008 abort();
6009 }
ad69471c 6010 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
6011 } else if (op == 4 || op == 6) {
6012 /* Narrowing operation. */
7d1b0095 6013 tmp = tcg_temp_new_i32();
79b0e534 6014 if (!u) {
9ee6e8bb 6015 switch (size) {
ad69471c
PB
6016 case 0:
6017 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
6018 break;
6019 case 1:
6020 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
6021 break;
6022 case 2:
6023 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
ecc7b3aa 6024 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
ad69471c 6025 break;
9ee6e8bb
PB
6026 default: abort();
6027 }
6028 } else {
6029 switch (size) {
ad69471c
PB
6030 case 0:
6031 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
6032 break;
6033 case 1:
6034 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
6035 break;
6036 case 2:
6037 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
6038 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
ecc7b3aa 6039 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
ad69471c 6040 break;
9ee6e8bb
PB
6041 default: abort();
6042 }
6043 }
ad69471c
PB
6044 if (pass == 0) {
6045 tmp3 = tmp;
6046 } else {
6047 neon_store_reg(rd, 0, tmp3);
6048 neon_store_reg(rd, 1, tmp);
6049 }
9ee6e8bb
PB
6050 } else {
6051 /* Write back the result. */
ad69471c 6052 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
6053 }
6054 }
6055 } else {
3e3326df
PM
6056 /* Two registers and a scalar. NB that for ops of this form
6057 * the ARM ARM labels bit 24 as Q, but it is in our variable
6058 * 'u', not 'q'.
6059 */
6060 if (size == 0) {
6061 return 1;
6062 }
9ee6e8bb 6063 switch (op) {
9ee6e8bb 6064 case 1: /* Float VMLA scalar */
9ee6e8bb 6065 case 5: /* Floating point VMLS scalar */
9ee6e8bb 6066 case 9: /* Floating point VMUL scalar */
3e3326df
PM
6067 if (size == 1) {
6068 return 1;
6069 }
6070 /* fall through */
6071 case 0: /* Integer VMLA scalar */
6072 case 4: /* Integer VMLS scalar */
6073 case 8: /* Integer VMUL scalar */
9ee6e8bb
PB
6074 case 12: /* VQDMULH scalar */
6075 case 13: /* VQRDMULH scalar */
3e3326df
PM
6076 if (u && ((rd | rn) & 1)) {
6077 return 1;
6078 }
dd8fbd78
FN
6079 tmp = neon_get_scalar(size, rm);
6080 neon_store_scratch(0, tmp);
9ee6e8bb 6081 for (pass = 0; pass < (u ? 4 : 2); pass++) {
dd8fbd78
FN
6082 tmp = neon_load_scratch(0);
6083 tmp2 = neon_load_reg(rn, pass);
9ee6e8bb
PB
6084 if (op == 12) {
6085 if (size == 1) {
02da0b2d 6086 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 6087 } else {
02da0b2d 6088 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
9ee6e8bb
PB
6089 }
6090 } else if (op == 13) {
6091 if (size == 1) {
02da0b2d 6092 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 6093 } else {
02da0b2d 6094 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
9ee6e8bb
PB
6095 }
6096 } else if (op & 1) {
aa47cfdd
PM
6097 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6098 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
6099 tcg_temp_free_ptr(fpstatus);
9ee6e8bb
PB
6100 } else {
6101 switch (size) {
dd8fbd78
FN
6102 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
6103 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
6104 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
3e3326df 6105 default: abort();
9ee6e8bb
PB
6106 }
6107 }
7d1b0095 6108 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
6109 if (op < 8) {
6110 /* Accumulate. */
dd8fbd78 6111 tmp2 = neon_load_reg(rd, pass);
9ee6e8bb
PB
6112 switch (op) {
6113 case 0:
dd8fbd78 6114 gen_neon_add(size, tmp, tmp2);
9ee6e8bb
PB
6115 break;
6116 case 1:
aa47cfdd
PM
6117 {
6118 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6119 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
6120 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6121 break;
aa47cfdd 6122 }
9ee6e8bb 6123 case 4:
dd8fbd78 6124 gen_neon_rsb(size, tmp, tmp2);
9ee6e8bb
PB
6125 break;
6126 case 5:
aa47cfdd
PM
6127 {
6128 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6129 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
6130 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6131 break;
aa47cfdd 6132 }
9ee6e8bb
PB
6133 default:
6134 abort();
6135 }
7d1b0095 6136 tcg_temp_free_i32(tmp2);
9ee6e8bb 6137 }
dd8fbd78 6138 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
6139 }
6140 break;
9ee6e8bb 6141 case 3: /* VQDMLAL scalar */
9ee6e8bb 6142 case 7: /* VQDMLSL scalar */
9ee6e8bb 6143 case 11: /* VQDMULL scalar */
3e3326df 6144 if (u == 1) {
ad69471c 6145 return 1;
3e3326df
PM
6146 }
6147 /* fall through */
6148 case 2: /* VMLAL sclar */
6149 case 6: /* VMLSL scalar */
6150 case 10: /* VMULL scalar */
6151 if (rd & 1) {
6152 return 1;
6153 }
dd8fbd78 6154 tmp2 = neon_get_scalar(size, rm);
c6067f04
CL
6155 /* We need a copy of tmp2 because gen_neon_mull
6156 * deletes it during pass 0. */
7d1b0095 6157 tmp4 = tcg_temp_new_i32();
c6067f04 6158 tcg_gen_mov_i32(tmp4, tmp2);
dd8fbd78 6159 tmp3 = neon_load_reg(rn, 1);
ad69471c 6160
9ee6e8bb 6161 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
6162 if (pass == 0) {
6163 tmp = neon_load_reg(rn, 0);
9ee6e8bb 6164 } else {
dd8fbd78 6165 tmp = tmp3;
c6067f04 6166 tmp2 = tmp4;
9ee6e8bb 6167 }
ad69471c 6168 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
ad69471c
PB
6169 if (op != 11) {
6170 neon_load_reg64(cpu_V1, rd + pass);
9ee6e8bb 6171 }
9ee6e8bb 6172 switch (op) {
4dc064e6
PM
6173 case 6:
6174 gen_neon_negl(cpu_V0, size);
6175 /* Fall through */
6176 case 2:
ad69471c 6177 gen_neon_addl(size);
9ee6e8bb
PB
6178 break;
6179 case 3: case 7:
ad69471c 6180 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4dc064e6
PM
6181 if (op == 7) {
6182 gen_neon_negl(cpu_V0, size);
6183 }
ad69471c 6184 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
9ee6e8bb
PB
6185 break;
6186 case 10:
6187 /* no-op */
6188 break;
6189 case 11:
ad69471c 6190 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
9ee6e8bb
PB
6191 break;
6192 default:
6193 abort();
6194 }
ad69471c 6195 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb 6196 }
61adacc8
RH
6197 break;
6198 case 14: /* VQRDMLAH scalar */
6199 case 15: /* VQRDMLSH scalar */
6200 {
6201 NeonGenThreeOpEnvFn *fn;
dd8fbd78 6202
962fcbf2 6203 if (!dc_isar_feature(aa32_rdm, s)) {
61adacc8
RH
6204 return 1;
6205 }
6206 if (u && ((rd | rn) & 1)) {
6207 return 1;
6208 }
6209 if (op == 14) {
6210 if (size == 1) {
6211 fn = gen_helper_neon_qrdmlah_s16;
6212 } else {
6213 fn = gen_helper_neon_qrdmlah_s32;
6214 }
6215 } else {
6216 if (size == 1) {
6217 fn = gen_helper_neon_qrdmlsh_s16;
6218 } else {
6219 fn = gen_helper_neon_qrdmlsh_s32;
6220 }
6221 }
dd8fbd78 6222
61adacc8
RH
6223 tmp2 = neon_get_scalar(size, rm);
6224 for (pass = 0; pass < (u ? 4 : 2); pass++) {
6225 tmp = neon_load_reg(rn, pass);
6226 tmp3 = neon_load_reg(rd, pass);
6227 fn(tmp, cpu_env, tmp, tmp2, tmp3);
6228 tcg_temp_free_i32(tmp3);
6229 neon_store_reg(rd, pass, tmp);
6230 }
6231 tcg_temp_free_i32(tmp2);
6232 }
9ee6e8bb 6233 break;
61adacc8
RH
6234 default:
6235 g_assert_not_reached();
9ee6e8bb
PB
6236 }
6237 }
6238 } else { /* size == 3 */
6239 if (!u) {
6240 /* Extract. */
9ee6e8bb 6241 imm = (insn >> 8) & 0xf;
ad69471c
PB
6242
6243 if (imm > 7 && !q)
6244 return 1;
6245
52579ea1
PM
6246 if (q && ((rd | rn | rm) & 1)) {
6247 return 1;
6248 }
6249
ad69471c
PB
6250 if (imm == 0) {
6251 neon_load_reg64(cpu_V0, rn);
6252 if (q) {
6253 neon_load_reg64(cpu_V1, rn + 1);
9ee6e8bb 6254 }
ad69471c
PB
6255 } else if (imm == 8) {
6256 neon_load_reg64(cpu_V0, rn + 1);
6257 if (q) {
6258 neon_load_reg64(cpu_V1, rm);
9ee6e8bb 6259 }
ad69471c 6260 } else if (q) {
a7812ae4 6261 tmp64 = tcg_temp_new_i64();
ad69471c
PB
6262 if (imm < 8) {
6263 neon_load_reg64(cpu_V0, rn);
a7812ae4 6264 neon_load_reg64(tmp64, rn + 1);
ad69471c
PB
6265 } else {
6266 neon_load_reg64(cpu_V0, rn + 1);
a7812ae4 6267 neon_load_reg64(tmp64, rm);
ad69471c
PB
6268 }
6269 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
a7812ae4 6270 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
ad69471c
PB
6271 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6272 if (imm < 8) {
6273 neon_load_reg64(cpu_V1, rm);
9ee6e8bb 6274 } else {
ad69471c
PB
6275 neon_load_reg64(cpu_V1, rm + 1);
6276 imm -= 8;
9ee6e8bb 6277 }
ad69471c 6278 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
a7812ae4
PB
6279 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
6280 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
b75263d6 6281 tcg_temp_free_i64(tmp64);
ad69471c 6282 } else {
a7812ae4 6283 /* BUGFIX */
ad69471c 6284 neon_load_reg64(cpu_V0, rn);
a7812ae4 6285 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
ad69471c 6286 neon_load_reg64(cpu_V1, rm);
a7812ae4 6287 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
ad69471c
PB
6288 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6289 }
6290 neon_store_reg64(cpu_V0, rd);
6291 if (q) {
6292 neon_store_reg64(cpu_V1, rd + 1);
9ee6e8bb
PB
6293 }
6294 } else if ((insn & (1 << 11)) == 0) {
6295 /* Two register misc. */
6296 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
6297 size = (insn >> 18) & 3;
600b828c
PM
6298 /* UNDEF for unknown op values and bad op-size combinations */
6299 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
6300 return 1;
6301 }
fe8fcf3d
PM
6302 if (neon_2rm_is_v8_op(op) &&
6303 !arm_dc_feature(s, ARM_FEATURE_V8)) {
6304 return 1;
6305 }
fc2a9b37
PM
6306 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
6307 q && ((rm | rd) & 1)) {
6308 return 1;
6309 }
9ee6e8bb 6310 switch (op) {
600b828c 6311 case NEON_2RM_VREV64:
9ee6e8bb 6312 for (pass = 0; pass < (q ? 2 : 1); pass++) {
dd8fbd78
FN
6313 tmp = neon_load_reg(rm, pass * 2);
6314 tmp2 = neon_load_reg(rm, pass * 2 + 1);
9ee6e8bb 6315 switch (size) {
dd8fbd78
FN
6316 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6317 case 1: gen_swap_half(tmp); break;
9ee6e8bb
PB
6318 case 2: /* no-op */ break;
6319 default: abort();
6320 }
dd8fbd78 6321 neon_store_reg(rd, pass * 2 + 1, tmp);
9ee6e8bb 6322 if (size == 2) {
dd8fbd78 6323 neon_store_reg(rd, pass * 2, tmp2);
9ee6e8bb 6324 } else {
9ee6e8bb 6325 switch (size) {
dd8fbd78
FN
6326 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
6327 case 1: gen_swap_half(tmp2); break;
9ee6e8bb
PB
6328 default: abort();
6329 }
dd8fbd78 6330 neon_store_reg(rd, pass * 2, tmp2);
9ee6e8bb
PB
6331 }
6332 }
6333 break;
600b828c
PM
6334 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
6335 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
ad69471c
PB
6336 for (pass = 0; pass < q + 1; pass++) {
6337 tmp = neon_load_reg(rm, pass * 2);
6338 gen_neon_widen(cpu_V0, tmp, size, op & 1);
6339 tmp = neon_load_reg(rm, pass * 2 + 1);
6340 gen_neon_widen(cpu_V1, tmp, size, op & 1);
6341 switch (size) {
6342 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
6343 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
6344 case 2: tcg_gen_add_i64(CPU_V001); break;
6345 default: abort();
6346 }
600b828c 6347 if (op >= NEON_2RM_VPADAL) {
9ee6e8bb 6348 /* Accumulate. */
ad69471c
PB
6349 neon_load_reg64(cpu_V1, rd + pass);
6350 gen_neon_addl(size);
9ee6e8bb 6351 }
ad69471c 6352 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
6353 }
6354 break;
600b828c 6355 case NEON_2RM_VTRN:
9ee6e8bb 6356 if (size == 2) {
a5a14945 6357 int n;
9ee6e8bb 6358 for (n = 0; n < (q ? 4 : 2); n += 2) {
dd8fbd78
FN
6359 tmp = neon_load_reg(rm, n);
6360 tmp2 = neon_load_reg(rd, n + 1);
6361 neon_store_reg(rm, n, tmp2);
6362 neon_store_reg(rd, n + 1, tmp);
9ee6e8bb
PB
6363 }
6364 } else {
6365 goto elementwise;
6366 }
6367 break;
600b828c 6368 case NEON_2RM_VUZP:
02acedf9 6369 if (gen_neon_unzip(rd, rm, size, q)) {
9ee6e8bb 6370 return 1;
9ee6e8bb
PB
6371 }
6372 break;
600b828c 6373 case NEON_2RM_VZIP:
d68a6f3a 6374 if (gen_neon_zip(rd, rm, size, q)) {
9ee6e8bb 6375 return 1;
9ee6e8bb
PB
6376 }
6377 break;
600b828c
PM
6378 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
6379 /* also VQMOVUN; op field and mnemonics don't line up */
fc2a9b37
PM
6380 if (rm & 1) {
6381 return 1;
6382 }
f764718d 6383 tmp2 = NULL;
9ee6e8bb 6384 for (pass = 0; pass < 2; pass++) {
ad69471c 6385 neon_load_reg64(cpu_V0, rm + pass);
7d1b0095 6386 tmp = tcg_temp_new_i32();
600b828c
PM
6387 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
6388 tmp, cpu_V0);
ad69471c
PB
6389 if (pass == 0) {
6390 tmp2 = tmp;
6391 } else {
6392 neon_store_reg(rd, 0, tmp2);
6393 neon_store_reg(rd, 1, tmp);
9ee6e8bb 6394 }
9ee6e8bb
PB
6395 }
6396 break;
600b828c 6397 case NEON_2RM_VSHLL:
fc2a9b37 6398 if (q || (rd & 1)) {
9ee6e8bb 6399 return 1;
600b828c 6400 }
ad69471c
PB
6401 tmp = neon_load_reg(rm, 0);
6402 tmp2 = neon_load_reg(rm, 1);
9ee6e8bb 6403 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
6404 if (pass == 1)
6405 tmp = tmp2;
6406 gen_neon_widen(cpu_V0, tmp, size, 1);
30d11a2a 6407 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
ad69471c 6408 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
6409 }
6410 break;
600b828c 6411 case NEON_2RM_VCVT_F16_F32:
486624fc
AB
6412 {
6413 TCGv_ptr fpst;
6414 TCGv_i32 ahp;
6415
602f6e42 6416 if (!dc_isar_feature(aa32_fp16_spconv, s) ||
fc2a9b37
PM
6417 q || (rm & 1)) {
6418 return 1;
6419 }
486624fc
AB
6420 fpst = get_fpstatus_ptr(true);
6421 ahp = get_ahp_flag();
58f2682e
PM
6422 tmp = neon_load_reg(rm, 0);
6423 gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp);
6424 tmp2 = neon_load_reg(rm, 1);
6425 gen_helper_vfp_fcvt_f32_to_f16(tmp2, tmp2, fpst, ahp);
60011498
PB
6426 tcg_gen_shli_i32(tmp2, tmp2, 16);
6427 tcg_gen_or_i32(tmp2, tmp2, tmp);
58f2682e
PM
6428 tcg_temp_free_i32(tmp);
6429 tmp = neon_load_reg(rm, 2);
6430 gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp);
6431 tmp3 = neon_load_reg(rm, 3);
60011498 6432 neon_store_reg(rd, 0, tmp2);
58f2682e
PM
6433 gen_helper_vfp_fcvt_f32_to_f16(tmp3, tmp3, fpst, ahp);
6434 tcg_gen_shli_i32(tmp3, tmp3, 16);
6435 tcg_gen_or_i32(tmp3, tmp3, tmp);
6436 neon_store_reg(rd, 1, tmp3);
7d1b0095 6437 tcg_temp_free_i32(tmp);
486624fc
AB
6438 tcg_temp_free_i32(ahp);
6439 tcg_temp_free_ptr(fpst);
60011498 6440 break;
486624fc 6441 }
600b828c 6442 case NEON_2RM_VCVT_F32_F16:
486624fc
AB
6443 {
6444 TCGv_ptr fpst;
6445 TCGv_i32 ahp;
602f6e42 6446 if (!dc_isar_feature(aa32_fp16_spconv, s) ||
fc2a9b37
PM
6447 q || (rd & 1)) {
6448 return 1;
6449 }
486624fc
AB
6450 fpst = get_fpstatus_ptr(true);
6451 ahp = get_ahp_flag();
7d1b0095 6452 tmp3 = tcg_temp_new_i32();
60011498
PB
6453 tmp = neon_load_reg(rm, 0);
6454 tmp2 = neon_load_reg(rm, 1);
6455 tcg_gen_ext16u_i32(tmp3, tmp);
b66f6b99
PM
6456 gen_helper_vfp_fcvt_f16_to_f32(tmp3, tmp3, fpst, ahp);
6457 neon_store_reg(rd, 0, tmp3);
6458 tcg_gen_shri_i32(tmp, tmp, 16);
6459 gen_helper_vfp_fcvt_f16_to_f32(tmp, tmp, fpst, ahp);
6460 neon_store_reg(rd, 1, tmp);
6461 tmp3 = tcg_temp_new_i32();
60011498 6462 tcg_gen_ext16u_i32(tmp3, tmp2);
b66f6b99
PM
6463 gen_helper_vfp_fcvt_f16_to_f32(tmp3, tmp3, fpst, ahp);
6464 neon_store_reg(rd, 2, tmp3);
6465 tcg_gen_shri_i32(tmp2, tmp2, 16);
6466 gen_helper_vfp_fcvt_f16_to_f32(tmp2, tmp2, fpst, ahp);
6467 neon_store_reg(rd, 3, tmp2);
486624fc
AB
6468 tcg_temp_free_i32(ahp);
6469 tcg_temp_free_ptr(fpst);
60011498 6470 break;
486624fc 6471 }
9d935509 6472 case NEON_2RM_AESE: case NEON_2RM_AESMC:
962fcbf2 6473 if (!dc_isar_feature(aa32_aes, s) || ((rm | rd) & 1)) {
9d935509
AB
6474 return 1;
6475 }
1a66ac61
RH
6476 ptr1 = vfp_reg_ptr(true, rd);
6477 ptr2 = vfp_reg_ptr(true, rm);
9d935509
AB
6478
6479 /* Bit 6 is the lowest opcode bit; it distinguishes between
6480 * encryption (AESE/AESMC) and decryption (AESD/AESIMC)
6481 */
6482 tmp3 = tcg_const_i32(extract32(insn, 6, 1));
6483
6484 if (op == NEON_2RM_AESE) {
1a66ac61 6485 gen_helper_crypto_aese(ptr1, ptr2, tmp3);
9d935509 6486 } else {
1a66ac61 6487 gen_helper_crypto_aesmc(ptr1, ptr2, tmp3);
9d935509 6488 }
1a66ac61
RH
6489 tcg_temp_free_ptr(ptr1);
6490 tcg_temp_free_ptr(ptr2);
9d935509
AB
6491 tcg_temp_free_i32(tmp3);
6492 break;
f1ecb913 6493 case NEON_2RM_SHA1H:
962fcbf2 6494 if (!dc_isar_feature(aa32_sha1, s) || ((rm | rd) & 1)) {
f1ecb913
AB
6495 return 1;
6496 }
1a66ac61
RH
6497 ptr1 = vfp_reg_ptr(true, rd);
6498 ptr2 = vfp_reg_ptr(true, rm);
f1ecb913 6499
1a66ac61 6500 gen_helper_crypto_sha1h(ptr1, ptr2);
f1ecb913 6501
1a66ac61
RH
6502 tcg_temp_free_ptr(ptr1);
6503 tcg_temp_free_ptr(ptr2);
f1ecb913
AB
6504 break;
6505 case NEON_2RM_SHA1SU1:
6506 if ((rm | rd) & 1) {
6507 return 1;
6508 }
6509 /* bit 6 (q): set -> SHA256SU0, cleared -> SHA1SU1 */
6510 if (q) {
962fcbf2 6511 if (!dc_isar_feature(aa32_sha2, s)) {
f1ecb913
AB
6512 return 1;
6513 }
962fcbf2 6514 } else if (!dc_isar_feature(aa32_sha1, s)) {
f1ecb913
AB
6515 return 1;
6516 }
1a66ac61
RH
6517 ptr1 = vfp_reg_ptr(true, rd);
6518 ptr2 = vfp_reg_ptr(true, rm);
f1ecb913 6519 if (q) {
1a66ac61 6520 gen_helper_crypto_sha256su0(ptr1, ptr2);
f1ecb913 6521 } else {
1a66ac61 6522 gen_helper_crypto_sha1su1(ptr1, ptr2);
f1ecb913 6523 }
1a66ac61
RH
6524 tcg_temp_free_ptr(ptr1);
6525 tcg_temp_free_ptr(ptr2);
f1ecb913 6526 break;
4bf940be
RH
6527
6528 case NEON_2RM_VMVN:
6529 tcg_gen_gvec_not(0, rd_ofs, rm_ofs, vec_size, vec_size);
6530 break;
6531 case NEON_2RM_VNEG:
6532 tcg_gen_gvec_neg(size, rd_ofs, rm_ofs, vec_size, vec_size);
6533 break;
4e027a71
RH
6534 case NEON_2RM_VABS:
6535 tcg_gen_gvec_abs(size, rd_ofs, rm_ofs, vec_size, vec_size);
6536 break;
4bf940be 6537
9ee6e8bb
PB
6538 default:
6539 elementwise:
6540 for (pass = 0; pass < (q ? 4 : 2); pass++) {
60737ed5 6541 tmp = neon_load_reg(rm, pass);
9ee6e8bb 6542 switch (op) {
600b828c 6543 case NEON_2RM_VREV32:
9ee6e8bb 6544 switch (size) {
dd8fbd78
FN
6545 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6546 case 1: gen_swap_half(tmp); break;
600b828c 6547 default: abort();
9ee6e8bb
PB
6548 }
6549 break;
600b828c 6550 case NEON_2RM_VREV16:
dd8fbd78 6551 gen_rev16(tmp);
9ee6e8bb 6552 break;
600b828c 6553 case NEON_2RM_VCLS:
9ee6e8bb 6554 switch (size) {
dd8fbd78
FN
6555 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
6556 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
6557 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
600b828c 6558 default: abort();
9ee6e8bb
PB
6559 }
6560 break;
600b828c 6561 case NEON_2RM_VCLZ:
9ee6e8bb 6562 switch (size) {
dd8fbd78
FN
6563 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
6564 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
7539a012 6565 case 2: tcg_gen_clzi_i32(tmp, tmp, 32); break;
600b828c 6566 default: abort();
9ee6e8bb
PB
6567 }
6568 break;
600b828c 6569 case NEON_2RM_VCNT:
dd8fbd78 6570 gen_helper_neon_cnt_u8(tmp, tmp);
9ee6e8bb 6571 break;
600b828c 6572 case NEON_2RM_VQABS:
9ee6e8bb 6573 switch (size) {
02da0b2d
PM
6574 case 0:
6575 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
6576 break;
6577 case 1:
6578 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
6579 break;
6580 case 2:
6581 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
6582 break;
600b828c 6583 default: abort();
9ee6e8bb
PB
6584 }
6585 break;
600b828c 6586 case NEON_2RM_VQNEG:
9ee6e8bb 6587 switch (size) {
02da0b2d
PM
6588 case 0:
6589 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
6590 break;
6591 case 1:
6592 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
6593 break;
6594 case 2:
6595 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
6596 break;
600b828c 6597 default: abort();
9ee6e8bb
PB
6598 }
6599 break;
600b828c 6600 case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
dd8fbd78 6601 tmp2 = tcg_const_i32(0);
9ee6e8bb 6602 switch(size) {
dd8fbd78
FN
6603 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
6604 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
6605 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
600b828c 6606 default: abort();
9ee6e8bb 6607 }
39d5492a 6608 tcg_temp_free_i32(tmp2);
600b828c 6609 if (op == NEON_2RM_VCLE0) {
dd8fbd78 6610 tcg_gen_not_i32(tmp, tmp);
600b828c 6611 }
9ee6e8bb 6612 break;
600b828c 6613 case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
dd8fbd78 6614 tmp2 = tcg_const_i32(0);
9ee6e8bb 6615 switch(size) {
dd8fbd78
FN
6616 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
6617 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
6618 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
600b828c 6619 default: abort();
9ee6e8bb 6620 }
39d5492a 6621 tcg_temp_free_i32(tmp2);
600b828c 6622 if (op == NEON_2RM_VCLT0) {
dd8fbd78 6623 tcg_gen_not_i32(tmp, tmp);
600b828c 6624 }
9ee6e8bb 6625 break;
600b828c 6626 case NEON_2RM_VCEQ0:
dd8fbd78 6627 tmp2 = tcg_const_i32(0);
9ee6e8bb 6628 switch(size) {
dd8fbd78
FN
6629 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
6630 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
6631 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
600b828c 6632 default: abort();
9ee6e8bb 6633 }
39d5492a 6634 tcg_temp_free_i32(tmp2);
9ee6e8bb 6635 break;
600b828c 6636 case NEON_2RM_VCGT0_F:
aa47cfdd
PM
6637 {
6638 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
dd8fbd78 6639 tmp2 = tcg_const_i32(0);
aa47cfdd 6640 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
39d5492a 6641 tcg_temp_free_i32(tmp2);
aa47cfdd 6642 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6643 break;
aa47cfdd 6644 }
600b828c 6645 case NEON_2RM_VCGE0_F:
aa47cfdd
PM
6646 {
6647 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
dd8fbd78 6648 tmp2 = tcg_const_i32(0);
aa47cfdd 6649 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
39d5492a 6650 tcg_temp_free_i32(tmp2);
aa47cfdd 6651 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6652 break;
aa47cfdd 6653 }
600b828c 6654 case NEON_2RM_VCEQ0_F:
aa47cfdd
PM
6655 {
6656 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
dd8fbd78 6657 tmp2 = tcg_const_i32(0);
aa47cfdd 6658 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
39d5492a 6659 tcg_temp_free_i32(tmp2);
aa47cfdd 6660 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6661 break;
aa47cfdd 6662 }
600b828c 6663 case NEON_2RM_VCLE0_F:
aa47cfdd
PM
6664 {
6665 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
0e326109 6666 tmp2 = tcg_const_i32(0);
aa47cfdd 6667 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
39d5492a 6668 tcg_temp_free_i32(tmp2);
aa47cfdd 6669 tcg_temp_free_ptr(fpstatus);
0e326109 6670 break;
aa47cfdd 6671 }
600b828c 6672 case NEON_2RM_VCLT0_F:
aa47cfdd
PM
6673 {
6674 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
0e326109 6675 tmp2 = tcg_const_i32(0);
aa47cfdd 6676 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
39d5492a 6677 tcg_temp_free_i32(tmp2);
aa47cfdd 6678 tcg_temp_free_ptr(fpstatus);
0e326109 6679 break;
aa47cfdd 6680 }
600b828c 6681 case NEON_2RM_VABS_F:
fd8a68cd 6682 gen_helper_vfp_abss(tmp, tmp);
9ee6e8bb 6683 break;
600b828c 6684 case NEON_2RM_VNEG_F:
cedcc96f 6685 gen_helper_vfp_negs(tmp, tmp);
9ee6e8bb 6686 break;
600b828c 6687 case NEON_2RM_VSWP:
dd8fbd78
FN
6688 tmp2 = neon_load_reg(rd, pass);
6689 neon_store_reg(rm, pass, tmp2);
9ee6e8bb 6690 break;
600b828c 6691 case NEON_2RM_VTRN:
dd8fbd78 6692 tmp2 = neon_load_reg(rd, pass);
9ee6e8bb 6693 switch (size) {
dd8fbd78
FN
6694 case 0: gen_neon_trn_u8(tmp, tmp2); break;
6695 case 1: gen_neon_trn_u16(tmp, tmp2); break;
600b828c 6696 default: abort();
9ee6e8bb 6697 }
dd8fbd78 6698 neon_store_reg(rm, pass, tmp2);
9ee6e8bb 6699 break;
34f7b0a2
WN
6700 case NEON_2RM_VRINTN:
6701 case NEON_2RM_VRINTA:
6702 case NEON_2RM_VRINTM:
6703 case NEON_2RM_VRINTP:
6704 case NEON_2RM_VRINTZ:
6705 {
6706 TCGv_i32 tcg_rmode;
6707 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6708 int rmode;
6709
6710 if (op == NEON_2RM_VRINTZ) {
6711 rmode = FPROUNDING_ZERO;
6712 } else {
6713 rmode = fp_decode_rm[((op & 0x6) >> 1) ^ 1];
6714 }
6715
6716 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
6717 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6718 cpu_env);
3b52ad1f 6719 gen_helper_rints(tmp, tmp, fpstatus);
34f7b0a2
WN
6720 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6721 cpu_env);
6722 tcg_temp_free_ptr(fpstatus);
6723 tcg_temp_free_i32(tcg_rmode);
6724 break;
6725 }
2ce70625
WN
6726 case NEON_2RM_VRINTX:
6727 {
6728 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
3b52ad1f 6729 gen_helper_rints_exact(tmp, tmp, fpstatus);
2ce70625
WN
6730 tcg_temp_free_ptr(fpstatus);
6731 break;
6732 }
901ad525
WN
6733 case NEON_2RM_VCVTAU:
6734 case NEON_2RM_VCVTAS:
6735 case NEON_2RM_VCVTNU:
6736 case NEON_2RM_VCVTNS:
6737 case NEON_2RM_VCVTPU:
6738 case NEON_2RM_VCVTPS:
6739 case NEON_2RM_VCVTMU:
6740 case NEON_2RM_VCVTMS:
6741 {
6742 bool is_signed = !extract32(insn, 7, 1);
6743 TCGv_ptr fpst = get_fpstatus_ptr(1);
6744 TCGv_i32 tcg_rmode, tcg_shift;
6745 int rmode = fp_decode_rm[extract32(insn, 8, 2)];
6746
6747 tcg_shift = tcg_const_i32(0);
6748 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
6749 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6750 cpu_env);
6751
6752 if (is_signed) {
30bf0a01 6753 gen_helper_vfp_tosls(tmp, tmp,
901ad525
WN
6754 tcg_shift, fpst);
6755 } else {
30bf0a01 6756 gen_helper_vfp_touls(tmp, tmp,
901ad525
WN
6757 tcg_shift, fpst);
6758 }
6759
6760 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6761 cpu_env);
6762 tcg_temp_free_i32(tcg_rmode);
6763 tcg_temp_free_i32(tcg_shift);
6764 tcg_temp_free_ptr(fpst);
6765 break;
6766 }
600b828c 6767 case NEON_2RM_VRECPE:
b6d4443a
AB
6768 {
6769 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6770 gen_helper_recpe_u32(tmp, tmp, fpstatus);
6771 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6772 break;
b6d4443a 6773 }
600b828c 6774 case NEON_2RM_VRSQRTE:
c2fb418e
AB
6775 {
6776 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6777 gen_helper_rsqrte_u32(tmp, tmp, fpstatus);
6778 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6779 break;
c2fb418e 6780 }
600b828c 6781 case NEON_2RM_VRECPE_F:
b6d4443a
AB
6782 {
6783 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
9a011fec 6784 gen_helper_recpe_f32(tmp, tmp, fpstatus);
b6d4443a 6785 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6786 break;
b6d4443a 6787 }
600b828c 6788 case NEON_2RM_VRSQRTE_F:
c2fb418e
AB
6789 {
6790 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
9a011fec 6791 gen_helper_rsqrte_f32(tmp, tmp, fpstatus);
c2fb418e 6792 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6793 break;
c2fb418e 6794 }
600b828c 6795 case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
60737ed5
PM
6796 {
6797 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6798 gen_helper_vfp_sitos(tmp, tmp, fpstatus);
6799 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6800 break;
60737ed5 6801 }
600b828c 6802 case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
60737ed5
PM
6803 {
6804 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6805 gen_helper_vfp_uitos(tmp, tmp, fpstatus);
6806 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6807 break;
60737ed5 6808 }
600b828c 6809 case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
60737ed5
PM
6810 {
6811 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6812 gen_helper_vfp_tosizs(tmp, tmp, fpstatus);
6813 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6814 break;
60737ed5 6815 }
600b828c 6816 case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
60737ed5
PM
6817 {
6818 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6819 gen_helper_vfp_touizs(tmp, tmp, fpstatus);
6820 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6821 break;
60737ed5 6822 }
9ee6e8bb 6823 default:
600b828c
PM
6824 /* Reserved op values were caught by the
6825 * neon_2rm_sizes[] check earlier.
6826 */
6827 abort();
9ee6e8bb 6828 }
60737ed5 6829 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
6830 }
6831 break;
6832 }
6833 } else if ((insn & (1 << 10)) == 0) {
6834 /* VTBL, VTBX. */
56907d77
PM
6835 int n = ((insn >> 8) & 3) + 1;
6836 if ((rn + n) > 32) {
6837 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
6838 * helper function running off the end of the register file.
6839 */
6840 return 1;
6841 }
6842 n <<= 3;
9ee6e8bb 6843 if (insn & (1 << 6)) {
8f8e3aa4 6844 tmp = neon_load_reg(rd, 0);
9ee6e8bb 6845 } else {
7d1b0095 6846 tmp = tcg_temp_new_i32();
8f8e3aa4 6847 tcg_gen_movi_i32(tmp, 0);
9ee6e8bb 6848 }
8f8e3aa4 6849 tmp2 = neon_load_reg(rm, 0);
e7c06c4e 6850 ptr1 = vfp_reg_ptr(true, rn);
b75263d6 6851 tmp5 = tcg_const_i32(n);
e7c06c4e 6852 gen_helper_neon_tbl(tmp2, tmp2, tmp, ptr1, tmp5);
7d1b0095 6853 tcg_temp_free_i32(tmp);
9ee6e8bb 6854 if (insn & (1 << 6)) {
8f8e3aa4 6855 tmp = neon_load_reg(rd, 1);
9ee6e8bb 6856 } else {
7d1b0095 6857 tmp = tcg_temp_new_i32();
8f8e3aa4 6858 tcg_gen_movi_i32(tmp, 0);
9ee6e8bb 6859 }
8f8e3aa4 6860 tmp3 = neon_load_reg(rm, 1);
e7c06c4e 6861 gen_helper_neon_tbl(tmp3, tmp3, tmp, ptr1, tmp5);
25aeb69b 6862 tcg_temp_free_i32(tmp5);
e7c06c4e 6863 tcg_temp_free_ptr(ptr1);
8f8e3aa4 6864 neon_store_reg(rd, 0, tmp2);
3018f259 6865 neon_store_reg(rd, 1, tmp3);
7d1b0095 6866 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
6867 } else if ((insn & 0x380) == 0) {
6868 /* VDUP */
32f91fb7
RH
6869 int element;
6870 TCGMemOp size;
6871
133da6aa
JR
6872 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
6873 return 1;
6874 }
9ee6e8bb 6875 if (insn & (1 << 16)) {
32f91fb7
RH
6876 size = MO_8;
6877 element = (insn >> 17) & 7;
9ee6e8bb 6878 } else if (insn & (1 << 17)) {
32f91fb7
RH
6879 size = MO_16;
6880 element = (insn >> 18) & 3;
6881 } else {
6882 size = MO_32;
6883 element = (insn >> 19) & 1;
9ee6e8bb 6884 }
32f91fb7
RH
6885 tcg_gen_gvec_dup_mem(size, neon_reg_offset(rd, 0),
6886 neon_element_offset(rm, element, size),
6887 q ? 16 : 8, q ? 16 : 8);
9ee6e8bb
PB
6888 } else {
6889 return 1;
6890 }
6891 }
6892 }
6893 return 0;
6894}
6895
8b7209fa
RH
6896/* Advanced SIMD three registers of the same length extension.
6897 * 31 25 23 22 20 16 12 11 10 9 8 3 0
6898 * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
6899 * | 1 1 1 1 1 1 0 | op1 | D | op2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
6900 * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
6901 */
6902static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
6903{
26c470a7
RH
6904 gen_helper_gvec_3 *fn_gvec = NULL;
6905 gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
6906 int rd, rn, rm, opr_sz;
6907 int data = 0;
87732318
RH
6908 int off_rn, off_rm;
6909 bool is_long = false, q = extract32(insn, 6, 1);
6910 bool ptr_is_env = false;
8b7209fa
RH
6911
6912 if ((insn & 0xfe200f10) == 0xfc200800) {
6913 /* VCMLA -- 1111 110R R.1S .... .... 1000 ...0 .... */
26c470a7
RH
6914 int size = extract32(insn, 20, 1);
6915 data = extract32(insn, 23, 2); /* rot */
962fcbf2 6916 if (!dc_isar_feature(aa32_vcma, s)
5763190f 6917 || (!size && !dc_isar_feature(aa32_fp16_arith, s))) {
8b7209fa
RH
6918 return 1;
6919 }
6920 fn_gvec_ptr = size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
6921 } else if ((insn & 0xfea00f10) == 0xfc800800) {
6922 /* VCADD -- 1111 110R 1.0S .... .... 1000 ...0 .... */
26c470a7
RH
6923 int size = extract32(insn, 20, 1);
6924 data = extract32(insn, 24, 1); /* rot */
962fcbf2 6925 if (!dc_isar_feature(aa32_vcma, s)
5763190f 6926 || (!size && !dc_isar_feature(aa32_fp16_arith, s))) {
8b7209fa
RH
6927 return 1;
6928 }
6929 fn_gvec_ptr = size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
26c470a7
RH
6930 } else if ((insn & 0xfeb00f00) == 0xfc200d00) {
6931 /* V[US]DOT -- 1111 1100 0.10 .... .... 1101 .Q.U .... */
6932 bool u = extract32(insn, 4, 1);
962fcbf2 6933 if (!dc_isar_feature(aa32_dp, s)) {
26c470a7
RH
6934 return 1;
6935 }
6936 fn_gvec = u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b;
87732318
RH
6937 } else if ((insn & 0xff300f10) == 0xfc200810) {
6938 /* VFM[AS]L -- 1111 1100 S.10 .... .... 1000 .Q.1 .... */
6939 int is_s = extract32(insn, 23, 1);
6940 if (!dc_isar_feature(aa32_fhm, s)) {
6941 return 1;
6942 }
6943 is_long = true;
6944 data = is_s; /* is_2 == 0 */
6945 fn_gvec_ptr = gen_helper_gvec_fmlal_a32;
6946 ptr_is_env = true;
8b7209fa
RH
6947 } else {
6948 return 1;
6949 }
6950
87732318
RH
6951 VFP_DREG_D(rd, insn);
6952 if (rd & q) {
6953 return 1;
6954 }
6955 if (q || !is_long) {
6956 VFP_DREG_N(rn, insn);
6957 VFP_DREG_M(rm, insn);
6958 if ((rn | rm) & q & !is_long) {
6959 return 1;
6960 }
6961 off_rn = vfp_reg_offset(1, rn);
6962 off_rm = vfp_reg_offset(1, rm);
6963 } else {
6964 rn = VFP_SREG_N(insn);
6965 rm = VFP_SREG_M(insn);
6966 off_rn = vfp_reg_offset(0, rn);
6967 off_rm = vfp_reg_offset(0, rm);
6968 }
6969
8b7209fa
RH
6970 if (s->fp_excp_el) {
6971 gen_exception_insn(s, 4, EXCP_UDEF,
4be42f40 6972 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
8b7209fa
RH
6973 return 0;
6974 }
6975 if (!s->vfp_enabled) {
6976 return 1;
6977 }
6978
6979 opr_sz = (1 + q) * 8;
26c470a7 6980 if (fn_gvec_ptr) {
87732318
RH
6981 TCGv_ptr ptr;
6982 if (ptr_is_env) {
6983 ptr = cpu_env;
6984 } else {
6985 ptr = get_fpstatus_ptr(1);
6986 }
6987 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
26c470a7 6988 opr_sz, opr_sz, data, fn_gvec_ptr);
87732318
RH
6989 if (!ptr_is_env) {
6990 tcg_temp_free_ptr(ptr);
6991 }
26c470a7 6992 } else {
87732318 6993 tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
26c470a7
RH
6994 opr_sz, opr_sz, data, fn_gvec);
6995 }
8b7209fa
RH
6996 return 0;
6997}
6998
638808ff
RH
6999/* Advanced SIMD two registers and a scalar extension.
7000 * 31 24 23 22 20 16 12 11 10 9 8 3 0
7001 * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
7002 * | 1 1 1 1 1 1 1 0 | o1 | D | o2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
7003 * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
7004 *
7005 */
7006
7007static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
7008{
26c470a7
RH
7009 gen_helper_gvec_3 *fn_gvec = NULL;
7010 gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
2cc99919 7011 int rd, rn, rm, opr_sz, data;
87732318
RH
7012 int off_rn, off_rm;
7013 bool is_long = false, q = extract32(insn, 6, 1);
7014 bool ptr_is_env = false;
638808ff
RH
7015
7016 if ((insn & 0xff000f10) == 0xfe000800) {
7017 /* VCMLA (indexed) -- 1111 1110 S.RR .... .... 1000 ...0 .... */
2cc99919
RH
7018 int rot = extract32(insn, 20, 2);
7019 int size = extract32(insn, 23, 1);
7020 int index;
7021
962fcbf2 7022 if (!dc_isar_feature(aa32_vcma, s)) {
638808ff
RH
7023 return 1;
7024 }
2cc99919 7025 if (size == 0) {
5763190f 7026 if (!dc_isar_feature(aa32_fp16_arith, s)) {
2cc99919
RH
7027 return 1;
7028 }
7029 /* For fp16, rm is just Vm, and index is M. */
7030 rm = extract32(insn, 0, 4);
7031 index = extract32(insn, 5, 1);
7032 } else {
7033 /* For fp32, rm is the usual M:Vm, and index is 0. */
7034 VFP_DREG_M(rm, insn);
7035 index = 0;
7036 }
7037 data = (index << 2) | rot;
7038 fn_gvec_ptr = (size ? gen_helper_gvec_fcmlas_idx
7039 : gen_helper_gvec_fcmlah_idx);
26c470a7
RH
7040 } else if ((insn & 0xffb00f00) == 0xfe200d00) {
7041 /* V[US]DOT -- 1111 1110 0.10 .... .... 1101 .Q.U .... */
7042 int u = extract32(insn, 4, 1);
87732318 7043
962fcbf2 7044 if (!dc_isar_feature(aa32_dp, s)) {
26c470a7
RH
7045 return 1;
7046 }
7047 fn_gvec = u ? gen_helper_gvec_udot_idx_b : gen_helper_gvec_sdot_idx_b;
7048 /* rm is just Vm, and index is M. */
7049 data = extract32(insn, 5, 1); /* index */
7050 rm = extract32(insn, 0, 4);
87732318
RH
7051 } else if ((insn & 0xffa00f10) == 0xfe000810) {
7052 /* VFM[AS]L -- 1111 1110 0.0S .... .... 1000 .Q.1 .... */
7053 int is_s = extract32(insn, 20, 1);
7054 int vm20 = extract32(insn, 0, 3);
7055 int vm3 = extract32(insn, 3, 1);
7056 int m = extract32(insn, 5, 1);
7057 int index;
7058
7059 if (!dc_isar_feature(aa32_fhm, s)) {
7060 return 1;
7061 }
7062 if (q) {
7063 rm = vm20;
7064 index = m * 2 + vm3;
7065 } else {
7066 rm = vm20 * 2 + m;
7067 index = vm3;
7068 }
7069 is_long = true;
7070 data = (index << 2) | is_s; /* is_2 == 0 */
7071 fn_gvec_ptr = gen_helper_gvec_fmlal_idx_a32;
7072 ptr_is_env = true;
638808ff
RH
7073 } else {
7074 return 1;
7075 }
7076
87732318
RH
7077 VFP_DREG_D(rd, insn);
7078 if (rd & q) {
7079 return 1;
7080 }
7081 if (q || !is_long) {
7082 VFP_DREG_N(rn, insn);
7083 if (rn & q & !is_long) {
7084 return 1;
7085 }
7086 off_rn = vfp_reg_offset(1, rn);
7087 off_rm = vfp_reg_offset(1, rm);
7088 } else {
7089 rn = VFP_SREG_N(insn);
7090 off_rn = vfp_reg_offset(0, rn);
7091 off_rm = vfp_reg_offset(0, rm);
7092 }
638808ff
RH
7093 if (s->fp_excp_el) {
7094 gen_exception_insn(s, 4, EXCP_UDEF,
4be42f40 7095 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
638808ff
RH
7096 return 0;
7097 }
7098 if (!s->vfp_enabled) {
7099 return 1;
7100 }
7101
7102 opr_sz = (1 + q) * 8;
26c470a7 7103 if (fn_gvec_ptr) {
87732318
RH
7104 TCGv_ptr ptr;
7105 if (ptr_is_env) {
7106 ptr = cpu_env;
7107 } else {
7108 ptr = get_fpstatus_ptr(1);
7109 }
7110 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
26c470a7 7111 opr_sz, opr_sz, data, fn_gvec_ptr);
87732318
RH
7112 if (!ptr_is_env) {
7113 tcg_temp_free_ptr(ptr);
7114 }
26c470a7 7115 } else {
87732318 7116 tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
26c470a7
RH
7117 opr_sz, opr_sz, data, fn_gvec);
7118 }
638808ff
RH
7119 return 0;
7120}
7121
7dcc1f89 7122static int disas_coproc_insn(DisasContext *s, uint32_t insn)
9ee6e8bb 7123{
4b6a83fb
PM
7124 int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
7125 const ARMCPRegInfo *ri;
9ee6e8bb
PB
7126
7127 cpnum = (insn >> 8) & 0xf;
c0f4af17
PM
7128
7129 /* First check for coprocessor space used for XScale/iwMMXt insns */
d614a513 7130 if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cpnum < 2)) {
c0f4af17
PM
7131 if (extract32(s->c15_cpar, cpnum, 1) == 0) {
7132 return 1;
7133 }
d614a513 7134 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
7dcc1f89 7135 return disas_iwmmxt_insn(s, insn);
d614a513 7136 } else if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
7dcc1f89 7137 return disas_dsp_insn(s, insn);
c0f4af17
PM
7138 }
7139 return 1;
4b6a83fb
PM
7140 }
7141
7142 /* Otherwise treat as a generic register access */
7143 is64 = (insn & (1 << 25)) == 0;
7144 if (!is64 && ((insn & (1 << 4)) == 0)) {
7145 /* cdp */
7146 return 1;
7147 }
7148
7149 crm = insn & 0xf;
7150 if (is64) {
7151 crn = 0;
7152 opc1 = (insn >> 4) & 0xf;
7153 opc2 = 0;
7154 rt2 = (insn >> 16) & 0xf;
7155 } else {
7156 crn = (insn >> 16) & 0xf;
7157 opc1 = (insn >> 21) & 7;
7158 opc2 = (insn >> 5) & 7;
7159 rt2 = 0;
7160 }
7161 isread = (insn >> 20) & 1;
7162 rt = (insn >> 12) & 0xf;
7163
60322b39 7164 ri = get_arm_cp_reginfo(s->cp_regs,
51a79b03 7165 ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
4b6a83fb
PM
7166 if (ri) {
7167 /* Check access permissions */
dcbff19b 7168 if (!cp_access_ok(s->current_el, ri, isread)) {
4b6a83fb
PM
7169 return 1;
7170 }
7171
c0f4af17 7172 if (ri->accessfn ||
d614a513 7173 (arm_dc_feature(s, ARM_FEATURE_XSCALE) && cpnum < 14)) {
f59df3f2
PM
7174 /* Emit code to perform further access permissions checks at
7175 * runtime; this may result in an exception.
c0f4af17
PM
7176 * Note that on XScale all cp0..c13 registers do an access check
7177 * call in order to handle c15_cpar.
f59df3f2
PM
7178 */
7179 TCGv_ptr tmpptr;
3f208fd7 7180 TCGv_i32 tcg_syn, tcg_isread;
8bcbf37c
PM
7181 uint32_t syndrome;
7182
7183 /* Note that since we are an implementation which takes an
7184 * exception on a trapped conditional instruction only if the
7185 * instruction passes its condition code check, we can take
7186 * advantage of the clause in the ARM ARM that allows us to set
7187 * the COND field in the instruction to 0xE in all cases.
7188 * We could fish the actual condition out of the insn (ARM)
7189 * or the condexec bits (Thumb) but it isn't necessary.
7190 */
7191 switch (cpnum) {
7192 case 14:
7193 if (is64) {
7194 syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
4df32259 7195 isread, false);
8bcbf37c
PM
7196 } else {
7197 syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
4df32259 7198 rt, isread, false);
8bcbf37c
PM
7199 }
7200 break;
7201 case 15:
7202 if (is64) {
7203 syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
4df32259 7204 isread, false);
8bcbf37c
PM
7205 } else {
7206 syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
4df32259 7207 rt, isread, false);
8bcbf37c
PM
7208 }
7209 break;
7210 default:
7211 /* ARMv8 defines that only coprocessors 14 and 15 exist,
7212 * so this can only happen if this is an ARMv7 or earlier CPU,
7213 * in which case the syndrome information won't actually be
7214 * guest visible.
7215 */
d614a513 7216 assert(!arm_dc_feature(s, ARM_FEATURE_V8));
8bcbf37c
PM
7217 syndrome = syn_uncategorized();
7218 break;
7219 }
7220
43bfa4a1 7221 gen_set_condexec(s);
3977ee5d 7222 gen_set_pc_im(s, s->pc - 4);
f59df3f2 7223 tmpptr = tcg_const_ptr(ri);
8bcbf37c 7224 tcg_syn = tcg_const_i32(syndrome);
3f208fd7
PM
7225 tcg_isread = tcg_const_i32(isread);
7226 gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn,
7227 tcg_isread);
f59df3f2 7228 tcg_temp_free_ptr(tmpptr);
8bcbf37c 7229 tcg_temp_free_i32(tcg_syn);
3f208fd7 7230 tcg_temp_free_i32(tcg_isread);
f59df3f2
PM
7231 }
7232
4b6a83fb
PM
7233 /* Handle special cases first */
7234 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
7235 case ARM_CP_NOP:
7236 return 0;
7237 case ARM_CP_WFI:
7238 if (isread) {
7239 return 1;
7240 }
eaed129d 7241 gen_set_pc_im(s, s->pc);
dcba3a8d 7242 s->base.is_jmp = DISAS_WFI;
2bee5105 7243 return 0;
4b6a83fb
PM
7244 default:
7245 break;
7246 }
7247
c5a49c63 7248 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
2452731c
PM
7249 gen_io_start();
7250 }
7251
4b6a83fb
PM
7252 if (isread) {
7253 /* Read */
7254 if (is64) {
7255 TCGv_i64 tmp64;
7256 TCGv_i32 tmp;
7257 if (ri->type & ARM_CP_CONST) {
7258 tmp64 = tcg_const_i64(ri->resetvalue);
7259 } else if (ri->readfn) {
7260 TCGv_ptr tmpptr;
4b6a83fb
PM
7261 tmp64 = tcg_temp_new_i64();
7262 tmpptr = tcg_const_ptr(ri);
7263 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
7264 tcg_temp_free_ptr(tmpptr);
7265 } else {
7266 tmp64 = tcg_temp_new_i64();
7267 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
7268 }
7269 tmp = tcg_temp_new_i32();
ecc7b3aa 7270 tcg_gen_extrl_i64_i32(tmp, tmp64);
4b6a83fb
PM
7271 store_reg(s, rt, tmp);
7272 tcg_gen_shri_i64(tmp64, tmp64, 32);
ed336850 7273 tmp = tcg_temp_new_i32();
ecc7b3aa 7274 tcg_gen_extrl_i64_i32(tmp, tmp64);
ed336850 7275 tcg_temp_free_i64(tmp64);
4b6a83fb
PM
7276 store_reg(s, rt2, tmp);
7277 } else {
39d5492a 7278 TCGv_i32 tmp;
4b6a83fb
PM
7279 if (ri->type & ARM_CP_CONST) {
7280 tmp = tcg_const_i32(ri->resetvalue);
7281 } else if (ri->readfn) {
7282 TCGv_ptr tmpptr;
4b6a83fb
PM
7283 tmp = tcg_temp_new_i32();
7284 tmpptr = tcg_const_ptr(ri);
7285 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
7286 tcg_temp_free_ptr(tmpptr);
7287 } else {
7288 tmp = load_cpu_offset(ri->fieldoffset);
7289 }
7290 if (rt == 15) {
7291 /* Destination register of r15 for 32 bit loads sets
7292 * the condition codes from the high 4 bits of the value
7293 */
7294 gen_set_nzcv(tmp);
7295 tcg_temp_free_i32(tmp);
7296 } else {
7297 store_reg(s, rt, tmp);
7298 }
7299 }
7300 } else {
7301 /* Write */
7302 if (ri->type & ARM_CP_CONST) {
7303 /* If not forbidden by access permissions, treat as WI */
7304 return 0;
7305 }
7306
7307 if (is64) {
39d5492a 7308 TCGv_i32 tmplo, tmphi;
4b6a83fb
PM
7309 TCGv_i64 tmp64 = tcg_temp_new_i64();
7310 tmplo = load_reg(s, rt);
7311 tmphi = load_reg(s, rt2);
7312 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
7313 tcg_temp_free_i32(tmplo);
7314 tcg_temp_free_i32(tmphi);
7315 if (ri->writefn) {
7316 TCGv_ptr tmpptr = tcg_const_ptr(ri);
4b6a83fb
PM
7317 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
7318 tcg_temp_free_ptr(tmpptr);
7319 } else {
7320 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
7321 }
7322 tcg_temp_free_i64(tmp64);
7323 } else {
7324 if (ri->writefn) {
39d5492a 7325 TCGv_i32 tmp;
4b6a83fb 7326 TCGv_ptr tmpptr;
4b6a83fb
PM
7327 tmp = load_reg(s, rt);
7328 tmpptr = tcg_const_ptr(ri);
7329 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
7330 tcg_temp_free_ptr(tmpptr);
7331 tcg_temp_free_i32(tmp);
7332 } else {
39d5492a 7333 TCGv_i32 tmp = load_reg(s, rt);
4b6a83fb
PM
7334 store_cpu_offset(tmp, ri->fieldoffset);
7335 }
7336 }
2452731c
PM
7337 }
7338
c5a49c63 7339 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
2452731c
PM
7340 /* I/O operations must end the TB here (whether read or write) */
7341 gen_io_end();
7342 gen_lookup_tb(s);
7343 } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
4b6a83fb
PM
7344 /* We default to ending the TB on a coprocessor register write,
7345 * but allow this to be suppressed by the register definition
7346 * (usually only necessary to work around guest bugs).
7347 */
2452731c 7348 gen_lookup_tb(s);
4b6a83fb 7349 }
2452731c 7350
4b6a83fb
PM
7351 return 0;
7352 }
7353
626187d8
PM
7354 /* Unknown register; this might be a guest error or a QEMU
7355 * unimplemented feature.
7356 */
7357 if (is64) {
7358 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
51a79b03
PM
7359 "64 bit system register cp:%d opc1: %d crm:%d "
7360 "(%s)\n",
7361 isread ? "read" : "write", cpnum, opc1, crm,
7362 s->ns ? "non-secure" : "secure");
626187d8
PM
7363 } else {
7364 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
51a79b03
PM
7365 "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d "
7366 "(%s)\n",
7367 isread ? "read" : "write", cpnum, opc1, crn, crm, opc2,
7368 s->ns ? "non-secure" : "secure");
626187d8
PM
7369 }
7370
4a9a539f 7371 return 1;
9ee6e8bb
PB
7372}
7373
5e3f878a
PB
7374
7375/* Store a 64-bit value to a register pair. Clobbers val. */
a7812ae4 7376static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5e3f878a 7377{
39d5492a 7378 TCGv_i32 tmp;
7d1b0095 7379 tmp = tcg_temp_new_i32();
ecc7b3aa 7380 tcg_gen_extrl_i64_i32(tmp, val);
5e3f878a 7381 store_reg(s, rlow, tmp);
7d1b0095 7382 tmp = tcg_temp_new_i32();
5e3f878a 7383 tcg_gen_shri_i64(val, val, 32);
ecc7b3aa 7384 tcg_gen_extrl_i64_i32(tmp, val);
5e3f878a
PB
7385 store_reg(s, rhigh, tmp);
7386}
7387
7388/* load a 32-bit value from a register and perform a 64-bit accumulate. */
a7812ae4 7389static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5e3f878a 7390{
a7812ae4 7391 TCGv_i64 tmp;
39d5492a 7392 TCGv_i32 tmp2;
5e3f878a 7393
36aa55dc 7394 /* Load value and extend to 64 bits. */
a7812ae4 7395 tmp = tcg_temp_new_i64();
5e3f878a
PB
7396 tmp2 = load_reg(s, rlow);
7397 tcg_gen_extu_i32_i64(tmp, tmp2);
7d1b0095 7398 tcg_temp_free_i32(tmp2);
5e3f878a 7399 tcg_gen_add_i64(val, val, tmp);
b75263d6 7400 tcg_temp_free_i64(tmp);
5e3f878a
PB
7401}
7402
7403/* load and add a 64-bit value from a register pair. */
a7812ae4 7404static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5e3f878a 7405{
a7812ae4 7406 TCGv_i64 tmp;
39d5492a
PM
7407 TCGv_i32 tmpl;
7408 TCGv_i32 tmph;
5e3f878a
PB
7409
7410 /* Load 64-bit value rd:rn. */
36aa55dc
PB
7411 tmpl = load_reg(s, rlow);
7412 tmph = load_reg(s, rhigh);
a7812ae4 7413 tmp = tcg_temp_new_i64();
36aa55dc 7414 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
7d1b0095
PM
7415 tcg_temp_free_i32(tmpl);
7416 tcg_temp_free_i32(tmph);
5e3f878a 7417 tcg_gen_add_i64(val, val, tmp);
b75263d6 7418 tcg_temp_free_i64(tmp);
5e3f878a
PB
7419}
7420
c9f10124 7421/* Set N and Z flags from hi|lo. */
39d5492a 7422static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
5e3f878a 7423{
c9f10124
RH
7424 tcg_gen_mov_i32(cpu_NF, hi);
7425 tcg_gen_or_i32(cpu_ZF, lo, hi);
5e3f878a
PB
7426}
7427
426f5abc
PB
7428/* Load/Store exclusive instructions are implemented by remembering
7429 the value/address loaded, and seeing if these are the same
354161b3 7430 when the store is performed. This should be sufficient to implement
426f5abc 7431 the architecturally mandated semantics, and avoids having to monitor
354161b3
EC
7432 regular stores. The compare vs the remembered value is done during
7433 the cmpxchg operation, but we must compare the addresses manually. */
426f5abc 7434static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
39d5492a 7435 TCGv_i32 addr, int size)
426f5abc 7436{
94ee24e7 7437 TCGv_i32 tmp = tcg_temp_new_i32();
354161b3 7438 TCGMemOp opc = size | MO_ALIGN | s->be_data;
426f5abc 7439
50225ad0
PM
7440 s->is_ldex = true;
7441
426f5abc 7442 if (size == 3) {
39d5492a 7443 TCGv_i32 tmp2 = tcg_temp_new_i32();
354161b3 7444 TCGv_i64 t64 = tcg_temp_new_i64();
03d05e2d 7445
3448d47b
PM
7446 /* For AArch32, architecturally the 32-bit word at the lowest
7447 * address is always Rt and the one at addr+4 is Rt2, even if
7448 * the CPU is big-endian. That means we don't want to do a
7449 * gen_aa32_ld_i64(), which invokes gen_aa32_frob64() as if
7450 * for an architecturally 64-bit access, but instead do a
7451 * 64-bit access using MO_BE if appropriate and then split
7452 * the two halves.
7453 * This only makes a difference for BE32 user-mode, where
7454 * frob64() must not flip the two halves of the 64-bit data
7455 * but this code must treat BE32 user-mode like BE32 system.
7456 */
7457 TCGv taddr = gen_aa32_addr(s, addr, opc);
7458
7459 tcg_gen_qemu_ld_i64(t64, taddr, get_mem_index(s), opc);
7460 tcg_temp_free(taddr);
354161b3 7461 tcg_gen_mov_i64(cpu_exclusive_val, t64);
3448d47b
PM
7462 if (s->be_data == MO_BE) {
7463 tcg_gen_extr_i64_i32(tmp2, tmp, t64);
7464 } else {
7465 tcg_gen_extr_i64_i32(tmp, tmp2, t64);
7466 }
354161b3
EC
7467 tcg_temp_free_i64(t64);
7468
7469 store_reg(s, rt2, tmp2);
03d05e2d 7470 } else {
354161b3 7471 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), opc);
03d05e2d 7472 tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
426f5abc 7473 }
03d05e2d
PM
7474
7475 store_reg(s, rt, tmp);
7476 tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
426f5abc
PB
7477}
7478
7479static void gen_clrex(DisasContext *s)
7480{
03d05e2d 7481 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
426f5abc
PB
7482}
7483
426f5abc 7484static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
39d5492a 7485 TCGv_i32 addr, int size)
426f5abc 7486{
354161b3
EC
7487 TCGv_i32 t0, t1, t2;
7488 TCGv_i64 extaddr;
7489 TCGv taddr;
42a268c2
RH
7490 TCGLabel *done_label;
7491 TCGLabel *fail_label;
354161b3 7492 TCGMemOp opc = size | MO_ALIGN | s->be_data;
426f5abc
PB
7493
7494 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
7495 [addr] = {Rt};
7496 {Rd} = 0;
7497 } else {
7498 {Rd} = 1;
7499 } */
7500 fail_label = gen_new_label();
7501 done_label = gen_new_label();
03d05e2d
PM
7502 extaddr = tcg_temp_new_i64();
7503 tcg_gen_extu_i32_i64(extaddr, addr);
7504 tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
7505 tcg_temp_free_i64(extaddr);
7506
354161b3
EC
7507 taddr = gen_aa32_addr(s, addr, opc);
7508 t0 = tcg_temp_new_i32();
7509 t1 = load_reg(s, rt);
426f5abc 7510 if (size == 3) {
354161b3
EC
7511 TCGv_i64 o64 = tcg_temp_new_i64();
7512 TCGv_i64 n64 = tcg_temp_new_i64();
03d05e2d 7513
354161b3 7514 t2 = load_reg(s, rt2);
3448d47b
PM
7515 /* For AArch32, architecturally the 32-bit word at the lowest
7516 * address is always Rt and the one at addr+4 is Rt2, even if
7517 * the CPU is big-endian. Since we're going to treat this as a
7518 * single 64-bit BE store, we need to put the two halves in the
7519 * opposite order for BE to LE, so that they end up in the right
7520 * places.
7521 * We don't want gen_aa32_frob64() because that does the wrong
7522 * thing for BE32 usermode.
7523 */
7524 if (s->be_data == MO_BE) {
7525 tcg_gen_concat_i32_i64(n64, t2, t1);
7526 } else {
7527 tcg_gen_concat_i32_i64(n64, t1, t2);
7528 }
354161b3 7529 tcg_temp_free_i32(t2);
03d05e2d 7530
354161b3
EC
7531 tcg_gen_atomic_cmpxchg_i64(o64, taddr, cpu_exclusive_val, n64,
7532 get_mem_index(s), opc);
7533 tcg_temp_free_i64(n64);
7534
354161b3
EC
7535 tcg_gen_setcond_i64(TCG_COND_NE, o64, o64, cpu_exclusive_val);
7536 tcg_gen_extrl_i64_i32(t0, o64);
7537
7538 tcg_temp_free_i64(o64);
7539 } else {
7540 t2 = tcg_temp_new_i32();
7541 tcg_gen_extrl_i64_i32(t2, cpu_exclusive_val);
7542 tcg_gen_atomic_cmpxchg_i32(t0, taddr, t2, t1, get_mem_index(s), opc);
7543 tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t2);
7544 tcg_temp_free_i32(t2);
426f5abc 7545 }
354161b3
EC
7546 tcg_temp_free_i32(t1);
7547 tcg_temp_free(taddr);
7548 tcg_gen_mov_i32(cpu_R[rd], t0);
7549 tcg_temp_free_i32(t0);
426f5abc 7550 tcg_gen_br(done_label);
354161b3 7551
426f5abc
PB
7552 gen_set_label(fail_label);
7553 tcg_gen_movi_i32(cpu_R[rd], 1);
7554 gen_set_label(done_label);
03d05e2d 7555 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
426f5abc 7556}
426f5abc 7557
81465888
PM
7558/* gen_srs:
7559 * @env: CPUARMState
7560 * @s: DisasContext
7561 * @mode: mode field from insn (which stack to store to)
7562 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
7563 * @writeback: true if writeback bit set
7564 *
7565 * Generate code for the SRS (Store Return State) insn.
7566 */
7567static void gen_srs(DisasContext *s,
7568 uint32_t mode, uint32_t amode, bool writeback)
7569{
7570 int32_t offset;
cbc0326b
PM
7571 TCGv_i32 addr, tmp;
7572 bool undef = false;
7573
7574 /* SRS is:
7575 * - trapped to EL3 if EL3 is AArch64 and we are at Secure EL1
ba63cf47 7576 * and specified mode is monitor mode
cbc0326b
PM
7577 * - UNDEFINED in Hyp mode
7578 * - UNPREDICTABLE in User or System mode
7579 * - UNPREDICTABLE if the specified mode is:
7580 * -- not implemented
7581 * -- not a valid mode number
7582 * -- a mode that's at a higher exception level
7583 * -- Monitor, if we are Non-secure
f01377f5 7584 * For the UNPREDICTABLE cases we choose to UNDEF.
cbc0326b 7585 */
ba63cf47 7586 if (s->current_el == 1 && !s->ns && mode == ARM_CPU_MODE_MON) {
cbc0326b
PM
7587 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), 3);
7588 return;
7589 }
7590
7591 if (s->current_el == 0 || s->current_el == 2) {
7592 undef = true;
7593 }
7594
7595 switch (mode) {
7596 case ARM_CPU_MODE_USR:
7597 case ARM_CPU_MODE_FIQ:
7598 case ARM_CPU_MODE_IRQ:
7599 case ARM_CPU_MODE_SVC:
7600 case ARM_CPU_MODE_ABT:
7601 case ARM_CPU_MODE_UND:
7602 case ARM_CPU_MODE_SYS:
7603 break;
7604 case ARM_CPU_MODE_HYP:
7605 if (s->current_el == 1 || !arm_dc_feature(s, ARM_FEATURE_EL2)) {
7606 undef = true;
7607 }
7608 break;
7609 case ARM_CPU_MODE_MON:
7610 /* No need to check specifically for "are we non-secure" because
7611 * we've already made EL0 UNDEF and handled the trap for S-EL1;
7612 * so if this isn't EL3 then we must be non-secure.
7613 */
7614 if (s->current_el != 3) {
7615 undef = true;
7616 }
7617 break;
7618 default:
7619 undef = true;
7620 }
7621
7622 if (undef) {
7623 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
7624 default_exception_el(s));
7625 return;
7626 }
7627
7628 addr = tcg_temp_new_i32();
7629 tmp = tcg_const_i32(mode);
f01377f5
PM
7630 /* get_r13_banked() will raise an exception if called from System mode */
7631 gen_set_condexec(s);
7632 gen_set_pc_im(s, s->pc - 4);
81465888
PM
7633 gen_helper_get_r13_banked(addr, cpu_env, tmp);
7634 tcg_temp_free_i32(tmp);
7635 switch (amode) {
7636 case 0: /* DA */
7637 offset = -4;
7638 break;
7639 case 1: /* IA */
7640 offset = 0;
7641 break;
7642 case 2: /* DB */
7643 offset = -8;
7644 break;
7645 case 3: /* IB */
7646 offset = 4;
7647 break;
7648 default:
7649 abort();
7650 }
7651 tcg_gen_addi_i32(addr, addr, offset);
7652 tmp = load_reg(s, 14);
12dcc321 7653 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 7654 tcg_temp_free_i32(tmp);
81465888
PM
7655 tmp = load_cpu_field(spsr);
7656 tcg_gen_addi_i32(addr, addr, 4);
12dcc321 7657 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 7658 tcg_temp_free_i32(tmp);
81465888
PM
7659 if (writeback) {
7660 switch (amode) {
7661 case 0:
7662 offset = -8;
7663 break;
7664 case 1:
7665 offset = 4;
7666 break;
7667 case 2:
7668 offset = -4;
7669 break;
7670 case 3:
7671 offset = 0;
7672 break;
7673 default:
7674 abort();
7675 }
7676 tcg_gen_addi_i32(addr, addr, offset);
7677 tmp = tcg_const_i32(mode);
7678 gen_helper_set_r13_banked(cpu_env, tmp, addr);
7679 tcg_temp_free_i32(tmp);
7680 }
7681 tcg_temp_free_i32(addr);
dcba3a8d 7682 s->base.is_jmp = DISAS_UPDATE;
81465888
PM
7683}
7684
c2d9644e
RK
7685/* Generate a label used for skipping this instruction */
7686static void arm_gen_condlabel(DisasContext *s)
7687{
7688 if (!s->condjmp) {
7689 s->condlabel = gen_new_label();
7690 s->condjmp = 1;
7691 }
7692}
7693
7694/* Skip this instruction if the ARM condition is false */
7695static void arm_skip_unless(DisasContext *s, uint32_t cond)
7696{
7697 arm_gen_condlabel(s);
7698 arm_gen_test_cc(cond ^ 1, s->condlabel);
7699}
7700
f4df2210 7701static void disas_arm_insn(DisasContext *s, unsigned int insn)
9ee6e8bb 7702{
f4df2210 7703 unsigned int cond, val, op1, i, shift, rm, rs, rn, rd, sh;
39d5492a
PM
7704 TCGv_i32 tmp;
7705 TCGv_i32 tmp2;
7706 TCGv_i32 tmp3;
7707 TCGv_i32 addr;
a7812ae4 7708 TCGv_i64 tmp64;
9ee6e8bb 7709
e13886e3
PM
7710 /* M variants do not implement ARM mode; this must raise the INVSTATE
7711 * UsageFault exception.
7712 */
b53d8923 7713 if (arm_dc_feature(s, ARM_FEATURE_M)) {
e13886e3
PM
7714 gen_exception_insn(s, 4, EXCP_INVSTATE, syn_uncategorized(),
7715 default_exception_el(s));
7716 return;
b53d8923 7717 }
9ee6e8bb
PB
7718 cond = insn >> 28;
7719 if (cond == 0xf){
be5e7a76
DES
7720 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
7721 * choose to UNDEF. In ARMv5 and above the space is used
7722 * for miscellaneous unconditional instructions.
7723 */
7724 ARCH(5);
7725
9ee6e8bb
PB
7726 /* Unconditional instructions. */
7727 if (((insn >> 25) & 7) == 1) {
7728 /* NEON Data processing. */
d614a513 7729 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
9ee6e8bb 7730 goto illegal_op;
d614a513 7731 }
9ee6e8bb 7732
7dcc1f89 7733 if (disas_neon_data_insn(s, insn)) {
9ee6e8bb 7734 goto illegal_op;
7dcc1f89 7735 }
9ee6e8bb
PB
7736 return;
7737 }
7738 if ((insn & 0x0f100000) == 0x04000000) {
7739 /* NEON load/store. */
d614a513 7740 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
9ee6e8bb 7741 goto illegal_op;
d614a513 7742 }
9ee6e8bb 7743
7dcc1f89 7744 if (disas_neon_ls_insn(s, insn)) {
9ee6e8bb 7745 goto illegal_op;
7dcc1f89 7746 }
9ee6e8bb
PB
7747 return;
7748 }
6a57f3eb
WN
7749 if ((insn & 0x0f000e10) == 0x0e000a00) {
7750 /* VFP. */
7dcc1f89 7751 if (disas_vfp_insn(s, insn)) {
6a57f3eb
WN
7752 goto illegal_op;
7753 }
7754 return;
7755 }
3d185e5d
PM
7756 if (((insn & 0x0f30f000) == 0x0510f000) ||
7757 ((insn & 0x0f30f010) == 0x0710f000)) {
7758 if ((insn & (1 << 22)) == 0) {
7759 /* PLDW; v7MP */
d614a513 7760 if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
3d185e5d
PM
7761 goto illegal_op;
7762 }
7763 }
7764 /* Otherwise PLD; v5TE+ */
be5e7a76 7765 ARCH(5TE);
3d185e5d
PM
7766 return;
7767 }
7768 if (((insn & 0x0f70f000) == 0x0450f000) ||
7769 ((insn & 0x0f70f010) == 0x0650f000)) {
7770 ARCH(7);
7771 return; /* PLI; V7 */
7772 }
7773 if (((insn & 0x0f700000) == 0x04100000) ||
7774 ((insn & 0x0f700010) == 0x06100000)) {
d614a513 7775 if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
3d185e5d
PM
7776 goto illegal_op;
7777 }
7778 return; /* v7MP: Unallocated memory hint: must NOP */
7779 }
7780
7781 if ((insn & 0x0ffffdff) == 0x01010000) {
9ee6e8bb
PB
7782 ARCH(6);
7783 /* setend */
9886ecdf
PB
7784 if (((insn >> 9) & 1) != !!(s->be_data == MO_BE)) {
7785 gen_helper_setend(cpu_env);
dcba3a8d 7786 s->base.is_jmp = DISAS_UPDATE;
9ee6e8bb
PB
7787 }
7788 return;
7789 } else if ((insn & 0x0fffff00) == 0x057ff000) {
7790 switch ((insn >> 4) & 0xf) {
7791 case 1: /* clrex */
7792 ARCH(6K);
426f5abc 7793 gen_clrex(s);
9ee6e8bb
PB
7794 return;
7795 case 4: /* dsb */
7796 case 5: /* dmb */
9ee6e8bb 7797 ARCH(7);
61e4c432 7798 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
9ee6e8bb 7799 return;
6df99dec
SS
7800 case 6: /* isb */
7801 /* We need to break the TB after this insn to execute
7802 * self-modifying code correctly and also to take
7803 * any pending interrupts immediately.
7804 */
0b609cc1 7805 gen_goto_tb(s, 0, s->pc & ~1);
6df99dec 7806 return;
9888bd1e
RH
7807 case 7: /* sb */
7808 if ((insn & 0xf) || !dc_isar_feature(aa32_sb, s)) {
7809 goto illegal_op;
7810 }
7811 /*
7812 * TODO: There is no speculation barrier opcode
7813 * for TCG; MB and end the TB instead.
7814 */
7815 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
7816 gen_goto_tb(s, 0, s->pc & ~1);
7817 return;
9ee6e8bb
PB
7818 default:
7819 goto illegal_op;
7820 }
7821 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
7822 /* srs */
81465888
PM
7823 ARCH(6);
7824 gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21));
3b328448 7825 return;
ea825eee 7826 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
9ee6e8bb 7827 /* rfe */
c67b6b71 7828 int32_t offset;
9ee6e8bb
PB
7829 if (IS_USER(s))
7830 goto illegal_op;
7831 ARCH(6);
7832 rn = (insn >> 16) & 0xf;
b0109805 7833 addr = load_reg(s, rn);
9ee6e8bb
PB
7834 i = (insn >> 23) & 3;
7835 switch (i) {
b0109805 7836 case 0: offset = -4; break; /* DA */
c67b6b71
FN
7837 case 1: offset = 0; break; /* IA */
7838 case 2: offset = -8; break; /* DB */
b0109805 7839 case 3: offset = 4; break; /* IB */
9ee6e8bb
PB
7840 default: abort();
7841 }
7842 if (offset)
b0109805
PB
7843 tcg_gen_addi_i32(addr, addr, offset);
7844 /* Load PC into tmp and CPSR into tmp2. */
5a839c0d 7845 tmp = tcg_temp_new_i32();
12dcc321 7846 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 7847 tcg_gen_addi_i32(addr, addr, 4);
5a839c0d 7848 tmp2 = tcg_temp_new_i32();
12dcc321 7849 gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
9ee6e8bb
PB
7850 if (insn & (1 << 21)) {
7851 /* Base writeback. */
7852 switch (i) {
b0109805 7853 case 0: offset = -8; break;
c67b6b71
FN
7854 case 1: offset = 4; break;
7855 case 2: offset = -4; break;
b0109805 7856 case 3: offset = 0; break;
9ee6e8bb
PB
7857 default: abort();
7858 }
7859 if (offset)
b0109805
PB
7860 tcg_gen_addi_i32(addr, addr, offset);
7861 store_reg(s, rn, addr);
7862 } else {
7d1b0095 7863 tcg_temp_free_i32(addr);
9ee6e8bb 7864 }
b0109805 7865 gen_rfe(s, tmp, tmp2);
c67b6b71 7866 return;
9ee6e8bb
PB
7867 } else if ((insn & 0x0e000000) == 0x0a000000) {
7868 /* branch link and change to thumb (blx <offset>) */
7869 int32_t offset;
7870
7871 val = (uint32_t)s->pc;
7d1b0095 7872 tmp = tcg_temp_new_i32();
d9ba4830
PB
7873 tcg_gen_movi_i32(tmp, val);
7874 store_reg(s, 14, tmp);
9ee6e8bb
PB
7875 /* Sign-extend the 24-bit offset */
7876 offset = (((int32_t)insn) << 8) >> 8;
7877 /* offset * 4 + bit24 * 2 + (thumb bit) */
7878 val += (offset << 2) | ((insn >> 23) & 2) | 1;
7879 /* pipeline offset */
7880 val += 4;
be5e7a76 7881 /* protected by ARCH(5); above, near the start of uncond block */
d9ba4830 7882 gen_bx_im(s, val);
9ee6e8bb
PB
7883 return;
7884 } else if ((insn & 0x0e000f00) == 0x0c000100) {
d614a513 7885 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
9ee6e8bb 7886 /* iWMMXt register transfer. */
c0f4af17 7887 if (extract32(s->c15_cpar, 1, 1)) {
7dcc1f89 7888 if (!disas_iwmmxt_insn(s, insn)) {
9ee6e8bb 7889 return;
c0f4af17
PM
7890 }
7891 }
9ee6e8bb 7892 }
8b7209fa
RH
7893 } else if ((insn & 0x0e000a00) == 0x0c000800
7894 && arm_dc_feature(s, ARM_FEATURE_V8)) {
7895 if (disas_neon_insn_3same_ext(s, insn)) {
7896 goto illegal_op;
7897 }
7898 return;
638808ff
RH
7899 } else if ((insn & 0x0f000a00) == 0x0e000800
7900 && arm_dc_feature(s, ARM_FEATURE_V8)) {
7901 if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
7902 goto illegal_op;
7903 }
7904 return;
9ee6e8bb
PB
7905 } else if ((insn & 0x0fe00000) == 0x0c400000) {
7906 /* Coprocessor double register transfer. */
be5e7a76 7907 ARCH(5TE);
9ee6e8bb
PB
7908 } else if ((insn & 0x0f000010) == 0x0e000010) {
7909 /* Additional coprocessor register transfer. */
7997d92f 7910 } else if ((insn & 0x0ff10020) == 0x01000000) {
9ee6e8bb
PB
7911 uint32_t mask;
7912 uint32_t val;
7913 /* cps (privileged) */
7914 if (IS_USER(s))
7915 return;
7916 mask = val = 0;
7917 if (insn & (1 << 19)) {
7918 if (insn & (1 << 8))
7919 mask |= CPSR_A;
7920 if (insn & (1 << 7))
7921 mask |= CPSR_I;
7922 if (insn & (1 << 6))
7923 mask |= CPSR_F;
7924 if (insn & (1 << 18))
7925 val |= mask;
7926 }
7997d92f 7927 if (insn & (1 << 17)) {
9ee6e8bb
PB
7928 mask |= CPSR_M;
7929 val |= (insn & 0x1f);
7930 }
7931 if (mask) {
2fbac54b 7932 gen_set_psr_im(s, mask, 0, val);
9ee6e8bb
PB
7933 }
7934 return;
7935 }
7936 goto illegal_op;
7937 }
7938 if (cond != 0xe) {
7939 /* if not always execute, we generate a conditional jump to
7940 next instruction */
c2d9644e 7941 arm_skip_unless(s, cond);
9ee6e8bb
PB
7942 }
7943 if ((insn & 0x0f900000) == 0x03000000) {
7944 if ((insn & (1 << 21)) == 0) {
7945 ARCH(6T2);
7946 rd = (insn >> 12) & 0xf;
7947 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
7948 if ((insn & (1 << 22)) == 0) {
7949 /* MOVW */
7d1b0095 7950 tmp = tcg_temp_new_i32();
5e3f878a 7951 tcg_gen_movi_i32(tmp, val);
9ee6e8bb
PB
7952 } else {
7953 /* MOVT */
5e3f878a 7954 tmp = load_reg(s, rd);
86831435 7955 tcg_gen_ext16u_i32(tmp, tmp);
5e3f878a 7956 tcg_gen_ori_i32(tmp, tmp, val << 16);
9ee6e8bb 7957 }
5e3f878a 7958 store_reg(s, rd, tmp);
9ee6e8bb
PB
7959 } else {
7960 if (((insn >> 12) & 0xf) != 0xf)
7961 goto illegal_op;
7962 if (((insn >> 16) & 0xf) == 0) {
7963 gen_nop_hint(s, insn & 0xff);
7964 } else {
7965 /* CPSR = immediate */
7966 val = insn & 0xff;
7967 shift = ((insn >> 8) & 0xf) * 2;
7968 if (shift)
7969 val = (val >> shift) | (val << (32 - shift));
9ee6e8bb 7970 i = ((insn & (1 << 22)) != 0);
7dcc1f89
PM
7971 if (gen_set_psr_im(s, msr_mask(s, (insn >> 16) & 0xf, i),
7972 i, val)) {
9ee6e8bb 7973 goto illegal_op;
7dcc1f89 7974 }
9ee6e8bb
PB
7975 }
7976 }
7977 } else if ((insn & 0x0f900000) == 0x01000000
7978 && (insn & 0x00000090) != 0x00000090) {
7979 /* miscellaneous instructions */
7980 op1 = (insn >> 21) & 3;
7981 sh = (insn >> 4) & 0xf;
7982 rm = insn & 0xf;
7983 switch (sh) {
8bfd0550
PM
7984 case 0x0: /* MSR, MRS */
7985 if (insn & (1 << 9)) {
7986 /* MSR (banked) and MRS (banked) */
7987 int sysm = extract32(insn, 16, 4) |
7988 (extract32(insn, 8, 1) << 4);
7989 int r = extract32(insn, 22, 1);
7990
7991 if (op1 & 1) {
7992 /* MSR (banked) */
7993 gen_msr_banked(s, r, sysm, rm);
7994 } else {
7995 /* MRS (banked) */
7996 int rd = extract32(insn, 12, 4);
7997
7998 gen_mrs_banked(s, r, sysm, rd);
7999 }
8000 break;
8001 }
8002
8003 /* MSR, MRS (for PSRs) */
9ee6e8bb
PB
8004 if (op1 & 1) {
8005 /* PSR = reg */
2fbac54b 8006 tmp = load_reg(s, rm);
9ee6e8bb 8007 i = ((op1 & 2) != 0);
7dcc1f89 8008 if (gen_set_psr(s, msr_mask(s, (insn >> 16) & 0xf, i), i, tmp))
9ee6e8bb
PB
8009 goto illegal_op;
8010 } else {
8011 /* reg = PSR */
8012 rd = (insn >> 12) & 0xf;
8013 if (op1 & 2) {
8014 if (IS_USER(s))
8015 goto illegal_op;
d9ba4830 8016 tmp = load_cpu_field(spsr);
9ee6e8bb 8017 } else {
7d1b0095 8018 tmp = tcg_temp_new_i32();
9ef39277 8019 gen_helper_cpsr_read(tmp, cpu_env);
9ee6e8bb 8020 }
d9ba4830 8021 store_reg(s, rd, tmp);
9ee6e8bb
PB
8022 }
8023 break;
8024 case 0x1:
8025 if (op1 == 1) {
8026 /* branch/exchange thumb (bx). */
be5e7a76 8027 ARCH(4T);
d9ba4830
PB
8028 tmp = load_reg(s, rm);
8029 gen_bx(s, tmp);
9ee6e8bb
PB
8030 } else if (op1 == 3) {
8031 /* clz */
be5e7a76 8032 ARCH(5);
9ee6e8bb 8033 rd = (insn >> 12) & 0xf;
1497c961 8034 tmp = load_reg(s, rm);
7539a012 8035 tcg_gen_clzi_i32(tmp, tmp, 32);
1497c961 8036 store_reg(s, rd, tmp);
9ee6e8bb
PB
8037 } else {
8038 goto illegal_op;
8039 }
8040 break;
8041 case 0x2:
8042 if (op1 == 1) {
8043 ARCH(5J); /* bxj */
8044 /* Trivial implementation equivalent to bx. */
d9ba4830
PB
8045 tmp = load_reg(s, rm);
8046 gen_bx(s, tmp);
9ee6e8bb
PB
8047 } else {
8048 goto illegal_op;
8049 }
8050 break;
8051 case 0x3:
8052 if (op1 != 1)
8053 goto illegal_op;
8054
be5e7a76 8055 ARCH(5);
9ee6e8bb 8056 /* branch link/exchange thumb (blx) */
d9ba4830 8057 tmp = load_reg(s, rm);
7d1b0095 8058 tmp2 = tcg_temp_new_i32();
d9ba4830
PB
8059 tcg_gen_movi_i32(tmp2, s->pc);
8060 store_reg(s, 14, tmp2);
8061 gen_bx(s, tmp);
9ee6e8bb 8062 break;
eb0ecd5a
WN
8063 case 0x4:
8064 {
8065 /* crc32/crc32c */
8066 uint32_t c = extract32(insn, 8, 4);
8067
8068 /* Check this CPU supports ARMv8 CRC instructions.
8069 * op1 == 3 is UNPREDICTABLE but handle as UNDEFINED.
8070 * Bits 8, 10 and 11 should be zero.
8071 */
962fcbf2 8072 if (!dc_isar_feature(aa32_crc32, s) || op1 == 0x3 || (c & 0xd) != 0) {
eb0ecd5a
WN
8073 goto illegal_op;
8074 }
8075
8076 rn = extract32(insn, 16, 4);
8077 rd = extract32(insn, 12, 4);
8078
8079 tmp = load_reg(s, rn);
8080 tmp2 = load_reg(s, rm);
aa633469
PM
8081 if (op1 == 0) {
8082 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
8083 } else if (op1 == 1) {
8084 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
8085 }
eb0ecd5a
WN
8086 tmp3 = tcg_const_i32(1 << op1);
8087 if (c & 0x2) {
8088 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
8089 } else {
8090 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
8091 }
8092 tcg_temp_free_i32(tmp2);
8093 tcg_temp_free_i32(tmp3);
8094 store_reg(s, rd, tmp);
8095 break;
8096 }
9ee6e8bb 8097 case 0x5: /* saturating add/subtract */
be5e7a76 8098 ARCH(5TE);
9ee6e8bb
PB
8099 rd = (insn >> 12) & 0xf;
8100 rn = (insn >> 16) & 0xf;
b40d0353 8101 tmp = load_reg(s, rm);
5e3f878a 8102 tmp2 = load_reg(s, rn);
9ee6e8bb 8103 if (op1 & 2)
9ef39277 8104 gen_helper_double_saturate(tmp2, cpu_env, tmp2);
9ee6e8bb 8105 if (op1 & 1)
9ef39277 8106 gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 8107 else
9ef39277 8108 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
7d1b0095 8109 tcg_temp_free_i32(tmp2);
5e3f878a 8110 store_reg(s, rd, tmp);
9ee6e8bb 8111 break;
55c544ed
PM
8112 case 0x6: /* ERET */
8113 if (op1 != 3) {
8114 goto illegal_op;
8115 }
8116 if (!arm_dc_feature(s, ARM_FEATURE_V7VE)) {
8117 goto illegal_op;
8118 }
8119 if ((insn & 0x000fff0f) != 0x0000000e) {
8120 /* UNPREDICTABLE; we choose to UNDEF */
8121 goto illegal_op;
8122 }
8123
8124 if (s->current_el == 2) {
8125 tmp = load_cpu_field(elr_el[2]);
8126 } else {
8127 tmp = load_reg(s, 14);
8128 }
8129 gen_exception_return(s, tmp);
8130 break;
49e14940 8131 case 7:
d4a2dc67
PM
8132 {
8133 int imm16 = extract32(insn, 0, 4) | (extract32(insn, 8, 12) << 4);
37e6456e 8134 switch (op1) {
19a6e31c
PM
8135 case 0:
8136 /* HLT */
8137 gen_hlt(s, imm16);
8138 break;
37e6456e
PM
8139 case 1:
8140 /* bkpt */
8141 ARCH(5);
c900a2e6 8142 gen_exception_bkpt_insn(s, 4, syn_aa32_bkpt(imm16, false));
37e6456e
PM
8143 break;
8144 case 2:
8145 /* Hypervisor call (v7) */
8146 ARCH(7);
8147 if (IS_USER(s)) {
8148 goto illegal_op;
8149 }
8150 gen_hvc(s, imm16);
8151 break;
8152 case 3:
8153 /* Secure monitor call (v6+) */
8154 ARCH(6K);
8155 if (IS_USER(s)) {
8156 goto illegal_op;
8157 }
8158 gen_smc(s);
8159 break;
8160 default:
19a6e31c 8161 g_assert_not_reached();
49e14940 8162 }
9ee6e8bb 8163 break;
d4a2dc67 8164 }
9ee6e8bb
PB
8165 case 0x8: /* signed multiply */
8166 case 0xa:
8167 case 0xc:
8168 case 0xe:
be5e7a76 8169 ARCH(5TE);
9ee6e8bb
PB
8170 rs = (insn >> 8) & 0xf;
8171 rn = (insn >> 12) & 0xf;
8172 rd = (insn >> 16) & 0xf;
8173 if (op1 == 1) {
8174 /* (32 * 16) >> 16 */
5e3f878a
PB
8175 tmp = load_reg(s, rm);
8176 tmp2 = load_reg(s, rs);
9ee6e8bb 8177 if (sh & 4)
5e3f878a 8178 tcg_gen_sari_i32(tmp2, tmp2, 16);
9ee6e8bb 8179 else
5e3f878a 8180 gen_sxth(tmp2);
a7812ae4
PB
8181 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8182 tcg_gen_shri_i64(tmp64, tmp64, 16);
7d1b0095 8183 tmp = tcg_temp_new_i32();
ecc7b3aa 8184 tcg_gen_extrl_i64_i32(tmp, tmp64);
b75263d6 8185 tcg_temp_free_i64(tmp64);
9ee6e8bb 8186 if ((sh & 2) == 0) {
5e3f878a 8187 tmp2 = load_reg(s, rn);
9ef39277 8188 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 8189 tcg_temp_free_i32(tmp2);
9ee6e8bb 8190 }
5e3f878a 8191 store_reg(s, rd, tmp);
9ee6e8bb
PB
8192 } else {
8193 /* 16 * 16 */
5e3f878a
PB
8194 tmp = load_reg(s, rm);
8195 tmp2 = load_reg(s, rs);
8196 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
7d1b0095 8197 tcg_temp_free_i32(tmp2);
9ee6e8bb 8198 if (op1 == 2) {
a7812ae4
PB
8199 tmp64 = tcg_temp_new_i64();
8200 tcg_gen_ext_i32_i64(tmp64, tmp);
7d1b0095 8201 tcg_temp_free_i32(tmp);
a7812ae4
PB
8202 gen_addq(s, tmp64, rn, rd);
8203 gen_storeq_reg(s, rn, rd, tmp64);
b75263d6 8204 tcg_temp_free_i64(tmp64);
9ee6e8bb
PB
8205 } else {
8206 if (op1 == 0) {
5e3f878a 8207 tmp2 = load_reg(s, rn);
9ef39277 8208 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 8209 tcg_temp_free_i32(tmp2);
9ee6e8bb 8210 }
5e3f878a 8211 store_reg(s, rd, tmp);
9ee6e8bb
PB
8212 }
8213 }
8214 break;
8215 default:
8216 goto illegal_op;
8217 }
8218 } else if (((insn & 0x0e000000) == 0 &&
8219 (insn & 0x00000090) != 0x90) ||
8220 ((insn & 0x0e000000) == (1 << 25))) {
8221 int set_cc, logic_cc, shiftop;
8222
8223 op1 = (insn >> 21) & 0xf;
8224 set_cc = (insn >> 20) & 1;
8225 logic_cc = table_logic_cc[op1] & set_cc;
8226
8227 /* data processing instruction */
8228 if (insn & (1 << 25)) {
8229 /* immediate operand */
8230 val = insn & 0xff;
8231 shift = ((insn >> 8) & 0xf) * 2;
e9bb4aa9 8232 if (shift) {
9ee6e8bb 8233 val = (val >> shift) | (val << (32 - shift));
e9bb4aa9 8234 }
7d1b0095 8235 tmp2 = tcg_temp_new_i32();
e9bb4aa9
JR
8236 tcg_gen_movi_i32(tmp2, val);
8237 if (logic_cc && shift) {
8238 gen_set_CF_bit31(tmp2);
8239 }
9ee6e8bb
PB
8240 } else {
8241 /* register */
8242 rm = (insn) & 0xf;
e9bb4aa9 8243 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
8244 shiftop = (insn >> 5) & 3;
8245 if (!(insn & (1 << 4))) {
8246 shift = (insn >> 7) & 0x1f;
e9bb4aa9 8247 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
9ee6e8bb
PB
8248 } else {
8249 rs = (insn >> 8) & 0xf;
8984bd2e 8250 tmp = load_reg(s, rs);
e9bb4aa9 8251 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
9ee6e8bb
PB
8252 }
8253 }
8254 if (op1 != 0x0f && op1 != 0x0d) {
8255 rn = (insn >> 16) & 0xf;
e9bb4aa9
JR
8256 tmp = load_reg(s, rn);
8257 } else {
f764718d 8258 tmp = NULL;
9ee6e8bb
PB
8259 }
8260 rd = (insn >> 12) & 0xf;
8261 switch(op1) {
8262 case 0x00:
e9bb4aa9
JR
8263 tcg_gen_and_i32(tmp, tmp, tmp2);
8264 if (logic_cc) {
8265 gen_logic_CC(tmp);
8266 }
7dcc1f89 8267 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8268 break;
8269 case 0x01:
e9bb4aa9
JR
8270 tcg_gen_xor_i32(tmp, tmp, tmp2);
8271 if (logic_cc) {
8272 gen_logic_CC(tmp);
8273 }
7dcc1f89 8274 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8275 break;
8276 case 0x02:
8277 if (set_cc && rd == 15) {
8278 /* SUBS r15, ... is used for exception return. */
e9bb4aa9 8279 if (IS_USER(s)) {
9ee6e8bb 8280 goto illegal_op;
e9bb4aa9 8281 }
72485ec4 8282 gen_sub_CC(tmp, tmp, tmp2);
e9bb4aa9 8283 gen_exception_return(s, tmp);
9ee6e8bb 8284 } else {
e9bb4aa9 8285 if (set_cc) {
72485ec4 8286 gen_sub_CC(tmp, tmp, tmp2);
e9bb4aa9
JR
8287 } else {
8288 tcg_gen_sub_i32(tmp, tmp, tmp2);
8289 }
7dcc1f89 8290 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8291 }
8292 break;
8293 case 0x03:
e9bb4aa9 8294 if (set_cc) {
72485ec4 8295 gen_sub_CC(tmp, tmp2, tmp);
e9bb4aa9
JR
8296 } else {
8297 tcg_gen_sub_i32(tmp, tmp2, tmp);
8298 }
7dcc1f89 8299 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8300 break;
8301 case 0x04:
e9bb4aa9 8302 if (set_cc) {
72485ec4 8303 gen_add_CC(tmp, tmp, tmp2);
e9bb4aa9
JR
8304 } else {
8305 tcg_gen_add_i32(tmp, tmp, tmp2);
8306 }
7dcc1f89 8307 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8308 break;
8309 case 0x05:
e9bb4aa9 8310 if (set_cc) {
49b4c31e 8311 gen_adc_CC(tmp, tmp, tmp2);
e9bb4aa9
JR
8312 } else {
8313 gen_add_carry(tmp, tmp, tmp2);
8314 }
7dcc1f89 8315 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8316 break;
8317 case 0x06:
e9bb4aa9 8318 if (set_cc) {
2de68a49 8319 gen_sbc_CC(tmp, tmp, tmp2);
e9bb4aa9
JR
8320 } else {
8321 gen_sub_carry(tmp, tmp, tmp2);
8322 }
7dcc1f89 8323 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8324 break;
8325 case 0x07:
e9bb4aa9 8326 if (set_cc) {
2de68a49 8327 gen_sbc_CC(tmp, tmp2, tmp);
e9bb4aa9
JR
8328 } else {
8329 gen_sub_carry(tmp, tmp2, tmp);
8330 }
7dcc1f89 8331 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8332 break;
8333 case 0x08:
8334 if (set_cc) {
e9bb4aa9
JR
8335 tcg_gen_and_i32(tmp, tmp, tmp2);
8336 gen_logic_CC(tmp);
9ee6e8bb 8337 }
7d1b0095 8338 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8339 break;
8340 case 0x09:
8341 if (set_cc) {
e9bb4aa9
JR
8342 tcg_gen_xor_i32(tmp, tmp, tmp2);
8343 gen_logic_CC(tmp);
9ee6e8bb 8344 }
7d1b0095 8345 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8346 break;
8347 case 0x0a:
8348 if (set_cc) {
72485ec4 8349 gen_sub_CC(tmp, tmp, tmp2);
9ee6e8bb 8350 }
7d1b0095 8351 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8352 break;
8353 case 0x0b:
8354 if (set_cc) {
72485ec4 8355 gen_add_CC(tmp, tmp, tmp2);
9ee6e8bb 8356 }
7d1b0095 8357 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8358 break;
8359 case 0x0c:
e9bb4aa9
JR
8360 tcg_gen_or_i32(tmp, tmp, tmp2);
8361 if (logic_cc) {
8362 gen_logic_CC(tmp);
8363 }
7dcc1f89 8364 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8365 break;
8366 case 0x0d:
8367 if (logic_cc && rd == 15) {
8368 /* MOVS r15, ... is used for exception return. */
e9bb4aa9 8369 if (IS_USER(s)) {
9ee6e8bb 8370 goto illegal_op;
e9bb4aa9
JR
8371 }
8372 gen_exception_return(s, tmp2);
9ee6e8bb 8373 } else {
e9bb4aa9
JR
8374 if (logic_cc) {
8375 gen_logic_CC(tmp2);
8376 }
7dcc1f89 8377 store_reg_bx(s, rd, tmp2);
9ee6e8bb
PB
8378 }
8379 break;
8380 case 0x0e:
f669df27 8381 tcg_gen_andc_i32(tmp, tmp, tmp2);
e9bb4aa9
JR
8382 if (logic_cc) {
8383 gen_logic_CC(tmp);
8384 }
7dcc1f89 8385 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8386 break;
8387 default:
8388 case 0x0f:
e9bb4aa9
JR
8389 tcg_gen_not_i32(tmp2, tmp2);
8390 if (logic_cc) {
8391 gen_logic_CC(tmp2);
8392 }
7dcc1f89 8393 store_reg_bx(s, rd, tmp2);
9ee6e8bb
PB
8394 break;
8395 }
e9bb4aa9 8396 if (op1 != 0x0f && op1 != 0x0d) {
7d1b0095 8397 tcg_temp_free_i32(tmp2);
e9bb4aa9 8398 }
9ee6e8bb
PB
8399 } else {
8400 /* other instructions */
8401 op1 = (insn >> 24) & 0xf;
8402 switch(op1) {
8403 case 0x0:
8404 case 0x1:
8405 /* multiplies, extra load/stores */
8406 sh = (insn >> 5) & 3;
8407 if (sh == 0) {
8408 if (op1 == 0x0) {
8409 rd = (insn >> 16) & 0xf;
8410 rn = (insn >> 12) & 0xf;
8411 rs = (insn >> 8) & 0xf;
8412 rm = (insn) & 0xf;
8413 op1 = (insn >> 20) & 0xf;
8414 switch (op1) {
8415 case 0: case 1: case 2: case 3: case 6:
8416 /* 32 bit mul */
5e3f878a
PB
8417 tmp = load_reg(s, rs);
8418 tmp2 = load_reg(s, rm);
8419 tcg_gen_mul_i32(tmp, tmp, tmp2);
7d1b0095 8420 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
8421 if (insn & (1 << 22)) {
8422 /* Subtract (mls) */
8423 ARCH(6T2);
5e3f878a
PB
8424 tmp2 = load_reg(s, rn);
8425 tcg_gen_sub_i32(tmp, tmp2, tmp);
7d1b0095 8426 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
8427 } else if (insn & (1 << 21)) {
8428 /* Add */
5e3f878a
PB
8429 tmp2 = load_reg(s, rn);
8430 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 8431 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
8432 }
8433 if (insn & (1 << 20))
5e3f878a
PB
8434 gen_logic_CC(tmp);
8435 store_reg(s, rd, tmp);
9ee6e8bb 8436 break;
8aac08b1
AJ
8437 case 4:
8438 /* 64 bit mul double accumulate (UMAAL) */
8439 ARCH(6);
8440 tmp = load_reg(s, rs);
8441 tmp2 = load_reg(s, rm);
8442 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
8443 gen_addq_lo(s, tmp64, rn);
8444 gen_addq_lo(s, tmp64, rd);
8445 gen_storeq_reg(s, rn, rd, tmp64);
8446 tcg_temp_free_i64(tmp64);
8447 break;
8448 case 8: case 9: case 10: case 11:
8449 case 12: case 13: case 14: case 15:
8450 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
5e3f878a
PB
8451 tmp = load_reg(s, rs);
8452 tmp2 = load_reg(s, rm);
8aac08b1 8453 if (insn & (1 << 22)) {
c9f10124 8454 tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2);
8aac08b1 8455 } else {
c9f10124 8456 tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2);
8aac08b1
AJ
8457 }
8458 if (insn & (1 << 21)) { /* mult accumulate */
39d5492a
PM
8459 TCGv_i32 al = load_reg(s, rn);
8460 TCGv_i32 ah = load_reg(s, rd);
c9f10124 8461 tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, al, ah);
39d5492a
PM
8462 tcg_temp_free_i32(al);
8463 tcg_temp_free_i32(ah);
9ee6e8bb 8464 }
8aac08b1 8465 if (insn & (1 << 20)) {
c9f10124 8466 gen_logicq_cc(tmp, tmp2);
8aac08b1 8467 }
c9f10124
RH
8468 store_reg(s, rn, tmp);
8469 store_reg(s, rd, tmp2);
9ee6e8bb 8470 break;
8aac08b1
AJ
8471 default:
8472 goto illegal_op;
9ee6e8bb
PB
8473 }
8474 } else {
8475 rn = (insn >> 16) & 0xf;
8476 rd = (insn >> 12) & 0xf;
8477 if (insn & (1 << 23)) {
8478 /* load/store exclusive */
96c55295
PM
8479 bool is_ld = extract32(insn, 20, 1);
8480 bool is_lasr = !extract32(insn, 8, 1);
2359bf80 8481 int op2 = (insn >> 8) & 3;
86753403 8482 op1 = (insn >> 21) & 0x3;
2359bf80
MR
8483
8484 switch (op2) {
8485 case 0: /* lda/stl */
8486 if (op1 == 1) {
8487 goto illegal_op;
8488 }
8489 ARCH(8);
8490 break;
8491 case 1: /* reserved */
8492 goto illegal_op;
8493 case 2: /* ldaex/stlex */
8494 ARCH(8);
8495 break;
8496 case 3: /* ldrex/strex */
8497 if (op1) {
8498 ARCH(6K);
8499 } else {
8500 ARCH(6);
8501 }
8502 break;
8503 }
8504
3174f8e9 8505 addr = tcg_temp_local_new_i32();
98a46317 8506 load_reg_var(s, addr, rn);
2359bf80 8507
96c55295
PM
8508 if (is_lasr && !is_ld) {
8509 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
8510 }
8511
2359bf80 8512 if (op2 == 0) {
96c55295 8513 if (is_ld) {
2359bf80
MR
8514 tmp = tcg_temp_new_i32();
8515 switch (op1) {
8516 case 0: /* lda */
9bb6558a
PM
8517 gen_aa32_ld32u_iss(s, tmp, addr,
8518 get_mem_index(s),
8519 rd | ISSIsAcqRel);
2359bf80
MR
8520 break;
8521 case 2: /* ldab */
9bb6558a
PM
8522 gen_aa32_ld8u_iss(s, tmp, addr,
8523 get_mem_index(s),
8524 rd | ISSIsAcqRel);
2359bf80
MR
8525 break;
8526 case 3: /* ldah */
9bb6558a
PM
8527 gen_aa32_ld16u_iss(s, tmp, addr,
8528 get_mem_index(s),
8529 rd | ISSIsAcqRel);
2359bf80
MR
8530 break;
8531 default:
8532 abort();
8533 }
8534 store_reg(s, rd, tmp);
8535 } else {
8536 rm = insn & 0xf;
8537 tmp = load_reg(s, rm);
8538 switch (op1) {
8539 case 0: /* stl */
9bb6558a
PM
8540 gen_aa32_st32_iss(s, tmp, addr,
8541 get_mem_index(s),
8542 rm | ISSIsAcqRel);
2359bf80
MR
8543 break;
8544 case 2: /* stlb */
9bb6558a
PM
8545 gen_aa32_st8_iss(s, tmp, addr,
8546 get_mem_index(s),
8547 rm | ISSIsAcqRel);
2359bf80
MR
8548 break;
8549 case 3: /* stlh */
9bb6558a
PM
8550 gen_aa32_st16_iss(s, tmp, addr,
8551 get_mem_index(s),
8552 rm | ISSIsAcqRel);
2359bf80
MR
8553 break;
8554 default:
8555 abort();
8556 }
8557 tcg_temp_free_i32(tmp);
8558 }
96c55295 8559 } else if (is_ld) {
86753403
PB
8560 switch (op1) {
8561 case 0: /* ldrex */
426f5abc 8562 gen_load_exclusive(s, rd, 15, addr, 2);
86753403
PB
8563 break;
8564 case 1: /* ldrexd */
426f5abc 8565 gen_load_exclusive(s, rd, rd + 1, addr, 3);
86753403
PB
8566 break;
8567 case 2: /* ldrexb */
426f5abc 8568 gen_load_exclusive(s, rd, 15, addr, 0);
86753403
PB
8569 break;
8570 case 3: /* ldrexh */
426f5abc 8571 gen_load_exclusive(s, rd, 15, addr, 1);
86753403
PB
8572 break;
8573 default:
8574 abort();
8575 }
9ee6e8bb
PB
8576 } else {
8577 rm = insn & 0xf;
86753403
PB
8578 switch (op1) {
8579 case 0: /* strex */
426f5abc 8580 gen_store_exclusive(s, rd, rm, 15, addr, 2);
86753403
PB
8581 break;
8582 case 1: /* strexd */
502e64fe 8583 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
86753403
PB
8584 break;
8585 case 2: /* strexb */
426f5abc 8586 gen_store_exclusive(s, rd, rm, 15, addr, 0);
86753403
PB
8587 break;
8588 case 3: /* strexh */
426f5abc 8589 gen_store_exclusive(s, rd, rm, 15, addr, 1);
86753403
PB
8590 break;
8591 default:
8592 abort();
8593 }
9ee6e8bb 8594 }
39d5492a 8595 tcg_temp_free_i32(addr);
96c55295
PM
8596
8597 if (is_lasr && is_ld) {
8598 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
8599 }
c4869ca6
OS
8600 } else if ((insn & 0x00300f00) == 0) {
8601 /* 0bcccc_0001_0x00_xxxx_xxxx_0000_1001_xxxx
8602 * - SWP, SWPB
8603 */
8604
cf12bce0
EC
8605 TCGv taddr;
8606 TCGMemOp opc = s->be_data;
8607
9ee6e8bb
PB
8608 rm = (insn) & 0xf;
8609
9ee6e8bb 8610 if (insn & (1 << 22)) {
cf12bce0 8611 opc |= MO_UB;
9ee6e8bb 8612 } else {
cf12bce0 8613 opc |= MO_UL | MO_ALIGN;
9ee6e8bb 8614 }
cf12bce0
EC
8615
8616 addr = load_reg(s, rn);
8617 taddr = gen_aa32_addr(s, addr, opc);
7d1b0095 8618 tcg_temp_free_i32(addr);
cf12bce0
EC
8619
8620 tmp = load_reg(s, rm);
8621 tcg_gen_atomic_xchg_i32(tmp, taddr, tmp,
8622 get_mem_index(s), opc);
8623 tcg_temp_free(taddr);
8624 store_reg(s, rd, tmp);
c4869ca6
OS
8625 } else {
8626 goto illegal_op;
9ee6e8bb
PB
8627 }
8628 }
8629 } else {
8630 int address_offset;
3960c336 8631 bool load = insn & (1 << 20);
63f26fcf
PM
8632 bool wbit = insn & (1 << 21);
8633 bool pbit = insn & (1 << 24);
3960c336 8634 bool doubleword = false;
9bb6558a
PM
8635 ISSInfo issinfo;
8636
9ee6e8bb
PB
8637 /* Misc load/store */
8638 rn = (insn >> 16) & 0xf;
8639 rd = (insn >> 12) & 0xf;
3960c336 8640
9bb6558a
PM
8641 /* ISS not valid if writeback */
8642 issinfo = (pbit & !wbit) ? rd : ISSInvalid;
8643
3960c336
PM
8644 if (!load && (sh & 2)) {
8645 /* doubleword */
8646 ARCH(5TE);
8647 if (rd & 1) {
8648 /* UNPREDICTABLE; we choose to UNDEF */
8649 goto illegal_op;
8650 }
8651 load = (sh & 1) == 0;
8652 doubleword = true;
8653 }
8654
b0109805 8655 addr = load_reg(s, rn);
63f26fcf 8656 if (pbit) {
b0109805 8657 gen_add_datah_offset(s, insn, 0, addr);
63f26fcf 8658 }
9ee6e8bb 8659 address_offset = 0;
3960c336
PM
8660
8661 if (doubleword) {
8662 if (!load) {
9ee6e8bb 8663 /* store */
b0109805 8664 tmp = load_reg(s, rd);
12dcc321 8665 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 8666 tcg_temp_free_i32(tmp);
b0109805
PB
8667 tcg_gen_addi_i32(addr, addr, 4);
8668 tmp = load_reg(s, rd + 1);
12dcc321 8669 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 8670 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8671 } else {
8672 /* load */
5a839c0d 8673 tmp = tcg_temp_new_i32();
12dcc321 8674 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805
PB
8675 store_reg(s, rd, tmp);
8676 tcg_gen_addi_i32(addr, addr, 4);
5a839c0d 8677 tmp = tcg_temp_new_i32();
12dcc321 8678 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9ee6e8bb 8679 rd++;
9ee6e8bb
PB
8680 }
8681 address_offset = -4;
3960c336
PM
8682 } else if (load) {
8683 /* load */
8684 tmp = tcg_temp_new_i32();
8685 switch (sh) {
8686 case 1:
9bb6558a
PM
8687 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s),
8688 issinfo);
3960c336
PM
8689 break;
8690 case 2:
9bb6558a
PM
8691 gen_aa32_ld8s_iss(s, tmp, addr, get_mem_index(s),
8692 issinfo);
3960c336
PM
8693 break;
8694 default:
8695 case 3:
9bb6558a
PM
8696 gen_aa32_ld16s_iss(s, tmp, addr, get_mem_index(s),
8697 issinfo);
3960c336
PM
8698 break;
8699 }
9ee6e8bb
PB
8700 } else {
8701 /* store */
b0109805 8702 tmp = load_reg(s, rd);
9bb6558a 8703 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), issinfo);
5a839c0d 8704 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8705 }
8706 /* Perform base writeback before the loaded value to
8707 ensure correct behavior with overlapping index registers.
b6af0975 8708 ldrd with base writeback is undefined if the
9ee6e8bb 8709 destination and index registers overlap. */
63f26fcf 8710 if (!pbit) {
b0109805
PB
8711 gen_add_datah_offset(s, insn, address_offset, addr);
8712 store_reg(s, rn, addr);
63f26fcf 8713 } else if (wbit) {
9ee6e8bb 8714 if (address_offset)
b0109805
PB
8715 tcg_gen_addi_i32(addr, addr, address_offset);
8716 store_reg(s, rn, addr);
8717 } else {
7d1b0095 8718 tcg_temp_free_i32(addr);
9ee6e8bb
PB
8719 }
8720 if (load) {
8721 /* Complete the load. */
b0109805 8722 store_reg(s, rd, tmp);
9ee6e8bb
PB
8723 }
8724 }
8725 break;
8726 case 0x4:
8727 case 0x5:
8728 goto do_ldst;
8729 case 0x6:
8730 case 0x7:
8731 if (insn & (1 << 4)) {
8732 ARCH(6);
8733 /* Armv6 Media instructions. */
8734 rm = insn & 0xf;
8735 rn = (insn >> 16) & 0xf;
2c0262af 8736 rd = (insn >> 12) & 0xf;
9ee6e8bb
PB
8737 rs = (insn >> 8) & 0xf;
8738 switch ((insn >> 23) & 3) {
8739 case 0: /* Parallel add/subtract. */
8740 op1 = (insn >> 20) & 7;
6ddbc6e4
PB
8741 tmp = load_reg(s, rn);
8742 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
8743 sh = (insn >> 5) & 7;
8744 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
8745 goto illegal_op;
6ddbc6e4 8746 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
7d1b0095 8747 tcg_temp_free_i32(tmp2);
6ddbc6e4 8748 store_reg(s, rd, tmp);
9ee6e8bb
PB
8749 break;
8750 case 1:
8751 if ((insn & 0x00700020) == 0) {
6c95676b 8752 /* Halfword pack. */
3670669c
PB
8753 tmp = load_reg(s, rn);
8754 tmp2 = load_reg(s, rm);
9ee6e8bb 8755 shift = (insn >> 7) & 0x1f;
3670669c
PB
8756 if (insn & (1 << 6)) {
8757 /* pkhtb */
22478e79
AZ
8758 if (shift == 0)
8759 shift = 31;
8760 tcg_gen_sari_i32(tmp2, tmp2, shift);
3670669c 8761 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
86831435 8762 tcg_gen_ext16u_i32(tmp2, tmp2);
3670669c
PB
8763 } else {
8764 /* pkhbt */
22478e79
AZ
8765 if (shift)
8766 tcg_gen_shli_i32(tmp2, tmp2, shift);
86831435 8767 tcg_gen_ext16u_i32(tmp, tmp);
3670669c
PB
8768 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
8769 }
8770 tcg_gen_or_i32(tmp, tmp, tmp2);
7d1b0095 8771 tcg_temp_free_i32(tmp2);
3670669c 8772 store_reg(s, rd, tmp);
9ee6e8bb
PB
8773 } else if ((insn & 0x00200020) == 0x00200000) {
8774 /* [us]sat */
6ddbc6e4 8775 tmp = load_reg(s, rm);
9ee6e8bb
PB
8776 shift = (insn >> 7) & 0x1f;
8777 if (insn & (1 << 6)) {
8778 if (shift == 0)
8779 shift = 31;
6ddbc6e4 8780 tcg_gen_sari_i32(tmp, tmp, shift);
9ee6e8bb 8781 } else {
6ddbc6e4 8782 tcg_gen_shli_i32(tmp, tmp, shift);
9ee6e8bb
PB
8783 }
8784 sh = (insn >> 16) & 0x1f;
40d3c433
CL
8785 tmp2 = tcg_const_i32(sh);
8786 if (insn & (1 << 22))
9ef39277 8787 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
40d3c433 8788 else
9ef39277 8789 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
40d3c433 8790 tcg_temp_free_i32(tmp2);
6ddbc6e4 8791 store_reg(s, rd, tmp);
9ee6e8bb
PB
8792 } else if ((insn & 0x00300fe0) == 0x00200f20) {
8793 /* [us]sat16 */
6ddbc6e4 8794 tmp = load_reg(s, rm);
9ee6e8bb 8795 sh = (insn >> 16) & 0x1f;
40d3c433
CL
8796 tmp2 = tcg_const_i32(sh);
8797 if (insn & (1 << 22))
9ef39277 8798 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
40d3c433 8799 else
9ef39277 8800 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
40d3c433 8801 tcg_temp_free_i32(tmp2);
6ddbc6e4 8802 store_reg(s, rd, tmp);
9ee6e8bb
PB
8803 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
8804 /* Select bytes. */
6ddbc6e4
PB
8805 tmp = load_reg(s, rn);
8806 tmp2 = load_reg(s, rm);
7d1b0095 8807 tmp3 = tcg_temp_new_i32();
0ecb72a5 8808 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 8809 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7d1b0095
PM
8810 tcg_temp_free_i32(tmp3);
8811 tcg_temp_free_i32(tmp2);
6ddbc6e4 8812 store_reg(s, rd, tmp);
9ee6e8bb 8813 } else if ((insn & 0x000003e0) == 0x00000060) {
5e3f878a 8814 tmp = load_reg(s, rm);
9ee6e8bb 8815 shift = (insn >> 10) & 3;
1301f322 8816 /* ??? In many cases it's not necessary to do a
9ee6e8bb
PB
8817 rotate, a shift is sufficient. */
8818 if (shift != 0)
f669df27 8819 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
9ee6e8bb
PB
8820 op1 = (insn >> 20) & 7;
8821 switch (op1) {
5e3f878a
PB
8822 case 0: gen_sxtb16(tmp); break;
8823 case 2: gen_sxtb(tmp); break;
8824 case 3: gen_sxth(tmp); break;
8825 case 4: gen_uxtb16(tmp); break;
8826 case 6: gen_uxtb(tmp); break;
8827 case 7: gen_uxth(tmp); break;
9ee6e8bb
PB
8828 default: goto illegal_op;
8829 }
8830 if (rn != 15) {
5e3f878a 8831 tmp2 = load_reg(s, rn);
9ee6e8bb 8832 if ((op1 & 3) == 0) {
5e3f878a 8833 gen_add16(tmp, tmp2);
9ee6e8bb 8834 } else {
5e3f878a 8835 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 8836 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
8837 }
8838 }
6c95676b 8839 store_reg(s, rd, tmp);
9ee6e8bb
PB
8840 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
8841 /* rev */
b0109805 8842 tmp = load_reg(s, rm);
9ee6e8bb
PB
8843 if (insn & (1 << 22)) {
8844 if (insn & (1 << 7)) {
b0109805 8845 gen_revsh(tmp);
9ee6e8bb
PB
8846 } else {
8847 ARCH(6T2);
b0109805 8848 gen_helper_rbit(tmp, tmp);
9ee6e8bb
PB
8849 }
8850 } else {
8851 if (insn & (1 << 7))
b0109805 8852 gen_rev16(tmp);
9ee6e8bb 8853 else
66896cb8 8854 tcg_gen_bswap32_i32(tmp, tmp);
9ee6e8bb 8855 }
b0109805 8856 store_reg(s, rd, tmp);
9ee6e8bb
PB
8857 } else {
8858 goto illegal_op;
8859 }
8860 break;
8861 case 2: /* Multiplies (Type 3). */
41e9564d
PM
8862 switch ((insn >> 20) & 0x7) {
8863 case 5:
8864 if (((insn >> 6) ^ (insn >> 7)) & 1) {
8865 /* op2 not 00x or 11x : UNDEF */
8866 goto illegal_op;
8867 }
838fa72d
AJ
8868 /* Signed multiply most significant [accumulate].
8869 (SMMUL, SMMLA, SMMLS) */
41e9564d
PM
8870 tmp = load_reg(s, rm);
8871 tmp2 = load_reg(s, rs);
a7812ae4 8872 tmp64 = gen_muls_i64_i32(tmp, tmp2);
838fa72d 8873
955a7dd5 8874 if (rd != 15) {
838fa72d 8875 tmp = load_reg(s, rd);
9ee6e8bb 8876 if (insn & (1 << 6)) {
838fa72d 8877 tmp64 = gen_subq_msw(tmp64, tmp);
9ee6e8bb 8878 } else {
838fa72d 8879 tmp64 = gen_addq_msw(tmp64, tmp);
9ee6e8bb
PB
8880 }
8881 }
838fa72d
AJ
8882 if (insn & (1 << 5)) {
8883 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
8884 }
8885 tcg_gen_shri_i64(tmp64, tmp64, 32);
7d1b0095 8886 tmp = tcg_temp_new_i32();
ecc7b3aa 8887 tcg_gen_extrl_i64_i32(tmp, tmp64);
838fa72d 8888 tcg_temp_free_i64(tmp64);
955a7dd5 8889 store_reg(s, rn, tmp);
41e9564d
PM
8890 break;
8891 case 0:
8892 case 4:
8893 /* SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD */
8894 if (insn & (1 << 7)) {
8895 goto illegal_op;
8896 }
8897 tmp = load_reg(s, rm);
8898 tmp2 = load_reg(s, rs);
9ee6e8bb 8899 if (insn & (1 << 5))
5e3f878a
PB
8900 gen_swap_half(tmp2);
8901 gen_smul_dual(tmp, tmp2);
9ee6e8bb 8902 if (insn & (1 << 22)) {
5e3f878a 8903 /* smlald, smlsld */
33bbd75a
PC
8904 TCGv_i64 tmp64_2;
8905
a7812ae4 8906 tmp64 = tcg_temp_new_i64();
33bbd75a 8907 tmp64_2 = tcg_temp_new_i64();
a7812ae4 8908 tcg_gen_ext_i32_i64(tmp64, tmp);
33bbd75a 8909 tcg_gen_ext_i32_i64(tmp64_2, tmp2);
7d1b0095 8910 tcg_temp_free_i32(tmp);
33bbd75a
PC
8911 tcg_temp_free_i32(tmp2);
8912 if (insn & (1 << 6)) {
8913 tcg_gen_sub_i64(tmp64, tmp64, tmp64_2);
8914 } else {
8915 tcg_gen_add_i64(tmp64, tmp64, tmp64_2);
8916 }
8917 tcg_temp_free_i64(tmp64_2);
a7812ae4
PB
8918 gen_addq(s, tmp64, rd, rn);
8919 gen_storeq_reg(s, rd, rn, tmp64);
b75263d6 8920 tcg_temp_free_i64(tmp64);
9ee6e8bb 8921 } else {
5e3f878a 8922 /* smuad, smusd, smlad, smlsd */
33bbd75a
PC
8923 if (insn & (1 << 6)) {
8924 /* This subtraction cannot overflow. */
8925 tcg_gen_sub_i32(tmp, tmp, tmp2);
8926 } else {
8927 /* This addition cannot overflow 32 bits;
8928 * however it may overflow considered as a
8929 * signed operation, in which case we must set
8930 * the Q flag.
8931 */
8932 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8933 }
8934 tcg_temp_free_i32(tmp2);
22478e79 8935 if (rd != 15)
9ee6e8bb 8936 {
22478e79 8937 tmp2 = load_reg(s, rd);
9ef39277 8938 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 8939 tcg_temp_free_i32(tmp2);
9ee6e8bb 8940 }
22478e79 8941 store_reg(s, rn, tmp);
9ee6e8bb 8942 }
41e9564d 8943 break;
b8b8ea05
PM
8944 case 1:
8945 case 3:
8946 /* SDIV, UDIV */
7e0cf8b4 8947 if (!dc_isar_feature(arm_div, s)) {
b8b8ea05
PM
8948 goto illegal_op;
8949 }
8950 if (((insn >> 5) & 7) || (rd != 15)) {
8951 goto illegal_op;
8952 }
8953 tmp = load_reg(s, rm);
8954 tmp2 = load_reg(s, rs);
8955 if (insn & (1 << 21)) {
8956 gen_helper_udiv(tmp, tmp, tmp2);
8957 } else {
8958 gen_helper_sdiv(tmp, tmp, tmp2);
8959 }
8960 tcg_temp_free_i32(tmp2);
8961 store_reg(s, rn, tmp);
8962 break;
41e9564d
PM
8963 default:
8964 goto illegal_op;
9ee6e8bb
PB
8965 }
8966 break;
8967 case 3:
8968 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
8969 switch (op1) {
8970 case 0: /* Unsigned sum of absolute differences. */
6ddbc6e4
PB
8971 ARCH(6);
8972 tmp = load_reg(s, rm);
8973 tmp2 = load_reg(s, rs);
8974 gen_helper_usad8(tmp, tmp, tmp2);
7d1b0095 8975 tcg_temp_free_i32(tmp2);
ded9d295
AZ
8976 if (rd != 15) {
8977 tmp2 = load_reg(s, rd);
6ddbc6e4 8978 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 8979 tcg_temp_free_i32(tmp2);
9ee6e8bb 8980 }
ded9d295 8981 store_reg(s, rn, tmp);
9ee6e8bb
PB
8982 break;
8983 case 0x20: case 0x24: case 0x28: case 0x2c:
8984 /* Bitfield insert/clear. */
8985 ARCH(6T2);
8986 shift = (insn >> 7) & 0x1f;
8987 i = (insn >> 16) & 0x1f;
45140a57
KB
8988 if (i < shift) {
8989 /* UNPREDICTABLE; we choose to UNDEF */
8990 goto illegal_op;
8991 }
9ee6e8bb
PB
8992 i = i + 1 - shift;
8993 if (rm == 15) {
7d1b0095 8994 tmp = tcg_temp_new_i32();
5e3f878a 8995 tcg_gen_movi_i32(tmp, 0);
9ee6e8bb 8996 } else {
5e3f878a 8997 tmp = load_reg(s, rm);
9ee6e8bb
PB
8998 }
8999 if (i != 32) {
5e3f878a 9000 tmp2 = load_reg(s, rd);
d593c48e 9001 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, i);
7d1b0095 9002 tcg_temp_free_i32(tmp2);
9ee6e8bb 9003 }
5e3f878a 9004 store_reg(s, rd, tmp);
9ee6e8bb
PB
9005 break;
9006 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
9007 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
4cc633c3 9008 ARCH(6T2);
5e3f878a 9009 tmp = load_reg(s, rm);
9ee6e8bb
PB
9010 shift = (insn >> 7) & 0x1f;
9011 i = ((insn >> 16) & 0x1f) + 1;
9012 if (shift + i > 32)
9013 goto illegal_op;
9014 if (i < 32) {
9015 if (op1 & 0x20) {
59a71b4c 9016 tcg_gen_extract_i32(tmp, tmp, shift, i);
9ee6e8bb 9017 } else {
59a71b4c 9018 tcg_gen_sextract_i32(tmp, tmp, shift, i);
9ee6e8bb
PB
9019 }
9020 }
5e3f878a 9021 store_reg(s, rd, tmp);
9ee6e8bb
PB
9022 break;
9023 default:
9024 goto illegal_op;
9025 }
9026 break;
9027 }
9028 break;
9029 }
9030 do_ldst:
9031 /* Check for undefined extension instructions
9032 * per the ARM Bible IE:
9033 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
9034 */
9035 sh = (0xf << 20) | (0xf << 4);
9036 if (op1 == 0x7 && ((insn & sh) == sh))
9037 {
9038 goto illegal_op;
9039 }
9040 /* load/store byte/word */
9041 rn = (insn >> 16) & 0xf;
9042 rd = (insn >> 12) & 0xf;
b0109805 9043 tmp2 = load_reg(s, rn);
a99caa48
PM
9044 if ((insn & 0x01200000) == 0x00200000) {
9045 /* ldrt/strt */
579d21cc 9046 i = get_a32_user_mem_index(s);
a99caa48
PM
9047 } else {
9048 i = get_mem_index(s);
9049 }
9ee6e8bb 9050 if (insn & (1 << 24))
b0109805 9051 gen_add_data_offset(s, insn, tmp2);
9ee6e8bb
PB
9052 if (insn & (1 << 20)) {
9053 /* load */
5a839c0d 9054 tmp = tcg_temp_new_i32();
9ee6e8bb 9055 if (insn & (1 << 22)) {
9bb6558a 9056 gen_aa32_ld8u_iss(s, tmp, tmp2, i, rd);
9ee6e8bb 9057 } else {
9bb6558a 9058 gen_aa32_ld32u_iss(s, tmp, tmp2, i, rd);
9ee6e8bb 9059 }
9ee6e8bb
PB
9060 } else {
9061 /* store */
b0109805 9062 tmp = load_reg(s, rd);
5a839c0d 9063 if (insn & (1 << 22)) {
9bb6558a 9064 gen_aa32_st8_iss(s, tmp, tmp2, i, rd);
5a839c0d 9065 } else {
9bb6558a 9066 gen_aa32_st32_iss(s, tmp, tmp2, i, rd);
5a839c0d
PM
9067 }
9068 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
9069 }
9070 if (!(insn & (1 << 24))) {
b0109805
PB
9071 gen_add_data_offset(s, insn, tmp2);
9072 store_reg(s, rn, tmp2);
9073 } else if (insn & (1 << 21)) {
9074 store_reg(s, rn, tmp2);
9075 } else {
7d1b0095 9076 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
9077 }
9078 if (insn & (1 << 20)) {
9079 /* Complete the load. */
7dcc1f89 9080 store_reg_from_load(s, rd, tmp);
9ee6e8bb
PB
9081 }
9082 break;
9083 case 0x08:
9084 case 0x09:
9085 {
da3e53dd
PM
9086 int j, n, loaded_base;
9087 bool exc_return = false;
9088 bool is_load = extract32(insn, 20, 1);
9089 bool user = false;
39d5492a 9090 TCGv_i32 loaded_var;
9ee6e8bb
PB
9091 /* load/store multiple words */
9092 /* XXX: store correct base if write back */
9ee6e8bb 9093 if (insn & (1 << 22)) {
da3e53dd 9094 /* LDM (user), LDM (exception return) and STM (user) */
9ee6e8bb
PB
9095 if (IS_USER(s))
9096 goto illegal_op; /* only usable in supervisor mode */
9097
da3e53dd
PM
9098 if (is_load && extract32(insn, 15, 1)) {
9099 exc_return = true;
9100 } else {
9101 user = true;
9102 }
9ee6e8bb
PB
9103 }
9104 rn = (insn >> 16) & 0xf;
b0109805 9105 addr = load_reg(s, rn);
9ee6e8bb
PB
9106
9107 /* compute total size */
9108 loaded_base = 0;
f764718d 9109 loaded_var = NULL;
9ee6e8bb 9110 n = 0;
9798ac71 9111 for (i = 0; i < 16; i++) {
9ee6e8bb
PB
9112 if (insn & (1 << i))
9113 n++;
9114 }
9115 /* XXX: test invalid n == 0 case ? */
9116 if (insn & (1 << 23)) {
9117 if (insn & (1 << 24)) {
9118 /* pre increment */
b0109805 9119 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb
PB
9120 } else {
9121 /* post increment */
9122 }
9123 } else {
9124 if (insn & (1 << 24)) {
9125 /* pre decrement */
b0109805 9126 tcg_gen_addi_i32(addr, addr, -(n * 4));
9ee6e8bb
PB
9127 } else {
9128 /* post decrement */
9129 if (n != 1)
b0109805 9130 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
9ee6e8bb
PB
9131 }
9132 }
9133 j = 0;
9798ac71 9134 for (i = 0; i < 16; i++) {
9ee6e8bb 9135 if (insn & (1 << i)) {
da3e53dd 9136 if (is_load) {
9ee6e8bb 9137 /* load */
5a839c0d 9138 tmp = tcg_temp_new_i32();
12dcc321 9139 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
be5e7a76 9140 if (user) {
b75263d6 9141 tmp2 = tcg_const_i32(i);
1ce94f81 9142 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
b75263d6 9143 tcg_temp_free_i32(tmp2);
7d1b0095 9144 tcg_temp_free_i32(tmp);
9ee6e8bb 9145 } else if (i == rn) {
b0109805 9146 loaded_var = tmp;
9ee6e8bb 9147 loaded_base = 1;
9d090d17 9148 } else if (i == 15 && exc_return) {
fb0e8e79 9149 store_pc_exc_ret(s, tmp);
9ee6e8bb 9150 } else {
7dcc1f89 9151 store_reg_from_load(s, i, tmp);
9ee6e8bb
PB
9152 }
9153 } else {
9154 /* store */
9155 if (i == 15) {
9156 /* special case: r15 = PC + 8 */
9157 val = (long)s->pc + 4;
7d1b0095 9158 tmp = tcg_temp_new_i32();
b0109805 9159 tcg_gen_movi_i32(tmp, val);
9ee6e8bb 9160 } else if (user) {
7d1b0095 9161 tmp = tcg_temp_new_i32();
b75263d6 9162 tmp2 = tcg_const_i32(i);
9ef39277 9163 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
b75263d6 9164 tcg_temp_free_i32(tmp2);
9ee6e8bb 9165 } else {
b0109805 9166 tmp = load_reg(s, i);
9ee6e8bb 9167 }
12dcc321 9168 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 9169 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
9170 }
9171 j++;
9172 /* no need to add after the last transfer */
9173 if (j != n)
b0109805 9174 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb
PB
9175 }
9176 }
9177 if (insn & (1 << 21)) {
9178 /* write back */
9179 if (insn & (1 << 23)) {
9180 if (insn & (1 << 24)) {
9181 /* pre increment */
9182 } else {
9183 /* post increment */
b0109805 9184 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb
PB
9185 }
9186 } else {
9187 if (insn & (1 << 24)) {
9188 /* pre decrement */
9189 if (n != 1)
b0109805 9190 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
9ee6e8bb
PB
9191 } else {
9192 /* post decrement */
b0109805 9193 tcg_gen_addi_i32(addr, addr, -(n * 4));
9ee6e8bb
PB
9194 }
9195 }
b0109805
PB
9196 store_reg(s, rn, addr);
9197 } else {
7d1b0095 9198 tcg_temp_free_i32(addr);
9ee6e8bb
PB
9199 }
9200 if (loaded_base) {
b0109805 9201 store_reg(s, rn, loaded_var);
9ee6e8bb 9202 }
da3e53dd 9203 if (exc_return) {
9ee6e8bb 9204 /* Restore CPSR from SPSR. */
d9ba4830 9205 tmp = load_cpu_field(spsr);
e69ad9df
AL
9206 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
9207 gen_io_start();
9208 }
235ea1f5 9209 gen_helper_cpsr_write_eret(cpu_env, tmp);
e69ad9df
AL
9210 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
9211 gen_io_end();
9212 }
7d1b0095 9213 tcg_temp_free_i32(tmp);
b29fd33d 9214 /* Must exit loop to check un-masked IRQs */
dcba3a8d 9215 s->base.is_jmp = DISAS_EXIT;
9ee6e8bb
PB
9216 }
9217 }
9218 break;
9219 case 0xa:
9220 case 0xb:
9221 {
9222 int32_t offset;
9223
9224 /* branch (and link) */
9225 val = (int32_t)s->pc;
9226 if (insn & (1 << 24)) {
7d1b0095 9227 tmp = tcg_temp_new_i32();
5e3f878a
PB
9228 tcg_gen_movi_i32(tmp, val);
9229 store_reg(s, 14, tmp);
9ee6e8bb 9230 }
534df156
PM
9231 offset = sextract32(insn << 2, 0, 26);
9232 val += offset + 4;
9ee6e8bb
PB
9233 gen_jmp(s, val);
9234 }
9235 break;
9236 case 0xc:
9237 case 0xd:
9238 case 0xe:
6a57f3eb
WN
9239 if (((insn >> 8) & 0xe) == 10) {
9240 /* VFP. */
7dcc1f89 9241 if (disas_vfp_insn(s, insn)) {
6a57f3eb
WN
9242 goto illegal_op;
9243 }
7dcc1f89 9244 } else if (disas_coproc_insn(s, insn)) {
6a57f3eb 9245 /* Coprocessor. */
9ee6e8bb 9246 goto illegal_op;
6a57f3eb 9247 }
9ee6e8bb
PB
9248 break;
9249 case 0xf:
9250 /* swi */
eaed129d 9251 gen_set_pc_im(s, s->pc);
d4a2dc67 9252 s->svc_imm = extract32(insn, 0, 24);
dcba3a8d 9253 s->base.is_jmp = DISAS_SWI;
9ee6e8bb
PB
9254 break;
9255 default:
9256 illegal_op:
73710361
GB
9257 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
9258 default_exception_el(s));
9ee6e8bb
PB
9259 break;
9260 }
9261 }
9262}
9263
296e5a0a
PM
9264static bool thumb_insn_is_16bit(DisasContext *s, uint32_t insn)
9265{
9266 /* Return true if this is a 16 bit instruction. We must be precise
9267 * about this (matching the decode). We assume that s->pc still
9268 * points to the first 16 bits of the insn.
9269 */
9270 if ((insn >> 11) < 0x1d) {
9271 /* Definitely a 16-bit instruction */
9272 return true;
9273 }
9274
9275 /* Top five bits 0b11101 / 0b11110 / 0b11111 : this is the
9276 * first half of a 32-bit Thumb insn. Thumb-1 cores might
9277 * end up actually treating this as two 16-bit insns, though,
9278 * if it's half of a bl/blx pair that might span a page boundary.
9279 */
14120108
JS
9280 if (arm_dc_feature(s, ARM_FEATURE_THUMB2) ||
9281 arm_dc_feature(s, ARM_FEATURE_M)) {
296e5a0a
PM
9282 /* Thumb2 cores (including all M profile ones) always treat
9283 * 32-bit insns as 32-bit.
9284 */
9285 return false;
9286 }
9287
bfe7ad5b 9288 if ((insn >> 11) == 0x1e && s->pc - s->page_start < TARGET_PAGE_SIZE - 3) {
296e5a0a
PM
9289 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix, and the suffix
9290 * is not on the next page; we merge this into a 32-bit
9291 * insn.
9292 */
9293 return false;
9294 }
9295 /* 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF);
9296 * 0b1111_1xxx_xxxx_xxxx : BL suffix;
9297 * 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix on the end of a page
9298 * -- handle as single 16 bit insn
9299 */
9300 return true;
9301}
9302
9ee6e8bb
PB
9303/* Return true if this is a Thumb-2 logical op. */
9304static int
9305thumb2_logic_op(int op)
9306{
9307 return (op < 8);
9308}
9309
9310/* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
9311 then set condition code flags based on the result of the operation.
9312 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
9313 to the high bit of T1.
9314 Returns zero if the opcode is valid. */
9315
9316static int
39d5492a
PM
9317gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out,
9318 TCGv_i32 t0, TCGv_i32 t1)
9ee6e8bb
PB
9319{
9320 int logic_cc;
9321
9322 logic_cc = 0;
9323 switch (op) {
9324 case 0: /* and */
396e467c 9325 tcg_gen_and_i32(t0, t0, t1);
9ee6e8bb
PB
9326 logic_cc = conds;
9327 break;
9328 case 1: /* bic */
f669df27 9329 tcg_gen_andc_i32(t0, t0, t1);
9ee6e8bb
PB
9330 logic_cc = conds;
9331 break;
9332 case 2: /* orr */
396e467c 9333 tcg_gen_or_i32(t0, t0, t1);
9ee6e8bb
PB
9334 logic_cc = conds;
9335 break;
9336 case 3: /* orn */
29501f1b 9337 tcg_gen_orc_i32(t0, t0, t1);
9ee6e8bb
PB
9338 logic_cc = conds;
9339 break;
9340 case 4: /* eor */
396e467c 9341 tcg_gen_xor_i32(t0, t0, t1);
9ee6e8bb
PB
9342 logic_cc = conds;
9343 break;
9344 case 8: /* add */
9345 if (conds)
72485ec4 9346 gen_add_CC(t0, t0, t1);
9ee6e8bb 9347 else
396e467c 9348 tcg_gen_add_i32(t0, t0, t1);
9ee6e8bb
PB
9349 break;
9350 case 10: /* adc */
9351 if (conds)
49b4c31e 9352 gen_adc_CC(t0, t0, t1);
9ee6e8bb 9353 else
396e467c 9354 gen_adc(t0, t1);
9ee6e8bb
PB
9355 break;
9356 case 11: /* sbc */
2de68a49
RH
9357 if (conds) {
9358 gen_sbc_CC(t0, t0, t1);
9359 } else {
396e467c 9360 gen_sub_carry(t0, t0, t1);
2de68a49 9361 }
9ee6e8bb
PB
9362 break;
9363 case 13: /* sub */
9364 if (conds)
72485ec4 9365 gen_sub_CC(t0, t0, t1);
9ee6e8bb 9366 else
396e467c 9367 tcg_gen_sub_i32(t0, t0, t1);
9ee6e8bb
PB
9368 break;
9369 case 14: /* rsb */
9370 if (conds)
72485ec4 9371 gen_sub_CC(t0, t1, t0);
9ee6e8bb 9372 else
396e467c 9373 tcg_gen_sub_i32(t0, t1, t0);
9ee6e8bb
PB
9374 break;
9375 default: /* 5, 6, 7, 9, 12, 15. */
9376 return 1;
9377 }
9378 if (logic_cc) {
396e467c 9379 gen_logic_CC(t0);
9ee6e8bb 9380 if (shifter_out)
396e467c 9381 gen_set_CF_bit31(t1);
9ee6e8bb
PB
9382 }
9383 return 0;
9384}
9385
2eea841c
PM
9386/* Translate a 32-bit thumb instruction. */
9387static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
9ee6e8bb 9388{
296e5a0a 9389 uint32_t imm, shift, offset;
9ee6e8bb 9390 uint32_t rd, rn, rm, rs;
39d5492a
PM
9391 TCGv_i32 tmp;
9392 TCGv_i32 tmp2;
9393 TCGv_i32 tmp3;
9394 TCGv_i32 addr;
a7812ae4 9395 TCGv_i64 tmp64;
9ee6e8bb
PB
9396 int op;
9397 int shiftop;
9398 int conds;
9399 int logic_cc;
9400
14120108
JS
9401 /*
9402 * ARMv6-M supports a limited subset of Thumb2 instructions.
9403 * Other Thumb1 architectures allow only 32-bit
9404 * combined BL/BLX prefix and suffix.
296e5a0a 9405 */
14120108
JS
9406 if (arm_dc_feature(s, ARM_FEATURE_M) &&
9407 !arm_dc_feature(s, ARM_FEATURE_V7)) {
9408 int i;
9409 bool found = false;
8297cb13
JS
9410 static const uint32_t armv6m_insn[] = {0xf3808000 /* msr */,
9411 0xf3b08040 /* dsb */,
9412 0xf3b08050 /* dmb */,
9413 0xf3b08060 /* isb */,
9414 0xf3e08000 /* mrs */,
9415 0xf000d000 /* bl */};
9416 static const uint32_t armv6m_mask[] = {0xffe0d000,
9417 0xfff0d0f0,
9418 0xfff0d0f0,
9419 0xfff0d0f0,
9420 0xffe0d000,
9421 0xf800d000};
14120108
JS
9422
9423 for (i = 0; i < ARRAY_SIZE(armv6m_insn); i++) {
9424 if ((insn & armv6m_mask[i]) == armv6m_insn[i]) {
9425 found = true;
9426 break;
9427 }
9428 }
9429 if (!found) {
9430 goto illegal_op;
9431 }
9432 } else if ((insn & 0xf800e800) != 0xf000e800) {
9ee6e8bb
PB
9433 ARCH(6T2);
9434 }
9435
9436 rn = (insn >> 16) & 0xf;
9437 rs = (insn >> 12) & 0xf;
9438 rd = (insn >> 8) & 0xf;
9439 rm = insn & 0xf;
9440 switch ((insn >> 25) & 0xf) {
9441 case 0: case 1: case 2: case 3:
9442 /* 16-bit instructions. Should never happen. */
9443 abort();
9444 case 4:
9445 if (insn & (1 << 22)) {
ebfe27c5
PM
9446 /* 0b1110_100x_x1xx_xxxx_xxxx_xxxx_xxxx_xxxx
9447 * - load/store doubleword, load/store exclusive, ldacq/strel,
5158de24 9448 * table branch, TT.
ebfe27c5 9449 */
76eff04d
PM
9450 if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_M) &&
9451 arm_dc_feature(s, ARM_FEATURE_V8)) {
9452 /* 0b1110_1001_0111_1111_1110_1001_0111_111
9453 * - SG (v8M only)
9454 * The bulk of the behaviour for this instruction is implemented
9455 * in v7m_handle_execute_nsc(), which deals with the insn when
9456 * it is executed by a CPU in non-secure state from memory
9457 * which is Secure & NonSecure-Callable.
9458 * Here we only need to handle the remaining cases:
9459 * * in NS memory (including the "security extension not
9460 * implemented" case) : NOP
9461 * * in S memory but CPU already secure (clear IT bits)
9462 * We know that the attribute for the memory this insn is
9463 * in must match the current CPU state, because otherwise
9464 * get_phys_addr_pmsav8 would have generated an exception.
9465 */
9466 if (s->v8m_secure) {
9467 /* Like the IT insn, we don't need to generate any code */
9468 s->condexec_cond = 0;
9469 s->condexec_mask = 0;
9470 }
9471 } else if (insn & 0x01200000) {
ebfe27c5
PM
9472 /* 0b1110_1000_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
9473 * - load/store dual (post-indexed)
9474 * 0b1111_1001_x10x_xxxx_xxxx_xxxx_xxxx_xxxx
9475 * - load/store dual (literal and immediate)
9476 * 0b1111_1001_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
9477 * - load/store dual (pre-indexed)
9478 */
910d7692
PM
9479 bool wback = extract32(insn, 21, 1);
9480
9ee6e8bb 9481 if (rn == 15) {
ebfe27c5
PM
9482 if (insn & (1 << 21)) {
9483 /* UNPREDICTABLE */
9484 goto illegal_op;
9485 }
7d1b0095 9486 addr = tcg_temp_new_i32();
b0109805 9487 tcg_gen_movi_i32(addr, s->pc & ~3);
9ee6e8bb 9488 } else {
b0109805 9489 addr = load_reg(s, rn);
9ee6e8bb
PB
9490 }
9491 offset = (insn & 0xff) * 4;
910d7692 9492 if ((insn & (1 << 23)) == 0) {
9ee6e8bb 9493 offset = -offset;
910d7692
PM
9494 }
9495
9496 if (s->v8m_stackcheck && rn == 13 && wback) {
9497 /*
9498 * Here 'addr' is the current SP; if offset is +ve we're
9499 * moving SP up, else down. It is UNKNOWN whether the limit
9500 * check triggers when SP starts below the limit and ends
9501 * up above it; check whichever of the current and final
9502 * SP is lower, so QEMU will trigger in that situation.
9503 */
9504 if ((int32_t)offset < 0) {
9505 TCGv_i32 newsp = tcg_temp_new_i32();
9506
9507 tcg_gen_addi_i32(newsp, addr, offset);
9508 gen_helper_v8m_stackcheck(cpu_env, newsp);
9509 tcg_temp_free_i32(newsp);
9510 } else {
9511 gen_helper_v8m_stackcheck(cpu_env, addr);
9512 }
9513 }
9514
9ee6e8bb 9515 if (insn & (1 << 24)) {
b0109805 9516 tcg_gen_addi_i32(addr, addr, offset);
9ee6e8bb
PB
9517 offset = 0;
9518 }
9519 if (insn & (1 << 20)) {
9520 /* ldrd */
e2592fad 9521 tmp = tcg_temp_new_i32();
12dcc321 9522 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805
PB
9523 store_reg(s, rs, tmp);
9524 tcg_gen_addi_i32(addr, addr, 4);
e2592fad 9525 tmp = tcg_temp_new_i32();
12dcc321 9526 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 9527 store_reg(s, rd, tmp);
9ee6e8bb
PB
9528 } else {
9529 /* strd */
b0109805 9530 tmp = load_reg(s, rs);
12dcc321 9531 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
e2592fad 9532 tcg_temp_free_i32(tmp);
b0109805
PB
9533 tcg_gen_addi_i32(addr, addr, 4);
9534 tmp = load_reg(s, rd);
12dcc321 9535 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
e2592fad 9536 tcg_temp_free_i32(tmp);
9ee6e8bb 9537 }
910d7692 9538 if (wback) {
9ee6e8bb 9539 /* Base writeback. */
b0109805
PB
9540 tcg_gen_addi_i32(addr, addr, offset - 4);
9541 store_reg(s, rn, addr);
9542 } else {
7d1b0095 9543 tcg_temp_free_i32(addr);
9ee6e8bb
PB
9544 }
9545 } else if ((insn & (1 << 23)) == 0) {
ebfe27c5
PM
9546 /* 0b1110_1000_010x_xxxx_xxxx_xxxx_xxxx_xxxx
9547 * - load/store exclusive word
5158de24 9548 * - TT (v8M only)
ebfe27c5
PM
9549 */
9550 if (rs == 15) {
5158de24
PM
9551 if (!(insn & (1 << 20)) &&
9552 arm_dc_feature(s, ARM_FEATURE_M) &&
9553 arm_dc_feature(s, ARM_FEATURE_V8)) {
9554 /* 0b1110_1000_0100_xxxx_1111_xxxx_xxxx_xxxx
9555 * - TT (v8M only)
9556 */
9557 bool alt = insn & (1 << 7);
9558 TCGv_i32 addr, op, ttresp;
9559
9560 if ((insn & 0x3f) || rd == 13 || rd == 15 || rn == 15) {
9561 /* we UNDEF for these UNPREDICTABLE cases */
9562 goto illegal_op;
9563 }
9564
9565 if (alt && !s->v8m_secure) {
9566 goto illegal_op;
9567 }
9568
9569 addr = load_reg(s, rn);
9570 op = tcg_const_i32(extract32(insn, 6, 2));
9571 ttresp = tcg_temp_new_i32();
9572 gen_helper_v7m_tt(ttresp, cpu_env, addr, op);
9573 tcg_temp_free_i32(addr);
9574 tcg_temp_free_i32(op);
9575 store_reg(s, rd, ttresp);
384c6c03 9576 break;
5158de24 9577 }
ebfe27c5
PM
9578 goto illegal_op;
9579 }
39d5492a 9580 addr = tcg_temp_local_new_i32();
98a46317 9581 load_reg_var(s, addr, rn);
426f5abc 9582 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
2c0262af 9583 if (insn & (1 << 20)) {
426f5abc 9584 gen_load_exclusive(s, rs, 15, addr, 2);
9ee6e8bb 9585 } else {
426f5abc 9586 gen_store_exclusive(s, rd, rs, 15, addr, 2);
9ee6e8bb 9587 }
39d5492a 9588 tcg_temp_free_i32(addr);
2359bf80 9589 } else if ((insn & (7 << 5)) == 0) {
9ee6e8bb
PB
9590 /* Table Branch. */
9591 if (rn == 15) {
7d1b0095 9592 addr = tcg_temp_new_i32();
b0109805 9593 tcg_gen_movi_i32(addr, s->pc);
9ee6e8bb 9594 } else {
b0109805 9595 addr = load_reg(s, rn);
9ee6e8bb 9596 }
b26eefb6 9597 tmp = load_reg(s, rm);
b0109805 9598 tcg_gen_add_i32(addr, addr, tmp);
9ee6e8bb
PB
9599 if (insn & (1 << 4)) {
9600 /* tbh */
b0109805 9601 tcg_gen_add_i32(addr, addr, tmp);
7d1b0095 9602 tcg_temp_free_i32(tmp);
e2592fad 9603 tmp = tcg_temp_new_i32();
12dcc321 9604 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
9ee6e8bb 9605 } else { /* tbb */
7d1b0095 9606 tcg_temp_free_i32(tmp);
e2592fad 9607 tmp = tcg_temp_new_i32();
12dcc321 9608 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
9ee6e8bb 9609 }
7d1b0095 9610 tcg_temp_free_i32(addr);
b0109805
PB
9611 tcg_gen_shli_i32(tmp, tmp, 1);
9612 tcg_gen_addi_i32(tmp, tmp, s->pc);
9613 store_reg(s, 15, tmp);
9ee6e8bb 9614 } else {
96c55295
PM
9615 bool is_lasr = false;
9616 bool is_ld = extract32(insn, 20, 1);
2359bf80 9617 int op2 = (insn >> 6) & 0x3;
9ee6e8bb 9618 op = (insn >> 4) & 0x3;
2359bf80
MR
9619 switch (op2) {
9620 case 0:
426f5abc 9621 goto illegal_op;
2359bf80
MR
9622 case 1:
9623 /* Load/store exclusive byte/halfword/doubleword */
9624 if (op == 2) {
9625 goto illegal_op;
9626 }
9627 ARCH(7);
9628 break;
9629 case 2:
9630 /* Load-acquire/store-release */
9631 if (op == 3) {
9632 goto illegal_op;
9633 }
9634 /* Fall through */
9635 case 3:
9636 /* Load-acquire/store-release exclusive */
9637 ARCH(8);
96c55295 9638 is_lasr = true;
2359bf80 9639 break;
426f5abc 9640 }
96c55295
PM
9641
9642 if (is_lasr && !is_ld) {
9643 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
9644 }
9645
39d5492a 9646 addr = tcg_temp_local_new_i32();
98a46317 9647 load_reg_var(s, addr, rn);
2359bf80 9648 if (!(op2 & 1)) {
96c55295 9649 if (is_ld) {
2359bf80
MR
9650 tmp = tcg_temp_new_i32();
9651 switch (op) {
9652 case 0: /* ldab */
9bb6558a
PM
9653 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s),
9654 rs | ISSIsAcqRel);
2359bf80
MR
9655 break;
9656 case 1: /* ldah */
9bb6558a
PM
9657 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s),
9658 rs | ISSIsAcqRel);
2359bf80
MR
9659 break;
9660 case 2: /* lda */
9bb6558a
PM
9661 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s),
9662 rs | ISSIsAcqRel);
2359bf80
MR
9663 break;
9664 default:
9665 abort();
9666 }
9667 store_reg(s, rs, tmp);
9668 } else {
9669 tmp = load_reg(s, rs);
9670 switch (op) {
9671 case 0: /* stlb */
9bb6558a
PM
9672 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s),
9673 rs | ISSIsAcqRel);
2359bf80
MR
9674 break;
9675 case 1: /* stlh */
9bb6558a
PM
9676 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s),
9677 rs | ISSIsAcqRel);
2359bf80
MR
9678 break;
9679 case 2: /* stl */
9bb6558a
PM
9680 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s),
9681 rs | ISSIsAcqRel);
2359bf80
MR
9682 break;
9683 default:
9684 abort();
9685 }
9686 tcg_temp_free_i32(tmp);
9687 }
96c55295 9688 } else if (is_ld) {
426f5abc 9689 gen_load_exclusive(s, rs, rd, addr, op);
9ee6e8bb 9690 } else {
426f5abc 9691 gen_store_exclusive(s, rm, rs, rd, addr, op);
9ee6e8bb 9692 }
39d5492a 9693 tcg_temp_free_i32(addr);
96c55295
PM
9694
9695 if (is_lasr && is_ld) {
9696 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
9697 }
9ee6e8bb
PB
9698 }
9699 } else {
9700 /* Load/store multiple, RFE, SRS. */
9701 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
00115976 9702 /* RFE, SRS: not available in user mode or on M profile */
b53d8923 9703 if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
9ee6e8bb 9704 goto illegal_op;
00115976 9705 }
9ee6e8bb
PB
9706 if (insn & (1 << 20)) {
9707 /* rfe */
b0109805
PB
9708 addr = load_reg(s, rn);
9709 if ((insn & (1 << 24)) == 0)
9710 tcg_gen_addi_i32(addr, addr, -8);
9711 /* Load PC into tmp and CPSR into tmp2. */
e2592fad 9712 tmp = tcg_temp_new_i32();
12dcc321 9713 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 9714 tcg_gen_addi_i32(addr, addr, 4);
e2592fad 9715 tmp2 = tcg_temp_new_i32();
12dcc321 9716 gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
9ee6e8bb
PB
9717 if (insn & (1 << 21)) {
9718 /* Base writeback. */
b0109805
PB
9719 if (insn & (1 << 24)) {
9720 tcg_gen_addi_i32(addr, addr, 4);
9721 } else {
9722 tcg_gen_addi_i32(addr, addr, -4);
9723 }
9724 store_reg(s, rn, addr);
9725 } else {
7d1b0095 9726 tcg_temp_free_i32(addr);
9ee6e8bb 9727 }
b0109805 9728 gen_rfe(s, tmp, tmp2);
9ee6e8bb
PB
9729 } else {
9730 /* srs */
81465888
PM
9731 gen_srs(s, (insn & 0x1f), (insn & (1 << 24)) ? 1 : 2,
9732 insn & (1 << 21));
9ee6e8bb
PB
9733 }
9734 } else {
5856d44e 9735 int i, loaded_base = 0;
39d5492a 9736 TCGv_i32 loaded_var;
7c0ed88e 9737 bool wback = extract32(insn, 21, 1);
9ee6e8bb 9738 /* Load/store multiple. */
b0109805 9739 addr = load_reg(s, rn);
9ee6e8bb
PB
9740 offset = 0;
9741 for (i = 0; i < 16; i++) {
9742 if (insn & (1 << i))
9743 offset += 4;
9744 }
7c0ed88e 9745
9ee6e8bb 9746 if (insn & (1 << 24)) {
b0109805 9747 tcg_gen_addi_i32(addr, addr, -offset);
9ee6e8bb
PB
9748 }
9749
7c0ed88e
PM
9750 if (s->v8m_stackcheck && rn == 13 && wback) {
9751 /*
9752 * If the writeback is incrementing SP rather than
9753 * decrementing it, and the initial SP is below the
9754 * stack limit but the final written-back SP would
9755 * be above, then then we must not perform any memory
9756 * accesses, but it is IMPDEF whether we generate
9757 * an exception. We choose to do so in this case.
9758 * At this point 'addr' is the lowest address, so
9759 * either the original SP (if incrementing) or our
9760 * final SP (if decrementing), so that's what we check.
9761 */
9762 gen_helper_v8m_stackcheck(cpu_env, addr);
9763 }
9764
f764718d 9765 loaded_var = NULL;
9ee6e8bb
PB
9766 for (i = 0; i < 16; i++) {
9767 if ((insn & (1 << i)) == 0)
9768 continue;
9769 if (insn & (1 << 20)) {
9770 /* Load. */
e2592fad 9771 tmp = tcg_temp_new_i32();
12dcc321 9772 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9ee6e8bb 9773 if (i == 15) {
3bb8a96f 9774 gen_bx_excret(s, tmp);
5856d44e
YO
9775 } else if (i == rn) {
9776 loaded_var = tmp;
9777 loaded_base = 1;
9ee6e8bb 9778 } else {
b0109805 9779 store_reg(s, i, tmp);
9ee6e8bb
PB
9780 }
9781 } else {
9782 /* Store. */
b0109805 9783 tmp = load_reg(s, i);
12dcc321 9784 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
e2592fad 9785 tcg_temp_free_i32(tmp);
9ee6e8bb 9786 }
b0109805 9787 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb 9788 }
5856d44e
YO
9789 if (loaded_base) {
9790 store_reg(s, rn, loaded_var);
9791 }
7c0ed88e 9792 if (wback) {
9ee6e8bb
PB
9793 /* Base register writeback. */
9794 if (insn & (1 << 24)) {
b0109805 9795 tcg_gen_addi_i32(addr, addr, -offset);
9ee6e8bb
PB
9796 }
9797 /* Fault if writeback register is in register list. */
9798 if (insn & (1 << rn))
9799 goto illegal_op;
b0109805
PB
9800 store_reg(s, rn, addr);
9801 } else {
7d1b0095 9802 tcg_temp_free_i32(addr);
9ee6e8bb
PB
9803 }
9804 }
9805 }
9806 break;
2af9ab77
JB
9807 case 5:
9808
9ee6e8bb 9809 op = (insn >> 21) & 0xf;
2af9ab77 9810 if (op == 6) {
62b44f05
AR
9811 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9812 goto illegal_op;
9813 }
2af9ab77
JB
9814 /* Halfword pack. */
9815 tmp = load_reg(s, rn);
9816 tmp2 = load_reg(s, rm);
9817 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
9818 if (insn & (1 << 5)) {
9819 /* pkhtb */
9820 if (shift == 0)
9821 shift = 31;
9822 tcg_gen_sari_i32(tmp2, tmp2, shift);
9823 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
9824 tcg_gen_ext16u_i32(tmp2, tmp2);
9825 } else {
9826 /* pkhbt */
9827 if (shift)
9828 tcg_gen_shli_i32(tmp2, tmp2, shift);
9829 tcg_gen_ext16u_i32(tmp, tmp);
9830 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
9831 }
9832 tcg_gen_or_i32(tmp, tmp, tmp2);
7d1b0095 9833 tcg_temp_free_i32(tmp2);
3174f8e9
FN
9834 store_reg(s, rd, tmp);
9835 } else {
2af9ab77
JB
9836 /* Data processing register constant shift. */
9837 if (rn == 15) {
7d1b0095 9838 tmp = tcg_temp_new_i32();
2af9ab77
JB
9839 tcg_gen_movi_i32(tmp, 0);
9840 } else {
9841 tmp = load_reg(s, rn);
9842 }
9843 tmp2 = load_reg(s, rm);
9844
9845 shiftop = (insn >> 4) & 3;
9846 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
9847 conds = (insn & (1 << 20)) != 0;
9848 logic_cc = (conds && thumb2_logic_op(op));
9849 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
9850 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
9851 goto illegal_op;
7d1b0095 9852 tcg_temp_free_i32(tmp2);
55203189
PM
9853 if (rd == 13 &&
9854 ((op == 2 && rn == 15) ||
9855 (op == 8 && rn == 13) ||
9856 (op == 13 && rn == 13))) {
9857 /* MOV SP, ... or ADD SP, SP, ... or SUB SP, SP, ... */
9858 store_sp_checked(s, tmp);
9859 } else if (rd != 15) {
2af9ab77
JB
9860 store_reg(s, rd, tmp);
9861 } else {
7d1b0095 9862 tcg_temp_free_i32(tmp);
2af9ab77 9863 }
3174f8e9 9864 }
9ee6e8bb
PB
9865 break;
9866 case 13: /* Misc data processing. */
9867 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
9868 if (op < 4 && (insn & 0xf000) != 0xf000)
9869 goto illegal_op;
9870 switch (op) {
9871 case 0: /* Register controlled shift. */
8984bd2e
PB
9872 tmp = load_reg(s, rn);
9873 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
9874 if ((insn & 0x70) != 0)
9875 goto illegal_op;
a2d12f0f
PM
9876 /*
9877 * 0b1111_1010_0xxx_xxxx_1111_xxxx_0000_xxxx:
9878 * - MOV, MOVS (register-shifted register), flagsetting
9879 */
9ee6e8bb 9880 op = (insn >> 21) & 3;
8984bd2e
PB
9881 logic_cc = (insn & (1 << 20)) != 0;
9882 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
9883 if (logic_cc)
9884 gen_logic_CC(tmp);
bedb8a6b 9885 store_reg(s, rd, tmp);
9ee6e8bb
PB
9886 break;
9887 case 1: /* Sign/zero extend. */
62b44f05
AR
9888 op = (insn >> 20) & 7;
9889 switch (op) {
9890 case 0: /* SXTAH, SXTH */
9891 case 1: /* UXTAH, UXTH */
9892 case 4: /* SXTAB, SXTB */
9893 case 5: /* UXTAB, UXTB */
9894 break;
9895 case 2: /* SXTAB16, SXTB16 */
9896 case 3: /* UXTAB16, UXTB16 */
9897 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9898 goto illegal_op;
9899 }
9900 break;
9901 default:
9902 goto illegal_op;
9903 }
9904 if (rn != 15) {
9905 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9906 goto illegal_op;
9907 }
9908 }
5e3f878a 9909 tmp = load_reg(s, rm);
9ee6e8bb 9910 shift = (insn >> 4) & 3;
1301f322 9911 /* ??? In many cases it's not necessary to do a
9ee6e8bb
PB
9912 rotate, a shift is sufficient. */
9913 if (shift != 0)
f669df27 9914 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
9ee6e8bb
PB
9915 op = (insn >> 20) & 7;
9916 switch (op) {
5e3f878a
PB
9917 case 0: gen_sxth(tmp); break;
9918 case 1: gen_uxth(tmp); break;
9919 case 2: gen_sxtb16(tmp); break;
9920 case 3: gen_uxtb16(tmp); break;
9921 case 4: gen_sxtb(tmp); break;
9922 case 5: gen_uxtb(tmp); break;
62b44f05
AR
9923 default:
9924 g_assert_not_reached();
9ee6e8bb
PB
9925 }
9926 if (rn != 15) {
5e3f878a 9927 tmp2 = load_reg(s, rn);
9ee6e8bb 9928 if ((op >> 1) == 1) {
5e3f878a 9929 gen_add16(tmp, tmp2);
9ee6e8bb 9930 } else {
5e3f878a 9931 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 9932 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
9933 }
9934 }
5e3f878a 9935 store_reg(s, rd, tmp);
9ee6e8bb
PB
9936 break;
9937 case 2: /* SIMD add/subtract. */
62b44f05
AR
9938 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9939 goto illegal_op;
9940 }
9ee6e8bb
PB
9941 op = (insn >> 20) & 7;
9942 shift = (insn >> 4) & 7;
9943 if ((op & 3) == 3 || (shift & 3) == 3)
9944 goto illegal_op;
6ddbc6e4
PB
9945 tmp = load_reg(s, rn);
9946 tmp2 = load_reg(s, rm);
9947 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7d1b0095 9948 tcg_temp_free_i32(tmp2);
6ddbc6e4 9949 store_reg(s, rd, tmp);
9ee6e8bb
PB
9950 break;
9951 case 3: /* Other data processing. */
9952 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
9953 if (op < 4) {
9954 /* Saturating add/subtract. */
62b44f05
AR
9955 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9956 goto illegal_op;
9957 }
d9ba4830
PB
9958 tmp = load_reg(s, rn);
9959 tmp2 = load_reg(s, rm);
9ee6e8bb 9960 if (op & 1)
9ef39277 9961 gen_helper_double_saturate(tmp, cpu_env, tmp);
4809c612 9962 if (op & 2)
9ef39277 9963 gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);
9ee6e8bb 9964 else
9ef39277 9965 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
7d1b0095 9966 tcg_temp_free_i32(tmp2);
9ee6e8bb 9967 } else {
62b44f05
AR
9968 switch (op) {
9969 case 0x0a: /* rbit */
9970 case 0x08: /* rev */
9971 case 0x09: /* rev16 */
9972 case 0x0b: /* revsh */
9973 case 0x18: /* clz */
9974 break;
9975 case 0x10: /* sel */
9976 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9977 goto illegal_op;
9978 }
9979 break;
9980 case 0x20: /* crc32/crc32c */
9981 case 0x21:
9982 case 0x22:
9983 case 0x28:
9984 case 0x29:
9985 case 0x2a:
962fcbf2 9986 if (!dc_isar_feature(aa32_crc32, s)) {
62b44f05
AR
9987 goto illegal_op;
9988 }
9989 break;
9990 default:
9991 goto illegal_op;
9992 }
d9ba4830 9993 tmp = load_reg(s, rn);
9ee6e8bb
PB
9994 switch (op) {
9995 case 0x0a: /* rbit */
d9ba4830 9996 gen_helper_rbit(tmp, tmp);
9ee6e8bb
PB
9997 break;
9998 case 0x08: /* rev */
66896cb8 9999 tcg_gen_bswap32_i32(tmp, tmp);
9ee6e8bb
PB
10000 break;
10001 case 0x09: /* rev16 */
d9ba4830 10002 gen_rev16(tmp);
9ee6e8bb
PB
10003 break;
10004 case 0x0b: /* revsh */
d9ba4830 10005 gen_revsh(tmp);
9ee6e8bb
PB
10006 break;
10007 case 0x10: /* sel */
d9ba4830 10008 tmp2 = load_reg(s, rm);
7d1b0095 10009 tmp3 = tcg_temp_new_i32();
0ecb72a5 10010 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
d9ba4830 10011 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7d1b0095
PM
10012 tcg_temp_free_i32(tmp3);
10013 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
10014 break;
10015 case 0x18: /* clz */
7539a012 10016 tcg_gen_clzi_i32(tmp, tmp, 32);
9ee6e8bb 10017 break;
eb0ecd5a
WN
10018 case 0x20:
10019 case 0x21:
10020 case 0x22:
10021 case 0x28:
10022 case 0x29:
10023 case 0x2a:
10024 {
10025 /* crc32/crc32c */
10026 uint32_t sz = op & 0x3;
10027 uint32_t c = op & 0x8;
10028
eb0ecd5a 10029 tmp2 = load_reg(s, rm);
aa633469
PM
10030 if (sz == 0) {
10031 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
10032 } else if (sz == 1) {
10033 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
10034 }
eb0ecd5a
WN
10035 tmp3 = tcg_const_i32(1 << sz);
10036 if (c) {
10037 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
10038 } else {
10039 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
10040 }
10041 tcg_temp_free_i32(tmp2);
10042 tcg_temp_free_i32(tmp3);
10043 break;
10044 }
9ee6e8bb 10045 default:
62b44f05 10046 g_assert_not_reached();
9ee6e8bb
PB
10047 }
10048 }
d9ba4830 10049 store_reg(s, rd, tmp);
9ee6e8bb
PB
10050 break;
10051 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
62b44f05
AR
10052 switch ((insn >> 20) & 7) {
10053 case 0: /* 32 x 32 -> 32 */
10054 case 7: /* Unsigned sum of absolute differences. */
10055 break;
10056 case 1: /* 16 x 16 -> 32 */
10057 case 2: /* Dual multiply add. */
10058 case 3: /* 32 * 16 -> 32msb */
10059 case 4: /* Dual multiply subtract. */
10060 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
10061 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10062 goto illegal_op;
10063 }
10064 break;
10065 }
9ee6e8bb 10066 op = (insn >> 4) & 0xf;
d9ba4830
PB
10067 tmp = load_reg(s, rn);
10068 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
10069 switch ((insn >> 20) & 7) {
10070 case 0: /* 32 x 32 -> 32 */
d9ba4830 10071 tcg_gen_mul_i32(tmp, tmp, tmp2);
7d1b0095 10072 tcg_temp_free_i32(tmp2);
9ee6e8bb 10073 if (rs != 15) {
d9ba4830 10074 tmp2 = load_reg(s, rs);
9ee6e8bb 10075 if (op)
d9ba4830 10076 tcg_gen_sub_i32(tmp, tmp2, tmp);
9ee6e8bb 10077 else
d9ba4830 10078 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 10079 tcg_temp_free_i32(tmp2);
9ee6e8bb 10080 }
9ee6e8bb
PB
10081 break;
10082 case 1: /* 16 x 16 -> 32 */
d9ba4830 10083 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7d1b0095 10084 tcg_temp_free_i32(tmp2);
9ee6e8bb 10085 if (rs != 15) {
d9ba4830 10086 tmp2 = load_reg(s, rs);
9ef39277 10087 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 10088 tcg_temp_free_i32(tmp2);
9ee6e8bb 10089 }
9ee6e8bb
PB
10090 break;
10091 case 2: /* Dual multiply add. */
10092 case 4: /* Dual multiply subtract. */
10093 if (op)
d9ba4830
PB
10094 gen_swap_half(tmp2);
10095 gen_smul_dual(tmp, tmp2);
9ee6e8bb 10096 if (insn & (1 << 22)) {
e1d177b9 10097 /* This subtraction cannot overflow. */
d9ba4830 10098 tcg_gen_sub_i32(tmp, tmp, tmp2);
9ee6e8bb 10099 } else {
e1d177b9
PM
10100 /* This addition cannot overflow 32 bits;
10101 * however it may overflow considered as a signed
10102 * operation, in which case we must set the Q flag.
10103 */
9ef39277 10104 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 10105 }
7d1b0095 10106 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
10107 if (rs != 15)
10108 {
d9ba4830 10109 tmp2 = load_reg(s, rs);
9ef39277 10110 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 10111 tcg_temp_free_i32(tmp2);
9ee6e8bb 10112 }
9ee6e8bb
PB
10113 break;
10114 case 3: /* 32 * 16 -> 32msb */
10115 if (op)
d9ba4830 10116 tcg_gen_sari_i32(tmp2, tmp2, 16);
9ee6e8bb 10117 else
d9ba4830 10118 gen_sxth(tmp2);
a7812ae4
PB
10119 tmp64 = gen_muls_i64_i32(tmp, tmp2);
10120 tcg_gen_shri_i64(tmp64, tmp64, 16);
7d1b0095 10121 tmp = tcg_temp_new_i32();
ecc7b3aa 10122 tcg_gen_extrl_i64_i32(tmp, tmp64);
b75263d6 10123 tcg_temp_free_i64(tmp64);
9ee6e8bb
PB
10124 if (rs != 15)
10125 {
d9ba4830 10126 tmp2 = load_reg(s, rs);
9ef39277 10127 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 10128 tcg_temp_free_i32(tmp2);
9ee6e8bb 10129 }
9ee6e8bb 10130 break;
838fa72d
AJ
10131 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
10132 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9ee6e8bb 10133 if (rs != 15) {
838fa72d
AJ
10134 tmp = load_reg(s, rs);
10135 if (insn & (1 << 20)) {
10136 tmp64 = gen_addq_msw(tmp64, tmp);
99c475ab 10137 } else {
838fa72d 10138 tmp64 = gen_subq_msw(tmp64, tmp);
99c475ab 10139 }
2c0262af 10140 }
838fa72d
AJ
10141 if (insn & (1 << 4)) {
10142 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
10143 }
10144 tcg_gen_shri_i64(tmp64, tmp64, 32);
7d1b0095 10145 tmp = tcg_temp_new_i32();
ecc7b3aa 10146 tcg_gen_extrl_i64_i32(tmp, tmp64);
838fa72d 10147 tcg_temp_free_i64(tmp64);
9ee6e8bb
PB
10148 break;
10149 case 7: /* Unsigned sum of absolute differences. */
d9ba4830 10150 gen_helper_usad8(tmp, tmp, tmp2);
7d1b0095 10151 tcg_temp_free_i32(tmp2);
9ee6e8bb 10152 if (rs != 15) {
d9ba4830
PB
10153 tmp2 = load_reg(s, rs);
10154 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 10155 tcg_temp_free_i32(tmp2);
5fd46862 10156 }
9ee6e8bb 10157 break;
2c0262af 10158 }
d9ba4830 10159 store_reg(s, rd, tmp);
2c0262af 10160 break;
9ee6e8bb
PB
10161 case 6: case 7: /* 64-bit multiply, Divide. */
10162 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
5e3f878a
PB
10163 tmp = load_reg(s, rn);
10164 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
10165 if ((op & 0x50) == 0x10) {
10166 /* sdiv, udiv */
7e0cf8b4 10167 if (!dc_isar_feature(thumb_div, s)) {
9ee6e8bb 10168 goto illegal_op;
47789990 10169 }
9ee6e8bb 10170 if (op & 0x20)
5e3f878a 10171 gen_helper_udiv(tmp, tmp, tmp2);
2c0262af 10172 else
5e3f878a 10173 gen_helper_sdiv(tmp, tmp, tmp2);
7d1b0095 10174 tcg_temp_free_i32(tmp2);
5e3f878a 10175 store_reg(s, rd, tmp);
9ee6e8bb
PB
10176 } else if ((op & 0xe) == 0xc) {
10177 /* Dual multiply accumulate long. */
62b44f05
AR
10178 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10179 tcg_temp_free_i32(tmp);
10180 tcg_temp_free_i32(tmp2);
10181 goto illegal_op;
10182 }
9ee6e8bb 10183 if (op & 1)
5e3f878a
PB
10184 gen_swap_half(tmp2);
10185 gen_smul_dual(tmp, tmp2);
9ee6e8bb 10186 if (op & 0x10) {
5e3f878a 10187 tcg_gen_sub_i32(tmp, tmp, tmp2);
b5ff1b31 10188 } else {
5e3f878a 10189 tcg_gen_add_i32(tmp, tmp, tmp2);
b5ff1b31 10190 }
7d1b0095 10191 tcg_temp_free_i32(tmp2);
a7812ae4
PB
10192 /* BUGFIX */
10193 tmp64 = tcg_temp_new_i64();
10194 tcg_gen_ext_i32_i64(tmp64, tmp);
7d1b0095 10195 tcg_temp_free_i32(tmp);
a7812ae4
PB
10196 gen_addq(s, tmp64, rs, rd);
10197 gen_storeq_reg(s, rs, rd, tmp64);
b75263d6 10198 tcg_temp_free_i64(tmp64);
2c0262af 10199 } else {
9ee6e8bb
PB
10200 if (op & 0x20) {
10201 /* Unsigned 64-bit multiply */
a7812ae4 10202 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
b5ff1b31 10203 } else {
9ee6e8bb
PB
10204 if (op & 8) {
10205 /* smlalxy */
62b44f05
AR
10206 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10207 tcg_temp_free_i32(tmp2);
10208 tcg_temp_free_i32(tmp);
10209 goto illegal_op;
10210 }
5e3f878a 10211 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7d1b0095 10212 tcg_temp_free_i32(tmp2);
a7812ae4
PB
10213 tmp64 = tcg_temp_new_i64();
10214 tcg_gen_ext_i32_i64(tmp64, tmp);
7d1b0095 10215 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
10216 } else {
10217 /* Signed 64-bit multiply */
a7812ae4 10218 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9ee6e8bb 10219 }
b5ff1b31 10220 }
9ee6e8bb
PB
10221 if (op & 4) {
10222 /* umaal */
62b44f05
AR
10223 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10224 tcg_temp_free_i64(tmp64);
10225 goto illegal_op;
10226 }
a7812ae4
PB
10227 gen_addq_lo(s, tmp64, rs);
10228 gen_addq_lo(s, tmp64, rd);
9ee6e8bb
PB
10229 } else if (op & 0x40) {
10230 /* 64-bit accumulate. */
a7812ae4 10231 gen_addq(s, tmp64, rs, rd);
9ee6e8bb 10232 }
a7812ae4 10233 gen_storeq_reg(s, rs, rd, tmp64);
b75263d6 10234 tcg_temp_free_i64(tmp64);
5fd46862 10235 }
2c0262af 10236 break;
9ee6e8bb
PB
10237 }
10238 break;
10239 case 6: case 7: case 14: case 15:
10240 /* Coprocessor. */
7517748e 10241 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8859ba3c
PM
10242 /* 0b111x_11xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx */
10243 if (extract32(insn, 24, 2) == 3) {
10244 goto illegal_op; /* op0 = 0b11 : unallocated */
10245 }
10246
10247 /*
10248 * Decode VLLDM and VLSTM first: these are nonstandard because:
10249 * * if there is no FPU then these insns must NOP in
10250 * Secure state and UNDEF in Nonsecure state
10251 * * if there is an FPU then these insns do not have
10252 * the usual behaviour that disas_vfp_insn() provides of
10253 * being controlled by CPACR/NSACR enable bits or the
10254 * lazy-stacking logic.
7517748e 10255 */
b1e5336a
PM
10256 if (arm_dc_feature(s, ARM_FEATURE_V8) &&
10257 (insn & 0xffa00f00) == 0xec200a00) {
10258 /* 0b1110_1100_0x1x_xxxx_xxxx_1010_xxxx_xxxx
10259 * - VLLDM, VLSTM
10260 * We choose to UNDEF if the RAZ bits are non-zero.
10261 */
10262 if (!s->v8m_secure || (insn & 0x0040f0ff)) {
10263 goto illegal_op;
10264 }
019076b0
PM
10265
10266 if (arm_dc_feature(s, ARM_FEATURE_VFP)) {
10267 TCGv_i32 fptr = load_reg(s, rn);
10268
10269 if (extract32(insn, 20, 1)) {
956fe143 10270 gen_helper_v7m_vlldm(cpu_env, fptr);
019076b0
PM
10271 } else {
10272 gen_helper_v7m_vlstm(cpu_env, fptr);
10273 }
10274 tcg_temp_free_i32(fptr);
10275
10276 /* End the TB, because we have updated FP control bits */
10277 s->base.is_jmp = DISAS_UPDATE;
10278 }
b1e5336a
PM
10279 break;
10280 }
8859ba3c
PM
10281 if (arm_dc_feature(s, ARM_FEATURE_VFP) &&
10282 ((insn >> 8) & 0xe) == 10) {
10283 /* FP, and the CPU supports it */
10284 if (disas_vfp_insn(s, insn)) {
10285 goto illegal_op;
10286 }
10287 break;
10288 }
10289
b1e5336a 10290 /* All other insns: NOCP */
7517748e
PM
10291 gen_exception_insn(s, 4, EXCP_NOCP, syn_uncategorized(),
10292 default_exception_el(s));
10293 break;
10294 }
0052087e
RH
10295 if ((insn & 0xfe000a00) == 0xfc000800
10296 && arm_dc_feature(s, ARM_FEATURE_V8)) {
10297 /* The Thumb2 and ARM encodings are identical. */
10298 if (disas_neon_insn_3same_ext(s, insn)) {
10299 goto illegal_op;
10300 }
10301 } else if ((insn & 0xff000a00) == 0xfe000800
10302 && arm_dc_feature(s, ARM_FEATURE_V8)) {
10303 /* The Thumb2 and ARM encodings are identical. */
10304 if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
10305 goto illegal_op;
10306 }
10307 } else if (((insn >> 24) & 3) == 3) {
9ee6e8bb 10308 /* Translate into the equivalent ARM encoding. */
f06053e3 10309 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
7dcc1f89 10310 if (disas_neon_data_insn(s, insn)) {
9ee6e8bb 10311 goto illegal_op;
7dcc1f89 10312 }
6a57f3eb 10313 } else if (((insn >> 8) & 0xe) == 10) {
7dcc1f89 10314 if (disas_vfp_insn(s, insn)) {
6a57f3eb
WN
10315 goto illegal_op;
10316 }
9ee6e8bb
PB
10317 } else {
10318 if (insn & (1 << 28))
10319 goto illegal_op;
7dcc1f89 10320 if (disas_coproc_insn(s, insn)) {
9ee6e8bb 10321 goto illegal_op;
7dcc1f89 10322 }
9ee6e8bb
PB
10323 }
10324 break;
10325 case 8: case 9: case 10: case 11:
10326 if (insn & (1 << 15)) {
10327 /* Branches, misc control. */
10328 if (insn & 0x5000) {
10329 /* Unconditional branch. */
10330 /* signextend(hw1[10:0]) -> offset[:12]. */
10331 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
10332 /* hw1[10:0] -> offset[11:1]. */
10333 offset |= (insn & 0x7ff) << 1;
10334 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
10335 offset[24:22] already have the same value because of the
10336 sign extension above. */
10337 offset ^= ((~insn) & (1 << 13)) << 10;
10338 offset ^= ((~insn) & (1 << 11)) << 11;
10339
9ee6e8bb
PB
10340 if (insn & (1 << 14)) {
10341 /* Branch and link. */
3174f8e9 10342 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
b5ff1b31 10343 }
3b46e624 10344
b0109805 10345 offset += s->pc;
9ee6e8bb
PB
10346 if (insn & (1 << 12)) {
10347 /* b/bl */
b0109805 10348 gen_jmp(s, offset);
9ee6e8bb
PB
10349 } else {
10350 /* blx */
b0109805 10351 offset &= ~(uint32_t)2;
be5e7a76 10352 /* thumb2 bx, no need to check */
b0109805 10353 gen_bx_im(s, offset);
2c0262af 10354 }
9ee6e8bb
PB
10355 } else if (((insn >> 23) & 7) == 7) {
10356 /* Misc control */
10357 if (insn & (1 << 13))
10358 goto illegal_op;
10359
10360 if (insn & (1 << 26)) {
001b3cab
PM
10361 if (arm_dc_feature(s, ARM_FEATURE_M)) {
10362 goto illegal_op;
10363 }
37e6456e
PM
10364 if (!(insn & (1 << 20))) {
10365 /* Hypervisor call (v7) */
10366 int imm16 = extract32(insn, 16, 4) << 12
10367 | extract32(insn, 0, 12);
10368 ARCH(7);
10369 if (IS_USER(s)) {
10370 goto illegal_op;
10371 }
10372 gen_hvc(s, imm16);
10373 } else {
10374 /* Secure monitor call (v6+) */
10375 ARCH(6K);
10376 if (IS_USER(s)) {
10377 goto illegal_op;
10378 }
10379 gen_smc(s);
10380 }
2c0262af 10381 } else {
9ee6e8bb
PB
10382 op = (insn >> 20) & 7;
10383 switch (op) {
10384 case 0: /* msr cpsr. */
b53d8923 10385 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8984bd2e 10386 tmp = load_reg(s, rn);
b28b3377
PM
10387 /* the constant is the mask and SYSm fields */
10388 addr = tcg_const_i32(insn & 0xfff);
8984bd2e 10389 gen_helper_v7m_msr(cpu_env, addr, tmp);
b75263d6 10390 tcg_temp_free_i32(addr);
7d1b0095 10391 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
10392 gen_lookup_tb(s);
10393 break;
10394 }
10395 /* fall through */
10396 case 1: /* msr spsr. */
b53d8923 10397 if (arm_dc_feature(s, ARM_FEATURE_M)) {
9ee6e8bb 10398 goto illegal_op;
b53d8923 10399 }
8bfd0550
PM
10400
10401 if (extract32(insn, 5, 1)) {
10402 /* MSR (banked) */
10403 int sysm = extract32(insn, 8, 4) |
10404 (extract32(insn, 4, 1) << 4);
10405 int r = op & 1;
10406
10407 gen_msr_banked(s, r, sysm, rm);
10408 break;
10409 }
10410
10411 /* MSR (for PSRs) */
2fbac54b
FN
10412 tmp = load_reg(s, rn);
10413 if (gen_set_psr(s,
7dcc1f89 10414 msr_mask(s, (insn >> 8) & 0xf, op == 1),
2fbac54b 10415 op == 1, tmp))
9ee6e8bb
PB
10416 goto illegal_op;
10417 break;
10418 case 2: /* cps, nop-hint. */
10419 if (((insn >> 8) & 7) == 0) {
10420 gen_nop_hint(s, insn & 0xff);
10421 }
10422 /* Implemented as NOP in user mode. */
10423 if (IS_USER(s))
10424 break;
10425 offset = 0;
10426 imm = 0;
10427 if (insn & (1 << 10)) {
10428 if (insn & (1 << 7))
10429 offset |= CPSR_A;
10430 if (insn & (1 << 6))
10431 offset |= CPSR_I;
10432 if (insn & (1 << 5))
10433 offset |= CPSR_F;
10434 if (insn & (1 << 9))
10435 imm = CPSR_A | CPSR_I | CPSR_F;
10436 }
10437 if (insn & (1 << 8)) {
10438 offset |= 0x1f;
10439 imm |= (insn & 0x1f);
10440 }
10441 if (offset) {
2fbac54b 10442 gen_set_psr_im(s, offset, 0, imm);
9ee6e8bb
PB
10443 }
10444 break;
10445 case 3: /* Special control operations. */
14120108 10446 if (!arm_dc_feature(s, ARM_FEATURE_V7) &&
8297cb13 10447 !arm_dc_feature(s, ARM_FEATURE_M)) {
14120108
JS
10448 goto illegal_op;
10449 }
9ee6e8bb
PB
10450 op = (insn >> 4) & 0xf;
10451 switch (op) {
10452 case 2: /* clrex */
426f5abc 10453 gen_clrex(s);
9ee6e8bb
PB
10454 break;
10455 case 4: /* dsb */
10456 case 5: /* dmb */
61e4c432 10457 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
9ee6e8bb 10458 break;
6df99dec
SS
10459 case 6: /* isb */
10460 /* We need to break the TB after this insn
10461 * to execute self-modifying code correctly
10462 * and also to take any pending interrupts
10463 * immediately.
10464 */
0b609cc1 10465 gen_goto_tb(s, 0, s->pc & ~1);
6df99dec 10466 break;
9888bd1e
RH
10467 case 7: /* sb */
10468 if ((insn & 0xf) || !dc_isar_feature(aa32_sb, s)) {
10469 goto illegal_op;
10470 }
10471 /*
10472 * TODO: There is no speculation barrier opcode
10473 * for TCG; MB and end the TB instead.
10474 */
10475 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
10476 gen_goto_tb(s, 0, s->pc & ~1);
10477 break;
9ee6e8bb
PB
10478 default:
10479 goto illegal_op;
10480 }
10481 break;
10482 case 4: /* bxj */
9d7c59c8
PM
10483 /* Trivial implementation equivalent to bx.
10484 * This instruction doesn't exist at all for M-profile.
10485 */
10486 if (arm_dc_feature(s, ARM_FEATURE_M)) {
10487 goto illegal_op;
10488 }
d9ba4830
PB
10489 tmp = load_reg(s, rn);
10490 gen_bx(s, tmp);
9ee6e8bb
PB
10491 break;
10492 case 5: /* Exception return. */
b8b45b68
RV
10493 if (IS_USER(s)) {
10494 goto illegal_op;
10495 }
10496 if (rn != 14 || rd != 15) {
10497 goto illegal_op;
10498 }
55c544ed
PM
10499 if (s->current_el == 2) {
10500 /* ERET from Hyp uses ELR_Hyp, not LR */
10501 if (insn & 0xff) {
10502 goto illegal_op;
10503 }
10504 tmp = load_cpu_field(elr_el[2]);
10505 } else {
10506 tmp = load_reg(s, rn);
10507 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
10508 }
b8b45b68
RV
10509 gen_exception_return(s, tmp);
10510 break;
8bfd0550 10511 case 6: /* MRS */
43ac6574
PM
10512 if (extract32(insn, 5, 1) &&
10513 !arm_dc_feature(s, ARM_FEATURE_M)) {
8bfd0550
PM
10514 /* MRS (banked) */
10515 int sysm = extract32(insn, 16, 4) |
10516 (extract32(insn, 4, 1) << 4);
10517
10518 gen_mrs_banked(s, 0, sysm, rd);
10519 break;
10520 }
10521
3d54026f
PM
10522 if (extract32(insn, 16, 4) != 0xf) {
10523 goto illegal_op;
10524 }
10525 if (!arm_dc_feature(s, ARM_FEATURE_M) &&
10526 extract32(insn, 0, 8) != 0) {
10527 goto illegal_op;
10528 }
10529
8bfd0550 10530 /* mrs cpsr */
7d1b0095 10531 tmp = tcg_temp_new_i32();
b53d8923 10532 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8984bd2e
PB
10533 addr = tcg_const_i32(insn & 0xff);
10534 gen_helper_v7m_mrs(tmp, cpu_env, addr);
b75263d6 10535 tcg_temp_free_i32(addr);
9ee6e8bb 10536 } else {
9ef39277 10537 gen_helper_cpsr_read(tmp, cpu_env);
9ee6e8bb 10538 }
8984bd2e 10539 store_reg(s, rd, tmp);
9ee6e8bb 10540 break;
8bfd0550 10541 case 7: /* MRS */
43ac6574
PM
10542 if (extract32(insn, 5, 1) &&
10543 !arm_dc_feature(s, ARM_FEATURE_M)) {
8bfd0550
PM
10544 /* MRS (banked) */
10545 int sysm = extract32(insn, 16, 4) |
10546 (extract32(insn, 4, 1) << 4);
10547
10548 gen_mrs_banked(s, 1, sysm, rd);
10549 break;
10550 }
10551
10552 /* mrs spsr. */
9ee6e8bb 10553 /* Not accessible in user mode. */
b53d8923 10554 if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
9ee6e8bb 10555 goto illegal_op;
b53d8923 10556 }
3d54026f
PM
10557
10558 if (extract32(insn, 16, 4) != 0xf ||
10559 extract32(insn, 0, 8) != 0) {
10560 goto illegal_op;
10561 }
10562
d9ba4830
PB
10563 tmp = load_cpu_field(spsr);
10564 store_reg(s, rd, tmp);
9ee6e8bb 10565 break;
2c0262af
FB
10566 }
10567 }
9ee6e8bb
PB
10568 } else {
10569 /* Conditional branch. */
10570 op = (insn >> 22) & 0xf;
10571 /* Generate a conditional jump to next instruction. */
c2d9644e 10572 arm_skip_unless(s, op);
9ee6e8bb
PB
10573
10574 /* offset[11:1] = insn[10:0] */
10575 offset = (insn & 0x7ff) << 1;
10576 /* offset[17:12] = insn[21:16]. */
10577 offset |= (insn & 0x003f0000) >> 4;
10578 /* offset[31:20] = insn[26]. */
10579 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
10580 /* offset[18] = insn[13]. */
10581 offset |= (insn & (1 << 13)) << 5;
10582 /* offset[19] = insn[11]. */
10583 offset |= (insn & (1 << 11)) << 8;
10584
10585 /* jump to the offset */
b0109805 10586 gen_jmp(s, s->pc + offset);
9ee6e8bb
PB
10587 }
10588 } else {
55203189
PM
10589 /*
10590 * 0b1111_0xxx_xxxx_0xxx_xxxx_xxxx
10591 * - Data-processing (modified immediate, plain binary immediate)
10592 */
9ee6e8bb 10593 if (insn & (1 << 25)) {
55203189
PM
10594 /*
10595 * 0b1111_0x1x_xxxx_0xxx_xxxx_xxxx
10596 * - Data-processing (plain binary immediate)
10597 */
9ee6e8bb
PB
10598 if (insn & (1 << 24)) {
10599 if (insn & (1 << 20))
10600 goto illegal_op;
10601 /* Bitfield/Saturate. */
10602 op = (insn >> 21) & 7;
10603 imm = insn & 0x1f;
10604 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
6ddbc6e4 10605 if (rn == 15) {
7d1b0095 10606 tmp = tcg_temp_new_i32();
6ddbc6e4
PB
10607 tcg_gen_movi_i32(tmp, 0);
10608 } else {
10609 tmp = load_reg(s, rn);
10610 }
9ee6e8bb
PB
10611 switch (op) {
10612 case 2: /* Signed bitfield extract. */
10613 imm++;
10614 if (shift + imm > 32)
10615 goto illegal_op;
59a71b4c
RH
10616 if (imm < 32) {
10617 tcg_gen_sextract_i32(tmp, tmp, shift, imm);
10618 }
9ee6e8bb
PB
10619 break;
10620 case 6: /* Unsigned bitfield extract. */
10621 imm++;
10622 if (shift + imm > 32)
10623 goto illegal_op;
59a71b4c
RH
10624 if (imm < 32) {
10625 tcg_gen_extract_i32(tmp, tmp, shift, imm);
10626 }
9ee6e8bb
PB
10627 break;
10628 case 3: /* Bitfield insert/clear. */
10629 if (imm < shift)
10630 goto illegal_op;
10631 imm = imm + 1 - shift;
10632 if (imm != 32) {
6ddbc6e4 10633 tmp2 = load_reg(s, rd);
d593c48e 10634 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, imm);
7d1b0095 10635 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
10636 }
10637 break;
10638 case 7:
10639 goto illegal_op;
10640 default: /* Saturate. */
9ee6e8bb
PB
10641 if (shift) {
10642 if (op & 1)
6ddbc6e4 10643 tcg_gen_sari_i32(tmp, tmp, shift);
9ee6e8bb 10644 else
6ddbc6e4 10645 tcg_gen_shli_i32(tmp, tmp, shift);
9ee6e8bb 10646 }
6ddbc6e4 10647 tmp2 = tcg_const_i32(imm);
9ee6e8bb
PB
10648 if (op & 4) {
10649 /* Unsigned. */
62b44f05
AR
10650 if ((op & 1) && shift == 0) {
10651 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10652 tcg_temp_free_i32(tmp);
10653 tcg_temp_free_i32(tmp2);
10654 goto illegal_op;
10655 }
9ef39277 10656 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
62b44f05 10657 } else {
9ef39277 10658 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
62b44f05 10659 }
2c0262af 10660 } else {
9ee6e8bb 10661 /* Signed. */
62b44f05
AR
10662 if ((op & 1) && shift == 0) {
10663 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10664 tcg_temp_free_i32(tmp);
10665 tcg_temp_free_i32(tmp2);
10666 goto illegal_op;
10667 }
9ef39277 10668 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
62b44f05 10669 } else {
9ef39277 10670 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
62b44f05 10671 }
2c0262af 10672 }
b75263d6 10673 tcg_temp_free_i32(tmp2);
9ee6e8bb 10674 break;
2c0262af 10675 }
6ddbc6e4 10676 store_reg(s, rd, tmp);
9ee6e8bb
PB
10677 } else {
10678 imm = ((insn & 0x04000000) >> 15)
10679 | ((insn & 0x7000) >> 4) | (insn & 0xff);
10680 if (insn & (1 << 22)) {
10681 /* 16-bit immediate. */
10682 imm |= (insn >> 4) & 0xf000;
10683 if (insn & (1 << 23)) {
10684 /* movt */
5e3f878a 10685 tmp = load_reg(s, rd);
86831435 10686 tcg_gen_ext16u_i32(tmp, tmp);
5e3f878a 10687 tcg_gen_ori_i32(tmp, tmp, imm << 16);
2c0262af 10688 } else {
9ee6e8bb 10689 /* movw */
7d1b0095 10690 tmp = tcg_temp_new_i32();
5e3f878a 10691 tcg_gen_movi_i32(tmp, imm);
2c0262af 10692 }
55203189 10693 store_reg(s, rd, tmp);
2c0262af 10694 } else {
9ee6e8bb
PB
10695 /* Add/sub 12-bit immediate. */
10696 if (rn == 15) {
b0109805 10697 offset = s->pc & ~(uint32_t)3;
9ee6e8bb 10698 if (insn & (1 << 23))
b0109805 10699 offset -= imm;
9ee6e8bb 10700 else
b0109805 10701 offset += imm;
7d1b0095 10702 tmp = tcg_temp_new_i32();
5e3f878a 10703 tcg_gen_movi_i32(tmp, offset);
55203189 10704 store_reg(s, rd, tmp);
2c0262af 10705 } else {
5e3f878a 10706 tmp = load_reg(s, rn);
9ee6e8bb 10707 if (insn & (1 << 23))
5e3f878a 10708 tcg_gen_subi_i32(tmp, tmp, imm);
9ee6e8bb 10709 else
5e3f878a 10710 tcg_gen_addi_i32(tmp, tmp, imm);
55203189
PM
10711 if (rn == 13 && rd == 13) {
10712 /* ADD SP, SP, imm or SUB SP, SP, imm */
10713 store_sp_checked(s, tmp);
10714 } else {
10715 store_reg(s, rd, tmp);
10716 }
2c0262af 10717 }
9ee6e8bb 10718 }
191abaa2 10719 }
9ee6e8bb 10720 } else {
55203189
PM
10721 /*
10722 * 0b1111_0x0x_xxxx_0xxx_xxxx_xxxx
10723 * - Data-processing (modified immediate)
10724 */
9ee6e8bb
PB
10725 int shifter_out = 0;
10726 /* modified 12-bit immediate. */
10727 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
10728 imm = (insn & 0xff);
10729 switch (shift) {
10730 case 0: /* XY */
10731 /* Nothing to do. */
10732 break;
10733 case 1: /* 00XY00XY */
10734 imm |= imm << 16;
10735 break;
10736 case 2: /* XY00XY00 */
10737 imm |= imm << 16;
10738 imm <<= 8;
10739 break;
10740 case 3: /* XYXYXYXY */
10741 imm |= imm << 16;
10742 imm |= imm << 8;
10743 break;
10744 default: /* Rotated constant. */
10745 shift = (shift << 1) | (imm >> 7);
10746 imm |= 0x80;
10747 imm = imm << (32 - shift);
10748 shifter_out = 1;
10749 break;
b5ff1b31 10750 }
7d1b0095 10751 tmp2 = tcg_temp_new_i32();
3174f8e9 10752 tcg_gen_movi_i32(tmp2, imm);
9ee6e8bb 10753 rn = (insn >> 16) & 0xf;
3174f8e9 10754 if (rn == 15) {
7d1b0095 10755 tmp = tcg_temp_new_i32();
3174f8e9
FN
10756 tcg_gen_movi_i32(tmp, 0);
10757 } else {
10758 tmp = load_reg(s, rn);
10759 }
9ee6e8bb
PB
10760 op = (insn >> 21) & 0xf;
10761 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
3174f8e9 10762 shifter_out, tmp, tmp2))
9ee6e8bb 10763 goto illegal_op;
7d1b0095 10764 tcg_temp_free_i32(tmp2);
9ee6e8bb 10765 rd = (insn >> 8) & 0xf;
55203189
PM
10766 if (rd == 13 && rn == 13
10767 && (op == 8 || op == 13)) {
10768 /* ADD(S) SP, SP, imm or SUB(S) SP, SP, imm */
10769 store_sp_checked(s, tmp);
10770 } else if (rd != 15) {
3174f8e9
FN
10771 store_reg(s, rd, tmp);
10772 } else {
7d1b0095 10773 tcg_temp_free_i32(tmp);
2c0262af 10774 }
2c0262af 10775 }
9ee6e8bb
PB
10776 }
10777 break;
10778 case 12: /* Load/store single data item. */
10779 {
10780 int postinc = 0;
10781 int writeback = 0;
a99caa48 10782 int memidx;
9bb6558a
PM
10783 ISSInfo issinfo;
10784
9ee6e8bb 10785 if ((insn & 0x01100000) == 0x01000000) {
7dcc1f89 10786 if (disas_neon_ls_insn(s, insn)) {
c1713132 10787 goto illegal_op;
7dcc1f89 10788 }
9ee6e8bb
PB
10789 break;
10790 }
a2fdc890
PM
10791 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
10792 if (rs == 15) {
10793 if (!(insn & (1 << 20))) {
10794 goto illegal_op;
10795 }
10796 if (op != 2) {
10797 /* Byte or halfword load space with dest == r15 : memory hints.
10798 * Catch them early so we don't emit pointless addressing code.
10799 * This space is a mix of:
10800 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
10801 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
10802 * cores)
10803 * unallocated hints, which must be treated as NOPs
10804 * UNPREDICTABLE space, which we NOP or UNDEF depending on
10805 * which is easiest for the decoding logic
10806 * Some space which must UNDEF
10807 */
10808 int op1 = (insn >> 23) & 3;
10809 int op2 = (insn >> 6) & 0x3f;
10810 if (op & 2) {
10811 goto illegal_op;
10812 }
10813 if (rn == 15) {
02afbf64
PM
10814 /* UNPREDICTABLE, unallocated hint or
10815 * PLD/PLDW/PLI (literal)
10816 */
2eea841c 10817 return;
a2fdc890
PM
10818 }
10819 if (op1 & 1) {
2eea841c 10820 return; /* PLD/PLDW/PLI or unallocated hint */
a2fdc890
PM
10821 }
10822 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
2eea841c 10823 return; /* PLD/PLDW/PLI or unallocated hint */
a2fdc890
PM
10824 }
10825 /* UNDEF space, or an UNPREDICTABLE */
2eea841c 10826 goto illegal_op;
a2fdc890
PM
10827 }
10828 }
a99caa48 10829 memidx = get_mem_index(s);
9ee6e8bb 10830 if (rn == 15) {
7d1b0095 10831 addr = tcg_temp_new_i32();
9ee6e8bb
PB
10832 /* PC relative. */
10833 /* s->pc has already been incremented by 4. */
10834 imm = s->pc & 0xfffffffc;
10835 if (insn & (1 << 23))
10836 imm += insn & 0xfff;
10837 else
10838 imm -= insn & 0xfff;
b0109805 10839 tcg_gen_movi_i32(addr, imm);
9ee6e8bb 10840 } else {
b0109805 10841 addr = load_reg(s, rn);
9ee6e8bb
PB
10842 if (insn & (1 << 23)) {
10843 /* Positive offset. */
10844 imm = insn & 0xfff;
b0109805 10845 tcg_gen_addi_i32(addr, addr, imm);
9ee6e8bb 10846 } else {
9ee6e8bb 10847 imm = insn & 0xff;
2a0308c5
PM
10848 switch ((insn >> 8) & 0xf) {
10849 case 0x0: /* Shifted Register. */
9ee6e8bb 10850 shift = (insn >> 4) & 0xf;
2a0308c5
PM
10851 if (shift > 3) {
10852 tcg_temp_free_i32(addr);
18c9b560 10853 goto illegal_op;
2a0308c5 10854 }
b26eefb6 10855 tmp = load_reg(s, rm);
9ee6e8bb 10856 if (shift)
b26eefb6 10857 tcg_gen_shli_i32(tmp, tmp, shift);
b0109805 10858 tcg_gen_add_i32(addr, addr, tmp);
7d1b0095 10859 tcg_temp_free_i32(tmp);
9ee6e8bb 10860 break;
2a0308c5 10861 case 0xc: /* Negative offset. */
b0109805 10862 tcg_gen_addi_i32(addr, addr, -imm);
9ee6e8bb 10863 break;
2a0308c5 10864 case 0xe: /* User privilege. */
b0109805 10865 tcg_gen_addi_i32(addr, addr, imm);
579d21cc 10866 memidx = get_a32_user_mem_index(s);
9ee6e8bb 10867 break;
2a0308c5 10868 case 0x9: /* Post-decrement. */
9ee6e8bb
PB
10869 imm = -imm;
10870 /* Fall through. */
2a0308c5 10871 case 0xb: /* Post-increment. */
9ee6e8bb
PB
10872 postinc = 1;
10873 writeback = 1;
10874 break;
2a0308c5 10875 case 0xd: /* Pre-decrement. */
9ee6e8bb
PB
10876 imm = -imm;
10877 /* Fall through. */
2a0308c5 10878 case 0xf: /* Pre-increment. */
9ee6e8bb
PB
10879 writeback = 1;
10880 break;
10881 default:
2a0308c5 10882 tcg_temp_free_i32(addr);
b7bcbe95 10883 goto illegal_op;
9ee6e8bb
PB
10884 }
10885 }
10886 }
9bb6558a
PM
10887
10888 issinfo = writeback ? ISSInvalid : rs;
10889
0bc003ba
PM
10890 if (s->v8m_stackcheck && rn == 13 && writeback) {
10891 /*
10892 * Stackcheck. Here we know 'addr' is the current SP;
10893 * if imm is +ve we're moving SP up, else down. It is
10894 * UNKNOWN whether the limit check triggers when SP starts
10895 * below the limit and ends up above it; we chose to do so.
10896 */
10897 if ((int32_t)imm < 0) {
10898 TCGv_i32 newsp = tcg_temp_new_i32();
10899
10900 tcg_gen_addi_i32(newsp, addr, imm);
10901 gen_helper_v8m_stackcheck(cpu_env, newsp);
10902 tcg_temp_free_i32(newsp);
10903 } else {
10904 gen_helper_v8m_stackcheck(cpu_env, addr);
10905 }
10906 }
10907
10908 if (writeback && !postinc) {
10909 tcg_gen_addi_i32(addr, addr, imm);
10910 }
10911
9ee6e8bb
PB
10912 if (insn & (1 << 20)) {
10913 /* Load. */
5a839c0d 10914 tmp = tcg_temp_new_i32();
a2fdc890 10915 switch (op) {
5a839c0d 10916 case 0:
9bb6558a 10917 gen_aa32_ld8u_iss(s, tmp, addr, memidx, issinfo);
5a839c0d
PM
10918 break;
10919 case 4:
9bb6558a 10920 gen_aa32_ld8s_iss(s, tmp, addr, memidx, issinfo);
5a839c0d
PM
10921 break;
10922 case 1:
9bb6558a 10923 gen_aa32_ld16u_iss(s, tmp, addr, memidx, issinfo);
5a839c0d
PM
10924 break;
10925 case 5:
9bb6558a 10926 gen_aa32_ld16s_iss(s, tmp, addr, memidx, issinfo);
5a839c0d
PM
10927 break;
10928 case 2:
9bb6558a 10929 gen_aa32_ld32u_iss(s, tmp, addr, memidx, issinfo);
5a839c0d 10930 break;
2a0308c5 10931 default:
5a839c0d 10932 tcg_temp_free_i32(tmp);
2a0308c5
PM
10933 tcg_temp_free_i32(addr);
10934 goto illegal_op;
a2fdc890
PM
10935 }
10936 if (rs == 15) {
3bb8a96f 10937 gen_bx_excret(s, tmp);
9ee6e8bb 10938 } else {
a2fdc890 10939 store_reg(s, rs, tmp);
9ee6e8bb
PB
10940 }
10941 } else {
10942 /* Store. */
b0109805 10943 tmp = load_reg(s, rs);
9ee6e8bb 10944 switch (op) {
5a839c0d 10945 case 0:
9bb6558a 10946 gen_aa32_st8_iss(s, tmp, addr, memidx, issinfo);
5a839c0d
PM
10947 break;
10948 case 1:
9bb6558a 10949 gen_aa32_st16_iss(s, tmp, addr, memidx, issinfo);
5a839c0d
PM
10950 break;
10951 case 2:
9bb6558a 10952 gen_aa32_st32_iss(s, tmp, addr, memidx, issinfo);
5a839c0d 10953 break;
2a0308c5 10954 default:
5a839c0d 10955 tcg_temp_free_i32(tmp);
2a0308c5
PM
10956 tcg_temp_free_i32(addr);
10957 goto illegal_op;
b7bcbe95 10958 }
5a839c0d 10959 tcg_temp_free_i32(tmp);
2c0262af 10960 }
9ee6e8bb 10961 if (postinc)
b0109805
PB
10962 tcg_gen_addi_i32(addr, addr, imm);
10963 if (writeback) {
10964 store_reg(s, rn, addr);
10965 } else {
7d1b0095 10966 tcg_temp_free_i32(addr);
b0109805 10967 }
9ee6e8bb
PB
10968 }
10969 break;
10970 default:
10971 goto illegal_op;
2c0262af 10972 }
2eea841c 10973 return;
9ee6e8bb 10974illegal_op:
2eea841c
PM
10975 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
10976 default_exception_el(s));
2c0262af
FB
10977}
10978
296e5a0a 10979static void disas_thumb_insn(DisasContext *s, uint32_t insn)
99c475ab 10980{
296e5a0a 10981 uint32_t val, op, rm, rn, rd, shift, cond;
99c475ab
FB
10982 int32_t offset;
10983 int i;
39d5492a
PM
10984 TCGv_i32 tmp;
10985 TCGv_i32 tmp2;
10986 TCGv_i32 addr;
99c475ab 10987
99c475ab
FB
10988 switch (insn >> 12) {
10989 case 0: case 1:
396e467c 10990
99c475ab
FB
10991 rd = insn & 7;
10992 op = (insn >> 11) & 3;
10993 if (op == 3) {
a2d12f0f
PM
10994 /*
10995 * 0b0001_1xxx_xxxx_xxxx
10996 * - Add, subtract (three low registers)
10997 * - Add, subtract (two low registers and immediate)
10998 */
99c475ab 10999 rn = (insn >> 3) & 7;
396e467c 11000 tmp = load_reg(s, rn);
99c475ab
FB
11001 if (insn & (1 << 10)) {
11002 /* immediate */
7d1b0095 11003 tmp2 = tcg_temp_new_i32();
396e467c 11004 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
99c475ab
FB
11005 } else {
11006 /* reg */
11007 rm = (insn >> 6) & 7;
396e467c 11008 tmp2 = load_reg(s, rm);
99c475ab 11009 }
9ee6e8bb
PB
11010 if (insn & (1 << 9)) {
11011 if (s->condexec_mask)
396e467c 11012 tcg_gen_sub_i32(tmp, tmp, tmp2);
9ee6e8bb 11013 else
72485ec4 11014 gen_sub_CC(tmp, tmp, tmp2);
9ee6e8bb
PB
11015 } else {
11016 if (s->condexec_mask)
396e467c 11017 tcg_gen_add_i32(tmp, tmp, tmp2);
9ee6e8bb 11018 else
72485ec4 11019 gen_add_CC(tmp, tmp, tmp2);
9ee6e8bb 11020 }
7d1b0095 11021 tcg_temp_free_i32(tmp2);
396e467c 11022 store_reg(s, rd, tmp);
99c475ab
FB
11023 } else {
11024 /* shift immediate */
11025 rm = (insn >> 3) & 7;
11026 shift = (insn >> 6) & 0x1f;
9a119ff6
PB
11027 tmp = load_reg(s, rm);
11028 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
11029 if (!s->condexec_mask)
11030 gen_logic_CC(tmp);
11031 store_reg(s, rd, tmp);
99c475ab
FB
11032 }
11033 break;
11034 case 2: case 3:
a2d12f0f
PM
11035 /*
11036 * 0b001x_xxxx_xxxx_xxxx
11037 * - Add, subtract, compare, move (one low register and immediate)
11038 */
99c475ab
FB
11039 op = (insn >> 11) & 3;
11040 rd = (insn >> 8) & 0x7;
396e467c 11041 if (op == 0) { /* mov */
7d1b0095 11042 tmp = tcg_temp_new_i32();
396e467c 11043 tcg_gen_movi_i32(tmp, insn & 0xff);
9ee6e8bb 11044 if (!s->condexec_mask)
396e467c
FN
11045 gen_logic_CC(tmp);
11046 store_reg(s, rd, tmp);
11047 } else {
11048 tmp = load_reg(s, rd);
7d1b0095 11049 tmp2 = tcg_temp_new_i32();
396e467c
FN
11050 tcg_gen_movi_i32(tmp2, insn & 0xff);
11051 switch (op) {
11052 case 1: /* cmp */
72485ec4 11053 gen_sub_CC(tmp, tmp, tmp2);
7d1b0095
PM
11054 tcg_temp_free_i32(tmp);
11055 tcg_temp_free_i32(tmp2);
396e467c
FN
11056 break;
11057 case 2: /* add */
11058 if (s->condexec_mask)
11059 tcg_gen_add_i32(tmp, tmp, tmp2);
11060 else
72485ec4 11061 gen_add_CC(tmp, tmp, tmp2);
7d1b0095 11062 tcg_temp_free_i32(tmp2);
396e467c
FN
11063 store_reg(s, rd, tmp);
11064 break;
11065 case 3: /* sub */
11066 if (s->condexec_mask)
11067 tcg_gen_sub_i32(tmp, tmp, tmp2);
11068 else
72485ec4 11069 gen_sub_CC(tmp, tmp, tmp2);
7d1b0095 11070 tcg_temp_free_i32(tmp2);
396e467c
FN
11071 store_reg(s, rd, tmp);
11072 break;
11073 }
99c475ab 11074 }
99c475ab
FB
11075 break;
11076 case 4:
11077 if (insn & (1 << 11)) {
11078 rd = (insn >> 8) & 7;
5899f386
FB
11079 /* load pc-relative. Bit 1 of PC is ignored. */
11080 val = s->pc + 2 + ((insn & 0xff) * 4);
11081 val &= ~(uint32_t)2;
7d1b0095 11082 addr = tcg_temp_new_i32();
b0109805 11083 tcg_gen_movi_i32(addr, val);
c40c8556 11084 tmp = tcg_temp_new_i32();
9bb6558a
PM
11085 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s),
11086 rd | ISSIs16Bit);
7d1b0095 11087 tcg_temp_free_i32(addr);
b0109805 11088 store_reg(s, rd, tmp);
99c475ab
FB
11089 break;
11090 }
11091 if (insn & (1 << 10)) {
ebfe27c5
PM
11092 /* 0b0100_01xx_xxxx_xxxx
11093 * - data processing extended, branch and exchange
11094 */
99c475ab
FB
11095 rd = (insn & 7) | ((insn >> 4) & 8);
11096 rm = (insn >> 3) & 0xf;
11097 op = (insn >> 8) & 3;
11098 switch (op) {
11099 case 0: /* add */
396e467c
FN
11100 tmp = load_reg(s, rd);
11101 tmp2 = load_reg(s, rm);
11102 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 11103 tcg_temp_free_i32(tmp2);
55203189
PM
11104 if (rd == 13) {
11105 /* ADD SP, SP, reg */
11106 store_sp_checked(s, tmp);
11107 } else {
11108 store_reg(s, rd, tmp);
11109 }
99c475ab
FB
11110 break;
11111 case 1: /* cmp */
396e467c
FN
11112 tmp = load_reg(s, rd);
11113 tmp2 = load_reg(s, rm);
72485ec4 11114 gen_sub_CC(tmp, tmp, tmp2);
7d1b0095
PM
11115 tcg_temp_free_i32(tmp2);
11116 tcg_temp_free_i32(tmp);
99c475ab
FB
11117 break;
11118 case 2: /* mov/cpy */
396e467c 11119 tmp = load_reg(s, rm);
55203189
PM
11120 if (rd == 13) {
11121 /* MOV SP, reg */
11122 store_sp_checked(s, tmp);
11123 } else {
11124 store_reg(s, rd, tmp);
11125 }
99c475ab 11126 break;
ebfe27c5
PM
11127 case 3:
11128 {
11129 /* 0b0100_0111_xxxx_xxxx
11130 * - branch [and link] exchange thumb register
11131 */
11132 bool link = insn & (1 << 7);
11133
fb602cb7 11134 if (insn & 3) {
ebfe27c5
PM
11135 goto undef;
11136 }
11137 if (link) {
be5e7a76 11138 ARCH(5);
ebfe27c5 11139 }
fb602cb7
PM
11140 if ((insn & 4)) {
11141 /* BXNS/BLXNS: only exists for v8M with the
11142 * security extensions, and always UNDEF if NonSecure.
11143 * We don't implement these in the user-only mode
11144 * either (in theory you can use them from Secure User
11145 * mode but they are too tied in to system emulation.)
11146 */
11147 if (!s->v8m_secure || IS_USER_ONLY) {
11148 goto undef;
11149 }
11150 if (link) {
3e3fa230 11151 gen_blxns(s, rm);
fb602cb7
PM
11152 } else {
11153 gen_bxns(s, rm);
11154 }
11155 break;
11156 }
11157 /* BLX/BX */
ebfe27c5
PM
11158 tmp = load_reg(s, rm);
11159 if (link) {
99c475ab 11160 val = (uint32_t)s->pc | 1;
7d1b0095 11161 tmp2 = tcg_temp_new_i32();
b0109805
PB
11162 tcg_gen_movi_i32(tmp2, val);
11163 store_reg(s, 14, tmp2);
3bb8a96f
PM
11164 gen_bx(s, tmp);
11165 } else {
11166 /* Only BX works as exception-return, not BLX */
11167 gen_bx_excret(s, tmp);
99c475ab 11168 }
99c475ab
FB
11169 break;
11170 }
ebfe27c5 11171 }
99c475ab
FB
11172 break;
11173 }
11174
a2d12f0f
PM
11175 /*
11176 * 0b0100_00xx_xxxx_xxxx
11177 * - Data-processing (two low registers)
11178 */
99c475ab
FB
11179 rd = insn & 7;
11180 rm = (insn >> 3) & 7;
11181 op = (insn >> 6) & 0xf;
11182 if (op == 2 || op == 3 || op == 4 || op == 7) {
11183 /* the shift/rotate ops want the operands backwards */
11184 val = rm;
11185 rm = rd;
11186 rd = val;
11187 val = 1;
11188 } else {
11189 val = 0;
11190 }
11191
396e467c 11192 if (op == 9) { /* neg */
7d1b0095 11193 tmp = tcg_temp_new_i32();
396e467c
FN
11194 tcg_gen_movi_i32(tmp, 0);
11195 } else if (op != 0xf) { /* mvn doesn't read its first operand */
11196 tmp = load_reg(s, rd);
11197 } else {
f764718d 11198 tmp = NULL;
396e467c 11199 }
99c475ab 11200
396e467c 11201 tmp2 = load_reg(s, rm);
5899f386 11202 switch (op) {
99c475ab 11203 case 0x0: /* and */
396e467c 11204 tcg_gen_and_i32(tmp, tmp, tmp2);
9ee6e8bb 11205 if (!s->condexec_mask)
396e467c 11206 gen_logic_CC(tmp);
99c475ab
FB
11207 break;
11208 case 0x1: /* eor */
396e467c 11209 tcg_gen_xor_i32(tmp, tmp, tmp2);
9ee6e8bb 11210 if (!s->condexec_mask)
396e467c 11211 gen_logic_CC(tmp);
99c475ab
FB
11212 break;
11213 case 0x2: /* lsl */
9ee6e8bb 11214 if (s->condexec_mask) {
365af80e 11215 gen_shl(tmp2, tmp2, tmp);
9ee6e8bb 11216 } else {
9ef39277 11217 gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
396e467c 11218 gen_logic_CC(tmp2);
9ee6e8bb 11219 }
99c475ab
FB
11220 break;
11221 case 0x3: /* lsr */
9ee6e8bb 11222 if (s->condexec_mask) {
365af80e 11223 gen_shr(tmp2, tmp2, tmp);
9ee6e8bb 11224 } else {
9ef39277 11225 gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
396e467c 11226 gen_logic_CC(tmp2);
9ee6e8bb 11227 }
99c475ab
FB
11228 break;
11229 case 0x4: /* asr */
9ee6e8bb 11230 if (s->condexec_mask) {
365af80e 11231 gen_sar(tmp2, tmp2, tmp);
9ee6e8bb 11232 } else {
9ef39277 11233 gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
396e467c 11234 gen_logic_CC(tmp2);
9ee6e8bb 11235 }
99c475ab
FB
11236 break;
11237 case 0x5: /* adc */
49b4c31e 11238 if (s->condexec_mask) {
396e467c 11239 gen_adc(tmp, tmp2);
49b4c31e
RH
11240 } else {
11241 gen_adc_CC(tmp, tmp, tmp2);
11242 }
99c475ab
FB
11243 break;
11244 case 0x6: /* sbc */
2de68a49 11245 if (s->condexec_mask) {
396e467c 11246 gen_sub_carry(tmp, tmp, tmp2);
2de68a49
RH
11247 } else {
11248 gen_sbc_CC(tmp, tmp, tmp2);
11249 }
99c475ab
FB
11250 break;
11251 case 0x7: /* ror */
9ee6e8bb 11252 if (s->condexec_mask) {
f669df27
AJ
11253 tcg_gen_andi_i32(tmp, tmp, 0x1f);
11254 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
9ee6e8bb 11255 } else {
9ef39277 11256 gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);
396e467c 11257 gen_logic_CC(tmp2);
9ee6e8bb 11258 }
99c475ab
FB
11259 break;
11260 case 0x8: /* tst */
396e467c
FN
11261 tcg_gen_and_i32(tmp, tmp, tmp2);
11262 gen_logic_CC(tmp);
99c475ab 11263 rd = 16;
5899f386 11264 break;
99c475ab 11265 case 0x9: /* neg */
9ee6e8bb 11266 if (s->condexec_mask)
396e467c 11267 tcg_gen_neg_i32(tmp, tmp2);
9ee6e8bb 11268 else
72485ec4 11269 gen_sub_CC(tmp, tmp, tmp2);
99c475ab
FB
11270 break;
11271 case 0xa: /* cmp */
72485ec4 11272 gen_sub_CC(tmp, tmp, tmp2);
99c475ab
FB
11273 rd = 16;
11274 break;
11275 case 0xb: /* cmn */
72485ec4 11276 gen_add_CC(tmp, tmp, tmp2);
99c475ab
FB
11277 rd = 16;
11278 break;
11279 case 0xc: /* orr */
396e467c 11280 tcg_gen_or_i32(tmp, tmp, tmp2);
9ee6e8bb 11281 if (!s->condexec_mask)
396e467c 11282 gen_logic_CC(tmp);
99c475ab
FB
11283 break;
11284 case 0xd: /* mul */
7b2919a0 11285 tcg_gen_mul_i32(tmp, tmp, tmp2);
9ee6e8bb 11286 if (!s->condexec_mask)
396e467c 11287 gen_logic_CC(tmp);
99c475ab
FB
11288 break;
11289 case 0xe: /* bic */
f669df27 11290 tcg_gen_andc_i32(tmp, tmp, tmp2);
9ee6e8bb 11291 if (!s->condexec_mask)
396e467c 11292 gen_logic_CC(tmp);
99c475ab
FB
11293 break;
11294 case 0xf: /* mvn */
396e467c 11295 tcg_gen_not_i32(tmp2, tmp2);
9ee6e8bb 11296 if (!s->condexec_mask)
396e467c 11297 gen_logic_CC(tmp2);
99c475ab 11298 val = 1;
5899f386 11299 rm = rd;
99c475ab
FB
11300 break;
11301 }
11302 if (rd != 16) {
396e467c
FN
11303 if (val) {
11304 store_reg(s, rm, tmp2);
11305 if (op != 0xf)
7d1b0095 11306 tcg_temp_free_i32(tmp);
396e467c
FN
11307 } else {
11308 store_reg(s, rd, tmp);
7d1b0095 11309 tcg_temp_free_i32(tmp2);
396e467c
FN
11310 }
11311 } else {
7d1b0095
PM
11312 tcg_temp_free_i32(tmp);
11313 tcg_temp_free_i32(tmp2);
99c475ab
FB
11314 }
11315 break;
11316
11317 case 5:
11318 /* load/store register offset. */
11319 rd = insn & 7;
11320 rn = (insn >> 3) & 7;
11321 rm = (insn >> 6) & 7;
11322 op = (insn >> 9) & 7;
b0109805 11323 addr = load_reg(s, rn);
b26eefb6 11324 tmp = load_reg(s, rm);
b0109805 11325 tcg_gen_add_i32(addr, addr, tmp);
7d1b0095 11326 tcg_temp_free_i32(tmp);
99c475ab 11327
c40c8556 11328 if (op < 3) { /* store */
b0109805 11329 tmp = load_reg(s, rd);
c40c8556
PM
11330 } else {
11331 tmp = tcg_temp_new_i32();
11332 }
99c475ab
FB
11333
11334 switch (op) {
11335 case 0: /* str */
9bb6558a 11336 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
11337 break;
11338 case 1: /* strh */
9bb6558a 11339 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
11340 break;
11341 case 2: /* strb */
9bb6558a 11342 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
11343 break;
11344 case 3: /* ldrsb */
9bb6558a 11345 gen_aa32_ld8s_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
11346 break;
11347 case 4: /* ldr */
9bb6558a 11348 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
11349 break;
11350 case 5: /* ldrh */
9bb6558a 11351 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
11352 break;
11353 case 6: /* ldrb */
9bb6558a 11354 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
11355 break;
11356 case 7: /* ldrsh */
9bb6558a 11357 gen_aa32_ld16s_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
11358 break;
11359 }
c40c8556 11360 if (op >= 3) { /* load */
b0109805 11361 store_reg(s, rd, tmp);
c40c8556
PM
11362 } else {
11363 tcg_temp_free_i32(tmp);
11364 }
7d1b0095 11365 tcg_temp_free_i32(addr);
99c475ab
FB
11366 break;
11367
11368 case 6:
11369 /* load/store word immediate offset */
11370 rd = insn & 7;
11371 rn = (insn >> 3) & 7;
b0109805 11372 addr = load_reg(s, rn);
99c475ab 11373 val = (insn >> 4) & 0x7c;
b0109805 11374 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
11375
11376 if (insn & (1 << 11)) {
11377 /* load */
c40c8556 11378 tmp = tcg_temp_new_i32();
12dcc321 11379 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 11380 store_reg(s, rd, tmp);
99c475ab
FB
11381 } else {
11382 /* store */
b0109805 11383 tmp = load_reg(s, rd);
12dcc321 11384 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
c40c8556 11385 tcg_temp_free_i32(tmp);
99c475ab 11386 }
7d1b0095 11387 tcg_temp_free_i32(addr);
99c475ab
FB
11388 break;
11389
11390 case 7:
11391 /* load/store byte immediate offset */
11392 rd = insn & 7;
11393 rn = (insn >> 3) & 7;
b0109805 11394 addr = load_reg(s, rn);
99c475ab 11395 val = (insn >> 6) & 0x1f;
b0109805 11396 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
11397
11398 if (insn & (1 << 11)) {
11399 /* load */
c40c8556 11400 tmp = tcg_temp_new_i32();
9bb6558a 11401 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
b0109805 11402 store_reg(s, rd, tmp);
99c475ab
FB
11403 } else {
11404 /* store */
b0109805 11405 tmp = load_reg(s, rd);
9bb6558a 11406 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
c40c8556 11407 tcg_temp_free_i32(tmp);
99c475ab 11408 }
7d1b0095 11409 tcg_temp_free_i32(addr);
99c475ab
FB
11410 break;
11411
11412 case 8:
11413 /* load/store halfword immediate offset */
11414 rd = insn & 7;
11415 rn = (insn >> 3) & 7;
b0109805 11416 addr = load_reg(s, rn);
99c475ab 11417 val = (insn >> 5) & 0x3e;
b0109805 11418 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
11419
11420 if (insn & (1 << 11)) {
11421 /* load */
c40c8556 11422 tmp = tcg_temp_new_i32();
9bb6558a 11423 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
b0109805 11424 store_reg(s, rd, tmp);
99c475ab
FB
11425 } else {
11426 /* store */
b0109805 11427 tmp = load_reg(s, rd);
9bb6558a 11428 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
c40c8556 11429 tcg_temp_free_i32(tmp);
99c475ab 11430 }
7d1b0095 11431 tcg_temp_free_i32(addr);
99c475ab
FB
11432 break;
11433
11434 case 9:
11435 /* load/store from stack */
11436 rd = (insn >> 8) & 7;
b0109805 11437 addr = load_reg(s, 13);
99c475ab 11438 val = (insn & 0xff) * 4;
b0109805 11439 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
11440
11441 if (insn & (1 << 11)) {
11442 /* load */
c40c8556 11443 tmp = tcg_temp_new_i32();
9bb6558a 11444 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
b0109805 11445 store_reg(s, rd, tmp);
99c475ab
FB
11446 } else {
11447 /* store */
b0109805 11448 tmp = load_reg(s, rd);
9bb6558a 11449 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
c40c8556 11450 tcg_temp_free_i32(tmp);
99c475ab 11451 }
7d1b0095 11452 tcg_temp_free_i32(addr);
99c475ab
FB
11453 break;
11454
11455 case 10:
55203189
PM
11456 /*
11457 * 0b1010_xxxx_xxxx_xxxx
11458 * - Add PC/SP (immediate)
11459 */
99c475ab 11460 rd = (insn >> 8) & 7;
5899f386
FB
11461 if (insn & (1 << 11)) {
11462 /* SP */
5e3f878a 11463 tmp = load_reg(s, 13);
5899f386
FB
11464 } else {
11465 /* PC. bit 1 is ignored. */
7d1b0095 11466 tmp = tcg_temp_new_i32();
5e3f878a 11467 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
5899f386 11468 }
99c475ab 11469 val = (insn & 0xff) * 4;
5e3f878a
PB
11470 tcg_gen_addi_i32(tmp, tmp, val);
11471 store_reg(s, rd, tmp);
99c475ab
FB
11472 break;
11473
11474 case 11:
11475 /* misc */
11476 op = (insn >> 8) & 0xf;
11477 switch (op) {
11478 case 0:
55203189
PM
11479 /*
11480 * 0b1011_0000_xxxx_xxxx
11481 * - ADD (SP plus immediate)
11482 * - SUB (SP minus immediate)
11483 */
b26eefb6 11484 tmp = load_reg(s, 13);
99c475ab
FB
11485 val = (insn & 0x7f) * 4;
11486 if (insn & (1 << 7))
6a0d8a1d 11487 val = -(int32_t)val;
b26eefb6 11488 tcg_gen_addi_i32(tmp, tmp, val);
55203189 11489 store_sp_checked(s, tmp);
99c475ab
FB
11490 break;
11491
9ee6e8bb
PB
11492 case 2: /* sign/zero extend. */
11493 ARCH(6);
11494 rd = insn & 7;
11495 rm = (insn >> 3) & 7;
b0109805 11496 tmp = load_reg(s, rm);
9ee6e8bb 11497 switch ((insn >> 6) & 3) {
b0109805
PB
11498 case 0: gen_sxth(tmp); break;
11499 case 1: gen_sxtb(tmp); break;
11500 case 2: gen_uxth(tmp); break;
11501 case 3: gen_uxtb(tmp); break;
9ee6e8bb 11502 }
b0109805 11503 store_reg(s, rd, tmp);
9ee6e8bb 11504 break;
99c475ab 11505 case 4: case 5: case 0xc: case 0xd:
aa369e5c
PM
11506 /*
11507 * 0b1011_x10x_xxxx_xxxx
11508 * - push/pop
11509 */
b0109805 11510 addr = load_reg(s, 13);
5899f386
FB
11511 if (insn & (1 << 8))
11512 offset = 4;
99c475ab 11513 else
5899f386
FB
11514 offset = 0;
11515 for (i = 0; i < 8; i++) {
11516 if (insn & (1 << i))
11517 offset += 4;
11518 }
11519 if ((insn & (1 << 11)) == 0) {
b0109805 11520 tcg_gen_addi_i32(addr, addr, -offset);
5899f386 11521 }
aa369e5c
PM
11522
11523 if (s->v8m_stackcheck) {
11524 /*
11525 * Here 'addr' is the lower of "old SP" and "new SP";
11526 * if this is a pop that starts below the limit and ends
11527 * above it, it is UNKNOWN whether the limit check triggers;
11528 * we choose to trigger.
11529 */
11530 gen_helper_v8m_stackcheck(cpu_env, addr);
11531 }
11532
99c475ab
FB
11533 for (i = 0; i < 8; i++) {
11534 if (insn & (1 << i)) {
11535 if (insn & (1 << 11)) {
11536 /* pop */
c40c8556 11537 tmp = tcg_temp_new_i32();
12dcc321 11538 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 11539 store_reg(s, i, tmp);
99c475ab
FB
11540 } else {
11541 /* push */
b0109805 11542 tmp = load_reg(s, i);
12dcc321 11543 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
c40c8556 11544 tcg_temp_free_i32(tmp);
99c475ab 11545 }
5899f386 11546 /* advance to the next address. */
b0109805 11547 tcg_gen_addi_i32(addr, addr, 4);
99c475ab
FB
11548 }
11549 }
f764718d 11550 tmp = NULL;
99c475ab
FB
11551 if (insn & (1 << 8)) {
11552 if (insn & (1 << 11)) {
11553 /* pop pc */
c40c8556 11554 tmp = tcg_temp_new_i32();
12dcc321 11555 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
99c475ab
FB
11556 /* don't set the pc until the rest of the instruction
11557 has completed */
11558 } else {
11559 /* push lr */
b0109805 11560 tmp = load_reg(s, 14);
12dcc321 11561 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
c40c8556 11562 tcg_temp_free_i32(tmp);
99c475ab 11563 }
b0109805 11564 tcg_gen_addi_i32(addr, addr, 4);
99c475ab 11565 }
5899f386 11566 if ((insn & (1 << 11)) == 0) {
b0109805 11567 tcg_gen_addi_i32(addr, addr, -offset);
5899f386 11568 }
99c475ab 11569 /* write back the new stack pointer */
b0109805 11570 store_reg(s, 13, addr);
99c475ab 11571 /* set the new PC value */
be5e7a76 11572 if ((insn & 0x0900) == 0x0900) {
7dcc1f89 11573 store_reg_from_load(s, 15, tmp);
be5e7a76 11574 }
99c475ab
FB
11575 break;
11576
9ee6e8bb
PB
11577 case 1: case 3: case 9: case 11: /* czb */
11578 rm = insn & 7;
d9ba4830 11579 tmp = load_reg(s, rm);
c2d9644e 11580 arm_gen_condlabel(s);
9ee6e8bb 11581 if (insn & (1 << 11))
cb63669a 11582 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
9ee6e8bb 11583 else
cb63669a 11584 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
7d1b0095 11585 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
11586 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
11587 val = (uint32_t)s->pc + 2;
11588 val += offset;
11589 gen_jmp(s, val);
11590 break;
11591
11592 case 15: /* IT, nop-hint. */
11593 if ((insn & 0xf) == 0) {
11594 gen_nop_hint(s, (insn >> 4) & 0xf);
11595 break;
11596 }
5529de1e
PM
11597 /*
11598 * IT (If-Then)
11599 *
11600 * Combinations of firstcond and mask which set up an 0b1111
11601 * condition are UNPREDICTABLE; we take the CONSTRAINED
11602 * UNPREDICTABLE choice to treat 0b1111 the same as 0b1110,
11603 * i.e. both meaning "execute always".
11604 */
9ee6e8bb
PB
11605 s->condexec_cond = (insn >> 4) & 0xe;
11606 s->condexec_mask = insn & 0x1f;
11607 /* No actual code generated for this insn, just setup state. */
11608 break;
11609
06c949e6 11610 case 0xe: /* bkpt */
d4a2dc67
PM
11611 {
11612 int imm8 = extract32(insn, 0, 8);
be5e7a76 11613 ARCH(5);
c900a2e6 11614 gen_exception_bkpt_insn(s, 2, syn_aa32_bkpt(imm8, true));
06c949e6 11615 break;
d4a2dc67 11616 }
06c949e6 11617
19a6e31c
PM
11618 case 0xa: /* rev, and hlt */
11619 {
11620 int op1 = extract32(insn, 6, 2);
11621
11622 if (op1 == 2) {
11623 /* HLT */
11624 int imm6 = extract32(insn, 0, 6);
11625
11626 gen_hlt(s, imm6);
11627 break;
11628 }
11629
11630 /* Otherwise this is rev */
9ee6e8bb
PB
11631 ARCH(6);
11632 rn = (insn >> 3) & 0x7;
11633 rd = insn & 0x7;
b0109805 11634 tmp = load_reg(s, rn);
19a6e31c 11635 switch (op1) {
66896cb8 11636 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
b0109805
PB
11637 case 1: gen_rev16(tmp); break;
11638 case 3: gen_revsh(tmp); break;
19a6e31c
PM
11639 default:
11640 g_assert_not_reached();
9ee6e8bb 11641 }
b0109805 11642 store_reg(s, rd, tmp);
9ee6e8bb 11643 break;
19a6e31c 11644 }
9ee6e8bb 11645
d9e028c1
PM
11646 case 6:
11647 switch ((insn >> 5) & 7) {
11648 case 2:
11649 /* setend */
11650 ARCH(6);
9886ecdf
PB
11651 if (((insn >> 3) & 1) != !!(s->be_data == MO_BE)) {
11652 gen_helper_setend(cpu_env);
dcba3a8d 11653 s->base.is_jmp = DISAS_UPDATE;
d9e028c1 11654 }
9ee6e8bb 11655 break;
d9e028c1
PM
11656 case 3:
11657 /* cps */
11658 ARCH(6);
11659 if (IS_USER(s)) {
11660 break;
8984bd2e 11661 }
b53d8923 11662 if (arm_dc_feature(s, ARM_FEATURE_M)) {
d9e028c1
PM
11663 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
11664 /* FAULTMASK */
11665 if (insn & 1) {
11666 addr = tcg_const_i32(19);
11667 gen_helper_v7m_msr(cpu_env, addr, tmp);
11668 tcg_temp_free_i32(addr);
11669 }
11670 /* PRIMASK */
11671 if (insn & 2) {
11672 addr = tcg_const_i32(16);
11673 gen_helper_v7m_msr(cpu_env, addr, tmp);
11674 tcg_temp_free_i32(addr);
11675 }
11676 tcg_temp_free_i32(tmp);
11677 gen_lookup_tb(s);
11678 } else {
11679 if (insn & (1 << 4)) {
11680 shift = CPSR_A | CPSR_I | CPSR_F;
11681 } else {
11682 shift = 0;
11683 }
11684 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
8984bd2e 11685 }
d9e028c1
PM
11686 break;
11687 default:
11688 goto undef;
9ee6e8bb
PB
11689 }
11690 break;
11691
99c475ab
FB
11692 default:
11693 goto undef;
11694 }
11695 break;
11696
11697 case 12:
a7d3970d 11698 {
99c475ab 11699 /* load/store multiple */
f764718d 11700 TCGv_i32 loaded_var = NULL;
99c475ab 11701 rn = (insn >> 8) & 0x7;
b0109805 11702 addr = load_reg(s, rn);
99c475ab
FB
11703 for (i = 0; i < 8; i++) {
11704 if (insn & (1 << i)) {
99c475ab
FB
11705 if (insn & (1 << 11)) {
11706 /* load */
c40c8556 11707 tmp = tcg_temp_new_i32();
12dcc321 11708 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
a7d3970d
PM
11709 if (i == rn) {
11710 loaded_var = tmp;
11711 } else {
11712 store_reg(s, i, tmp);
11713 }
99c475ab
FB
11714 } else {
11715 /* store */
b0109805 11716 tmp = load_reg(s, i);
12dcc321 11717 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
c40c8556 11718 tcg_temp_free_i32(tmp);
99c475ab 11719 }
5899f386 11720 /* advance to the next address */
b0109805 11721 tcg_gen_addi_i32(addr, addr, 4);
99c475ab
FB
11722 }
11723 }
b0109805 11724 if ((insn & (1 << rn)) == 0) {
a7d3970d 11725 /* base reg not in list: base register writeback */
b0109805
PB
11726 store_reg(s, rn, addr);
11727 } else {
a7d3970d
PM
11728 /* base reg in list: if load, complete it now */
11729 if (insn & (1 << 11)) {
11730 store_reg(s, rn, loaded_var);
11731 }
7d1b0095 11732 tcg_temp_free_i32(addr);
b0109805 11733 }
99c475ab 11734 break;
a7d3970d 11735 }
99c475ab
FB
11736 case 13:
11737 /* conditional branch or swi */
11738 cond = (insn >> 8) & 0xf;
11739 if (cond == 0xe)
11740 goto undef;
11741
11742 if (cond == 0xf) {
11743 /* swi */
eaed129d 11744 gen_set_pc_im(s, s->pc);
d4a2dc67 11745 s->svc_imm = extract32(insn, 0, 8);
dcba3a8d 11746 s->base.is_jmp = DISAS_SWI;
99c475ab
FB
11747 break;
11748 }
11749 /* generate a conditional jump to next instruction */
c2d9644e 11750 arm_skip_unless(s, cond);
99c475ab
FB
11751
11752 /* jump to the offset */
5899f386 11753 val = (uint32_t)s->pc + 2;
99c475ab 11754 offset = ((int32_t)insn << 24) >> 24;
5899f386 11755 val += offset << 1;
8aaca4c0 11756 gen_jmp(s, val);
99c475ab
FB
11757 break;
11758
11759 case 14:
358bf29e 11760 if (insn & (1 << 11)) {
296e5a0a
PM
11761 /* thumb_insn_is_16bit() ensures we can't get here for
11762 * a Thumb2 CPU, so this must be a thumb1 split BL/BLX:
11763 * 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF)
11764 */
11765 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
11766 ARCH(5);
11767 offset = ((insn & 0x7ff) << 1);
11768 tmp = load_reg(s, 14);
11769 tcg_gen_addi_i32(tmp, tmp, offset);
11770 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
11771
11772 tmp2 = tcg_temp_new_i32();
11773 tcg_gen_movi_i32(tmp2, s->pc | 1);
11774 store_reg(s, 14, tmp2);
11775 gen_bx(s, tmp);
358bf29e
PB
11776 break;
11777 }
9ee6e8bb 11778 /* unconditional branch */
99c475ab
FB
11779 val = (uint32_t)s->pc;
11780 offset = ((int32_t)insn << 21) >> 21;
11781 val += (offset << 1) + 2;
8aaca4c0 11782 gen_jmp(s, val);
99c475ab
FB
11783 break;
11784
11785 case 15:
296e5a0a
PM
11786 /* thumb_insn_is_16bit() ensures we can't get here for
11787 * a Thumb2 CPU, so this must be a thumb1 split BL/BLX.
11788 */
11789 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
11790
11791 if (insn & (1 << 11)) {
11792 /* 0b1111_1xxx_xxxx_xxxx : BL suffix */
11793 offset = ((insn & 0x7ff) << 1) | 1;
11794 tmp = load_reg(s, 14);
11795 tcg_gen_addi_i32(tmp, tmp, offset);
11796
11797 tmp2 = tcg_temp_new_i32();
11798 tcg_gen_movi_i32(tmp2, s->pc | 1);
11799 store_reg(s, 14, tmp2);
11800 gen_bx(s, tmp);
11801 } else {
11802 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix */
11803 uint32_t uoffset = ((int32_t)insn << 21) >> 9;
11804
11805 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + uoffset);
11806 }
9ee6e8bb 11807 break;
99c475ab
FB
11808 }
11809 return;
9ee6e8bb 11810illegal_op:
99c475ab 11811undef:
73710361
GB
11812 gen_exception_insn(s, 2, EXCP_UDEF, syn_uncategorized(),
11813 default_exception_el(s));
99c475ab
FB
11814}
11815
541ebcd4
PM
11816static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
11817{
11818 /* Return true if the insn at dc->pc might cross a page boundary.
11819 * (False positives are OK, false negatives are not.)
5b8d7289
PM
11820 * We know this is a Thumb insn, and our caller ensures we are
11821 * only called if dc->pc is less than 4 bytes from the page
11822 * boundary, so we cross the page if the first 16 bits indicate
11823 * that this is a 32 bit insn.
541ebcd4 11824 */
5b8d7289 11825 uint16_t insn = arm_lduw_code(env, s->pc, s->sctlr_b);
541ebcd4 11826
5b8d7289 11827 return !thumb_insn_is_16bit(s, insn);
541ebcd4
PM
11828}
11829
b542683d 11830static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
2c0262af 11831{
1d8a5535 11832 DisasContext *dc = container_of(dcbase, DisasContext, base);
9c489ea6 11833 CPUARMState *env = cs->env_ptr;
2fc0cc0e 11834 ARMCPU *cpu = env_archcpu(env);
aad821ac
RH
11835 uint32_t tb_flags = dc->base.tb->flags;
11836 uint32_t condexec, core_mmu_idx;
3b46e624 11837
962fcbf2 11838 dc->isar = &cpu->isar;
dcba3a8d 11839 dc->pc = dc->base.pc_first;
e50e6a20 11840 dc->condjmp = 0;
3926cc84 11841
40f860cd 11842 dc->aarch64 = 0;
cef9ee70
SS
11843 /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
11844 * there is no secure EL1, so we route exceptions to EL3.
11845 */
11846 dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
11847 !arm_el_is_aa64(env, 3);
aad821ac
RH
11848 dc->thumb = FIELD_EX32(tb_flags, TBFLAG_A32, THUMB);
11849 dc->sctlr_b = FIELD_EX32(tb_flags, TBFLAG_A32, SCTLR_B);
11850 dc->be_data = FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
11851 condexec = FIELD_EX32(tb_flags, TBFLAG_A32, CONDEXEC);
11852 dc->condexec_mask = (condexec & 0xf) << 1;
11853 dc->condexec_cond = condexec >> 4;
11854 core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX);
11855 dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
c1e37810 11856 dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
3926cc84 11857#if !defined(CONFIG_USER_ONLY)
c1e37810 11858 dc->user = (dc->current_el == 0);
3926cc84 11859#endif
aad821ac
RH
11860 dc->ns = FIELD_EX32(tb_flags, TBFLAG_A32, NS);
11861 dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL);
11862 dc->vfp_enabled = FIELD_EX32(tb_flags, TBFLAG_A32, VFPEN);
11863 dc->vec_len = FIELD_EX32(tb_flags, TBFLAG_A32, VECLEN);
ea7ac69d
PM
11864 if (arm_feature(env, ARM_FEATURE_XSCALE)) {
11865 dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
11866 dc->vec_stride = 0;
11867 } else {
11868 dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
11869 dc->c15_cpar = 0;
11870 }
aad821ac 11871 dc->v7m_handler_mode = FIELD_EX32(tb_flags, TBFLAG_A32, HANDLER);
fb602cb7
PM
11872 dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
11873 regime_is_secure(env, dc->mmu_idx);
aad821ac 11874 dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_A32, STACKCHECK);
6d60c67a 11875 dc->v8m_fpccr_s_wrong = FIELD_EX32(tb_flags, TBFLAG_A32, FPCCR_S_WRONG);
6000531e
PM
11876 dc->v7m_new_fp_ctxt_needed =
11877 FIELD_EX32(tb_flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED);
e33cf0f8 11878 dc->v7m_lspact = FIELD_EX32(tb_flags, TBFLAG_A32, LSPACT);
60322b39 11879 dc->cp_regs = cpu->cp_regs;
a984e42c 11880 dc->features = env->features;
40f860cd 11881
50225ad0
PM
11882 /* Single step state. The code-generation logic here is:
11883 * SS_ACTIVE == 0:
11884 * generate code with no special handling for single-stepping (except
11885 * that anything that can make us go to SS_ACTIVE == 1 must end the TB;
11886 * this happens anyway because those changes are all system register or
11887 * PSTATE writes).
11888 * SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
11889 * emit code for one insn
11890 * emit code to clear PSTATE.SS
11891 * emit code to generate software step exception for completed step
11892 * end TB (as usual for having generated an exception)
11893 * SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
11894 * emit code to generate a software step exception
11895 * end the TB
11896 */
aad821ac
RH
11897 dc->ss_active = FIELD_EX32(tb_flags, TBFLAG_ANY, SS_ACTIVE);
11898 dc->pstate_ss = FIELD_EX32(tb_flags, TBFLAG_ANY, PSTATE_SS);
50225ad0
PM
11899 dc->is_ldex = false;
11900 dc->ss_same_el = false; /* Can't be true since EL_d must be AArch64 */
11901
bfe7ad5b 11902 dc->page_start = dc->base.pc_first & TARGET_PAGE_MASK;
1d8a5535 11903
f7708456
RH
11904 /* If architectural single step active, limit to 1. */
11905 if (is_singlestepping(dc)) {
b542683d 11906 dc->base.max_insns = 1;
f7708456
RH
11907 }
11908
d0264d86
RH
11909 /* ARM is a fixed-length ISA. Bound the number of insns to execute
11910 to those left on the page. */
11911 if (!dc->thumb) {
bfe7ad5b 11912 int bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
b542683d 11913 dc->base.max_insns = MIN(dc->base.max_insns, bound);
d0264d86
RH
11914 }
11915
d9eea52c
PM
11916 cpu_V0 = tcg_temp_new_i64();
11917 cpu_V1 = tcg_temp_new_i64();
e677137d 11918 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
a7812ae4 11919 cpu_M0 = tcg_temp_new_i64();
1d8a5535
LV
11920}
11921
b1476854
LV
11922static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
11923{
11924 DisasContext *dc = container_of(dcbase, DisasContext, base);
11925
11926 /* A note on handling of the condexec (IT) bits:
11927 *
11928 * We want to avoid the overhead of having to write the updated condexec
11929 * bits back to the CPUARMState for every instruction in an IT block. So:
11930 * (1) if the condexec bits are not already zero then we write
11931 * zero back into the CPUARMState now. This avoids complications trying
11932 * to do it at the end of the block. (For example if we don't do this
11933 * it's hard to identify whether we can safely skip writing condexec
11934 * at the end of the TB, which we definitely want to do for the case
11935 * where a TB doesn't do anything with the IT state at all.)
11936 * (2) if we are going to leave the TB then we call gen_set_condexec()
11937 * which will write the correct value into CPUARMState if zero is wrong.
11938 * This is done both for leaving the TB at the end, and for leaving
11939 * it because of an exception we know will happen, which is done in
11940 * gen_exception_insn(). The latter is necessary because we need to
11941 * leave the TB with the PC/IT state just prior to execution of the
11942 * instruction which caused the exception.
11943 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
11944 * then the CPUARMState will be wrong and we need to reset it.
11945 * This is handled in the same way as restoration of the
11946 * PC in these situations; we save the value of the condexec bits
11947 * for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
11948 * then uses this to restore them after an exception.
11949 *
11950 * Note that there are no instructions which can read the condexec
11951 * bits, and none which can write non-static values to them, so
11952 * we don't need to care about whether CPUARMState is correct in the
11953 * middle of a TB.
11954 */
11955
11956 /* Reset the conditional execution bits immediately. This avoids
11957 complications trying to do it at the end of the block. */
11958 if (dc->condexec_mask || dc->condexec_cond) {
11959 TCGv_i32 tmp = tcg_temp_new_i32();
11960 tcg_gen_movi_i32(tmp, 0);
11961 store_cpu_field(tmp, condexec_bits);
11962 }
11963}
11964
f62bd897
LV
11965static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
11966{
11967 DisasContext *dc = container_of(dcbase, DisasContext, base);
11968
f62bd897
LV
11969 tcg_gen_insn_start(dc->pc,
11970 (dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
11971 0);
15fa08f8 11972 dc->insn_start = tcg_last_op();
f62bd897
LV
11973}
11974
a68956ad
LV
11975static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
11976 const CPUBreakpoint *bp)
11977{
11978 DisasContext *dc = container_of(dcbase, DisasContext, base);
11979
11980 if (bp->flags & BP_CPU) {
11981 gen_set_condexec(dc);
11982 gen_set_pc_im(dc, dc->pc);
11983 gen_helper_check_breakpoints(cpu_env);
11984 /* End the TB early; it's likely not going to be executed */
11985 dc->base.is_jmp = DISAS_TOO_MANY;
11986 } else {
11987 gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
11988 /* The address covered by the breakpoint must be
11989 included in [tb->pc, tb->pc + tb->size) in order
11990 to for it to be properly cleared -- thus we
11991 increment the PC here so that the logic setting
11992 tb->size below does the right thing. */
11993 /* TODO: Advance PC by correct instruction length to
11994 * avoid disassembler error messages */
11995 dc->pc += 2;
11996 dc->base.is_jmp = DISAS_NORETURN;
11997 }
11998
11999 return true;
12000}
12001
722ef0a5 12002static bool arm_pre_translate_insn(DisasContext *dc)
13189a90 12003{
13189a90
LV
12004#ifdef CONFIG_USER_ONLY
12005 /* Intercept jump to the magic kernel page. */
12006 if (dc->pc >= 0xffff0000) {
12007 /* We always get here via a jump, so know we are not in a
12008 conditional execution block. */
12009 gen_exception_internal(EXCP_KERNEL_TRAP);
12010 dc->base.is_jmp = DISAS_NORETURN;
722ef0a5 12011 return true;
13189a90
LV
12012 }
12013#endif
12014
12015 if (dc->ss_active && !dc->pstate_ss) {
12016 /* Singlestep state is Active-pending.
12017 * If we're in this state at the start of a TB then either
12018 * a) we just took an exception to an EL which is being debugged
12019 * and this is the first insn in the exception handler
12020 * b) debug exceptions were masked and we just unmasked them
12021 * without changing EL (eg by clearing PSTATE.D)
12022 * In either case we're going to take a swstep exception in the
12023 * "did not step an insn" case, and so the syndrome ISV and EX
12024 * bits should be zero.
12025 */
12026 assert(dc->base.num_insns == 1);
12027 gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
12028 default_exception_el(dc));
12029 dc->base.is_jmp = DISAS_NORETURN;
722ef0a5 12030 return true;
13189a90
LV
12031 }
12032
722ef0a5
RH
12033 return false;
12034}
13189a90 12035
d0264d86 12036static void arm_post_translate_insn(DisasContext *dc)
722ef0a5 12037{
13189a90
LV
12038 if (dc->condjmp && !dc->base.is_jmp) {
12039 gen_set_label(dc->condlabel);
12040 dc->condjmp = 0;
12041 }
13189a90 12042 dc->base.pc_next = dc->pc;
23169224 12043 translator_loop_temp_check(&dc->base);
13189a90
LV
12044}
12045
722ef0a5
RH
12046static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
12047{
12048 DisasContext *dc = container_of(dcbase, DisasContext, base);
12049 CPUARMState *env = cpu->env_ptr;
12050 unsigned int insn;
12051
12052 if (arm_pre_translate_insn(dc)) {
12053 return;
12054 }
12055
12056 insn = arm_ldl_code(env, dc->pc, dc->sctlr_b);
58803318 12057 dc->insn = insn;
722ef0a5
RH
12058 dc->pc += 4;
12059 disas_arm_insn(dc, insn);
12060
d0264d86
RH
12061 arm_post_translate_insn(dc);
12062
12063 /* ARM is a fixed-length ISA. We performed the cross-page check
12064 in init_disas_context by adjusting max_insns. */
722ef0a5
RH
12065}
12066
dcf14dfb
PM
12067static bool thumb_insn_is_unconditional(DisasContext *s, uint32_t insn)
12068{
12069 /* Return true if this Thumb insn is always unconditional,
12070 * even inside an IT block. This is true of only a very few
12071 * instructions: BKPT, HLT, and SG.
12072 *
12073 * A larger class of instructions are UNPREDICTABLE if used
12074 * inside an IT block; we do not need to detect those here, because
12075 * what we do by default (perform the cc check and update the IT
12076 * bits state machine) is a permitted CONSTRAINED UNPREDICTABLE
12077 * choice for those situations.
12078 *
12079 * insn is either a 16-bit or a 32-bit instruction; the two are
12080 * distinguishable because for the 16-bit case the top 16 bits
12081 * are zeroes, and that isn't a valid 32-bit encoding.
12082 */
12083 if ((insn & 0xffffff00) == 0xbe00) {
12084 /* BKPT */
12085 return true;
12086 }
12087
12088 if ((insn & 0xffffffc0) == 0xba80 && arm_dc_feature(s, ARM_FEATURE_V8) &&
12089 !arm_dc_feature(s, ARM_FEATURE_M)) {
12090 /* HLT: v8A only. This is unconditional even when it is going to
12091 * UNDEF; see the v8A ARM ARM DDI0487B.a H3.3.
12092 * For v7 cores this was a plain old undefined encoding and so
12093 * honours its cc check. (We might be using the encoding as
12094 * a semihosting trap, but we don't change the cc check behaviour
12095 * on that account, because a debugger connected to a real v7A
12096 * core and emulating semihosting traps by catching the UNDEF
12097 * exception would also only see cases where the cc check passed.
12098 * No guest code should be trying to do a HLT semihosting trap
12099 * in an IT block anyway.
12100 */
12101 return true;
12102 }
12103
12104 if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_V8) &&
12105 arm_dc_feature(s, ARM_FEATURE_M)) {
12106 /* SG: v8M only */
12107 return true;
12108 }
12109
12110 return false;
12111}
12112
722ef0a5
RH
12113static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
12114{
12115 DisasContext *dc = container_of(dcbase, DisasContext, base);
12116 CPUARMState *env = cpu->env_ptr;
296e5a0a
PM
12117 uint32_t insn;
12118 bool is_16bit;
722ef0a5
RH
12119
12120 if (arm_pre_translate_insn(dc)) {
12121 return;
12122 }
12123
296e5a0a
PM
12124 insn = arm_lduw_code(env, dc->pc, dc->sctlr_b);
12125 is_16bit = thumb_insn_is_16bit(dc, insn);
12126 dc->pc += 2;
12127 if (!is_16bit) {
12128 uint32_t insn2 = arm_lduw_code(env, dc->pc, dc->sctlr_b);
12129
12130 insn = insn << 16 | insn2;
12131 dc->pc += 2;
12132 }
58803318 12133 dc->insn = insn;
296e5a0a 12134
dcf14dfb 12135 if (dc->condexec_mask && !thumb_insn_is_unconditional(dc, insn)) {
296e5a0a
PM
12136 uint32_t cond = dc->condexec_cond;
12137
5529de1e
PM
12138 /*
12139 * Conditionally skip the insn. Note that both 0xe and 0xf mean
12140 * "always"; 0xf is not "never".
12141 */
12142 if (cond < 0x0e) {
c2d9644e 12143 arm_skip_unless(dc, cond);
296e5a0a
PM
12144 }
12145 }
12146
12147 if (is_16bit) {
12148 disas_thumb_insn(dc, insn);
12149 } else {
2eea841c 12150 disas_thumb2_insn(dc, insn);
296e5a0a 12151 }
722ef0a5
RH
12152
12153 /* Advance the Thumb condexec condition. */
12154 if (dc->condexec_mask) {
12155 dc->condexec_cond = ((dc->condexec_cond & 0xe) |
12156 ((dc->condexec_mask >> 4) & 1));
12157 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
12158 if (dc->condexec_mask == 0) {
12159 dc->condexec_cond = 0;
12160 }
12161 }
12162
d0264d86
RH
12163 arm_post_translate_insn(dc);
12164
12165 /* Thumb is a variable-length ISA. Stop translation when the next insn
12166 * will touch a new page. This ensures that prefetch aborts occur at
12167 * the right place.
12168 *
12169 * We want to stop the TB if the next insn starts in a new page,
12170 * or if it spans between this page and the next. This means that
12171 * if we're looking at the last halfword in the page we need to
12172 * see if it's a 16-bit Thumb insn (which will fit in this TB)
12173 * or a 32-bit Thumb insn (which won't).
12174 * This is to avoid generating a silly TB with a single 16-bit insn
12175 * in it at the end of this page (which would execute correctly
12176 * but isn't very efficient).
12177 */
12178 if (dc->base.is_jmp == DISAS_NEXT
bfe7ad5b
EC
12179 && (dc->pc - dc->page_start >= TARGET_PAGE_SIZE
12180 || (dc->pc - dc->page_start >= TARGET_PAGE_SIZE - 3
d0264d86
RH
12181 && insn_crosses_page(env, dc)))) {
12182 dc->base.is_jmp = DISAS_TOO_MANY;
12183 }
722ef0a5
RH
12184}
12185
70d3c035 12186static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
1d8a5535 12187{
70d3c035 12188 DisasContext *dc = container_of(dcbase, DisasContext, base);
2e70f6ef 12189
c5a49c63 12190 if (tb_cflags(dc->base.tb) & CF_LAST_IO && dc->condjmp) {
70d3c035
LV
12191 /* FIXME: This can theoretically happen with self-modifying code. */
12192 cpu_abort(cpu, "IO on conditional branch instruction");
2e70f6ef 12193 }
9ee6e8bb 12194
b5ff1b31 12195 /* At this stage dc->condjmp will only be set when the skipped
9ee6e8bb
PB
12196 instruction was a conditional branch or trap, and the PC has
12197 already been written. */
f021b2c4 12198 gen_set_condexec(dc);
dcba3a8d 12199 if (dc->base.is_jmp == DISAS_BX_EXCRET) {
3bb8a96f
PM
12200 /* Exception return branches need some special case code at the
12201 * end of the TB, which is complex enough that it has to
12202 * handle the single-step vs not and the condition-failed
12203 * insn codepath itself.
12204 */
12205 gen_bx_excret_final_code(dc);
12206 } else if (unlikely(is_singlestepping(dc))) {
7999a5c8 12207 /* Unconditional and "condition passed" instruction codepath. */
dcba3a8d 12208 switch (dc->base.is_jmp) {
7999a5c8 12209 case DISAS_SWI:
50225ad0 12210 gen_ss_advance(dc);
73710361
GB
12211 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
12212 default_exception_el(dc));
7999a5c8
SF
12213 break;
12214 case DISAS_HVC:
37e6456e 12215 gen_ss_advance(dc);
73710361 12216 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
7999a5c8
SF
12217 break;
12218 case DISAS_SMC:
37e6456e 12219 gen_ss_advance(dc);
73710361 12220 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
7999a5c8
SF
12221 break;
12222 case DISAS_NEXT:
a68956ad 12223 case DISAS_TOO_MANY:
7999a5c8
SF
12224 case DISAS_UPDATE:
12225 gen_set_pc_im(dc, dc->pc);
12226 /* fall through */
12227 default:
5425415e
PM
12228 /* FIXME: Single stepping a WFI insn will not halt the CPU. */
12229 gen_singlestep_exception(dc);
a0c231e6
RH
12230 break;
12231 case DISAS_NORETURN:
12232 break;
7999a5c8 12233 }
8aaca4c0 12234 } else {
9ee6e8bb
PB
12235 /* While branches must always occur at the end of an IT block,
12236 there are a few other things that can cause us to terminate
65626741 12237 the TB in the middle of an IT block:
9ee6e8bb
PB
12238 - Exception generating instructions (bkpt, swi, undefined).
12239 - Page boundaries.
12240 - Hardware watchpoints.
12241 Hardware breakpoints have already been handled and skip this code.
12242 */
dcba3a8d 12243 switch(dc->base.is_jmp) {
8aaca4c0 12244 case DISAS_NEXT:
a68956ad 12245 case DISAS_TOO_MANY:
6e256c93 12246 gen_goto_tb(dc, 1, dc->pc);
8aaca4c0 12247 break;
577bf808 12248 case DISAS_JUMP:
8a6b28c7
EC
12249 gen_goto_ptr();
12250 break;
e8d52302
AB
12251 case DISAS_UPDATE:
12252 gen_set_pc_im(dc, dc->pc);
12253 /* fall through */
577bf808 12254 default:
8aaca4c0 12255 /* indicate that the hash table must be used to find the next TB */
07ea28b4 12256 tcg_gen_exit_tb(NULL, 0);
8aaca4c0 12257 break;
a0c231e6 12258 case DISAS_NORETURN:
8aaca4c0
FB
12259 /* nothing more to generate */
12260 break;
9ee6e8bb 12261 case DISAS_WFI:
58803318
SS
12262 {
12263 TCGv_i32 tmp = tcg_const_i32((dc->thumb &&
12264 !(dc->insn & (1U << 31))) ? 2 : 4);
12265
12266 gen_helper_wfi(cpu_env, tmp);
12267 tcg_temp_free_i32(tmp);
84549b6d
PM
12268 /* The helper doesn't necessarily throw an exception, but we
12269 * must go back to the main loop to check for interrupts anyway.
12270 */
07ea28b4 12271 tcg_gen_exit_tb(NULL, 0);
9ee6e8bb 12272 break;
58803318 12273 }
72c1d3af
PM
12274 case DISAS_WFE:
12275 gen_helper_wfe(cpu_env);
12276 break;
c87e5a61
PM
12277 case DISAS_YIELD:
12278 gen_helper_yield(cpu_env);
12279 break;
9ee6e8bb 12280 case DISAS_SWI:
73710361
GB
12281 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
12282 default_exception_el(dc));
9ee6e8bb 12283 break;
37e6456e 12284 case DISAS_HVC:
73710361 12285 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
37e6456e
PM
12286 break;
12287 case DISAS_SMC:
73710361 12288 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
37e6456e 12289 break;
8aaca4c0 12290 }
f021b2c4
PM
12291 }
12292
12293 if (dc->condjmp) {
12294 /* "Condition failed" instruction codepath for the branch/trap insn */
12295 gen_set_label(dc->condlabel);
12296 gen_set_condexec(dc);
b636649f 12297 if (unlikely(is_singlestepping(dc))) {
f021b2c4
PM
12298 gen_set_pc_im(dc, dc->pc);
12299 gen_singlestep_exception(dc);
12300 } else {
6e256c93 12301 gen_goto_tb(dc, 1, dc->pc);
e50e6a20 12302 }
2c0262af 12303 }
23169224
LV
12304
12305 /* Functions above can change dc->pc, so re-align db->pc_next */
12306 dc->base.pc_next = dc->pc;
70d3c035
LV
12307}
12308
4013f7fc
LV
12309static void arm_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
12310{
12311 DisasContext *dc = container_of(dcbase, DisasContext, base);
12312
12313 qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
1d48474d 12314 log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
4013f7fc
LV
12315}
12316
23169224
LV
12317static const TranslatorOps arm_translator_ops = {
12318 .init_disas_context = arm_tr_init_disas_context,
12319 .tb_start = arm_tr_tb_start,
12320 .insn_start = arm_tr_insn_start,
12321 .breakpoint_check = arm_tr_breakpoint_check,
12322 .translate_insn = arm_tr_translate_insn,
12323 .tb_stop = arm_tr_tb_stop,
12324 .disas_log = arm_tr_disas_log,
12325};
12326
722ef0a5
RH
12327static const TranslatorOps thumb_translator_ops = {
12328 .init_disas_context = arm_tr_init_disas_context,
12329 .tb_start = arm_tr_tb_start,
12330 .insn_start = arm_tr_insn_start,
12331 .breakpoint_check = arm_tr_breakpoint_check,
12332 .translate_insn = thumb_tr_translate_insn,
12333 .tb_stop = arm_tr_tb_stop,
12334 .disas_log = arm_tr_disas_log,
12335};
12336
70d3c035 12337/* generate intermediate code for basic block 'tb'. */
8b86d6d2 12338void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
70d3c035 12339{
23169224
LV
12340 DisasContext dc;
12341 const TranslatorOps *ops = &arm_translator_ops;
70d3c035 12342
aad821ac 12343 if (FIELD_EX32(tb->flags, TBFLAG_A32, THUMB)) {
722ef0a5
RH
12344 ops = &thumb_translator_ops;
12345 }
23169224 12346#ifdef TARGET_AARCH64
aad821ac 12347 if (FIELD_EX32(tb->flags, TBFLAG_ANY, AARCH64_STATE)) {
23169224 12348 ops = &aarch64_translator_ops;
2c0262af
FB
12349 }
12350#endif
23169224 12351
8b86d6d2 12352 translator_loop(ops, &dc.base, cpu, tb, max_insns);
2c0262af
FB
12353}
12354
bad729e2
RH
12355void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
12356 target_ulong *data)
d2856f1a 12357{
3926cc84 12358 if (is_a64(env)) {
bad729e2 12359 env->pc = data[0];
40f860cd 12360 env->condexec_bits = 0;
aaa1f954 12361 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
3926cc84 12362 } else {
bad729e2
RH
12363 env->regs[15] = data[0];
12364 env->condexec_bits = data[1];
aaa1f954 12365 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
3926cc84 12366 }
d2856f1a 12367}