]> git.proxmox.com Git - mirror_qemu.git/blame - target/arm/translate.c
target/arm: Reorg NEON VLD/VST all elements
[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"
19a6e31c 32#include "exec/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
b26eefb6 69/* FIXME: These should be removed. */
39d5492a 70static TCGv_i32 cpu_F0s, cpu_F1s;
a7812ae4 71static TCGv_i64 cpu_F0d, cpu_F1d;
b26eefb6 72
022c62cb 73#include "exec/gen-icount.h"
2e70f6ef 74
308e5636 75static const char * const regnames[] =
155c3eac
FN
76 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
77 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
78
61adacc8
RH
79/* Function prototypes for gen_ functions calling Neon helpers. */
80typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32,
81 TCGv_i32, TCGv_i32);
82
b26eefb6
PB
83/* initialize TCG globals. */
84void arm_translate_init(void)
85{
155c3eac
FN
86 int i;
87
155c3eac 88 for (i = 0; i < 16; i++) {
e1ccc054 89 cpu_R[i] = tcg_global_mem_new_i32(cpu_env,
0ecb72a5 90 offsetof(CPUARMState, regs[i]),
155c3eac
FN
91 regnames[i]);
92 }
e1ccc054
RH
93 cpu_CF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, CF), "CF");
94 cpu_NF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, NF), "NF");
95 cpu_VF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, VF), "VF");
96 cpu_ZF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, ZF), "ZF");
66c374de 97
e1ccc054 98 cpu_exclusive_addr = tcg_global_mem_new_i64(cpu_env,
0ecb72a5 99 offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
e1ccc054 100 cpu_exclusive_val = tcg_global_mem_new_i64(cpu_env,
0ecb72a5 101 offsetof(CPUARMState, exclusive_val), "exclusive_val");
155c3eac 102
14ade10f 103 a64_translate_init();
b26eefb6
PB
104}
105
9bb6558a
PM
106/* Flags for the disas_set_da_iss info argument:
107 * lower bits hold the Rt register number, higher bits are flags.
108 */
109typedef enum ISSInfo {
110 ISSNone = 0,
111 ISSRegMask = 0x1f,
112 ISSInvalid = (1 << 5),
113 ISSIsAcqRel = (1 << 6),
114 ISSIsWrite = (1 << 7),
115 ISSIs16Bit = (1 << 8),
116} ISSInfo;
117
118/* Save the syndrome information for a Data Abort */
119static void disas_set_da_iss(DisasContext *s, TCGMemOp memop, ISSInfo issinfo)
120{
121 uint32_t syn;
122 int sas = memop & MO_SIZE;
123 bool sse = memop & MO_SIGN;
124 bool is_acqrel = issinfo & ISSIsAcqRel;
125 bool is_write = issinfo & ISSIsWrite;
126 bool is_16bit = issinfo & ISSIs16Bit;
127 int srt = issinfo & ISSRegMask;
128
129 if (issinfo & ISSInvalid) {
130 /* Some callsites want to conditionally provide ISS info,
131 * eg "only if this was not a writeback"
132 */
133 return;
134 }
135
136 if (srt == 15) {
137 /* For AArch32, insns where the src/dest is R15 never generate
138 * ISS information. Catching that here saves checking at all
139 * the call sites.
140 */
141 return;
142 }
143
144 syn = syn_data_abort_with_iss(0, sas, sse, srt, 0, is_acqrel,
145 0, 0, 0, is_write, 0, is_16bit);
146 disas_set_insn_syndrome(s, syn);
147}
148
8bd5c820 149static inline int get_a32_user_mem_index(DisasContext *s)
579d21cc 150{
8bd5c820 151 /* Return the core mmu_idx to use for A32/T32 "unprivileged load/store"
579d21cc
PM
152 * insns:
153 * if PL2, UNPREDICTABLE (we choose to implement as if PL0)
154 * otherwise, access as if at PL0.
155 */
156 switch (s->mmu_idx) {
157 case ARMMMUIdx_S1E2: /* this one is UNPREDICTABLE */
158 case ARMMMUIdx_S12NSE0:
159 case ARMMMUIdx_S12NSE1:
8bd5c820 160 return arm_to_core_mmu_idx(ARMMMUIdx_S12NSE0);
579d21cc
PM
161 case ARMMMUIdx_S1E3:
162 case ARMMMUIdx_S1SE0:
163 case ARMMMUIdx_S1SE1:
8bd5c820 164 return arm_to_core_mmu_idx(ARMMMUIdx_S1SE0);
e7b921c2
PM
165 case ARMMMUIdx_MUser:
166 case ARMMMUIdx_MPriv:
167 return arm_to_core_mmu_idx(ARMMMUIdx_MUser);
62593718
PM
168 case ARMMMUIdx_MUserNegPri:
169 case ARMMMUIdx_MPrivNegPri:
170 return arm_to_core_mmu_idx(ARMMMUIdx_MUserNegPri);
b9f587d6
PM
171 case ARMMMUIdx_MSUser:
172 case ARMMMUIdx_MSPriv:
b9f587d6 173 return arm_to_core_mmu_idx(ARMMMUIdx_MSUser);
62593718
PM
174 case ARMMMUIdx_MSUserNegPri:
175 case ARMMMUIdx_MSPrivNegPri:
176 return arm_to_core_mmu_idx(ARMMMUIdx_MSUserNegPri);
579d21cc
PM
177 case ARMMMUIdx_S2NS:
178 default:
179 g_assert_not_reached();
180 }
181}
182
39d5492a 183static inline TCGv_i32 load_cpu_offset(int offset)
d9ba4830 184{
39d5492a 185 TCGv_i32 tmp = tcg_temp_new_i32();
d9ba4830
PB
186 tcg_gen_ld_i32(tmp, cpu_env, offset);
187 return tmp;
188}
189
0ecb72a5 190#define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
d9ba4830 191
39d5492a 192static inline void store_cpu_offset(TCGv_i32 var, int offset)
d9ba4830
PB
193{
194 tcg_gen_st_i32(var, cpu_env, offset);
7d1b0095 195 tcg_temp_free_i32(var);
d9ba4830
PB
196}
197
198#define store_cpu_field(var, name) \
0ecb72a5 199 store_cpu_offset(var, offsetof(CPUARMState, name))
d9ba4830 200
b26eefb6 201/* Set a variable to the value of a CPU register. */
39d5492a 202static void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
b26eefb6
PB
203{
204 if (reg == 15) {
205 uint32_t addr;
b90372ad 206 /* normally, since we updated PC, we need only to add one insn */
b26eefb6
PB
207 if (s->thumb)
208 addr = (long)s->pc + 2;
209 else
210 addr = (long)s->pc + 4;
211 tcg_gen_movi_i32(var, addr);
212 } else {
155c3eac 213 tcg_gen_mov_i32(var, cpu_R[reg]);
b26eefb6
PB
214 }
215}
216
217/* Create a new temporary and set it to the value of a CPU register. */
39d5492a 218static inline TCGv_i32 load_reg(DisasContext *s, int reg)
b26eefb6 219{
39d5492a 220 TCGv_i32 tmp = tcg_temp_new_i32();
b26eefb6
PB
221 load_reg_var(s, tmp, reg);
222 return tmp;
223}
224
225/* Set a CPU register. The source must be a temporary and will be
226 marked as dead. */
39d5492a 227static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
b26eefb6
PB
228{
229 if (reg == 15) {
9b6a3ea7
PM
230 /* In Thumb mode, we must ignore bit 0.
231 * In ARM mode, for ARMv4 and ARMv5, it is UNPREDICTABLE if bits [1:0]
232 * are not 0b00, but for ARMv6 and above, we must ignore bits [1:0].
233 * We choose to ignore [1:0] in ARM mode for all architecture versions.
234 */
235 tcg_gen_andi_i32(var, var, s->thumb ? ~1 : ~3);
dcba3a8d 236 s->base.is_jmp = DISAS_JUMP;
b26eefb6 237 }
155c3eac 238 tcg_gen_mov_i32(cpu_R[reg], var);
7d1b0095 239 tcg_temp_free_i32(var);
b26eefb6
PB
240}
241
55203189
PM
242/*
243 * Variant of store_reg which applies v8M stack-limit checks before updating
244 * SP. If the check fails this will result in an exception being taken.
245 * We disable the stack checks for CONFIG_USER_ONLY because we have
246 * no idea what the stack limits should be in that case.
247 * If stack checking is not being done this just acts like store_reg().
248 */
249static void store_sp_checked(DisasContext *s, TCGv_i32 var)
250{
251#ifndef CONFIG_USER_ONLY
252 if (s->v8m_stackcheck) {
253 gen_helper_v8m_stackcheck(cpu_env, var);
254 }
255#endif
256 store_reg(s, 13, var);
257}
258
b26eefb6 259/* Value extensions. */
86831435
PB
260#define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
261#define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
b26eefb6
PB
262#define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
263#define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
264
1497c961
PB
265#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
266#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
8f01245e 267
b26eefb6 268
39d5492a 269static inline void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
b75263d6 270{
39d5492a 271 TCGv_i32 tmp_mask = tcg_const_i32(mask);
1ce94f81 272 gen_helper_cpsr_write(cpu_env, var, tmp_mask);
b75263d6
JR
273 tcg_temp_free_i32(tmp_mask);
274}
d9ba4830
PB
275/* Set NZCV flags from the high 4 bits of var. */
276#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
277
d4a2dc67 278static void gen_exception_internal(int excp)
d9ba4830 279{
d4a2dc67
PM
280 TCGv_i32 tcg_excp = tcg_const_i32(excp);
281
282 assert(excp_is_internal(excp));
283 gen_helper_exception_internal(cpu_env, tcg_excp);
284 tcg_temp_free_i32(tcg_excp);
285}
286
73710361 287static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el)
d4a2dc67
PM
288{
289 TCGv_i32 tcg_excp = tcg_const_i32(excp);
290 TCGv_i32 tcg_syn = tcg_const_i32(syndrome);
73710361 291 TCGv_i32 tcg_el = tcg_const_i32(target_el);
d4a2dc67 292
73710361
GB
293 gen_helper_exception_with_syndrome(cpu_env, tcg_excp,
294 tcg_syn, tcg_el);
295
296 tcg_temp_free_i32(tcg_el);
d4a2dc67
PM
297 tcg_temp_free_i32(tcg_syn);
298 tcg_temp_free_i32(tcg_excp);
d9ba4830
PB
299}
300
50225ad0
PM
301static void gen_ss_advance(DisasContext *s)
302{
303 /* If the singlestep state is Active-not-pending, advance to
304 * Active-pending.
305 */
306 if (s->ss_active) {
307 s->pstate_ss = 0;
308 gen_helper_clear_pstate_ss(cpu_env);
309 }
310}
311
312static void gen_step_complete_exception(DisasContext *s)
313{
314 /* We just completed step of an insn. Move from Active-not-pending
315 * to Active-pending, and then also take the swstep exception.
316 * This corresponds to making the (IMPDEF) choice to prioritize
317 * swstep exceptions over asynchronous exceptions taken to an exception
318 * level where debug is disabled. This choice has the advantage that
319 * we do not need to maintain internal state corresponding to the
320 * ISV/EX syndrome bits between completion of the step and generation
321 * of the exception, and our syndrome information is always correct.
322 */
323 gen_ss_advance(s);
73710361
GB
324 gen_exception(EXCP_UDEF, syn_swstep(s->ss_same_el, 1, s->is_ldex),
325 default_exception_el(s));
dcba3a8d 326 s->base.is_jmp = DISAS_NORETURN;
50225ad0
PM
327}
328
5425415e
PM
329static void gen_singlestep_exception(DisasContext *s)
330{
331 /* Generate the right kind of exception for singlestep, which is
332 * either the architectural singlestep or EXCP_DEBUG for QEMU's
333 * gdb singlestepping.
334 */
335 if (s->ss_active) {
336 gen_step_complete_exception(s);
337 } else {
338 gen_exception_internal(EXCP_DEBUG);
339 }
340}
341
b636649f
PM
342static inline bool is_singlestepping(DisasContext *s)
343{
344 /* Return true if we are singlestepping either because of
345 * architectural singlestep or QEMU gdbstub singlestep. This does
346 * not include the command line '-singlestep' mode which is rather
347 * misnamed as it only means "one instruction per TB" and doesn't
348 * affect the code we generate.
349 */
dcba3a8d 350 return s->base.singlestep_enabled || s->ss_active;
b636649f
PM
351}
352
39d5492a 353static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
3670669c 354{
39d5492a
PM
355 TCGv_i32 tmp1 = tcg_temp_new_i32();
356 TCGv_i32 tmp2 = tcg_temp_new_i32();
22478e79
AZ
357 tcg_gen_ext16s_i32(tmp1, a);
358 tcg_gen_ext16s_i32(tmp2, b);
3670669c 359 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
7d1b0095 360 tcg_temp_free_i32(tmp2);
3670669c
PB
361 tcg_gen_sari_i32(a, a, 16);
362 tcg_gen_sari_i32(b, b, 16);
363 tcg_gen_mul_i32(b, b, a);
364 tcg_gen_mov_i32(a, tmp1);
7d1b0095 365 tcg_temp_free_i32(tmp1);
3670669c
PB
366}
367
368/* Byteswap each halfword. */
39d5492a 369static void gen_rev16(TCGv_i32 var)
3670669c 370{
39d5492a 371 TCGv_i32 tmp = tcg_temp_new_i32();
68cedf73 372 TCGv_i32 mask = tcg_const_i32(0x00ff00ff);
3670669c 373 tcg_gen_shri_i32(tmp, var, 8);
68cedf73
AJ
374 tcg_gen_and_i32(tmp, tmp, mask);
375 tcg_gen_and_i32(var, var, mask);
3670669c 376 tcg_gen_shli_i32(var, var, 8);
3670669c 377 tcg_gen_or_i32(var, var, tmp);
68cedf73 378 tcg_temp_free_i32(mask);
7d1b0095 379 tcg_temp_free_i32(tmp);
3670669c
PB
380}
381
382/* Byteswap low halfword and sign extend. */
39d5492a 383static void gen_revsh(TCGv_i32 var)
3670669c 384{
1a855029
AJ
385 tcg_gen_ext16u_i32(var, var);
386 tcg_gen_bswap16_i32(var, var);
387 tcg_gen_ext16s_i32(var, var);
3670669c
PB
388}
389
838fa72d 390/* Return (b << 32) + a. Mark inputs as dead */
39d5492a 391static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv_i32 b)
3670669c 392{
838fa72d
AJ
393 TCGv_i64 tmp64 = tcg_temp_new_i64();
394
395 tcg_gen_extu_i32_i64(tmp64, b);
7d1b0095 396 tcg_temp_free_i32(b);
838fa72d
AJ
397 tcg_gen_shli_i64(tmp64, tmp64, 32);
398 tcg_gen_add_i64(a, tmp64, a);
399
400 tcg_temp_free_i64(tmp64);
401 return a;
402}
403
404/* Return (b << 32) - a. Mark inputs as dead. */
39d5492a 405static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv_i32 b)
838fa72d
AJ
406{
407 TCGv_i64 tmp64 = tcg_temp_new_i64();
408
409 tcg_gen_extu_i32_i64(tmp64, b);
7d1b0095 410 tcg_temp_free_i32(b);
838fa72d
AJ
411 tcg_gen_shli_i64(tmp64, tmp64, 32);
412 tcg_gen_sub_i64(a, tmp64, a);
413
414 tcg_temp_free_i64(tmp64);
415 return a;
3670669c
PB
416}
417
5e3f878a 418/* 32x32->64 multiply. Marks inputs as dead. */
39d5492a 419static TCGv_i64 gen_mulu_i64_i32(TCGv_i32 a, TCGv_i32 b)
5e3f878a 420{
39d5492a
PM
421 TCGv_i32 lo = tcg_temp_new_i32();
422 TCGv_i32 hi = tcg_temp_new_i32();
831d7fe8 423 TCGv_i64 ret;
5e3f878a 424
831d7fe8 425 tcg_gen_mulu2_i32(lo, hi, a, b);
7d1b0095 426 tcg_temp_free_i32(a);
7d1b0095 427 tcg_temp_free_i32(b);
831d7fe8
RH
428
429 ret = tcg_temp_new_i64();
430 tcg_gen_concat_i32_i64(ret, lo, hi);
39d5492a
PM
431 tcg_temp_free_i32(lo);
432 tcg_temp_free_i32(hi);
831d7fe8
RH
433
434 return ret;
5e3f878a
PB
435}
436
39d5492a 437static TCGv_i64 gen_muls_i64_i32(TCGv_i32 a, TCGv_i32 b)
5e3f878a 438{
39d5492a
PM
439 TCGv_i32 lo = tcg_temp_new_i32();
440 TCGv_i32 hi = tcg_temp_new_i32();
831d7fe8 441 TCGv_i64 ret;
5e3f878a 442
831d7fe8 443 tcg_gen_muls2_i32(lo, hi, a, b);
7d1b0095 444 tcg_temp_free_i32(a);
7d1b0095 445 tcg_temp_free_i32(b);
831d7fe8
RH
446
447 ret = tcg_temp_new_i64();
448 tcg_gen_concat_i32_i64(ret, lo, hi);
39d5492a
PM
449 tcg_temp_free_i32(lo);
450 tcg_temp_free_i32(hi);
831d7fe8
RH
451
452 return ret;
5e3f878a
PB
453}
454
8f01245e 455/* Swap low and high halfwords. */
39d5492a 456static void gen_swap_half(TCGv_i32 var)
8f01245e 457{
39d5492a 458 TCGv_i32 tmp = tcg_temp_new_i32();
8f01245e
PB
459 tcg_gen_shri_i32(tmp, var, 16);
460 tcg_gen_shli_i32(var, var, 16);
461 tcg_gen_or_i32(var, var, tmp);
7d1b0095 462 tcg_temp_free_i32(tmp);
8f01245e
PB
463}
464
b26eefb6
PB
465/* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
466 tmp = (t0 ^ t1) & 0x8000;
467 t0 &= ~0x8000;
468 t1 &= ~0x8000;
469 t0 = (t0 + t1) ^ tmp;
470 */
471
39d5492a 472static void gen_add16(TCGv_i32 t0, TCGv_i32 t1)
b26eefb6 473{
39d5492a 474 TCGv_i32 tmp = tcg_temp_new_i32();
b26eefb6
PB
475 tcg_gen_xor_i32(tmp, t0, t1);
476 tcg_gen_andi_i32(tmp, tmp, 0x8000);
477 tcg_gen_andi_i32(t0, t0, ~0x8000);
478 tcg_gen_andi_i32(t1, t1, ~0x8000);
479 tcg_gen_add_i32(t0, t0, t1);
480 tcg_gen_xor_i32(t0, t0, tmp);
7d1b0095
PM
481 tcg_temp_free_i32(tmp);
482 tcg_temp_free_i32(t1);
b26eefb6
PB
483}
484
485/* Set CF to the top bit of var. */
39d5492a 486static void gen_set_CF_bit31(TCGv_i32 var)
b26eefb6 487{
66c374de 488 tcg_gen_shri_i32(cpu_CF, var, 31);
b26eefb6
PB
489}
490
491/* Set N and Z flags from var. */
39d5492a 492static inline void gen_logic_CC(TCGv_i32 var)
b26eefb6 493{
66c374de
AJ
494 tcg_gen_mov_i32(cpu_NF, var);
495 tcg_gen_mov_i32(cpu_ZF, var);
b26eefb6
PB
496}
497
498/* T0 += T1 + CF. */
39d5492a 499static void gen_adc(TCGv_i32 t0, TCGv_i32 t1)
b26eefb6 500{
396e467c 501 tcg_gen_add_i32(t0, t0, t1);
66c374de 502 tcg_gen_add_i32(t0, t0, cpu_CF);
b26eefb6
PB
503}
504
e9bb4aa9 505/* dest = T0 + T1 + CF. */
39d5492a 506static void gen_add_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
e9bb4aa9 507{
e9bb4aa9 508 tcg_gen_add_i32(dest, t0, t1);
66c374de 509 tcg_gen_add_i32(dest, dest, cpu_CF);
e9bb4aa9
JR
510}
511
3670669c 512/* dest = T0 - T1 + CF - 1. */
39d5492a 513static void gen_sub_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
3670669c 514{
3670669c 515 tcg_gen_sub_i32(dest, t0, t1);
66c374de 516 tcg_gen_add_i32(dest, dest, cpu_CF);
3670669c 517 tcg_gen_subi_i32(dest, dest, 1);
3670669c
PB
518}
519
72485ec4 520/* dest = T0 + T1. Compute C, N, V and Z flags */
39d5492a 521static void gen_add_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
72485ec4 522{
39d5492a 523 TCGv_i32 tmp = tcg_temp_new_i32();
e3482cb8
RH
524 tcg_gen_movi_i32(tmp, 0);
525 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, t1, tmp);
72485ec4 526 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
72485ec4 527 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
72485ec4
AJ
528 tcg_gen_xor_i32(tmp, t0, t1);
529 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
530 tcg_temp_free_i32(tmp);
531 tcg_gen_mov_i32(dest, cpu_NF);
532}
533
49b4c31e 534/* dest = T0 + T1 + CF. Compute C, N, V and Z flags */
39d5492a 535static void gen_adc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
49b4c31e 536{
39d5492a 537 TCGv_i32 tmp = tcg_temp_new_i32();
49b4c31e
RH
538 if (TCG_TARGET_HAS_add2_i32) {
539 tcg_gen_movi_i32(tmp, 0);
540 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp);
8c3ac601 541 tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1, tmp);
49b4c31e
RH
542 } else {
543 TCGv_i64 q0 = tcg_temp_new_i64();
544 TCGv_i64 q1 = tcg_temp_new_i64();
545 tcg_gen_extu_i32_i64(q0, t0);
546 tcg_gen_extu_i32_i64(q1, t1);
547 tcg_gen_add_i64(q0, q0, q1);
548 tcg_gen_extu_i32_i64(q1, cpu_CF);
549 tcg_gen_add_i64(q0, q0, q1);
550 tcg_gen_extr_i64_i32(cpu_NF, cpu_CF, q0);
551 tcg_temp_free_i64(q0);
552 tcg_temp_free_i64(q1);
553 }
554 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
555 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
556 tcg_gen_xor_i32(tmp, t0, t1);
557 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
558 tcg_temp_free_i32(tmp);
559 tcg_gen_mov_i32(dest, cpu_NF);
560}
561
72485ec4 562/* dest = T0 - T1. Compute C, N, V and Z flags */
39d5492a 563static void gen_sub_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
72485ec4 564{
39d5492a 565 TCGv_i32 tmp;
72485ec4
AJ
566 tcg_gen_sub_i32(cpu_NF, t0, t1);
567 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
568 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0, t1);
569 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
570 tmp = tcg_temp_new_i32();
571 tcg_gen_xor_i32(tmp, t0, t1);
572 tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
573 tcg_temp_free_i32(tmp);
574 tcg_gen_mov_i32(dest, cpu_NF);
575}
576
e77f0832 577/* dest = T0 + ~T1 + CF. Compute C, N, V and Z flags */
39d5492a 578static void gen_sbc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
2de68a49 579{
39d5492a 580 TCGv_i32 tmp = tcg_temp_new_i32();
e77f0832
RH
581 tcg_gen_not_i32(tmp, t1);
582 gen_adc_CC(dest, t0, tmp);
39d5492a 583 tcg_temp_free_i32(tmp);
2de68a49
RH
584}
585
365af80e 586#define GEN_SHIFT(name) \
39d5492a 587static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \
365af80e 588{ \
39d5492a 589 TCGv_i32 tmp1, tmp2, tmp3; \
365af80e
AJ
590 tmp1 = tcg_temp_new_i32(); \
591 tcg_gen_andi_i32(tmp1, t1, 0xff); \
592 tmp2 = tcg_const_i32(0); \
593 tmp3 = tcg_const_i32(0x1f); \
594 tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
595 tcg_temp_free_i32(tmp3); \
596 tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
597 tcg_gen_##name##_i32(dest, tmp2, tmp1); \
598 tcg_temp_free_i32(tmp2); \
599 tcg_temp_free_i32(tmp1); \
600}
601GEN_SHIFT(shl)
602GEN_SHIFT(shr)
603#undef GEN_SHIFT
604
39d5492a 605static void gen_sar(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
365af80e 606{
39d5492a 607 TCGv_i32 tmp1, tmp2;
365af80e
AJ
608 tmp1 = tcg_temp_new_i32();
609 tcg_gen_andi_i32(tmp1, t1, 0xff);
610 tmp2 = tcg_const_i32(0x1f);
611 tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1);
612 tcg_temp_free_i32(tmp2);
613 tcg_gen_sar_i32(dest, t0, tmp1);
614 tcg_temp_free_i32(tmp1);
615}
616
39d5492a 617static void tcg_gen_abs_i32(TCGv_i32 dest, TCGv_i32 src)
36c91fd1 618{
39d5492a
PM
619 TCGv_i32 c0 = tcg_const_i32(0);
620 TCGv_i32 tmp = tcg_temp_new_i32();
36c91fd1
PM
621 tcg_gen_neg_i32(tmp, src);
622 tcg_gen_movcond_i32(TCG_COND_GT, dest, src, c0, src, tmp);
623 tcg_temp_free_i32(c0);
624 tcg_temp_free_i32(tmp);
625}
ad69471c 626
39d5492a 627static void shifter_out_im(TCGv_i32 var, int shift)
b26eefb6 628{
9a119ff6 629 if (shift == 0) {
66c374de 630 tcg_gen_andi_i32(cpu_CF, var, 1);
b26eefb6 631 } else {
66c374de
AJ
632 tcg_gen_shri_i32(cpu_CF, var, shift);
633 if (shift != 31) {
634 tcg_gen_andi_i32(cpu_CF, cpu_CF, 1);
635 }
9a119ff6 636 }
9a119ff6 637}
b26eefb6 638
9a119ff6 639/* Shift by immediate. Includes special handling for shift == 0. */
39d5492a
PM
640static inline void gen_arm_shift_im(TCGv_i32 var, int shiftop,
641 int shift, int flags)
9a119ff6
PB
642{
643 switch (shiftop) {
644 case 0: /* LSL */
645 if (shift != 0) {
646 if (flags)
647 shifter_out_im(var, 32 - shift);
648 tcg_gen_shli_i32(var, var, shift);
649 }
650 break;
651 case 1: /* LSR */
652 if (shift == 0) {
653 if (flags) {
66c374de 654 tcg_gen_shri_i32(cpu_CF, var, 31);
9a119ff6
PB
655 }
656 tcg_gen_movi_i32(var, 0);
657 } else {
658 if (flags)
659 shifter_out_im(var, shift - 1);
660 tcg_gen_shri_i32(var, var, shift);
661 }
662 break;
663 case 2: /* ASR */
664 if (shift == 0)
665 shift = 32;
666 if (flags)
667 shifter_out_im(var, shift - 1);
668 if (shift == 32)
669 shift = 31;
670 tcg_gen_sari_i32(var, var, shift);
671 break;
672 case 3: /* ROR/RRX */
673 if (shift != 0) {
674 if (flags)
675 shifter_out_im(var, shift - 1);
f669df27 676 tcg_gen_rotri_i32(var, var, shift); break;
9a119ff6 677 } else {
39d5492a 678 TCGv_i32 tmp = tcg_temp_new_i32();
b6348f29 679 tcg_gen_shli_i32(tmp, cpu_CF, 31);
9a119ff6
PB
680 if (flags)
681 shifter_out_im(var, 0);
682 tcg_gen_shri_i32(var, var, 1);
b26eefb6 683 tcg_gen_or_i32(var, var, tmp);
7d1b0095 684 tcg_temp_free_i32(tmp);
b26eefb6
PB
685 }
686 }
687};
688
39d5492a
PM
689static inline void gen_arm_shift_reg(TCGv_i32 var, int shiftop,
690 TCGv_i32 shift, int flags)
8984bd2e
PB
691{
692 if (flags) {
693 switch (shiftop) {
9ef39277
BS
694 case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break;
695 case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break;
696 case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break;
697 case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break;
8984bd2e
PB
698 }
699 } else {
700 switch (shiftop) {
365af80e
AJ
701 case 0:
702 gen_shl(var, var, shift);
703 break;
704 case 1:
705 gen_shr(var, var, shift);
706 break;
707 case 2:
708 gen_sar(var, var, shift);
709 break;
f669df27
AJ
710 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
711 tcg_gen_rotr_i32(var, var, shift); break;
8984bd2e
PB
712 }
713 }
7d1b0095 714 tcg_temp_free_i32(shift);
8984bd2e
PB
715}
716
6ddbc6e4
PB
717#define PAS_OP(pfx) \
718 switch (op2) { \
719 case 0: gen_pas_helper(glue(pfx,add16)); break; \
720 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
721 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
722 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
723 case 4: gen_pas_helper(glue(pfx,add8)); break; \
724 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
725 }
39d5492a 726static void gen_arm_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
6ddbc6e4 727{
a7812ae4 728 TCGv_ptr tmp;
6ddbc6e4
PB
729
730 switch (op1) {
731#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
732 case 1:
a7812ae4 733 tmp = tcg_temp_new_ptr();
0ecb72a5 734 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 735 PAS_OP(s)
b75263d6 736 tcg_temp_free_ptr(tmp);
6ddbc6e4
PB
737 break;
738 case 5:
a7812ae4 739 tmp = tcg_temp_new_ptr();
0ecb72a5 740 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 741 PAS_OP(u)
b75263d6 742 tcg_temp_free_ptr(tmp);
6ddbc6e4
PB
743 break;
744#undef gen_pas_helper
745#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
746 case 2:
747 PAS_OP(q);
748 break;
749 case 3:
750 PAS_OP(sh);
751 break;
752 case 6:
753 PAS_OP(uq);
754 break;
755 case 7:
756 PAS_OP(uh);
757 break;
758#undef gen_pas_helper
759 }
760}
9ee6e8bb
PB
761#undef PAS_OP
762
6ddbc6e4
PB
763/* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
764#define PAS_OP(pfx) \
ed89a2f1 765 switch (op1) { \
6ddbc6e4
PB
766 case 0: gen_pas_helper(glue(pfx,add8)); break; \
767 case 1: gen_pas_helper(glue(pfx,add16)); break; \
768 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
769 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
770 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
771 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
772 }
39d5492a 773static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
6ddbc6e4 774{
a7812ae4 775 TCGv_ptr tmp;
6ddbc6e4 776
ed89a2f1 777 switch (op2) {
6ddbc6e4
PB
778#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
779 case 0:
a7812ae4 780 tmp = tcg_temp_new_ptr();
0ecb72a5 781 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 782 PAS_OP(s)
b75263d6 783 tcg_temp_free_ptr(tmp);
6ddbc6e4
PB
784 break;
785 case 4:
a7812ae4 786 tmp = tcg_temp_new_ptr();
0ecb72a5 787 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 788 PAS_OP(u)
b75263d6 789 tcg_temp_free_ptr(tmp);
6ddbc6e4
PB
790 break;
791#undef gen_pas_helper
792#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
793 case 1:
794 PAS_OP(q);
795 break;
796 case 2:
797 PAS_OP(sh);
798 break;
799 case 5:
800 PAS_OP(uq);
801 break;
802 case 6:
803 PAS_OP(uh);
804 break;
805#undef gen_pas_helper
806 }
807}
9ee6e8bb
PB
808#undef PAS_OP
809
39fb730a 810/*
6c2c63d3 811 * Generate a conditional based on ARM condition code cc.
39fb730a
AG
812 * This is common between ARM and Aarch64 targets.
813 */
6c2c63d3 814void arm_test_cc(DisasCompare *cmp, int cc)
d9ba4830 815{
6c2c63d3
RH
816 TCGv_i32 value;
817 TCGCond cond;
818 bool global = true;
d9ba4830 819
d9ba4830
PB
820 switch (cc) {
821 case 0: /* eq: Z */
d9ba4830 822 case 1: /* ne: !Z */
6c2c63d3
RH
823 cond = TCG_COND_EQ;
824 value = cpu_ZF;
d9ba4830 825 break;
6c2c63d3 826
d9ba4830 827 case 2: /* cs: C */
d9ba4830 828 case 3: /* cc: !C */
6c2c63d3
RH
829 cond = TCG_COND_NE;
830 value = cpu_CF;
d9ba4830 831 break;
6c2c63d3 832
d9ba4830 833 case 4: /* mi: N */
d9ba4830 834 case 5: /* pl: !N */
6c2c63d3
RH
835 cond = TCG_COND_LT;
836 value = cpu_NF;
d9ba4830 837 break;
6c2c63d3 838
d9ba4830 839 case 6: /* vs: V */
d9ba4830 840 case 7: /* vc: !V */
6c2c63d3
RH
841 cond = TCG_COND_LT;
842 value = cpu_VF;
d9ba4830 843 break;
6c2c63d3 844
d9ba4830 845 case 8: /* hi: C && !Z */
6c2c63d3
RH
846 case 9: /* ls: !C || Z -> !(C && !Z) */
847 cond = TCG_COND_NE;
848 value = tcg_temp_new_i32();
849 global = false;
850 /* CF is 1 for C, so -CF is an all-bits-set mask for C;
851 ZF is non-zero for !Z; so AND the two subexpressions. */
852 tcg_gen_neg_i32(value, cpu_CF);
853 tcg_gen_and_i32(value, value, cpu_ZF);
d9ba4830 854 break;
6c2c63d3 855
d9ba4830 856 case 10: /* ge: N == V -> N ^ V == 0 */
d9ba4830 857 case 11: /* lt: N != V -> N ^ V != 0 */
6c2c63d3
RH
858 /* Since we're only interested in the sign bit, == 0 is >= 0. */
859 cond = TCG_COND_GE;
860 value = tcg_temp_new_i32();
861 global = false;
862 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
d9ba4830 863 break;
6c2c63d3 864
d9ba4830 865 case 12: /* gt: !Z && N == V */
d9ba4830 866 case 13: /* le: Z || N != V */
6c2c63d3
RH
867 cond = TCG_COND_NE;
868 value = tcg_temp_new_i32();
869 global = false;
870 /* (N == V) is equal to the sign bit of ~(NF ^ VF). Propagate
871 * the sign bit then AND with ZF to yield the result. */
872 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
873 tcg_gen_sari_i32(value, value, 31);
874 tcg_gen_andc_i32(value, cpu_ZF, value);
d9ba4830 875 break;
6c2c63d3 876
9305eac0
RH
877 case 14: /* always */
878 case 15: /* always */
879 /* Use the ALWAYS condition, which will fold early.
880 * It doesn't matter what we use for the value. */
881 cond = TCG_COND_ALWAYS;
882 value = cpu_ZF;
883 goto no_invert;
884
d9ba4830
PB
885 default:
886 fprintf(stderr, "Bad condition code 0x%x\n", cc);
887 abort();
888 }
6c2c63d3
RH
889
890 if (cc & 1) {
891 cond = tcg_invert_cond(cond);
892 }
893
9305eac0 894 no_invert:
6c2c63d3
RH
895 cmp->cond = cond;
896 cmp->value = value;
897 cmp->value_global = global;
898}
899
900void arm_free_cc(DisasCompare *cmp)
901{
902 if (!cmp->value_global) {
903 tcg_temp_free_i32(cmp->value);
904 }
905}
906
907void arm_jump_cc(DisasCompare *cmp, TCGLabel *label)
908{
909 tcg_gen_brcondi_i32(cmp->cond, cmp->value, 0, label);
910}
911
912void arm_gen_test_cc(int cc, TCGLabel *label)
913{
914 DisasCompare cmp;
915 arm_test_cc(&cmp, cc);
916 arm_jump_cc(&cmp, label);
917 arm_free_cc(&cmp);
d9ba4830 918}
2c0262af 919
b1d8e52e 920static const uint8_t table_logic_cc[16] = {
2c0262af
FB
921 1, /* and */
922 1, /* xor */
923 0, /* sub */
924 0, /* rsb */
925 0, /* add */
926 0, /* adc */
927 0, /* sbc */
928 0, /* rsc */
929 1, /* andl */
930 1, /* xorl */
931 0, /* cmp */
932 0, /* cmn */
933 1, /* orr */
934 1, /* mov */
935 1, /* bic */
936 1, /* mvn */
937};
3b46e624 938
4d5e8c96
PM
939static inline void gen_set_condexec(DisasContext *s)
940{
941 if (s->condexec_mask) {
942 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
943 TCGv_i32 tmp = tcg_temp_new_i32();
944 tcg_gen_movi_i32(tmp, val);
945 store_cpu_field(tmp, condexec_bits);
946 }
947}
948
949static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
950{
951 tcg_gen_movi_i32(cpu_R[15], val);
952}
953
d9ba4830
PB
954/* Set PC and Thumb state from an immediate address. */
955static inline void gen_bx_im(DisasContext *s, uint32_t addr)
99c475ab 956{
39d5492a 957 TCGv_i32 tmp;
99c475ab 958
dcba3a8d 959 s->base.is_jmp = DISAS_JUMP;
d9ba4830 960 if (s->thumb != (addr & 1)) {
7d1b0095 961 tmp = tcg_temp_new_i32();
d9ba4830 962 tcg_gen_movi_i32(tmp, addr & 1);
0ecb72a5 963 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, thumb));
7d1b0095 964 tcg_temp_free_i32(tmp);
d9ba4830 965 }
155c3eac 966 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
d9ba4830
PB
967}
968
969/* Set PC and Thumb state from var. var is marked as dead. */
39d5492a 970static inline void gen_bx(DisasContext *s, TCGv_i32 var)
d9ba4830 971{
dcba3a8d 972 s->base.is_jmp = DISAS_JUMP;
155c3eac
FN
973 tcg_gen_andi_i32(cpu_R[15], var, ~1);
974 tcg_gen_andi_i32(var, var, 1);
975 store_cpu_field(var, thumb);
d9ba4830
PB
976}
977
3bb8a96f
PM
978/* Set PC and Thumb state from var. var is marked as dead.
979 * For M-profile CPUs, include logic to detect exception-return
980 * branches and handle them. This is needed for Thumb POP/LDM to PC, LDR to PC,
981 * and BX reg, and no others, and happens only for code in Handler mode.
982 */
983static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var)
984{
985 /* Generate the same code here as for a simple bx, but flag via
dcba3a8d 986 * s->base.is_jmp that we need to do the rest of the work later.
3bb8a96f
PM
987 */
988 gen_bx(s, var);
d02a8698
PM
989 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY) ||
990 (s->v7m_handler_mode && arm_dc_feature(s, ARM_FEATURE_M))) {
dcba3a8d 991 s->base.is_jmp = DISAS_BX_EXCRET;
3bb8a96f
PM
992 }
993}
994
995static inline void gen_bx_excret_final_code(DisasContext *s)
996{
997 /* Generate the code to finish possible exception return and end the TB */
998 TCGLabel *excret_label = gen_new_label();
d02a8698
PM
999 uint32_t min_magic;
1000
1001 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY)) {
1002 /* Covers FNC_RETURN and EXC_RETURN magic */
1003 min_magic = FNC_RETURN_MIN_MAGIC;
1004 } else {
1005 /* EXC_RETURN magic only */
1006 min_magic = EXC_RETURN_MIN_MAGIC;
1007 }
3bb8a96f
PM
1008
1009 /* Is the new PC value in the magic range indicating exception return? */
d02a8698 1010 tcg_gen_brcondi_i32(TCG_COND_GEU, cpu_R[15], min_magic, excret_label);
3bb8a96f
PM
1011 /* No: end the TB as we would for a DISAS_JMP */
1012 if (is_singlestepping(s)) {
1013 gen_singlestep_exception(s);
1014 } else {
07ea28b4 1015 tcg_gen_exit_tb(NULL, 0);
3bb8a96f
PM
1016 }
1017 gen_set_label(excret_label);
1018 /* Yes: this is an exception return.
1019 * At this point in runtime env->regs[15] and env->thumb will hold
1020 * the exception-return magic number, which do_v7m_exception_exit()
1021 * will read. Nothing else will be able to see those values because
1022 * the cpu-exec main loop guarantees that we will always go straight
1023 * from raising the exception to the exception-handling code.
1024 *
1025 * gen_ss_advance(s) does nothing on M profile currently but
1026 * calling it is conceptually the right thing as we have executed
1027 * this instruction (compare SWI, HVC, SMC handling).
1028 */
1029 gen_ss_advance(s);
1030 gen_exception_internal(EXCP_EXCEPTION_EXIT);
1031}
1032
fb602cb7
PM
1033static inline void gen_bxns(DisasContext *s, int rm)
1034{
1035 TCGv_i32 var = load_reg(s, rm);
1036
1037 /* The bxns helper may raise an EXCEPTION_EXIT exception, so in theory
1038 * we need to sync state before calling it, but:
1039 * - we don't need to do gen_set_pc_im() because the bxns helper will
1040 * always set the PC itself
1041 * - we don't need to do gen_set_condexec() because BXNS is UNPREDICTABLE
1042 * unless it's outside an IT block or the last insn in an IT block,
1043 * so we know that condexec == 0 (already set at the top of the TB)
1044 * is correct in the non-UNPREDICTABLE cases, and we can choose
1045 * "zeroes the IT bits" as our UNPREDICTABLE behaviour otherwise.
1046 */
1047 gen_helper_v7m_bxns(cpu_env, var);
1048 tcg_temp_free_i32(var);
ef475b5d 1049 s->base.is_jmp = DISAS_EXIT;
fb602cb7
PM
1050}
1051
3e3fa230
PM
1052static inline void gen_blxns(DisasContext *s, int rm)
1053{
1054 TCGv_i32 var = load_reg(s, rm);
1055
1056 /* We don't need to sync condexec state, for the same reason as bxns.
1057 * We do however need to set the PC, because the blxns helper reads it.
1058 * The blxns helper may throw an exception.
1059 */
1060 gen_set_pc_im(s, s->pc);
1061 gen_helper_v7m_blxns(cpu_env, var);
1062 tcg_temp_free_i32(var);
1063 s->base.is_jmp = DISAS_EXIT;
1064}
1065
21aeb343
JR
1066/* Variant of store_reg which uses branch&exchange logic when storing
1067 to r15 in ARM architecture v7 and above. The source must be a temporary
1068 and will be marked as dead. */
7dcc1f89 1069static inline void store_reg_bx(DisasContext *s, int reg, TCGv_i32 var)
21aeb343
JR
1070{
1071 if (reg == 15 && ENABLE_ARCH_7) {
1072 gen_bx(s, var);
1073 } else {
1074 store_reg(s, reg, var);
1075 }
1076}
1077
be5e7a76
DES
1078/* Variant of store_reg which uses branch&exchange logic when storing
1079 * to r15 in ARM architecture v5T and above. This is used for storing
1080 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
1081 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
7dcc1f89 1082static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
be5e7a76
DES
1083{
1084 if (reg == 15 && ENABLE_ARCH_5) {
3bb8a96f 1085 gen_bx_excret(s, var);
be5e7a76
DES
1086 } else {
1087 store_reg(s, reg, var);
1088 }
1089}
1090
e334bd31
PB
1091#ifdef CONFIG_USER_ONLY
1092#define IS_USER_ONLY 1
1093#else
1094#define IS_USER_ONLY 0
1095#endif
1096
08307563
PM
1097/* Abstractions of "generate code to do a guest load/store for
1098 * AArch32", where a vaddr is always 32 bits (and is zero
1099 * extended if we're a 64 bit core) and data is also
1100 * 32 bits unless specifically doing a 64 bit access.
1101 * These functions work like tcg_gen_qemu_{ld,st}* except
09f78135 1102 * that the address argument is TCGv_i32 rather than TCGv.
08307563 1103 */
08307563 1104
7f5616f5 1105static inline TCGv gen_aa32_addr(DisasContext *s, TCGv_i32 a32, TCGMemOp op)
08307563 1106{
7f5616f5
RH
1107 TCGv addr = tcg_temp_new();
1108 tcg_gen_extu_i32_tl(addr, a32);
1109
e334bd31 1110 /* Not needed for user-mode BE32, where we use MO_BE instead. */
7f5616f5
RH
1111 if (!IS_USER_ONLY && s->sctlr_b && (op & MO_SIZE) < MO_32) {
1112 tcg_gen_xori_tl(addr, addr, 4 - (1 << (op & MO_SIZE)));
e334bd31 1113 }
7f5616f5 1114 return addr;
08307563
PM
1115}
1116
7f5616f5
RH
1117static void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
1118 int index, TCGMemOp opc)
08307563 1119{
2aeba0d0
JS
1120 TCGv addr;
1121
1122 if (arm_dc_feature(s, ARM_FEATURE_M) &&
1123 !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
1124 opc |= MO_ALIGN;
1125 }
1126
1127 addr = gen_aa32_addr(s, a32, opc);
7f5616f5
RH
1128 tcg_gen_qemu_ld_i32(val, addr, index, opc);
1129 tcg_temp_free(addr);
08307563
PM
1130}
1131
7f5616f5
RH
1132static void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
1133 int index, TCGMemOp opc)
1134{
2aeba0d0
JS
1135 TCGv addr;
1136
1137 if (arm_dc_feature(s, ARM_FEATURE_M) &&
1138 !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
1139 opc |= MO_ALIGN;
1140 }
1141
1142 addr = gen_aa32_addr(s, a32, opc);
7f5616f5
RH
1143 tcg_gen_qemu_st_i32(val, addr, index, opc);
1144 tcg_temp_free(addr);
1145}
08307563 1146
7f5616f5 1147#define DO_GEN_LD(SUFF, OPC) \
12dcc321 1148static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
7f5616f5 1149 TCGv_i32 a32, int index) \
08307563 1150{ \
7f5616f5 1151 gen_aa32_ld_i32(s, val, a32, index, OPC | s->be_data); \
9bb6558a
PM
1152} \
1153static inline void gen_aa32_ld##SUFF##_iss(DisasContext *s, \
1154 TCGv_i32 val, \
1155 TCGv_i32 a32, int index, \
1156 ISSInfo issinfo) \
1157{ \
1158 gen_aa32_ld##SUFF(s, val, a32, index); \
1159 disas_set_da_iss(s, OPC, issinfo); \
08307563
PM
1160}
1161
7f5616f5 1162#define DO_GEN_ST(SUFF, OPC) \
12dcc321 1163static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
7f5616f5 1164 TCGv_i32 a32, int index) \
08307563 1165{ \
7f5616f5 1166 gen_aa32_st_i32(s, val, a32, index, OPC | s->be_data); \
9bb6558a
PM
1167} \
1168static inline void gen_aa32_st##SUFF##_iss(DisasContext *s, \
1169 TCGv_i32 val, \
1170 TCGv_i32 a32, int index, \
1171 ISSInfo issinfo) \
1172{ \
1173 gen_aa32_st##SUFF(s, val, a32, index); \
1174 disas_set_da_iss(s, OPC, issinfo | ISSIsWrite); \
08307563
PM
1175}
1176
7f5616f5 1177static inline void gen_aa32_frob64(DisasContext *s, TCGv_i64 val)
08307563 1178{
e334bd31
PB
1179 /* Not needed for user-mode BE32, where we use MO_BE instead. */
1180 if (!IS_USER_ONLY && s->sctlr_b) {
1181 tcg_gen_rotri_i64(val, val, 32);
1182 }
08307563
PM
1183}
1184
7f5616f5
RH
1185static void gen_aa32_ld_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
1186 int index, TCGMemOp opc)
08307563 1187{
7f5616f5
RH
1188 TCGv addr = gen_aa32_addr(s, a32, opc);
1189 tcg_gen_qemu_ld_i64(val, addr, index, opc);
1190 gen_aa32_frob64(s, val);
1191 tcg_temp_free(addr);
1192}
1193
1194static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
1195 TCGv_i32 a32, int index)
1196{
1197 gen_aa32_ld_i64(s, val, a32, index, MO_Q | s->be_data);
1198}
1199
1200static void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
1201 int index, TCGMemOp opc)
1202{
1203 TCGv addr = gen_aa32_addr(s, a32, opc);
e334bd31
PB
1204
1205 /* Not needed for user-mode BE32, where we use MO_BE instead. */
1206 if (!IS_USER_ONLY && s->sctlr_b) {
7f5616f5 1207 TCGv_i64 tmp = tcg_temp_new_i64();
e334bd31 1208 tcg_gen_rotri_i64(tmp, val, 32);
7f5616f5
RH
1209 tcg_gen_qemu_st_i64(tmp, addr, index, opc);
1210 tcg_temp_free_i64(tmp);
e334bd31 1211 } else {
7f5616f5 1212 tcg_gen_qemu_st_i64(val, addr, index, opc);
e334bd31 1213 }
7f5616f5 1214 tcg_temp_free(addr);
08307563
PM
1215}
1216
7f5616f5
RH
1217static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
1218 TCGv_i32 a32, int index)
1219{
1220 gen_aa32_st_i64(s, val, a32, index, MO_Q | s->be_data);
1221}
08307563 1222
7f5616f5
RH
1223DO_GEN_LD(8s, MO_SB)
1224DO_GEN_LD(8u, MO_UB)
1225DO_GEN_LD(16s, MO_SW)
1226DO_GEN_LD(16u, MO_UW)
1227DO_GEN_LD(32u, MO_UL)
7f5616f5
RH
1228DO_GEN_ST(8, MO_UB)
1229DO_GEN_ST(16, MO_UW)
1230DO_GEN_ST(32, MO_UL)
08307563 1231
37e6456e
PM
1232static inline void gen_hvc(DisasContext *s, int imm16)
1233{
1234 /* The pre HVC helper handles cases when HVC gets trapped
1235 * as an undefined insn by runtime configuration (ie before
1236 * the insn really executes).
1237 */
1238 gen_set_pc_im(s, s->pc - 4);
1239 gen_helper_pre_hvc(cpu_env);
1240 /* Otherwise we will treat this as a real exception which
1241 * happens after execution of the insn. (The distinction matters
1242 * for the PC value reported to the exception handler and also
1243 * for single stepping.)
1244 */
1245 s->svc_imm = imm16;
1246 gen_set_pc_im(s, s->pc);
dcba3a8d 1247 s->base.is_jmp = DISAS_HVC;
37e6456e
PM
1248}
1249
1250static inline void gen_smc(DisasContext *s)
1251{
1252 /* As with HVC, we may take an exception either before or after
1253 * the insn executes.
1254 */
1255 TCGv_i32 tmp;
1256
1257 gen_set_pc_im(s, s->pc - 4);
1258 tmp = tcg_const_i32(syn_aa32_smc());
1259 gen_helper_pre_smc(cpu_env, tmp);
1260 tcg_temp_free_i32(tmp);
1261 gen_set_pc_im(s, s->pc);
dcba3a8d 1262 s->base.is_jmp = DISAS_SMC;
37e6456e
PM
1263}
1264
d4a2dc67
PM
1265static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
1266{
1267 gen_set_condexec(s);
1268 gen_set_pc_im(s, s->pc - offset);
1269 gen_exception_internal(excp);
dcba3a8d 1270 s->base.is_jmp = DISAS_NORETURN;
d4a2dc67
PM
1271}
1272
73710361
GB
1273static void gen_exception_insn(DisasContext *s, int offset, int excp,
1274 int syn, uint32_t target_el)
d4a2dc67
PM
1275{
1276 gen_set_condexec(s);
1277 gen_set_pc_im(s, s->pc - offset);
73710361 1278 gen_exception(excp, syn, target_el);
dcba3a8d 1279 s->base.is_jmp = DISAS_NORETURN;
d4a2dc67
PM
1280}
1281
c900a2e6
PM
1282static void gen_exception_bkpt_insn(DisasContext *s, int offset, uint32_t syn)
1283{
1284 TCGv_i32 tcg_syn;
1285
1286 gen_set_condexec(s);
1287 gen_set_pc_im(s, s->pc - offset);
1288 tcg_syn = tcg_const_i32(syn);
1289 gen_helper_exception_bkpt_insn(cpu_env, tcg_syn);
1290 tcg_temp_free_i32(tcg_syn);
1291 s->base.is_jmp = DISAS_NORETURN;
1292}
1293
b5ff1b31
FB
1294/* Force a TB lookup after an instruction that changes the CPU state. */
1295static inline void gen_lookup_tb(DisasContext *s)
1296{
a6445c52 1297 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
dcba3a8d 1298 s->base.is_jmp = DISAS_EXIT;
b5ff1b31
FB
1299}
1300
19a6e31c
PM
1301static inline void gen_hlt(DisasContext *s, int imm)
1302{
1303 /* HLT. This has two purposes.
1304 * Architecturally, it is an external halting debug instruction.
1305 * Since QEMU doesn't implement external debug, we treat this as
1306 * it is required for halting debug disabled: it will UNDEF.
1307 * Secondly, "HLT 0x3C" is a T32 semihosting trap instruction,
1308 * and "HLT 0xF000" is an A32 semihosting syscall. These traps
1309 * must trigger semihosting even for ARMv7 and earlier, where
1310 * HLT was an undefined encoding.
1311 * In system mode, we don't allow userspace access to
1312 * semihosting, to provide some semblance of security
1313 * (and for consistency with our 32-bit semihosting).
1314 */
1315 if (semihosting_enabled() &&
1316#ifndef CONFIG_USER_ONLY
1317 s->current_el != 0 &&
1318#endif
1319 (imm == (s->thumb ? 0x3c : 0xf000))) {
1320 gen_exception_internal_insn(s, 0, EXCP_SEMIHOST);
1321 return;
1322 }
1323
1324 gen_exception_insn(s, s->thumb ? 2 : 4, EXCP_UDEF, syn_uncategorized(),
1325 default_exception_el(s));
1326}
1327
b0109805 1328static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
39d5492a 1329 TCGv_i32 var)
2c0262af 1330{
1e8d4eec 1331 int val, rm, shift, shiftop;
39d5492a 1332 TCGv_i32 offset;
2c0262af
FB
1333
1334 if (!(insn & (1 << 25))) {
1335 /* immediate */
1336 val = insn & 0xfff;
1337 if (!(insn & (1 << 23)))
1338 val = -val;
537730b9 1339 if (val != 0)
b0109805 1340 tcg_gen_addi_i32(var, var, val);
2c0262af
FB
1341 } else {
1342 /* shift/register */
1343 rm = (insn) & 0xf;
1344 shift = (insn >> 7) & 0x1f;
1e8d4eec 1345 shiftop = (insn >> 5) & 3;
b26eefb6 1346 offset = load_reg(s, rm);
9a119ff6 1347 gen_arm_shift_im(offset, shiftop, shift, 0);
2c0262af 1348 if (!(insn & (1 << 23)))
b0109805 1349 tcg_gen_sub_i32(var, var, offset);
2c0262af 1350 else
b0109805 1351 tcg_gen_add_i32(var, var, offset);
7d1b0095 1352 tcg_temp_free_i32(offset);
2c0262af
FB
1353 }
1354}
1355
191f9a93 1356static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
39d5492a 1357 int extra, TCGv_i32 var)
2c0262af
FB
1358{
1359 int val, rm;
39d5492a 1360 TCGv_i32 offset;
3b46e624 1361
2c0262af
FB
1362 if (insn & (1 << 22)) {
1363 /* immediate */
1364 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
1365 if (!(insn & (1 << 23)))
1366 val = -val;
18acad92 1367 val += extra;
537730b9 1368 if (val != 0)
b0109805 1369 tcg_gen_addi_i32(var, var, val);
2c0262af
FB
1370 } else {
1371 /* register */
191f9a93 1372 if (extra)
b0109805 1373 tcg_gen_addi_i32(var, var, extra);
2c0262af 1374 rm = (insn) & 0xf;
b26eefb6 1375 offset = load_reg(s, rm);
2c0262af 1376 if (!(insn & (1 << 23)))
b0109805 1377 tcg_gen_sub_i32(var, var, offset);
2c0262af 1378 else
b0109805 1379 tcg_gen_add_i32(var, var, offset);
7d1b0095 1380 tcg_temp_free_i32(offset);
2c0262af
FB
1381 }
1382}
1383
5aaebd13
PM
1384static TCGv_ptr get_fpstatus_ptr(int neon)
1385{
1386 TCGv_ptr statusptr = tcg_temp_new_ptr();
1387 int offset;
1388 if (neon) {
0ecb72a5 1389 offset = offsetof(CPUARMState, vfp.standard_fp_status);
5aaebd13 1390 } else {
0ecb72a5 1391 offset = offsetof(CPUARMState, vfp.fp_status);
5aaebd13
PM
1392 }
1393 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
1394 return statusptr;
1395}
1396
4373f3ce
PB
1397#define VFP_OP2(name) \
1398static inline void gen_vfp_##name(int dp) \
1399{ \
ae1857ec
PM
1400 TCGv_ptr fpst = get_fpstatus_ptr(0); \
1401 if (dp) { \
1402 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, fpst); \
1403 } else { \
1404 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, fpst); \
1405 } \
1406 tcg_temp_free_ptr(fpst); \
b7bcbe95
FB
1407}
1408
4373f3ce
PB
1409VFP_OP2(add)
1410VFP_OP2(sub)
1411VFP_OP2(mul)
1412VFP_OP2(div)
1413
1414#undef VFP_OP2
1415
605a6aed
PM
1416static inline void gen_vfp_F1_mul(int dp)
1417{
1418 /* Like gen_vfp_mul() but put result in F1 */
ae1857ec 1419 TCGv_ptr fpst = get_fpstatus_ptr(0);
605a6aed 1420 if (dp) {
ae1857ec 1421 gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, fpst);
605a6aed 1422 } else {
ae1857ec 1423 gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, fpst);
605a6aed 1424 }
ae1857ec 1425 tcg_temp_free_ptr(fpst);
605a6aed
PM
1426}
1427
1428static inline void gen_vfp_F1_neg(int dp)
1429{
1430 /* Like gen_vfp_neg() but put result in F1 */
1431 if (dp) {
1432 gen_helper_vfp_negd(cpu_F1d, cpu_F0d);
1433 } else {
1434 gen_helper_vfp_negs(cpu_F1s, cpu_F0s);
1435 }
1436}
1437
4373f3ce
PB
1438static inline void gen_vfp_abs(int dp)
1439{
1440 if (dp)
1441 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1442 else
1443 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1444}
1445
1446static inline void gen_vfp_neg(int dp)
1447{
1448 if (dp)
1449 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1450 else
1451 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1452}
1453
1454static inline void gen_vfp_sqrt(int dp)
1455{
1456 if (dp)
1457 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1458 else
1459 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1460}
1461
1462static inline void gen_vfp_cmp(int dp)
1463{
1464 if (dp)
1465 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1466 else
1467 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1468}
1469
1470static inline void gen_vfp_cmpe(int dp)
1471{
1472 if (dp)
1473 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1474 else
1475 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1476}
1477
1478static inline void gen_vfp_F1_ld0(int dp)
1479{
1480 if (dp)
5b340b51 1481 tcg_gen_movi_i64(cpu_F1d, 0);
4373f3ce 1482 else
5b340b51 1483 tcg_gen_movi_i32(cpu_F1s, 0);
4373f3ce
PB
1484}
1485
5500b06c
PM
1486#define VFP_GEN_ITOF(name) \
1487static inline void gen_vfp_##name(int dp, int neon) \
1488{ \
5aaebd13 1489 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
5500b06c
PM
1490 if (dp) { \
1491 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
1492 } else { \
1493 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1494 } \
b7fa9214 1495 tcg_temp_free_ptr(statusptr); \
4373f3ce
PB
1496}
1497
5500b06c
PM
1498VFP_GEN_ITOF(uito)
1499VFP_GEN_ITOF(sito)
1500#undef VFP_GEN_ITOF
4373f3ce 1501
5500b06c
PM
1502#define VFP_GEN_FTOI(name) \
1503static inline void gen_vfp_##name(int dp, int neon) \
1504{ \
5aaebd13 1505 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
5500b06c
PM
1506 if (dp) { \
1507 gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
1508 } else { \
1509 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1510 } \
b7fa9214 1511 tcg_temp_free_ptr(statusptr); \
4373f3ce
PB
1512}
1513
5500b06c
PM
1514VFP_GEN_FTOI(toui)
1515VFP_GEN_FTOI(touiz)
1516VFP_GEN_FTOI(tosi)
1517VFP_GEN_FTOI(tosiz)
1518#undef VFP_GEN_FTOI
4373f3ce 1519
16d5b3ca 1520#define VFP_GEN_FIX(name, round) \
5500b06c 1521static inline void gen_vfp_##name(int dp, int shift, int neon) \
4373f3ce 1522{ \
39d5492a 1523 TCGv_i32 tmp_shift = tcg_const_i32(shift); \
5aaebd13 1524 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
5500b06c 1525 if (dp) { \
16d5b3ca
WN
1526 gen_helper_vfp_##name##d##round(cpu_F0d, cpu_F0d, tmp_shift, \
1527 statusptr); \
5500b06c 1528 } else { \
16d5b3ca
WN
1529 gen_helper_vfp_##name##s##round(cpu_F0s, cpu_F0s, tmp_shift, \
1530 statusptr); \
5500b06c 1531 } \
b75263d6 1532 tcg_temp_free_i32(tmp_shift); \
b7fa9214 1533 tcg_temp_free_ptr(statusptr); \
9ee6e8bb 1534}
16d5b3ca
WN
1535VFP_GEN_FIX(tosh, _round_to_zero)
1536VFP_GEN_FIX(tosl, _round_to_zero)
1537VFP_GEN_FIX(touh, _round_to_zero)
1538VFP_GEN_FIX(toul, _round_to_zero)
1539VFP_GEN_FIX(shto, )
1540VFP_GEN_FIX(slto, )
1541VFP_GEN_FIX(uhto, )
1542VFP_GEN_FIX(ulto, )
4373f3ce 1543#undef VFP_GEN_FIX
9ee6e8bb 1544
39d5492a 1545static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr)
b5ff1b31 1546{
08307563 1547 if (dp) {
12dcc321 1548 gen_aa32_ld64(s, cpu_F0d, addr, get_mem_index(s));
08307563 1549 } else {
12dcc321 1550 gen_aa32_ld32u(s, cpu_F0s, addr, get_mem_index(s));
08307563 1551 }
b5ff1b31
FB
1552}
1553
39d5492a 1554static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
b5ff1b31 1555{
08307563 1556 if (dp) {
12dcc321 1557 gen_aa32_st64(s, cpu_F0d, addr, get_mem_index(s));
08307563 1558 } else {
12dcc321 1559 gen_aa32_st32(s, cpu_F0s, addr, get_mem_index(s));
08307563 1560 }
b5ff1b31
FB
1561}
1562
c39c2b90 1563static inline long vfp_reg_offset(bool dp, unsigned reg)
8e96005d 1564{
9a2b5256 1565 if (dp) {
c39c2b90 1566 return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]);
8e96005d 1567 } else {
c39c2b90 1568 long ofs = offsetof(CPUARMState, vfp.zregs[reg >> 2].d[(reg >> 1) & 1]);
9a2b5256
RH
1569 if (reg & 1) {
1570 ofs += offsetof(CPU_DoubleU, l.upper);
1571 } else {
1572 ofs += offsetof(CPU_DoubleU, l.lower);
1573 }
1574 return ofs;
8e96005d
FB
1575 }
1576}
9ee6e8bb
PB
1577
1578/* Return the offset of a 32-bit piece of a NEON register.
1579 zero is the least significant end of the register. */
1580static inline long
1581neon_reg_offset (int reg, int n)
1582{
1583 int sreg;
1584 sreg = reg * 2 + n;
1585 return vfp_reg_offset(0, sreg);
1586}
1587
32f91fb7
RH
1588/* Return the offset of a 2**SIZE piece of a NEON register, at index ELE,
1589 * where 0 is the least significant end of the register.
1590 */
1591static inline long
1592neon_element_offset(int reg, int element, TCGMemOp size)
1593{
1594 int element_size = 1 << size;
1595 int ofs = element * element_size;
1596#ifdef HOST_WORDS_BIGENDIAN
1597 /* Calculate the offset assuming fully little-endian,
1598 * then XOR to account for the order of the 8-byte units.
1599 */
1600 if (element_size < 8) {
1601 ofs ^= 8 - element_size;
1602 }
1603#endif
1604 return neon_reg_offset(reg, 0) + ofs;
1605}
1606
39d5492a 1607static TCGv_i32 neon_load_reg(int reg, int pass)
8f8e3aa4 1608{
39d5492a 1609 TCGv_i32 tmp = tcg_temp_new_i32();
8f8e3aa4
PB
1610 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1611 return tmp;
1612}
1613
ac55d007
RH
1614static void neon_load_element64(TCGv_i64 var, int reg, int ele, TCGMemOp mop)
1615{
1616 long offset = neon_element_offset(reg, ele, mop & MO_SIZE);
1617
1618 switch (mop) {
1619 case MO_UB:
1620 tcg_gen_ld8u_i64(var, cpu_env, offset);
1621 break;
1622 case MO_UW:
1623 tcg_gen_ld16u_i64(var, cpu_env, offset);
1624 break;
1625 case MO_UL:
1626 tcg_gen_ld32u_i64(var, cpu_env, offset);
1627 break;
1628 case MO_Q:
1629 tcg_gen_ld_i64(var, cpu_env, offset);
1630 break;
1631 default:
1632 g_assert_not_reached();
1633 }
1634}
1635
39d5492a 1636static void neon_store_reg(int reg, int pass, TCGv_i32 var)
8f8e3aa4
PB
1637{
1638 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
7d1b0095 1639 tcg_temp_free_i32(var);
8f8e3aa4
PB
1640}
1641
ac55d007
RH
1642static void neon_store_element64(int reg, int ele, TCGMemOp size, TCGv_i64 var)
1643{
1644 long offset = neon_element_offset(reg, ele, size);
1645
1646 switch (size) {
1647 case MO_8:
1648 tcg_gen_st8_i64(var, cpu_env, offset);
1649 break;
1650 case MO_16:
1651 tcg_gen_st16_i64(var, cpu_env, offset);
1652 break;
1653 case MO_32:
1654 tcg_gen_st32_i64(var, cpu_env, offset);
1655 break;
1656 case MO_64:
1657 tcg_gen_st_i64(var, cpu_env, offset);
1658 break;
1659 default:
1660 g_assert_not_reached();
1661 }
1662}
1663
a7812ae4 1664static inline void neon_load_reg64(TCGv_i64 var, int reg)
ad69471c
PB
1665{
1666 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1667}
1668
a7812ae4 1669static inline void neon_store_reg64(TCGv_i64 var, int reg)
ad69471c
PB
1670{
1671 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1672}
1673
1a66ac61
RH
1674static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
1675{
1676 TCGv_ptr ret = tcg_temp_new_ptr();
1677 tcg_gen_addi_ptr(ret, cpu_env, vfp_reg_offset(dp, reg));
1678 return ret;
1679}
1680
4373f3ce
PB
1681#define tcg_gen_ld_f32 tcg_gen_ld_i32
1682#define tcg_gen_ld_f64 tcg_gen_ld_i64
1683#define tcg_gen_st_f32 tcg_gen_st_i32
1684#define tcg_gen_st_f64 tcg_gen_st_i64
1685
b7bcbe95
FB
1686static inline void gen_mov_F0_vreg(int dp, int reg)
1687{
1688 if (dp)
4373f3ce 1689 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95 1690 else
4373f3ce 1691 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95
FB
1692}
1693
1694static inline void gen_mov_F1_vreg(int dp, int reg)
1695{
1696 if (dp)
4373f3ce 1697 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95 1698 else
4373f3ce 1699 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95
FB
1700}
1701
1702static inline void gen_mov_vreg_F0(int dp, int reg)
1703{
1704 if (dp)
4373f3ce 1705 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95 1706 else
4373f3ce 1707 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
b7bcbe95
FB
1708}
1709
d00584b7 1710#define ARM_CP_RW_BIT (1 << 20)
18c9b560 1711
a7812ae4 1712static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
e677137d 1713{
0ecb72a5 1714 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
e677137d
PB
1715}
1716
a7812ae4 1717static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
e677137d 1718{
0ecb72a5 1719 tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
e677137d
PB
1720}
1721
39d5492a 1722static inline TCGv_i32 iwmmxt_load_creg(int reg)
e677137d 1723{
39d5492a 1724 TCGv_i32 var = tcg_temp_new_i32();
0ecb72a5 1725 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
da6b5335 1726 return var;
e677137d
PB
1727}
1728
39d5492a 1729static inline void iwmmxt_store_creg(int reg, TCGv_i32 var)
e677137d 1730{
0ecb72a5 1731 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
7d1b0095 1732 tcg_temp_free_i32(var);
e677137d
PB
1733}
1734
1735static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1736{
1737 iwmmxt_store_reg(cpu_M0, rn);
1738}
1739
1740static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1741{
1742 iwmmxt_load_reg(cpu_M0, rn);
1743}
1744
1745static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1746{
1747 iwmmxt_load_reg(cpu_V1, rn);
1748 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1749}
1750
1751static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1752{
1753 iwmmxt_load_reg(cpu_V1, rn);
1754 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1755}
1756
1757static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1758{
1759 iwmmxt_load_reg(cpu_V1, rn);
1760 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1761}
1762
1763#define IWMMXT_OP(name) \
1764static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1765{ \
1766 iwmmxt_load_reg(cpu_V1, rn); \
1767 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1768}
1769
477955bd
PM
1770#define IWMMXT_OP_ENV(name) \
1771static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1772{ \
1773 iwmmxt_load_reg(cpu_V1, rn); \
1774 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1775}
1776
1777#define IWMMXT_OP_ENV_SIZE(name) \
1778IWMMXT_OP_ENV(name##b) \
1779IWMMXT_OP_ENV(name##w) \
1780IWMMXT_OP_ENV(name##l)
e677137d 1781
477955bd 1782#define IWMMXT_OP_ENV1(name) \
e677137d
PB
1783static inline void gen_op_iwmmxt_##name##_M0(void) \
1784{ \
477955bd 1785 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
e677137d
PB
1786}
1787
1788IWMMXT_OP(maddsq)
1789IWMMXT_OP(madduq)
1790IWMMXT_OP(sadb)
1791IWMMXT_OP(sadw)
1792IWMMXT_OP(mulslw)
1793IWMMXT_OP(mulshw)
1794IWMMXT_OP(mululw)
1795IWMMXT_OP(muluhw)
1796IWMMXT_OP(macsw)
1797IWMMXT_OP(macuw)
1798
477955bd
PM
1799IWMMXT_OP_ENV_SIZE(unpackl)
1800IWMMXT_OP_ENV_SIZE(unpackh)
1801
1802IWMMXT_OP_ENV1(unpacklub)
1803IWMMXT_OP_ENV1(unpackluw)
1804IWMMXT_OP_ENV1(unpacklul)
1805IWMMXT_OP_ENV1(unpackhub)
1806IWMMXT_OP_ENV1(unpackhuw)
1807IWMMXT_OP_ENV1(unpackhul)
1808IWMMXT_OP_ENV1(unpacklsb)
1809IWMMXT_OP_ENV1(unpacklsw)
1810IWMMXT_OP_ENV1(unpacklsl)
1811IWMMXT_OP_ENV1(unpackhsb)
1812IWMMXT_OP_ENV1(unpackhsw)
1813IWMMXT_OP_ENV1(unpackhsl)
1814
1815IWMMXT_OP_ENV_SIZE(cmpeq)
1816IWMMXT_OP_ENV_SIZE(cmpgtu)
1817IWMMXT_OP_ENV_SIZE(cmpgts)
1818
1819IWMMXT_OP_ENV_SIZE(mins)
1820IWMMXT_OP_ENV_SIZE(minu)
1821IWMMXT_OP_ENV_SIZE(maxs)
1822IWMMXT_OP_ENV_SIZE(maxu)
1823
1824IWMMXT_OP_ENV_SIZE(subn)
1825IWMMXT_OP_ENV_SIZE(addn)
1826IWMMXT_OP_ENV_SIZE(subu)
1827IWMMXT_OP_ENV_SIZE(addu)
1828IWMMXT_OP_ENV_SIZE(subs)
1829IWMMXT_OP_ENV_SIZE(adds)
1830
1831IWMMXT_OP_ENV(avgb0)
1832IWMMXT_OP_ENV(avgb1)
1833IWMMXT_OP_ENV(avgw0)
1834IWMMXT_OP_ENV(avgw1)
e677137d 1835
477955bd
PM
1836IWMMXT_OP_ENV(packuw)
1837IWMMXT_OP_ENV(packul)
1838IWMMXT_OP_ENV(packuq)
1839IWMMXT_OP_ENV(packsw)
1840IWMMXT_OP_ENV(packsl)
1841IWMMXT_OP_ENV(packsq)
e677137d 1842
e677137d
PB
1843static void gen_op_iwmmxt_set_mup(void)
1844{
39d5492a 1845 TCGv_i32 tmp;
e677137d
PB
1846 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1847 tcg_gen_ori_i32(tmp, tmp, 2);
1848 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1849}
1850
1851static void gen_op_iwmmxt_set_cup(void)
1852{
39d5492a 1853 TCGv_i32 tmp;
e677137d
PB
1854 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1855 tcg_gen_ori_i32(tmp, tmp, 1);
1856 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1857}
1858
1859static void gen_op_iwmmxt_setpsr_nz(void)
1860{
39d5492a 1861 TCGv_i32 tmp = tcg_temp_new_i32();
e677137d
PB
1862 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1863 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1864}
1865
1866static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1867{
1868 iwmmxt_load_reg(cpu_V1, rn);
86831435 1869 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
e677137d
PB
1870 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1871}
1872
39d5492a
PM
1873static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn,
1874 TCGv_i32 dest)
18c9b560
AZ
1875{
1876 int rd;
1877 uint32_t offset;
39d5492a 1878 TCGv_i32 tmp;
18c9b560
AZ
1879
1880 rd = (insn >> 16) & 0xf;
da6b5335 1881 tmp = load_reg(s, rd);
18c9b560
AZ
1882
1883 offset = (insn & 0xff) << ((insn >> 7) & 2);
1884 if (insn & (1 << 24)) {
1885 /* Pre indexed */
1886 if (insn & (1 << 23))
da6b5335 1887 tcg_gen_addi_i32(tmp, tmp, offset);
18c9b560 1888 else
da6b5335
FN
1889 tcg_gen_addi_i32(tmp, tmp, -offset);
1890 tcg_gen_mov_i32(dest, tmp);
18c9b560 1891 if (insn & (1 << 21))
da6b5335
FN
1892 store_reg(s, rd, tmp);
1893 else
7d1b0095 1894 tcg_temp_free_i32(tmp);
18c9b560
AZ
1895 } else if (insn & (1 << 21)) {
1896 /* Post indexed */
da6b5335 1897 tcg_gen_mov_i32(dest, tmp);
18c9b560 1898 if (insn & (1 << 23))
da6b5335 1899 tcg_gen_addi_i32(tmp, tmp, offset);
18c9b560 1900 else
da6b5335
FN
1901 tcg_gen_addi_i32(tmp, tmp, -offset);
1902 store_reg(s, rd, tmp);
18c9b560
AZ
1903 } else if (!(insn & (1 << 23)))
1904 return 1;
1905 return 0;
1906}
1907
39d5492a 1908static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest)
18c9b560
AZ
1909{
1910 int rd = (insn >> 0) & 0xf;
39d5492a 1911 TCGv_i32 tmp;
18c9b560 1912
da6b5335
FN
1913 if (insn & (1 << 8)) {
1914 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
18c9b560 1915 return 1;
da6b5335
FN
1916 } else {
1917 tmp = iwmmxt_load_creg(rd);
1918 }
1919 } else {
7d1b0095 1920 tmp = tcg_temp_new_i32();
da6b5335 1921 iwmmxt_load_reg(cpu_V0, rd);
ecc7b3aa 1922 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
da6b5335
FN
1923 }
1924 tcg_gen_andi_i32(tmp, tmp, mask);
1925 tcg_gen_mov_i32(dest, tmp);
7d1b0095 1926 tcg_temp_free_i32(tmp);
18c9b560
AZ
1927 return 0;
1928}
1929
a1c7273b 1930/* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
18c9b560 1931 (ie. an undefined instruction). */
7dcc1f89 1932static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
18c9b560
AZ
1933{
1934 int rd, wrd;
1935 int rdhi, rdlo, rd0, rd1, i;
39d5492a
PM
1936 TCGv_i32 addr;
1937 TCGv_i32 tmp, tmp2, tmp3;
18c9b560
AZ
1938
1939 if ((insn & 0x0e000e00) == 0x0c000000) {
1940 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1941 wrd = insn & 0xf;
1942 rdlo = (insn >> 12) & 0xf;
1943 rdhi = (insn >> 16) & 0xf;
d00584b7 1944 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
da6b5335 1945 iwmmxt_load_reg(cpu_V0, wrd);
ecc7b3aa 1946 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
da6b5335 1947 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
ecc7b3aa 1948 tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
d00584b7 1949 } else { /* TMCRR */
da6b5335
FN
1950 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1951 iwmmxt_store_reg(cpu_V0, wrd);
18c9b560
AZ
1952 gen_op_iwmmxt_set_mup();
1953 }
1954 return 0;
1955 }
1956
1957 wrd = (insn >> 12) & 0xf;
7d1b0095 1958 addr = tcg_temp_new_i32();
da6b5335 1959 if (gen_iwmmxt_address(s, insn, addr)) {
7d1b0095 1960 tcg_temp_free_i32(addr);
18c9b560 1961 return 1;
da6b5335 1962 }
18c9b560 1963 if (insn & ARM_CP_RW_BIT) {
d00584b7 1964 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
7d1b0095 1965 tmp = tcg_temp_new_i32();
12dcc321 1966 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
da6b5335 1967 iwmmxt_store_creg(wrd, tmp);
18c9b560 1968 } else {
e677137d
PB
1969 i = 1;
1970 if (insn & (1 << 8)) {
d00584b7 1971 if (insn & (1 << 22)) { /* WLDRD */
12dcc321 1972 gen_aa32_ld64(s, cpu_M0, addr, get_mem_index(s));
e677137d 1973 i = 0;
d00584b7 1974 } else { /* WLDRW wRd */
29531141 1975 tmp = tcg_temp_new_i32();
12dcc321 1976 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
e677137d
PB
1977 }
1978 } else {
29531141 1979 tmp = tcg_temp_new_i32();
d00584b7 1980 if (insn & (1 << 22)) { /* WLDRH */
12dcc321 1981 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
d00584b7 1982 } else { /* WLDRB */
12dcc321 1983 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
e677137d
PB
1984 }
1985 }
1986 if (i) {
1987 tcg_gen_extu_i32_i64(cpu_M0, tmp);
7d1b0095 1988 tcg_temp_free_i32(tmp);
e677137d 1989 }
18c9b560
AZ
1990 gen_op_iwmmxt_movq_wRn_M0(wrd);
1991 }
1992 } else {
d00584b7 1993 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
da6b5335 1994 tmp = iwmmxt_load_creg(wrd);
12dcc321 1995 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
18c9b560
AZ
1996 } else {
1997 gen_op_iwmmxt_movq_M0_wRn(wrd);
7d1b0095 1998 tmp = tcg_temp_new_i32();
e677137d 1999 if (insn & (1 << 8)) {
d00584b7 2000 if (insn & (1 << 22)) { /* WSTRD */
12dcc321 2001 gen_aa32_st64(s, cpu_M0, addr, get_mem_index(s));
d00584b7 2002 } else { /* WSTRW wRd */
ecc7b3aa 2003 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
12dcc321 2004 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
e677137d
PB
2005 }
2006 } else {
d00584b7 2007 if (insn & (1 << 22)) { /* WSTRH */
ecc7b3aa 2008 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
12dcc321 2009 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
d00584b7 2010 } else { /* WSTRB */
ecc7b3aa 2011 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
12dcc321 2012 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
e677137d
PB
2013 }
2014 }
18c9b560 2015 }
29531141 2016 tcg_temp_free_i32(tmp);
18c9b560 2017 }
7d1b0095 2018 tcg_temp_free_i32(addr);
18c9b560
AZ
2019 return 0;
2020 }
2021
2022 if ((insn & 0x0f000000) != 0x0e000000)
2023 return 1;
2024
2025 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
d00584b7 2026 case 0x000: /* WOR */
18c9b560
AZ
2027 wrd = (insn >> 12) & 0xf;
2028 rd0 = (insn >> 0) & 0xf;
2029 rd1 = (insn >> 16) & 0xf;
2030 gen_op_iwmmxt_movq_M0_wRn(rd0);
2031 gen_op_iwmmxt_orq_M0_wRn(rd1);
2032 gen_op_iwmmxt_setpsr_nz();
2033 gen_op_iwmmxt_movq_wRn_M0(wrd);
2034 gen_op_iwmmxt_set_mup();
2035 gen_op_iwmmxt_set_cup();
2036 break;
d00584b7 2037 case 0x011: /* TMCR */
18c9b560
AZ
2038 if (insn & 0xf)
2039 return 1;
2040 rd = (insn >> 12) & 0xf;
2041 wrd = (insn >> 16) & 0xf;
2042 switch (wrd) {
2043 case ARM_IWMMXT_wCID:
2044 case ARM_IWMMXT_wCASF:
2045 break;
2046 case ARM_IWMMXT_wCon:
2047 gen_op_iwmmxt_set_cup();
2048 /* Fall through. */
2049 case ARM_IWMMXT_wCSSF:
da6b5335
FN
2050 tmp = iwmmxt_load_creg(wrd);
2051 tmp2 = load_reg(s, rd);
f669df27 2052 tcg_gen_andc_i32(tmp, tmp, tmp2);
7d1b0095 2053 tcg_temp_free_i32(tmp2);
da6b5335 2054 iwmmxt_store_creg(wrd, tmp);
18c9b560
AZ
2055 break;
2056 case ARM_IWMMXT_wCGR0:
2057 case ARM_IWMMXT_wCGR1:
2058 case ARM_IWMMXT_wCGR2:
2059 case ARM_IWMMXT_wCGR3:
2060 gen_op_iwmmxt_set_cup();
da6b5335
FN
2061 tmp = load_reg(s, rd);
2062 iwmmxt_store_creg(wrd, tmp);
18c9b560
AZ
2063 break;
2064 default:
2065 return 1;
2066 }
2067 break;
d00584b7 2068 case 0x100: /* WXOR */
18c9b560
AZ
2069 wrd = (insn >> 12) & 0xf;
2070 rd0 = (insn >> 0) & 0xf;
2071 rd1 = (insn >> 16) & 0xf;
2072 gen_op_iwmmxt_movq_M0_wRn(rd0);
2073 gen_op_iwmmxt_xorq_M0_wRn(rd1);
2074 gen_op_iwmmxt_setpsr_nz();
2075 gen_op_iwmmxt_movq_wRn_M0(wrd);
2076 gen_op_iwmmxt_set_mup();
2077 gen_op_iwmmxt_set_cup();
2078 break;
d00584b7 2079 case 0x111: /* TMRC */
18c9b560
AZ
2080 if (insn & 0xf)
2081 return 1;
2082 rd = (insn >> 12) & 0xf;
2083 wrd = (insn >> 16) & 0xf;
da6b5335
FN
2084 tmp = iwmmxt_load_creg(wrd);
2085 store_reg(s, rd, tmp);
18c9b560 2086 break;
d00584b7 2087 case 0x300: /* WANDN */
18c9b560
AZ
2088 wrd = (insn >> 12) & 0xf;
2089 rd0 = (insn >> 0) & 0xf;
2090 rd1 = (insn >> 16) & 0xf;
2091 gen_op_iwmmxt_movq_M0_wRn(rd0);
e677137d 2092 tcg_gen_neg_i64(cpu_M0, cpu_M0);
18c9b560
AZ
2093 gen_op_iwmmxt_andq_M0_wRn(rd1);
2094 gen_op_iwmmxt_setpsr_nz();
2095 gen_op_iwmmxt_movq_wRn_M0(wrd);
2096 gen_op_iwmmxt_set_mup();
2097 gen_op_iwmmxt_set_cup();
2098 break;
d00584b7 2099 case 0x200: /* WAND */
18c9b560
AZ
2100 wrd = (insn >> 12) & 0xf;
2101 rd0 = (insn >> 0) & 0xf;
2102 rd1 = (insn >> 16) & 0xf;
2103 gen_op_iwmmxt_movq_M0_wRn(rd0);
2104 gen_op_iwmmxt_andq_M0_wRn(rd1);
2105 gen_op_iwmmxt_setpsr_nz();
2106 gen_op_iwmmxt_movq_wRn_M0(wrd);
2107 gen_op_iwmmxt_set_mup();
2108 gen_op_iwmmxt_set_cup();
2109 break;
d00584b7 2110 case 0x810: case 0xa10: /* WMADD */
18c9b560
AZ
2111 wrd = (insn >> 12) & 0xf;
2112 rd0 = (insn >> 0) & 0xf;
2113 rd1 = (insn >> 16) & 0xf;
2114 gen_op_iwmmxt_movq_M0_wRn(rd0);
2115 if (insn & (1 << 21))
2116 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
2117 else
2118 gen_op_iwmmxt_madduq_M0_wRn(rd1);
2119 gen_op_iwmmxt_movq_wRn_M0(wrd);
2120 gen_op_iwmmxt_set_mup();
2121 break;
d00584b7 2122 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
18c9b560
AZ
2123 wrd = (insn >> 12) & 0xf;
2124 rd0 = (insn >> 16) & 0xf;
2125 rd1 = (insn >> 0) & 0xf;
2126 gen_op_iwmmxt_movq_M0_wRn(rd0);
2127 switch ((insn >> 22) & 3) {
2128 case 0:
2129 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
2130 break;
2131 case 1:
2132 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
2133 break;
2134 case 2:
2135 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
2136 break;
2137 case 3:
2138 return 1;
2139 }
2140 gen_op_iwmmxt_movq_wRn_M0(wrd);
2141 gen_op_iwmmxt_set_mup();
2142 gen_op_iwmmxt_set_cup();
2143 break;
d00584b7 2144 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
18c9b560
AZ
2145 wrd = (insn >> 12) & 0xf;
2146 rd0 = (insn >> 16) & 0xf;
2147 rd1 = (insn >> 0) & 0xf;
2148 gen_op_iwmmxt_movq_M0_wRn(rd0);
2149 switch ((insn >> 22) & 3) {
2150 case 0:
2151 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
2152 break;
2153 case 1:
2154 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
2155 break;
2156 case 2:
2157 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
2158 break;
2159 case 3:
2160 return 1;
2161 }
2162 gen_op_iwmmxt_movq_wRn_M0(wrd);
2163 gen_op_iwmmxt_set_mup();
2164 gen_op_iwmmxt_set_cup();
2165 break;
d00584b7 2166 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
18c9b560
AZ
2167 wrd = (insn >> 12) & 0xf;
2168 rd0 = (insn >> 16) & 0xf;
2169 rd1 = (insn >> 0) & 0xf;
2170 gen_op_iwmmxt_movq_M0_wRn(rd0);
2171 if (insn & (1 << 22))
2172 gen_op_iwmmxt_sadw_M0_wRn(rd1);
2173 else
2174 gen_op_iwmmxt_sadb_M0_wRn(rd1);
2175 if (!(insn & (1 << 20)))
2176 gen_op_iwmmxt_addl_M0_wRn(wrd);
2177 gen_op_iwmmxt_movq_wRn_M0(wrd);
2178 gen_op_iwmmxt_set_mup();
2179 break;
d00584b7 2180 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
18c9b560
AZ
2181 wrd = (insn >> 12) & 0xf;
2182 rd0 = (insn >> 16) & 0xf;
2183 rd1 = (insn >> 0) & 0xf;
2184 gen_op_iwmmxt_movq_M0_wRn(rd0);
e677137d
PB
2185 if (insn & (1 << 21)) {
2186 if (insn & (1 << 20))
2187 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
2188 else
2189 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
2190 } else {
2191 if (insn & (1 << 20))
2192 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
2193 else
2194 gen_op_iwmmxt_mululw_M0_wRn(rd1);
2195 }
18c9b560
AZ
2196 gen_op_iwmmxt_movq_wRn_M0(wrd);
2197 gen_op_iwmmxt_set_mup();
2198 break;
d00584b7 2199 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
18c9b560
AZ
2200 wrd = (insn >> 12) & 0xf;
2201 rd0 = (insn >> 16) & 0xf;
2202 rd1 = (insn >> 0) & 0xf;
2203 gen_op_iwmmxt_movq_M0_wRn(rd0);
2204 if (insn & (1 << 21))
2205 gen_op_iwmmxt_macsw_M0_wRn(rd1);
2206 else
2207 gen_op_iwmmxt_macuw_M0_wRn(rd1);
2208 if (!(insn & (1 << 20))) {
e677137d
PB
2209 iwmmxt_load_reg(cpu_V1, wrd);
2210 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
18c9b560
AZ
2211 }
2212 gen_op_iwmmxt_movq_wRn_M0(wrd);
2213 gen_op_iwmmxt_set_mup();
2214 break;
d00584b7 2215 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
18c9b560
AZ
2216 wrd = (insn >> 12) & 0xf;
2217 rd0 = (insn >> 16) & 0xf;
2218 rd1 = (insn >> 0) & 0xf;
2219 gen_op_iwmmxt_movq_M0_wRn(rd0);
2220 switch ((insn >> 22) & 3) {
2221 case 0:
2222 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
2223 break;
2224 case 1:
2225 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
2226 break;
2227 case 2:
2228 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
2229 break;
2230 case 3:
2231 return 1;
2232 }
2233 gen_op_iwmmxt_movq_wRn_M0(wrd);
2234 gen_op_iwmmxt_set_mup();
2235 gen_op_iwmmxt_set_cup();
2236 break;
d00584b7 2237 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
18c9b560
AZ
2238 wrd = (insn >> 12) & 0xf;
2239 rd0 = (insn >> 16) & 0xf;
2240 rd1 = (insn >> 0) & 0xf;
2241 gen_op_iwmmxt_movq_M0_wRn(rd0);
e677137d
PB
2242 if (insn & (1 << 22)) {
2243 if (insn & (1 << 20))
2244 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
2245 else
2246 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
2247 } else {
2248 if (insn & (1 << 20))
2249 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
2250 else
2251 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
2252 }
18c9b560
AZ
2253 gen_op_iwmmxt_movq_wRn_M0(wrd);
2254 gen_op_iwmmxt_set_mup();
2255 gen_op_iwmmxt_set_cup();
2256 break;
d00584b7 2257 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
18c9b560
AZ
2258 wrd = (insn >> 12) & 0xf;
2259 rd0 = (insn >> 16) & 0xf;
2260 rd1 = (insn >> 0) & 0xf;
2261 gen_op_iwmmxt_movq_M0_wRn(rd0);
da6b5335
FN
2262 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
2263 tcg_gen_andi_i32(tmp, tmp, 7);
2264 iwmmxt_load_reg(cpu_V1, rd1);
2265 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
7d1b0095 2266 tcg_temp_free_i32(tmp);
18c9b560
AZ
2267 gen_op_iwmmxt_movq_wRn_M0(wrd);
2268 gen_op_iwmmxt_set_mup();
2269 break;
d00584b7 2270 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
da6b5335
FN
2271 if (((insn >> 6) & 3) == 3)
2272 return 1;
18c9b560
AZ
2273 rd = (insn >> 12) & 0xf;
2274 wrd = (insn >> 16) & 0xf;
da6b5335 2275 tmp = load_reg(s, rd);
18c9b560
AZ
2276 gen_op_iwmmxt_movq_M0_wRn(wrd);
2277 switch ((insn >> 6) & 3) {
2278 case 0:
da6b5335
FN
2279 tmp2 = tcg_const_i32(0xff);
2280 tmp3 = tcg_const_i32((insn & 7) << 3);
18c9b560
AZ
2281 break;
2282 case 1:
da6b5335
FN
2283 tmp2 = tcg_const_i32(0xffff);
2284 tmp3 = tcg_const_i32((insn & 3) << 4);
18c9b560
AZ
2285 break;
2286 case 2:
da6b5335
FN
2287 tmp2 = tcg_const_i32(0xffffffff);
2288 tmp3 = tcg_const_i32((insn & 1) << 5);
18c9b560 2289 break;
da6b5335 2290 default:
f764718d
RH
2291 tmp2 = NULL;
2292 tmp3 = NULL;
18c9b560 2293 }
da6b5335 2294 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
39d5492a
PM
2295 tcg_temp_free_i32(tmp3);
2296 tcg_temp_free_i32(tmp2);
7d1b0095 2297 tcg_temp_free_i32(tmp);
18c9b560
AZ
2298 gen_op_iwmmxt_movq_wRn_M0(wrd);
2299 gen_op_iwmmxt_set_mup();
2300 break;
d00584b7 2301 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
18c9b560
AZ
2302 rd = (insn >> 12) & 0xf;
2303 wrd = (insn >> 16) & 0xf;
da6b5335 2304 if (rd == 15 || ((insn >> 22) & 3) == 3)
18c9b560
AZ
2305 return 1;
2306 gen_op_iwmmxt_movq_M0_wRn(wrd);
7d1b0095 2307 tmp = tcg_temp_new_i32();
18c9b560
AZ
2308 switch ((insn >> 22) & 3) {
2309 case 0:
da6b5335 2310 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
ecc7b3aa 2311 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
da6b5335
FN
2312 if (insn & 8) {
2313 tcg_gen_ext8s_i32(tmp, tmp);
2314 } else {
2315 tcg_gen_andi_i32(tmp, tmp, 0xff);
18c9b560
AZ
2316 }
2317 break;
2318 case 1:
da6b5335 2319 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
ecc7b3aa 2320 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
da6b5335
FN
2321 if (insn & 8) {
2322 tcg_gen_ext16s_i32(tmp, tmp);
2323 } else {
2324 tcg_gen_andi_i32(tmp, tmp, 0xffff);
18c9b560
AZ
2325 }
2326 break;
2327 case 2:
da6b5335 2328 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
ecc7b3aa 2329 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
18c9b560 2330 break;
18c9b560 2331 }
da6b5335 2332 store_reg(s, rd, tmp);
18c9b560 2333 break;
d00584b7 2334 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
da6b5335 2335 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
18c9b560 2336 return 1;
da6b5335 2337 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
18c9b560
AZ
2338 switch ((insn >> 22) & 3) {
2339 case 0:
da6b5335 2340 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
18c9b560
AZ
2341 break;
2342 case 1:
da6b5335 2343 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
18c9b560
AZ
2344 break;
2345 case 2:
da6b5335 2346 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
18c9b560 2347 break;
18c9b560 2348 }
da6b5335
FN
2349 tcg_gen_shli_i32(tmp, tmp, 28);
2350 gen_set_nzcv(tmp);
7d1b0095 2351 tcg_temp_free_i32(tmp);
18c9b560 2352 break;
d00584b7 2353 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
da6b5335
FN
2354 if (((insn >> 6) & 3) == 3)
2355 return 1;
18c9b560
AZ
2356 rd = (insn >> 12) & 0xf;
2357 wrd = (insn >> 16) & 0xf;
da6b5335 2358 tmp = load_reg(s, rd);
18c9b560
AZ
2359 switch ((insn >> 6) & 3) {
2360 case 0:
da6b5335 2361 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
18c9b560
AZ
2362 break;
2363 case 1:
da6b5335 2364 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
18c9b560
AZ
2365 break;
2366 case 2:
da6b5335 2367 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
18c9b560 2368 break;
18c9b560 2369 }
7d1b0095 2370 tcg_temp_free_i32(tmp);
18c9b560
AZ
2371 gen_op_iwmmxt_movq_wRn_M0(wrd);
2372 gen_op_iwmmxt_set_mup();
2373 break;
d00584b7 2374 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
da6b5335 2375 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
18c9b560 2376 return 1;
da6b5335 2377 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
7d1b0095 2378 tmp2 = tcg_temp_new_i32();
da6b5335 2379 tcg_gen_mov_i32(tmp2, tmp);
18c9b560
AZ
2380 switch ((insn >> 22) & 3) {
2381 case 0:
2382 for (i = 0; i < 7; i ++) {
da6b5335
FN
2383 tcg_gen_shli_i32(tmp2, tmp2, 4);
2384 tcg_gen_and_i32(tmp, tmp, tmp2);
18c9b560
AZ
2385 }
2386 break;
2387 case 1:
2388 for (i = 0; i < 3; i ++) {
da6b5335
FN
2389 tcg_gen_shli_i32(tmp2, tmp2, 8);
2390 tcg_gen_and_i32(tmp, tmp, tmp2);
18c9b560
AZ
2391 }
2392 break;
2393 case 2:
da6b5335
FN
2394 tcg_gen_shli_i32(tmp2, tmp2, 16);
2395 tcg_gen_and_i32(tmp, tmp, tmp2);
18c9b560 2396 break;
18c9b560 2397 }
da6b5335 2398 gen_set_nzcv(tmp);
7d1b0095
PM
2399 tcg_temp_free_i32(tmp2);
2400 tcg_temp_free_i32(tmp);
18c9b560 2401 break;
d00584b7 2402 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
18c9b560
AZ
2403 wrd = (insn >> 12) & 0xf;
2404 rd0 = (insn >> 16) & 0xf;
2405 gen_op_iwmmxt_movq_M0_wRn(rd0);
2406 switch ((insn >> 22) & 3) {
2407 case 0:
e677137d 2408 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
18c9b560
AZ
2409 break;
2410 case 1:
e677137d 2411 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
18c9b560
AZ
2412 break;
2413 case 2:
e677137d 2414 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
18c9b560
AZ
2415 break;
2416 case 3:
2417 return 1;
2418 }
2419 gen_op_iwmmxt_movq_wRn_M0(wrd);
2420 gen_op_iwmmxt_set_mup();
2421 break;
d00584b7 2422 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
da6b5335 2423 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
18c9b560 2424 return 1;
da6b5335 2425 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
7d1b0095 2426 tmp2 = tcg_temp_new_i32();
da6b5335 2427 tcg_gen_mov_i32(tmp2, tmp);
18c9b560
AZ
2428 switch ((insn >> 22) & 3) {
2429 case 0:
2430 for (i = 0; i < 7; i ++) {
da6b5335
FN
2431 tcg_gen_shli_i32(tmp2, tmp2, 4);
2432 tcg_gen_or_i32(tmp, tmp, tmp2);
18c9b560
AZ
2433 }
2434 break;
2435 case 1:
2436 for (i = 0; i < 3; i ++) {
da6b5335
FN
2437 tcg_gen_shli_i32(tmp2, tmp2, 8);
2438 tcg_gen_or_i32(tmp, tmp, tmp2);
18c9b560
AZ
2439 }
2440 break;
2441 case 2:
da6b5335
FN
2442 tcg_gen_shli_i32(tmp2, tmp2, 16);
2443 tcg_gen_or_i32(tmp, tmp, tmp2);
18c9b560 2444 break;
18c9b560 2445 }
da6b5335 2446 gen_set_nzcv(tmp);
7d1b0095
PM
2447 tcg_temp_free_i32(tmp2);
2448 tcg_temp_free_i32(tmp);
18c9b560 2449 break;
d00584b7 2450 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
18c9b560
AZ
2451 rd = (insn >> 12) & 0xf;
2452 rd0 = (insn >> 16) & 0xf;
da6b5335 2453 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
18c9b560
AZ
2454 return 1;
2455 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2456 tmp = tcg_temp_new_i32();
18c9b560
AZ
2457 switch ((insn >> 22) & 3) {
2458 case 0:
da6b5335 2459 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
18c9b560
AZ
2460 break;
2461 case 1:
da6b5335 2462 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
18c9b560
AZ
2463 break;
2464 case 2:
da6b5335 2465 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
18c9b560 2466 break;
18c9b560 2467 }
da6b5335 2468 store_reg(s, rd, tmp);
18c9b560 2469 break;
d00584b7 2470 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
18c9b560
AZ
2471 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2472 wrd = (insn >> 12) & 0xf;
2473 rd0 = (insn >> 16) & 0xf;
2474 rd1 = (insn >> 0) & 0xf;
2475 gen_op_iwmmxt_movq_M0_wRn(rd0);
2476 switch ((insn >> 22) & 3) {
2477 case 0:
2478 if (insn & (1 << 21))
2479 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2480 else
2481 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2482 break;
2483 case 1:
2484 if (insn & (1 << 21))
2485 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2486 else
2487 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2488 break;
2489 case 2:
2490 if (insn & (1 << 21))
2491 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2492 else
2493 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2494 break;
2495 case 3:
2496 return 1;
2497 }
2498 gen_op_iwmmxt_movq_wRn_M0(wrd);
2499 gen_op_iwmmxt_set_mup();
2500 gen_op_iwmmxt_set_cup();
2501 break;
d00584b7 2502 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
18c9b560
AZ
2503 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2504 wrd = (insn >> 12) & 0xf;
2505 rd0 = (insn >> 16) & 0xf;
2506 gen_op_iwmmxt_movq_M0_wRn(rd0);
2507 switch ((insn >> 22) & 3) {
2508 case 0:
2509 if (insn & (1 << 21))
2510 gen_op_iwmmxt_unpacklsb_M0();
2511 else
2512 gen_op_iwmmxt_unpacklub_M0();
2513 break;
2514 case 1:
2515 if (insn & (1 << 21))
2516 gen_op_iwmmxt_unpacklsw_M0();
2517 else
2518 gen_op_iwmmxt_unpackluw_M0();
2519 break;
2520 case 2:
2521 if (insn & (1 << 21))
2522 gen_op_iwmmxt_unpacklsl_M0();
2523 else
2524 gen_op_iwmmxt_unpacklul_M0();
2525 break;
2526 case 3:
2527 return 1;
2528 }
2529 gen_op_iwmmxt_movq_wRn_M0(wrd);
2530 gen_op_iwmmxt_set_mup();
2531 gen_op_iwmmxt_set_cup();
2532 break;
d00584b7 2533 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
18c9b560
AZ
2534 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2535 wrd = (insn >> 12) & 0xf;
2536 rd0 = (insn >> 16) & 0xf;
2537 gen_op_iwmmxt_movq_M0_wRn(rd0);
2538 switch ((insn >> 22) & 3) {
2539 case 0:
2540 if (insn & (1 << 21))
2541 gen_op_iwmmxt_unpackhsb_M0();
2542 else
2543 gen_op_iwmmxt_unpackhub_M0();
2544 break;
2545 case 1:
2546 if (insn & (1 << 21))
2547 gen_op_iwmmxt_unpackhsw_M0();
2548 else
2549 gen_op_iwmmxt_unpackhuw_M0();
2550 break;
2551 case 2:
2552 if (insn & (1 << 21))
2553 gen_op_iwmmxt_unpackhsl_M0();
2554 else
2555 gen_op_iwmmxt_unpackhul_M0();
2556 break;
2557 case 3:
2558 return 1;
2559 }
2560 gen_op_iwmmxt_movq_wRn_M0(wrd);
2561 gen_op_iwmmxt_set_mup();
2562 gen_op_iwmmxt_set_cup();
2563 break;
d00584b7 2564 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
18c9b560 2565 case 0x214: case 0x614: case 0xa14: case 0xe14:
da6b5335
FN
2566 if (((insn >> 22) & 3) == 0)
2567 return 1;
18c9b560
AZ
2568 wrd = (insn >> 12) & 0xf;
2569 rd0 = (insn >> 16) & 0xf;
2570 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2571 tmp = tcg_temp_new_i32();
da6b5335 2572 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
7d1b0095 2573 tcg_temp_free_i32(tmp);
18c9b560 2574 return 1;
da6b5335 2575 }
18c9b560 2576 switch ((insn >> 22) & 3) {
18c9b560 2577 case 1:
477955bd 2578 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2579 break;
2580 case 2:
477955bd 2581 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2582 break;
2583 case 3:
477955bd 2584 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2585 break;
2586 }
7d1b0095 2587 tcg_temp_free_i32(tmp);
18c9b560
AZ
2588 gen_op_iwmmxt_movq_wRn_M0(wrd);
2589 gen_op_iwmmxt_set_mup();
2590 gen_op_iwmmxt_set_cup();
2591 break;
d00584b7 2592 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
18c9b560 2593 case 0x014: case 0x414: case 0x814: case 0xc14:
da6b5335
FN
2594 if (((insn >> 22) & 3) == 0)
2595 return 1;
18c9b560
AZ
2596 wrd = (insn >> 12) & 0xf;
2597 rd0 = (insn >> 16) & 0xf;
2598 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2599 tmp = tcg_temp_new_i32();
da6b5335 2600 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
7d1b0095 2601 tcg_temp_free_i32(tmp);
18c9b560 2602 return 1;
da6b5335 2603 }
18c9b560 2604 switch ((insn >> 22) & 3) {
18c9b560 2605 case 1:
477955bd 2606 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2607 break;
2608 case 2:
477955bd 2609 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2610 break;
2611 case 3:
477955bd 2612 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2613 break;
2614 }
7d1b0095 2615 tcg_temp_free_i32(tmp);
18c9b560
AZ
2616 gen_op_iwmmxt_movq_wRn_M0(wrd);
2617 gen_op_iwmmxt_set_mup();
2618 gen_op_iwmmxt_set_cup();
2619 break;
d00584b7 2620 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
18c9b560 2621 case 0x114: case 0x514: case 0x914: case 0xd14:
da6b5335
FN
2622 if (((insn >> 22) & 3) == 0)
2623 return 1;
18c9b560
AZ
2624 wrd = (insn >> 12) & 0xf;
2625 rd0 = (insn >> 16) & 0xf;
2626 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2627 tmp = tcg_temp_new_i32();
da6b5335 2628 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
7d1b0095 2629 tcg_temp_free_i32(tmp);
18c9b560 2630 return 1;
da6b5335 2631 }
18c9b560 2632 switch ((insn >> 22) & 3) {
18c9b560 2633 case 1:
477955bd 2634 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2635 break;
2636 case 2:
477955bd 2637 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2638 break;
2639 case 3:
477955bd 2640 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2641 break;
2642 }
7d1b0095 2643 tcg_temp_free_i32(tmp);
18c9b560
AZ
2644 gen_op_iwmmxt_movq_wRn_M0(wrd);
2645 gen_op_iwmmxt_set_mup();
2646 gen_op_iwmmxt_set_cup();
2647 break;
d00584b7 2648 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
18c9b560 2649 case 0x314: case 0x714: case 0xb14: case 0xf14:
da6b5335
FN
2650 if (((insn >> 22) & 3) == 0)
2651 return 1;
18c9b560
AZ
2652 wrd = (insn >> 12) & 0xf;
2653 rd0 = (insn >> 16) & 0xf;
2654 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2655 tmp = tcg_temp_new_i32();
18c9b560 2656 switch ((insn >> 22) & 3) {
18c9b560 2657 case 1:
da6b5335 2658 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
7d1b0095 2659 tcg_temp_free_i32(tmp);
18c9b560 2660 return 1;
da6b5335 2661 }
477955bd 2662 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2663 break;
2664 case 2:
da6b5335 2665 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
7d1b0095 2666 tcg_temp_free_i32(tmp);
18c9b560 2667 return 1;
da6b5335 2668 }
477955bd 2669 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2670 break;
2671 case 3:
da6b5335 2672 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
7d1b0095 2673 tcg_temp_free_i32(tmp);
18c9b560 2674 return 1;
da6b5335 2675 }
477955bd 2676 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2677 break;
2678 }
7d1b0095 2679 tcg_temp_free_i32(tmp);
18c9b560
AZ
2680 gen_op_iwmmxt_movq_wRn_M0(wrd);
2681 gen_op_iwmmxt_set_mup();
2682 gen_op_iwmmxt_set_cup();
2683 break;
d00584b7 2684 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
18c9b560
AZ
2685 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2686 wrd = (insn >> 12) & 0xf;
2687 rd0 = (insn >> 16) & 0xf;
2688 rd1 = (insn >> 0) & 0xf;
2689 gen_op_iwmmxt_movq_M0_wRn(rd0);
2690 switch ((insn >> 22) & 3) {
2691 case 0:
2692 if (insn & (1 << 21))
2693 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2694 else
2695 gen_op_iwmmxt_minub_M0_wRn(rd1);
2696 break;
2697 case 1:
2698 if (insn & (1 << 21))
2699 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2700 else
2701 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2702 break;
2703 case 2:
2704 if (insn & (1 << 21))
2705 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2706 else
2707 gen_op_iwmmxt_minul_M0_wRn(rd1);
2708 break;
2709 case 3:
2710 return 1;
2711 }
2712 gen_op_iwmmxt_movq_wRn_M0(wrd);
2713 gen_op_iwmmxt_set_mup();
2714 break;
d00584b7 2715 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
18c9b560
AZ
2716 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2717 wrd = (insn >> 12) & 0xf;
2718 rd0 = (insn >> 16) & 0xf;
2719 rd1 = (insn >> 0) & 0xf;
2720 gen_op_iwmmxt_movq_M0_wRn(rd0);
2721 switch ((insn >> 22) & 3) {
2722 case 0:
2723 if (insn & (1 << 21))
2724 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2725 else
2726 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2727 break;
2728 case 1:
2729 if (insn & (1 << 21))
2730 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2731 else
2732 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2733 break;
2734 case 2:
2735 if (insn & (1 << 21))
2736 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2737 else
2738 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2739 break;
2740 case 3:
2741 return 1;
2742 }
2743 gen_op_iwmmxt_movq_wRn_M0(wrd);
2744 gen_op_iwmmxt_set_mup();
2745 break;
d00584b7 2746 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
18c9b560
AZ
2747 case 0x402: case 0x502: case 0x602: case 0x702:
2748 wrd = (insn >> 12) & 0xf;
2749 rd0 = (insn >> 16) & 0xf;
2750 rd1 = (insn >> 0) & 0xf;
2751 gen_op_iwmmxt_movq_M0_wRn(rd0);
da6b5335
FN
2752 tmp = tcg_const_i32((insn >> 20) & 3);
2753 iwmmxt_load_reg(cpu_V1, rd1);
2754 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
39d5492a 2755 tcg_temp_free_i32(tmp);
18c9b560
AZ
2756 gen_op_iwmmxt_movq_wRn_M0(wrd);
2757 gen_op_iwmmxt_set_mup();
2758 break;
d00584b7 2759 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
18c9b560
AZ
2760 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2761 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2762 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2763 wrd = (insn >> 12) & 0xf;
2764 rd0 = (insn >> 16) & 0xf;
2765 rd1 = (insn >> 0) & 0xf;
2766 gen_op_iwmmxt_movq_M0_wRn(rd0);
2767 switch ((insn >> 20) & 0xf) {
2768 case 0x0:
2769 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2770 break;
2771 case 0x1:
2772 gen_op_iwmmxt_subub_M0_wRn(rd1);
2773 break;
2774 case 0x3:
2775 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2776 break;
2777 case 0x4:
2778 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2779 break;
2780 case 0x5:
2781 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2782 break;
2783 case 0x7:
2784 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2785 break;
2786 case 0x8:
2787 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2788 break;
2789 case 0x9:
2790 gen_op_iwmmxt_subul_M0_wRn(rd1);
2791 break;
2792 case 0xb:
2793 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2794 break;
2795 default:
2796 return 1;
2797 }
2798 gen_op_iwmmxt_movq_wRn_M0(wrd);
2799 gen_op_iwmmxt_set_mup();
2800 gen_op_iwmmxt_set_cup();
2801 break;
d00584b7 2802 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
18c9b560
AZ
2803 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2804 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2805 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2806 wrd = (insn >> 12) & 0xf;
2807 rd0 = (insn >> 16) & 0xf;
2808 gen_op_iwmmxt_movq_M0_wRn(rd0);
da6b5335 2809 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
477955bd 2810 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
39d5492a 2811 tcg_temp_free_i32(tmp);
18c9b560
AZ
2812 gen_op_iwmmxt_movq_wRn_M0(wrd);
2813 gen_op_iwmmxt_set_mup();
2814 gen_op_iwmmxt_set_cup();
2815 break;
d00584b7 2816 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
18c9b560
AZ
2817 case 0x418: case 0x518: case 0x618: case 0x718:
2818 case 0x818: case 0x918: case 0xa18: case 0xb18:
2819 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2820 wrd = (insn >> 12) & 0xf;
2821 rd0 = (insn >> 16) & 0xf;
2822 rd1 = (insn >> 0) & 0xf;
2823 gen_op_iwmmxt_movq_M0_wRn(rd0);
2824 switch ((insn >> 20) & 0xf) {
2825 case 0x0:
2826 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2827 break;
2828 case 0x1:
2829 gen_op_iwmmxt_addub_M0_wRn(rd1);
2830 break;
2831 case 0x3:
2832 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2833 break;
2834 case 0x4:
2835 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2836 break;
2837 case 0x5:
2838 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2839 break;
2840 case 0x7:
2841 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2842 break;
2843 case 0x8:
2844 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2845 break;
2846 case 0x9:
2847 gen_op_iwmmxt_addul_M0_wRn(rd1);
2848 break;
2849 case 0xb:
2850 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2851 break;
2852 default:
2853 return 1;
2854 }
2855 gen_op_iwmmxt_movq_wRn_M0(wrd);
2856 gen_op_iwmmxt_set_mup();
2857 gen_op_iwmmxt_set_cup();
2858 break;
d00584b7 2859 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
18c9b560
AZ
2860 case 0x408: case 0x508: case 0x608: case 0x708:
2861 case 0x808: case 0x908: case 0xa08: case 0xb08:
2862 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
da6b5335
FN
2863 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2864 return 1;
18c9b560
AZ
2865 wrd = (insn >> 12) & 0xf;
2866 rd0 = (insn >> 16) & 0xf;
2867 rd1 = (insn >> 0) & 0xf;
2868 gen_op_iwmmxt_movq_M0_wRn(rd0);
18c9b560 2869 switch ((insn >> 22) & 3) {
18c9b560
AZ
2870 case 1:
2871 if (insn & (1 << 21))
2872 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2873 else
2874 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2875 break;
2876 case 2:
2877 if (insn & (1 << 21))
2878 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2879 else
2880 gen_op_iwmmxt_packul_M0_wRn(rd1);
2881 break;
2882 case 3:
2883 if (insn & (1 << 21))
2884 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2885 else
2886 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2887 break;
2888 }
2889 gen_op_iwmmxt_movq_wRn_M0(wrd);
2890 gen_op_iwmmxt_set_mup();
2891 gen_op_iwmmxt_set_cup();
2892 break;
2893 case 0x201: case 0x203: case 0x205: case 0x207:
2894 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2895 case 0x211: case 0x213: case 0x215: case 0x217:
2896 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2897 wrd = (insn >> 5) & 0xf;
2898 rd0 = (insn >> 12) & 0xf;
2899 rd1 = (insn >> 0) & 0xf;
2900 if (rd0 == 0xf || rd1 == 0xf)
2901 return 1;
2902 gen_op_iwmmxt_movq_M0_wRn(wrd);
da6b5335
FN
2903 tmp = load_reg(s, rd0);
2904 tmp2 = load_reg(s, rd1);
18c9b560 2905 switch ((insn >> 16) & 0xf) {
d00584b7 2906 case 0x0: /* TMIA */
da6b5335 2907 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560 2908 break;
d00584b7 2909 case 0x8: /* TMIAPH */
da6b5335 2910 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560 2911 break;
d00584b7 2912 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
18c9b560 2913 if (insn & (1 << 16))
da6b5335 2914 tcg_gen_shri_i32(tmp, tmp, 16);
18c9b560 2915 if (insn & (1 << 17))
da6b5335
FN
2916 tcg_gen_shri_i32(tmp2, tmp2, 16);
2917 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2918 break;
2919 default:
7d1b0095
PM
2920 tcg_temp_free_i32(tmp2);
2921 tcg_temp_free_i32(tmp);
18c9b560
AZ
2922 return 1;
2923 }
7d1b0095
PM
2924 tcg_temp_free_i32(tmp2);
2925 tcg_temp_free_i32(tmp);
18c9b560
AZ
2926 gen_op_iwmmxt_movq_wRn_M0(wrd);
2927 gen_op_iwmmxt_set_mup();
2928 break;
2929 default:
2930 return 1;
2931 }
2932
2933 return 0;
2934}
2935
a1c7273b 2936/* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
18c9b560 2937 (ie. an undefined instruction). */
7dcc1f89 2938static int disas_dsp_insn(DisasContext *s, uint32_t insn)
18c9b560
AZ
2939{
2940 int acc, rd0, rd1, rdhi, rdlo;
39d5492a 2941 TCGv_i32 tmp, tmp2;
18c9b560
AZ
2942
2943 if ((insn & 0x0ff00f10) == 0x0e200010) {
2944 /* Multiply with Internal Accumulate Format */
2945 rd0 = (insn >> 12) & 0xf;
2946 rd1 = insn & 0xf;
2947 acc = (insn >> 5) & 7;
2948
2949 if (acc != 0)
2950 return 1;
2951
3a554c0f
FN
2952 tmp = load_reg(s, rd0);
2953 tmp2 = load_reg(s, rd1);
18c9b560 2954 switch ((insn >> 16) & 0xf) {
d00584b7 2955 case 0x0: /* MIA */
3a554c0f 2956 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560 2957 break;
d00584b7 2958 case 0x8: /* MIAPH */
3a554c0f 2959 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560 2960 break;
d00584b7
PM
2961 case 0xc: /* MIABB */
2962 case 0xd: /* MIABT */
2963 case 0xe: /* MIATB */
2964 case 0xf: /* MIATT */
18c9b560 2965 if (insn & (1 << 16))
3a554c0f 2966 tcg_gen_shri_i32(tmp, tmp, 16);
18c9b560 2967 if (insn & (1 << 17))
3a554c0f
FN
2968 tcg_gen_shri_i32(tmp2, tmp2, 16);
2969 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2970 break;
2971 default:
2972 return 1;
2973 }
7d1b0095
PM
2974 tcg_temp_free_i32(tmp2);
2975 tcg_temp_free_i32(tmp);
18c9b560
AZ
2976
2977 gen_op_iwmmxt_movq_wRn_M0(acc);
2978 return 0;
2979 }
2980
2981 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2982 /* Internal Accumulator Access Format */
2983 rdhi = (insn >> 16) & 0xf;
2984 rdlo = (insn >> 12) & 0xf;
2985 acc = insn & 7;
2986
2987 if (acc != 0)
2988 return 1;
2989
d00584b7 2990 if (insn & ARM_CP_RW_BIT) { /* MRA */
3a554c0f 2991 iwmmxt_load_reg(cpu_V0, acc);
ecc7b3aa 2992 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
3a554c0f 2993 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
ecc7b3aa 2994 tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
3a554c0f 2995 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
d00584b7 2996 } else { /* MAR */
3a554c0f
FN
2997 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2998 iwmmxt_store_reg(cpu_V0, acc);
18c9b560
AZ
2999 }
3000 return 0;
3001 }
3002
3003 return 1;
3004}
3005
9ee6e8bb
PB
3006#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
3007#define VFP_SREG(insn, bigbit, smallbit) \
3008 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
3009#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
d614a513 3010 if (arm_dc_feature(s, ARM_FEATURE_VFP3)) { \
9ee6e8bb
PB
3011 reg = (((insn) >> (bigbit)) & 0x0f) \
3012 | (((insn) >> ((smallbit) - 4)) & 0x10); \
3013 } else { \
3014 if (insn & (1 << (smallbit))) \
3015 return 1; \
3016 reg = ((insn) >> (bigbit)) & 0x0f; \
3017 }} while (0)
3018
3019#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
3020#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
3021#define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
3022#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
3023#define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
3024#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
3025
4373f3ce 3026/* Move between integer and VFP cores. */
39d5492a 3027static TCGv_i32 gen_vfp_mrs(void)
4373f3ce 3028{
39d5492a 3029 TCGv_i32 tmp = tcg_temp_new_i32();
4373f3ce
PB
3030 tcg_gen_mov_i32(tmp, cpu_F0s);
3031 return tmp;
3032}
3033
39d5492a 3034static void gen_vfp_msr(TCGv_i32 tmp)
4373f3ce
PB
3035{
3036 tcg_gen_mov_i32(cpu_F0s, tmp);
7d1b0095 3037 tcg_temp_free_i32(tmp);
4373f3ce
PB
3038}
3039
39d5492a 3040static void gen_neon_dup_low16(TCGv_i32 var)
ad69471c 3041{
39d5492a 3042 TCGv_i32 tmp = tcg_temp_new_i32();
86831435 3043 tcg_gen_ext16u_i32(var, var);
ad69471c
PB
3044 tcg_gen_shli_i32(tmp, var, 16);
3045 tcg_gen_or_i32(var, var, tmp);
7d1b0095 3046 tcg_temp_free_i32(tmp);
ad69471c
PB
3047}
3048
39d5492a 3049static void gen_neon_dup_high16(TCGv_i32 var)
ad69471c 3050{
39d5492a 3051 TCGv_i32 tmp = tcg_temp_new_i32();
ad69471c
PB
3052 tcg_gen_andi_i32(var, var, 0xffff0000);
3053 tcg_gen_shri_i32(tmp, var, 16);
3054 tcg_gen_or_i32(var, var, tmp);
7d1b0095 3055 tcg_temp_free_i32(tmp);
ad69471c
PB
3056}
3057
04731fb5
WN
3058static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
3059 uint32_t dp)
3060{
3061 uint32_t cc = extract32(insn, 20, 2);
3062
3063 if (dp) {
3064 TCGv_i64 frn, frm, dest;
3065 TCGv_i64 tmp, zero, zf, nf, vf;
3066
3067 zero = tcg_const_i64(0);
3068
3069 frn = tcg_temp_new_i64();
3070 frm = tcg_temp_new_i64();
3071 dest = tcg_temp_new_i64();
3072
3073 zf = tcg_temp_new_i64();
3074 nf = tcg_temp_new_i64();
3075 vf = tcg_temp_new_i64();
3076
3077 tcg_gen_extu_i32_i64(zf, cpu_ZF);
3078 tcg_gen_ext_i32_i64(nf, cpu_NF);
3079 tcg_gen_ext_i32_i64(vf, cpu_VF);
3080
3081 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
3082 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
3083 switch (cc) {
3084 case 0: /* eq: Z */
3085 tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero,
3086 frn, frm);
3087 break;
3088 case 1: /* vs: V */
3089 tcg_gen_movcond_i64(TCG_COND_LT, dest, vf, zero,
3090 frn, frm);
3091 break;
3092 case 2: /* ge: N == V -> N ^ V == 0 */
3093 tmp = tcg_temp_new_i64();
3094 tcg_gen_xor_i64(tmp, vf, nf);
3095 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
3096 frn, frm);
3097 tcg_temp_free_i64(tmp);
3098 break;
3099 case 3: /* gt: !Z && N == V */
3100 tcg_gen_movcond_i64(TCG_COND_NE, dest, zf, zero,
3101 frn, frm);
3102 tmp = tcg_temp_new_i64();
3103 tcg_gen_xor_i64(tmp, vf, nf);
3104 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
3105 dest, frm);
3106 tcg_temp_free_i64(tmp);
3107 break;
3108 }
3109 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
3110 tcg_temp_free_i64(frn);
3111 tcg_temp_free_i64(frm);
3112 tcg_temp_free_i64(dest);
3113
3114 tcg_temp_free_i64(zf);
3115 tcg_temp_free_i64(nf);
3116 tcg_temp_free_i64(vf);
3117
3118 tcg_temp_free_i64(zero);
3119 } else {
3120 TCGv_i32 frn, frm, dest;
3121 TCGv_i32 tmp, zero;
3122
3123 zero = tcg_const_i32(0);
3124
3125 frn = tcg_temp_new_i32();
3126 frm = tcg_temp_new_i32();
3127 dest = tcg_temp_new_i32();
3128 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
3129 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
3130 switch (cc) {
3131 case 0: /* eq: Z */
3132 tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero,
3133 frn, frm);
3134 break;
3135 case 1: /* vs: V */
3136 tcg_gen_movcond_i32(TCG_COND_LT, dest, cpu_VF, zero,
3137 frn, frm);
3138 break;
3139 case 2: /* ge: N == V -> N ^ V == 0 */
3140 tmp = tcg_temp_new_i32();
3141 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
3142 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
3143 frn, frm);
3144 tcg_temp_free_i32(tmp);
3145 break;
3146 case 3: /* gt: !Z && N == V */
3147 tcg_gen_movcond_i32(TCG_COND_NE, dest, cpu_ZF, zero,
3148 frn, frm);
3149 tmp = tcg_temp_new_i32();
3150 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
3151 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
3152 dest, frm);
3153 tcg_temp_free_i32(tmp);
3154 break;
3155 }
3156 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
3157 tcg_temp_free_i32(frn);
3158 tcg_temp_free_i32(frm);
3159 tcg_temp_free_i32(dest);
3160
3161 tcg_temp_free_i32(zero);
3162 }
3163
3164 return 0;
3165}
3166
40cfacdd
WN
3167static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn,
3168 uint32_t rm, uint32_t dp)
3169{
3170 uint32_t vmin = extract32(insn, 6, 1);
3171 TCGv_ptr fpst = get_fpstatus_ptr(0);
3172
3173 if (dp) {
3174 TCGv_i64 frn, frm, dest;
3175
3176 frn = tcg_temp_new_i64();
3177 frm = tcg_temp_new_i64();
3178 dest = tcg_temp_new_i64();
3179
3180 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
3181 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
3182 if (vmin) {
f71a2ae5 3183 gen_helper_vfp_minnumd(dest, frn, frm, fpst);
40cfacdd 3184 } else {
f71a2ae5 3185 gen_helper_vfp_maxnumd(dest, frn, frm, fpst);
40cfacdd
WN
3186 }
3187 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
3188 tcg_temp_free_i64(frn);
3189 tcg_temp_free_i64(frm);
3190 tcg_temp_free_i64(dest);
3191 } else {
3192 TCGv_i32 frn, frm, dest;
3193
3194 frn = tcg_temp_new_i32();
3195 frm = tcg_temp_new_i32();
3196 dest = tcg_temp_new_i32();
3197
3198 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
3199 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
3200 if (vmin) {
f71a2ae5 3201 gen_helper_vfp_minnums(dest, frn, frm, fpst);
40cfacdd 3202 } else {
f71a2ae5 3203 gen_helper_vfp_maxnums(dest, frn, frm, fpst);
40cfacdd
WN
3204 }
3205 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
3206 tcg_temp_free_i32(frn);
3207 tcg_temp_free_i32(frm);
3208 tcg_temp_free_i32(dest);
3209 }
3210
3211 tcg_temp_free_ptr(fpst);
3212 return 0;
3213}
3214
7655f39b
WN
3215static int handle_vrint(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
3216 int rounding)
3217{
3218 TCGv_ptr fpst = get_fpstatus_ptr(0);
3219 TCGv_i32 tcg_rmode;
3220
3221 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
9b049916 3222 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
7655f39b
WN
3223
3224 if (dp) {
3225 TCGv_i64 tcg_op;
3226 TCGv_i64 tcg_res;
3227 tcg_op = tcg_temp_new_i64();
3228 tcg_res = tcg_temp_new_i64();
3229 tcg_gen_ld_f64(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
3230 gen_helper_rintd(tcg_res, tcg_op, fpst);
3231 tcg_gen_st_f64(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
3232 tcg_temp_free_i64(tcg_op);
3233 tcg_temp_free_i64(tcg_res);
3234 } else {
3235 TCGv_i32 tcg_op;
3236 TCGv_i32 tcg_res;
3237 tcg_op = tcg_temp_new_i32();
3238 tcg_res = tcg_temp_new_i32();
3239 tcg_gen_ld_f32(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
3240 gen_helper_rints(tcg_res, tcg_op, fpst);
3241 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
3242 tcg_temp_free_i32(tcg_op);
3243 tcg_temp_free_i32(tcg_res);
3244 }
3245
9b049916 3246 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
7655f39b
WN
3247 tcg_temp_free_i32(tcg_rmode);
3248
3249 tcg_temp_free_ptr(fpst);
3250 return 0;
3251}
3252
c9975a83
WN
3253static int handle_vcvt(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
3254 int rounding)
3255{
3256 bool is_signed = extract32(insn, 7, 1);
3257 TCGv_ptr fpst = get_fpstatus_ptr(0);
3258 TCGv_i32 tcg_rmode, tcg_shift;
3259
3260 tcg_shift = tcg_const_i32(0);
3261
3262 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
9b049916 3263 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
c9975a83
WN
3264
3265 if (dp) {
3266 TCGv_i64 tcg_double, tcg_res;
3267 TCGv_i32 tcg_tmp;
3268 /* Rd is encoded as a single precision register even when the source
3269 * is double precision.
3270 */
3271 rd = ((rd << 1) & 0x1e) | ((rd >> 4) & 0x1);
3272 tcg_double = tcg_temp_new_i64();
3273 tcg_res = tcg_temp_new_i64();
3274 tcg_tmp = tcg_temp_new_i32();
3275 tcg_gen_ld_f64(tcg_double, cpu_env, vfp_reg_offset(1, rm));
3276 if (is_signed) {
3277 gen_helper_vfp_tosld(tcg_res, tcg_double, tcg_shift, fpst);
3278 } else {
3279 gen_helper_vfp_tould(tcg_res, tcg_double, tcg_shift, fpst);
3280 }
ecc7b3aa 3281 tcg_gen_extrl_i64_i32(tcg_tmp, tcg_res);
c9975a83
WN
3282 tcg_gen_st_f32(tcg_tmp, cpu_env, vfp_reg_offset(0, rd));
3283 tcg_temp_free_i32(tcg_tmp);
3284 tcg_temp_free_i64(tcg_res);
3285 tcg_temp_free_i64(tcg_double);
3286 } else {
3287 TCGv_i32 tcg_single, tcg_res;
3288 tcg_single = tcg_temp_new_i32();
3289 tcg_res = tcg_temp_new_i32();
3290 tcg_gen_ld_f32(tcg_single, cpu_env, vfp_reg_offset(0, rm));
3291 if (is_signed) {
3292 gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst);
3293 } else {
3294 gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst);
3295 }
3296 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(0, rd));
3297 tcg_temp_free_i32(tcg_res);
3298 tcg_temp_free_i32(tcg_single);
3299 }
3300
9b049916 3301 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
c9975a83
WN
3302 tcg_temp_free_i32(tcg_rmode);
3303
3304 tcg_temp_free_i32(tcg_shift);
3305
3306 tcg_temp_free_ptr(fpst);
3307
3308 return 0;
3309}
7655f39b
WN
3310
3311/* Table for converting the most common AArch32 encoding of
3312 * rounding mode to arm_fprounding order (which matches the
3313 * common AArch64 order); see ARM ARM pseudocode FPDecodeRM().
3314 */
3315static const uint8_t fp_decode_rm[] = {
3316 FPROUNDING_TIEAWAY,
3317 FPROUNDING_TIEEVEN,
3318 FPROUNDING_POSINF,
3319 FPROUNDING_NEGINF,
3320};
3321
7dcc1f89 3322static int disas_vfp_v8_insn(DisasContext *s, uint32_t insn)
04731fb5
WN
3323{
3324 uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
3325
d614a513 3326 if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
04731fb5
WN
3327 return 1;
3328 }
3329
3330 if (dp) {
3331 VFP_DREG_D(rd, insn);
3332 VFP_DREG_N(rn, insn);
3333 VFP_DREG_M(rm, insn);
3334 } else {
3335 rd = VFP_SREG_D(insn);
3336 rn = VFP_SREG_N(insn);
3337 rm = VFP_SREG_M(insn);
3338 }
3339
3340 if ((insn & 0x0f800e50) == 0x0e000a00) {
3341 return handle_vsel(insn, rd, rn, rm, dp);
40cfacdd
WN
3342 } else if ((insn & 0x0fb00e10) == 0x0e800a00) {
3343 return handle_vminmaxnm(insn, rd, rn, rm, dp);
7655f39b
WN
3344 } else if ((insn & 0x0fbc0ed0) == 0x0eb80a40) {
3345 /* VRINTA, VRINTN, VRINTP, VRINTM */
3346 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
3347 return handle_vrint(insn, rd, rm, dp, rounding);
c9975a83
WN
3348 } else if ((insn & 0x0fbc0e50) == 0x0ebc0a40) {
3349 /* VCVTA, VCVTN, VCVTP, VCVTM */
3350 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
3351 return handle_vcvt(insn, rd, rm, dp, rounding);
04731fb5
WN
3352 }
3353 return 1;
3354}
3355
a1c7273b 3356/* Disassemble a VFP instruction. Returns nonzero if an error occurred
b7bcbe95 3357 (ie. an undefined instruction). */
7dcc1f89 3358static int disas_vfp_insn(DisasContext *s, uint32_t insn)
b7bcbe95
FB
3359{
3360 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
3361 int dp, veclen;
39d5492a
PM
3362 TCGv_i32 addr;
3363 TCGv_i32 tmp;
3364 TCGv_i32 tmp2;
b7bcbe95 3365
d614a513 3366 if (!arm_dc_feature(s, ARM_FEATURE_VFP)) {
40f137e1 3367 return 1;
d614a513 3368 }
40f137e1 3369
2c7ffc41
PM
3370 /* FIXME: this access check should not take precedence over UNDEF
3371 * for invalid encodings; we will generate incorrect syndrome information
3372 * for attempts to execute invalid vfp/neon encodings with FP disabled.
3373 */
9dbbc748 3374 if (s->fp_excp_el) {
2c7ffc41 3375 gen_exception_insn(s, 4, EXCP_UDEF,
7d197d2d 3376 syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
2c7ffc41
PM
3377 return 0;
3378 }
3379
5df8bac1 3380 if (!s->vfp_enabled) {
9ee6e8bb 3381 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
40f137e1
PB
3382 if ((insn & 0x0fe00fff) != 0x0ee00a10)
3383 return 1;
3384 rn = (insn >> 16) & 0xf;
a50c0f51
PM
3385 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC && rn != ARM_VFP_MVFR2
3386 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0) {
40f137e1 3387 return 1;
a50c0f51 3388 }
40f137e1 3389 }
6a57f3eb
WN
3390
3391 if (extract32(insn, 28, 4) == 0xf) {
3392 /* Encodings with T=1 (Thumb) or unconditional (ARM):
3393 * only used in v8 and above.
3394 */
7dcc1f89 3395 return disas_vfp_v8_insn(s, insn);
6a57f3eb
WN
3396 }
3397
b7bcbe95
FB
3398 dp = ((insn & 0xf00) == 0xb00);
3399 switch ((insn >> 24) & 0xf) {
3400 case 0xe:
3401 if (insn & (1 << 4)) {
3402 /* single register transfer */
b7bcbe95
FB
3403 rd = (insn >> 12) & 0xf;
3404 if (dp) {
9ee6e8bb
PB
3405 int size;
3406 int pass;
3407
3408 VFP_DREG_N(rn, insn);
3409 if (insn & 0xf)
b7bcbe95 3410 return 1;
9ee6e8bb 3411 if (insn & 0x00c00060
d614a513 3412 && !arm_dc_feature(s, ARM_FEATURE_NEON)) {
9ee6e8bb 3413 return 1;
d614a513 3414 }
9ee6e8bb
PB
3415
3416 pass = (insn >> 21) & 1;
3417 if (insn & (1 << 22)) {
3418 size = 0;
3419 offset = ((insn >> 5) & 3) * 8;
3420 } else if (insn & (1 << 5)) {
3421 size = 1;
3422 offset = (insn & (1 << 6)) ? 16 : 0;
3423 } else {
3424 size = 2;
3425 offset = 0;
3426 }
18c9b560 3427 if (insn & ARM_CP_RW_BIT) {
b7bcbe95 3428 /* vfp->arm */
ad69471c 3429 tmp = neon_load_reg(rn, pass);
9ee6e8bb
PB
3430 switch (size) {
3431 case 0:
9ee6e8bb 3432 if (offset)
ad69471c 3433 tcg_gen_shri_i32(tmp, tmp, offset);
9ee6e8bb 3434 if (insn & (1 << 23))
ad69471c 3435 gen_uxtb(tmp);
9ee6e8bb 3436 else
ad69471c 3437 gen_sxtb(tmp);
9ee6e8bb
PB
3438 break;
3439 case 1:
9ee6e8bb
PB
3440 if (insn & (1 << 23)) {
3441 if (offset) {
ad69471c 3442 tcg_gen_shri_i32(tmp, tmp, 16);
9ee6e8bb 3443 } else {
ad69471c 3444 gen_uxth(tmp);
9ee6e8bb
PB
3445 }
3446 } else {
3447 if (offset) {
ad69471c 3448 tcg_gen_sari_i32(tmp, tmp, 16);
9ee6e8bb 3449 } else {
ad69471c 3450 gen_sxth(tmp);
9ee6e8bb
PB
3451 }
3452 }
3453 break;
3454 case 2:
9ee6e8bb
PB
3455 break;
3456 }
ad69471c 3457 store_reg(s, rd, tmp);
b7bcbe95
FB
3458 } else {
3459 /* arm->vfp */
ad69471c 3460 tmp = load_reg(s, rd);
9ee6e8bb
PB
3461 if (insn & (1 << 23)) {
3462 /* VDUP */
32f91fb7
RH
3463 int vec_size = pass ? 16 : 8;
3464 tcg_gen_gvec_dup_i32(size, neon_reg_offset(rn, 0),
3465 vec_size, vec_size, tmp);
3466 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
3467 } else {
3468 /* VMOV */
3469 switch (size) {
3470 case 0:
ad69471c 3471 tmp2 = neon_load_reg(rn, pass);
d593c48e 3472 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 8);
7d1b0095 3473 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
3474 break;
3475 case 1:
ad69471c 3476 tmp2 = neon_load_reg(rn, pass);
d593c48e 3477 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 16);
7d1b0095 3478 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
3479 break;
3480 case 2:
9ee6e8bb
PB
3481 break;
3482 }
ad69471c 3483 neon_store_reg(rn, pass, tmp);
9ee6e8bb 3484 }
b7bcbe95 3485 }
9ee6e8bb
PB
3486 } else { /* !dp */
3487 if ((insn & 0x6f) != 0x00)
3488 return 1;
3489 rn = VFP_SREG_N(insn);
18c9b560 3490 if (insn & ARM_CP_RW_BIT) {
b7bcbe95
FB
3491 /* vfp->arm */
3492 if (insn & (1 << 21)) {
3493 /* system register */
40f137e1 3494 rn >>= 1;
9ee6e8bb 3495
b7bcbe95 3496 switch (rn) {
40f137e1 3497 case ARM_VFP_FPSID:
4373f3ce 3498 /* VFP2 allows access to FSID from userspace.
9ee6e8bb
PB
3499 VFP3 restricts all id registers to privileged
3500 accesses. */
3501 if (IS_USER(s)
d614a513 3502 && arm_dc_feature(s, ARM_FEATURE_VFP3)) {
9ee6e8bb 3503 return 1;
d614a513 3504 }
4373f3ce 3505 tmp = load_cpu_field(vfp.xregs[rn]);
9ee6e8bb 3506 break;
40f137e1 3507 case ARM_VFP_FPEXC:
9ee6e8bb
PB
3508 if (IS_USER(s))
3509 return 1;
4373f3ce 3510 tmp = load_cpu_field(vfp.xregs[rn]);
9ee6e8bb 3511 break;
40f137e1
PB
3512 case ARM_VFP_FPINST:
3513 case ARM_VFP_FPINST2:
9ee6e8bb
PB
3514 /* Not present in VFP3. */
3515 if (IS_USER(s)
d614a513 3516 || arm_dc_feature(s, ARM_FEATURE_VFP3)) {
9ee6e8bb 3517 return 1;
d614a513 3518 }
4373f3ce 3519 tmp = load_cpu_field(vfp.xregs[rn]);
b7bcbe95 3520 break;
40f137e1 3521 case ARM_VFP_FPSCR:
601d70b9 3522 if (rd == 15) {
4373f3ce
PB
3523 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
3524 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
3525 } else {
7d1b0095 3526 tmp = tcg_temp_new_i32();
4373f3ce
PB
3527 gen_helper_vfp_get_fpscr(tmp, cpu_env);
3528 }
b7bcbe95 3529 break;
a50c0f51 3530 case ARM_VFP_MVFR2:
d614a513 3531 if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
a50c0f51
PM
3532 return 1;
3533 }
3534 /* fall through */
9ee6e8bb
PB
3535 case ARM_VFP_MVFR0:
3536 case ARM_VFP_MVFR1:
3537 if (IS_USER(s)
d614a513 3538 || !arm_dc_feature(s, ARM_FEATURE_MVFR)) {
9ee6e8bb 3539 return 1;
d614a513 3540 }
4373f3ce 3541 tmp = load_cpu_field(vfp.xregs[rn]);
9ee6e8bb 3542 break;
b7bcbe95
FB
3543 default:
3544 return 1;
3545 }
3546 } else {
3547 gen_mov_F0_vreg(0, rn);
4373f3ce 3548 tmp = gen_vfp_mrs();
b7bcbe95
FB
3549 }
3550 if (rd == 15) {
b5ff1b31 3551 /* Set the 4 flag bits in the CPSR. */
4373f3ce 3552 gen_set_nzcv(tmp);
7d1b0095 3553 tcg_temp_free_i32(tmp);
4373f3ce
PB
3554 } else {
3555 store_reg(s, rd, tmp);
3556 }
b7bcbe95
FB
3557 } else {
3558 /* arm->vfp */
b7bcbe95 3559 if (insn & (1 << 21)) {
40f137e1 3560 rn >>= 1;
b7bcbe95
FB
3561 /* system register */
3562 switch (rn) {
40f137e1 3563 case ARM_VFP_FPSID:
9ee6e8bb
PB
3564 case ARM_VFP_MVFR0:
3565 case ARM_VFP_MVFR1:
b7bcbe95
FB
3566 /* Writes are ignored. */
3567 break;
40f137e1 3568 case ARM_VFP_FPSCR:
e4c1cfa5 3569 tmp = load_reg(s, rd);
4373f3ce 3570 gen_helper_vfp_set_fpscr(cpu_env, tmp);
7d1b0095 3571 tcg_temp_free_i32(tmp);
b5ff1b31 3572 gen_lookup_tb(s);
b7bcbe95 3573 break;
40f137e1 3574 case ARM_VFP_FPEXC:
9ee6e8bb
PB
3575 if (IS_USER(s))
3576 return 1;
71b3c3de
JR
3577 /* TODO: VFP subarchitecture support.
3578 * For now, keep the EN bit only */
e4c1cfa5 3579 tmp = load_reg(s, rd);
71b3c3de 3580 tcg_gen_andi_i32(tmp, tmp, 1 << 30);
4373f3ce 3581 store_cpu_field(tmp, vfp.xregs[rn]);
40f137e1
PB
3582 gen_lookup_tb(s);
3583 break;
3584 case ARM_VFP_FPINST:
3585 case ARM_VFP_FPINST2:
23adb861
PM
3586 if (IS_USER(s)) {
3587 return 1;
3588 }
e4c1cfa5 3589 tmp = load_reg(s, rd);
4373f3ce 3590 store_cpu_field(tmp, vfp.xregs[rn]);
40f137e1 3591 break;
b7bcbe95
FB
3592 default:
3593 return 1;
3594 }
3595 } else {
e4c1cfa5 3596 tmp = load_reg(s, rd);
4373f3ce 3597 gen_vfp_msr(tmp);
b7bcbe95
FB
3598 gen_mov_vreg_F0(0, rn);
3599 }
3600 }
3601 }
3602 } else {
3603 /* data processing */
3604 /* The opcode is in bits 23, 21, 20 and 6. */
3605 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
3606 if (dp) {
3607 if (op == 15) {
3608 /* rn is opcode */
3609 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
3610 } else {
3611 /* rn is register number */
9ee6e8bb 3612 VFP_DREG_N(rn, insn);
b7bcbe95
FB
3613 }
3614
239c20c7
WN
3615 if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18) ||
3616 ((rn & 0x1e) == 0x6))) {
3617 /* Integer or single/half precision destination. */
9ee6e8bb 3618 rd = VFP_SREG_D(insn);
b7bcbe95 3619 } else {
9ee6e8bb 3620 VFP_DREG_D(rd, insn);
b7bcbe95 3621 }
04595bf6 3622 if (op == 15 &&
239c20c7
WN
3623 (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14) ||
3624 ((rn & 0x1e) == 0x4))) {
3625 /* VCVT from int or half precision is always from S reg
3626 * regardless of dp bit. VCVT with immediate frac_bits
3627 * has same format as SREG_M.
04595bf6
PM
3628 */
3629 rm = VFP_SREG_M(insn);
b7bcbe95 3630 } else {
9ee6e8bb 3631 VFP_DREG_M(rm, insn);
b7bcbe95
FB
3632 }
3633 } else {
9ee6e8bb 3634 rn = VFP_SREG_N(insn);
b7bcbe95
FB
3635 if (op == 15 && rn == 15) {
3636 /* Double precision destination. */
9ee6e8bb
PB
3637 VFP_DREG_D(rd, insn);
3638 } else {
3639 rd = VFP_SREG_D(insn);
3640 }
04595bf6
PM
3641 /* NB that we implicitly rely on the encoding for the frac_bits
3642 * in VCVT of fixed to float being the same as that of an SREG_M
3643 */
9ee6e8bb 3644 rm = VFP_SREG_M(insn);
b7bcbe95
FB
3645 }
3646
69d1fc22 3647 veclen = s->vec_len;
b7bcbe95
FB
3648 if (op == 15 && rn > 3)
3649 veclen = 0;
3650
3651 /* Shut up compiler warnings. */
3652 delta_m = 0;
3653 delta_d = 0;
3654 bank_mask = 0;
3b46e624 3655
b7bcbe95
FB
3656 if (veclen > 0) {
3657 if (dp)
3658 bank_mask = 0xc;
3659 else
3660 bank_mask = 0x18;
3661
3662 /* Figure out what type of vector operation this is. */
3663 if ((rd & bank_mask) == 0) {
3664 /* scalar */
3665 veclen = 0;
3666 } else {
3667 if (dp)
69d1fc22 3668 delta_d = (s->vec_stride >> 1) + 1;
b7bcbe95 3669 else
69d1fc22 3670 delta_d = s->vec_stride + 1;
b7bcbe95
FB
3671
3672 if ((rm & bank_mask) == 0) {
3673 /* mixed scalar/vector */
3674 delta_m = 0;
3675 } else {
3676 /* vector */
3677 delta_m = delta_d;
3678 }
3679 }
3680 }
3681
3682 /* Load the initial operands. */
3683 if (op == 15) {
3684 switch (rn) {
3685 case 16:
3686 case 17:
3687 /* Integer source */
3688 gen_mov_F0_vreg(0, rm);
3689 break;
3690 case 8:
3691 case 9:
3692 /* Compare */
3693 gen_mov_F0_vreg(dp, rd);
3694 gen_mov_F1_vreg(dp, rm);
3695 break;
3696 case 10:
3697 case 11:
3698 /* Compare with zero */
3699 gen_mov_F0_vreg(dp, rd);
3700 gen_vfp_F1_ld0(dp);
3701 break;
9ee6e8bb
PB
3702 case 20:
3703 case 21:
3704 case 22:
3705 case 23:
644ad806
PB
3706 case 28:
3707 case 29:
3708 case 30:
3709 case 31:
9ee6e8bb
PB
3710 /* Source and destination the same. */
3711 gen_mov_F0_vreg(dp, rd);
3712 break;
6e0c0ed1
PM
3713 case 4:
3714 case 5:
3715 case 6:
3716 case 7:
239c20c7
WN
3717 /* VCVTB, VCVTT: only present with the halfprec extension
3718 * UNPREDICTABLE if bit 8 is set prior to ARMv8
3719 * (we choose to UNDEF)
6e0c0ed1 3720 */
d614a513
PM
3721 if ((dp && !arm_dc_feature(s, ARM_FEATURE_V8)) ||
3722 !arm_dc_feature(s, ARM_FEATURE_VFP_FP16)) {
6e0c0ed1
PM
3723 return 1;
3724 }
239c20c7
WN
3725 if (!extract32(rn, 1, 1)) {
3726 /* Half precision source. */
3727 gen_mov_F0_vreg(0, rm);
3728 break;
3729 }
6e0c0ed1 3730 /* Otherwise fall through */
b7bcbe95
FB
3731 default:
3732 /* One source operand. */
3733 gen_mov_F0_vreg(dp, rm);
9ee6e8bb 3734 break;
b7bcbe95
FB
3735 }
3736 } else {
3737 /* Two source operands. */
3738 gen_mov_F0_vreg(dp, rn);
3739 gen_mov_F1_vreg(dp, rm);
3740 }
3741
3742 for (;;) {
3743 /* Perform the calculation. */
3744 switch (op) {
605a6aed
PM
3745 case 0: /* VMLA: fd + (fn * fm) */
3746 /* Note that order of inputs to the add matters for NaNs */
3747 gen_vfp_F1_mul(dp);
3748 gen_mov_F0_vreg(dp, rd);
b7bcbe95
FB
3749 gen_vfp_add(dp);
3750 break;
605a6aed 3751 case 1: /* VMLS: fd + -(fn * fm) */
b7bcbe95 3752 gen_vfp_mul(dp);
605a6aed
PM
3753 gen_vfp_F1_neg(dp);
3754 gen_mov_F0_vreg(dp, rd);
b7bcbe95
FB
3755 gen_vfp_add(dp);
3756 break;
605a6aed
PM
3757 case 2: /* VNMLS: -fd + (fn * fm) */
3758 /* Note that it isn't valid to replace (-A + B) with (B - A)
3759 * or similar plausible looking simplifications
3760 * because this will give wrong results for NaNs.
3761 */
3762 gen_vfp_F1_mul(dp);
3763 gen_mov_F0_vreg(dp, rd);
3764 gen_vfp_neg(dp);
3765 gen_vfp_add(dp);
b7bcbe95 3766 break;
605a6aed 3767 case 3: /* VNMLA: -fd + -(fn * fm) */
b7bcbe95 3768 gen_vfp_mul(dp);
605a6aed
PM
3769 gen_vfp_F1_neg(dp);
3770 gen_mov_F0_vreg(dp, rd);
b7bcbe95 3771 gen_vfp_neg(dp);
605a6aed 3772 gen_vfp_add(dp);
b7bcbe95
FB
3773 break;
3774 case 4: /* mul: fn * fm */
3775 gen_vfp_mul(dp);
3776 break;
3777 case 5: /* nmul: -(fn * fm) */
3778 gen_vfp_mul(dp);
3779 gen_vfp_neg(dp);
3780 break;
3781 case 6: /* add: fn + fm */
3782 gen_vfp_add(dp);
3783 break;
3784 case 7: /* sub: fn - fm */
3785 gen_vfp_sub(dp);
3786 break;
3787 case 8: /* div: fn / fm */
3788 gen_vfp_div(dp);
3789 break;
da97f52c
PM
3790 case 10: /* VFNMA : fd = muladd(-fd, fn, fm) */
3791 case 11: /* VFNMS : fd = muladd(-fd, -fn, fm) */
3792 case 12: /* VFMA : fd = muladd( fd, fn, fm) */
3793 case 13: /* VFMS : fd = muladd( fd, -fn, fm) */
3794 /* These are fused multiply-add, and must be done as one
3795 * floating point operation with no rounding between the
3796 * multiplication and addition steps.
3797 * NB that doing the negations here as separate steps is
3798 * correct : an input NaN should come out with its sign bit
3799 * flipped if it is a negated-input.
3800 */
d614a513 3801 if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
da97f52c
PM
3802 return 1;
3803 }
3804 if (dp) {
3805 TCGv_ptr fpst;
3806 TCGv_i64 frd;
3807 if (op & 1) {
3808 /* VFNMS, VFMS */
3809 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
3810 }
3811 frd = tcg_temp_new_i64();
3812 tcg_gen_ld_f64(frd, cpu_env, vfp_reg_offset(dp, rd));
3813 if (op & 2) {
3814 /* VFNMA, VFNMS */
3815 gen_helper_vfp_negd(frd, frd);
3816 }
3817 fpst = get_fpstatus_ptr(0);
3818 gen_helper_vfp_muladdd(cpu_F0d, cpu_F0d,
3819 cpu_F1d, frd, fpst);
3820 tcg_temp_free_ptr(fpst);
3821 tcg_temp_free_i64(frd);
3822 } else {
3823 TCGv_ptr fpst;
3824 TCGv_i32 frd;
3825 if (op & 1) {
3826 /* VFNMS, VFMS */
3827 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
3828 }
3829 frd = tcg_temp_new_i32();
3830 tcg_gen_ld_f32(frd, cpu_env, vfp_reg_offset(dp, rd));
3831 if (op & 2) {
3832 gen_helper_vfp_negs(frd, frd);
3833 }
3834 fpst = get_fpstatus_ptr(0);
3835 gen_helper_vfp_muladds(cpu_F0s, cpu_F0s,
3836 cpu_F1s, frd, fpst);
3837 tcg_temp_free_ptr(fpst);
3838 tcg_temp_free_i32(frd);
3839 }
3840 break;
9ee6e8bb 3841 case 14: /* fconst */
d614a513
PM
3842 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3843 return 1;
3844 }
9ee6e8bb
PB
3845
3846 n = (insn << 12) & 0x80000000;
3847 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3848 if (dp) {
3849 if (i & 0x40)
3850 i |= 0x3f80;
3851 else
3852 i |= 0x4000;
3853 n |= i << 16;
4373f3ce 3854 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
9ee6e8bb
PB
3855 } else {
3856 if (i & 0x40)
3857 i |= 0x780;
3858 else
3859 i |= 0x800;
3860 n |= i << 19;
5b340b51 3861 tcg_gen_movi_i32(cpu_F0s, n);
9ee6e8bb 3862 }
9ee6e8bb 3863 break;
b7bcbe95
FB
3864 case 15: /* extension space */
3865 switch (rn) {
3866 case 0: /* cpy */
3867 /* no-op */
3868 break;
3869 case 1: /* abs */
3870 gen_vfp_abs(dp);
3871 break;
3872 case 2: /* neg */
3873 gen_vfp_neg(dp);
3874 break;
3875 case 3: /* sqrt */
3876 gen_vfp_sqrt(dp);
3877 break;
239c20c7 3878 case 4: /* vcvtb.f32.f16, vcvtb.f64.f16 */
486624fc
AB
3879 {
3880 TCGv_ptr fpst = get_fpstatus_ptr(false);
3881 TCGv_i32 ahp_mode = get_ahp_flag();
60011498
PB
3882 tmp = gen_vfp_mrs();
3883 tcg_gen_ext16u_i32(tmp, tmp);
239c20c7
WN
3884 if (dp) {
3885 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
486624fc 3886 fpst, ahp_mode);
239c20c7
WN
3887 } else {
3888 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
486624fc 3889 fpst, ahp_mode);
239c20c7 3890 }
486624fc
AB
3891 tcg_temp_free_i32(ahp_mode);
3892 tcg_temp_free_ptr(fpst);
7d1b0095 3893 tcg_temp_free_i32(tmp);
60011498 3894 break;
486624fc 3895 }
239c20c7 3896 case 5: /* vcvtt.f32.f16, vcvtt.f64.f16 */
486624fc
AB
3897 {
3898 TCGv_ptr fpst = get_fpstatus_ptr(false);
3899 TCGv_i32 ahp = get_ahp_flag();
60011498
PB
3900 tmp = gen_vfp_mrs();
3901 tcg_gen_shri_i32(tmp, tmp, 16);
239c20c7
WN
3902 if (dp) {
3903 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
486624fc 3904 fpst, ahp);
239c20c7
WN
3905 } else {
3906 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
486624fc 3907 fpst, ahp);
239c20c7 3908 }
7d1b0095 3909 tcg_temp_free_i32(tmp);
486624fc
AB
3910 tcg_temp_free_i32(ahp);
3911 tcg_temp_free_ptr(fpst);
60011498 3912 break;
486624fc 3913 }
239c20c7 3914 case 6: /* vcvtb.f16.f32, vcvtb.f16.f64 */
486624fc
AB
3915 {
3916 TCGv_ptr fpst = get_fpstatus_ptr(false);
3917 TCGv_i32 ahp = get_ahp_flag();
7d1b0095 3918 tmp = tcg_temp_new_i32();
486624fc 3919
239c20c7
WN
3920 if (dp) {
3921 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
486624fc 3922 fpst, ahp);
239c20c7
WN
3923 } else {
3924 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
486624fc 3925 fpst, ahp);
239c20c7 3926 }
486624fc
AB
3927 tcg_temp_free_i32(ahp);
3928 tcg_temp_free_ptr(fpst);
60011498
PB
3929 gen_mov_F0_vreg(0, rd);
3930 tmp2 = gen_vfp_mrs();
3931 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3932 tcg_gen_or_i32(tmp, tmp, tmp2);
7d1b0095 3933 tcg_temp_free_i32(tmp2);
60011498
PB
3934 gen_vfp_msr(tmp);
3935 break;
486624fc 3936 }
239c20c7 3937 case 7: /* vcvtt.f16.f32, vcvtt.f16.f64 */
486624fc
AB
3938 {
3939 TCGv_ptr fpst = get_fpstatus_ptr(false);
3940 TCGv_i32 ahp = get_ahp_flag();
7d1b0095 3941 tmp = tcg_temp_new_i32();
239c20c7
WN
3942 if (dp) {
3943 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
486624fc 3944 fpst, ahp);
239c20c7
WN
3945 } else {
3946 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
486624fc 3947 fpst, ahp);
239c20c7 3948 }
486624fc
AB
3949 tcg_temp_free_i32(ahp);
3950 tcg_temp_free_ptr(fpst);
60011498
PB
3951 tcg_gen_shli_i32(tmp, tmp, 16);
3952 gen_mov_F0_vreg(0, rd);
3953 tmp2 = gen_vfp_mrs();
3954 tcg_gen_ext16u_i32(tmp2, tmp2);
3955 tcg_gen_or_i32(tmp, tmp, tmp2);
7d1b0095 3956 tcg_temp_free_i32(tmp2);
60011498
PB
3957 gen_vfp_msr(tmp);
3958 break;
486624fc 3959 }
b7bcbe95
FB
3960 case 8: /* cmp */
3961 gen_vfp_cmp(dp);
3962 break;
3963 case 9: /* cmpe */
3964 gen_vfp_cmpe(dp);
3965 break;
3966 case 10: /* cmpz */
3967 gen_vfp_cmp(dp);
3968 break;
3969 case 11: /* cmpez */
3970 gen_vfp_F1_ld0(dp);
3971 gen_vfp_cmpe(dp);
3972 break;
664c6733
WN
3973 case 12: /* vrintr */
3974 {
3975 TCGv_ptr fpst = get_fpstatus_ptr(0);
3976 if (dp) {
3977 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
3978 } else {
3979 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
3980 }
3981 tcg_temp_free_ptr(fpst);
3982 break;
3983 }
a290c62a
WN
3984 case 13: /* vrintz */
3985 {
3986 TCGv_ptr fpst = get_fpstatus_ptr(0);
3987 TCGv_i32 tcg_rmode;
3988 tcg_rmode = tcg_const_i32(float_round_to_zero);
9b049916 3989 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
a290c62a
WN
3990 if (dp) {
3991 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
3992 } else {
3993 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
3994 }
9b049916 3995 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
a290c62a
WN
3996 tcg_temp_free_i32(tcg_rmode);
3997 tcg_temp_free_ptr(fpst);
3998 break;
3999 }
4e82bc01
WN
4000 case 14: /* vrintx */
4001 {
4002 TCGv_ptr fpst = get_fpstatus_ptr(0);
4003 if (dp) {
4004 gen_helper_rintd_exact(cpu_F0d, cpu_F0d, fpst);
4005 } else {
4006 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpst);
4007 }
4008 tcg_temp_free_ptr(fpst);
4009 break;
4010 }
b7bcbe95
FB
4011 case 15: /* single<->double conversion */
4012 if (dp)
4373f3ce 4013 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
b7bcbe95 4014 else
4373f3ce 4015 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
b7bcbe95
FB
4016 break;
4017 case 16: /* fuito */
5500b06c 4018 gen_vfp_uito(dp, 0);
b7bcbe95
FB
4019 break;
4020 case 17: /* fsito */
5500b06c 4021 gen_vfp_sito(dp, 0);
b7bcbe95 4022 break;
9ee6e8bb 4023 case 20: /* fshto */
d614a513
PM
4024 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
4025 return 1;
4026 }
5500b06c 4027 gen_vfp_shto(dp, 16 - rm, 0);
9ee6e8bb
PB
4028 break;
4029 case 21: /* fslto */
d614a513
PM
4030 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
4031 return 1;
4032 }
5500b06c 4033 gen_vfp_slto(dp, 32 - rm, 0);
9ee6e8bb
PB
4034 break;
4035 case 22: /* fuhto */
d614a513
PM
4036 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
4037 return 1;
4038 }
5500b06c 4039 gen_vfp_uhto(dp, 16 - rm, 0);
9ee6e8bb
PB
4040 break;
4041 case 23: /* fulto */
d614a513
PM
4042 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
4043 return 1;
4044 }
5500b06c 4045 gen_vfp_ulto(dp, 32 - rm, 0);
9ee6e8bb 4046 break;
b7bcbe95 4047 case 24: /* ftoui */
5500b06c 4048 gen_vfp_toui(dp, 0);
b7bcbe95
FB
4049 break;
4050 case 25: /* ftouiz */
5500b06c 4051 gen_vfp_touiz(dp, 0);
b7bcbe95
FB
4052 break;
4053 case 26: /* ftosi */
5500b06c 4054 gen_vfp_tosi(dp, 0);
b7bcbe95
FB
4055 break;
4056 case 27: /* ftosiz */
5500b06c 4057 gen_vfp_tosiz(dp, 0);
b7bcbe95 4058 break;
9ee6e8bb 4059 case 28: /* ftosh */
d614a513
PM
4060 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
4061 return 1;
4062 }
5500b06c 4063 gen_vfp_tosh(dp, 16 - rm, 0);
9ee6e8bb
PB
4064 break;
4065 case 29: /* ftosl */
d614a513
PM
4066 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
4067 return 1;
4068 }
5500b06c 4069 gen_vfp_tosl(dp, 32 - rm, 0);
9ee6e8bb
PB
4070 break;
4071 case 30: /* ftouh */
d614a513
PM
4072 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
4073 return 1;
4074 }
5500b06c 4075 gen_vfp_touh(dp, 16 - rm, 0);
9ee6e8bb
PB
4076 break;
4077 case 31: /* ftoul */
d614a513
PM
4078 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
4079 return 1;
4080 }
5500b06c 4081 gen_vfp_toul(dp, 32 - rm, 0);
9ee6e8bb 4082 break;
b7bcbe95 4083 default: /* undefined */
b7bcbe95
FB
4084 return 1;
4085 }
4086 break;
4087 default: /* undefined */
b7bcbe95
FB
4088 return 1;
4089 }
4090
4091 /* Write back the result. */
239c20c7
WN
4092 if (op == 15 && (rn >= 8 && rn <= 11)) {
4093 /* Comparison, do nothing. */
4094 } else if (op == 15 && dp && ((rn & 0x1c) == 0x18 ||
4095 (rn & 0x1e) == 0x6)) {
4096 /* VCVT double to int: always integer result.
4097 * VCVT double to half precision is always a single
4098 * precision result.
4099 */
b7bcbe95 4100 gen_mov_vreg_F0(0, rd);
239c20c7 4101 } else if (op == 15 && rn == 15) {
b7bcbe95
FB
4102 /* conversion */
4103 gen_mov_vreg_F0(!dp, rd);
239c20c7 4104 } else {
b7bcbe95 4105 gen_mov_vreg_F0(dp, rd);
239c20c7 4106 }
b7bcbe95
FB
4107
4108 /* break out of the loop if we have finished */
4109 if (veclen == 0)
4110 break;
4111
4112 if (op == 15 && delta_m == 0) {
4113 /* single source one-many */
4114 while (veclen--) {
4115 rd = ((rd + delta_d) & (bank_mask - 1))
4116 | (rd & bank_mask);
4117 gen_mov_vreg_F0(dp, rd);
4118 }
4119 break;
4120 }
4121 /* Setup the next operands. */
4122 veclen--;
4123 rd = ((rd + delta_d) & (bank_mask - 1))
4124 | (rd & bank_mask);
4125
4126 if (op == 15) {
4127 /* One source operand. */
4128 rm = ((rm + delta_m) & (bank_mask - 1))
4129 | (rm & bank_mask);
4130 gen_mov_F0_vreg(dp, rm);
4131 } else {
4132 /* Two source operands. */
4133 rn = ((rn + delta_d) & (bank_mask - 1))
4134 | (rn & bank_mask);
4135 gen_mov_F0_vreg(dp, rn);
4136 if (delta_m) {
4137 rm = ((rm + delta_m) & (bank_mask - 1))
4138 | (rm & bank_mask);
4139 gen_mov_F1_vreg(dp, rm);
4140 }
4141 }
4142 }
4143 }
4144 break;
4145 case 0xc:
4146 case 0xd:
8387da81 4147 if ((insn & 0x03e00000) == 0x00400000) {
b7bcbe95
FB
4148 /* two-register transfer */
4149 rn = (insn >> 16) & 0xf;
4150 rd = (insn >> 12) & 0xf;
4151 if (dp) {
9ee6e8bb
PB
4152 VFP_DREG_M(rm, insn);
4153 } else {
4154 rm = VFP_SREG_M(insn);
4155 }
b7bcbe95 4156
18c9b560 4157 if (insn & ARM_CP_RW_BIT) {
b7bcbe95
FB
4158 /* vfp->arm */
4159 if (dp) {
4373f3ce
PB
4160 gen_mov_F0_vreg(0, rm * 2);
4161 tmp = gen_vfp_mrs();
4162 store_reg(s, rd, tmp);
4163 gen_mov_F0_vreg(0, rm * 2 + 1);
4164 tmp = gen_vfp_mrs();
4165 store_reg(s, rn, tmp);
b7bcbe95
FB
4166 } else {
4167 gen_mov_F0_vreg(0, rm);
4373f3ce 4168 tmp = gen_vfp_mrs();
8387da81 4169 store_reg(s, rd, tmp);
b7bcbe95 4170 gen_mov_F0_vreg(0, rm + 1);
4373f3ce 4171 tmp = gen_vfp_mrs();
8387da81 4172 store_reg(s, rn, tmp);
b7bcbe95
FB
4173 }
4174 } else {
4175 /* arm->vfp */
4176 if (dp) {
4373f3ce
PB
4177 tmp = load_reg(s, rd);
4178 gen_vfp_msr(tmp);
4179 gen_mov_vreg_F0(0, rm * 2);
4180 tmp = load_reg(s, rn);
4181 gen_vfp_msr(tmp);
4182 gen_mov_vreg_F0(0, rm * 2 + 1);
b7bcbe95 4183 } else {
8387da81 4184 tmp = load_reg(s, rd);
4373f3ce 4185 gen_vfp_msr(tmp);
b7bcbe95 4186 gen_mov_vreg_F0(0, rm);
8387da81 4187 tmp = load_reg(s, rn);
4373f3ce 4188 gen_vfp_msr(tmp);
b7bcbe95
FB
4189 gen_mov_vreg_F0(0, rm + 1);
4190 }
4191 }
4192 } else {
4193 /* Load/store */
4194 rn = (insn >> 16) & 0xf;
4195 if (dp)
9ee6e8bb 4196 VFP_DREG_D(rd, insn);
b7bcbe95 4197 else
9ee6e8bb 4198 rd = VFP_SREG_D(insn);
b7bcbe95
FB
4199 if ((insn & 0x01200000) == 0x01000000) {
4200 /* Single load/store */
4201 offset = (insn & 0xff) << 2;
4202 if ((insn & (1 << 23)) == 0)
4203 offset = -offset;
934814f1
PM
4204 if (s->thumb && rn == 15) {
4205 /* This is actually UNPREDICTABLE */
4206 addr = tcg_temp_new_i32();
4207 tcg_gen_movi_i32(addr, s->pc & ~2);
4208 } else {
4209 addr = load_reg(s, rn);
4210 }
312eea9f 4211 tcg_gen_addi_i32(addr, addr, offset);
b7bcbe95 4212 if (insn & (1 << 20)) {
312eea9f 4213 gen_vfp_ld(s, dp, addr);
b7bcbe95
FB
4214 gen_mov_vreg_F0(dp, rd);
4215 } else {
4216 gen_mov_F0_vreg(dp, rd);
312eea9f 4217 gen_vfp_st(s, dp, addr);
b7bcbe95 4218 }
7d1b0095 4219 tcg_temp_free_i32(addr);
b7bcbe95
FB
4220 } else {
4221 /* load/store multiple */
934814f1 4222 int w = insn & (1 << 21);
b7bcbe95
FB
4223 if (dp)
4224 n = (insn >> 1) & 0x7f;
4225 else
4226 n = insn & 0xff;
4227
934814f1
PM
4228 if (w && !(((insn >> 23) ^ (insn >> 24)) & 1)) {
4229 /* P == U , W == 1 => UNDEF */
4230 return 1;
4231 }
4232 if (n == 0 || (rd + n) > 32 || (dp && n > 16)) {
4233 /* UNPREDICTABLE cases for bad immediates: we choose to
4234 * UNDEF to avoid generating huge numbers of TCG ops
4235 */
4236 return 1;
4237 }
4238 if (rn == 15 && w) {
4239 /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
4240 return 1;
4241 }
4242
4243 if (s->thumb && rn == 15) {
4244 /* This is actually UNPREDICTABLE */
4245 addr = tcg_temp_new_i32();
4246 tcg_gen_movi_i32(addr, s->pc & ~2);
4247 } else {
4248 addr = load_reg(s, rn);
4249 }
b7bcbe95 4250 if (insn & (1 << 24)) /* pre-decrement */
312eea9f 4251 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
b7bcbe95 4252
8a954faf
PM
4253 if (s->v8m_stackcheck && rn == 13 && w) {
4254 /*
4255 * Here 'addr' is the lowest address we will store to,
4256 * and is either the old SP (if post-increment) or
4257 * the new SP (if pre-decrement). For post-increment
4258 * where the old value is below the limit and the new
4259 * value is above, it is UNKNOWN whether the limit check
4260 * triggers; we choose to trigger.
4261 */
4262 gen_helper_v8m_stackcheck(cpu_env, addr);
4263 }
4264
b7bcbe95
FB
4265 if (dp)
4266 offset = 8;
4267 else
4268 offset = 4;
4269 for (i = 0; i < n; i++) {
18c9b560 4270 if (insn & ARM_CP_RW_BIT) {
b7bcbe95 4271 /* load */
312eea9f 4272 gen_vfp_ld(s, dp, addr);
b7bcbe95
FB
4273 gen_mov_vreg_F0(dp, rd + i);
4274 } else {
4275 /* store */
4276 gen_mov_F0_vreg(dp, rd + i);
312eea9f 4277 gen_vfp_st(s, dp, addr);
b7bcbe95 4278 }
312eea9f 4279 tcg_gen_addi_i32(addr, addr, offset);
b7bcbe95 4280 }
934814f1 4281 if (w) {
b7bcbe95
FB
4282 /* writeback */
4283 if (insn & (1 << 24))
4284 offset = -offset * n;
4285 else if (dp && (insn & 1))
4286 offset = 4;
4287 else
4288 offset = 0;
4289
4290 if (offset != 0)
312eea9f
FN
4291 tcg_gen_addi_i32(addr, addr, offset);
4292 store_reg(s, rn, addr);
4293 } else {
7d1b0095 4294 tcg_temp_free_i32(addr);
b7bcbe95
FB
4295 }
4296 }
4297 }
4298 break;
4299 default:
4300 /* Should never happen. */
4301 return 1;
4302 }
4303 return 0;
4304}
4305
90aa39a1 4306static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
c53be334 4307{
90aa39a1 4308#ifndef CONFIG_USER_ONLY
dcba3a8d 4309 return (s->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
90aa39a1
SF
4310 ((s->pc - 1) & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
4311#else
4312 return true;
4313#endif
4314}
6e256c93 4315
8a6b28c7
EC
4316static void gen_goto_ptr(void)
4317{
7f11636d 4318 tcg_gen_lookup_and_goto_ptr();
8a6b28c7
EC
4319}
4320
4cae8f56
AB
4321/* This will end the TB but doesn't guarantee we'll return to
4322 * cpu_loop_exec. Any live exit_requests will be processed as we
4323 * enter the next TB.
4324 */
8a6b28c7 4325static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
90aa39a1
SF
4326{
4327 if (use_goto_tb(s, dest)) {
57fec1fe 4328 tcg_gen_goto_tb(n);
eaed129d 4329 gen_set_pc_im(s, dest);
07ea28b4 4330 tcg_gen_exit_tb(s->base.tb, n);
6e256c93 4331 } else {
eaed129d 4332 gen_set_pc_im(s, dest);
8a6b28c7 4333 gen_goto_ptr();
6e256c93 4334 }
dcba3a8d 4335 s->base.is_jmp = DISAS_NORETURN;
c53be334
FB
4336}
4337
8aaca4c0
FB
4338static inline void gen_jmp (DisasContext *s, uint32_t dest)
4339{
b636649f 4340 if (unlikely(is_singlestepping(s))) {
8aaca4c0 4341 /* An indirect jump so that we still trigger the debug exception. */
5899f386 4342 if (s->thumb)
d9ba4830
PB
4343 dest |= 1;
4344 gen_bx_im(s, dest);
8aaca4c0 4345 } else {
6e256c93 4346 gen_goto_tb(s, 0, dest);
8aaca4c0
FB
4347 }
4348}
4349
39d5492a 4350static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
b5ff1b31 4351{
ee097184 4352 if (x)
d9ba4830 4353 tcg_gen_sari_i32(t0, t0, 16);
b5ff1b31 4354 else
d9ba4830 4355 gen_sxth(t0);
ee097184 4356 if (y)
d9ba4830 4357 tcg_gen_sari_i32(t1, t1, 16);
b5ff1b31 4358 else
d9ba4830
PB
4359 gen_sxth(t1);
4360 tcg_gen_mul_i32(t0, t0, t1);
b5ff1b31
FB
4361}
4362
4363/* Return the mask of PSR bits set by a MSR instruction. */
7dcc1f89
PM
4364static uint32_t msr_mask(DisasContext *s, int flags, int spsr)
4365{
b5ff1b31
FB
4366 uint32_t mask;
4367
4368 mask = 0;
4369 if (flags & (1 << 0))
4370 mask |= 0xff;
4371 if (flags & (1 << 1))
4372 mask |= 0xff00;
4373 if (flags & (1 << 2))
4374 mask |= 0xff0000;
4375 if (flags & (1 << 3))
4376 mask |= 0xff000000;
9ee6e8bb 4377
2ae23e75 4378 /* Mask out undefined bits. */
9ee6e8bb 4379 mask &= ~CPSR_RESERVED;
d614a513 4380 if (!arm_dc_feature(s, ARM_FEATURE_V4T)) {
be5e7a76 4381 mask &= ~CPSR_T;
d614a513
PM
4382 }
4383 if (!arm_dc_feature(s, ARM_FEATURE_V5)) {
be5e7a76 4384 mask &= ~CPSR_Q; /* V5TE in reality*/
d614a513
PM
4385 }
4386 if (!arm_dc_feature(s, ARM_FEATURE_V6)) {
e160c51c 4387 mask &= ~(CPSR_E | CPSR_GE);
d614a513
PM
4388 }
4389 if (!arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
e160c51c 4390 mask &= ~CPSR_IT;
d614a513 4391 }
4051e12c
PM
4392 /* Mask out execution state and reserved bits. */
4393 if (!spsr) {
4394 mask &= ~(CPSR_EXEC | CPSR_RESERVED);
4395 }
b5ff1b31
FB
4396 /* Mask out privileged bits. */
4397 if (IS_USER(s))
9ee6e8bb 4398 mask &= CPSR_USER;
b5ff1b31
FB
4399 return mask;
4400}
4401
2fbac54b 4402/* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
39d5492a 4403static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
b5ff1b31 4404{
39d5492a 4405 TCGv_i32 tmp;
b5ff1b31
FB
4406 if (spsr) {
4407 /* ??? This is also undefined in system mode. */
4408 if (IS_USER(s))
4409 return 1;
d9ba4830
PB
4410
4411 tmp = load_cpu_field(spsr);
4412 tcg_gen_andi_i32(tmp, tmp, ~mask);
2fbac54b
FN
4413 tcg_gen_andi_i32(t0, t0, mask);
4414 tcg_gen_or_i32(tmp, tmp, t0);
d9ba4830 4415 store_cpu_field(tmp, spsr);
b5ff1b31 4416 } else {
2fbac54b 4417 gen_set_cpsr(t0, mask);
b5ff1b31 4418 }
7d1b0095 4419 tcg_temp_free_i32(t0);
b5ff1b31
FB
4420 gen_lookup_tb(s);
4421 return 0;
4422}
4423
2fbac54b
FN
4424/* Returns nonzero if access to the PSR is not permitted. */
4425static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
4426{
39d5492a 4427 TCGv_i32 tmp;
7d1b0095 4428 tmp = tcg_temp_new_i32();
2fbac54b
FN
4429 tcg_gen_movi_i32(tmp, val);
4430 return gen_set_psr(s, mask, spsr, tmp);
4431}
4432
8bfd0550
PM
4433static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
4434 int *tgtmode, int *regno)
4435{
4436 /* Decode the r and sysm fields of MSR/MRS banked accesses into
4437 * the target mode and register number, and identify the various
4438 * unpredictable cases.
4439 * MSR (banked) and MRS (banked) are CONSTRAINED UNPREDICTABLE if:
4440 * + executed in user mode
4441 * + using R15 as the src/dest register
4442 * + accessing an unimplemented register
4443 * + accessing a register that's inaccessible at current PL/security state*
4444 * + accessing a register that you could access with a different insn
4445 * We choose to UNDEF in all these cases.
4446 * Since we don't know which of the various AArch32 modes we are in
4447 * we have to defer some checks to runtime.
4448 * Accesses to Monitor mode registers from Secure EL1 (which implies
4449 * that EL3 is AArch64) must trap to EL3.
4450 *
4451 * If the access checks fail this function will emit code to take
4452 * an exception and return false. Otherwise it will return true,
4453 * and set *tgtmode and *regno appropriately.
4454 */
4455 int exc_target = default_exception_el(s);
4456
4457 /* These instructions are present only in ARMv8, or in ARMv7 with the
4458 * Virtualization Extensions.
4459 */
4460 if (!arm_dc_feature(s, ARM_FEATURE_V8) &&
4461 !arm_dc_feature(s, ARM_FEATURE_EL2)) {
4462 goto undef;
4463 }
4464
4465 if (IS_USER(s) || rn == 15) {
4466 goto undef;
4467 }
4468
4469 /* The table in the v8 ARM ARM section F5.2.3 describes the encoding
4470 * of registers into (r, sysm).
4471 */
4472 if (r) {
4473 /* SPSRs for other modes */
4474 switch (sysm) {
4475 case 0xe: /* SPSR_fiq */
4476 *tgtmode = ARM_CPU_MODE_FIQ;
4477 break;
4478 case 0x10: /* SPSR_irq */
4479 *tgtmode = ARM_CPU_MODE_IRQ;
4480 break;
4481 case 0x12: /* SPSR_svc */
4482 *tgtmode = ARM_CPU_MODE_SVC;
4483 break;
4484 case 0x14: /* SPSR_abt */
4485 *tgtmode = ARM_CPU_MODE_ABT;
4486 break;
4487 case 0x16: /* SPSR_und */
4488 *tgtmode = ARM_CPU_MODE_UND;
4489 break;
4490 case 0x1c: /* SPSR_mon */
4491 *tgtmode = ARM_CPU_MODE_MON;
4492 break;
4493 case 0x1e: /* SPSR_hyp */
4494 *tgtmode = ARM_CPU_MODE_HYP;
4495 break;
4496 default: /* unallocated */
4497 goto undef;
4498 }
4499 /* We arbitrarily assign SPSR a register number of 16. */
4500 *regno = 16;
4501 } else {
4502 /* general purpose registers for other modes */
4503 switch (sysm) {
4504 case 0x0 ... 0x6: /* 0b00xxx : r8_usr ... r14_usr */
4505 *tgtmode = ARM_CPU_MODE_USR;
4506 *regno = sysm + 8;
4507 break;
4508 case 0x8 ... 0xe: /* 0b01xxx : r8_fiq ... r14_fiq */
4509 *tgtmode = ARM_CPU_MODE_FIQ;
4510 *regno = sysm;
4511 break;
4512 case 0x10 ... 0x11: /* 0b1000x : r14_irq, r13_irq */
4513 *tgtmode = ARM_CPU_MODE_IRQ;
4514 *regno = sysm & 1 ? 13 : 14;
4515 break;
4516 case 0x12 ... 0x13: /* 0b1001x : r14_svc, r13_svc */
4517 *tgtmode = ARM_CPU_MODE_SVC;
4518 *regno = sysm & 1 ? 13 : 14;
4519 break;
4520 case 0x14 ... 0x15: /* 0b1010x : r14_abt, r13_abt */
4521 *tgtmode = ARM_CPU_MODE_ABT;
4522 *regno = sysm & 1 ? 13 : 14;
4523 break;
4524 case 0x16 ... 0x17: /* 0b1011x : r14_und, r13_und */
4525 *tgtmode = ARM_CPU_MODE_UND;
4526 *regno = sysm & 1 ? 13 : 14;
4527 break;
4528 case 0x1c ... 0x1d: /* 0b1110x : r14_mon, r13_mon */
4529 *tgtmode = ARM_CPU_MODE_MON;
4530 *regno = sysm & 1 ? 13 : 14;
4531 break;
4532 case 0x1e ... 0x1f: /* 0b1111x : elr_hyp, r13_hyp */
4533 *tgtmode = ARM_CPU_MODE_HYP;
4534 /* Arbitrarily pick 17 for ELR_Hyp (which is not a banked LR!) */
4535 *regno = sysm & 1 ? 13 : 17;
4536 break;
4537 default: /* unallocated */
4538 goto undef;
4539 }
4540 }
4541
4542 /* Catch the 'accessing inaccessible register' cases we can detect
4543 * at translate time.
4544 */
4545 switch (*tgtmode) {
4546 case ARM_CPU_MODE_MON:
4547 if (!arm_dc_feature(s, ARM_FEATURE_EL3) || s->ns) {
4548 goto undef;
4549 }
4550 if (s->current_el == 1) {
4551 /* If we're in Secure EL1 (which implies that EL3 is AArch64)
4552 * then accesses to Mon registers trap to EL3
4553 */
4554 exc_target = 3;
4555 goto undef;
4556 }
4557 break;
4558 case ARM_CPU_MODE_HYP:
aec4dd09
PM
4559 /*
4560 * SPSR_hyp and r13_hyp can only be accessed from Monitor mode
4561 * (and so we can forbid accesses from EL2 or below). elr_hyp
4562 * can be accessed also from Hyp mode, so forbid accesses from
4563 * EL0 or EL1.
8bfd0550 4564 */
aec4dd09
PM
4565 if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el < 2 ||
4566 (s->current_el < 3 && *regno != 17)) {
8bfd0550
PM
4567 goto undef;
4568 }
4569 break;
4570 default:
4571 break;
4572 }
4573
4574 return true;
4575
4576undef:
4577 /* If we get here then some access check did not pass */
4578 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), exc_target);
4579 return false;
4580}
4581
4582static void gen_msr_banked(DisasContext *s, int r, int sysm, int rn)
4583{
4584 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
4585 int tgtmode = 0, regno = 0;
4586
4587 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
4588 return;
4589 }
4590
4591 /* Sync state because msr_banked() can raise exceptions */
4592 gen_set_condexec(s);
4593 gen_set_pc_im(s, s->pc - 4);
4594 tcg_reg = load_reg(s, rn);
4595 tcg_tgtmode = tcg_const_i32(tgtmode);
4596 tcg_regno = tcg_const_i32(regno);
4597 gen_helper_msr_banked(cpu_env, tcg_reg, tcg_tgtmode, tcg_regno);
4598 tcg_temp_free_i32(tcg_tgtmode);
4599 tcg_temp_free_i32(tcg_regno);
4600 tcg_temp_free_i32(tcg_reg);
dcba3a8d 4601 s->base.is_jmp = DISAS_UPDATE;
8bfd0550
PM
4602}
4603
4604static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn)
4605{
4606 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
4607 int tgtmode = 0, regno = 0;
4608
4609 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
4610 return;
4611 }
4612
4613 /* Sync state because mrs_banked() can raise exceptions */
4614 gen_set_condexec(s);
4615 gen_set_pc_im(s, s->pc - 4);
4616 tcg_reg = tcg_temp_new_i32();
4617 tcg_tgtmode = tcg_const_i32(tgtmode);
4618 tcg_regno = tcg_const_i32(regno);
4619 gen_helper_mrs_banked(tcg_reg, cpu_env, tcg_tgtmode, tcg_regno);
4620 tcg_temp_free_i32(tcg_tgtmode);
4621 tcg_temp_free_i32(tcg_regno);
4622 store_reg(s, rn, tcg_reg);
dcba3a8d 4623 s->base.is_jmp = DISAS_UPDATE;
8bfd0550
PM
4624}
4625
fb0e8e79
PM
4626/* Store value to PC as for an exception return (ie don't
4627 * mask bits). The subsequent call to gen_helper_cpsr_write_eret()
4628 * will do the masking based on the new value of the Thumb bit.
4629 */
4630static void store_pc_exc_ret(DisasContext *s, TCGv_i32 pc)
b5ff1b31 4631{
fb0e8e79
PM
4632 tcg_gen_mov_i32(cpu_R[15], pc);
4633 tcg_temp_free_i32(pc);
b5ff1b31
FB
4634}
4635
b0109805 4636/* Generate a v6 exception return. Marks both values as dead. */
39d5492a 4637static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
2c0262af 4638{
fb0e8e79
PM
4639 store_pc_exc_ret(s, pc);
4640 /* The cpsr_write_eret helper will mask the low bits of PC
4641 * appropriately depending on the new Thumb bit, so it must
4642 * be called after storing the new PC.
4643 */
e69ad9df
AL
4644 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
4645 gen_io_start();
4646 }
235ea1f5 4647 gen_helper_cpsr_write_eret(cpu_env, cpsr);
e69ad9df
AL
4648 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
4649 gen_io_end();
4650 }
7d1b0095 4651 tcg_temp_free_i32(cpsr);
b29fd33d 4652 /* Must exit loop to check un-masked IRQs */
dcba3a8d 4653 s->base.is_jmp = DISAS_EXIT;
9ee6e8bb 4654}
3b46e624 4655
fb0e8e79
PM
4656/* Generate an old-style exception return. Marks pc as dead. */
4657static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
4658{
4659 gen_rfe(s, pc, load_cpu_field(spsr));
4660}
4661
c22edfeb
AB
4662/*
4663 * For WFI we will halt the vCPU until an IRQ. For WFE and YIELD we
4664 * only call the helper when running single threaded TCG code to ensure
4665 * the next round-robin scheduled vCPU gets a crack. In MTTCG mode we
4666 * just skip this instruction. Currently the SEV/SEVL instructions
4667 * which are *one* of many ways to wake the CPU from WFE are not
4668 * implemented so we can't sleep like WFI does.
4669 */
9ee6e8bb
PB
4670static void gen_nop_hint(DisasContext *s, int val)
4671{
4672 switch (val) {
2399d4e7
EC
4673 /* When running in MTTCG we don't generate jumps to the yield and
4674 * WFE helpers as it won't affect the scheduling of other vCPUs.
4675 * If we wanted to more completely model WFE/SEV so we don't busy
4676 * spin unnecessarily we would need to do something more involved.
4677 */
c87e5a61 4678 case 1: /* yield */
2399d4e7 4679 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
c22edfeb 4680 gen_set_pc_im(s, s->pc);
dcba3a8d 4681 s->base.is_jmp = DISAS_YIELD;
c22edfeb 4682 }
c87e5a61 4683 break;
9ee6e8bb 4684 case 3: /* wfi */
eaed129d 4685 gen_set_pc_im(s, s->pc);
dcba3a8d 4686 s->base.is_jmp = DISAS_WFI;
9ee6e8bb
PB
4687 break;
4688 case 2: /* wfe */
2399d4e7 4689 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
c22edfeb 4690 gen_set_pc_im(s, s->pc);
dcba3a8d 4691 s->base.is_jmp = DISAS_WFE;
c22edfeb 4692 }
72c1d3af 4693 break;
9ee6e8bb 4694 case 4: /* sev */
12b10571
MR
4695 case 5: /* sevl */
4696 /* TODO: Implement SEV, SEVL and WFE. May help SMP performance. */
9ee6e8bb
PB
4697 default: /* nop */
4698 break;
4699 }
4700}
99c475ab 4701
ad69471c 4702#define CPU_V001 cpu_V0, cpu_V0, cpu_V1
9ee6e8bb 4703
39d5492a 4704static inline void gen_neon_add(int size, TCGv_i32 t0, TCGv_i32 t1)
9ee6e8bb
PB
4705{
4706 switch (size) {
dd8fbd78
FN
4707 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
4708 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
4709 case 2: tcg_gen_add_i32(t0, t0, t1); break;
62698be3 4710 default: abort();
9ee6e8bb 4711 }
9ee6e8bb
PB
4712}
4713
39d5492a 4714static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
ad69471c
PB
4715{
4716 switch (size) {
dd8fbd78
FN
4717 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
4718 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
4719 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
ad69471c
PB
4720 default: return;
4721 }
4722}
4723
4724/* 32-bit pairwise ops end up the same as the elementwise versions. */
4725#define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
4726#define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
4727#define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
4728#define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
4729
ad69471c
PB
4730#define GEN_NEON_INTEGER_OP_ENV(name) do { \
4731 switch ((size << 1) | u) { \
4732 case 0: \
dd8fbd78 4733 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
4734 break; \
4735 case 1: \
dd8fbd78 4736 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
4737 break; \
4738 case 2: \
dd8fbd78 4739 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
4740 break; \
4741 case 3: \
dd8fbd78 4742 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
4743 break; \
4744 case 4: \
dd8fbd78 4745 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
4746 break; \
4747 case 5: \
dd8fbd78 4748 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
4749 break; \
4750 default: return 1; \
4751 }} while (0)
9ee6e8bb
PB
4752
4753#define GEN_NEON_INTEGER_OP(name) do { \
4754 switch ((size << 1) | u) { \
ad69471c 4755 case 0: \
dd8fbd78 4756 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
ad69471c
PB
4757 break; \
4758 case 1: \
dd8fbd78 4759 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
ad69471c
PB
4760 break; \
4761 case 2: \
dd8fbd78 4762 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
ad69471c
PB
4763 break; \
4764 case 3: \
dd8fbd78 4765 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
ad69471c
PB
4766 break; \
4767 case 4: \
dd8fbd78 4768 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
ad69471c
PB
4769 break; \
4770 case 5: \
dd8fbd78 4771 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
ad69471c 4772 break; \
9ee6e8bb
PB
4773 default: return 1; \
4774 }} while (0)
4775
39d5492a 4776static TCGv_i32 neon_load_scratch(int scratch)
9ee6e8bb 4777{
39d5492a 4778 TCGv_i32 tmp = tcg_temp_new_i32();
dd8fbd78
FN
4779 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
4780 return tmp;
9ee6e8bb
PB
4781}
4782
39d5492a 4783static void neon_store_scratch(int scratch, TCGv_i32 var)
9ee6e8bb 4784{
dd8fbd78 4785 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
7d1b0095 4786 tcg_temp_free_i32(var);
9ee6e8bb
PB
4787}
4788
39d5492a 4789static inline TCGv_i32 neon_get_scalar(int size, int reg)
9ee6e8bb 4790{
39d5492a 4791 TCGv_i32 tmp;
9ee6e8bb 4792 if (size == 1) {
0fad6efc
PM
4793 tmp = neon_load_reg(reg & 7, reg >> 4);
4794 if (reg & 8) {
dd8fbd78 4795 gen_neon_dup_high16(tmp);
0fad6efc
PM
4796 } else {
4797 gen_neon_dup_low16(tmp);
dd8fbd78 4798 }
0fad6efc
PM
4799 } else {
4800 tmp = neon_load_reg(reg & 15, reg >> 4);
9ee6e8bb 4801 }
dd8fbd78 4802 return tmp;
9ee6e8bb
PB
4803}
4804
02acedf9 4805static int gen_neon_unzip(int rd, int rm, int size, int q)
19457615 4806{
b13708bb
RH
4807 TCGv_ptr pd, pm;
4808
600b828c 4809 if (!q && size == 2) {
02acedf9
PM
4810 return 1;
4811 }
b13708bb
RH
4812 pd = vfp_reg_ptr(true, rd);
4813 pm = vfp_reg_ptr(true, rm);
02acedf9
PM
4814 if (q) {
4815 switch (size) {
4816 case 0:
b13708bb 4817 gen_helper_neon_qunzip8(pd, pm);
02acedf9
PM
4818 break;
4819 case 1:
b13708bb 4820 gen_helper_neon_qunzip16(pd, pm);
02acedf9
PM
4821 break;
4822 case 2:
b13708bb 4823 gen_helper_neon_qunzip32(pd, pm);
02acedf9
PM
4824 break;
4825 default:
4826 abort();
4827 }
4828 } else {
4829 switch (size) {
4830 case 0:
b13708bb 4831 gen_helper_neon_unzip8(pd, pm);
02acedf9
PM
4832 break;
4833 case 1:
b13708bb 4834 gen_helper_neon_unzip16(pd, pm);
02acedf9
PM
4835 break;
4836 default:
4837 abort();
4838 }
4839 }
b13708bb
RH
4840 tcg_temp_free_ptr(pd);
4841 tcg_temp_free_ptr(pm);
02acedf9 4842 return 0;
19457615
FN
4843}
4844
d68a6f3a 4845static int gen_neon_zip(int rd, int rm, int size, int q)
19457615 4846{
b13708bb
RH
4847 TCGv_ptr pd, pm;
4848
600b828c 4849 if (!q && size == 2) {
d68a6f3a
PM
4850 return 1;
4851 }
b13708bb
RH
4852 pd = vfp_reg_ptr(true, rd);
4853 pm = vfp_reg_ptr(true, rm);
d68a6f3a
PM
4854 if (q) {
4855 switch (size) {
4856 case 0:
b13708bb 4857 gen_helper_neon_qzip8(pd, pm);
d68a6f3a
PM
4858 break;
4859 case 1:
b13708bb 4860 gen_helper_neon_qzip16(pd, pm);
d68a6f3a
PM
4861 break;
4862 case 2:
b13708bb 4863 gen_helper_neon_qzip32(pd, pm);
d68a6f3a
PM
4864 break;
4865 default:
4866 abort();
4867 }
4868 } else {
4869 switch (size) {
4870 case 0:
b13708bb 4871 gen_helper_neon_zip8(pd, pm);
d68a6f3a
PM
4872 break;
4873 case 1:
b13708bb 4874 gen_helper_neon_zip16(pd, pm);
d68a6f3a
PM
4875 break;
4876 default:
4877 abort();
4878 }
4879 }
b13708bb
RH
4880 tcg_temp_free_ptr(pd);
4881 tcg_temp_free_ptr(pm);
d68a6f3a 4882 return 0;
19457615
FN
4883}
4884
39d5492a 4885static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
19457615 4886{
39d5492a 4887 TCGv_i32 rd, tmp;
19457615 4888
7d1b0095
PM
4889 rd = tcg_temp_new_i32();
4890 tmp = tcg_temp_new_i32();
19457615
FN
4891
4892 tcg_gen_shli_i32(rd, t0, 8);
4893 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
4894 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
4895 tcg_gen_or_i32(rd, rd, tmp);
4896
4897 tcg_gen_shri_i32(t1, t1, 8);
4898 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
4899 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
4900 tcg_gen_or_i32(t1, t1, tmp);
4901 tcg_gen_mov_i32(t0, rd);
4902
7d1b0095
PM
4903 tcg_temp_free_i32(tmp);
4904 tcg_temp_free_i32(rd);
19457615
FN
4905}
4906
39d5492a 4907static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
19457615 4908{
39d5492a 4909 TCGv_i32 rd, tmp;
19457615 4910
7d1b0095
PM
4911 rd = tcg_temp_new_i32();
4912 tmp = tcg_temp_new_i32();
19457615
FN
4913
4914 tcg_gen_shli_i32(rd, t0, 16);
4915 tcg_gen_andi_i32(tmp, t1, 0xffff);
4916 tcg_gen_or_i32(rd, rd, tmp);
4917 tcg_gen_shri_i32(t1, t1, 16);
4918 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
4919 tcg_gen_or_i32(t1, t1, tmp);
4920 tcg_gen_mov_i32(t0, rd);
4921
7d1b0095
PM
4922 tcg_temp_free_i32(tmp);
4923 tcg_temp_free_i32(rd);
19457615
FN
4924}
4925
4926
9ee6e8bb
PB
4927static struct {
4928 int nregs;
4929 int interleave;
4930 int spacing;
308e5636 4931} const neon_ls_element_type[11] = {
ac55d007
RH
4932 {1, 4, 1},
4933 {1, 4, 2},
9ee6e8bb 4934 {4, 1, 1},
ac55d007
RH
4935 {2, 2, 2},
4936 {1, 3, 1},
4937 {1, 3, 2},
9ee6e8bb
PB
4938 {3, 1, 1},
4939 {1, 1, 1},
ac55d007
RH
4940 {1, 2, 1},
4941 {1, 2, 2},
9ee6e8bb
PB
4942 {2, 1, 1}
4943};
4944
4945/* Translate a NEON load/store element instruction. Return nonzero if the
4946 instruction is invalid. */
7dcc1f89 4947static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
9ee6e8bb
PB
4948{
4949 int rd, rn, rm;
4950 int op;
4951 int nregs;
4952 int interleave;
84496233 4953 int spacing;
9ee6e8bb
PB
4954 int stride;
4955 int size;
4956 int reg;
4957 int pass;
4958 int load;
4959 int shift;
9ee6e8bb 4960 int n;
7377c2c9 4961 int vec_size;
ac55d007
RH
4962 int mmu_idx;
4963 TCGMemOp endian;
39d5492a
PM
4964 TCGv_i32 addr;
4965 TCGv_i32 tmp;
4966 TCGv_i32 tmp2;
84496233 4967 TCGv_i64 tmp64;
9ee6e8bb 4968
2c7ffc41
PM
4969 /* FIXME: this access check should not take precedence over UNDEF
4970 * for invalid encodings; we will generate incorrect syndrome information
4971 * for attempts to execute invalid vfp/neon encodings with FP disabled.
4972 */
9dbbc748 4973 if (s->fp_excp_el) {
2c7ffc41 4974 gen_exception_insn(s, 4, EXCP_UDEF,
4be42f40 4975 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
2c7ffc41
PM
4976 return 0;
4977 }
4978
5df8bac1 4979 if (!s->vfp_enabled)
9ee6e8bb
PB
4980 return 1;
4981 VFP_DREG_D(rd, insn);
4982 rn = (insn >> 16) & 0xf;
4983 rm = insn & 0xf;
4984 load = (insn & (1 << 21)) != 0;
ac55d007
RH
4985 endian = s->be_data;
4986 mmu_idx = get_mem_index(s);
9ee6e8bb
PB
4987 if ((insn & (1 << 23)) == 0) {
4988 /* Load store all elements. */
4989 op = (insn >> 8) & 0xf;
4990 size = (insn >> 6) & 3;
84496233 4991 if (op > 10)
9ee6e8bb 4992 return 1;
f2dd89d0
PM
4993 /* Catch UNDEF cases for bad values of align field */
4994 switch (op & 0xc) {
4995 case 4:
4996 if (((insn >> 5) & 1) == 1) {
4997 return 1;
4998 }
4999 break;
5000 case 8:
5001 if (((insn >> 4) & 3) == 3) {
5002 return 1;
5003 }
5004 break;
5005 default:
5006 break;
5007 }
9ee6e8bb
PB
5008 nregs = neon_ls_element_type[op].nregs;
5009 interleave = neon_ls_element_type[op].interleave;
84496233 5010 spacing = neon_ls_element_type[op].spacing;
ac55d007 5011 if (size == 3 && (interleave | spacing) != 1) {
84496233 5012 return 1;
ac55d007
RH
5013 }
5014 tmp64 = tcg_temp_new_i64();
e318a60b 5015 addr = tcg_temp_new_i32();
ac55d007 5016 tmp2 = tcg_const_i32(1 << size);
dcc65026 5017 load_reg_var(s, addr, rn);
9ee6e8bb 5018 for (reg = 0; reg < nregs; reg++) {
ac55d007
RH
5019 for (n = 0; n < 8 >> size; n++) {
5020 int xs;
5021 for (xs = 0; xs < interleave; xs++) {
5022 int tt = rd + reg + spacing * xs;
5023
5024 if (load) {
5025 gen_aa32_ld_i64(s, tmp64, addr, mmu_idx, endian | size);
5026 neon_store_element64(tt, n, size, tmp64);
5027 } else {
5028 neon_load_element64(tmp64, tt, n, size);
5029 gen_aa32_st_i64(s, tmp64, addr, mmu_idx, endian | size);
9ee6e8bb 5030 }
ac55d007 5031 tcg_gen_add_i32(addr, addr, tmp2);
9ee6e8bb
PB
5032 }
5033 }
9ee6e8bb 5034 }
e318a60b 5035 tcg_temp_free_i32(addr);
ac55d007
RH
5036 tcg_temp_free_i32(tmp2);
5037 tcg_temp_free_i64(tmp64);
5038 stride = nregs * interleave * 8;
9ee6e8bb
PB
5039 } else {
5040 size = (insn >> 10) & 3;
5041 if (size == 3) {
5042 /* Load single element to all lanes. */
8e18cde3
PM
5043 int a = (insn >> 4) & 1;
5044 if (!load) {
9ee6e8bb 5045 return 1;
8e18cde3 5046 }
9ee6e8bb
PB
5047 size = (insn >> 6) & 3;
5048 nregs = ((insn >> 8) & 3) + 1;
8e18cde3
PM
5049
5050 if (size == 3) {
5051 if (nregs != 4 || a == 0) {
9ee6e8bb 5052 return 1;
99c475ab 5053 }
8e18cde3
PM
5054 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
5055 size = 2;
5056 }
5057 if (nregs == 1 && a == 1 && size == 0) {
5058 return 1;
5059 }
5060 if (nregs == 3 && a == 1) {
5061 return 1;
5062 }
e318a60b 5063 addr = tcg_temp_new_i32();
8e18cde3 5064 load_reg_var(s, addr, rn);
7377c2c9
RH
5065
5066 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write.
5067 * VLD2/3/4 to all lanes: bit 5 indicates register stride.
5068 */
5069 stride = (insn & (1 << 5)) ? 2 : 1;
5070 vec_size = nregs == 1 ? stride * 8 : 8;
5071
5072 tmp = tcg_temp_new_i32();
5073 for (reg = 0; reg < nregs; reg++) {
5074 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
5075 s->be_data | size);
5076 if ((rd & 1) && vec_size == 16) {
5077 /* We cannot write 16 bytes at once because the
5078 * destination is unaligned.
5079 */
5080 tcg_gen_gvec_dup_i32(size, neon_reg_offset(rd, 0),
5081 8, 8, tmp);
5082 tcg_gen_gvec_mov(0, neon_reg_offset(rd + 1, 0),
5083 neon_reg_offset(rd, 0), 8, 8);
5084 } else {
5085 tcg_gen_gvec_dup_i32(size, neon_reg_offset(rd, 0),
5086 vec_size, vec_size, tmp);
8e18cde3 5087 }
7377c2c9
RH
5088 tcg_gen_addi_i32(addr, addr, 1 << size);
5089 rd += stride;
9ee6e8bb 5090 }
7377c2c9 5091 tcg_temp_free_i32(tmp);
e318a60b 5092 tcg_temp_free_i32(addr);
9ee6e8bb
PB
5093 stride = (1 << size) * nregs;
5094 } else {
5095 /* Single element. */
93262b16 5096 int idx = (insn >> 4) & 0xf;
9ee6e8bb
PB
5097 pass = (insn >> 7) & 1;
5098 switch (size) {
5099 case 0:
5100 shift = ((insn >> 5) & 3) * 8;
9ee6e8bb
PB
5101 stride = 1;
5102 break;
5103 case 1:
5104 shift = ((insn >> 6) & 1) * 16;
9ee6e8bb
PB
5105 stride = (insn & (1 << 5)) ? 2 : 1;
5106 break;
5107 case 2:
5108 shift = 0;
9ee6e8bb
PB
5109 stride = (insn & (1 << 6)) ? 2 : 1;
5110 break;
5111 default:
5112 abort();
5113 }
5114 nregs = ((insn >> 8) & 3) + 1;
93262b16
PM
5115 /* Catch the UNDEF cases. This is unavoidably a bit messy. */
5116 switch (nregs) {
5117 case 1:
5118 if (((idx & (1 << size)) != 0) ||
5119 (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
5120 return 1;
5121 }
5122 break;
5123 case 3:
5124 if ((idx & 1) != 0) {
5125 return 1;
5126 }
5127 /* fall through */
5128 case 2:
5129 if (size == 2 && (idx & 2) != 0) {
5130 return 1;
5131 }
5132 break;
5133 case 4:
5134 if ((size == 2) && ((idx & 3) == 3)) {
5135 return 1;
5136 }
5137 break;
5138 default:
5139 abort();
5140 }
5141 if ((rd + stride * (nregs - 1)) > 31) {
5142 /* Attempts to write off the end of the register file
5143 * are UNPREDICTABLE; we choose to UNDEF because otherwise
5144 * the neon_load_reg() would write off the end of the array.
5145 */
5146 return 1;
5147 }
e318a60b 5148 addr = tcg_temp_new_i32();
dcc65026 5149 load_reg_var(s, addr, rn);
9ee6e8bb
PB
5150 for (reg = 0; reg < nregs; reg++) {
5151 if (load) {
58ab8e96 5152 tmp = tcg_temp_new_i32();
9ee6e8bb
PB
5153 switch (size) {
5154 case 0:
12dcc321 5155 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
9ee6e8bb
PB
5156 break;
5157 case 1:
12dcc321 5158 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
9ee6e8bb
PB
5159 break;
5160 case 2:
12dcc321 5161 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9ee6e8bb 5162 break;
a50f5b91
PB
5163 default: /* Avoid compiler warnings. */
5164 abort();
9ee6e8bb
PB
5165 }
5166 if (size != 2) {
8f8e3aa4 5167 tmp2 = neon_load_reg(rd, pass);
d593c48e
AJ
5168 tcg_gen_deposit_i32(tmp, tmp2, tmp,
5169 shift, size ? 16 : 8);
7d1b0095 5170 tcg_temp_free_i32(tmp2);
9ee6e8bb 5171 }
8f8e3aa4 5172 neon_store_reg(rd, pass, tmp);
9ee6e8bb 5173 } else { /* Store */
8f8e3aa4
PB
5174 tmp = neon_load_reg(rd, pass);
5175 if (shift)
5176 tcg_gen_shri_i32(tmp, tmp, shift);
9ee6e8bb
PB
5177 switch (size) {
5178 case 0:
12dcc321 5179 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
9ee6e8bb
PB
5180 break;
5181 case 1:
12dcc321 5182 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
9ee6e8bb
PB
5183 break;
5184 case 2:
12dcc321 5185 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
9ee6e8bb 5186 break;
99c475ab 5187 }
58ab8e96 5188 tcg_temp_free_i32(tmp);
99c475ab 5189 }
9ee6e8bb 5190 rd += stride;
1b2b1e54 5191 tcg_gen_addi_i32(addr, addr, 1 << size);
99c475ab 5192 }
e318a60b 5193 tcg_temp_free_i32(addr);
9ee6e8bb 5194 stride = nregs * (1 << size);
99c475ab 5195 }
9ee6e8bb
PB
5196 }
5197 if (rm != 15) {
39d5492a 5198 TCGv_i32 base;
b26eefb6
PB
5199
5200 base = load_reg(s, rn);
9ee6e8bb 5201 if (rm == 13) {
b26eefb6 5202 tcg_gen_addi_i32(base, base, stride);
9ee6e8bb 5203 } else {
39d5492a 5204 TCGv_i32 index;
b26eefb6
PB
5205 index = load_reg(s, rm);
5206 tcg_gen_add_i32(base, base, index);
7d1b0095 5207 tcg_temp_free_i32(index);
9ee6e8bb 5208 }
b26eefb6 5209 store_reg(s, rn, base);
9ee6e8bb
PB
5210 }
5211 return 0;
5212}
3b46e624 5213
39d5492a 5214static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src)
ad69471c
PB
5215{
5216 switch (size) {
5217 case 0: gen_helper_neon_narrow_u8(dest, src); break;
5218 case 1: gen_helper_neon_narrow_u16(dest, src); break;
ecc7b3aa 5219 case 2: tcg_gen_extrl_i64_i32(dest, src); break;
ad69471c
PB
5220 default: abort();
5221 }
5222}
5223
39d5492a 5224static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
ad69471c
PB
5225{
5226 switch (size) {
02da0b2d
PM
5227 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
5228 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
5229 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
ad69471c
PB
5230 default: abort();
5231 }
5232}
5233
39d5492a 5234static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src)
ad69471c
PB
5235{
5236 switch (size) {
02da0b2d
PM
5237 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
5238 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
5239 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
ad69471c
PB
5240 default: abort();
5241 }
5242}
5243
39d5492a 5244static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
af1bbf30
JR
5245{
5246 switch (size) {
02da0b2d
PM
5247 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
5248 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
5249 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
af1bbf30
JR
5250 default: abort();
5251 }
5252}
5253
39d5492a 5254static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift,
ad69471c
PB
5255 int q, int u)
5256{
5257 if (q) {
5258 if (u) {
5259 switch (size) {
5260 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
5261 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
5262 default: abort();
5263 }
5264 } else {
5265 switch (size) {
5266 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
5267 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
5268 default: abort();
5269 }
5270 }
5271 } else {
5272 if (u) {
5273 switch (size) {
b408a9b0
CL
5274 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
5275 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
ad69471c
PB
5276 default: abort();
5277 }
5278 } else {
5279 switch (size) {
5280 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
5281 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
5282 default: abort();
5283 }
5284 }
5285 }
5286}
5287
39d5492a 5288static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
ad69471c
PB
5289{
5290 if (u) {
5291 switch (size) {
5292 case 0: gen_helper_neon_widen_u8(dest, src); break;
5293 case 1: gen_helper_neon_widen_u16(dest, src); break;
5294 case 2: tcg_gen_extu_i32_i64(dest, src); break;
5295 default: abort();
5296 }
5297 } else {
5298 switch (size) {
5299 case 0: gen_helper_neon_widen_s8(dest, src); break;
5300 case 1: gen_helper_neon_widen_s16(dest, src); break;
5301 case 2: tcg_gen_ext_i32_i64(dest, src); break;
5302 default: abort();
5303 }
5304 }
7d1b0095 5305 tcg_temp_free_i32(src);
ad69471c
PB
5306}
5307
5308static inline void gen_neon_addl(int size)
5309{
5310 switch (size) {
5311 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
5312 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
5313 case 2: tcg_gen_add_i64(CPU_V001); break;
5314 default: abort();
5315 }
5316}
5317
5318static inline void gen_neon_subl(int size)
5319{
5320 switch (size) {
5321 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
5322 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
5323 case 2: tcg_gen_sub_i64(CPU_V001); break;
5324 default: abort();
5325 }
5326}
5327
a7812ae4 5328static inline void gen_neon_negl(TCGv_i64 var, int size)
ad69471c
PB
5329{
5330 switch (size) {
5331 case 0: gen_helper_neon_negl_u16(var, var); break;
5332 case 1: gen_helper_neon_negl_u32(var, var); break;
ee6fa559
PM
5333 case 2:
5334 tcg_gen_neg_i64(var, var);
5335 break;
ad69471c
PB
5336 default: abort();
5337 }
5338}
5339
a7812ae4 5340static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
ad69471c
PB
5341{
5342 switch (size) {
02da0b2d
PM
5343 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
5344 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
ad69471c
PB
5345 default: abort();
5346 }
5347}
5348
39d5492a
PM
5349static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b,
5350 int size, int u)
ad69471c 5351{
a7812ae4 5352 TCGv_i64 tmp;
ad69471c
PB
5353
5354 switch ((size << 1) | u) {
5355 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
5356 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
5357 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
5358 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
5359 case 4:
5360 tmp = gen_muls_i64_i32(a, b);
5361 tcg_gen_mov_i64(dest, tmp);
7d2aabe2 5362 tcg_temp_free_i64(tmp);
ad69471c
PB
5363 break;
5364 case 5:
5365 tmp = gen_mulu_i64_i32(a, b);
5366 tcg_gen_mov_i64(dest, tmp);
7d2aabe2 5367 tcg_temp_free_i64(tmp);
ad69471c
PB
5368 break;
5369 default: abort();
5370 }
c6067f04
CL
5371
5372 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
5373 Don't forget to clean them now. */
5374 if (size < 2) {
7d1b0095
PM
5375 tcg_temp_free_i32(a);
5376 tcg_temp_free_i32(b);
c6067f04 5377 }
ad69471c
PB
5378}
5379
39d5492a
PM
5380static void gen_neon_narrow_op(int op, int u, int size,
5381 TCGv_i32 dest, TCGv_i64 src)
c33171c7
PM
5382{
5383 if (op) {
5384 if (u) {
5385 gen_neon_unarrow_sats(size, dest, src);
5386 } else {
5387 gen_neon_narrow(size, dest, src);
5388 }
5389 } else {
5390 if (u) {
5391 gen_neon_narrow_satu(size, dest, src);
5392 } else {
5393 gen_neon_narrow_sats(size, dest, src);
5394 }
5395 }
5396}
5397
62698be3
PM
5398/* Symbolic constants for op fields for Neon 3-register same-length.
5399 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
5400 * table A7-9.
5401 */
5402#define NEON_3R_VHADD 0
5403#define NEON_3R_VQADD 1
5404#define NEON_3R_VRHADD 2
5405#define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
5406#define NEON_3R_VHSUB 4
5407#define NEON_3R_VQSUB 5
5408#define NEON_3R_VCGT 6
5409#define NEON_3R_VCGE 7
5410#define NEON_3R_VSHL 8
5411#define NEON_3R_VQSHL 9
5412#define NEON_3R_VRSHL 10
5413#define NEON_3R_VQRSHL 11
5414#define NEON_3R_VMAX 12
5415#define NEON_3R_VMIN 13
5416#define NEON_3R_VABD 14
5417#define NEON_3R_VABA 15
5418#define NEON_3R_VADD_VSUB 16
5419#define NEON_3R_VTST_VCEQ 17
4a7832b0 5420#define NEON_3R_VML 18 /* VMLA, VMLS */
62698be3
PM
5421#define NEON_3R_VMUL 19
5422#define NEON_3R_VPMAX 20
5423#define NEON_3R_VPMIN 21
5424#define NEON_3R_VQDMULH_VQRDMULH 22
36a71934 5425#define NEON_3R_VPADD_VQRDMLAH 23
f1ecb913 5426#define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */
36a71934 5427#define NEON_3R_VFM_VQRDMLSH 25 /* VFMA, VFMS, VQRDMLSH */
62698be3
PM
5428#define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
5429#define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
5430#define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
5431#define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
5432#define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
505935fc 5433#define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */
62698be3
PM
5434
5435static const uint8_t neon_3r_sizes[] = {
5436 [NEON_3R_VHADD] = 0x7,
5437 [NEON_3R_VQADD] = 0xf,
5438 [NEON_3R_VRHADD] = 0x7,
5439 [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
5440 [NEON_3R_VHSUB] = 0x7,
5441 [NEON_3R_VQSUB] = 0xf,
5442 [NEON_3R_VCGT] = 0x7,
5443 [NEON_3R_VCGE] = 0x7,
5444 [NEON_3R_VSHL] = 0xf,
5445 [NEON_3R_VQSHL] = 0xf,
5446 [NEON_3R_VRSHL] = 0xf,
5447 [NEON_3R_VQRSHL] = 0xf,
5448 [NEON_3R_VMAX] = 0x7,
5449 [NEON_3R_VMIN] = 0x7,
5450 [NEON_3R_VABD] = 0x7,
5451 [NEON_3R_VABA] = 0x7,
5452 [NEON_3R_VADD_VSUB] = 0xf,
5453 [NEON_3R_VTST_VCEQ] = 0x7,
5454 [NEON_3R_VML] = 0x7,
5455 [NEON_3R_VMUL] = 0x7,
5456 [NEON_3R_VPMAX] = 0x7,
5457 [NEON_3R_VPMIN] = 0x7,
5458 [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
36a71934 5459 [NEON_3R_VPADD_VQRDMLAH] = 0x7,
f1ecb913 5460 [NEON_3R_SHA] = 0xf, /* size field encodes op type */
36a71934 5461 [NEON_3R_VFM_VQRDMLSH] = 0x7, /* For VFM, size bit 1 encodes op */
62698be3
PM
5462 [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
5463 [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
5464 [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
5465 [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
5466 [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
505935fc 5467 [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */
62698be3
PM
5468};
5469
600b828c
PM
5470/* Symbolic constants for op fields for Neon 2-register miscellaneous.
5471 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
5472 * table A7-13.
5473 */
5474#define NEON_2RM_VREV64 0
5475#define NEON_2RM_VREV32 1
5476#define NEON_2RM_VREV16 2
5477#define NEON_2RM_VPADDL 4
5478#define NEON_2RM_VPADDL_U 5
9d935509
AB
5479#define NEON_2RM_AESE 6 /* Includes AESD */
5480#define NEON_2RM_AESMC 7 /* Includes AESIMC */
600b828c
PM
5481#define NEON_2RM_VCLS 8
5482#define NEON_2RM_VCLZ 9
5483#define NEON_2RM_VCNT 10
5484#define NEON_2RM_VMVN 11
5485#define NEON_2RM_VPADAL 12
5486#define NEON_2RM_VPADAL_U 13
5487#define NEON_2RM_VQABS 14
5488#define NEON_2RM_VQNEG 15
5489#define NEON_2RM_VCGT0 16
5490#define NEON_2RM_VCGE0 17
5491#define NEON_2RM_VCEQ0 18
5492#define NEON_2RM_VCLE0 19
5493#define NEON_2RM_VCLT0 20
f1ecb913 5494#define NEON_2RM_SHA1H 21
600b828c
PM
5495#define NEON_2RM_VABS 22
5496#define NEON_2RM_VNEG 23
5497#define NEON_2RM_VCGT0_F 24
5498#define NEON_2RM_VCGE0_F 25
5499#define NEON_2RM_VCEQ0_F 26
5500#define NEON_2RM_VCLE0_F 27
5501#define NEON_2RM_VCLT0_F 28
5502#define NEON_2RM_VABS_F 30
5503#define NEON_2RM_VNEG_F 31
5504#define NEON_2RM_VSWP 32
5505#define NEON_2RM_VTRN 33
5506#define NEON_2RM_VUZP 34
5507#define NEON_2RM_VZIP 35
5508#define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
5509#define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
5510#define NEON_2RM_VSHLL 38
f1ecb913 5511#define NEON_2RM_SHA1SU1 39 /* Includes SHA256SU0 */
34f7b0a2 5512#define NEON_2RM_VRINTN 40
2ce70625 5513#define NEON_2RM_VRINTX 41
34f7b0a2
WN
5514#define NEON_2RM_VRINTA 42
5515#define NEON_2RM_VRINTZ 43
600b828c 5516#define NEON_2RM_VCVT_F16_F32 44
34f7b0a2 5517#define NEON_2RM_VRINTM 45
600b828c 5518#define NEON_2RM_VCVT_F32_F16 46
34f7b0a2 5519#define NEON_2RM_VRINTP 47
901ad525
WN
5520#define NEON_2RM_VCVTAU 48
5521#define NEON_2RM_VCVTAS 49
5522#define NEON_2RM_VCVTNU 50
5523#define NEON_2RM_VCVTNS 51
5524#define NEON_2RM_VCVTPU 52
5525#define NEON_2RM_VCVTPS 53
5526#define NEON_2RM_VCVTMU 54
5527#define NEON_2RM_VCVTMS 55
600b828c
PM
5528#define NEON_2RM_VRECPE 56
5529#define NEON_2RM_VRSQRTE 57
5530#define NEON_2RM_VRECPE_F 58
5531#define NEON_2RM_VRSQRTE_F 59
5532#define NEON_2RM_VCVT_FS 60
5533#define NEON_2RM_VCVT_FU 61
5534#define NEON_2RM_VCVT_SF 62
5535#define NEON_2RM_VCVT_UF 63
5536
5537static int neon_2rm_is_float_op(int op)
5538{
5539 /* Return true if this neon 2reg-misc op is float-to-float */
5540 return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
34f7b0a2 5541 (op >= NEON_2RM_VRINTN && op <= NEON_2RM_VRINTZ) ||
901ad525
WN
5542 op == NEON_2RM_VRINTM ||
5543 (op >= NEON_2RM_VRINTP && op <= NEON_2RM_VCVTMS) ||
34f7b0a2 5544 op >= NEON_2RM_VRECPE_F);
600b828c
PM
5545}
5546
fe8fcf3d
PM
5547static bool neon_2rm_is_v8_op(int op)
5548{
5549 /* Return true if this neon 2reg-misc op is ARMv8 and up */
5550 switch (op) {
5551 case NEON_2RM_VRINTN:
5552 case NEON_2RM_VRINTA:
5553 case NEON_2RM_VRINTM:
5554 case NEON_2RM_VRINTP:
5555 case NEON_2RM_VRINTZ:
5556 case NEON_2RM_VRINTX:
5557 case NEON_2RM_VCVTAU:
5558 case NEON_2RM_VCVTAS:
5559 case NEON_2RM_VCVTNU:
5560 case NEON_2RM_VCVTNS:
5561 case NEON_2RM_VCVTPU:
5562 case NEON_2RM_VCVTPS:
5563 case NEON_2RM_VCVTMU:
5564 case NEON_2RM_VCVTMS:
5565 return true;
5566 default:
5567 return false;
5568 }
5569}
5570
600b828c
PM
5571/* Each entry in this array has bit n set if the insn allows
5572 * size value n (otherwise it will UNDEF). Since unallocated
5573 * op values will have no bits set they always UNDEF.
5574 */
5575static const uint8_t neon_2rm_sizes[] = {
5576 [NEON_2RM_VREV64] = 0x7,
5577 [NEON_2RM_VREV32] = 0x3,
5578 [NEON_2RM_VREV16] = 0x1,
5579 [NEON_2RM_VPADDL] = 0x7,
5580 [NEON_2RM_VPADDL_U] = 0x7,
9d935509
AB
5581 [NEON_2RM_AESE] = 0x1,
5582 [NEON_2RM_AESMC] = 0x1,
600b828c
PM
5583 [NEON_2RM_VCLS] = 0x7,
5584 [NEON_2RM_VCLZ] = 0x7,
5585 [NEON_2RM_VCNT] = 0x1,
5586 [NEON_2RM_VMVN] = 0x1,
5587 [NEON_2RM_VPADAL] = 0x7,
5588 [NEON_2RM_VPADAL_U] = 0x7,
5589 [NEON_2RM_VQABS] = 0x7,
5590 [NEON_2RM_VQNEG] = 0x7,
5591 [NEON_2RM_VCGT0] = 0x7,
5592 [NEON_2RM_VCGE0] = 0x7,
5593 [NEON_2RM_VCEQ0] = 0x7,
5594 [NEON_2RM_VCLE0] = 0x7,
5595 [NEON_2RM_VCLT0] = 0x7,
f1ecb913 5596 [NEON_2RM_SHA1H] = 0x4,
600b828c
PM
5597 [NEON_2RM_VABS] = 0x7,
5598 [NEON_2RM_VNEG] = 0x7,
5599 [NEON_2RM_VCGT0_F] = 0x4,
5600 [NEON_2RM_VCGE0_F] = 0x4,
5601 [NEON_2RM_VCEQ0_F] = 0x4,
5602 [NEON_2RM_VCLE0_F] = 0x4,
5603 [NEON_2RM_VCLT0_F] = 0x4,
5604 [NEON_2RM_VABS_F] = 0x4,
5605 [NEON_2RM_VNEG_F] = 0x4,
5606 [NEON_2RM_VSWP] = 0x1,
5607 [NEON_2RM_VTRN] = 0x7,
5608 [NEON_2RM_VUZP] = 0x7,
5609 [NEON_2RM_VZIP] = 0x7,
5610 [NEON_2RM_VMOVN] = 0x7,
5611 [NEON_2RM_VQMOVN] = 0x7,
5612 [NEON_2RM_VSHLL] = 0x7,
f1ecb913 5613 [NEON_2RM_SHA1SU1] = 0x4,
34f7b0a2 5614 [NEON_2RM_VRINTN] = 0x4,
2ce70625 5615 [NEON_2RM_VRINTX] = 0x4,
34f7b0a2
WN
5616 [NEON_2RM_VRINTA] = 0x4,
5617 [NEON_2RM_VRINTZ] = 0x4,
600b828c 5618 [NEON_2RM_VCVT_F16_F32] = 0x2,
34f7b0a2 5619 [NEON_2RM_VRINTM] = 0x4,
600b828c 5620 [NEON_2RM_VCVT_F32_F16] = 0x2,
34f7b0a2 5621 [NEON_2RM_VRINTP] = 0x4,
901ad525
WN
5622 [NEON_2RM_VCVTAU] = 0x4,
5623 [NEON_2RM_VCVTAS] = 0x4,
5624 [NEON_2RM_VCVTNU] = 0x4,
5625 [NEON_2RM_VCVTNS] = 0x4,
5626 [NEON_2RM_VCVTPU] = 0x4,
5627 [NEON_2RM_VCVTPS] = 0x4,
5628 [NEON_2RM_VCVTMU] = 0x4,
5629 [NEON_2RM_VCVTMS] = 0x4,
600b828c
PM
5630 [NEON_2RM_VRECPE] = 0x4,
5631 [NEON_2RM_VRSQRTE] = 0x4,
5632 [NEON_2RM_VRECPE_F] = 0x4,
5633 [NEON_2RM_VRSQRTE_F] = 0x4,
5634 [NEON_2RM_VCVT_FS] = 0x4,
5635 [NEON_2RM_VCVT_FU] = 0x4,
5636 [NEON_2RM_VCVT_SF] = 0x4,
5637 [NEON_2RM_VCVT_UF] = 0x4,
5638};
5639
36a71934
RH
5640
5641/* Expand v8.1 simd helper. */
5642static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
5643 int q, int rd, int rn, int rm)
5644{
962fcbf2 5645 if (dc_isar_feature(aa32_rdm, s)) {
36a71934
RH
5646 int opr_sz = (1 + q) * 8;
5647 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
5648 vfp_reg_offset(1, rn),
5649 vfp_reg_offset(1, rm), cpu_env,
5650 opr_sz, opr_sz, 0, fn);
5651 return 0;
5652 }
5653 return 1;
5654}
5655
eabcd6fa
RH
5656/*
5657 * Expanders for VBitOps_VBIF, VBIT, VBSL.
5658 */
5659static void gen_bsl_i64(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
5660{
5661 tcg_gen_xor_i64(rn, rn, rm);
5662 tcg_gen_and_i64(rn, rn, rd);
5663 tcg_gen_xor_i64(rd, rm, rn);
5664}
5665
5666static void gen_bit_i64(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
5667{
5668 tcg_gen_xor_i64(rn, rn, rd);
5669 tcg_gen_and_i64(rn, rn, rm);
5670 tcg_gen_xor_i64(rd, rd, rn);
5671}
5672
5673static void gen_bif_i64(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
5674{
5675 tcg_gen_xor_i64(rn, rn, rd);
5676 tcg_gen_andc_i64(rn, rn, rm);
5677 tcg_gen_xor_i64(rd, rd, rn);
5678}
5679
5680static void gen_bsl_vec(unsigned vece, TCGv_vec rd, TCGv_vec rn, TCGv_vec rm)
5681{
5682 tcg_gen_xor_vec(vece, rn, rn, rm);
5683 tcg_gen_and_vec(vece, rn, rn, rd);
5684 tcg_gen_xor_vec(vece, rd, rm, rn);
5685}
5686
5687static void gen_bit_vec(unsigned vece, TCGv_vec rd, TCGv_vec rn, TCGv_vec rm)
5688{
5689 tcg_gen_xor_vec(vece, rn, rn, rd);
5690 tcg_gen_and_vec(vece, rn, rn, rm);
5691 tcg_gen_xor_vec(vece, rd, rd, rn);
5692}
5693
5694static void gen_bif_vec(unsigned vece, TCGv_vec rd, TCGv_vec rn, TCGv_vec rm)
5695{
5696 tcg_gen_xor_vec(vece, rn, rn, rd);
5697 tcg_gen_andc_vec(vece, rn, rn, rm);
5698 tcg_gen_xor_vec(vece, rd, rd, rn);
5699}
5700
5701const GVecGen3 bsl_op = {
5702 .fni8 = gen_bsl_i64,
5703 .fniv = gen_bsl_vec,
5704 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5705 .load_dest = true
5706};
5707
5708const GVecGen3 bit_op = {
5709 .fni8 = gen_bit_i64,
5710 .fniv = gen_bit_vec,
5711 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5712 .load_dest = true
5713};
5714
5715const GVecGen3 bif_op = {
5716 .fni8 = gen_bif_i64,
5717 .fniv = gen_bif_vec,
5718 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5719 .load_dest = true
5720};
5721
41f6c113
RH
5722static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5723{
5724 tcg_gen_vec_sar8i_i64(a, a, shift);
5725 tcg_gen_vec_add8_i64(d, d, a);
5726}
5727
5728static void gen_ssra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5729{
5730 tcg_gen_vec_sar16i_i64(a, a, shift);
5731 tcg_gen_vec_add16_i64(d, d, a);
5732}
5733
5734static void gen_ssra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
5735{
5736 tcg_gen_sari_i32(a, a, shift);
5737 tcg_gen_add_i32(d, d, a);
5738}
5739
5740static void gen_ssra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5741{
5742 tcg_gen_sari_i64(a, a, shift);
5743 tcg_gen_add_i64(d, d, a);
5744}
5745
5746static void gen_ssra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
5747{
5748 tcg_gen_sari_vec(vece, a, a, sh);
5749 tcg_gen_add_vec(vece, d, d, a);
5750}
5751
5752const GVecGen2i ssra_op[4] = {
5753 { .fni8 = gen_ssra8_i64,
5754 .fniv = gen_ssra_vec,
5755 .load_dest = true,
5756 .opc = INDEX_op_sari_vec,
5757 .vece = MO_8 },
5758 { .fni8 = gen_ssra16_i64,
5759 .fniv = gen_ssra_vec,
5760 .load_dest = true,
5761 .opc = INDEX_op_sari_vec,
5762 .vece = MO_16 },
5763 { .fni4 = gen_ssra32_i32,
5764 .fniv = gen_ssra_vec,
5765 .load_dest = true,
5766 .opc = INDEX_op_sari_vec,
5767 .vece = MO_32 },
5768 { .fni8 = gen_ssra64_i64,
5769 .fniv = gen_ssra_vec,
5770 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5771 .load_dest = true,
5772 .opc = INDEX_op_sari_vec,
5773 .vece = MO_64 },
5774};
5775
5776static void gen_usra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5777{
5778 tcg_gen_vec_shr8i_i64(a, a, shift);
5779 tcg_gen_vec_add8_i64(d, d, a);
5780}
5781
5782static void gen_usra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5783{
5784 tcg_gen_vec_shr16i_i64(a, a, shift);
5785 tcg_gen_vec_add16_i64(d, d, a);
5786}
5787
5788static void gen_usra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
5789{
5790 tcg_gen_shri_i32(a, a, shift);
5791 tcg_gen_add_i32(d, d, a);
5792}
5793
5794static void gen_usra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5795{
5796 tcg_gen_shri_i64(a, a, shift);
5797 tcg_gen_add_i64(d, d, a);
5798}
5799
5800static void gen_usra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
5801{
5802 tcg_gen_shri_vec(vece, a, a, sh);
5803 tcg_gen_add_vec(vece, d, d, a);
5804}
5805
5806const GVecGen2i usra_op[4] = {
5807 { .fni8 = gen_usra8_i64,
5808 .fniv = gen_usra_vec,
5809 .load_dest = true,
5810 .opc = INDEX_op_shri_vec,
5811 .vece = MO_8, },
5812 { .fni8 = gen_usra16_i64,
5813 .fniv = gen_usra_vec,
5814 .load_dest = true,
5815 .opc = INDEX_op_shri_vec,
5816 .vece = MO_16, },
5817 { .fni4 = gen_usra32_i32,
5818 .fniv = gen_usra_vec,
5819 .load_dest = true,
5820 .opc = INDEX_op_shri_vec,
5821 .vece = MO_32, },
5822 { .fni8 = gen_usra64_i64,
5823 .fniv = gen_usra_vec,
5824 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5825 .load_dest = true,
5826 .opc = INDEX_op_shri_vec,
5827 .vece = MO_64, },
5828};
eabcd6fa 5829
f3cd8218
RH
5830static void gen_shr8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5831{
5832 uint64_t mask = dup_const(MO_8, 0xff >> shift);
5833 TCGv_i64 t = tcg_temp_new_i64();
5834
5835 tcg_gen_shri_i64(t, a, shift);
5836 tcg_gen_andi_i64(t, t, mask);
5837 tcg_gen_andi_i64(d, d, ~mask);
5838 tcg_gen_or_i64(d, d, t);
5839 tcg_temp_free_i64(t);
5840}
5841
5842static void gen_shr16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5843{
5844 uint64_t mask = dup_const(MO_16, 0xffff >> shift);
5845 TCGv_i64 t = tcg_temp_new_i64();
5846
5847 tcg_gen_shri_i64(t, a, shift);
5848 tcg_gen_andi_i64(t, t, mask);
5849 tcg_gen_andi_i64(d, d, ~mask);
5850 tcg_gen_or_i64(d, d, t);
5851 tcg_temp_free_i64(t);
5852}
5853
5854static void gen_shr32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
5855{
5856 tcg_gen_shri_i32(a, a, shift);
5857 tcg_gen_deposit_i32(d, d, a, 0, 32 - shift);
5858}
5859
5860static void gen_shr64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5861{
5862 tcg_gen_shri_i64(a, a, shift);
5863 tcg_gen_deposit_i64(d, d, a, 0, 64 - shift);
5864}
5865
5866static void gen_shr_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
5867{
5868 if (sh == 0) {
5869 tcg_gen_mov_vec(d, a);
5870 } else {
5871 TCGv_vec t = tcg_temp_new_vec_matching(d);
5872 TCGv_vec m = tcg_temp_new_vec_matching(d);
5873
5874 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK((8 << vece) - sh, sh));
5875 tcg_gen_shri_vec(vece, t, a, sh);
5876 tcg_gen_and_vec(vece, d, d, m);
5877 tcg_gen_or_vec(vece, d, d, t);
5878
5879 tcg_temp_free_vec(t);
5880 tcg_temp_free_vec(m);
5881 }
5882}
5883
5884const GVecGen2i sri_op[4] = {
5885 { .fni8 = gen_shr8_ins_i64,
5886 .fniv = gen_shr_ins_vec,
5887 .load_dest = true,
5888 .opc = INDEX_op_shri_vec,
5889 .vece = MO_8 },
5890 { .fni8 = gen_shr16_ins_i64,
5891 .fniv = gen_shr_ins_vec,
5892 .load_dest = true,
5893 .opc = INDEX_op_shri_vec,
5894 .vece = MO_16 },
5895 { .fni4 = gen_shr32_ins_i32,
5896 .fniv = gen_shr_ins_vec,
5897 .load_dest = true,
5898 .opc = INDEX_op_shri_vec,
5899 .vece = MO_32 },
5900 { .fni8 = gen_shr64_ins_i64,
5901 .fniv = gen_shr_ins_vec,
5902 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5903 .load_dest = true,
5904 .opc = INDEX_op_shri_vec,
5905 .vece = MO_64 },
5906};
5907
5908static void gen_shl8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5909{
5910 uint64_t mask = dup_const(MO_8, 0xff << shift);
5911 TCGv_i64 t = tcg_temp_new_i64();
5912
5913 tcg_gen_shli_i64(t, a, shift);
5914 tcg_gen_andi_i64(t, t, mask);
5915 tcg_gen_andi_i64(d, d, ~mask);
5916 tcg_gen_or_i64(d, d, t);
5917 tcg_temp_free_i64(t);
5918}
5919
5920static void gen_shl16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5921{
5922 uint64_t mask = dup_const(MO_16, 0xffff << shift);
5923 TCGv_i64 t = tcg_temp_new_i64();
5924
5925 tcg_gen_shli_i64(t, a, shift);
5926 tcg_gen_andi_i64(t, t, mask);
5927 tcg_gen_andi_i64(d, d, ~mask);
5928 tcg_gen_or_i64(d, d, t);
5929 tcg_temp_free_i64(t);
5930}
5931
5932static void gen_shl32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
5933{
5934 tcg_gen_deposit_i32(d, d, a, shift, 32 - shift);
5935}
5936
5937static void gen_shl64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5938{
5939 tcg_gen_deposit_i64(d, d, a, shift, 64 - shift);
5940}
5941
5942static void gen_shl_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
5943{
5944 if (sh == 0) {
5945 tcg_gen_mov_vec(d, a);
5946 } else {
5947 TCGv_vec t = tcg_temp_new_vec_matching(d);
5948 TCGv_vec m = tcg_temp_new_vec_matching(d);
5949
5950 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK(0, sh));
5951 tcg_gen_shli_vec(vece, t, a, sh);
5952 tcg_gen_and_vec(vece, d, d, m);
5953 tcg_gen_or_vec(vece, d, d, t);
5954
5955 tcg_temp_free_vec(t);
5956 tcg_temp_free_vec(m);
5957 }
5958}
5959
5960const GVecGen2i sli_op[4] = {
5961 { .fni8 = gen_shl8_ins_i64,
5962 .fniv = gen_shl_ins_vec,
5963 .load_dest = true,
5964 .opc = INDEX_op_shli_vec,
5965 .vece = MO_8 },
5966 { .fni8 = gen_shl16_ins_i64,
5967 .fniv = gen_shl_ins_vec,
5968 .load_dest = true,
5969 .opc = INDEX_op_shli_vec,
5970 .vece = MO_16 },
5971 { .fni4 = gen_shl32_ins_i32,
5972 .fniv = gen_shl_ins_vec,
5973 .load_dest = true,
5974 .opc = INDEX_op_shli_vec,
5975 .vece = MO_32 },
5976 { .fni8 = gen_shl64_ins_i64,
5977 .fniv = gen_shl_ins_vec,
5978 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5979 .load_dest = true,
5980 .opc = INDEX_op_shli_vec,
5981 .vece = MO_64 },
5982};
5983
4a7832b0
RH
5984static void gen_mla8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
5985{
5986 gen_helper_neon_mul_u8(a, a, b);
5987 gen_helper_neon_add_u8(d, d, a);
5988}
5989
5990static void gen_mls8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
5991{
5992 gen_helper_neon_mul_u8(a, a, b);
5993 gen_helper_neon_sub_u8(d, d, a);
5994}
5995
5996static void gen_mla16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
5997{
5998 gen_helper_neon_mul_u16(a, a, b);
5999 gen_helper_neon_add_u16(d, d, a);
6000}
6001
6002static void gen_mls16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
6003{
6004 gen_helper_neon_mul_u16(a, a, b);
6005 gen_helper_neon_sub_u16(d, d, a);
6006}
6007
6008static void gen_mla32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
6009{
6010 tcg_gen_mul_i32(a, a, b);
6011 tcg_gen_add_i32(d, d, a);
6012}
6013
6014static void gen_mls32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
6015{
6016 tcg_gen_mul_i32(a, a, b);
6017 tcg_gen_sub_i32(d, d, a);
6018}
6019
6020static void gen_mla64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
6021{
6022 tcg_gen_mul_i64(a, a, b);
6023 tcg_gen_add_i64(d, d, a);
6024}
6025
6026static void gen_mls64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
6027{
6028 tcg_gen_mul_i64(a, a, b);
6029 tcg_gen_sub_i64(d, d, a);
6030}
6031
6032static void gen_mla_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
6033{
6034 tcg_gen_mul_vec(vece, a, a, b);
6035 tcg_gen_add_vec(vece, d, d, a);
6036}
6037
6038static void gen_mls_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
6039{
6040 tcg_gen_mul_vec(vece, a, a, b);
6041 tcg_gen_sub_vec(vece, d, d, a);
6042}
6043
6044/* Note that while NEON does not support VMLA and VMLS as 64-bit ops,
6045 * these tables are shared with AArch64 which does support them.
6046 */
6047const GVecGen3 mla_op[4] = {
6048 { .fni4 = gen_mla8_i32,
6049 .fniv = gen_mla_vec,
6050 .opc = INDEX_op_mul_vec,
6051 .load_dest = true,
6052 .vece = MO_8 },
6053 { .fni4 = gen_mla16_i32,
6054 .fniv = gen_mla_vec,
6055 .opc = INDEX_op_mul_vec,
6056 .load_dest = true,
6057 .vece = MO_16 },
6058 { .fni4 = gen_mla32_i32,
6059 .fniv = gen_mla_vec,
6060 .opc = INDEX_op_mul_vec,
6061 .load_dest = true,
6062 .vece = MO_32 },
6063 { .fni8 = gen_mla64_i64,
6064 .fniv = gen_mla_vec,
6065 .opc = INDEX_op_mul_vec,
6066 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
6067 .load_dest = true,
6068 .vece = MO_64 },
6069};
6070
6071const GVecGen3 mls_op[4] = {
6072 { .fni4 = gen_mls8_i32,
6073 .fniv = gen_mls_vec,
6074 .opc = INDEX_op_mul_vec,
6075 .load_dest = true,
6076 .vece = MO_8 },
6077 { .fni4 = gen_mls16_i32,
6078 .fniv = gen_mls_vec,
6079 .opc = INDEX_op_mul_vec,
6080 .load_dest = true,
6081 .vece = MO_16 },
6082 { .fni4 = gen_mls32_i32,
6083 .fniv = gen_mls_vec,
6084 .opc = INDEX_op_mul_vec,
6085 .load_dest = true,
6086 .vece = MO_32 },
6087 { .fni8 = gen_mls64_i64,
6088 .fniv = gen_mls_vec,
6089 .opc = INDEX_op_mul_vec,
6090 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
6091 .load_dest = true,
6092 .vece = MO_64 },
6093};
6094
ea580fa3
RH
6095/* CMTST : test is "if (X & Y != 0)". */
6096static void gen_cmtst_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
6097{
6098 tcg_gen_and_i32(d, a, b);
6099 tcg_gen_setcondi_i32(TCG_COND_NE, d, d, 0);
6100 tcg_gen_neg_i32(d, d);
6101}
6102
6103void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
6104{
6105 tcg_gen_and_i64(d, a, b);
6106 tcg_gen_setcondi_i64(TCG_COND_NE, d, d, 0);
6107 tcg_gen_neg_i64(d, d);
6108}
6109
6110static void gen_cmtst_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
6111{
6112 tcg_gen_and_vec(vece, d, a, b);
6113 tcg_gen_dupi_vec(vece, a, 0);
6114 tcg_gen_cmp_vec(TCG_COND_NE, vece, d, d, a);
6115}
6116
6117const GVecGen3 cmtst_op[4] = {
6118 { .fni4 = gen_helper_neon_tst_u8,
6119 .fniv = gen_cmtst_vec,
6120 .vece = MO_8 },
6121 { .fni4 = gen_helper_neon_tst_u16,
6122 .fniv = gen_cmtst_vec,
6123 .vece = MO_16 },
6124 { .fni4 = gen_cmtst_i32,
6125 .fniv = gen_cmtst_vec,
6126 .vece = MO_32 },
6127 { .fni8 = gen_cmtst_i64,
6128 .fniv = gen_cmtst_vec,
6129 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
6130 .vece = MO_64 },
6131};
6132
9ee6e8bb
PB
6133/* Translate a NEON data processing instruction. Return nonzero if the
6134 instruction is invalid.
ad69471c
PB
6135 We process data in a mixture of 32-bit and 64-bit chunks.
6136 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
2c0262af 6137
7dcc1f89 6138static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
9ee6e8bb
PB
6139{
6140 int op;
6141 int q;
eabcd6fa 6142 int rd, rn, rm, rd_ofs, rn_ofs, rm_ofs;
9ee6e8bb
PB
6143 int size;
6144 int shift;
6145 int pass;
6146 int count;
6147 int pairwise;
6148 int u;
eabcd6fa 6149 int vec_size;
f3cd8218 6150 uint32_t imm;
39d5492a 6151 TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
1a66ac61 6152 TCGv_ptr ptr1, ptr2, ptr3;
a7812ae4 6153 TCGv_i64 tmp64;
9ee6e8bb 6154
2c7ffc41
PM
6155 /* FIXME: this access check should not take precedence over UNDEF
6156 * for invalid encodings; we will generate incorrect syndrome information
6157 * for attempts to execute invalid vfp/neon encodings with FP disabled.
6158 */
9dbbc748 6159 if (s->fp_excp_el) {
2c7ffc41 6160 gen_exception_insn(s, 4, EXCP_UDEF,
4be42f40 6161 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
2c7ffc41
PM
6162 return 0;
6163 }
6164
5df8bac1 6165 if (!s->vfp_enabled)
9ee6e8bb
PB
6166 return 1;
6167 q = (insn & (1 << 6)) != 0;
6168 u = (insn >> 24) & 1;
6169 VFP_DREG_D(rd, insn);
6170 VFP_DREG_N(rn, insn);
6171 VFP_DREG_M(rm, insn);
6172 size = (insn >> 20) & 3;
eabcd6fa
RH
6173 vec_size = q ? 16 : 8;
6174 rd_ofs = neon_reg_offset(rd, 0);
6175 rn_ofs = neon_reg_offset(rn, 0);
6176 rm_ofs = neon_reg_offset(rm, 0);
6177
9ee6e8bb
PB
6178 if ((insn & (1 << 23)) == 0) {
6179 /* Three register same length. */
6180 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
62698be3
PM
6181 /* Catch invalid op and bad size combinations: UNDEF */
6182 if ((neon_3r_sizes[op] & (1 << size)) == 0) {
6183 return 1;
6184 }
25f84f79
PM
6185 /* All insns of this form UNDEF for either this condition or the
6186 * superset of cases "Q==1"; we catch the latter later.
6187 */
6188 if (q && ((rd | rn | rm) & 1)) {
6189 return 1;
6190 }
36a71934
RH
6191 switch (op) {
6192 case NEON_3R_SHA:
6193 /* The SHA-1/SHA-256 3-register instructions require special
6194 * treatment here, as their size field is overloaded as an
6195 * op type selector, and they all consume their input in a
6196 * single pass.
6197 */
f1ecb913
AB
6198 if (!q) {
6199 return 1;
6200 }
6201 if (!u) { /* SHA-1 */
962fcbf2 6202 if (!dc_isar_feature(aa32_sha1, s)) {
f1ecb913
AB
6203 return 1;
6204 }
1a66ac61
RH
6205 ptr1 = vfp_reg_ptr(true, rd);
6206 ptr2 = vfp_reg_ptr(true, rn);
6207 ptr3 = vfp_reg_ptr(true, rm);
f1ecb913 6208 tmp4 = tcg_const_i32(size);
1a66ac61 6209 gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp4);
f1ecb913
AB
6210 tcg_temp_free_i32(tmp4);
6211 } else { /* SHA-256 */
962fcbf2 6212 if (!dc_isar_feature(aa32_sha2, s) || size == 3) {
f1ecb913
AB
6213 return 1;
6214 }
1a66ac61
RH
6215 ptr1 = vfp_reg_ptr(true, rd);
6216 ptr2 = vfp_reg_ptr(true, rn);
6217 ptr3 = vfp_reg_ptr(true, rm);
f1ecb913
AB
6218 switch (size) {
6219 case 0:
1a66ac61 6220 gen_helper_crypto_sha256h(ptr1, ptr2, ptr3);
f1ecb913
AB
6221 break;
6222 case 1:
1a66ac61 6223 gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3);
f1ecb913
AB
6224 break;
6225 case 2:
1a66ac61 6226 gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3);
f1ecb913
AB
6227 break;
6228 }
6229 }
1a66ac61
RH
6230 tcg_temp_free_ptr(ptr1);
6231 tcg_temp_free_ptr(ptr2);
6232 tcg_temp_free_ptr(ptr3);
f1ecb913 6233 return 0;
36a71934
RH
6234
6235 case NEON_3R_VPADD_VQRDMLAH:
6236 if (!u) {
6237 break; /* VPADD */
6238 }
6239 /* VQRDMLAH */
6240 switch (size) {
6241 case 1:
6242 return do_v81_helper(s, gen_helper_gvec_qrdmlah_s16,
6243 q, rd, rn, rm);
6244 case 2:
6245 return do_v81_helper(s, gen_helper_gvec_qrdmlah_s32,
6246 q, rd, rn, rm);
6247 }
6248 return 1;
6249
6250 case NEON_3R_VFM_VQRDMLSH:
6251 if (!u) {
6252 /* VFM, VFMS */
6253 if (size == 1) {
6254 return 1;
6255 }
6256 break;
6257 }
6258 /* VQRDMLSH */
6259 switch (size) {
6260 case 1:
6261 return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s16,
6262 q, rd, rn, rm);
6263 case 2:
6264 return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s32,
6265 q, rd, rn, rm);
6266 }
6267 return 1;
eabcd6fa
RH
6268
6269 case NEON_3R_LOGIC: /* Logic ops. */
6270 switch ((u << 2) | size) {
6271 case 0: /* VAND */
6272 tcg_gen_gvec_and(0, rd_ofs, rn_ofs, rm_ofs,
6273 vec_size, vec_size);
6274 break;
6275 case 1: /* VBIC */
6276 tcg_gen_gvec_andc(0, rd_ofs, rn_ofs, rm_ofs,
6277 vec_size, vec_size);
6278 break;
6279 case 2:
6280 if (rn == rm) {
6281 /* VMOV */
6282 tcg_gen_gvec_mov(0, rd_ofs, rn_ofs, vec_size, vec_size);
6283 } else {
6284 /* VORR */
6285 tcg_gen_gvec_or(0, rd_ofs, rn_ofs, rm_ofs,
6286 vec_size, vec_size);
6287 }
6288 break;
6289 case 3: /* VORN */
6290 tcg_gen_gvec_orc(0, rd_ofs, rn_ofs, rm_ofs,
6291 vec_size, vec_size);
6292 break;
6293 case 4: /* VEOR */
6294 tcg_gen_gvec_xor(0, rd_ofs, rn_ofs, rm_ofs,
6295 vec_size, vec_size);
6296 break;
6297 case 5: /* VBSL */
6298 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
6299 vec_size, vec_size, &bsl_op);
6300 break;
6301 case 6: /* VBIT */
6302 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
6303 vec_size, vec_size, &bit_op);
6304 break;
6305 case 7: /* VBIF */
6306 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
6307 vec_size, vec_size, &bif_op);
6308 break;
6309 }
6310 return 0;
e4717ae0
RH
6311
6312 case NEON_3R_VADD_VSUB:
6313 if (u) {
6314 tcg_gen_gvec_sub(size, rd_ofs, rn_ofs, rm_ofs,
6315 vec_size, vec_size);
6316 } else {
6317 tcg_gen_gvec_add(size, rd_ofs, rn_ofs, rm_ofs,
6318 vec_size, vec_size);
6319 }
6320 return 0;
82083184
RH
6321
6322 case NEON_3R_VMUL: /* VMUL */
6323 if (u) {
6324 /* Polynomial case allows only P8 and is handled below. */
6325 if (size != 0) {
6326 return 1;
6327 }
6328 } else {
6329 tcg_gen_gvec_mul(size, rd_ofs, rn_ofs, rm_ofs,
6330 vec_size, vec_size);
6331 return 0;
6332 }
6333 break;
4a7832b0
RH
6334
6335 case NEON_3R_VML: /* VMLA, VMLS */
6336 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size,
6337 u ? &mls_op[size] : &mla_op[size]);
6338 return 0;
ea580fa3
RH
6339
6340 case NEON_3R_VTST_VCEQ:
6341 if (u) { /* VCEQ */
6342 tcg_gen_gvec_cmp(TCG_COND_EQ, size, rd_ofs, rn_ofs, rm_ofs,
6343 vec_size, vec_size);
6344 } else { /* VTST */
6345 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
6346 vec_size, vec_size, &cmtst_op[size]);
6347 }
6348 return 0;
6349
6350 case NEON_3R_VCGT:
6351 tcg_gen_gvec_cmp(u ? TCG_COND_GTU : TCG_COND_GT, size,
6352 rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
6353 return 0;
6354
6355 case NEON_3R_VCGE:
6356 tcg_gen_gvec_cmp(u ? TCG_COND_GEU : TCG_COND_GE, size,
6357 rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
6358 return 0;
f1ecb913 6359 }
4a7832b0 6360
eabcd6fa 6361 if (size == 3) {
62698be3 6362 /* 64-bit element instructions. */
9ee6e8bb 6363 for (pass = 0; pass < (q ? 2 : 1); pass++) {
ad69471c
PB
6364 neon_load_reg64(cpu_V0, rn + pass);
6365 neon_load_reg64(cpu_V1, rm + pass);
9ee6e8bb 6366 switch (op) {
62698be3 6367 case NEON_3R_VQADD:
9ee6e8bb 6368 if (u) {
02da0b2d
PM
6369 gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
6370 cpu_V0, cpu_V1);
2c0262af 6371 } else {
02da0b2d
PM
6372 gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
6373 cpu_V0, cpu_V1);
2c0262af 6374 }
9ee6e8bb 6375 break;
62698be3 6376 case NEON_3R_VQSUB:
9ee6e8bb 6377 if (u) {
02da0b2d
PM
6378 gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
6379 cpu_V0, cpu_V1);
ad69471c 6380 } else {
02da0b2d
PM
6381 gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
6382 cpu_V0, cpu_V1);
ad69471c
PB
6383 }
6384 break;
62698be3 6385 case NEON_3R_VSHL:
ad69471c
PB
6386 if (u) {
6387 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
6388 } else {
6389 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
6390 }
6391 break;
62698be3 6392 case NEON_3R_VQSHL:
ad69471c 6393 if (u) {
02da0b2d
PM
6394 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
6395 cpu_V1, cpu_V0);
ad69471c 6396 } else {
02da0b2d
PM
6397 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
6398 cpu_V1, cpu_V0);
ad69471c
PB
6399 }
6400 break;
62698be3 6401 case NEON_3R_VRSHL:
ad69471c
PB
6402 if (u) {
6403 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
1e8d4eec 6404 } else {
ad69471c
PB
6405 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
6406 }
6407 break;
62698be3 6408 case NEON_3R_VQRSHL:
ad69471c 6409 if (u) {
02da0b2d
PM
6410 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
6411 cpu_V1, cpu_V0);
ad69471c 6412 } else {
02da0b2d
PM
6413 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
6414 cpu_V1, cpu_V0);
1e8d4eec 6415 }
9ee6e8bb 6416 break;
9ee6e8bb
PB
6417 default:
6418 abort();
2c0262af 6419 }
ad69471c 6420 neon_store_reg64(cpu_V0, rd + pass);
2c0262af 6421 }
9ee6e8bb 6422 return 0;
2c0262af 6423 }
25f84f79 6424 pairwise = 0;
9ee6e8bb 6425 switch (op) {
62698be3
PM
6426 case NEON_3R_VSHL:
6427 case NEON_3R_VQSHL:
6428 case NEON_3R_VRSHL:
6429 case NEON_3R_VQRSHL:
9ee6e8bb 6430 {
ad69471c
PB
6431 int rtmp;
6432 /* Shift instruction operands are reversed. */
6433 rtmp = rn;
9ee6e8bb 6434 rn = rm;
ad69471c 6435 rm = rtmp;
9ee6e8bb 6436 }
2c0262af 6437 break;
36a71934 6438 case NEON_3R_VPADD_VQRDMLAH:
62698be3
PM
6439 case NEON_3R_VPMAX:
6440 case NEON_3R_VPMIN:
9ee6e8bb 6441 pairwise = 1;
2c0262af 6442 break;
25f84f79
PM
6443 case NEON_3R_FLOAT_ARITH:
6444 pairwise = (u && size < 2); /* if VPADD (float) */
6445 break;
6446 case NEON_3R_FLOAT_MINMAX:
6447 pairwise = u; /* if VPMIN/VPMAX (float) */
6448 break;
6449 case NEON_3R_FLOAT_CMP:
6450 if (!u && size) {
6451 /* no encoding for U=0 C=1x */
6452 return 1;
6453 }
6454 break;
6455 case NEON_3R_FLOAT_ACMP:
6456 if (!u) {
6457 return 1;
6458 }
6459 break;
505935fc
WN
6460 case NEON_3R_FLOAT_MISC:
6461 /* VMAXNM/VMINNM in ARMv8 */
d614a513 6462 if (u && !arm_dc_feature(s, ARM_FEATURE_V8)) {
25f84f79
PM
6463 return 1;
6464 }
2c0262af 6465 break;
36a71934
RH
6466 case NEON_3R_VFM_VQRDMLSH:
6467 if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
da97f52c
PM
6468 return 1;
6469 }
6470 break;
9ee6e8bb 6471 default:
2c0262af 6472 break;
9ee6e8bb 6473 }
dd8fbd78 6474
25f84f79
PM
6475 if (pairwise && q) {
6476 /* All the pairwise insns UNDEF if Q is set */
6477 return 1;
6478 }
6479
9ee6e8bb
PB
6480 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6481
6482 if (pairwise) {
6483 /* Pairwise. */
a5a14945
JR
6484 if (pass < 1) {
6485 tmp = neon_load_reg(rn, 0);
6486 tmp2 = neon_load_reg(rn, 1);
9ee6e8bb 6487 } else {
a5a14945
JR
6488 tmp = neon_load_reg(rm, 0);
6489 tmp2 = neon_load_reg(rm, 1);
9ee6e8bb
PB
6490 }
6491 } else {
6492 /* Elementwise. */
dd8fbd78
FN
6493 tmp = neon_load_reg(rn, pass);
6494 tmp2 = neon_load_reg(rm, pass);
9ee6e8bb
PB
6495 }
6496 switch (op) {
62698be3 6497 case NEON_3R_VHADD:
9ee6e8bb
PB
6498 GEN_NEON_INTEGER_OP(hadd);
6499 break;
62698be3 6500 case NEON_3R_VQADD:
02da0b2d 6501 GEN_NEON_INTEGER_OP_ENV(qadd);
2c0262af 6502 break;
62698be3 6503 case NEON_3R_VRHADD:
9ee6e8bb 6504 GEN_NEON_INTEGER_OP(rhadd);
2c0262af 6505 break;
62698be3 6506 case NEON_3R_VHSUB:
9ee6e8bb
PB
6507 GEN_NEON_INTEGER_OP(hsub);
6508 break;
62698be3 6509 case NEON_3R_VQSUB:
02da0b2d 6510 GEN_NEON_INTEGER_OP_ENV(qsub);
2c0262af 6511 break;
62698be3 6512 case NEON_3R_VSHL:
ad69471c 6513 GEN_NEON_INTEGER_OP(shl);
2c0262af 6514 break;
62698be3 6515 case NEON_3R_VQSHL:
02da0b2d 6516 GEN_NEON_INTEGER_OP_ENV(qshl);
2c0262af 6517 break;
62698be3 6518 case NEON_3R_VRSHL:
ad69471c 6519 GEN_NEON_INTEGER_OP(rshl);
2c0262af 6520 break;
62698be3 6521 case NEON_3R_VQRSHL:
02da0b2d 6522 GEN_NEON_INTEGER_OP_ENV(qrshl);
9ee6e8bb 6523 break;
62698be3 6524 case NEON_3R_VMAX:
9ee6e8bb
PB
6525 GEN_NEON_INTEGER_OP(max);
6526 break;
62698be3 6527 case NEON_3R_VMIN:
9ee6e8bb
PB
6528 GEN_NEON_INTEGER_OP(min);
6529 break;
62698be3 6530 case NEON_3R_VABD:
9ee6e8bb
PB
6531 GEN_NEON_INTEGER_OP(abd);
6532 break;
62698be3 6533 case NEON_3R_VABA:
9ee6e8bb 6534 GEN_NEON_INTEGER_OP(abd);
7d1b0095 6535 tcg_temp_free_i32(tmp2);
dd8fbd78
FN
6536 tmp2 = neon_load_reg(rd, pass);
6537 gen_neon_add(size, tmp, tmp2);
9ee6e8bb 6538 break;
62698be3 6539 case NEON_3R_VMUL:
82083184
RH
6540 /* VMUL.P8; other cases already eliminated. */
6541 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
9ee6e8bb 6542 break;
62698be3 6543 case NEON_3R_VPMAX:
9ee6e8bb
PB
6544 GEN_NEON_INTEGER_OP(pmax);
6545 break;
62698be3 6546 case NEON_3R_VPMIN:
9ee6e8bb
PB
6547 GEN_NEON_INTEGER_OP(pmin);
6548 break;
62698be3 6549 case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
9ee6e8bb
PB
6550 if (!u) { /* VQDMULH */
6551 switch (size) {
02da0b2d
PM
6552 case 1:
6553 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
6554 break;
6555 case 2:
6556 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
6557 break;
62698be3 6558 default: abort();
9ee6e8bb 6559 }
62698be3 6560 } else { /* VQRDMULH */
9ee6e8bb 6561 switch (size) {
02da0b2d
PM
6562 case 1:
6563 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
6564 break;
6565 case 2:
6566 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
6567 break;
62698be3 6568 default: abort();
9ee6e8bb
PB
6569 }
6570 }
6571 break;
36a71934 6572 case NEON_3R_VPADD_VQRDMLAH:
9ee6e8bb 6573 switch (size) {
dd8fbd78
FN
6574 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
6575 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
6576 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
62698be3 6577 default: abort();
9ee6e8bb
PB
6578 }
6579 break;
62698be3 6580 case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
aa47cfdd
PM
6581 {
6582 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
9ee6e8bb
PB
6583 switch ((u << 2) | size) {
6584 case 0: /* VADD */
aa47cfdd
PM
6585 case 4: /* VPADD */
6586 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
9ee6e8bb
PB
6587 break;
6588 case 2: /* VSUB */
aa47cfdd 6589 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
9ee6e8bb
PB
6590 break;
6591 case 6: /* VABD */
aa47cfdd 6592 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
9ee6e8bb
PB
6593 break;
6594 default:
62698be3 6595 abort();
9ee6e8bb 6596 }
aa47cfdd 6597 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6598 break;
aa47cfdd 6599 }
62698be3 6600 case NEON_3R_FLOAT_MULTIPLY:
aa47cfdd
PM
6601 {
6602 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6603 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
9ee6e8bb 6604 if (!u) {
7d1b0095 6605 tcg_temp_free_i32(tmp2);
dd8fbd78 6606 tmp2 = neon_load_reg(rd, pass);
9ee6e8bb 6607 if (size == 0) {
aa47cfdd 6608 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
9ee6e8bb 6609 } else {
aa47cfdd 6610 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
9ee6e8bb
PB
6611 }
6612 }
aa47cfdd 6613 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6614 break;
aa47cfdd 6615 }
62698be3 6616 case NEON_3R_FLOAT_CMP:
aa47cfdd
PM
6617 {
6618 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
9ee6e8bb 6619 if (!u) {
aa47cfdd 6620 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
b5ff1b31 6621 } else {
aa47cfdd
PM
6622 if (size == 0) {
6623 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
6624 } else {
6625 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
6626 }
b5ff1b31 6627 }
aa47cfdd 6628 tcg_temp_free_ptr(fpstatus);
2c0262af 6629 break;
aa47cfdd 6630 }
62698be3 6631 case NEON_3R_FLOAT_ACMP:
aa47cfdd
PM
6632 {
6633 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6634 if (size == 0) {
6635 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
6636 } else {
6637 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
6638 }
6639 tcg_temp_free_ptr(fpstatus);
2c0262af 6640 break;
aa47cfdd 6641 }
62698be3 6642 case NEON_3R_FLOAT_MINMAX:
aa47cfdd
PM
6643 {
6644 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6645 if (size == 0) {
f71a2ae5 6646 gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus);
aa47cfdd 6647 } else {
f71a2ae5 6648 gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus);
aa47cfdd
PM
6649 }
6650 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6651 break;
aa47cfdd 6652 }
505935fc
WN
6653 case NEON_3R_FLOAT_MISC:
6654 if (u) {
6655 /* VMAXNM/VMINNM */
6656 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6657 if (size == 0) {
f71a2ae5 6658 gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus);
505935fc 6659 } else {
f71a2ae5 6660 gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus);
505935fc
WN
6661 }
6662 tcg_temp_free_ptr(fpstatus);
6663 } else {
6664 if (size == 0) {
6665 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
6666 } else {
6667 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
6668 }
6669 }
2c0262af 6670 break;
36a71934 6671 case NEON_3R_VFM_VQRDMLSH:
da97f52c
PM
6672 {
6673 /* VFMA, VFMS: fused multiply-add */
6674 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6675 TCGv_i32 tmp3 = neon_load_reg(rd, pass);
6676 if (size) {
6677 /* VFMS */
6678 gen_helper_vfp_negs(tmp, tmp);
6679 }
6680 gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus);
6681 tcg_temp_free_i32(tmp3);
6682 tcg_temp_free_ptr(fpstatus);
6683 break;
6684 }
9ee6e8bb
PB
6685 default:
6686 abort();
2c0262af 6687 }
7d1b0095 6688 tcg_temp_free_i32(tmp2);
dd8fbd78 6689
9ee6e8bb
PB
6690 /* Save the result. For elementwise operations we can put it
6691 straight into the destination register. For pairwise operations
6692 we have to be careful to avoid clobbering the source operands. */
6693 if (pairwise && rd == rm) {
dd8fbd78 6694 neon_store_scratch(pass, tmp);
9ee6e8bb 6695 } else {
dd8fbd78 6696 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
6697 }
6698
6699 } /* for pass */
6700 if (pairwise && rd == rm) {
6701 for (pass = 0; pass < (q ? 4 : 2); pass++) {
dd8fbd78
FN
6702 tmp = neon_load_scratch(pass);
6703 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
6704 }
6705 }
ad69471c 6706 /* End of 3 register same size operations. */
9ee6e8bb
PB
6707 } else if (insn & (1 << 4)) {
6708 if ((insn & 0x00380080) != 0) {
6709 /* Two registers and shift. */
6710 op = (insn >> 8) & 0xf;
6711 if (insn & (1 << 7)) {
cc13115b
PM
6712 /* 64-bit shift. */
6713 if (op > 7) {
6714 return 1;
6715 }
9ee6e8bb
PB
6716 size = 3;
6717 } else {
6718 size = 2;
6719 while ((insn & (1 << (size + 19))) == 0)
6720 size--;
6721 }
6722 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
9ee6e8bb
PB
6723 if (op < 8) {
6724 /* Shift by immediate:
6725 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
cc13115b
PM
6726 if (q && ((rd | rm) & 1)) {
6727 return 1;
6728 }
6729 if (!u && (op == 4 || op == 6)) {
6730 return 1;
6731 }
9ee6e8bb
PB
6732 /* Right shifts are encoded as N - shift, where N is the
6733 element size in bits. */
1dc8425e 6734 if (op <= 4) {
9ee6e8bb 6735 shift = shift - (1 << (size + 3));
1dc8425e
RH
6736 }
6737
6738 switch (op) {
6739 case 0: /* VSHR */
6740 /* Right shift comes here negative. */
6741 shift = -shift;
6742 /* Shifts larger than the element size are architecturally
6743 * valid. Unsigned results in all zeros; signed results
6744 * in all sign bits.
6745 */
6746 if (!u) {
6747 tcg_gen_gvec_sari(size, rd_ofs, rm_ofs,
6748 MIN(shift, (8 << size) - 1),
6749 vec_size, vec_size);
6750 } else if (shift >= 8 << size) {
6751 tcg_gen_gvec_dup8i(rd_ofs, vec_size, vec_size, 0);
6752 } else {
6753 tcg_gen_gvec_shri(size, rd_ofs, rm_ofs, shift,
6754 vec_size, vec_size);
6755 }
6756 return 0;
6757
41f6c113
RH
6758 case 1: /* VSRA */
6759 /* Right shift comes here negative. */
6760 shift = -shift;
6761 /* Shifts larger than the element size are architecturally
6762 * valid. Unsigned results in all zeros; signed results
6763 * in all sign bits.
6764 */
6765 if (!u) {
6766 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
6767 MIN(shift, (8 << size) - 1),
6768 &ssra_op[size]);
6769 } else if (shift >= 8 << size) {
6770 /* rd += 0 */
6771 } else {
6772 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
6773 shift, &usra_op[size]);
6774 }
6775 return 0;
6776
f3cd8218
RH
6777 case 4: /* VSRI */
6778 if (!u) {
6779 return 1;
6780 }
6781 /* Right shift comes here negative. */
6782 shift = -shift;
6783 /* Shift out of range leaves destination unchanged. */
6784 if (shift < 8 << size) {
6785 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
6786 shift, &sri_op[size]);
6787 }
6788 return 0;
6789
1dc8425e 6790 case 5: /* VSHL, VSLI */
f3cd8218
RH
6791 if (u) { /* VSLI */
6792 /* Shift out of range leaves destination unchanged. */
6793 if (shift < 8 << size) {
6794 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size,
6795 vec_size, shift, &sli_op[size]);
6796 }
6797 } else { /* VSHL */
1dc8425e
RH
6798 /* Shifts larger than the element size are
6799 * architecturally valid and results in zero.
6800 */
6801 if (shift >= 8 << size) {
6802 tcg_gen_gvec_dup8i(rd_ofs, vec_size, vec_size, 0);
6803 } else {
6804 tcg_gen_gvec_shli(size, rd_ofs, rm_ofs, shift,
6805 vec_size, vec_size);
6806 }
1dc8425e 6807 }
f3cd8218 6808 return 0;
1dc8425e
RH
6809 }
6810
9ee6e8bb
PB
6811 if (size == 3) {
6812 count = q + 1;
6813 } else {
6814 count = q ? 4: 2;
6815 }
1dc8425e
RH
6816
6817 /* To avoid excessive duplication of ops we implement shift
6818 * by immediate using the variable shift operations.
6819 */
6820 imm = dup_const(size, shift);
9ee6e8bb
PB
6821
6822 for (pass = 0; pass < count; pass++) {
ad69471c
PB
6823 if (size == 3) {
6824 neon_load_reg64(cpu_V0, rm + pass);
6825 tcg_gen_movi_i64(cpu_V1, imm);
6826 switch (op) {
ad69471c
PB
6827 case 2: /* VRSHR */
6828 case 3: /* VRSRA */
6829 if (u)
6830 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
9ee6e8bb 6831 else
ad69471c 6832 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
9ee6e8bb 6833 break;
0322b26e 6834 case 6: /* VQSHLU */
02da0b2d
PM
6835 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
6836 cpu_V0, cpu_V1);
ad69471c 6837 break;
0322b26e
PM
6838 case 7: /* VQSHL */
6839 if (u) {
02da0b2d 6840 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
0322b26e
PM
6841 cpu_V0, cpu_V1);
6842 } else {
02da0b2d 6843 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
0322b26e
PM
6844 cpu_V0, cpu_V1);
6845 }
9ee6e8bb 6846 break;
1dc8425e
RH
6847 default:
6848 g_assert_not_reached();
9ee6e8bb 6849 }
41f6c113 6850 if (op == 3) {
ad69471c 6851 /* Accumulate. */
5371cb81 6852 neon_load_reg64(cpu_V1, rd + pass);
ad69471c 6853 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
ad69471c
PB
6854 }
6855 neon_store_reg64(cpu_V0, rd + pass);
6856 } else { /* size < 3 */
6857 /* Operands in T0 and T1. */
dd8fbd78 6858 tmp = neon_load_reg(rm, pass);
7d1b0095 6859 tmp2 = tcg_temp_new_i32();
dd8fbd78 6860 tcg_gen_movi_i32(tmp2, imm);
ad69471c 6861 switch (op) {
ad69471c
PB
6862 case 2: /* VRSHR */
6863 case 3: /* VRSRA */
6864 GEN_NEON_INTEGER_OP(rshl);
6865 break;
0322b26e 6866 case 6: /* VQSHLU */
ad69471c 6867 switch (size) {
0322b26e 6868 case 0:
02da0b2d
PM
6869 gen_helper_neon_qshlu_s8(tmp, cpu_env,
6870 tmp, tmp2);
0322b26e
PM
6871 break;
6872 case 1:
02da0b2d
PM
6873 gen_helper_neon_qshlu_s16(tmp, cpu_env,
6874 tmp, tmp2);
0322b26e
PM
6875 break;
6876 case 2:
02da0b2d
PM
6877 gen_helper_neon_qshlu_s32(tmp, cpu_env,
6878 tmp, tmp2);
0322b26e
PM
6879 break;
6880 default:
cc13115b 6881 abort();
ad69471c
PB
6882 }
6883 break;
0322b26e 6884 case 7: /* VQSHL */
02da0b2d 6885 GEN_NEON_INTEGER_OP_ENV(qshl);
0322b26e 6886 break;
1dc8425e
RH
6887 default:
6888 g_assert_not_reached();
ad69471c 6889 }
7d1b0095 6890 tcg_temp_free_i32(tmp2);
ad69471c 6891
41f6c113 6892 if (op == 3) {
ad69471c 6893 /* Accumulate. */
dd8fbd78 6894 tmp2 = neon_load_reg(rd, pass);
5371cb81 6895 gen_neon_add(size, tmp, tmp2);
7d1b0095 6896 tcg_temp_free_i32(tmp2);
ad69471c 6897 }
dd8fbd78 6898 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
6899 }
6900 } /* for pass */
6901 } else if (op < 10) {
ad69471c 6902 /* Shift by immediate and narrow:
9ee6e8bb 6903 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
0b36f4cd 6904 int input_unsigned = (op == 8) ? !u : u;
cc13115b
PM
6905 if (rm & 1) {
6906 return 1;
6907 }
9ee6e8bb
PB
6908 shift = shift - (1 << (size + 3));
6909 size++;
92cdfaeb 6910 if (size == 3) {
a7812ae4 6911 tmp64 = tcg_const_i64(shift);
92cdfaeb
PM
6912 neon_load_reg64(cpu_V0, rm);
6913 neon_load_reg64(cpu_V1, rm + 1);
6914 for (pass = 0; pass < 2; pass++) {
6915 TCGv_i64 in;
6916 if (pass == 0) {
6917 in = cpu_V0;
6918 } else {
6919 in = cpu_V1;
6920 }
ad69471c 6921 if (q) {
0b36f4cd 6922 if (input_unsigned) {
92cdfaeb 6923 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
0b36f4cd 6924 } else {
92cdfaeb 6925 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
0b36f4cd 6926 }
ad69471c 6927 } else {
0b36f4cd 6928 if (input_unsigned) {
92cdfaeb 6929 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
0b36f4cd 6930 } else {
92cdfaeb 6931 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
0b36f4cd 6932 }
ad69471c 6933 }
7d1b0095 6934 tmp = tcg_temp_new_i32();
92cdfaeb
PM
6935 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
6936 neon_store_reg(rd, pass, tmp);
6937 } /* for pass */
6938 tcg_temp_free_i64(tmp64);
6939 } else {
6940 if (size == 1) {
6941 imm = (uint16_t)shift;
6942 imm |= imm << 16;
2c0262af 6943 } else {
92cdfaeb
PM
6944 /* size == 2 */
6945 imm = (uint32_t)shift;
6946 }
6947 tmp2 = tcg_const_i32(imm);
6948 tmp4 = neon_load_reg(rm + 1, 0);
6949 tmp5 = neon_load_reg(rm + 1, 1);
6950 for (pass = 0; pass < 2; pass++) {
6951 if (pass == 0) {
6952 tmp = neon_load_reg(rm, 0);
6953 } else {
6954 tmp = tmp4;
6955 }
0b36f4cd
CL
6956 gen_neon_shift_narrow(size, tmp, tmp2, q,
6957 input_unsigned);
92cdfaeb
PM
6958 if (pass == 0) {
6959 tmp3 = neon_load_reg(rm, 1);
6960 } else {
6961 tmp3 = tmp5;
6962 }
0b36f4cd
CL
6963 gen_neon_shift_narrow(size, tmp3, tmp2, q,
6964 input_unsigned);
36aa55dc 6965 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
7d1b0095
PM
6966 tcg_temp_free_i32(tmp);
6967 tcg_temp_free_i32(tmp3);
6968 tmp = tcg_temp_new_i32();
92cdfaeb
PM
6969 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
6970 neon_store_reg(rd, pass, tmp);
6971 } /* for pass */
c6067f04 6972 tcg_temp_free_i32(tmp2);
b75263d6 6973 }
9ee6e8bb 6974 } else if (op == 10) {
cc13115b
PM
6975 /* VSHLL, VMOVL */
6976 if (q || (rd & 1)) {
9ee6e8bb 6977 return 1;
cc13115b 6978 }
ad69471c
PB
6979 tmp = neon_load_reg(rm, 0);
6980 tmp2 = neon_load_reg(rm, 1);
9ee6e8bb 6981 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
6982 if (pass == 1)
6983 tmp = tmp2;
6984
6985 gen_neon_widen(cpu_V0, tmp, size, u);
9ee6e8bb 6986
9ee6e8bb
PB
6987 if (shift != 0) {
6988 /* The shift is less than the width of the source
ad69471c
PB
6989 type, so we can just shift the whole register. */
6990 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
acdf01ef
CL
6991 /* Widen the result of shift: we need to clear
6992 * the potential overflow bits resulting from
6993 * left bits of the narrow input appearing as
6994 * right bits of left the neighbour narrow
6995 * input. */
ad69471c
PB
6996 if (size < 2 || !u) {
6997 uint64_t imm64;
6998 if (size == 0) {
6999 imm = (0xffu >> (8 - shift));
7000 imm |= imm << 16;
acdf01ef 7001 } else if (size == 1) {
ad69471c 7002 imm = 0xffff >> (16 - shift);
acdf01ef
CL
7003 } else {
7004 /* size == 2 */
7005 imm = 0xffffffff >> (32 - shift);
7006 }
7007 if (size < 2) {
7008 imm64 = imm | (((uint64_t)imm) << 32);
7009 } else {
7010 imm64 = imm;
9ee6e8bb 7011 }
acdf01ef 7012 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
9ee6e8bb
PB
7013 }
7014 }
ad69471c 7015 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb 7016 }
f73534a5 7017 } else if (op >= 14) {
9ee6e8bb 7018 /* VCVT fixed-point. */
cc13115b
PM
7019 if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
7020 return 1;
7021 }
f73534a5
PM
7022 /* We have already masked out the must-be-1 top bit of imm6,
7023 * hence this 32-shift where the ARM ARM has 64-imm6.
7024 */
7025 shift = 32 - shift;
9ee6e8bb 7026 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4373f3ce 7027 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
f73534a5 7028 if (!(op & 1)) {
9ee6e8bb 7029 if (u)
5500b06c 7030 gen_vfp_ulto(0, shift, 1);
9ee6e8bb 7031 else
5500b06c 7032 gen_vfp_slto(0, shift, 1);
9ee6e8bb
PB
7033 } else {
7034 if (u)
5500b06c 7035 gen_vfp_toul(0, shift, 1);
9ee6e8bb 7036 else
5500b06c 7037 gen_vfp_tosl(0, shift, 1);
2c0262af 7038 }
4373f3ce 7039 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
2c0262af
FB
7040 }
7041 } else {
9ee6e8bb
PB
7042 return 1;
7043 }
7044 } else { /* (insn & 0x00380080) == 0 */
246fa4ac
RH
7045 int invert, reg_ofs, vec_size;
7046
7d80fee5
PM
7047 if (q && (rd & 1)) {
7048 return 1;
7049 }
9ee6e8bb
PB
7050
7051 op = (insn >> 8) & 0xf;
7052 /* One register and immediate. */
7053 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
7054 invert = (insn & (1 << 5)) != 0;
7d80fee5
PM
7055 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
7056 * We choose to not special-case this and will behave as if a
7057 * valid constant encoding of 0 had been given.
7058 */
9ee6e8bb
PB
7059 switch (op) {
7060 case 0: case 1:
7061 /* no-op */
7062 break;
7063 case 2: case 3:
7064 imm <<= 8;
7065 break;
7066 case 4: case 5:
7067 imm <<= 16;
7068 break;
7069 case 6: case 7:
7070 imm <<= 24;
7071 break;
7072 case 8: case 9:
7073 imm |= imm << 16;
7074 break;
7075 case 10: case 11:
7076 imm = (imm << 8) | (imm << 24);
7077 break;
7078 case 12:
8e31209e 7079 imm = (imm << 8) | 0xff;
9ee6e8bb
PB
7080 break;
7081 case 13:
7082 imm = (imm << 16) | 0xffff;
7083 break;
7084 case 14:
7085 imm |= (imm << 8) | (imm << 16) | (imm << 24);
246fa4ac 7086 if (invert) {
9ee6e8bb 7087 imm = ~imm;
246fa4ac 7088 }
9ee6e8bb
PB
7089 break;
7090 case 15:
7d80fee5
PM
7091 if (invert) {
7092 return 1;
7093 }
9ee6e8bb
PB
7094 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
7095 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
7096 break;
7097 }
246fa4ac 7098 if (invert) {
9ee6e8bb 7099 imm = ~imm;
246fa4ac 7100 }
9ee6e8bb 7101
246fa4ac
RH
7102 reg_ofs = neon_reg_offset(rd, 0);
7103 vec_size = q ? 16 : 8;
7104
7105 if (op & 1 && op < 12) {
7106 if (invert) {
7107 /* The immediate value has already been inverted,
7108 * so BIC becomes AND.
7109 */
7110 tcg_gen_gvec_andi(MO_32, reg_ofs, reg_ofs, imm,
7111 vec_size, vec_size);
9ee6e8bb 7112 } else {
246fa4ac
RH
7113 tcg_gen_gvec_ori(MO_32, reg_ofs, reg_ofs, imm,
7114 vec_size, vec_size);
7115 }
7116 } else {
7117 /* VMOV, VMVN. */
7118 if (op == 14 && invert) {
7119 TCGv_i64 t64 = tcg_temp_new_i64();
7120
7121 for (pass = 0; pass <= q; ++pass) {
7122 uint64_t val = 0;
a5a14945 7123 int n;
246fa4ac
RH
7124
7125 for (n = 0; n < 8; n++) {
7126 if (imm & (1 << (n + pass * 8))) {
7127 val |= 0xffull << (n * 8);
7128 }
9ee6e8bb 7129 }
246fa4ac
RH
7130 tcg_gen_movi_i64(t64, val);
7131 neon_store_reg64(t64, rd + pass);
9ee6e8bb 7132 }
246fa4ac
RH
7133 tcg_temp_free_i64(t64);
7134 } else {
7135 tcg_gen_gvec_dup32i(reg_ofs, vec_size, vec_size, imm);
9ee6e8bb
PB
7136 }
7137 }
7138 }
e4b3861d 7139 } else { /* (insn & 0x00800010 == 0x00800000) */
9ee6e8bb
PB
7140 if (size != 3) {
7141 op = (insn >> 8) & 0xf;
7142 if ((insn & (1 << 6)) == 0) {
7143 /* Three registers of different lengths. */
7144 int src1_wide;
7145 int src2_wide;
7146 int prewiden;
526d0096
PM
7147 /* undefreq: bit 0 : UNDEF if size == 0
7148 * bit 1 : UNDEF if size == 1
7149 * bit 2 : UNDEF if size == 2
7150 * bit 3 : UNDEF if U == 1
7151 * Note that [2:0] set implies 'always UNDEF'
695272dc
PM
7152 */
7153 int undefreq;
7154 /* prewiden, src1_wide, src2_wide, undefreq */
7155 static const int neon_3reg_wide[16][4] = {
7156 {1, 0, 0, 0}, /* VADDL */
7157 {1, 1, 0, 0}, /* VADDW */
7158 {1, 0, 0, 0}, /* VSUBL */
7159 {1, 1, 0, 0}, /* VSUBW */
7160 {0, 1, 1, 0}, /* VADDHN */
7161 {0, 0, 0, 0}, /* VABAL */
7162 {0, 1, 1, 0}, /* VSUBHN */
7163 {0, 0, 0, 0}, /* VABDL */
7164 {0, 0, 0, 0}, /* VMLAL */
526d0096 7165 {0, 0, 0, 9}, /* VQDMLAL */
695272dc 7166 {0, 0, 0, 0}, /* VMLSL */
526d0096 7167 {0, 0, 0, 9}, /* VQDMLSL */
695272dc 7168 {0, 0, 0, 0}, /* Integer VMULL */
526d0096 7169 {0, 0, 0, 1}, /* VQDMULL */
4e624eda 7170 {0, 0, 0, 0xa}, /* Polynomial VMULL */
526d0096 7171 {0, 0, 0, 7}, /* Reserved: always UNDEF */
9ee6e8bb
PB
7172 };
7173
7174 prewiden = neon_3reg_wide[op][0];
7175 src1_wide = neon_3reg_wide[op][1];
7176 src2_wide = neon_3reg_wide[op][2];
695272dc 7177 undefreq = neon_3reg_wide[op][3];
9ee6e8bb 7178
526d0096
PM
7179 if ((undefreq & (1 << size)) ||
7180 ((undefreq & 8) && u)) {
695272dc
PM
7181 return 1;
7182 }
7183 if ((src1_wide && (rn & 1)) ||
7184 (src2_wide && (rm & 1)) ||
7185 (!src2_wide && (rd & 1))) {
ad69471c 7186 return 1;
695272dc 7187 }
ad69471c 7188
4e624eda
PM
7189 /* Handle VMULL.P64 (Polynomial 64x64 to 128 bit multiply)
7190 * outside the loop below as it only performs a single pass.
7191 */
7192 if (op == 14 && size == 2) {
7193 TCGv_i64 tcg_rn, tcg_rm, tcg_rd;
7194
962fcbf2 7195 if (!dc_isar_feature(aa32_pmull, s)) {
4e624eda
PM
7196 return 1;
7197 }
7198 tcg_rn = tcg_temp_new_i64();
7199 tcg_rm = tcg_temp_new_i64();
7200 tcg_rd = tcg_temp_new_i64();
7201 neon_load_reg64(tcg_rn, rn);
7202 neon_load_reg64(tcg_rm, rm);
7203 gen_helper_neon_pmull_64_lo(tcg_rd, tcg_rn, tcg_rm);
7204 neon_store_reg64(tcg_rd, rd);
7205 gen_helper_neon_pmull_64_hi(tcg_rd, tcg_rn, tcg_rm);
7206 neon_store_reg64(tcg_rd, rd + 1);
7207 tcg_temp_free_i64(tcg_rn);
7208 tcg_temp_free_i64(tcg_rm);
7209 tcg_temp_free_i64(tcg_rd);
7210 return 0;
7211 }
7212
9ee6e8bb
PB
7213 /* Avoid overlapping operands. Wide source operands are
7214 always aligned so will never overlap with wide
7215 destinations in problematic ways. */
8f8e3aa4 7216 if (rd == rm && !src2_wide) {
dd8fbd78
FN
7217 tmp = neon_load_reg(rm, 1);
7218 neon_store_scratch(2, tmp);
8f8e3aa4 7219 } else if (rd == rn && !src1_wide) {
dd8fbd78
FN
7220 tmp = neon_load_reg(rn, 1);
7221 neon_store_scratch(2, tmp);
9ee6e8bb 7222 }
f764718d 7223 tmp3 = NULL;
9ee6e8bb 7224 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
7225 if (src1_wide) {
7226 neon_load_reg64(cpu_V0, rn + pass);
f764718d 7227 tmp = NULL;
9ee6e8bb 7228 } else {
ad69471c 7229 if (pass == 1 && rd == rn) {
dd8fbd78 7230 tmp = neon_load_scratch(2);
9ee6e8bb 7231 } else {
ad69471c
PB
7232 tmp = neon_load_reg(rn, pass);
7233 }
7234 if (prewiden) {
7235 gen_neon_widen(cpu_V0, tmp, size, u);
9ee6e8bb
PB
7236 }
7237 }
ad69471c
PB
7238 if (src2_wide) {
7239 neon_load_reg64(cpu_V1, rm + pass);
f764718d 7240 tmp2 = NULL;
9ee6e8bb 7241 } else {
ad69471c 7242 if (pass == 1 && rd == rm) {
dd8fbd78 7243 tmp2 = neon_load_scratch(2);
9ee6e8bb 7244 } else {
ad69471c
PB
7245 tmp2 = neon_load_reg(rm, pass);
7246 }
7247 if (prewiden) {
7248 gen_neon_widen(cpu_V1, tmp2, size, u);
9ee6e8bb 7249 }
9ee6e8bb
PB
7250 }
7251 switch (op) {
7252 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
ad69471c 7253 gen_neon_addl(size);
9ee6e8bb 7254 break;
79b0e534 7255 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
ad69471c 7256 gen_neon_subl(size);
9ee6e8bb
PB
7257 break;
7258 case 5: case 7: /* VABAL, VABDL */
7259 switch ((size << 1) | u) {
ad69471c
PB
7260 case 0:
7261 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
7262 break;
7263 case 1:
7264 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
7265 break;
7266 case 2:
7267 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
7268 break;
7269 case 3:
7270 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
7271 break;
7272 case 4:
7273 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
7274 break;
7275 case 5:
7276 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
7277 break;
9ee6e8bb
PB
7278 default: abort();
7279 }
7d1b0095
PM
7280 tcg_temp_free_i32(tmp2);
7281 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
7282 break;
7283 case 8: case 9: case 10: case 11: case 12: case 13:
7284 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
ad69471c 7285 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
9ee6e8bb
PB
7286 break;
7287 case 14: /* Polynomial VMULL */
e5ca24cb 7288 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
7d1b0095
PM
7289 tcg_temp_free_i32(tmp2);
7290 tcg_temp_free_i32(tmp);
e5ca24cb 7291 break;
695272dc
PM
7292 default: /* 15 is RESERVED: caught earlier */
7293 abort();
9ee6e8bb 7294 }
ebcd88ce
PM
7295 if (op == 13) {
7296 /* VQDMULL */
7297 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
7298 neon_store_reg64(cpu_V0, rd + pass);
7299 } else if (op == 5 || (op >= 8 && op <= 11)) {
9ee6e8bb 7300 /* Accumulate. */
ebcd88ce 7301 neon_load_reg64(cpu_V1, rd + pass);
9ee6e8bb 7302 switch (op) {
4dc064e6
PM
7303 case 10: /* VMLSL */
7304 gen_neon_negl(cpu_V0, size);
7305 /* Fall through */
7306 case 5: case 8: /* VABAL, VMLAL */
ad69471c 7307 gen_neon_addl(size);
9ee6e8bb
PB
7308 break;
7309 case 9: case 11: /* VQDMLAL, VQDMLSL */
ad69471c 7310 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4dc064e6
PM
7311 if (op == 11) {
7312 gen_neon_negl(cpu_V0, size);
7313 }
ad69471c
PB
7314 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
7315 break;
9ee6e8bb
PB
7316 default:
7317 abort();
7318 }
ad69471c 7319 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
7320 } else if (op == 4 || op == 6) {
7321 /* Narrowing operation. */
7d1b0095 7322 tmp = tcg_temp_new_i32();
79b0e534 7323 if (!u) {
9ee6e8bb 7324 switch (size) {
ad69471c
PB
7325 case 0:
7326 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
7327 break;
7328 case 1:
7329 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
7330 break;
7331 case 2:
7332 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
ecc7b3aa 7333 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
ad69471c 7334 break;
9ee6e8bb
PB
7335 default: abort();
7336 }
7337 } else {
7338 switch (size) {
ad69471c
PB
7339 case 0:
7340 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
7341 break;
7342 case 1:
7343 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
7344 break;
7345 case 2:
7346 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
7347 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
ecc7b3aa 7348 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
ad69471c 7349 break;
9ee6e8bb
PB
7350 default: abort();
7351 }
7352 }
ad69471c
PB
7353 if (pass == 0) {
7354 tmp3 = tmp;
7355 } else {
7356 neon_store_reg(rd, 0, tmp3);
7357 neon_store_reg(rd, 1, tmp);
7358 }
9ee6e8bb
PB
7359 } else {
7360 /* Write back the result. */
ad69471c 7361 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
7362 }
7363 }
7364 } else {
3e3326df
PM
7365 /* Two registers and a scalar. NB that for ops of this form
7366 * the ARM ARM labels bit 24 as Q, but it is in our variable
7367 * 'u', not 'q'.
7368 */
7369 if (size == 0) {
7370 return 1;
7371 }
9ee6e8bb 7372 switch (op) {
9ee6e8bb 7373 case 1: /* Float VMLA scalar */
9ee6e8bb 7374 case 5: /* Floating point VMLS scalar */
9ee6e8bb 7375 case 9: /* Floating point VMUL scalar */
3e3326df
PM
7376 if (size == 1) {
7377 return 1;
7378 }
7379 /* fall through */
7380 case 0: /* Integer VMLA scalar */
7381 case 4: /* Integer VMLS scalar */
7382 case 8: /* Integer VMUL scalar */
9ee6e8bb
PB
7383 case 12: /* VQDMULH scalar */
7384 case 13: /* VQRDMULH scalar */
3e3326df
PM
7385 if (u && ((rd | rn) & 1)) {
7386 return 1;
7387 }
dd8fbd78
FN
7388 tmp = neon_get_scalar(size, rm);
7389 neon_store_scratch(0, tmp);
9ee6e8bb 7390 for (pass = 0; pass < (u ? 4 : 2); pass++) {
dd8fbd78
FN
7391 tmp = neon_load_scratch(0);
7392 tmp2 = neon_load_reg(rn, pass);
9ee6e8bb
PB
7393 if (op == 12) {
7394 if (size == 1) {
02da0b2d 7395 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 7396 } else {
02da0b2d 7397 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
9ee6e8bb
PB
7398 }
7399 } else if (op == 13) {
7400 if (size == 1) {
02da0b2d 7401 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 7402 } else {
02da0b2d 7403 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
9ee6e8bb
PB
7404 }
7405 } else if (op & 1) {
aa47cfdd
PM
7406 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7407 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
7408 tcg_temp_free_ptr(fpstatus);
9ee6e8bb
PB
7409 } else {
7410 switch (size) {
dd8fbd78
FN
7411 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
7412 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
7413 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
3e3326df 7414 default: abort();
9ee6e8bb
PB
7415 }
7416 }
7d1b0095 7417 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
7418 if (op < 8) {
7419 /* Accumulate. */
dd8fbd78 7420 tmp2 = neon_load_reg(rd, pass);
9ee6e8bb
PB
7421 switch (op) {
7422 case 0:
dd8fbd78 7423 gen_neon_add(size, tmp, tmp2);
9ee6e8bb
PB
7424 break;
7425 case 1:
aa47cfdd
PM
7426 {
7427 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7428 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
7429 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 7430 break;
aa47cfdd 7431 }
9ee6e8bb 7432 case 4:
dd8fbd78 7433 gen_neon_rsb(size, tmp, tmp2);
9ee6e8bb
PB
7434 break;
7435 case 5:
aa47cfdd
PM
7436 {
7437 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7438 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
7439 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 7440 break;
aa47cfdd 7441 }
9ee6e8bb
PB
7442 default:
7443 abort();
7444 }
7d1b0095 7445 tcg_temp_free_i32(tmp2);
9ee6e8bb 7446 }
dd8fbd78 7447 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
7448 }
7449 break;
9ee6e8bb 7450 case 3: /* VQDMLAL scalar */
9ee6e8bb 7451 case 7: /* VQDMLSL scalar */
9ee6e8bb 7452 case 11: /* VQDMULL scalar */
3e3326df 7453 if (u == 1) {
ad69471c 7454 return 1;
3e3326df
PM
7455 }
7456 /* fall through */
7457 case 2: /* VMLAL sclar */
7458 case 6: /* VMLSL scalar */
7459 case 10: /* VMULL scalar */
7460 if (rd & 1) {
7461 return 1;
7462 }
dd8fbd78 7463 tmp2 = neon_get_scalar(size, rm);
c6067f04
CL
7464 /* We need a copy of tmp2 because gen_neon_mull
7465 * deletes it during pass 0. */
7d1b0095 7466 tmp4 = tcg_temp_new_i32();
c6067f04 7467 tcg_gen_mov_i32(tmp4, tmp2);
dd8fbd78 7468 tmp3 = neon_load_reg(rn, 1);
ad69471c 7469
9ee6e8bb 7470 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
7471 if (pass == 0) {
7472 tmp = neon_load_reg(rn, 0);
9ee6e8bb 7473 } else {
dd8fbd78 7474 tmp = tmp3;
c6067f04 7475 tmp2 = tmp4;
9ee6e8bb 7476 }
ad69471c 7477 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
ad69471c
PB
7478 if (op != 11) {
7479 neon_load_reg64(cpu_V1, rd + pass);
9ee6e8bb 7480 }
9ee6e8bb 7481 switch (op) {
4dc064e6
PM
7482 case 6:
7483 gen_neon_negl(cpu_V0, size);
7484 /* Fall through */
7485 case 2:
ad69471c 7486 gen_neon_addl(size);
9ee6e8bb
PB
7487 break;
7488 case 3: case 7:
ad69471c 7489 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4dc064e6
PM
7490 if (op == 7) {
7491 gen_neon_negl(cpu_V0, size);
7492 }
ad69471c 7493 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
9ee6e8bb
PB
7494 break;
7495 case 10:
7496 /* no-op */
7497 break;
7498 case 11:
ad69471c 7499 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
9ee6e8bb
PB
7500 break;
7501 default:
7502 abort();
7503 }
ad69471c 7504 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb 7505 }
61adacc8
RH
7506 break;
7507 case 14: /* VQRDMLAH scalar */
7508 case 15: /* VQRDMLSH scalar */
7509 {
7510 NeonGenThreeOpEnvFn *fn;
dd8fbd78 7511
962fcbf2 7512 if (!dc_isar_feature(aa32_rdm, s)) {
61adacc8
RH
7513 return 1;
7514 }
7515 if (u && ((rd | rn) & 1)) {
7516 return 1;
7517 }
7518 if (op == 14) {
7519 if (size == 1) {
7520 fn = gen_helper_neon_qrdmlah_s16;
7521 } else {
7522 fn = gen_helper_neon_qrdmlah_s32;
7523 }
7524 } else {
7525 if (size == 1) {
7526 fn = gen_helper_neon_qrdmlsh_s16;
7527 } else {
7528 fn = gen_helper_neon_qrdmlsh_s32;
7529 }
7530 }
dd8fbd78 7531
61adacc8
RH
7532 tmp2 = neon_get_scalar(size, rm);
7533 for (pass = 0; pass < (u ? 4 : 2); pass++) {
7534 tmp = neon_load_reg(rn, pass);
7535 tmp3 = neon_load_reg(rd, pass);
7536 fn(tmp, cpu_env, tmp, tmp2, tmp3);
7537 tcg_temp_free_i32(tmp3);
7538 neon_store_reg(rd, pass, tmp);
7539 }
7540 tcg_temp_free_i32(tmp2);
7541 }
9ee6e8bb 7542 break;
61adacc8
RH
7543 default:
7544 g_assert_not_reached();
9ee6e8bb
PB
7545 }
7546 }
7547 } else { /* size == 3 */
7548 if (!u) {
7549 /* Extract. */
9ee6e8bb 7550 imm = (insn >> 8) & 0xf;
ad69471c
PB
7551
7552 if (imm > 7 && !q)
7553 return 1;
7554
52579ea1
PM
7555 if (q && ((rd | rn | rm) & 1)) {
7556 return 1;
7557 }
7558
ad69471c
PB
7559 if (imm == 0) {
7560 neon_load_reg64(cpu_V0, rn);
7561 if (q) {
7562 neon_load_reg64(cpu_V1, rn + 1);
9ee6e8bb 7563 }
ad69471c
PB
7564 } else if (imm == 8) {
7565 neon_load_reg64(cpu_V0, rn + 1);
7566 if (q) {
7567 neon_load_reg64(cpu_V1, rm);
9ee6e8bb 7568 }
ad69471c 7569 } else if (q) {
a7812ae4 7570 tmp64 = tcg_temp_new_i64();
ad69471c
PB
7571 if (imm < 8) {
7572 neon_load_reg64(cpu_V0, rn);
a7812ae4 7573 neon_load_reg64(tmp64, rn + 1);
ad69471c
PB
7574 } else {
7575 neon_load_reg64(cpu_V0, rn + 1);
a7812ae4 7576 neon_load_reg64(tmp64, rm);
ad69471c
PB
7577 }
7578 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
a7812ae4 7579 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
ad69471c
PB
7580 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
7581 if (imm < 8) {
7582 neon_load_reg64(cpu_V1, rm);
9ee6e8bb 7583 } else {
ad69471c
PB
7584 neon_load_reg64(cpu_V1, rm + 1);
7585 imm -= 8;
9ee6e8bb 7586 }
ad69471c 7587 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
a7812ae4
PB
7588 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
7589 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
b75263d6 7590 tcg_temp_free_i64(tmp64);
ad69471c 7591 } else {
a7812ae4 7592 /* BUGFIX */
ad69471c 7593 neon_load_reg64(cpu_V0, rn);
a7812ae4 7594 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
ad69471c 7595 neon_load_reg64(cpu_V1, rm);
a7812ae4 7596 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
ad69471c
PB
7597 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
7598 }
7599 neon_store_reg64(cpu_V0, rd);
7600 if (q) {
7601 neon_store_reg64(cpu_V1, rd + 1);
9ee6e8bb
PB
7602 }
7603 } else if ((insn & (1 << 11)) == 0) {
7604 /* Two register misc. */
7605 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
7606 size = (insn >> 18) & 3;
600b828c
PM
7607 /* UNDEF for unknown op values and bad op-size combinations */
7608 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
7609 return 1;
7610 }
fe8fcf3d
PM
7611 if (neon_2rm_is_v8_op(op) &&
7612 !arm_dc_feature(s, ARM_FEATURE_V8)) {
7613 return 1;
7614 }
fc2a9b37
PM
7615 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
7616 q && ((rm | rd) & 1)) {
7617 return 1;
7618 }
9ee6e8bb 7619 switch (op) {
600b828c 7620 case NEON_2RM_VREV64:
9ee6e8bb 7621 for (pass = 0; pass < (q ? 2 : 1); pass++) {
dd8fbd78
FN
7622 tmp = neon_load_reg(rm, pass * 2);
7623 tmp2 = neon_load_reg(rm, pass * 2 + 1);
9ee6e8bb 7624 switch (size) {
dd8fbd78
FN
7625 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
7626 case 1: gen_swap_half(tmp); break;
9ee6e8bb
PB
7627 case 2: /* no-op */ break;
7628 default: abort();
7629 }
dd8fbd78 7630 neon_store_reg(rd, pass * 2 + 1, tmp);
9ee6e8bb 7631 if (size == 2) {
dd8fbd78 7632 neon_store_reg(rd, pass * 2, tmp2);
9ee6e8bb 7633 } else {
9ee6e8bb 7634 switch (size) {
dd8fbd78
FN
7635 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
7636 case 1: gen_swap_half(tmp2); break;
9ee6e8bb
PB
7637 default: abort();
7638 }
dd8fbd78 7639 neon_store_reg(rd, pass * 2, tmp2);
9ee6e8bb
PB
7640 }
7641 }
7642 break;
600b828c
PM
7643 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
7644 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
ad69471c
PB
7645 for (pass = 0; pass < q + 1; pass++) {
7646 tmp = neon_load_reg(rm, pass * 2);
7647 gen_neon_widen(cpu_V0, tmp, size, op & 1);
7648 tmp = neon_load_reg(rm, pass * 2 + 1);
7649 gen_neon_widen(cpu_V1, tmp, size, op & 1);
7650 switch (size) {
7651 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
7652 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
7653 case 2: tcg_gen_add_i64(CPU_V001); break;
7654 default: abort();
7655 }
600b828c 7656 if (op >= NEON_2RM_VPADAL) {
9ee6e8bb 7657 /* Accumulate. */
ad69471c
PB
7658 neon_load_reg64(cpu_V1, rd + pass);
7659 gen_neon_addl(size);
9ee6e8bb 7660 }
ad69471c 7661 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
7662 }
7663 break;
600b828c 7664 case NEON_2RM_VTRN:
9ee6e8bb 7665 if (size == 2) {
a5a14945 7666 int n;
9ee6e8bb 7667 for (n = 0; n < (q ? 4 : 2); n += 2) {
dd8fbd78
FN
7668 tmp = neon_load_reg(rm, n);
7669 tmp2 = neon_load_reg(rd, n + 1);
7670 neon_store_reg(rm, n, tmp2);
7671 neon_store_reg(rd, n + 1, tmp);
9ee6e8bb
PB
7672 }
7673 } else {
7674 goto elementwise;
7675 }
7676 break;
600b828c 7677 case NEON_2RM_VUZP:
02acedf9 7678 if (gen_neon_unzip(rd, rm, size, q)) {
9ee6e8bb 7679 return 1;
9ee6e8bb
PB
7680 }
7681 break;
600b828c 7682 case NEON_2RM_VZIP:
d68a6f3a 7683 if (gen_neon_zip(rd, rm, size, q)) {
9ee6e8bb 7684 return 1;
9ee6e8bb
PB
7685 }
7686 break;
600b828c
PM
7687 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
7688 /* also VQMOVUN; op field and mnemonics don't line up */
fc2a9b37
PM
7689 if (rm & 1) {
7690 return 1;
7691 }
f764718d 7692 tmp2 = NULL;
9ee6e8bb 7693 for (pass = 0; pass < 2; pass++) {
ad69471c 7694 neon_load_reg64(cpu_V0, rm + pass);
7d1b0095 7695 tmp = tcg_temp_new_i32();
600b828c
PM
7696 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
7697 tmp, cpu_V0);
ad69471c
PB
7698 if (pass == 0) {
7699 tmp2 = tmp;
7700 } else {
7701 neon_store_reg(rd, 0, tmp2);
7702 neon_store_reg(rd, 1, tmp);
9ee6e8bb 7703 }
9ee6e8bb
PB
7704 }
7705 break;
600b828c 7706 case NEON_2RM_VSHLL:
fc2a9b37 7707 if (q || (rd & 1)) {
9ee6e8bb 7708 return 1;
600b828c 7709 }
ad69471c
PB
7710 tmp = neon_load_reg(rm, 0);
7711 tmp2 = neon_load_reg(rm, 1);
9ee6e8bb 7712 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
7713 if (pass == 1)
7714 tmp = tmp2;
7715 gen_neon_widen(cpu_V0, tmp, size, 1);
30d11a2a 7716 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
ad69471c 7717 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
7718 }
7719 break;
600b828c 7720 case NEON_2RM_VCVT_F16_F32:
486624fc
AB
7721 {
7722 TCGv_ptr fpst;
7723 TCGv_i32 ahp;
7724
d614a513 7725 if (!arm_dc_feature(s, ARM_FEATURE_VFP_FP16) ||
fc2a9b37
PM
7726 q || (rm & 1)) {
7727 return 1;
7728 }
7d1b0095
PM
7729 tmp = tcg_temp_new_i32();
7730 tmp2 = tcg_temp_new_i32();
486624fc
AB
7731 fpst = get_fpstatus_ptr(true);
7732 ahp = get_ahp_flag();
60011498 7733 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
486624fc 7734 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, fpst, ahp);
60011498 7735 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
486624fc 7736 gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, fpst, ahp);
60011498
PB
7737 tcg_gen_shli_i32(tmp2, tmp2, 16);
7738 tcg_gen_or_i32(tmp2, tmp2, tmp);
7739 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
486624fc 7740 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, fpst, ahp);
60011498
PB
7741 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
7742 neon_store_reg(rd, 0, tmp2);
7d1b0095 7743 tmp2 = tcg_temp_new_i32();
486624fc 7744 gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, fpst, ahp);
60011498
PB
7745 tcg_gen_shli_i32(tmp2, tmp2, 16);
7746 tcg_gen_or_i32(tmp2, tmp2, tmp);
7747 neon_store_reg(rd, 1, tmp2);
7d1b0095 7748 tcg_temp_free_i32(tmp);
486624fc
AB
7749 tcg_temp_free_i32(ahp);
7750 tcg_temp_free_ptr(fpst);
60011498 7751 break;
486624fc 7752 }
600b828c 7753 case NEON_2RM_VCVT_F32_F16:
486624fc
AB
7754 {
7755 TCGv_ptr fpst;
7756 TCGv_i32 ahp;
d614a513 7757 if (!arm_dc_feature(s, ARM_FEATURE_VFP_FP16) ||
fc2a9b37
PM
7758 q || (rd & 1)) {
7759 return 1;
7760 }
486624fc
AB
7761 fpst = get_fpstatus_ptr(true);
7762 ahp = get_ahp_flag();
7d1b0095 7763 tmp3 = tcg_temp_new_i32();
60011498
PB
7764 tmp = neon_load_reg(rm, 0);
7765 tmp2 = neon_load_reg(rm, 1);
7766 tcg_gen_ext16u_i32(tmp3, tmp);
486624fc 7767 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
60011498
PB
7768 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
7769 tcg_gen_shri_i32(tmp3, tmp, 16);
486624fc 7770 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
60011498 7771 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
7d1b0095 7772 tcg_temp_free_i32(tmp);
60011498 7773 tcg_gen_ext16u_i32(tmp3, tmp2);
486624fc 7774 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
60011498
PB
7775 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
7776 tcg_gen_shri_i32(tmp3, tmp2, 16);
486624fc 7777 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
60011498 7778 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
7d1b0095
PM
7779 tcg_temp_free_i32(tmp2);
7780 tcg_temp_free_i32(tmp3);
486624fc
AB
7781 tcg_temp_free_i32(ahp);
7782 tcg_temp_free_ptr(fpst);
60011498 7783 break;
486624fc 7784 }
9d935509 7785 case NEON_2RM_AESE: case NEON_2RM_AESMC:
962fcbf2 7786 if (!dc_isar_feature(aa32_aes, s) || ((rm | rd) & 1)) {
9d935509
AB
7787 return 1;
7788 }
1a66ac61
RH
7789 ptr1 = vfp_reg_ptr(true, rd);
7790 ptr2 = vfp_reg_ptr(true, rm);
9d935509
AB
7791
7792 /* Bit 6 is the lowest opcode bit; it distinguishes between
7793 * encryption (AESE/AESMC) and decryption (AESD/AESIMC)
7794 */
7795 tmp3 = tcg_const_i32(extract32(insn, 6, 1));
7796
7797 if (op == NEON_2RM_AESE) {
1a66ac61 7798 gen_helper_crypto_aese(ptr1, ptr2, tmp3);
9d935509 7799 } else {
1a66ac61 7800 gen_helper_crypto_aesmc(ptr1, ptr2, tmp3);
9d935509 7801 }
1a66ac61
RH
7802 tcg_temp_free_ptr(ptr1);
7803 tcg_temp_free_ptr(ptr2);
9d935509
AB
7804 tcg_temp_free_i32(tmp3);
7805 break;
f1ecb913 7806 case NEON_2RM_SHA1H:
962fcbf2 7807 if (!dc_isar_feature(aa32_sha1, s) || ((rm | rd) & 1)) {
f1ecb913
AB
7808 return 1;
7809 }
1a66ac61
RH
7810 ptr1 = vfp_reg_ptr(true, rd);
7811 ptr2 = vfp_reg_ptr(true, rm);
f1ecb913 7812
1a66ac61 7813 gen_helper_crypto_sha1h(ptr1, ptr2);
f1ecb913 7814
1a66ac61
RH
7815 tcg_temp_free_ptr(ptr1);
7816 tcg_temp_free_ptr(ptr2);
f1ecb913
AB
7817 break;
7818 case NEON_2RM_SHA1SU1:
7819 if ((rm | rd) & 1) {
7820 return 1;
7821 }
7822 /* bit 6 (q): set -> SHA256SU0, cleared -> SHA1SU1 */
7823 if (q) {
962fcbf2 7824 if (!dc_isar_feature(aa32_sha2, s)) {
f1ecb913
AB
7825 return 1;
7826 }
962fcbf2 7827 } else if (!dc_isar_feature(aa32_sha1, s)) {
f1ecb913
AB
7828 return 1;
7829 }
1a66ac61
RH
7830 ptr1 = vfp_reg_ptr(true, rd);
7831 ptr2 = vfp_reg_ptr(true, rm);
f1ecb913 7832 if (q) {
1a66ac61 7833 gen_helper_crypto_sha256su0(ptr1, ptr2);
f1ecb913 7834 } else {
1a66ac61 7835 gen_helper_crypto_sha1su1(ptr1, ptr2);
f1ecb913 7836 }
1a66ac61
RH
7837 tcg_temp_free_ptr(ptr1);
7838 tcg_temp_free_ptr(ptr2);
f1ecb913 7839 break;
4bf940be
RH
7840
7841 case NEON_2RM_VMVN:
7842 tcg_gen_gvec_not(0, rd_ofs, rm_ofs, vec_size, vec_size);
7843 break;
7844 case NEON_2RM_VNEG:
7845 tcg_gen_gvec_neg(size, rd_ofs, rm_ofs, vec_size, vec_size);
7846 break;
7847
9ee6e8bb
PB
7848 default:
7849 elementwise:
7850 for (pass = 0; pass < (q ? 4 : 2); pass++) {
600b828c 7851 if (neon_2rm_is_float_op(op)) {
4373f3ce
PB
7852 tcg_gen_ld_f32(cpu_F0s, cpu_env,
7853 neon_reg_offset(rm, pass));
f764718d 7854 tmp = NULL;
9ee6e8bb 7855 } else {
dd8fbd78 7856 tmp = neon_load_reg(rm, pass);
9ee6e8bb
PB
7857 }
7858 switch (op) {
600b828c 7859 case NEON_2RM_VREV32:
9ee6e8bb 7860 switch (size) {
dd8fbd78
FN
7861 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
7862 case 1: gen_swap_half(tmp); break;
600b828c 7863 default: abort();
9ee6e8bb
PB
7864 }
7865 break;
600b828c 7866 case NEON_2RM_VREV16:
dd8fbd78 7867 gen_rev16(tmp);
9ee6e8bb 7868 break;
600b828c 7869 case NEON_2RM_VCLS:
9ee6e8bb 7870 switch (size) {
dd8fbd78
FN
7871 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
7872 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
7873 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
600b828c 7874 default: abort();
9ee6e8bb
PB
7875 }
7876 break;
600b828c 7877 case NEON_2RM_VCLZ:
9ee6e8bb 7878 switch (size) {
dd8fbd78
FN
7879 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
7880 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
7539a012 7881 case 2: tcg_gen_clzi_i32(tmp, tmp, 32); break;
600b828c 7882 default: abort();
9ee6e8bb
PB
7883 }
7884 break;
600b828c 7885 case NEON_2RM_VCNT:
dd8fbd78 7886 gen_helper_neon_cnt_u8(tmp, tmp);
9ee6e8bb 7887 break;
600b828c 7888 case NEON_2RM_VQABS:
9ee6e8bb 7889 switch (size) {
02da0b2d
PM
7890 case 0:
7891 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
7892 break;
7893 case 1:
7894 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
7895 break;
7896 case 2:
7897 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
7898 break;
600b828c 7899 default: abort();
9ee6e8bb
PB
7900 }
7901 break;
600b828c 7902 case NEON_2RM_VQNEG:
9ee6e8bb 7903 switch (size) {
02da0b2d
PM
7904 case 0:
7905 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
7906 break;
7907 case 1:
7908 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
7909 break;
7910 case 2:
7911 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
7912 break;
600b828c 7913 default: abort();
9ee6e8bb
PB
7914 }
7915 break;
600b828c 7916 case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
dd8fbd78 7917 tmp2 = tcg_const_i32(0);
9ee6e8bb 7918 switch(size) {
dd8fbd78
FN
7919 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
7920 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
7921 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
600b828c 7922 default: abort();
9ee6e8bb 7923 }
39d5492a 7924 tcg_temp_free_i32(tmp2);
600b828c 7925 if (op == NEON_2RM_VCLE0) {
dd8fbd78 7926 tcg_gen_not_i32(tmp, tmp);
600b828c 7927 }
9ee6e8bb 7928 break;
600b828c 7929 case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
dd8fbd78 7930 tmp2 = tcg_const_i32(0);
9ee6e8bb 7931 switch(size) {
dd8fbd78
FN
7932 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
7933 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
7934 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
600b828c 7935 default: abort();
9ee6e8bb 7936 }
39d5492a 7937 tcg_temp_free_i32(tmp2);
600b828c 7938 if (op == NEON_2RM_VCLT0) {
dd8fbd78 7939 tcg_gen_not_i32(tmp, tmp);
600b828c 7940 }
9ee6e8bb 7941 break;
600b828c 7942 case NEON_2RM_VCEQ0:
dd8fbd78 7943 tmp2 = tcg_const_i32(0);
9ee6e8bb 7944 switch(size) {
dd8fbd78
FN
7945 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
7946 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
7947 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
600b828c 7948 default: abort();
9ee6e8bb 7949 }
39d5492a 7950 tcg_temp_free_i32(tmp2);
9ee6e8bb 7951 break;
600b828c 7952 case NEON_2RM_VABS:
9ee6e8bb 7953 switch(size) {
dd8fbd78
FN
7954 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
7955 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
7956 case 2: tcg_gen_abs_i32(tmp, tmp); break;
600b828c 7957 default: abort();
9ee6e8bb
PB
7958 }
7959 break;
600b828c 7960 case NEON_2RM_VCGT0_F:
aa47cfdd
PM
7961 {
7962 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
dd8fbd78 7963 tmp2 = tcg_const_i32(0);
aa47cfdd 7964 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
39d5492a 7965 tcg_temp_free_i32(tmp2);
aa47cfdd 7966 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 7967 break;
aa47cfdd 7968 }
600b828c 7969 case NEON_2RM_VCGE0_F:
aa47cfdd
PM
7970 {
7971 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
dd8fbd78 7972 tmp2 = tcg_const_i32(0);
aa47cfdd 7973 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
39d5492a 7974 tcg_temp_free_i32(tmp2);
aa47cfdd 7975 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 7976 break;
aa47cfdd 7977 }
600b828c 7978 case NEON_2RM_VCEQ0_F:
aa47cfdd
PM
7979 {
7980 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
dd8fbd78 7981 tmp2 = tcg_const_i32(0);
aa47cfdd 7982 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
39d5492a 7983 tcg_temp_free_i32(tmp2);
aa47cfdd 7984 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 7985 break;
aa47cfdd 7986 }
600b828c 7987 case NEON_2RM_VCLE0_F:
aa47cfdd
PM
7988 {
7989 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
0e326109 7990 tmp2 = tcg_const_i32(0);
aa47cfdd 7991 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
39d5492a 7992 tcg_temp_free_i32(tmp2);
aa47cfdd 7993 tcg_temp_free_ptr(fpstatus);
0e326109 7994 break;
aa47cfdd 7995 }
600b828c 7996 case NEON_2RM_VCLT0_F:
aa47cfdd
PM
7997 {
7998 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
0e326109 7999 tmp2 = tcg_const_i32(0);
aa47cfdd 8000 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
39d5492a 8001 tcg_temp_free_i32(tmp2);
aa47cfdd 8002 tcg_temp_free_ptr(fpstatus);
0e326109 8003 break;
aa47cfdd 8004 }
600b828c 8005 case NEON_2RM_VABS_F:
4373f3ce 8006 gen_vfp_abs(0);
9ee6e8bb 8007 break;
600b828c 8008 case NEON_2RM_VNEG_F:
4373f3ce 8009 gen_vfp_neg(0);
9ee6e8bb 8010 break;
600b828c 8011 case NEON_2RM_VSWP:
dd8fbd78
FN
8012 tmp2 = neon_load_reg(rd, pass);
8013 neon_store_reg(rm, pass, tmp2);
9ee6e8bb 8014 break;
600b828c 8015 case NEON_2RM_VTRN:
dd8fbd78 8016 tmp2 = neon_load_reg(rd, pass);
9ee6e8bb 8017 switch (size) {
dd8fbd78
FN
8018 case 0: gen_neon_trn_u8(tmp, tmp2); break;
8019 case 1: gen_neon_trn_u16(tmp, tmp2); break;
600b828c 8020 default: abort();
9ee6e8bb 8021 }
dd8fbd78 8022 neon_store_reg(rm, pass, tmp2);
9ee6e8bb 8023 break;
34f7b0a2
WN
8024 case NEON_2RM_VRINTN:
8025 case NEON_2RM_VRINTA:
8026 case NEON_2RM_VRINTM:
8027 case NEON_2RM_VRINTP:
8028 case NEON_2RM_VRINTZ:
8029 {
8030 TCGv_i32 tcg_rmode;
8031 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8032 int rmode;
8033
8034 if (op == NEON_2RM_VRINTZ) {
8035 rmode = FPROUNDING_ZERO;
8036 } else {
8037 rmode = fp_decode_rm[((op & 0x6) >> 1) ^ 1];
8038 }
8039
8040 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
8041 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
8042 cpu_env);
8043 gen_helper_rints(cpu_F0s, cpu_F0s, fpstatus);
8044 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
8045 cpu_env);
8046 tcg_temp_free_ptr(fpstatus);
8047 tcg_temp_free_i32(tcg_rmode);
8048 break;
8049 }
2ce70625
WN
8050 case NEON_2RM_VRINTX:
8051 {
8052 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8053 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpstatus);
8054 tcg_temp_free_ptr(fpstatus);
8055 break;
8056 }
901ad525
WN
8057 case NEON_2RM_VCVTAU:
8058 case NEON_2RM_VCVTAS:
8059 case NEON_2RM_VCVTNU:
8060 case NEON_2RM_VCVTNS:
8061 case NEON_2RM_VCVTPU:
8062 case NEON_2RM_VCVTPS:
8063 case NEON_2RM_VCVTMU:
8064 case NEON_2RM_VCVTMS:
8065 {
8066 bool is_signed = !extract32(insn, 7, 1);
8067 TCGv_ptr fpst = get_fpstatus_ptr(1);
8068 TCGv_i32 tcg_rmode, tcg_shift;
8069 int rmode = fp_decode_rm[extract32(insn, 8, 2)];
8070
8071 tcg_shift = tcg_const_i32(0);
8072 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
8073 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
8074 cpu_env);
8075
8076 if (is_signed) {
8077 gen_helper_vfp_tosls(cpu_F0s, cpu_F0s,
8078 tcg_shift, fpst);
8079 } else {
8080 gen_helper_vfp_touls(cpu_F0s, cpu_F0s,
8081 tcg_shift, fpst);
8082 }
8083
8084 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
8085 cpu_env);
8086 tcg_temp_free_i32(tcg_rmode);
8087 tcg_temp_free_i32(tcg_shift);
8088 tcg_temp_free_ptr(fpst);
8089 break;
8090 }
600b828c 8091 case NEON_2RM_VRECPE:
b6d4443a
AB
8092 {
8093 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8094 gen_helper_recpe_u32(tmp, tmp, fpstatus);
8095 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 8096 break;
b6d4443a 8097 }
600b828c 8098 case NEON_2RM_VRSQRTE:
c2fb418e
AB
8099 {
8100 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8101 gen_helper_rsqrte_u32(tmp, tmp, fpstatus);
8102 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 8103 break;
c2fb418e 8104 }
600b828c 8105 case NEON_2RM_VRECPE_F:
b6d4443a
AB
8106 {
8107 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8108 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, fpstatus);
8109 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 8110 break;
b6d4443a 8111 }
600b828c 8112 case NEON_2RM_VRSQRTE_F:
c2fb418e
AB
8113 {
8114 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8115 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, fpstatus);
8116 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 8117 break;
c2fb418e 8118 }
600b828c 8119 case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
5500b06c 8120 gen_vfp_sito(0, 1);
9ee6e8bb 8121 break;
600b828c 8122 case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
5500b06c 8123 gen_vfp_uito(0, 1);
9ee6e8bb 8124 break;
600b828c 8125 case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
5500b06c 8126 gen_vfp_tosiz(0, 1);
9ee6e8bb 8127 break;
600b828c 8128 case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
5500b06c 8129 gen_vfp_touiz(0, 1);
9ee6e8bb
PB
8130 break;
8131 default:
600b828c
PM
8132 /* Reserved op values were caught by the
8133 * neon_2rm_sizes[] check earlier.
8134 */
8135 abort();
9ee6e8bb 8136 }
600b828c 8137 if (neon_2rm_is_float_op(op)) {
4373f3ce
PB
8138 tcg_gen_st_f32(cpu_F0s, cpu_env,
8139 neon_reg_offset(rd, pass));
9ee6e8bb 8140 } else {
dd8fbd78 8141 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
8142 }
8143 }
8144 break;
8145 }
8146 } else if ((insn & (1 << 10)) == 0) {
8147 /* VTBL, VTBX. */
56907d77
PM
8148 int n = ((insn >> 8) & 3) + 1;
8149 if ((rn + n) > 32) {
8150 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
8151 * helper function running off the end of the register file.
8152 */
8153 return 1;
8154 }
8155 n <<= 3;
9ee6e8bb 8156 if (insn & (1 << 6)) {
8f8e3aa4 8157 tmp = neon_load_reg(rd, 0);
9ee6e8bb 8158 } else {
7d1b0095 8159 tmp = tcg_temp_new_i32();
8f8e3aa4 8160 tcg_gen_movi_i32(tmp, 0);
9ee6e8bb 8161 }
8f8e3aa4 8162 tmp2 = neon_load_reg(rm, 0);
e7c06c4e 8163 ptr1 = vfp_reg_ptr(true, rn);
b75263d6 8164 tmp5 = tcg_const_i32(n);
e7c06c4e 8165 gen_helper_neon_tbl(tmp2, tmp2, tmp, ptr1, tmp5);
7d1b0095 8166 tcg_temp_free_i32(tmp);
9ee6e8bb 8167 if (insn & (1 << 6)) {
8f8e3aa4 8168 tmp = neon_load_reg(rd, 1);
9ee6e8bb 8169 } else {
7d1b0095 8170 tmp = tcg_temp_new_i32();
8f8e3aa4 8171 tcg_gen_movi_i32(tmp, 0);
9ee6e8bb 8172 }
8f8e3aa4 8173 tmp3 = neon_load_reg(rm, 1);
e7c06c4e 8174 gen_helper_neon_tbl(tmp3, tmp3, tmp, ptr1, tmp5);
25aeb69b 8175 tcg_temp_free_i32(tmp5);
e7c06c4e 8176 tcg_temp_free_ptr(ptr1);
8f8e3aa4 8177 neon_store_reg(rd, 0, tmp2);
3018f259 8178 neon_store_reg(rd, 1, tmp3);
7d1b0095 8179 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8180 } else if ((insn & 0x380) == 0) {
8181 /* VDUP */
32f91fb7
RH
8182 int element;
8183 TCGMemOp size;
8184
133da6aa
JR
8185 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
8186 return 1;
8187 }
9ee6e8bb 8188 if (insn & (1 << 16)) {
32f91fb7
RH
8189 size = MO_8;
8190 element = (insn >> 17) & 7;
9ee6e8bb 8191 } else if (insn & (1 << 17)) {
32f91fb7
RH
8192 size = MO_16;
8193 element = (insn >> 18) & 3;
8194 } else {
8195 size = MO_32;
8196 element = (insn >> 19) & 1;
9ee6e8bb 8197 }
32f91fb7
RH
8198 tcg_gen_gvec_dup_mem(size, neon_reg_offset(rd, 0),
8199 neon_element_offset(rm, element, size),
8200 q ? 16 : 8, q ? 16 : 8);
9ee6e8bb
PB
8201 } else {
8202 return 1;
8203 }
8204 }
8205 }
8206 return 0;
8207}
8208
8b7209fa
RH
8209/* Advanced SIMD three registers of the same length extension.
8210 * 31 25 23 22 20 16 12 11 10 9 8 3 0
8211 * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
8212 * | 1 1 1 1 1 1 0 | op1 | D | op2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
8213 * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
8214 */
8215static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
8216{
26c470a7
RH
8217 gen_helper_gvec_3 *fn_gvec = NULL;
8218 gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
8219 int rd, rn, rm, opr_sz;
8220 int data = 0;
8b7209fa
RH
8221 bool q;
8222
8223 q = extract32(insn, 6, 1);
8224 VFP_DREG_D(rd, insn);
8225 VFP_DREG_N(rn, insn);
8226 VFP_DREG_M(rm, insn);
8227 if ((rd | rn | rm) & q) {
8228 return 1;
8229 }
8230
8231 if ((insn & 0xfe200f10) == 0xfc200800) {
8232 /* VCMLA -- 1111 110R R.1S .... .... 1000 ...0 .... */
26c470a7
RH
8233 int size = extract32(insn, 20, 1);
8234 data = extract32(insn, 23, 2); /* rot */
962fcbf2 8235 if (!dc_isar_feature(aa32_vcma, s)
5763190f 8236 || (!size && !dc_isar_feature(aa32_fp16_arith, s))) {
8b7209fa
RH
8237 return 1;
8238 }
8239 fn_gvec_ptr = size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
8240 } else if ((insn & 0xfea00f10) == 0xfc800800) {
8241 /* VCADD -- 1111 110R 1.0S .... .... 1000 ...0 .... */
26c470a7
RH
8242 int size = extract32(insn, 20, 1);
8243 data = extract32(insn, 24, 1); /* rot */
962fcbf2 8244 if (!dc_isar_feature(aa32_vcma, s)
5763190f 8245 || (!size && !dc_isar_feature(aa32_fp16_arith, s))) {
8b7209fa
RH
8246 return 1;
8247 }
8248 fn_gvec_ptr = size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
26c470a7
RH
8249 } else if ((insn & 0xfeb00f00) == 0xfc200d00) {
8250 /* V[US]DOT -- 1111 1100 0.10 .... .... 1101 .Q.U .... */
8251 bool u = extract32(insn, 4, 1);
962fcbf2 8252 if (!dc_isar_feature(aa32_dp, s)) {
26c470a7
RH
8253 return 1;
8254 }
8255 fn_gvec = u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b;
8b7209fa
RH
8256 } else {
8257 return 1;
8258 }
8259
8260 if (s->fp_excp_el) {
8261 gen_exception_insn(s, 4, EXCP_UDEF,
4be42f40 8262 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
8b7209fa
RH
8263 return 0;
8264 }
8265 if (!s->vfp_enabled) {
8266 return 1;
8267 }
8268
8269 opr_sz = (1 + q) * 8;
26c470a7
RH
8270 if (fn_gvec_ptr) {
8271 TCGv_ptr fpst = get_fpstatus_ptr(1);
8272 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
8273 vfp_reg_offset(1, rn),
8274 vfp_reg_offset(1, rm), fpst,
8275 opr_sz, opr_sz, data, fn_gvec_ptr);
8276 tcg_temp_free_ptr(fpst);
8277 } else {
8278 tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd),
8279 vfp_reg_offset(1, rn),
8280 vfp_reg_offset(1, rm),
8281 opr_sz, opr_sz, data, fn_gvec);
8282 }
8b7209fa
RH
8283 return 0;
8284}
8285
638808ff
RH
8286/* Advanced SIMD two registers and a scalar extension.
8287 * 31 24 23 22 20 16 12 11 10 9 8 3 0
8288 * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
8289 * | 1 1 1 1 1 1 1 0 | o1 | D | o2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
8290 * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
8291 *
8292 */
8293
8294static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
8295{
26c470a7
RH
8296 gen_helper_gvec_3 *fn_gvec = NULL;
8297 gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
2cc99919 8298 int rd, rn, rm, opr_sz, data;
638808ff
RH
8299 bool q;
8300
8301 q = extract32(insn, 6, 1);
8302 VFP_DREG_D(rd, insn);
8303 VFP_DREG_N(rn, insn);
638808ff
RH
8304 if ((rd | rn) & q) {
8305 return 1;
8306 }
8307
8308 if ((insn & 0xff000f10) == 0xfe000800) {
8309 /* VCMLA (indexed) -- 1111 1110 S.RR .... .... 1000 ...0 .... */
2cc99919
RH
8310 int rot = extract32(insn, 20, 2);
8311 int size = extract32(insn, 23, 1);
8312 int index;
8313
962fcbf2 8314 if (!dc_isar_feature(aa32_vcma, s)) {
638808ff
RH
8315 return 1;
8316 }
2cc99919 8317 if (size == 0) {
5763190f 8318 if (!dc_isar_feature(aa32_fp16_arith, s)) {
2cc99919
RH
8319 return 1;
8320 }
8321 /* For fp16, rm is just Vm, and index is M. */
8322 rm = extract32(insn, 0, 4);
8323 index = extract32(insn, 5, 1);
8324 } else {
8325 /* For fp32, rm is the usual M:Vm, and index is 0. */
8326 VFP_DREG_M(rm, insn);
8327 index = 0;
8328 }
8329 data = (index << 2) | rot;
8330 fn_gvec_ptr = (size ? gen_helper_gvec_fcmlas_idx
8331 : gen_helper_gvec_fcmlah_idx);
26c470a7
RH
8332 } else if ((insn & 0xffb00f00) == 0xfe200d00) {
8333 /* V[US]DOT -- 1111 1110 0.10 .... .... 1101 .Q.U .... */
8334 int u = extract32(insn, 4, 1);
962fcbf2 8335 if (!dc_isar_feature(aa32_dp, s)) {
26c470a7
RH
8336 return 1;
8337 }
8338 fn_gvec = u ? gen_helper_gvec_udot_idx_b : gen_helper_gvec_sdot_idx_b;
8339 /* rm is just Vm, and index is M. */
8340 data = extract32(insn, 5, 1); /* index */
8341 rm = extract32(insn, 0, 4);
638808ff
RH
8342 } else {
8343 return 1;
8344 }
8345
8346 if (s->fp_excp_el) {
8347 gen_exception_insn(s, 4, EXCP_UDEF,
4be42f40 8348 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
638808ff
RH
8349 return 0;
8350 }
8351 if (!s->vfp_enabled) {
8352 return 1;
8353 }
8354
8355 opr_sz = (1 + q) * 8;
26c470a7
RH
8356 if (fn_gvec_ptr) {
8357 TCGv_ptr fpst = get_fpstatus_ptr(1);
8358 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
8359 vfp_reg_offset(1, rn),
8360 vfp_reg_offset(1, rm), fpst,
8361 opr_sz, opr_sz, data, fn_gvec_ptr);
8362 tcg_temp_free_ptr(fpst);
8363 } else {
8364 tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd),
8365 vfp_reg_offset(1, rn),
8366 vfp_reg_offset(1, rm),
8367 opr_sz, opr_sz, data, fn_gvec);
8368 }
638808ff
RH
8369 return 0;
8370}
8371
7dcc1f89 8372static int disas_coproc_insn(DisasContext *s, uint32_t insn)
9ee6e8bb 8373{
4b6a83fb
PM
8374 int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
8375 const ARMCPRegInfo *ri;
9ee6e8bb
PB
8376
8377 cpnum = (insn >> 8) & 0xf;
c0f4af17
PM
8378
8379 /* First check for coprocessor space used for XScale/iwMMXt insns */
d614a513 8380 if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cpnum < 2)) {
c0f4af17
PM
8381 if (extract32(s->c15_cpar, cpnum, 1) == 0) {
8382 return 1;
8383 }
d614a513 8384 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
7dcc1f89 8385 return disas_iwmmxt_insn(s, insn);
d614a513 8386 } else if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
7dcc1f89 8387 return disas_dsp_insn(s, insn);
c0f4af17
PM
8388 }
8389 return 1;
4b6a83fb
PM
8390 }
8391
8392 /* Otherwise treat as a generic register access */
8393 is64 = (insn & (1 << 25)) == 0;
8394 if (!is64 && ((insn & (1 << 4)) == 0)) {
8395 /* cdp */
8396 return 1;
8397 }
8398
8399 crm = insn & 0xf;
8400 if (is64) {
8401 crn = 0;
8402 opc1 = (insn >> 4) & 0xf;
8403 opc2 = 0;
8404 rt2 = (insn >> 16) & 0xf;
8405 } else {
8406 crn = (insn >> 16) & 0xf;
8407 opc1 = (insn >> 21) & 7;
8408 opc2 = (insn >> 5) & 7;
8409 rt2 = 0;
8410 }
8411 isread = (insn >> 20) & 1;
8412 rt = (insn >> 12) & 0xf;
8413
60322b39 8414 ri = get_arm_cp_reginfo(s->cp_regs,
51a79b03 8415 ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
4b6a83fb
PM
8416 if (ri) {
8417 /* Check access permissions */
dcbff19b 8418 if (!cp_access_ok(s->current_el, ri, isread)) {
4b6a83fb
PM
8419 return 1;
8420 }
8421
c0f4af17 8422 if (ri->accessfn ||
d614a513 8423 (arm_dc_feature(s, ARM_FEATURE_XSCALE) && cpnum < 14)) {
f59df3f2
PM
8424 /* Emit code to perform further access permissions checks at
8425 * runtime; this may result in an exception.
c0f4af17
PM
8426 * Note that on XScale all cp0..c13 registers do an access check
8427 * call in order to handle c15_cpar.
f59df3f2
PM
8428 */
8429 TCGv_ptr tmpptr;
3f208fd7 8430 TCGv_i32 tcg_syn, tcg_isread;
8bcbf37c
PM
8431 uint32_t syndrome;
8432
8433 /* Note that since we are an implementation which takes an
8434 * exception on a trapped conditional instruction only if the
8435 * instruction passes its condition code check, we can take
8436 * advantage of the clause in the ARM ARM that allows us to set
8437 * the COND field in the instruction to 0xE in all cases.
8438 * We could fish the actual condition out of the insn (ARM)
8439 * or the condexec bits (Thumb) but it isn't necessary.
8440 */
8441 switch (cpnum) {
8442 case 14:
8443 if (is64) {
8444 syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
4df32259 8445 isread, false);
8bcbf37c
PM
8446 } else {
8447 syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
4df32259 8448 rt, isread, false);
8bcbf37c
PM
8449 }
8450 break;
8451 case 15:
8452 if (is64) {
8453 syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
4df32259 8454 isread, false);
8bcbf37c
PM
8455 } else {
8456 syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
4df32259 8457 rt, isread, false);
8bcbf37c
PM
8458 }
8459 break;
8460 default:
8461 /* ARMv8 defines that only coprocessors 14 and 15 exist,
8462 * so this can only happen if this is an ARMv7 or earlier CPU,
8463 * in which case the syndrome information won't actually be
8464 * guest visible.
8465 */
d614a513 8466 assert(!arm_dc_feature(s, ARM_FEATURE_V8));
8bcbf37c
PM
8467 syndrome = syn_uncategorized();
8468 break;
8469 }
8470
43bfa4a1 8471 gen_set_condexec(s);
3977ee5d 8472 gen_set_pc_im(s, s->pc - 4);
f59df3f2 8473 tmpptr = tcg_const_ptr(ri);
8bcbf37c 8474 tcg_syn = tcg_const_i32(syndrome);
3f208fd7
PM
8475 tcg_isread = tcg_const_i32(isread);
8476 gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn,
8477 tcg_isread);
f59df3f2 8478 tcg_temp_free_ptr(tmpptr);
8bcbf37c 8479 tcg_temp_free_i32(tcg_syn);
3f208fd7 8480 tcg_temp_free_i32(tcg_isread);
f59df3f2
PM
8481 }
8482
4b6a83fb
PM
8483 /* Handle special cases first */
8484 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
8485 case ARM_CP_NOP:
8486 return 0;
8487 case ARM_CP_WFI:
8488 if (isread) {
8489 return 1;
8490 }
eaed129d 8491 gen_set_pc_im(s, s->pc);
dcba3a8d 8492 s->base.is_jmp = DISAS_WFI;
2bee5105 8493 return 0;
4b6a83fb
PM
8494 default:
8495 break;
8496 }
8497
c5a49c63 8498 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
2452731c
PM
8499 gen_io_start();
8500 }
8501
4b6a83fb
PM
8502 if (isread) {
8503 /* Read */
8504 if (is64) {
8505 TCGv_i64 tmp64;
8506 TCGv_i32 tmp;
8507 if (ri->type & ARM_CP_CONST) {
8508 tmp64 = tcg_const_i64(ri->resetvalue);
8509 } else if (ri->readfn) {
8510 TCGv_ptr tmpptr;
4b6a83fb
PM
8511 tmp64 = tcg_temp_new_i64();
8512 tmpptr = tcg_const_ptr(ri);
8513 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
8514 tcg_temp_free_ptr(tmpptr);
8515 } else {
8516 tmp64 = tcg_temp_new_i64();
8517 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
8518 }
8519 tmp = tcg_temp_new_i32();
ecc7b3aa 8520 tcg_gen_extrl_i64_i32(tmp, tmp64);
4b6a83fb
PM
8521 store_reg(s, rt, tmp);
8522 tcg_gen_shri_i64(tmp64, tmp64, 32);
ed336850 8523 tmp = tcg_temp_new_i32();
ecc7b3aa 8524 tcg_gen_extrl_i64_i32(tmp, tmp64);
ed336850 8525 tcg_temp_free_i64(tmp64);
4b6a83fb
PM
8526 store_reg(s, rt2, tmp);
8527 } else {
39d5492a 8528 TCGv_i32 tmp;
4b6a83fb
PM
8529 if (ri->type & ARM_CP_CONST) {
8530 tmp = tcg_const_i32(ri->resetvalue);
8531 } else if (ri->readfn) {
8532 TCGv_ptr tmpptr;
4b6a83fb
PM
8533 tmp = tcg_temp_new_i32();
8534 tmpptr = tcg_const_ptr(ri);
8535 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
8536 tcg_temp_free_ptr(tmpptr);
8537 } else {
8538 tmp = load_cpu_offset(ri->fieldoffset);
8539 }
8540 if (rt == 15) {
8541 /* Destination register of r15 for 32 bit loads sets
8542 * the condition codes from the high 4 bits of the value
8543 */
8544 gen_set_nzcv(tmp);
8545 tcg_temp_free_i32(tmp);
8546 } else {
8547 store_reg(s, rt, tmp);
8548 }
8549 }
8550 } else {
8551 /* Write */
8552 if (ri->type & ARM_CP_CONST) {
8553 /* If not forbidden by access permissions, treat as WI */
8554 return 0;
8555 }
8556
8557 if (is64) {
39d5492a 8558 TCGv_i32 tmplo, tmphi;
4b6a83fb
PM
8559 TCGv_i64 tmp64 = tcg_temp_new_i64();
8560 tmplo = load_reg(s, rt);
8561 tmphi = load_reg(s, rt2);
8562 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
8563 tcg_temp_free_i32(tmplo);
8564 tcg_temp_free_i32(tmphi);
8565 if (ri->writefn) {
8566 TCGv_ptr tmpptr = tcg_const_ptr(ri);
4b6a83fb
PM
8567 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
8568 tcg_temp_free_ptr(tmpptr);
8569 } else {
8570 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
8571 }
8572 tcg_temp_free_i64(tmp64);
8573 } else {
8574 if (ri->writefn) {
39d5492a 8575 TCGv_i32 tmp;
4b6a83fb 8576 TCGv_ptr tmpptr;
4b6a83fb
PM
8577 tmp = load_reg(s, rt);
8578 tmpptr = tcg_const_ptr(ri);
8579 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
8580 tcg_temp_free_ptr(tmpptr);
8581 tcg_temp_free_i32(tmp);
8582 } else {
39d5492a 8583 TCGv_i32 tmp = load_reg(s, rt);
4b6a83fb
PM
8584 store_cpu_offset(tmp, ri->fieldoffset);
8585 }
8586 }
2452731c
PM
8587 }
8588
c5a49c63 8589 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
2452731c
PM
8590 /* I/O operations must end the TB here (whether read or write) */
8591 gen_io_end();
8592 gen_lookup_tb(s);
8593 } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
4b6a83fb
PM
8594 /* We default to ending the TB on a coprocessor register write,
8595 * but allow this to be suppressed by the register definition
8596 * (usually only necessary to work around guest bugs).
8597 */
2452731c 8598 gen_lookup_tb(s);
4b6a83fb 8599 }
2452731c 8600
4b6a83fb
PM
8601 return 0;
8602 }
8603
626187d8
PM
8604 /* Unknown register; this might be a guest error or a QEMU
8605 * unimplemented feature.
8606 */
8607 if (is64) {
8608 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
51a79b03
PM
8609 "64 bit system register cp:%d opc1: %d crm:%d "
8610 "(%s)\n",
8611 isread ? "read" : "write", cpnum, opc1, crm,
8612 s->ns ? "non-secure" : "secure");
626187d8
PM
8613 } else {
8614 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
51a79b03
PM
8615 "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d "
8616 "(%s)\n",
8617 isread ? "read" : "write", cpnum, opc1, crn, crm, opc2,
8618 s->ns ? "non-secure" : "secure");
626187d8
PM
8619 }
8620
4a9a539f 8621 return 1;
9ee6e8bb
PB
8622}
8623
5e3f878a
PB
8624
8625/* Store a 64-bit value to a register pair. Clobbers val. */
a7812ae4 8626static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5e3f878a 8627{
39d5492a 8628 TCGv_i32 tmp;
7d1b0095 8629 tmp = tcg_temp_new_i32();
ecc7b3aa 8630 tcg_gen_extrl_i64_i32(tmp, val);
5e3f878a 8631 store_reg(s, rlow, tmp);
7d1b0095 8632 tmp = tcg_temp_new_i32();
5e3f878a 8633 tcg_gen_shri_i64(val, val, 32);
ecc7b3aa 8634 tcg_gen_extrl_i64_i32(tmp, val);
5e3f878a
PB
8635 store_reg(s, rhigh, tmp);
8636}
8637
8638/* load a 32-bit value from a register and perform a 64-bit accumulate. */
a7812ae4 8639static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5e3f878a 8640{
a7812ae4 8641 TCGv_i64 tmp;
39d5492a 8642 TCGv_i32 tmp2;
5e3f878a 8643
36aa55dc 8644 /* Load value and extend to 64 bits. */
a7812ae4 8645 tmp = tcg_temp_new_i64();
5e3f878a
PB
8646 tmp2 = load_reg(s, rlow);
8647 tcg_gen_extu_i32_i64(tmp, tmp2);
7d1b0095 8648 tcg_temp_free_i32(tmp2);
5e3f878a 8649 tcg_gen_add_i64(val, val, tmp);
b75263d6 8650 tcg_temp_free_i64(tmp);
5e3f878a
PB
8651}
8652
8653/* load and add a 64-bit value from a register pair. */
a7812ae4 8654static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5e3f878a 8655{
a7812ae4 8656 TCGv_i64 tmp;
39d5492a
PM
8657 TCGv_i32 tmpl;
8658 TCGv_i32 tmph;
5e3f878a
PB
8659
8660 /* Load 64-bit value rd:rn. */
36aa55dc
PB
8661 tmpl = load_reg(s, rlow);
8662 tmph = load_reg(s, rhigh);
a7812ae4 8663 tmp = tcg_temp_new_i64();
36aa55dc 8664 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
7d1b0095
PM
8665 tcg_temp_free_i32(tmpl);
8666 tcg_temp_free_i32(tmph);
5e3f878a 8667 tcg_gen_add_i64(val, val, tmp);
b75263d6 8668 tcg_temp_free_i64(tmp);
5e3f878a
PB
8669}
8670
c9f10124 8671/* Set N and Z flags from hi|lo. */
39d5492a 8672static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
5e3f878a 8673{
c9f10124
RH
8674 tcg_gen_mov_i32(cpu_NF, hi);
8675 tcg_gen_or_i32(cpu_ZF, lo, hi);
5e3f878a
PB
8676}
8677
426f5abc
PB
8678/* Load/Store exclusive instructions are implemented by remembering
8679 the value/address loaded, and seeing if these are the same
354161b3 8680 when the store is performed. This should be sufficient to implement
426f5abc 8681 the architecturally mandated semantics, and avoids having to monitor
354161b3
EC
8682 regular stores. The compare vs the remembered value is done during
8683 the cmpxchg operation, but we must compare the addresses manually. */
426f5abc 8684static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
39d5492a 8685 TCGv_i32 addr, int size)
426f5abc 8686{
94ee24e7 8687 TCGv_i32 tmp = tcg_temp_new_i32();
354161b3 8688 TCGMemOp opc = size | MO_ALIGN | s->be_data;
426f5abc 8689
50225ad0
PM
8690 s->is_ldex = true;
8691
426f5abc 8692 if (size == 3) {
39d5492a 8693 TCGv_i32 tmp2 = tcg_temp_new_i32();
354161b3 8694 TCGv_i64 t64 = tcg_temp_new_i64();
03d05e2d 8695
3448d47b
PM
8696 /* For AArch32, architecturally the 32-bit word at the lowest
8697 * address is always Rt and the one at addr+4 is Rt2, even if
8698 * the CPU is big-endian. That means we don't want to do a
8699 * gen_aa32_ld_i64(), which invokes gen_aa32_frob64() as if
8700 * for an architecturally 64-bit access, but instead do a
8701 * 64-bit access using MO_BE if appropriate and then split
8702 * the two halves.
8703 * This only makes a difference for BE32 user-mode, where
8704 * frob64() must not flip the two halves of the 64-bit data
8705 * but this code must treat BE32 user-mode like BE32 system.
8706 */
8707 TCGv taddr = gen_aa32_addr(s, addr, opc);
8708
8709 tcg_gen_qemu_ld_i64(t64, taddr, get_mem_index(s), opc);
8710 tcg_temp_free(taddr);
354161b3 8711 tcg_gen_mov_i64(cpu_exclusive_val, t64);
3448d47b
PM
8712 if (s->be_data == MO_BE) {
8713 tcg_gen_extr_i64_i32(tmp2, tmp, t64);
8714 } else {
8715 tcg_gen_extr_i64_i32(tmp, tmp2, t64);
8716 }
354161b3
EC
8717 tcg_temp_free_i64(t64);
8718
8719 store_reg(s, rt2, tmp2);
03d05e2d 8720 } else {
354161b3 8721 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), opc);
03d05e2d 8722 tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
426f5abc 8723 }
03d05e2d
PM
8724
8725 store_reg(s, rt, tmp);
8726 tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
426f5abc
PB
8727}
8728
8729static void gen_clrex(DisasContext *s)
8730{
03d05e2d 8731 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
426f5abc
PB
8732}
8733
426f5abc 8734static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
39d5492a 8735 TCGv_i32 addr, int size)
426f5abc 8736{
354161b3
EC
8737 TCGv_i32 t0, t1, t2;
8738 TCGv_i64 extaddr;
8739 TCGv taddr;
42a268c2
RH
8740 TCGLabel *done_label;
8741 TCGLabel *fail_label;
354161b3 8742 TCGMemOp opc = size | MO_ALIGN | s->be_data;
426f5abc
PB
8743
8744 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
8745 [addr] = {Rt};
8746 {Rd} = 0;
8747 } else {
8748 {Rd} = 1;
8749 } */
8750 fail_label = gen_new_label();
8751 done_label = gen_new_label();
03d05e2d
PM
8752 extaddr = tcg_temp_new_i64();
8753 tcg_gen_extu_i32_i64(extaddr, addr);
8754 tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
8755 tcg_temp_free_i64(extaddr);
8756
354161b3
EC
8757 taddr = gen_aa32_addr(s, addr, opc);
8758 t0 = tcg_temp_new_i32();
8759 t1 = load_reg(s, rt);
426f5abc 8760 if (size == 3) {
354161b3
EC
8761 TCGv_i64 o64 = tcg_temp_new_i64();
8762 TCGv_i64 n64 = tcg_temp_new_i64();
03d05e2d 8763
354161b3 8764 t2 = load_reg(s, rt2);
3448d47b
PM
8765 /* For AArch32, architecturally the 32-bit word at the lowest
8766 * address is always Rt and the one at addr+4 is Rt2, even if
8767 * the CPU is big-endian. Since we're going to treat this as a
8768 * single 64-bit BE store, we need to put the two halves in the
8769 * opposite order for BE to LE, so that they end up in the right
8770 * places.
8771 * We don't want gen_aa32_frob64() because that does the wrong
8772 * thing for BE32 usermode.
8773 */
8774 if (s->be_data == MO_BE) {
8775 tcg_gen_concat_i32_i64(n64, t2, t1);
8776 } else {
8777 tcg_gen_concat_i32_i64(n64, t1, t2);
8778 }
354161b3 8779 tcg_temp_free_i32(t2);
03d05e2d 8780
354161b3
EC
8781 tcg_gen_atomic_cmpxchg_i64(o64, taddr, cpu_exclusive_val, n64,
8782 get_mem_index(s), opc);
8783 tcg_temp_free_i64(n64);
8784
354161b3
EC
8785 tcg_gen_setcond_i64(TCG_COND_NE, o64, o64, cpu_exclusive_val);
8786 tcg_gen_extrl_i64_i32(t0, o64);
8787
8788 tcg_temp_free_i64(o64);
8789 } else {
8790 t2 = tcg_temp_new_i32();
8791 tcg_gen_extrl_i64_i32(t2, cpu_exclusive_val);
8792 tcg_gen_atomic_cmpxchg_i32(t0, taddr, t2, t1, get_mem_index(s), opc);
8793 tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t2);
8794 tcg_temp_free_i32(t2);
426f5abc 8795 }
354161b3
EC
8796 tcg_temp_free_i32(t1);
8797 tcg_temp_free(taddr);
8798 tcg_gen_mov_i32(cpu_R[rd], t0);
8799 tcg_temp_free_i32(t0);
426f5abc 8800 tcg_gen_br(done_label);
354161b3 8801
426f5abc
PB
8802 gen_set_label(fail_label);
8803 tcg_gen_movi_i32(cpu_R[rd], 1);
8804 gen_set_label(done_label);
03d05e2d 8805 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
426f5abc 8806}
426f5abc 8807
81465888
PM
8808/* gen_srs:
8809 * @env: CPUARMState
8810 * @s: DisasContext
8811 * @mode: mode field from insn (which stack to store to)
8812 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
8813 * @writeback: true if writeback bit set
8814 *
8815 * Generate code for the SRS (Store Return State) insn.
8816 */
8817static void gen_srs(DisasContext *s,
8818 uint32_t mode, uint32_t amode, bool writeback)
8819{
8820 int32_t offset;
cbc0326b
PM
8821 TCGv_i32 addr, tmp;
8822 bool undef = false;
8823
8824 /* SRS is:
8825 * - trapped to EL3 if EL3 is AArch64 and we are at Secure EL1
ba63cf47 8826 * and specified mode is monitor mode
cbc0326b
PM
8827 * - UNDEFINED in Hyp mode
8828 * - UNPREDICTABLE in User or System mode
8829 * - UNPREDICTABLE if the specified mode is:
8830 * -- not implemented
8831 * -- not a valid mode number
8832 * -- a mode that's at a higher exception level
8833 * -- Monitor, if we are Non-secure
f01377f5 8834 * For the UNPREDICTABLE cases we choose to UNDEF.
cbc0326b 8835 */
ba63cf47 8836 if (s->current_el == 1 && !s->ns && mode == ARM_CPU_MODE_MON) {
cbc0326b
PM
8837 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), 3);
8838 return;
8839 }
8840
8841 if (s->current_el == 0 || s->current_el == 2) {
8842 undef = true;
8843 }
8844
8845 switch (mode) {
8846 case ARM_CPU_MODE_USR:
8847 case ARM_CPU_MODE_FIQ:
8848 case ARM_CPU_MODE_IRQ:
8849 case ARM_CPU_MODE_SVC:
8850 case ARM_CPU_MODE_ABT:
8851 case ARM_CPU_MODE_UND:
8852 case ARM_CPU_MODE_SYS:
8853 break;
8854 case ARM_CPU_MODE_HYP:
8855 if (s->current_el == 1 || !arm_dc_feature(s, ARM_FEATURE_EL2)) {
8856 undef = true;
8857 }
8858 break;
8859 case ARM_CPU_MODE_MON:
8860 /* No need to check specifically for "are we non-secure" because
8861 * we've already made EL0 UNDEF and handled the trap for S-EL1;
8862 * so if this isn't EL3 then we must be non-secure.
8863 */
8864 if (s->current_el != 3) {
8865 undef = true;
8866 }
8867 break;
8868 default:
8869 undef = true;
8870 }
8871
8872 if (undef) {
8873 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
8874 default_exception_el(s));
8875 return;
8876 }
8877
8878 addr = tcg_temp_new_i32();
8879 tmp = tcg_const_i32(mode);
f01377f5
PM
8880 /* get_r13_banked() will raise an exception if called from System mode */
8881 gen_set_condexec(s);
8882 gen_set_pc_im(s, s->pc - 4);
81465888
PM
8883 gen_helper_get_r13_banked(addr, cpu_env, tmp);
8884 tcg_temp_free_i32(tmp);
8885 switch (amode) {
8886 case 0: /* DA */
8887 offset = -4;
8888 break;
8889 case 1: /* IA */
8890 offset = 0;
8891 break;
8892 case 2: /* DB */
8893 offset = -8;
8894 break;
8895 case 3: /* IB */
8896 offset = 4;
8897 break;
8898 default:
8899 abort();
8900 }
8901 tcg_gen_addi_i32(addr, addr, offset);
8902 tmp = load_reg(s, 14);
12dcc321 8903 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 8904 tcg_temp_free_i32(tmp);
81465888
PM
8905 tmp = load_cpu_field(spsr);
8906 tcg_gen_addi_i32(addr, addr, 4);
12dcc321 8907 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 8908 tcg_temp_free_i32(tmp);
81465888
PM
8909 if (writeback) {
8910 switch (amode) {
8911 case 0:
8912 offset = -8;
8913 break;
8914 case 1:
8915 offset = 4;
8916 break;
8917 case 2:
8918 offset = -4;
8919 break;
8920 case 3:
8921 offset = 0;
8922 break;
8923 default:
8924 abort();
8925 }
8926 tcg_gen_addi_i32(addr, addr, offset);
8927 tmp = tcg_const_i32(mode);
8928 gen_helper_set_r13_banked(cpu_env, tmp, addr);
8929 tcg_temp_free_i32(tmp);
8930 }
8931 tcg_temp_free_i32(addr);
dcba3a8d 8932 s->base.is_jmp = DISAS_UPDATE;
81465888
PM
8933}
8934
c2d9644e
RK
8935/* Generate a label used for skipping this instruction */
8936static void arm_gen_condlabel(DisasContext *s)
8937{
8938 if (!s->condjmp) {
8939 s->condlabel = gen_new_label();
8940 s->condjmp = 1;
8941 }
8942}
8943
8944/* Skip this instruction if the ARM condition is false */
8945static void arm_skip_unless(DisasContext *s, uint32_t cond)
8946{
8947 arm_gen_condlabel(s);
8948 arm_gen_test_cc(cond ^ 1, s->condlabel);
8949}
8950
f4df2210 8951static void disas_arm_insn(DisasContext *s, unsigned int insn)
9ee6e8bb 8952{
f4df2210 8953 unsigned int cond, val, op1, i, shift, rm, rs, rn, rd, sh;
39d5492a
PM
8954 TCGv_i32 tmp;
8955 TCGv_i32 tmp2;
8956 TCGv_i32 tmp3;
8957 TCGv_i32 addr;
a7812ae4 8958 TCGv_i64 tmp64;
9ee6e8bb 8959
e13886e3
PM
8960 /* M variants do not implement ARM mode; this must raise the INVSTATE
8961 * UsageFault exception.
8962 */
b53d8923 8963 if (arm_dc_feature(s, ARM_FEATURE_M)) {
e13886e3
PM
8964 gen_exception_insn(s, 4, EXCP_INVSTATE, syn_uncategorized(),
8965 default_exception_el(s));
8966 return;
b53d8923 8967 }
9ee6e8bb
PB
8968 cond = insn >> 28;
8969 if (cond == 0xf){
be5e7a76
DES
8970 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
8971 * choose to UNDEF. In ARMv5 and above the space is used
8972 * for miscellaneous unconditional instructions.
8973 */
8974 ARCH(5);
8975
9ee6e8bb
PB
8976 /* Unconditional instructions. */
8977 if (((insn >> 25) & 7) == 1) {
8978 /* NEON Data processing. */
d614a513 8979 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
9ee6e8bb 8980 goto illegal_op;
d614a513 8981 }
9ee6e8bb 8982
7dcc1f89 8983 if (disas_neon_data_insn(s, insn)) {
9ee6e8bb 8984 goto illegal_op;
7dcc1f89 8985 }
9ee6e8bb
PB
8986 return;
8987 }
8988 if ((insn & 0x0f100000) == 0x04000000) {
8989 /* NEON load/store. */
d614a513 8990 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
9ee6e8bb 8991 goto illegal_op;
d614a513 8992 }
9ee6e8bb 8993
7dcc1f89 8994 if (disas_neon_ls_insn(s, insn)) {
9ee6e8bb 8995 goto illegal_op;
7dcc1f89 8996 }
9ee6e8bb
PB
8997 return;
8998 }
6a57f3eb
WN
8999 if ((insn & 0x0f000e10) == 0x0e000a00) {
9000 /* VFP. */
7dcc1f89 9001 if (disas_vfp_insn(s, insn)) {
6a57f3eb
WN
9002 goto illegal_op;
9003 }
9004 return;
9005 }
3d185e5d
PM
9006 if (((insn & 0x0f30f000) == 0x0510f000) ||
9007 ((insn & 0x0f30f010) == 0x0710f000)) {
9008 if ((insn & (1 << 22)) == 0) {
9009 /* PLDW; v7MP */
d614a513 9010 if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
3d185e5d
PM
9011 goto illegal_op;
9012 }
9013 }
9014 /* Otherwise PLD; v5TE+ */
be5e7a76 9015 ARCH(5TE);
3d185e5d
PM
9016 return;
9017 }
9018 if (((insn & 0x0f70f000) == 0x0450f000) ||
9019 ((insn & 0x0f70f010) == 0x0650f000)) {
9020 ARCH(7);
9021 return; /* PLI; V7 */
9022 }
9023 if (((insn & 0x0f700000) == 0x04100000) ||
9024 ((insn & 0x0f700010) == 0x06100000)) {
d614a513 9025 if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
3d185e5d
PM
9026 goto illegal_op;
9027 }
9028 return; /* v7MP: Unallocated memory hint: must NOP */
9029 }
9030
9031 if ((insn & 0x0ffffdff) == 0x01010000) {
9ee6e8bb
PB
9032 ARCH(6);
9033 /* setend */
9886ecdf
PB
9034 if (((insn >> 9) & 1) != !!(s->be_data == MO_BE)) {
9035 gen_helper_setend(cpu_env);
dcba3a8d 9036 s->base.is_jmp = DISAS_UPDATE;
9ee6e8bb
PB
9037 }
9038 return;
9039 } else if ((insn & 0x0fffff00) == 0x057ff000) {
9040 switch ((insn >> 4) & 0xf) {
9041 case 1: /* clrex */
9042 ARCH(6K);
426f5abc 9043 gen_clrex(s);
9ee6e8bb
PB
9044 return;
9045 case 4: /* dsb */
9046 case 5: /* dmb */
9ee6e8bb 9047 ARCH(7);
61e4c432 9048 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
9ee6e8bb 9049 return;
6df99dec
SS
9050 case 6: /* isb */
9051 /* We need to break the TB after this insn to execute
9052 * self-modifying code correctly and also to take
9053 * any pending interrupts immediately.
9054 */
0b609cc1 9055 gen_goto_tb(s, 0, s->pc & ~1);
6df99dec 9056 return;
9ee6e8bb
PB
9057 default:
9058 goto illegal_op;
9059 }
9060 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
9061 /* srs */
81465888
PM
9062 ARCH(6);
9063 gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21));
3b328448 9064 return;
ea825eee 9065 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
9ee6e8bb 9066 /* rfe */
c67b6b71 9067 int32_t offset;
9ee6e8bb
PB
9068 if (IS_USER(s))
9069 goto illegal_op;
9070 ARCH(6);
9071 rn = (insn >> 16) & 0xf;
b0109805 9072 addr = load_reg(s, rn);
9ee6e8bb
PB
9073 i = (insn >> 23) & 3;
9074 switch (i) {
b0109805 9075 case 0: offset = -4; break; /* DA */
c67b6b71
FN
9076 case 1: offset = 0; break; /* IA */
9077 case 2: offset = -8; break; /* DB */
b0109805 9078 case 3: offset = 4; break; /* IB */
9ee6e8bb
PB
9079 default: abort();
9080 }
9081 if (offset)
b0109805
PB
9082 tcg_gen_addi_i32(addr, addr, offset);
9083 /* Load PC into tmp and CPSR into tmp2. */
5a839c0d 9084 tmp = tcg_temp_new_i32();
12dcc321 9085 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 9086 tcg_gen_addi_i32(addr, addr, 4);
5a839c0d 9087 tmp2 = tcg_temp_new_i32();
12dcc321 9088 gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
9ee6e8bb
PB
9089 if (insn & (1 << 21)) {
9090 /* Base writeback. */
9091 switch (i) {
b0109805 9092 case 0: offset = -8; break;
c67b6b71
FN
9093 case 1: offset = 4; break;
9094 case 2: offset = -4; break;
b0109805 9095 case 3: offset = 0; break;
9ee6e8bb
PB
9096 default: abort();
9097 }
9098 if (offset)
b0109805
PB
9099 tcg_gen_addi_i32(addr, addr, offset);
9100 store_reg(s, rn, addr);
9101 } else {
7d1b0095 9102 tcg_temp_free_i32(addr);
9ee6e8bb 9103 }
b0109805 9104 gen_rfe(s, tmp, tmp2);
c67b6b71 9105 return;
9ee6e8bb
PB
9106 } else if ((insn & 0x0e000000) == 0x0a000000) {
9107 /* branch link and change to thumb (blx <offset>) */
9108 int32_t offset;
9109
9110 val = (uint32_t)s->pc;
7d1b0095 9111 tmp = tcg_temp_new_i32();
d9ba4830
PB
9112 tcg_gen_movi_i32(tmp, val);
9113 store_reg(s, 14, tmp);
9ee6e8bb
PB
9114 /* Sign-extend the 24-bit offset */
9115 offset = (((int32_t)insn) << 8) >> 8;
9116 /* offset * 4 + bit24 * 2 + (thumb bit) */
9117 val += (offset << 2) | ((insn >> 23) & 2) | 1;
9118 /* pipeline offset */
9119 val += 4;
be5e7a76 9120 /* protected by ARCH(5); above, near the start of uncond block */
d9ba4830 9121 gen_bx_im(s, val);
9ee6e8bb
PB
9122 return;
9123 } else if ((insn & 0x0e000f00) == 0x0c000100) {
d614a513 9124 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
9ee6e8bb 9125 /* iWMMXt register transfer. */
c0f4af17 9126 if (extract32(s->c15_cpar, 1, 1)) {
7dcc1f89 9127 if (!disas_iwmmxt_insn(s, insn)) {
9ee6e8bb 9128 return;
c0f4af17
PM
9129 }
9130 }
9ee6e8bb 9131 }
8b7209fa
RH
9132 } else if ((insn & 0x0e000a00) == 0x0c000800
9133 && arm_dc_feature(s, ARM_FEATURE_V8)) {
9134 if (disas_neon_insn_3same_ext(s, insn)) {
9135 goto illegal_op;
9136 }
9137 return;
638808ff
RH
9138 } else if ((insn & 0x0f000a00) == 0x0e000800
9139 && arm_dc_feature(s, ARM_FEATURE_V8)) {
9140 if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
9141 goto illegal_op;
9142 }
9143 return;
9ee6e8bb
PB
9144 } else if ((insn & 0x0fe00000) == 0x0c400000) {
9145 /* Coprocessor double register transfer. */
be5e7a76 9146 ARCH(5TE);
9ee6e8bb
PB
9147 } else if ((insn & 0x0f000010) == 0x0e000010) {
9148 /* Additional coprocessor register transfer. */
7997d92f 9149 } else if ((insn & 0x0ff10020) == 0x01000000) {
9ee6e8bb
PB
9150 uint32_t mask;
9151 uint32_t val;
9152 /* cps (privileged) */
9153 if (IS_USER(s))
9154 return;
9155 mask = val = 0;
9156 if (insn & (1 << 19)) {
9157 if (insn & (1 << 8))
9158 mask |= CPSR_A;
9159 if (insn & (1 << 7))
9160 mask |= CPSR_I;
9161 if (insn & (1 << 6))
9162 mask |= CPSR_F;
9163 if (insn & (1 << 18))
9164 val |= mask;
9165 }
7997d92f 9166 if (insn & (1 << 17)) {
9ee6e8bb
PB
9167 mask |= CPSR_M;
9168 val |= (insn & 0x1f);
9169 }
9170 if (mask) {
2fbac54b 9171 gen_set_psr_im(s, mask, 0, val);
9ee6e8bb
PB
9172 }
9173 return;
9174 }
9175 goto illegal_op;
9176 }
9177 if (cond != 0xe) {
9178 /* if not always execute, we generate a conditional jump to
9179 next instruction */
c2d9644e 9180 arm_skip_unless(s, cond);
9ee6e8bb
PB
9181 }
9182 if ((insn & 0x0f900000) == 0x03000000) {
9183 if ((insn & (1 << 21)) == 0) {
9184 ARCH(6T2);
9185 rd = (insn >> 12) & 0xf;
9186 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
9187 if ((insn & (1 << 22)) == 0) {
9188 /* MOVW */
7d1b0095 9189 tmp = tcg_temp_new_i32();
5e3f878a 9190 tcg_gen_movi_i32(tmp, val);
9ee6e8bb
PB
9191 } else {
9192 /* MOVT */
5e3f878a 9193 tmp = load_reg(s, rd);
86831435 9194 tcg_gen_ext16u_i32(tmp, tmp);
5e3f878a 9195 tcg_gen_ori_i32(tmp, tmp, val << 16);
9ee6e8bb 9196 }
5e3f878a 9197 store_reg(s, rd, tmp);
9ee6e8bb
PB
9198 } else {
9199 if (((insn >> 12) & 0xf) != 0xf)
9200 goto illegal_op;
9201 if (((insn >> 16) & 0xf) == 0) {
9202 gen_nop_hint(s, insn & 0xff);
9203 } else {
9204 /* CPSR = immediate */
9205 val = insn & 0xff;
9206 shift = ((insn >> 8) & 0xf) * 2;
9207 if (shift)
9208 val = (val >> shift) | (val << (32 - shift));
9ee6e8bb 9209 i = ((insn & (1 << 22)) != 0);
7dcc1f89
PM
9210 if (gen_set_psr_im(s, msr_mask(s, (insn >> 16) & 0xf, i),
9211 i, val)) {
9ee6e8bb 9212 goto illegal_op;
7dcc1f89 9213 }
9ee6e8bb
PB
9214 }
9215 }
9216 } else if ((insn & 0x0f900000) == 0x01000000
9217 && (insn & 0x00000090) != 0x00000090) {
9218 /* miscellaneous instructions */
9219 op1 = (insn >> 21) & 3;
9220 sh = (insn >> 4) & 0xf;
9221 rm = insn & 0xf;
9222 switch (sh) {
8bfd0550
PM
9223 case 0x0: /* MSR, MRS */
9224 if (insn & (1 << 9)) {
9225 /* MSR (banked) and MRS (banked) */
9226 int sysm = extract32(insn, 16, 4) |
9227 (extract32(insn, 8, 1) << 4);
9228 int r = extract32(insn, 22, 1);
9229
9230 if (op1 & 1) {
9231 /* MSR (banked) */
9232 gen_msr_banked(s, r, sysm, rm);
9233 } else {
9234 /* MRS (banked) */
9235 int rd = extract32(insn, 12, 4);
9236
9237 gen_mrs_banked(s, r, sysm, rd);
9238 }
9239 break;
9240 }
9241
9242 /* MSR, MRS (for PSRs) */
9ee6e8bb
PB
9243 if (op1 & 1) {
9244 /* PSR = reg */
2fbac54b 9245 tmp = load_reg(s, rm);
9ee6e8bb 9246 i = ((op1 & 2) != 0);
7dcc1f89 9247 if (gen_set_psr(s, msr_mask(s, (insn >> 16) & 0xf, i), i, tmp))
9ee6e8bb
PB
9248 goto illegal_op;
9249 } else {
9250 /* reg = PSR */
9251 rd = (insn >> 12) & 0xf;
9252 if (op1 & 2) {
9253 if (IS_USER(s))
9254 goto illegal_op;
d9ba4830 9255 tmp = load_cpu_field(spsr);
9ee6e8bb 9256 } else {
7d1b0095 9257 tmp = tcg_temp_new_i32();
9ef39277 9258 gen_helper_cpsr_read(tmp, cpu_env);
9ee6e8bb 9259 }
d9ba4830 9260 store_reg(s, rd, tmp);
9ee6e8bb
PB
9261 }
9262 break;
9263 case 0x1:
9264 if (op1 == 1) {
9265 /* branch/exchange thumb (bx). */
be5e7a76 9266 ARCH(4T);
d9ba4830
PB
9267 tmp = load_reg(s, rm);
9268 gen_bx(s, tmp);
9ee6e8bb
PB
9269 } else if (op1 == 3) {
9270 /* clz */
be5e7a76 9271 ARCH(5);
9ee6e8bb 9272 rd = (insn >> 12) & 0xf;
1497c961 9273 tmp = load_reg(s, rm);
7539a012 9274 tcg_gen_clzi_i32(tmp, tmp, 32);
1497c961 9275 store_reg(s, rd, tmp);
9ee6e8bb
PB
9276 } else {
9277 goto illegal_op;
9278 }
9279 break;
9280 case 0x2:
9281 if (op1 == 1) {
9282 ARCH(5J); /* bxj */
9283 /* Trivial implementation equivalent to bx. */
d9ba4830
PB
9284 tmp = load_reg(s, rm);
9285 gen_bx(s, tmp);
9ee6e8bb
PB
9286 } else {
9287 goto illegal_op;
9288 }
9289 break;
9290 case 0x3:
9291 if (op1 != 1)
9292 goto illegal_op;
9293
be5e7a76 9294 ARCH(5);
9ee6e8bb 9295 /* branch link/exchange thumb (blx) */
d9ba4830 9296 tmp = load_reg(s, rm);
7d1b0095 9297 tmp2 = tcg_temp_new_i32();
d9ba4830
PB
9298 tcg_gen_movi_i32(tmp2, s->pc);
9299 store_reg(s, 14, tmp2);
9300 gen_bx(s, tmp);
9ee6e8bb 9301 break;
eb0ecd5a
WN
9302 case 0x4:
9303 {
9304 /* crc32/crc32c */
9305 uint32_t c = extract32(insn, 8, 4);
9306
9307 /* Check this CPU supports ARMv8 CRC instructions.
9308 * op1 == 3 is UNPREDICTABLE but handle as UNDEFINED.
9309 * Bits 8, 10 and 11 should be zero.
9310 */
962fcbf2 9311 if (!dc_isar_feature(aa32_crc32, s) || op1 == 0x3 || (c & 0xd) != 0) {
eb0ecd5a
WN
9312 goto illegal_op;
9313 }
9314
9315 rn = extract32(insn, 16, 4);
9316 rd = extract32(insn, 12, 4);
9317
9318 tmp = load_reg(s, rn);
9319 tmp2 = load_reg(s, rm);
aa633469
PM
9320 if (op1 == 0) {
9321 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
9322 } else if (op1 == 1) {
9323 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
9324 }
eb0ecd5a
WN
9325 tmp3 = tcg_const_i32(1 << op1);
9326 if (c & 0x2) {
9327 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
9328 } else {
9329 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
9330 }
9331 tcg_temp_free_i32(tmp2);
9332 tcg_temp_free_i32(tmp3);
9333 store_reg(s, rd, tmp);
9334 break;
9335 }
9ee6e8bb 9336 case 0x5: /* saturating add/subtract */
be5e7a76 9337 ARCH(5TE);
9ee6e8bb
PB
9338 rd = (insn >> 12) & 0xf;
9339 rn = (insn >> 16) & 0xf;
b40d0353 9340 tmp = load_reg(s, rm);
5e3f878a 9341 tmp2 = load_reg(s, rn);
9ee6e8bb 9342 if (op1 & 2)
9ef39277 9343 gen_helper_double_saturate(tmp2, cpu_env, tmp2);
9ee6e8bb 9344 if (op1 & 1)
9ef39277 9345 gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 9346 else
9ef39277 9347 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
7d1b0095 9348 tcg_temp_free_i32(tmp2);
5e3f878a 9349 store_reg(s, rd, tmp);
9ee6e8bb 9350 break;
55c544ed
PM
9351 case 0x6: /* ERET */
9352 if (op1 != 3) {
9353 goto illegal_op;
9354 }
9355 if (!arm_dc_feature(s, ARM_FEATURE_V7VE)) {
9356 goto illegal_op;
9357 }
9358 if ((insn & 0x000fff0f) != 0x0000000e) {
9359 /* UNPREDICTABLE; we choose to UNDEF */
9360 goto illegal_op;
9361 }
9362
9363 if (s->current_el == 2) {
9364 tmp = load_cpu_field(elr_el[2]);
9365 } else {
9366 tmp = load_reg(s, 14);
9367 }
9368 gen_exception_return(s, tmp);
9369 break;
49e14940 9370 case 7:
d4a2dc67
PM
9371 {
9372 int imm16 = extract32(insn, 0, 4) | (extract32(insn, 8, 12) << 4);
37e6456e 9373 switch (op1) {
19a6e31c
PM
9374 case 0:
9375 /* HLT */
9376 gen_hlt(s, imm16);
9377 break;
37e6456e
PM
9378 case 1:
9379 /* bkpt */
9380 ARCH(5);
c900a2e6 9381 gen_exception_bkpt_insn(s, 4, syn_aa32_bkpt(imm16, false));
37e6456e
PM
9382 break;
9383 case 2:
9384 /* Hypervisor call (v7) */
9385 ARCH(7);
9386 if (IS_USER(s)) {
9387 goto illegal_op;
9388 }
9389 gen_hvc(s, imm16);
9390 break;
9391 case 3:
9392 /* Secure monitor call (v6+) */
9393 ARCH(6K);
9394 if (IS_USER(s)) {
9395 goto illegal_op;
9396 }
9397 gen_smc(s);
9398 break;
9399 default:
19a6e31c 9400 g_assert_not_reached();
49e14940 9401 }
9ee6e8bb 9402 break;
d4a2dc67 9403 }
9ee6e8bb
PB
9404 case 0x8: /* signed multiply */
9405 case 0xa:
9406 case 0xc:
9407 case 0xe:
be5e7a76 9408 ARCH(5TE);
9ee6e8bb
PB
9409 rs = (insn >> 8) & 0xf;
9410 rn = (insn >> 12) & 0xf;
9411 rd = (insn >> 16) & 0xf;
9412 if (op1 == 1) {
9413 /* (32 * 16) >> 16 */
5e3f878a
PB
9414 tmp = load_reg(s, rm);
9415 tmp2 = load_reg(s, rs);
9ee6e8bb 9416 if (sh & 4)
5e3f878a 9417 tcg_gen_sari_i32(tmp2, tmp2, 16);
9ee6e8bb 9418 else
5e3f878a 9419 gen_sxth(tmp2);
a7812ae4
PB
9420 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9421 tcg_gen_shri_i64(tmp64, tmp64, 16);
7d1b0095 9422 tmp = tcg_temp_new_i32();
ecc7b3aa 9423 tcg_gen_extrl_i64_i32(tmp, tmp64);
b75263d6 9424 tcg_temp_free_i64(tmp64);
9ee6e8bb 9425 if ((sh & 2) == 0) {
5e3f878a 9426 tmp2 = load_reg(s, rn);
9ef39277 9427 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 9428 tcg_temp_free_i32(tmp2);
9ee6e8bb 9429 }
5e3f878a 9430 store_reg(s, rd, tmp);
9ee6e8bb
PB
9431 } else {
9432 /* 16 * 16 */
5e3f878a
PB
9433 tmp = load_reg(s, rm);
9434 tmp2 = load_reg(s, rs);
9435 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
7d1b0095 9436 tcg_temp_free_i32(tmp2);
9ee6e8bb 9437 if (op1 == 2) {
a7812ae4
PB
9438 tmp64 = tcg_temp_new_i64();
9439 tcg_gen_ext_i32_i64(tmp64, tmp);
7d1b0095 9440 tcg_temp_free_i32(tmp);
a7812ae4
PB
9441 gen_addq(s, tmp64, rn, rd);
9442 gen_storeq_reg(s, rn, rd, tmp64);
b75263d6 9443 tcg_temp_free_i64(tmp64);
9ee6e8bb
PB
9444 } else {
9445 if (op1 == 0) {
5e3f878a 9446 tmp2 = load_reg(s, rn);
9ef39277 9447 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 9448 tcg_temp_free_i32(tmp2);
9ee6e8bb 9449 }
5e3f878a 9450 store_reg(s, rd, tmp);
9ee6e8bb
PB
9451 }
9452 }
9453 break;
9454 default:
9455 goto illegal_op;
9456 }
9457 } else if (((insn & 0x0e000000) == 0 &&
9458 (insn & 0x00000090) != 0x90) ||
9459 ((insn & 0x0e000000) == (1 << 25))) {
9460 int set_cc, logic_cc, shiftop;
9461
9462 op1 = (insn >> 21) & 0xf;
9463 set_cc = (insn >> 20) & 1;
9464 logic_cc = table_logic_cc[op1] & set_cc;
9465
9466 /* data processing instruction */
9467 if (insn & (1 << 25)) {
9468 /* immediate operand */
9469 val = insn & 0xff;
9470 shift = ((insn >> 8) & 0xf) * 2;
e9bb4aa9 9471 if (shift) {
9ee6e8bb 9472 val = (val >> shift) | (val << (32 - shift));
e9bb4aa9 9473 }
7d1b0095 9474 tmp2 = tcg_temp_new_i32();
e9bb4aa9
JR
9475 tcg_gen_movi_i32(tmp2, val);
9476 if (logic_cc && shift) {
9477 gen_set_CF_bit31(tmp2);
9478 }
9ee6e8bb
PB
9479 } else {
9480 /* register */
9481 rm = (insn) & 0xf;
e9bb4aa9 9482 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
9483 shiftop = (insn >> 5) & 3;
9484 if (!(insn & (1 << 4))) {
9485 shift = (insn >> 7) & 0x1f;
e9bb4aa9 9486 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
9ee6e8bb
PB
9487 } else {
9488 rs = (insn >> 8) & 0xf;
8984bd2e 9489 tmp = load_reg(s, rs);
e9bb4aa9 9490 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
9ee6e8bb
PB
9491 }
9492 }
9493 if (op1 != 0x0f && op1 != 0x0d) {
9494 rn = (insn >> 16) & 0xf;
e9bb4aa9
JR
9495 tmp = load_reg(s, rn);
9496 } else {
f764718d 9497 tmp = NULL;
9ee6e8bb
PB
9498 }
9499 rd = (insn >> 12) & 0xf;
9500 switch(op1) {
9501 case 0x00:
e9bb4aa9
JR
9502 tcg_gen_and_i32(tmp, tmp, tmp2);
9503 if (logic_cc) {
9504 gen_logic_CC(tmp);
9505 }
7dcc1f89 9506 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
9507 break;
9508 case 0x01:
e9bb4aa9
JR
9509 tcg_gen_xor_i32(tmp, tmp, tmp2);
9510 if (logic_cc) {
9511 gen_logic_CC(tmp);
9512 }
7dcc1f89 9513 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
9514 break;
9515 case 0x02:
9516 if (set_cc && rd == 15) {
9517 /* SUBS r15, ... is used for exception return. */
e9bb4aa9 9518 if (IS_USER(s)) {
9ee6e8bb 9519 goto illegal_op;
e9bb4aa9 9520 }
72485ec4 9521 gen_sub_CC(tmp, tmp, tmp2);
e9bb4aa9 9522 gen_exception_return(s, tmp);
9ee6e8bb 9523 } else {
e9bb4aa9 9524 if (set_cc) {
72485ec4 9525 gen_sub_CC(tmp, tmp, tmp2);
e9bb4aa9
JR
9526 } else {
9527 tcg_gen_sub_i32(tmp, tmp, tmp2);
9528 }
7dcc1f89 9529 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
9530 }
9531 break;
9532 case 0x03:
e9bb4aa9 9533 if (set_cc) {
72485ec4 9534 gen_sub_CC(tmp, tmp2, tmp);
e9bb4aa9
JR
9535 } else {
9536 tcg_gen_sub_i32(tmp, tmp2, tmp);
9537 }
7dcc1f89 9538 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
9539 break;
9540 case 0x04:
e9bb4aa9 9541 if (set_cc) {
72485ec4 9542 gen_add_CC(tmp, tmp, tmp2);
e9bb4aa9
JR
9543 } else {
9544 tcg_gen_add_i32(tmp, tmp, tmp2);
9545 }
7dcc1f89 9546 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
9547 break;
9548 case 0x05:
e9bb4aa9 9549 if (set_cc) {
49b4c31e 9550 gen_adc_CC(tmp, tmp, tmp2);
e9bb4aa9
JR
9551 } else {
9552 gen_add_carry(tmp, tmp, tmp2);
9553 }
7dcc1f89 9554 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
9555 break;
9556 case 0x06:
e9bb4aa9 9557 if (set_cc) {
2de68a49 9558 gen_sbc_CC(tmp, tmp, tmp2);
e9bb4aa9
JR
9559 } else {
9560 gen_sub_carry(tmp, tmp, tmp2);
9561 }
7dcc1f89 9562 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
9563 break;
9564 case 0x07:
e9bb4aa9 9565 if (set_cc) {
2de68a49 9566 gen_sbc_CC(tmp, tmp2, tmp);
e9bb4aa9
JR
9567 } else {
9568 gen_sub_carry(tmp, tmp2, tmp);
9569 }
7dcc1f89 9570 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
9571 break;
9572 case 0x08:
9573 if (set_cc) {
e9bb4aa9
JR
9574 tcg_gen_and_i32(tmp, tmp, tmp2);
9575 gen_logic_CC(tmp);
9ee6e8bb 9576 }
7d1b0095 9577 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
9578 break;
9579 case 0x09:
9580 if (set_cc) {
e9bb4aa9
JR
9581 tcg_gen_xor_i32(tmp, tmp, tmp2);
9582 gen_logic_CC(tmp);
9ee6e8bb 9583 }
7d1b0095 9584 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
9585 break;
9586 case 0x0a:
9587 if (set_cc) {
72485ec4 9588 gen_sub_CC(tmp, tmp, tmp2);
9ee6e8bb 9589 }
7d1b0095 9590 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
9591 break;
9592 case 0x0b:
9593 if (set_cc) {
72485ec4 9594 gen_add_CC(tmp, tmp, tmp2);
9ee6e8bb 9595 }
7d1b0095 9596 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
9597 break;
9598 case 0x0c:
e9bb4aa9
JR
9599 tcg_gen_or_i32(tmp, tmp, tmp2);
9600 if (logic_cc) {
9601 gen_logic_CC(tmp);
9602 }
7dcc1f89 9603 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
9604 break;
9605 case 0x0d:
9606 if (logic_cc && rd == 15) {
9607 /* MOVS r15, ... is used for exception return. */
e9bb4aa9 9608 if (IS_USER(s)) {
9ee6e8bb 9609 goto illegal_op;
e9bb4aa9
JR
9610 }
9611 gen_exception_return(s, tmp2);
9ee6e8bb 9612 } else {
e9bb4aa9
JR
9613 if (logic_cc) {
9614 gen_logic_CC(tmp2);
9615 }
7dcc1f89 9616 store_reg_bx(s, rd, tmp2);
9ee6e8bb
PB
9617 }
9618 break;
9619 case 0x0e:
f669df27 9620 tcg_gen_andc_i32(tmp, tmp, tmp2);
e9bb4aa9
JR
9621 if (logic_cc) {
9622 gen_logic_CC(tmp);
9623 }
7dcc1f89 9624 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
9625 break;
9626 default:
9627 case 0x0f:
e9bb4aa9
JR
9628 tcg_gen_not_i32(tmp2, tmp2);
9629 if (logic_cc) {
9630 gen_logic_CC(tmp2);
9631 }
7dcc1f89 9632 store_reg_bx(s, rd, tmp2);
9ee6e8bb
PB
9633 break;
9634 }
e9bb4aa9 9635 if (op1 != 0x0f && op1 != 0x0d) {
7d1b0095 9636 tcg_temp_free_i32(tmp2);
e9bb4aa9 9637 }
9ee6e8bb
PB
9638 } else {
9639 /* other instructions */
9640 op1 = (insn >> 24) & 0xf;
9641 switch(op1) {
9642 case 0x0:
9643 case 0x1:
9644 /* multiplies, extra load/stores */
9645 sh = (insn >> 5) & 3;
9646 if (sh == 0) {
9647 if (op1 == 0x0) {
9648 rd = (insn >> 16) & 0xf;
9649 rn = (insn >> 12) & 0xf;
9650 rs = (insn >> 8) & 0xf;
9651 rm = (insn) & 0xf;
9652 op1 = (insn >> 20) & 0xf;
9653 switch (op1) {
9654 case 0: case 1: case 2: case 3: case 6:
9655 /* 32 bit mul */
5e3f878a
PB
9656 tmp = load_reg(s, rs);
9657 tmp2 = load_reg(s, rm);
9658 tcg_gen_mul_i32(tmp, tmp, tmp2);
7d1b0095 9659 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
9660 if (insn & (1 << 22)) {
9661 /* Subtract (mls) */
9662 ARCH(6T2);
5e3f878a
PB
9663 tmp2 = load_reg(s, rn);
9664 tcg_gen_sub_i32(tmp, tmp2, tmp);
7d1b0095 9665 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
9666 } else if (insn & (1 << 21)) {
9667 /* Add */
5e3f878a
PB
9668 tmp2 = load_reg(s, rn);
9669 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 9670 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
9671 }
9672 if (insn & (1 << 20))
5e3f878a
PB
9673 gen_logic_CC(tmp);
9674 store_reg(s, rd, tmp);
9ee6e8bb 9675 break;
8aac08b1
AJ
9676 case 4:
9677 /* 64 bit mul double accumulate (UMAAL) */
9678 ARCH(6);
9679 tmp = load_reg(s, rs);
9680 tmp2 = load_reg(s, rm);
9681 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
9682 gen_addq_lo(s, tmp64, rn);
9683 gen_addq_lo(s, tmp64, rd);
9684 gen_storeq_reg(s, rn, rd, tmp64);
9685 tcg_temp_free_i64(tmp64);
9686 break;
9687 case 8: case 9: case 10: case 11:
9688 case 12: case 13: case 14: case 15:
9689 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
5e3f878a
PB
9690 tmp = load_reg(s, rs);
9691 tmp2 = load_reg(s, rm);
8aac08b1 9692 if (insn & (1 << 22)) {
c9f10124 9693 tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2);
8aac08b1 9694 } else {
c9f10124 9695 tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2);
8aac08b1
AJ
9696 }
9697 if (insn & (1 << 21)) { /* mult accumulate */
39d5492a
PM
9698 TCGv_i32 al = load_reg(s, rn);
9699 TCGv_i32 ah = load_reg(s, rd);
c9f10124 9700 tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, al, ah);
39d5492a
PM
9701 tcg_temp_free_i32(al);
9702 tcg_temp_free_i32(ah);
9ee6e8bb 9703 }
8aac08b1 9704 if (insn & (1 << 20)) {
c9f10124 9705 gen_logicq_cc(tmp, tmp2);
8aac08b1 9706 }
c9f10124
RH
9707 store_reg(s, rn, tmp);
9708 store_reg(s, rd, tmp2);
9ee6e8bb 9709 break;
8aac08b1
AJ
9710 default:
9711 goto illegal_op;
9ee6e8bb
PB
9712 }
9713 } else {
9714 rn = (insn >> 16) & 0xf;
9715 rd = (insn >> 12) & 0xf;
9716 if (insn & (1 << 23)) {
9717 /* load/store exclusive */
2359bf80 9718 int op2 = (insn >> 8) & 3;
86753403 9719 op1 = (insn >> 21) & 0x3;
2359bf80
MR
9720
9721 switch (op2) {
9722 case 0: /* lda/stl */
9723 if (op1 == 1) {
9724 goto illegal_op;
9725 }
9726 ARCH(8);
9727 break;
9728 case 1: /* reserved */
9729 goto illegal_op;
9730 case 2: /* ldaex/stlex */
9731 ARCH(8);
9732 break;
9733 case 3: /* ldrex/strex */
9734 if (op1) {
9735 ARCH(6K);
9736 } else {
9737 ARCH(6);
9738 }
9739 break;
9740 }
9741
3174f8e9 9742 addr = tcg_temp_local_new_i32();
98a46317 9743 load_reg_var(s, addr, rn);
2359bf80
MR
9744
9745 /* Since the emulation does not have barriers,
9746 the acquire/release semantics need no special
9747 handling */
9748 if (op2 == 0) {
9749 if (insn & (1 << 20)) {
9750 tmp = tcg_temp_new_i32();
9751 switch (op1) {
9752 case 0: /* lda */
9bb6558a
PM
9753 gen_aa32_ld32u_iss(s, tmp, addr,
9754 get_mem_index(s),
9755 rd | ISSIsAcqRel);
2359bf80
MR
9756 break;
9757 case 2: /* ldab */
9bb6558a
PM
9758 gen_aa32_ld8u_iss(s, tmp, addr,
9759 get_mem_index(s),
9760 rd | ISSIsAcqRel);
2359bf80
MR
9761 break;
9762 case 3: /* ldah */
9bb6558a
PM
9763 gen_aa32_ld16u_iss(s, tmp, addr,
9764 get_mem_index(s),
9765 rd | ISSIsAcqRel);
2359bf80
MR
9766 break;
9767 default:
9768 abort();
9769 }
9770 store_reg(s, rd, tmp);
9771 } else {
9772 rm = insn & 0xf;
9773 tmp = load_reg(s, rm);
9774 switch (op1) {
9775 case 0: /* stl */
9bb6558a
PM
9776 gen_aa32_st32_iss(s, tmp, addr,
9777 get_mem_index(s),
9778 rm | ISSIsAcqRel);
2359bf80
MR
9779 break;
9780 case 2: /* stlb */
9bb6558a
PM
9781 gen_aa32_st8_iss(s, tmp, addr,
9782 get_mem_index(s),
9783 rm | ISSIsAcqRel);
2359bf80
MR
9784 break;
9785 case 3: /* stlh */
9bb6558a
PM
9786 gen_aa32_st16_iss(s, tmp, addr,
9787 get_mem_index(s),
9788 rm | ISSIsAcqRel);
2359bf80
MR
9789 break;
9790 default:
9791 abort();
9792 }
9793 tcg_temp_free_i32(tmp);
9794 }
9795 } else if (insn & (1 << 20)) {
86753403
PB
9796 switch (op1) {
9797 case 0: /* ldrex */
426f5abc 9798 gen_load_exclusive(s, rd, 15, addr, 2);
86753403
PB
9799 break;
9800 case 1: /* ldrexd */
426f5abc 9801 gen_load_exclusive(s, rd, rd + 1, addr, 3);
86753403
PB
9802 break;
9803 case 2: /* ldrexb */
426f5abc 9804 gen_load_exclusive(s, rd, 15, addr, 0);
86753403
PB
9805 break;
9806 case 3: /* ldrexh */
426f5abc 9807 gen_load_exclusive(s, rd, 15, addr, 1);
86753403
PB
9808 break;
9809 default:
9810 abort();
9811 }
9ee6e8bb
PB
9812 } else {
9813 rm = insn & 0xf;
86753403
PB
9814 switch (op1) {
9815 case 0: /* strex */
426f5abc 9816 gen_store_exclusive(s, rd, rm, 15, addr, 2);
86753403
PB
9817 break;
9818 case 1: /* strexd */
502e64fe 9819 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
86753403
PB
9820 break;
9821 case 2: /* strexb */
426f5abc 9822 gen_store_exclusive(s, rd, rm, 15, addr, 0);
86753403
PB
9823 break;
9824 case 3: /* strexh */
426f5abc 9825 gen_store_exclusive(s, rd, rm, 15, addr, 1);
86753403
PB
9826 break;
9827 default:
9828 abort();
9829 }
9ee6e8bb 9830 }
39d5492a 9831 tcg_temp_free_i32(addr);
c4869ca6
OS
9832 } else if ((insn & 0x00300f00) == 0) {
9833 /* 0bcccc_0001_0x00_xxxx_xxxx_0000_1001_xxxx
9834 * - SWP, SWPB
9835 */
9836
cf12bce0
EC
9837 TCGv taddr;
9838 TCGMemOp opc = s->be_data;
9839
9ee6e8bb
PB
9840 rm = (insn) & 0xf;
9841
9ee6e8bb 9842 if (insn & (1 << 22)) {
cf12bce0 9843 opc |= MO_UB;
9ee6e8bb 9844 } else {
cf12bce0 9845 opc |= MO_UL | MO_ALIGN;
9ee6e8bb 9846 }
cf12bce0
EC
9847
9848 addr = load_reg(s, rn);
9849 taddr = gen_aa32_addr(s, addr, opc);
7d1b0095 9850 tcg_temp_free_i32(addr);
cf12bce0
EC
9851
9852 tmp = load_reg(s, rm);
9853 tcg_gen_atomic_xchg_i32(tmp, taddr, tmp,
9854 get_mem_index(s), opc);
9855 tcg_temp_free(taddr);
9856 store_reg(s, rd, tmp);
c4869ca6
OS
9857 } else {
9858 goto illegal_op;
9ee6e8bb
PB
9859 }
9860 }
9861 } else {
9862 int address_offset;
3960c336 9863 bool load = insn & (1 << 20);
63f26fcf
PM
9864 bool wbit = insn & (1 << 21);
9865 bool pbit = insn & (1 << 24);
3960c336 9866 bool doubleword = false;
9bb6558a
PM
9867 ISSInfo issinfo;
9868
9ee6e8bb
PB
9869 /* Misc load/store */
9870 rn = (insn >> 16) & 0xf;
9871 rd = (insn >> 12) & 0xf;
3960c336 9872
9bb6558a
PM
9873 /* ISS not valid if writeback */
9874 issinfo = (pbit & !wbit) ? rd : ISSInvalid;
9875
3960c336
PM
9876 if (!load && (sh & 2)) {
9877 /* doubleword */
9878 ARCH(5TE);
9879 if (rd & 1) {
9880 /* UNPREDICTABLE; we choose to UNDEF */
9881 goto illegal_op;
9882 }
9883 load = (sh & 1) == 0;
9884 doubleword = true;
9885 }
9886
b0109805 9887 addr = load_reg(s, rn);
63f26fcf 9888 if (pbit) {
b0109805 9889 gen_add_datah_offset(s, insn, 0, addr);
63f26fcf 9890 }
9ee6e8bb 9891 address_offset = 0;
3960c336
PM
9892
9893 if (doubleword) {
9894 if (!load) {
9ee6e8bb 9895 /* store */
b0109805 9896 tmp = load_reg(s, rd);
12dcc321 9897 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 9898 tcg_temp_free_i32(tmp);
b0109805
PB
9899 tcg_gen_addi_i32(addr, addr, 4);
9900 tmp = load_reg(s, rd + 1);
12dcc321 9901 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 9902 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
9903 } else {
9904 /* load */
5a839c0d 9905 tmp = tcg_temp_new_i32();
12dcc321 9906 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805
PB
9907 store_reg(s, rd, tmp);
9908 tcg_gen_addi_i32(addr, addr, 4);
5a839c0d 9909 tmp = tcg_temp_new_i32();
12dcc321 9910 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9ee6e8bb 9911 rd++;
9ee6e8bb
PB
9912 }
9913 address_offset = -4;
3960c336
PM
9914 } else if (load) {
9915 /* load */
9916 tmp = tcg_temp_new_i32();
9917 switch (sh) {
9918 case 1:
9bb6558a
PM
9919 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s),
9920 issinfo);
3960c336
PM
9921 break;
9922 case 2:
9bb6558a
PM
9923 gen_aa32_ld8s_iss(s, tmp, addr, get_mem_index(s),
9924 issinfo);
3960c336
PM
9925 break;
9926 default:
9927 case 3:
9bb6558a
PM
9928 gen_aa32_ld16s_iss(s, tmp, addr, get_mem_index(s),
9929 issinfo);
3960c336
PM
9930 break;
9931 }
9ee6e8bb
PB
9932 } else {
9933 /* store */
b0109805 9934 tmp = load_reg(s, rd);
9bb6558a 9935 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), issinfo);
5a839c0d 9936 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
9937 }
9938 /* Perform base writeback before the loaded value to
9939 ensure correct behavior with overlapping index registers.
b6af0975 9940 ldrd with base writeback is undefined if the
9ee6e8bb 9941 destination and index registers overlap. */
63f26fcf 9942 if (!pbit) {
b0109805
PB
9943 gen_add_datah_offset(s, insn, address_offset, addr);
9944 store_reg(s, rn, addr);
63f26fcf 9945 } else if (wbit) {
9ee6e8bb 9946 if (address_offset)
b0109805
PB
9947 tcg_gen_addi_i32(addr, addr, address_offset);
9948 store_reg(s, rn, addr);
9949 } else {
7d1b0095 9950 tcg_temp_free_i32(addr);
9ee6e8bb
PB
9951 }
9952 if (load) {
9953 /* Complete the load. */
b0109805 9954 store_reg(s, rd, tmp);
9ee6e8bb
PB
9955 }
9956 }
9957 break;
9958 case 0x4:
9959 case 0x5:
9960 goto do_ldst;
9961 case 0x6:
9962 case 0x7:
9963 if (insn & (1 << 4)) {
9964 ARCH(6);
9965 /* Armv6 Media instructions. */
9966 rm = insn & 0xf;
9967 rn = (insn >> 16) & 0xf;
2c0262af 9968 rd = (insn >> 12) & 0xf;
9ee6e8bb
PB
9969 rs = (insn >> 8) & 0xf;
9970 switch ((insn >> 23) & 3) {
9971 case 0: /* Parallel add/subtract. */
9972 op1 = (insn >> 20) & 7;
6ddbc6e4
PB
9973 tmp = load_reg(s, rn);
9974 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
9975 sh = (insn >> 5) & 7;
9976 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
9977 goto illegal_op;
6ddbc6e4 9978 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
7d1b0095 9979 tcg_temp_free_i32(tmp2);
6ddbc6e4 9980 store_reg(s, rd, tmp);
9ee6e8bb
PB
9981 break;
9982 case 1:
9983 if ((insn & 0x00700020) == 0) {
6c95676b 9984 /* Halfword pack. */
3670669c
PB
9985 tmp = load_reg(s, rn);
9986 tmp2 = load_reg(s, rm);
9ee6e8bb 9987 shift = (insn >> 7) & 0x1f;
3670669c
PB
9988 if (insn & (1 << 6)) {
9989 /* pkhtb */
22478e79
AZ
9990 if (shift == 0)
9991 shift = 31;
9992 tcg_gen_sari_i32(tmp2, tmp2, shift);
3670669c 9993 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
86831435 9994 tcg_gen_ext16u_i32(tmp2, tmp2);
3670669c
PB
9995 } else {
9996 /* pkhbt */
22478e79
AZ
9997 if (shift)
9998 tcg_gen_shli_i32(tmp2, tmp2, shift);
86831435 9999 tcg_gen_ext16u_i32(tmp, tmp);
3670669c
PB
10000 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
10001 }
10002 tcg_gen_or_i32(tmp, tmp, tmp2);
7d1b0095 10003 tcg_temp_free_i32(tmp2);
3670669c 10004 store_reg(s, rd, tmp);
9ee6e8bb
PB
10005 } else if ((insn & 0x00200020) == 0x00200000) {
10006 /* [us]sat */
6ddbc6e4 10007 tmp = load_reg(s, rm);
9ee6e8bb
PB
10008 shift = (insn >> 7) & 0x1f;
10009 if (insn & (1 << 6)) {
10010 if (shift == 0)
10011 shift = 31;
6ddbc6e4 10012 tcg_gen_sari_i32(tmp, tmp, shift);
9ee6e8bb 10013 } else {
6ddbc6e4 10014 tcg_gen_shli_i32(tmp, tmp, shift);
9ee6e8bb
PB
10015 }
10016 sh = (insn >> 16) & 0x1f;
40d3c433
CL
10017 tmp2 = tcg_const_i32(sh);
10018 if (insn & (1 << 22))
9ef39277 10019 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
40d3c433 10020 else
9ef39277 10021 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
40d3c433 10022 tcg_temp_free_i32(tmp2);
6ddbc6e4 10023 store_reg(s, rd, tmp);
9ee6e8bb
PB
10024 } else if ((insn & 0x00300fe0) == 0x00200f20) {
10025 /* [us]sat16 */
6ddbc6e4 10026 tmp = load_reg(s, rm);
9ee6e8bb 10027 sh = (insn >> 16) & 0x1f;
40d3c433
CL
10028 tmp2 = tcg_const_i32(sh);
10029 if (insn & (1 << 22))
9ef39277 10030 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
40d3c433 10031 else
9ef39277 10032 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
40d3c433 10033 tcg_temp_free_i32(tmp2);
6ddbc6e4 10034 store_reg(s, rd, tmp);
9ee6e8bb
PB
10035 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
10036 /* Select bytes. */
6ddbc6e4
PB
10037 tmp = load_reg(s, rn);
10038 tmp2 = load_reg(s, rm);
7d1b0095 10039 tmp3 = tcg_temp_new_i32();
0ecb72a5 10040 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 10041 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7d1b0095
PM
10042 tcg_temp_free_i32(tmp3);
10043 tcg_temp_free_i32(tmp2);
6ddbc6e4 10044 store_reg(s, rd, tmp);
9ee6e8bb 10045 } else if ((insn & 0x000003e0) == 0x00000060) {
5e3f878a 10046 tmp = load_reg(s, rm);
9ee6e8bb 10047 shift = (insn >> 10) & 3;
1301f322 10048 /* ??? In many cases it's not necessary to do a
9ee6e8bb
PB
10049 rotate, a shift is sufficient. */
10050 if (shift != 0)
f669df27 10051 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
9ee6e8bb
PB
10052 op1 = (insn >> 20) & 7;
10053 switch (op1) {
5e3f878a
PB
10054 case 0: gen_sxtb16(tmp); break;
10055 case 2: gen_sxtb(tmp); break;
10056 case 3: gen_sxth(tmp); break;
10057 case 4: gen_uxtb16(tmp); break;
10058 case 6: gen_uxtb(tmp); break;
10059 case 7: gen_uxth(tmp); break;
9ee6e8bb
PB
10060 default: goto illegal_op;
10061 }
10062 if (rn != 15) {
5e3f878a 10063 tmp2 = load_reg(s, rn);
9ee6e8bb 10064 if ((op1 & 3) == 0) {
5e3f878a 10065 gen_add16(tmp, tmp2);
9ee6e8bb 10066 } else {
5e3f878a 10067 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 10068 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
10069 }
10070 }
6c95676b 10071 store_reg(s, rd, tmp);
9ee6e8bb
PB
10072 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
10073 /* rev */
b0109805 10074 tmp = load_reg(s, rm);
9ee6e8bb
PB
10075 if (insn & (1 << 22)) {
10076 if (insn & (1 << 7)) {
b0109805 10077 gen_revsh(tmp);
9ee6e8bb
PB
10078 } else {
10079 ARCH(6T2);
b0109805 10080 gen_helper_rbit(tmp, tmp);
9ee6e8bb
PB
10081 }
10082 } else {
10083 if (insn & (1 << 7))
b0109805 10084 gen_rev16(tmp);
9ee6e8bb 10085 else
66896cb8 10086 tcg_gen_bswap32_i32(tmp, tmp);
9ee6e8bb 10087 }
b0109805 10088 store_reg(s, rd, tmp);
9ee6e8bb
PB
10089 } else {
10090 goto illegal_op;
10091 }
10092 break;
10093 case 2: /* Multiplies (Type 3). */
41e9564d
PM
10094 switch ((insn >> 20) & 0x7) {
10095 case 5:
10096 if (((insn >> 6) ^ (insn >> 7)) & 1) {
10097 /* op2 not 00x or 11x : UNDEF */
10098 goto illegal_op;
10099 }
838fa72d
AJ
10100 /* Signed multiply most significant [accumulate].
10101 (SMMUL, SMMLA, SMMLS) */
41e9564d
PM
10102 tmp = load_reg(s, rm);
10103 tmp2 = load_reg(s, rs);
a7812ae4 10104 tmp64 = gen_muls_i64_i32(tmp, tmp2);
838fa72d 10105
955a7dd5 10106 if (rd != 15) {
838fa72d 10107 tmp = load_reg(s, rd);
9ee6e8bb 10108 if (insn & (1 << 6)) {
838fa72d 10109 tmp64 = gen_subq_msw(tmp64, tmp);
9ee6e8bb 10110 } else {
838fa72d 10111 tmp64 = gen_addq_msw(tmp64, tmp);
9ee6e8bb
PB
10112 }
10113 }
838fa72d
AJ
10114 if (insn & (1 << 5)) {
10115 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
10116 }
10117 tcg_gen_shri_i64(tmp64, tmp64, 32);
7d1b0095 10118 tmp = tcg_temp_new_i32();
ecc7b3aa 10119 tcg_gen_extrl_i64_i32(tmp, tmp64);
838fa72d 10120 tcg_temp_free_i64(tmp64);
955a7dd5 10121 store_reg(s, rn, tmp);
41e9564d
PM
10122 break;
10123 case 0:
10124 case 4:
10125 /* SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD */
10126 if (insn & (1 << 7)) {
10127 goto illegal_op;
10128 }
10129 tmp = load_reg(s, rm);
10130 tmp2 = load_reg(s, rs);
9ee6e8bb 10131 if (insn & (1 << 5))
5e3f878a
PB
10132 gen_swap_half(tmp2);
10133 gen_smul_dual(tmp, tmp2);
9ee6e8bb 10134 if (insn & (1 << 22)) {
5e3f878a 10135 /* smlald, smlsld */
33bbd75a
PC
10136 TCGv_i64 tmp64_2;
10137
a7812ae4 10138 tmp64 = tcg_temp_new_i64();
33bbd75a 10139 tmp64_2 = tcg_temp_new_i64();
a7812ae4 10140 tcg_gen_ext_i32_i64(tmp64, tmp);
33bbd75a 10141 tcg_gen_ext_i32_i64(tmp64_2, tmp2);
7d1b0095 10142 tcg_temp_free_i32(tmp);
33bbd75a
PC
10143 tcg_temp_free_i32(tmp2);
10144 if (insn & (1 << 6)) {
10145 tcg_gen_sub_i64(tmp64, tmp64, tmp64_2);
10146 } else {
10147 tcg_gen_add_i64(tmp64, tmp64, tmp64_2);
10148 }
10149 tcg_temp_free_i64(tmp64_2);
a7812ae4
PB
10150 gen_addq(s, tmp64, rd, rn);
10151 gen_storeq_reg(s, rd, rn, tmp64);
b75263d6 10152 tcg_temp_free_i64(tmp64);
9ee6e8bb 10153 } else {
5e3f878a 10154 /* smuad, smusd, smlad, smlsd */
33bbd75a
PC
10155 if (insn & (1 << 6)) {
10156 /* This subtraction cannot overflow. */
10157 tcg_gen_sub_i32(tmp, tmp, tmp2);
10158 } else {
10159 /* This addition cannot overflow 32 bits;
10160 * however it may overflow considered as a
10161 * signed operation, in which case we must set
10162 * the Q flag.
10163 */
10164 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
10165 }
10166 tcg_temp_free_i32(tmp2);
22478e79 10167 if (rd != 15)
9ee6e8bb 10168 {
22478e79 10169 tmp2 = load_reg(s, rd);
9ef39277 10170 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 10171 tcg_temp_free_i32(tmp2);
9ee6e8bb 10172 }
22478e79 10173 store_reg(s, rn, tmp);
9ee6e8bb 10174 }
41e9564d 10175 break;
b8b8ea05
PM
10176 case 1:
10177 case 3:
10178 /* SDIV, UDIV */
7e0cf8b4 10179 if (!dc_isar_feature(arm_div, s)) {
b8b8ea05
PM
10180 goto illegal_op;
10181 }
10182 if (((insn >> 5) & 7) || (rd != 15)) {
10183 goto illegal_op;
10184 }
10185 tmp = load_reg(s, rm);
10186 tmp2 = load_reg(s, rs);
10187 if (insn & (1 << 21)) {
10188 gen_helper_udiv(tmp, tmp, tmp2);
10189 } else {
10190 gen_helper_sdiv(tmp, tmp, tmp2);
10191 }
10192 tcg_temp_free_i32(tmp2);
10193 store_reg(s, rn, tmp);
10194 break;
41e9564d
PM
10195 default:
10196 goto illegal_op;
9ee6e8bb
PB
10197 }
10198 break;
10199 case 3:
10200 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
10201 switch (op1) {
10202 case 0: /* Unsigned sum of absolute differences. */
6ddbc6e4
PB
10203 ARCH(6);
10204 tmp = load_reg(s, rm);
10205 tmp2 = load_reg(s, rs);
10206 gen_helper_usad8(tmp, tmp, tmp2);
7d1b0095 10207 tcg_temp_free_i32(tmp2);
ded9d295
AZ
10208 if (rd != 15) {
10209 tmp2 = load_reg(s, rd);
6ddbc6e4 10210 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 10211 tcg_temp_free_i32(tmp2);
9ee6e8bb 10212 }
ded9d295 10213 store_reg(s, rn, tmp);
9ee6e8bb
PB
10214 break;
10215 case 0x20: case 0x24: case 0x28: case 0x2c:
10216 /* Bitfield insert/clear. */
10217 ARCH(6T2);
10218 shift = (insn >> 7) & 0x1f;
10219 i = (insn >> 16) & 0x1f;
45140a57
KB
10220 if (i < shift) {
10221 /* UNPREDICTABLE; we choose to UNDEF */
10222 goto illegal_op;
10223 }
9ee6e8bb
PB
10224 i = i + 1 - shift;
10225 if (rm == 15) {
7d1b0095 10226 tmp = tcg_temp_new_i32();
5e3f878a 10227 tcg_gen_movi_i32(tmp, 0);
9ee6e8bb 10228 } else {
5e3f878a 10229 tmp = load_reg(s, rm);
9ee6e8bb
PB
10230 }
10231 if (i != 32) {
5e3f878a 10232 tmp2 = load_reg(s, rd);
d593c48e 10233 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, i);
7d1b0095 10234 tcg_temp_free_i32(tmp2);
9ee6e8bb 10235 }
5e3f878a 10236 store_reg(s, rd, tmp);
9ee6e8bb
PB
10237 break;
10238 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
10239 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
4cc633c3 10240 ARCH(6T2);
5e3f878a 10241 tmp = load_reg(s, rm);
9ee6e8bb
PB
10242 shift = (insn >> 7) & 0x1f;
10243 i = ((insn >> 16) & 0x1f) + 1;
10244 if (shift + i > 32)
10245 goto illegal_op;
10246 if (i < 32) {
10247 if (op1 & 0x20) {
59a71b4c 10248 tcg_gen_extract_i32(tmp, tmp, shift, i);
9ee6e8bb 10249 } else {
59a71b4c 10250 tcg_gen_sextract_i32(tmp, tmp, shift, i);
9ee6e8bb
PB
10251 }
10252 }
5e3f878a 10253 store_reg(s, rd, tmp);
9ee6e8bb
PB
10254 break;
10255 default:
10256 goto illegal_op;
10257 }
10258 break;
10259 }
10260 break;
10261 }
10262 do_ldst:
10263 /* Check for undefined extension instructions
10264 * per the ARM Bible IE:
10265 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
10266 */
10267 sh = (0xf << 20) | (0xf << 4);
10268 if (op1 == 0x7 && ((insn & sh) == sh))
10269 {
10270 goto illegal_op;
10271 }
10272 /* load/store byte/word */
10273 rn = (insn >> 16) & 0xf;
10274 rd = (insn >> 12) & 0xf;
b0109805 10275 tmp2 = load_reg(s, rn);
a99caa48
PM
10276 if ((insn & 0x01200000) == 0x00200000) {
10277 /* ldrt/strt */
579d21cc 10278 i = get_a32_user_mem_index(s);
a99caa48
PM
10279 } else {
10280 i = get_mem_index(s);
10281 }
9ee6e8bb 10282 if (insn & (1 << 24))
b0109805 10283 gen_add_data_offset(s, insn, tmp2);
9ee6e8bb
PB
10284 if (insn & (1 << 20)) {
10285 /* load */
5a839c0d 10286 tmp = tcg_temp_new_i32();
9ee6e8bb 10287 if (insn & (1 << 22)) {
9bb6558a 10288 gen_aa32_ld8u_iss(s, tmp, tmp2, i, rd);
9ee6e8bb 10289 } else {
9bb6558a 10290 gen_aa32_ld32u_iss(s, tmp, tmp2, i, rd);
9ee6e8bb 10291 }
9ee6e8bb
PB
10292 } else {
10293 /* store */
b0109805 10294 tmp = load_reg(s, rd);
5a839c0d 10295 if (insn & (1 << 22)) {
9bb6558a 10296 gen_aa32_st8_iss(s, tmp, tmp2, i, rd);
5a839c0d 10297 } else {
9bb6558a 10298 gen_aa32_st32_iss(s, tmp, tmp2, i, rd);
5a839c0d
PM
10299 }
10300 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
10301 }
10302 if (!(insn & (1 << 24))) {
b0109805
PB
10303 gen_add_data_offset(s, insn, tmp2);
10304 store_reg(s, rn, tmp2);
10305 } else if (insn & (1 << 21)) {
10306 store_reg(s, rn, tmp2);
10307 } else {
7d1b0095 10308 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
10309 }
10310 if (insn & (1 << 20)) {
10311 /* Complete the load. */
7dcc1f89 10312 store_reg_from_load(s, rd, tmp);
9ee6e8bb
PB
10313 }
10314 break;
10315 case 0x08:
10316 case 0x09:
10317 {
da3e53dd
PM
10318 int j, n, loaded_base;
10319 bool exc_return = false;
10320 bool is_load = extract32(insn, 20, 1);
10321 bool user = false;
39d5492a 10322 TCGv_i32 loaded_var;
9ee6e8bb
PB
10323 /* load/store multiple words */
10324 /* XXX: store correct base if write back */
9ee6e8bb 10325 if (insn & (1 << 22)) {
da3e53dd 10326 /* LDM (user), LDM (exception return) and STM (user) */
9ee6e8bb
PB
10327 if (IS_USER(s))
10328 goto illegal_op; /* only usable in supervisor mode */
10329
da3e53dd
PM
10330 if (is_load && extract32(insn, 15, 1)) {
10331 exc_return = true;
10332 } else {
10333 user = true;
10334 }
9ee6e8bb
PB
10335 }
10336 rn = (insn >> 16) & 0xf;
b0109805 10337 addr = load_reg(s, rn);
9ee6e8bb
PB
10338
10339 /* compute total size */
10340 loaded_base = 0;
f764718d 10341 loaded_var = NULL;
9ee6e8bb
PB
10342 n = 0;
10343 for(i=0;i<16;i++) {
10344 if (insn & (1 << i))
10345 n++;
10346 }
10347 /* XXX: test invalid n == 0 case ? */
10348 if (insn & (1 << 23)) {
10349 if (insn & (1 << 24)) {
10350 /* pre increment */
b0109805 10351 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb
PB
10352 } else {
10353 /* post increment */
10354 }
10355 } else {
10356 if (insn & (1 << 24)) {
10357 /* pre decrement */
b0109805 10358 tcg_gen_addi_i32(addr, addr, -(n * 4));
9ee6e8bb
PB
10359 } else {
10360 /* post decrement */
10361 if (n != 1)
b0109805 10362 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
9ee6e8bb
PB
10363 }
10364 }
10365 j = 0;
10366 for(i=0;i<16;i++) {
10367 if (insn & (1 << i)) {
da3e53dd 10368 if (is_load) {
9ee6e8bb 10369 /* load */
5a839c0d 10370 tmp = tcg_temp_new_i32();
12dcc321 10371 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
be5e7a76 10372 if (user) {
b75263d6 10373 tmp2 = tcg_const_i32(i);
1ce94f81 10374 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
b75263d6 10375 tcg_temp_free_i32(tmp2);
7d1b0095 10376 tcg_temp_free_i32(tmp);
9ee6e8bb 10377 } else if (i == rn) {
b0109805 10378 loaded_var = tmp;
9ee6e8bb 10379 loaded_base = 1;
fb0e8e79
PM
10380 } else if (rn == 15 && exc_return) {
10381 store_pc_exc_ret(s, tmp);
9ee6e8bb 10382 } else {
7dcc1f89 10383 store_reg_from_load(s, i, tmp);
9ee6e8bb
PB
10384 }
10385 } else {
10386 /* store */
10387 if (i == 15) {
10388 /* special case: r15 = PC + 8 */
10389 val = (long)s->pc + 4;
7d1b0095 10390 tmp = tcg_temp_new_i32();
b0109805 10391 tcg_gen_movi_i32(tmp, val);
9ee6e8bb 10392 } else if (user) {
7d1b0095 10393 tmp = tcg_temp_new_i32();
b75263d6 10394 tmp2 = tcg_const_i32(i);
9ef39277 10395 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
b75263d6 10396 tcg_temp_free_i32(tmp2);
9ee6e8bb 10397 } else {
b0109805 10398 tmp = load_reg(s, i);
9ee6e8bb 10399 }
12dcc321 10400 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 10401 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
10402 }
10403 j++;
10404 /* no need to add after the last transfer */
10405 if (j != n)
b0109805 10406 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb
PB
10407 }
10408 }
10409 if (insn & (1 << 21)) {
10410 /* write back */
10411 if (insn & (1 << 23)) {
10412 if (insn & (1 << 24)) {
10413 /* pre increment */
10414 } else {
10415 /* post increment */
b0109805 10416 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb
PB
10417 }
10418 } else {
10419 if (insn & (1 << 24)) {
10420 /* pre decrement */
10421 if (n != 1)
b0109805 10422 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
9ee6e8bb
PB
10423 } else {
10424 /* post decrement */
b0109805 10425 tcg_gen_addi_i32(addr, addr, -(n * 4));
9ee6e8bb
PB
10426 }
10427 }
b0109805
PB
10428 store_reg(s, rn, addr);
10429 } else {
7d1b0095 10430 tcg_temp_free_i32(addr);
9ee6e8bb
PB
10431 }
10432 if (loaded_base) {
b0109805 10433 store_reg(s, rn, loaded_var);
9ee6e8bb 10434 }
da3e53dd 10435 if (exc_return) {
9ee6e8bb 10436 /* Restore CPSR from SPSR. */
d9ba4830 10437 tmp = load_cpu_field(spsr);
e69ad9df
AL
10438 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
10439 gen_io_start();
10440 }
235ea1f5 10441 gen_helper_cpsr_write_eret(cpu_env, tmp);
e69ad9df
AL
10442 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
10443 gen_io_end();
10444 }
7d1b0095 10445 tcg_temp_free_i32(tmp);
b29fd33d 10446 /* Must exit loop to check un-masked IRQs */
dcba3a8d 10447 s->base.is_jmp = DISAS_EXIT;
9ee6e8bb
PB
10448 }
10449 }
10450 break;
10451 case 0xa:
10452 case 0xb:
10453 {
10454 int32_t offset;
10455
10456 /* branch (and link) */
10457 val = (int32_t)s->pc;
10458 if (insn & (1 << 24)) {
7d1b0095 10459 tmp = tcg_temp_new_i32();
5e3f878a
PB
10460 tcg_gen_movi_i32(tmp, val);
10461 store_reg(s, 14, tmp);
9ee6e8bb 10462 }
534df156
PM
10463 offset = sextract32(insn << 2, 0, 26);
10464 val += offset + 4;
9ee6e8bb
PB
10465 gen_jmp(s, val);
10466 }
10467 break;
10468 case 0xc:
10469 case 0xd:
10470 case 0xe:
6a57f3eb
WN
10471 if (((insn >> 8) & 0xe) == 10) {
10472 /* VFP. */
7dcc1f89 10473 if (disas_vfp_insn(s, insn)) {
6a57f3eb
WN
10474 goto illegal_op;
10475 }
7dcc1f89 10476 } else if (disas_coproc_insn(s, insn)) {
6a57f3eb 10477 /* Coprocessor. */
9ee6e8bb 10478 goto illegal_op;
6a57f3eb 10479 }
9ee6e8bb
PB
10480 break;
10481 case 0xf:
10482 /* swi */
eaed129d 10483 gen_set_pc_im(s, s->pc);
d4a2dc67 10484 s->svc_imm = extract32(insn, 0, 24);
dcba3a8d 10485 s->base.is_jmp = DISAS_SWI;
9ee6e8bb
PB
10486 break;
10487 default:
10488 illegal_op:
73710361
GB
10489 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
10490 default_exception_el(s));
9ee6e8bb
PB
10491 break;
10492 }
10493 }
10494}
10495
296e5a0a
PM
10496static bool thumb_insn_is_16bit(DisasContext *s, uint32_t insn)
10497{
10498 /* Return true if this is a 16 bit instruction. We must be precise
10499 * about this (matching the decode). We assume that s->pc still
10500 * points to the first 16 bits of the insn.
10501 */
10502 if ((insn >> 11) < 0x1d) {
10503 /* Definitely a 16-bit instruction */
10504 return true;
10505 }
10506
10507 /* Top five bits 0b11101 / 0b11110 / 0b11111 : this is the
10508 * first half of a 32-bit Thumb insn. Thumb-1 cores might
10509 * end up actually treating this as two 16-bit insns, though,
10510 * if it's half of a bl/blx pair that might span a page boundary.
10511 */
14120108
JS
10512 if (arm_dc_feature(s, ARM_FEATURE_THUMB2) ||
10513 arm_dc_feature(s, ARM_FEATURE_M)) {
296e5a0a
PM
10514 /* Thumb2 cores (including all M profile ones) always treat
10515 * 32-bit insns as 32-bit.
10516 */
10517 return false;
10518 }
10519
bfe7ad5b 10520 if ((insn >> 11) == 0x1e && s->pc - s->page_start < TARGET_PAGE_SIZE - 3) {
296e5a0a
PM
10521 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix, and the suffix
10522 * is not on the next page; we merge this into a 32-bit
10523 * insn.
10524 */
10525 return false;
10526 }
10527 /* 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF);
10528 * 0b1111_1xxx_xxxx_xxxx : BL suffix;
10529 * 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix on the end of a page
10530 * -- handle as single 16 bit insn
10531 */
10532 return true;
10533}
10534
9ee6e8bb
PB
10535/* Return true if this is a Thumb-2 logical op. */
10536static int
10537thumb2_logic_op(int op)
10538{
10539 return (op < 8);
10540}
10541
10542/* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
10543 then set condition code flags based on the result of the operation.
10544 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
10545 to the high bit of T1.
10546 Returns zero if the opcode is valid. */
10547
10548static int
39d5492a
PM
10549gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out,
10550 TCGv_i32 t0, TCGv_i32 t1)
9ee6e8bb
PB
10551{
10552 int logic_cc;
10553
10554 logic_cc = 0;
10555 switch (op) {
10556 case 0: /* and */
396e467c 10557 tcg_gen_and_i32(t0, t0, t1);
9ee6e8bb
PB
10558 logic_cc = conds;
10559 break;
10560 case 1: /* bic */
f669df27 10561 tcg_gen_andc_i32(t0, t0, t1);
9ee6e8bb
PB
10562 logic_cc = conds;
10563 break;
10564 case 2: /* orr */
396e467c 10565 tcg_gen_or_i32(t0, t0, t1);
9ee6e8bb
PB
10566 logic_cc = conds;
10567 break;
10568 case 3: /* orn */
29501f1b 10569 tcg_gen_orc_i32(t0, t0, t1);
9ee6e8bb
PB
10570 logic_cc = conds;
10571 break;
10572 case 4: /* eor */
396e467c 10573 tcg_gen_xor_i32(t0, t0, t1);
9ee6e8bb
PB
10574 logic_cc = conds;
10575 break;
10576 case 8: /* add */
10577 if (conds)
72485ec4 10578 gen_add_CC(t0, t0, t1);
9ee6e8bb 10579 else
396e467c 10580 tcg_gen_add_i32(t0, t0, t1);
9ee6e8bb
PB
10581 break;
10582 case 10: /* adc */
10583 if (conds)
49b4c31e 10584 gen_adc_CC(t0, t0, t1);
9ee6e8bb 10585 else
396e467c 10586 gen_adc(t0, t1);
9ee6e8bb
PB
10587 break;
10588 case 11: /* sbc */
2de68a49
RH
10589 if (conds) {
10590 gen_sbc_CC(t0, t0, t1);
10591 } else {
396e467c 10592 gen_sub_carry(t0, t0, t1);
2de68a49 10593 }
9ee6e8bb
PB
10594 break;
10595 case 13: /* sub */
10596 if (conds)
72485ec4 10597 gen_sub_CC(t0, t0, t1);
9ee6e8bb 10598 else
396e467c 10599 tcg_gen_sub_i32(t0, t0, t1);
9ee6e8bb
PB
10600 break;
10601 case 14: /* rsb */
10602 if (conds)
72485ec4 10603 gen_sub_CC(t0, t1, t0);
9ee6e8bb 10604 else
396e467c 10605 tcg_gen_sub_i32(t0, t1, t0);
9ee6e8bb
PB
10606 break;
10607 default: /* 5, 6, 7, 9, 12, 15. */
10608 return 1;
10609 }
10610 if (logic_cc) {
396e467c 10611 gen_logic_CC(t0);
9ee6e8bb 10612 if (shifter_out)
396e467c 10613 gen_set_CF_bit31(t1);
9ee6e8bb
PB
10614 }
10615 return 0;
10616}
10617
2eea841c
PM
10618/* Translate a 32-bit thumb instruction. */
10619static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
9ee6e8bb 10620{
296e5a0a 10621 uint32_t imm, shift, offset;
9ee6e8bb 10622 uint32_t rd, rn, rm, rs;
39d5492a
PM
10623 TCGv_i32 tmp;
10624 TCGv_i32 tmp2;
10625 TCGv_i32 tmp3;
10626 TCGv_i32 addr;
a7812ae4 10627 TCGv_i64 tmp64;
9ee6e8bb
PB
10628 int op;
10629 int shiftop;
10630 int conds;
10631 int logic_cc;
10632
14120108
JS
10633 /*
10634 * ARMv6-M supports a limited subset of Thumb2 instructions.
10635 * Other Thumb1 architectures allow only 32-bit
10636 * combined BL/BLX prefix and suffix.
296e5a0a 10637 */
14120108
JS
10638 if (arm_dc_feature(s, ARM_FEATURE_M) &&
10639 !arm_dc_feature(s, ARM_FEATURE_V7)) {
10640 int i;
10641 bool found = false;
8297cb13
JS
10642 static const uint32_t armv6m_insn[] = {0xf3808000 /* msr */,
10643 0xf3b08040 /* dsb */,
10644 0xf3b08050 /* dmb */,
10645 0xf3b08060 /* isb */,
10646 0xf3e08000 /* mrs */,
10647 0xf000d000 /* bl */};
10648 static const uint32_t armv6m_mask[] = {0xffe0d000,
10649 0xfff0d0f0,
10650 0xfff0d0f0,
10651 0xfff0d0f0,
10652 0xffe0d000,
10653 0xf800d000};
14120108
JS
10654
10655 for (i = 0; i < ARRAY_SIZE(armv6m_insn); i++) {
10656 if ((insn & armv6m_mask[i]) == armv6m_insn[i]) {
10657 found = true;
10658 break;
10659 }
10660 }
10661 if (!found) {
10662 goto illegal_op;
10663 }
10664 } else if ((insn & 0xf800e800) != 0xf000e800) {
9ee6e8bb
PB
10665 ARCH(6T2);
10666 }
10667
10668 rn = (insn >> 16) & 0xf;
10669 rs = (insn >> 12) & 0xf;
10670 rd = (insn >> 8) & 0xf;
10671 rm = insn & 0xf;
10672 switch ((insn >> 25) & 0xf) {
10673 case 0: case 1: case 2: case 3:
10674 /* 16-bit instructions. Should never happen. */
10675 abort();
10676 case 4:
10677 if (insn & (1 << 22)) {
ebfe27c5
PM
10678 /* 0b1110_100x_x1xx_xxxx_xxxx_xxxx_xxxx_xxxx
10679 * - load/store doubleword, load/store exclusive, ldacq/strel,
5158de24 10680 * table branch, TT.
ebfe27c5 10681 */
76eff04d
PM
10682 if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_M) &&
10683 arm_dc_feature(s, ARM_FEATURE_V8)) {
10684 /* 0b1110_1001_0111_1111_1110_1001_0111_111
10685 * - SG (v8M only)
10686 * The bulk of the behaviour for this instruction is implemented
10687 * in v7m_handle_execute_nsc(), which deals with the insn when
10688 * it is executed by a CPU in non-secure state from memory
10689 * which is Secure & NonSecure-Callable.
10690 * Here we only need to handle the remaining cases:
10691 * * in NS memory (including the "security extension not
10692 * implemented" case) : NOP
10693 * * in S memory but CPU already secure (clear IT bits)
10694 * We know that the attribute for the memory this insn is
10695 * in must match the current CPU state, because otherwise
10696 * get_phys_addr_pmsav8 would have generated an exception.
10697 */
10698 if (s->v8m_secure) {
10699 /* Like the IT insn, we don't need to generate any code */
10700 s->condexec_cond = 0;
10701 s->condexec_mask = 0;
10702 }
10703 } else if (insn & 0x01200000) {
ebfe27c5
PM
10704 /* 0b1110_1000_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
10705 * - load/store dual (post-indexed)
10706 * 0b1111_1001_x10x_xxxx_xxxx_xxxx_xxxx_xxxx
10707 * - load/store dual (literal and immediate)
10708 * 0b1111_1001_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
10709 * - load/store dual (pre-indexed)
10710 */
910d7692
PM
10711 bool wback = extract32(insn, 21, 1);
10712
9ee6e8bb 10713 if (rn == 15) {
ebfe27c5
PM
10714 if (insn & (1 << 21)) {
10715 /* UNPREDICTABLE */
10716 goto illegal_op;
10717 }
7d1b0095 10718 addr = tcg_temp_new_i32();
b0109805 10719 tcg_gen_movi_i32(addr, s->pc & ~3);
9ee6e8bb 10720 } else {
b0109805 10721 addr = load_reg(s, rn);
9ee6e8bb
PB
10722 }
10723 offset = (insn & 0xff) * 4;
910d7692 10724 if ((insn & (1 << 23)) == 0) {
9ee6e8bb 10725 offset = -offset;
910d7692
PM
10726 }
10727
10728 if (s->v8m_stackcheck && rn == 13 && wback) {
10729 /*
10730 * Here 'addr' is the current SP; if offset is +ve we're
10731 * moving SP up, else down. It is UNKNOWN whether the limit
10732 * check triggers when SP starts below the limit and ends
10733 * up above it; check whichever of the current and final
10734 * SP is lower, so QEMU will trigger in that situation.
10735 */
10736 if ((int32_t)offset < 0) {
10737 TCGv_i32 newsp = tcg_temp_new_i32();
10738
10739 tcg_gen_addi_i32(newsp, addr, offset);
10740 gen_helper_v8m_stackcheck(cpu_env, newsp);
10741 tcg_temp_free_i32(newsp);
10742 } else {
10743 gen_helper_v8m_stackcheck(cpu_env, addr);
10744 }
10745 }
10746
9ee6e8bb 10747 if (insn & (1 << 24)) {
b0109805 10748 tcg_gen_addi_i32(addr, addr, offset);
9ee6e8bb
PB
10749 offset = 0;
10750 }
10751 if (insn & (1 << 20)) {
10752 /* ldrd */
e2592fad 10753 tmp = tcg_temp_new_i32();
12dcc321 10754 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805
PB
10755 store_reg(s, rs, tmp);
10756 tcg_gen_addi_i32(addr, addr, 4);
e2592fad 10757 tmp = tcg_temp_new_i32();
12dcc321 10758 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 10759 store_reg(s, rd, tmp);
9ee6e8bb
PB
10760 } else {
10761 /* strd */
b0109805 10762 tmp = load_reg(s, rs);
12dcc321 10763 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
e2592fad 10764 tcg_temp_free_i32(tmp);
b0109805
PB
10765 tcg_gen_addi_i32(addr, addr, 4);
10766 tmp = load_reg(s, rd);
12dcc321 10767 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
e2592fad 10768 tcg_temp_free_i32(tmp);
9ee6e8bb 10769 }
910d7692 10770 if (wback) {
9ee6e8bb 10771 /* Base writeback. */
b0109805
PB
10772 tcg_gen_addi_i32(addr, addr, offset - 4);
10773 store_reg(s, rn, addr);
10774 } else {
7d1b0095 10775 tcg_temp_free_i32(addr);
9ee6e8bb
PB
10776 }
10777 } else if ((insn & (1 << 23)) == 0) {
ebfe27c5
PM
10778 /* 0b1110_1000_010x_xxxx_xxxx_xxxx_xxxx_xxxx
10779 * - load/store exclusive word
5158de24 10780 * - TT (v8M only)
ebfe27c5
PM
10781 */
10782 if (rs == 15) {
5158de24
PM
10783 if (!(insn & (1 << 20)) &&
10784 arm_dc_feature(s, ARM_FEATURE_M) &&
10785 arm_dc_feature(s, ARM_FEATURE_V8)) {
10786 /* 0b1110_1000_0100_xxxx_1111_xxxx_xxxx_xxxx
10787 * - TT (v8M only)
10788 */
10789 bool alt = insn & (1 << 7);
10790 TCGv_i32 addr, op, ttresp;
10791
10792 if ((insn & 0x3f) || rd == 13 || rd == 15 || rn == 15) {
10793 /* we UNDEF for these UNPREDICTABLE cases */
10794 goto illegal_op;
10795 }
10796
10797 if (alt && !s->v8m_secure) {
10798 goto illegal_op;
10799 }
10800
10801 addr = load_reg(s, rn);
10802 op = tcg_const_i32(extract32(insn, 6, 2));
10803 ttresp = tcg_temp_new_i32();
10804 gen_helper_v7m_tt(ttresp, cpu_env, addr, op);
10805 tcg_temp_free_i32(addr);
10806 tcg_temp_free_i32(op);
10807 store_reg(s, rd, ttresp);
384c6c03 10808 break;
5158de24 10809 }
ebfe27c5
PM
10810 goto illegal_op;
10811 }
39d5492a 10812 addr = tcg_temp_local_new_i32();
98a46317 10813 load_reg_var(s, addr, rn);
426f5abc 10814 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
2c0262af 10815 if (insn & (1 << 20)) {
426f5abc 10816 gen_load_exclusive(s, rs, 15, addr, 2);
9ee6e8bb 10817 } else {
426f5abc 10818 gen_store_exclusive(s, rd, rs, 15, addr, 2);
9ee6e8bb 10819 }
39d5492a 10820 tcg_temp_free_i32(addr);
2359bf80 10821 } else if ((insn & (7 << 5)) == 0) {
9ee6e8bb
PB
10822 /* Table Branch. */
10823 if (rn == 15) {
7d1b0095 10824 addr = tcg_temp_new_i32();
b0109805 10825 tcg_gen_movi_i32(addr, s->pc);
9ee6e8bb 10826 } else {
b0109805 10827 addr = load_reg(s, rn);
9ee6e8bb 10828 }
b26eefb6 10829 tmp = load_reg(s, rm);
b0109805 10830 tcg_gen_add_i32(addr, addr, tmp);
9ee6e8bb
PB
10831 if (insn & (1 << 4)) {
10832 /* tbh */
b0109805 10833 tcg_gen_add_i32(addr, addr, tmp);
7d1b0095 10834 tcg_temp_free_i32(tmp);
e2592fad 10835 tmp = tcg_temp_new_i32();
12dcc321 10836 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
9ee6e8bb 10837 } else { /* tbb */
7d1b0095 10838 tcg_temp_free_i32(tmp);
e2592fad 10839 tmp = tcg_temp_new_i32();
12dcc321 10840 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
9ee6e8bb 10841 }
7d1b0095 10842 tcg_temp_free_i32(addr);
b0109805
PB
10843 tcg_gen_shli_i32(tmp, tmp, 1);
10844 tcg_gen_addi_i32(tmp, tmp, s->pc);
10845 store_reg(s, 15, tmp);
9ee6e8bb 10846 } else {
2359bf80 10847 int op2 = (insn >> 6) & 0x3;
9ee6e8bb 10848 op = (insn >> 4) & 0x3;
2359bf80
MR
10849 switch (op2) {
10850 case 0:
426f5abc 10851 goto illegal_op;
2359bf80
MR
10852 case 1:
10853 /* Load/store exclusive byte/halfword/doubleword */
10854 if (op == 2) {
10855 goto illegal_op;
10856 }
10857 ARCH(7);
10858 break;
10859 case 2:
10860 /* Load-acquire/store-release */
10861 if (op == 3) {
10862 goto illegal_op;
10863 }
10864 /* Fall through */
10865 case 3:
10866 /* Load-acquire/store-release exclusive */
10867 ARCH(8);
10868 break;
426f5abc 10869 }
39d5492a 10870 addr = tcg_temp_local_new_i32();
98a46317 10871 load_reg_var(s, addr, rn);
2359bf80
MR
10872 if (!(op2 & 1)) {
10873 if (insn & (1 << 20)) {
10874 tmp = tcg_temp_new_i32();
10875 switch (op) {
10876 case 0: /* ldab */
9bb6558a
PM
10877 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s),
10878 rs | ISSIsAcqRel);
2359bf80
MR
10879 break;
10880 case 1: /* ldah */
9bb6558a
PM
10881 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s),
10882 rs | ISSIsAcqRel);
2359bf80
MR
10883 break;
10884 case 2: /* lda */
9bb6558a
PM
10885 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s),
10886 rs | ISSIsAcqRel);
2359bf80
MR
10887 break;
10888 default:
10889 abort();
10890 }
10891 store_reg(s, rs, tmp);
10892 } else {
10893 tmp = load_reg(s, rs);
10894 switch (op) {
10895 case 0: /* stlb */
9bb6558a
PM
10896 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s),
10897 rs | ISSIsAcqRel);
2359bf80
MR
10898 break;
10899 case 1: /* stlh */
9bb6558a
PM
10900 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s),
10901 rs | ISSIsAcqRel);
2359bf80
MR
10902 break;
10903 case 2: /* stl */
9bb6558a
PM
10904 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s),
10905 rs | ISSIsAcqRel);
2359bf80
MR
10906 break;
10907 default:
10908 abort();
10909 }
10910 tcg_temp_free_i32(tmp);
10911 }
10912 } else if (insn & (1 << 20)) {
426f5abc 10913 gen_load_exclusive(s, rs, rd, addr, op);
9ee6e8bb 10914 } else {
426f5abc 10915 gen_store_exclusive(s, rm, rs, rd, addr, op);
9ee6e8bb 10916 }
39d5492a 10917 tcg_temp_free_i32(addr);
9ee6e8bb
PB
10918 }
10919 } else {
10920 /* Load/store multiple, RFE, SRS. */
10921 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
00115976 10922 /* RFE, SRS: not available in user mode or on M profile */
b53d8923 10923 if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
9ee6e8bb 10924 goto illegal_op;
00115976 10925 }
9ee6e8bb
PB
10926 if (insn & (1 << 20)) {
10927 /* rfe */
b0109805
PB
10928 addr = load_reg(s, rn);
10929 if ((insn & (1 << 24)) == 0)
10930 tcg_gen_addi_i32(addr, addr, -8);
10931 /* Load PC into tmp and CPSR into tmp2. */
e2592fad 10932 tmp = tcg_temp_new_i32();
12dcc321 10933 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 10934 tcg_gen_addi_i32(addr, addr, 4);
e2592fad 10935 tmp2 = tcg_temp_new_i32();
12dcc321 10936 gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
9ee6e8bb
PB
10937 if (insn & (1 << 21)) {
10938 /* Base writeback. */
b0109805
PB
10939 if (insn & (1 << 24)) {
10940 tcg_gen_addi_i32(addr, addr, 4);
10941 } else {
10942 tcg_gen_addi_i32(addr, addr, -4);
10943 }
10944 store_reg(s, rn, addr);
10945 } else {
7d1b0095 10946 tcg_temp_free_i32(addr);
9ee6e8bb 10947 }
b0109805 10948 gen_rfe(s, tmp, tmp2);
9ee6e8bb
PB
10949 } else {
10950 /* srs */
81465888
PM
10951 gen_srs(s, (insn & 0x1f), (insn & (1 << 24)) ? 1 : 2,
10952 insn & (1 << 21));
9ee6e8bb
PB
10953 }
10954 } else {
5856d44e 10955 int i, loaded_base = 0;
39d5492a 10956 TCGv_i32 loaded_var;
7c0ed88e 10957 bool wback = extract32(insn, 21, 1);
9ee6e8bb 10958 /* Load/store multiple. */
b0109805 10959 addr = load_reg(s, rn);
9ee6e8bb
PB
10960 offset = 0;
10961 for (i = 0; i < 16; i++) {
10962 if (insn & (1 << i))
10963 offset += 4;
10964 }
7c0ed88e 10965
9ee6e8bb 10966 if (insn & (1 << 24)) {
b0109805 10967 tcg_gen_addi_i32(addr, addr, -offset);
9ee6e8bb
PB
10968 }
10969
7c0ed88e
PM
10970 if (s->v8m_stackcheck && rn == 13 && wback) {
10971 /*
10972 * If the writeback is incrementing SP rather than
10973 * decrementing it, and the initial SP is below the
10974 * stack limit but the final written-back SP would
10975 * be above, then then we must not perform any memory
10976 * accesses, but it is IMPDEF whether we generate
10977 * an exception. We choose to do so in this case.
10978 * At this point 'addr' is the lowest address, so
10979 * either the original SP (if incrementing) or our
10980 * final SP (if decrementing), so that's what we check.
10981 */
10982 gen_helper_v8m_stackcheck(cpu_env, addr);
10983 }
10984
f764718d 10985 loaded_var = NULL;
9ee6e8bb
PB
10986 for (i = 0; i < 16; i++) {
10987 if ((insn & (1 << i)) == 0)
10988 continue;
10989 if (insn & (1 << 20)) {
10990 /* Load. */
e2592fad 10991 tmp = tcg_temp_new_i32();
12dcc321 10992 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9ee6e8bb 10993 if (i == 15) {
3bb8a96f 10994 gen_bx_excret(s, tmp);
5856d44e
YO
10995 } else if (i == rn) {
10996 loaded_var = tmp;
10997 loaded_base = 1;
9ee6e8bb 10998 } else {
b0109805 10999 store_reg(s, i, tmp);
9ee6e8bb
PB
11000 }
11001 } else {
11002 /* Store. */
b0109805 11003 tmp = load_reg(s, i);
12dcc321 11004 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
e2592fad 11005 tcg_temp_free_i32(tmp);
9ee6e8bb 11006 }
b0109805 11007 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb 11008 }
5856d44e
YO
11009 if (loaded_base) {
11010 store_reg(s, rn, loaded_var);
11011 }
7c0ed88e 11012 if (wback) {
9ee6e8bb
PB
11013 /* Base register writeback. */
11014 if (insn & (1 << 24)) {
b0109805 11015 tcg_gen_addi_i32(addr, addr, -offset);
9ee6e8bb
PB
11016 }
11017 /* Fault if writeback register is in register list. */
11018 if (insn & (1 << rn))
11019 goto illegal_op;
b0109805
PB
11020 store_reg(s, rn, addr);
11021 } else {
7d1b0095 11022 tcg_temp_free_i32(addr);
9ee6e8bb
PB
11023 }
11024 }
11025 }
11026 break;
2af9ab77
JB
11027 case 5:
11028
9ee6e8bb 11029 op = (insn >> 21) & 0xf;
2af9ab77 11030 if (op == 6) {
62b44f05
AR
11031 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11032 goto illegal_op;
11033 }
2af9ab77
JB
11034 /* Halfword pack. */
11035 tmp = load_reg(s, rn);
11036 tmp2 = load_reg(s, rm);
11037 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
11038 if (insn & (1 << 5)) {
11039 /* pkhtb */
11040 if (shift == 0)
11041 shift = 31;
11042 tcg_gen_sari_i32(tmp2, tmp2, shift);
11043 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
11044 tcg_gen_ext16u_i32(tmp2, tmp2);
11045 } else {
11046 /* pkhbt */
11047 if (shift)
11048 tcg_gen_shli_i32(tmp2, tmp2, shift);
11049 tcg_gen_ext16u_i32(tmp, tmp);
11050 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
11051 }
11052 tcg_gen_or_i32(tmp, tmp, tmp2);
7d1b0095 11053 tcg_temp_free_i32(tmp2);
3174f8e9
FN
11054 store_reg(s, rd, tmp);
11055 } else {
2af9ab77
JB
11056 /* Data processing register constant shift. */
11057 if (rn == 15) {
7d1b0095 11058 tmp = tcg_temp_new_i32();
2af9ab77
JB
11059 tcg_gen_movi_i32(tmp, 0);
11060 } else {
11061 tmp = load_reg(s, rn);
11062 }
11063 tmp2 = load_reg(s, rm);
11064
11065 shiftop = (insn >> 4) & 3;
11066 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
11067 conds = (insn & (1 << 20)) != 0;
11068 logic_cc = (conds && thumb2_logic_op(op));
11069 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
11070 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
11071 goto illegal_op;
7d1b0095 11072 tcg_temp_free_i32(tmp2);
55203189
PM
11073 if (rd == 13 &&
11074 ((op == 2 && rn == 15) ||
11075 (op == 8 && rn == 13) ||
11076 (op == 13 && rn == 13))) {
11077 /* MOV SP, ... or ADD SP, SP, ... or SUB SP, SP, ... */
11078 store_sp_checked(s, tmp);
11079 } else if (rd != 15) {
2af9ab77
JB
11080 store_reg(s, rd, tmp);
11081 } else {
7d1b0095 11082 tcg_temp_free_i32(tmp);
2af9ab77 11083 }
3174f8e9 11084 }
9ee6e8bb
PB
11085 break;
11086 case 13: /* Misc data processing. */
11087 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
11088 if (op < 4 && (insn & 0xf000) != 0xf000)
11089 goto illegal_op;
11090 switch (op) {
11091 case 0: /* Register controlled shift. */
8984bd2e
PB
11092 tmp = load_reg(s, rn);
11093 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
11094 if ((insn & 0x70) != 0)
11095 goto illegal_op;
a2d12f0f
PM
11096 /*
11097 * 0b1111_1010_0xxx_xxxx_1111_xxxx_0000_xxxx:
11098 * - MOV, MOVS (register-shifted register), flagsetting
11099 */
9ee6e8bb 11100 op = (insn >> 21) & 3;
8984bd2e
PB
11101 logic_cc = (insn & (1 << 20)) != 0;
11102 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
11103 if (logic_cc)
11104 gen_logic_CC(tmp);
bedb8a6b 11105 store_reg(s, rd, tmp);
9ee6e8bb
PB
11106 break;
11107 case 1: /* Sign/zero extend. */
62b44f05
AR
11108 op = (insn >> 20) & 7;
11109 switch (op) {
11110 case 0: /* SXTAH, SXTH */
11111 case 1: /* UXTAH, UXTH */
11112 case 4: /* SXTAB, SXTB */
11113 case 5: /* UXTAB, UXTB */
11114 break;
11115 case 2: /* SXTAB16, SXTB16 */
11116 case 3: /* UXTAB16, UXTB16 */
11117 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11118 goto illegal_op;
11119 }
11120 break;
11121 default:
11122 goto illegal_op;
11123 }
11124 if (rn != 15) {
11125 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11126 goto illegal_op;
11127 }
11128 }
5e3f878a 11129 tmp = load_reg(s, rm);
9ee6e8bb 11130 shift = (insn >> 4) & 3;
1301f322 11131 /* ??? In many cases it's not necessary to do a
9ee6e8bb
PB
11132 rotate, a shift is sufficient. */
11133 if (shift != 0)
f669df27 11134 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
9ee6e8bb
PB
11135 op = (insn >> 20) & 7;
11136 switch (op) {
5e3f878a
PB
11137 case 0: gen_sxth(tmp); break;
11138 case 1: gen_uxth(tmp); break;
11139 case 2: gen_sxtb16(tmp); break;
11140 case 3: gen_uxtb16(tmp); break;
11141 case 4: gen_sxtb(tmp); break;
11142 case 5: gen_uxtb(tmp); break;
62b44f05
AR
11143 default:
11144 g_assert_not_reached();
9ee6e8bb
PB
11145 }
11146 if (rn != 15) {
5e3f878a 11147 tmp2 = load_reg(s, rn);
9ee6e8bb 11148 if ((op >> 1) == 1) {
5e3f878a 11149 gen_add16(tmp, tmp2);
9ee6e8bb 11150 } else {
5e3f878a 11151 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 11152 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
11153 }
11154 }
5e3f878a 11155 store_reg(s, rd, tmp);
9ee6e8bb
PB
11156 break;
11157 case 2: /* SIMD add/subtract. */
62b44f05
AR
11158 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11159 goto illegal_op;
11160 }
9ee6e8bb
PB
11161 op = (insn >> 20) & 7;
11162 shift = (insn >> 4) & 7;
11163 if ((op & 3) == 3 || (shift & 3) == 3)
11164 goto illegal_op;
6ddbc6e4
PB
11165 tmp = load_reg(s, rn);
11166 tmp2 = load_reg(s, rm);
11167 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7d1b0095 11168 tcg_temp_free_i32(tmp2);
6ddbc6e4 11169 store_reg(s, rd, tmp);
9ee6e8bb
PB
11170 break;
11171 case 3: /* Other data processing. */
11172 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
11173 if (op < 4) {
11174 /* Saturating add/subtract. */
62b44f05
AR
11175 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11176 goto illegal_op;
11177 }
d9ba4830
PB
11178 tmp = load_reg(s, rn);
11179 tmp2 = load_reg(s, rm);
9ee6e8bb 11180 if (op & 1)
9ef39277 11181 gen_helper_double_saturate(tmp, cpu_env, tmp);
4809c612 11182 if (op & 2)
9ef39277 11183 gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);
9ee6e8bb 11184 else
9ef39277 11185 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
7d1b0095 11186 tcg_temp_free_i32(tmp2);
9ee6e8bb 11187 } else {
62b44f05
AR
11188 switch (op) {
11189 case 0x0a: /* rbit */
11190 case 0x08: /* rev */
11191 case 0x09: /* rev16 */
11192 case 0x0b: /* revsh */
11193 case 0x18: /* clz */
11194 break;
11195 case 0x10: /* sel */
11196 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11197 goto illegal_op;
11198 }
11199 break;
11200 case 0x20: /* crc32/crc32c */
11201 case 0x21:
11202 case 0x22:
11203 case 0x28:
11204 case 0x29:
11205 case 0x2a:
962fcbf2 11206 if (!dc_isar_feature(aa32_crc32, s)) {
62b44f05
AR
11207 goto illegal_op;
11208 }
11209 break;
11210 default:
11211 goto illegal_op;
11212 }
d9ba4830 11213 tmp = load_reg(s, rn);
9ee6e8bb
PB
11214 switch (op) {
11215 case 0x0a: /* rbit */
d9ba4830 11216 gen_helper_rbit(tmp, tmp);
9ee6e8bb
PB
11217 break;
11218 case 0x08: /* rev */
66896cb8 11219 tcg_gen_bswap32_i32(tmp, tmp);
9ee6e8bb
PB
11220 break;
11221 case 0x09: /* rev16 */
d9ba4830 11222 gen_rev16(tmp);
9ee6e8bb
PB
11223 break;
11224 case 0x0b: /* revsh */
d9ba4830 11225 gen_revsh(tmp);
9ee6e8bb
PB
11226 break;
11227 case 0x10: /* sel */
d9ba4830 11228 tmp2 = load_reg(s, rm);
7d1b0095 11229 tmp3 = tcg_temp_new_i32();
0ecb72a5 11230 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
d9ba4830 11231 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7d1b0095
PM
11232 tcg_temp_free_i32(tmp3);
11233 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
11234 break;
11235 case 0x18: /* clz */
7539a012 11236 tcg_gen_clzi_i32(tmp, tmp, 32);
9ee6e8bb 11237 break;
eb0ecd5a
WN
11238 case 0x20:
11239 case 0x21:
11240 case 0x22:
11241 case 0x28:
11242 case 0x29:
11243 case 0x2a:
11244 {
11245 /* crc32/crc32c */
11246 uint32_t sz = op & 0x3;
11247 uint32_t c = op & 0x8;
11248
eb0ecd5a 11249 tmp2 = load_reg(s, rm);
aa633469
PM
11250 if (sz == 0) {
11251 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
11252 } else if (sz == 1) {
11253 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
11254 }
eb0ecd5a
WN
11255 tmp3 = tcg_const_i32(1 << sz);
11256 if (c) {
11257 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
11258 } else {
11259 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
11260 }
11261 tcg_temp_free_i32(tmp2);
11262 tcg_temp_free_i32(tmp3);
11263 break;
11264 }
9ee6e8bb 11265 default:
62b44f05 11266 g_assert_not_reached();
9ee6e8bb
PB
11267 }
11268 }
d9ba4830 11269 store_reg(s, rd, tmp);
9ee6e8bb
PB
11270 break;
11271 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
62b44f05
AR
11272 switch ((insn >> 20) & 7) {
11273 case 0: /* 32 x 32 -> 32 */
11274 case 7: /* Unsigned sum of absolute differences. */
11275 break;
11276 case 1: /* 16 x 16 -> 32 */
11277 case 2: /* Dual multiply add. */
11278 case 3: /* 32 * 16 -> 32msb */
11279 case 4: /* Dual multiply subtract. */
11280 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
11281 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11282 goto illegal_op;
11283 }
11284 break;
11285 }
9ee6e8bb 11286 op = (insn >> 4) & 0xf;
d9ba4830
PB
11287 tmp = load_reg(s, rn);
11288 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
11289 switch ((insn >> 20) & 7) {
11290 case 0: /* 32 x 32 -> 32 */
d9ba4830 11291 tcg_gen_mul_i32(tmp, tmp, tmp2);
7d1b0095 11292 tcg_temp_free_i32(tmp2);
9ee6e8bb 11293 if (rs != 15) {
d9ba4830 11294 tmp2 = load_reg(s, rs);
9ee6e8bb 11295 if (op)
d9ba4830 11296 tcg_gen_sub_i32(tmp, tmp2, tmp);
9ee6e8bb 11297 else
d9ba4830 11298 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 11299 tcg_temp_free_i32(tmp2);
9ee6e8bb 11300 }
9ee6e8bb
PB
11301 break;
11302 case 1: /* 16 x 16 -> 32 */
d9ba4830 11303 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7d1b0095 11304 tcg_temp_free_i32(tmp2);
9ee6e8bb 11305 if (rs != 15) {
d9ba4830 11306 tmp2 = load_reg(s, rs);
9ef39277 11307 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 11308 tcg_temp_free_i32(tmp2);
9ee6e8bb 11309 }
9ee6e8bb
PB
11310 break;
11311 case 2: /* Dual multiply add. */
11312 case 4: /* Dual multiply subtract. */
11313 if (op)
d9ba4830
PB
11314 gen_swap_half(tmp2);
11315 gen_smul_dual(tmp, tmp2);
9ee6e8bb 11316 if (insn & (1 << 22)) {
e1d177b9 11317 /* This subtraction cannot overflow. */
d9ba4830 11318 tcg_gen_sub_i32(tmp, tmp, tmp2);
9ee6e8bb 11319 } else {
e1d177b9
PM
11320 /* This addition cannot overflow 32 bits;
11321 * however it may overflow considered as a signed
11322 * operation, in which case we must set the Q flag.
11323 */
9ef39277 11324 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 11325 }
7d1b0095 11326 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
11327 if (rs != 15)
11328 {
d9ba4830 11329 tmp2 = load_reg(s, rs);
9ef39277 11330 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 11331 tcg_temp_free_i32(tmp2);
9ee6e8bb 11332 }
9ee6e8bb
PB
11333 break;
11334 case 3: /* 32 * 16 -> 32msb */
11335 if (op)
d9ba4830 11336 tcg_gen_sari_i32(tmp2, tmp2, 16);
9ee6e8bb 11337 else
d9ba4830 11338 gen_sxth(tmp2);
a7812ae4
PB
11339 tmp64 = gen_muls_i64_i32(tmp, tmp2);
11340 tcg_gen_shri_i64(tmp64, tmp64, 16);
7d1b0095 11341 tmp = tcg_temp_new_i32();
ecc7b3aa 11342 tcg_gen_extrl_i64_i32(tmp, tmp64);
b75263d6 11343 tcg_temp_free_i64(tmp64);
9ee6e8bb
PB
11344 if (rs != 15)
11345 {
d9ba4830 11346 tmp2 = load_reg(s, rs);
9ef39277 11347 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 11348 tcg_temp_free_i32(tmp2);
9ee6e8bb 11349 }
9ee6e8bb 11350 break;
838fa72d
AJ
11351 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
11352 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9ee6e8bb 11353 if (rs != 15) {
838fa72d
AJ
11354 tmp = load_reg(s, rs);
11355 if (insn & (1 << 20)) {
11356 tmp64 = gen_addq_msw(tmp64, tmp);
99c475ab 11357 } else {
838fa72d 11358 tmp64 = gen_subq_msw(tmp64, tmp);
99c475ab 11359 }
2c0262af 11360 }
838fa72d
AJ
11361 if (insn & (1 << 4)) {
11362 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
11363 }
11364 tcg_gen_shri_i64(tmp64, tmp64, 32);
7d1b0095 11365 tmp = tcg_temp_new_i32();
ecc7b3aa 11366 tcg_gen_extrl_i64_i32(tmp, tmp64);
838fa72d 11367 tcg_temp_free_i64(tmp64);
9ee6e8bb
PB
11368 break;
11369 case 7: /* Unsigned sum of absolute differences. */
d9ba4830 11370 gen_helper_usad8(tmp, tmp, tmp2);
7d1b0095 11371 tcg_temp_free_i32(tmp2);
9ee6e8bb 11372 if (rs != 15) {
d9ba4830
PB
11373 tmp2 = load_reg(s, rs);
11374 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 11375 tcg_temp_free_i32(tmp2);
5fd46862 11376 }
9ee6e8bb 11377 break;
2c0262af 11378 }
d9ba4830 11379 store_reg(s, rd, tmp);
2c0262af 11380 break;
9ee6e8bb
PB
11381 case 6: case 7: /* 64-bit multiply, Divide. */
11382 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
5e3f878a
PB
11383 tmp = load_reg(s, rn);
11384 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
11385 if ((op & 0x50) == 0x10) {
11386 /* sdiv, udiv */
7e0cf8b4 11387 if (!dc_isar_feature(thumb_div, s)) {
9ee6e8bb 11388 goto illegal_op;
47789990 11389 }
9ee6e8bb 11390 if (op & 0x20)
5e3f878a 11391 gen_helper_udiv(tmp, tmp, tmp2);
2c0262af 11392 else
5e3f878a 11393 gen_helper_sdiv(tmp, tmp, tmp2);
7d1b0095 11394 tcg_temp_free_i32(tmp2);
5e3f878a 11395 store_reg(s, rd, tmp);
9ee6e8bb
PB
11396 } else if ((op & 0xe) == 0xc) {
11397 /* Dual multiply accumulate long. */
62b44f05
AR
11398 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11399 tcg_temp_free_i32(tmp);
11400 tcg_temp_free_i32(tmp2);
11401 goto illegal_op;
11402 }
9ee6e8bb 11403 if (op & 1)
5e3f878a
PB
11404 gen_swap_half(tmp2);
11405 gen_smul_dual(tmp, tmp2);
9ee6e8bb 11406 if (op & 0x10) {
5e3f878a 11407 tcg_gen_sub_i32(tmp, tmp, tmp2);
b5ff1b31 11408 } else {
5e3f878a 11409 tcg_gen_add_i32(tmp, tmp, tmp2);
b5ff1b31 11410 }
7d1b0095 11411 tcg_temp_free_i32(tmp2);
a7812ae4
PB
11412 /* BUGFIX */
11413 tmp64 = tcg_temp_new_i64();
11414 tcg_gen_ext_i32_i64(tmp64, tmp);
7d1b0095 11415 tcg_temp_free_i32(tmp);
a7812ae4
PB
11416 gen_addq(s, tmp64, rs, rd);
11417 gen_storeq_reg(s, rs, rd, tmp64);
b75263d6 11418 tcg_temp_free_i64(tmp64);
2c0262af 11419 } else {
9ee6e8bb
PB
11420 if (op & 0x20) {
11421 /* Unsigned 64-bit multiply */
a7812ae4 11422 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
b5ff1b31 11423 } else {
9ee6e8bb
PB
11424 if (op & 8) {
11425 /* smlalxy */
62b44f05
AR
11426 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11427 tcg_temp_free_i32(tmp2);
11428 tcg_temp_free_i32(tmp);
11429 goto illegal_op;
11430 }
5e3f878a 11431 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7d1b0095 11432 tcg_temp_free_i32(tmp2);
a7812ae4
PB
11433 tmp64 = tcg_temp_new_i64();
11434 tcg_gen_ext_i32_i64(tmp64, tmp);
7d1b0095 11435 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
11436 } else {
11437 /* Signed 64-bit multiply */
a7812ae4 11438 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9ee6e8bb 11439 }
b5ff1b31 11440 }
9ee6e8bb
PB
11441 if (op & 4) {
11442 /* umaal */
62b44f05
AR
11443 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11444 tcg_temp_free_i64(tmp64);
11445 goto illegal_op;
11446 }
a7812ae4
PB
11447 gen_addq_lo(s, tmp64, rs);
11448 gen_addq_lo(s, tmp64, rd);
9ee6e8bb
PB
11449 } else if (op & 0x40) {
11450 /* 64-bit accumulate. */
a7812ae4 11451 gen_addq(s, tmp64, rs, rd);
9ee6e8bb 11452 }
a7812ae4 11453 gen_storeq_reg(s, rs, rd, tmp64);
b75263d6 11454 tcg_temp_free_i64(tmp64);
5fd46862 11455 }
2c0262af 11456 break;
9ee6e8bb
PB
11457 }
11458 break;
11459 case 6: case 7: case 14: case 15:
11460 /* Coprocessor. */
7517748e
PM
11461 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11462 /* We don't currently implement M profile FP support,
b1e5336a
PM
11463 * so this entire space should give a NOCP fault, with
11464 * the exception of the v8M VLLDM and VLSTM insns, which
11465 * must be NOPs in Secure state and UNDEF in Nonsecure state.
7517748e 11466 */
b1e5336a
PM
11467 if (arm_dc_feature(s, ARM_FEATURE_V8) &&
11468 (insn & 0xffa00f00) == 0xec200a00) {
11469 /* 0b1110_1100_0x1x_xxxx_xxxx_1010_xxxx_xxxx
11470 * - VLLDM, VLSTM
11471 * We choose to UNDEF if the RAZ bits are non-zero.
11472 */
11473 if (!s->v8m_secure || (insn & 0x0040f0ff)) {
11474 goto illegal_op;
11475 }
11476 /* Just NOP since FP support is not implemented */
11477 break;
11478 }
11479 /* All other insns: NOCP */
7517748e
PM
11480 gen_exception_insn(s, 4, EXCP_NOCP, syn_uncategorized(),
11481 default_exception_el(s));
11482 break;
11483 }
0052087e
RH
11484 if ((insn & 0xfe000a00) == 0xfc000800
11485 && arm_dc_feature(s, ARM_FEATURE_V8)) {
11486 /* The Thumb2 and ARM encodings are identical. */
11487 if (disas_neon_insn_3same_ext(s, insn)) {
11488 goto illegal_op;
11489 }
11490 } else if ((insn & 0xff000a00) == 0xfe000800
11491 && arm_dc_feature(s, ARM_FEATURE_V8)) {
11492 /* The Thumb2 and ARM encodings are identical. */
11493 if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
11494 goto illegal_op;
11495 }
11496 } else if (((insn >> 24) & 3) == 3) {
9ee6e8bb 11497 /* Translate into the equivalent ARM encoding. */
f06053e3 11498 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
7dcc1f89 11499 if (disas_neon_data_insn(s, insn)) {
9ee6e8bb 11500 goto illegal_op;
7dcc1f89 11501 }
6a57f3eb 11502 } else if (((insn >> 8) & 0xe) == 10) {
7dcc1f89 11503 if (disas_vfp_insn(s, insn)) {
6a57f3eb
WN
11504 goto illegal_op;
11505 }
9ee6e8bb
PB
11506 } else {
11507 if (insn & (1 << 28))
11508 goto illegal_op;
7dcc1f89 11509 if (disas_coproc_insn(s, insn)) {
9ee6e8bb 11510 goto illegal_op;
7dcc1f89 11511 }
9ee6e8bb
PB
11512 }
11513 break;
11514 case 8: case 9: case 10: case 11:
11515 if (insn & (1 << 15)) {
11516 /* Branches, misc control. */
11517 if (insn & 0x5000) {
11518 /* Unconditional branch. */
11519 /* signextend(hw1[10:0]) -> offset[:12]. */
11520 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
11521 /* hw1[10:0] -> offset[11:1]. */
11522 offset |= (insn & 0x7ff) << 1;
11523 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
11524 offset[24:22] already have the same value because of the
11525 sign extension above. */
11526 offset ^= ((~insn) & (1 << 13)) << 10;
11527 offset ^= ((~insn) & (1 << 11)) << 11;
11528
9ee6e8bb
PB
11529 if (insn & (1 << 14)) {
11530 /* Branch and link. */
3174f8e9 11531 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
b5ff1b31 11532 }
3b46e624 11533
b0109805 11534 offset += s->pc;
9ee6e8bb
PB
11535 if (insn & (1 << 12)) {
11536 /* b/bl */
b0109805 11537 gen_jmp(s, offset);
9ee6e8bb
PB
11538 } else {
11539 /* blx */
b0109805 11540 offset &= ~(uint32_t)2;
be5e7a76 11541 /* thumb2 bx, no need to check */
b0109805 11542 gen_bx_im(s, offset);
2c0262af 11543 }
9ee6e8bb
PB
11544 } else if (((insn >> 23) & 7) == 7) {
11545 /* Misc control */
11546 if (insn & (1 << 13))
11547 goto illegal_op;
11548
11549 if (insn & (1 << 26)) {
001b3cab
PM
11550 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11551 goto illegal_op;
11552 }
37e6456e
PM
11553 if (!(insn & (1 << 20))) {
11554 /* Hypervisor call (v7) */
11555 int imm16 = extract32(insn, 16, 4) << 12
11556 | extract32(insn, 0, 12);
11557 ARCH(7);
11558 if (IS_USER(s)) {
11559 goto illegal_op;
11560 }
11561 gen_hvc(s, imm16);
11562 } else {
11563 /* Secure monitor call (v6+) */
11564 ARCH(6K);
11565 if (IS_USER(s)) {
11566 goto illegal_op;
11567 }
11568 gen_smc(s);
11569 }
2c0262af 11570 } else {
9ee6e8bb
PB
11571 op = (insn >> 20) & 7;
11572 switch (op) {
11573 case 0: /* msr cpsr. */
b53d8923 11574 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8984bd2e 11575 tmp = load_reg(s, rn);
b28b3377
PM
11576 /* the constant is the mask and SYSm fields */
11577 addr = tcg_const_i32(insn & 0xfff);
8984bd2e 11578 gen_helper_v7m_msr(cpu_env, addr, tmp);
b75263d6 11579 tcg_temp_free_i32(addr);
7d1b0095 11580 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
11581 gen_lookup_tb(s);
11582 break;
11583 }
11584 /* fall through */
11585 case 1: /* msr spsr. */
b53d8923 11586 if (arm_dc_feature(s, ARM_FEATURE_M)) {
9ee6e8bb 11587 goto illegal_op;
b53d8923 11588 }
8bfd0550
PM
11589
11590 if (extract32(insn, 5, 1)) {
11591 /* MSR (banked) */
11592 int sysm = extract32(insn, 8, 4) |
11593 (extract32(insn, 4, 1) << 4);
11594 int r = op & 1;
11595
11596 gen_msr_banked(s, r, sysm, rm);
11597 break;
11598 }
11599
11600 /* MSR (for PSRs) */
2fbac54b
FN
11601 tmp = load_reg(s, rn);
11602 if (gen_set_psr(s,
7dcc1f89 11603 msr_mask(s, (insn >> 8) & 0xf, op == 1),
2fbac54b 11604 op == 1, tmp))
9ee6e8bb
PB
11605 goto illegal_op;
11606 break;
11607 case 2: /* cps, nop-hint. */
11608 if (((insn >> 8) & 7) == 0) {
11609 gen_nop_hint(s, insn & 0xff);
11610 }
11611 /* Implemented as NOP in user mode. */
11612 if (IS_USER(s))
11613 break;
11614 offset = 0;
11615 imm = 0;
11616 if (insn & (1 << 10)) {
11617 if (insn & (1 << 7))
11618 offset |= CPSR_A;
11619 if (insn & (1 << 6))
11620 offset |= CPSR_I;
11621 if (insn & (1 << 5))
11622 offset |= CPSR_F;
11623 if (insn & (1 << 9))
11624 imm = CPSR_A | CPSR_I | CPSR_F;
11625 }
11626 if (insn & (1 << 8)) {
11627 offset |= 0x1f;
11628 imm |= (insn & 0x1f);
11629 }
11630 if (offset) {
2fbac54b 11631 gen_set_psr_im(s, offset, 0, imm);
9ee6e8bb
PB
11632 }
11633 break;
11634 case 3: /* Special control operations. */
14120108 11635 if (!arm_dc_feature(s, ARM_FEATURE_V7) &&
8297cb13 11636 !arm_dc_feature(s, ARM_FEATURE_M)) {
14120108
JS
11637 goto illegal_op;
11638 }
9ee6e8bb
PB
11639 op = (insn >> 4) & 0xf;
11640 switch (op) {
11641 case 2: /* clrex */
426f5abc 11642 gen_clrex(s);
9ee6e8bb
PB
11643 break;
11644 case 4: /* dsb */
11645 case 5: /* dmb */
61e4c432 11646 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
9ee6e8bb 11647 break;
6df99dec
SS
11648 case 6: /* isb */
11649 /* We need to break the TB after this insn
11650 * to execute self-modifying code correctly
11651 * and also to take any pending interrupts
11652 * immediately.
11653 */
0b609cc1 11654 gen_goto_tb(s, 0, s->pc & ~1);
6df99dec 11655 break;
9ee6e8bb
PB
11656 default:
11657 goto illegal_op;
11658 }
11659 break;
11660 case 4: /* bxj */
9d7c59c8
PM
11661 /* Trivial implementation equivalent to bx.
11662 * This instruction doesn't exist at all for M-profile.
11663 */
11664 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11665 goto illegal_op;
11666 }
d9ba4830
PB
11667 tmp = load_reg(s, rn);
11668 gen_bx(s, tmp);
9ee6e8bb
PB
11669 break;
11670 case 5: /* Exception return. */
b8b45b68
RV
11671 if (IS_USER(s)) {
11672 goto illegal_op;
11673 }
11674 if (rn != 14 || rd != 15) {
11675 goto illegal_op;
11676 }
55c544ed
PM
11677 if (s->current_el == 2) {
11678 /* ERET from Hyp uses ELR_Hyp, not LR */
11679 if (insn & 0xff) {
11680 goto illegal_op;
11681 }
11682 tmp = load_cpu_field(elr_el[2]);
11683 } else {
11684 tmp = load_reg(s, rn);
11685 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
11686 }
b8b45b68
RV
11687 gen_exception_return(s, tmp);
11688 break;
8bfd0550 11689 case 6: /* MRS */
43ac6574
PM
11690 if (extract32(insn, 5, 1) &&
11691 !arm_dc_feature(s, ARM_FEATURE_M)) {
8bfd0550
PM
11692 /* MRS (banked) */
11693 int sysm = extract32(insn, 16, 4) |
11694 (extract32(insn, 4, 1) << 4);
11695
11696 gen_mrs_banked(s, 0, sysm, rd);
11697 break;
11698 }
11699
3d54026f
PM
11700 if (extract32(insn, 16, 4) != 0xf) {
11701 goto illegal_op;
11702 }
11703 if (!arm_dc_feature(s, ARM_FEATURE_M) &&
11704 extract32(insn, 0, 8) != 0) {
11705 goto illegal_op;
11706 }
11707
8bfd0550 11708 /* mrs cpsr */
7d1b0095 11709 tmp = tcg_temp_new_i32();
b53d8923 11710 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8984bd2e
PB
11711 addr = tcg_const_i32(insn & 0xff);
11712 gen_helper_v7m_mrs(tmp, cpu_env, addr);
b75263d6 11713 tcg_temp_free_i32(addr);
9ee6e8bb 11714 } else {
9ef39277 11715 gen_helper_cpsr_read(tmp, cpu_env);
9ee6e8bb 11716 }
8984bd2e 11717 store_reg(s, rd, tmp);
9ee6e8bb 11718 break;
8bfd0550 11719 case 7: /* MRS */
43ac6574
PM
11720 if (extract32(insn, 5, 1) &&
11721 !arm_dc_feature(s, ARM_FEATURE_M)) {
8bfd0550
PM
11722 /* MRS (banked) */
11723 int sysm = extract32(insn, 16, 4) |
11724 (extract32(insn, 4, 1) << 4);
11725
11726 gen_mrs_banked(s, 1, sysm, rd);
11727 break;
11728 }
11729
11730 /* mrs spsr. */
9ee6e8bb 11731 /* Not accessible in user mode. */
b53d8923 11732 if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
9ee6e8bb 11733 goto illegal_op;
b53d8923 11734 }
3d54026f
PM
11735
11736 if (extract32(insn, 16, 4) != 0xf ||
11737 extract32(insn, 0, 8) != 0) {
11738 goto illegal_op;
11739 }
11740
d9ba4830
PB
11741 tmp = load_cpu_field(spsr);
11742 store_reg(s, rd, tmp);
9ee6e8bb 11743 break;
2c0262af
FB
11744 }
11745 }
9ee6e8bb
PB
11746 } else {
11747 /* Conditional branch. */
11748 op = (insn >> 22) & 0xf;
11749 /* Generate a conditional jump to next instruction. */
c2d9644e 11750 arm_skip_unless(s, op);
9ee6e8bb
PB
11751
11752 /* offset[11:1] = insn[10:0] */
11753 offset = (insn & 0x7ff) << 1;
11754 /* offset[17:12] = insn[21:16]. */
11755 offset |= (insn & 0x003f0000) >> 4;
11756 /* offset[31:20] = insn[26]. */
11757 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
11758 /* offset[18] = insn[13]. */
11759 offset |= (insn & (1 << 13)) << 5;
11760 /* offset[19] = insn[11]. */
11761 offset |= (insn & (1 << 11)) << 8;
11762
11763 /* jump to the offset */
b0109805 11764 gen_jmp(s, s->pc + offset);
9ee6e8bb
PB
11765 }
11766 } else {
55203189
PM
11767 /*
11768 * 0b1111_0xxx_xxxx_0xxx_xxxx_xxxx
11769 * - Data-processing (modified immediate, plain binary immediate)
11770 */
9ee6e8bb 11771 if (insn & (1 << 25)) {
55203189
PM
11772 /*
11773 * 0b1111_0x1x_xxxx_0xxx_xxxx_xxxx
11774 * - Data-processing (plain binary immediate)
11775 */
9ee6e8bb
PB
11776 if (insn & (1 << 24)) {
11777 if (insn & (1 << 20))
11778 goto illegal_op;
11779 /* Bitfield/Saturate. */
11780 op = (insn >> 21) & 7;
11781 imm = insn & 0x1f;
11782 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
6ddbc6e4 11783 if (rn == 15) {
7d1b0095 11784 tmp = tcg_temp_new_i32();
6ddbc6e4
PB
11785 tcg_gen_movi_i32(tmp, 0);
11786 } else {
11787 tmp = load_reg(s, rn);
11788 }
9ee6e8bb
PB
11789 switch (op) {
11790 case 2: /* Signed bitfield extract. */
11791 imm++;
11792 if (shift + imm > 32)
11793 goto illegal_op;
59a71b4c
RH
11794 if (imm < 32) {
11795 tcg_gen_sextract_i32(tmp, tmp, shift, imm);
11796 }
9ee6e8bb
PB
11797 break;
11798 case 6: /* Unsigned bitfield extract. */
11799 imm++;
11800 if (shift + imm > 32)
11801 goto illegal_op;
59a71b4c
RH
11802 if (imm < 32) {
11803 tcg_gen_extract_i32(tmp, tmp, shift, imm);
11804 }
9ee6e8bb
PB
11805 break;
11806 case 3: /* Bitfield insert/clear. */
11807 if (imm < shift)
11808 goto illegal_op;
11809 imm = imm + 1 - shift;
11810 if (imm != 32) {
6ddbc6e4 11811 tmp2 = load_reg(s, rd);
d593c48e 11812 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, imm);
7d1b0095 11813 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
11814 }
11815 break;
11816 case 7:
11817 goto illegal_op;
11818 default: /* Saturate. */
9ee6e8bb
PB
11819 if (shift) {
11820 if (op & 1)
6ddbc6e4 11821 tcg_gen_sari_i32(tmp, tmp, shift);
9ee6e8bb 11822 else
6ddbc6e4 11823 tcg_gen_shli_i32(tmp, tmp, shift);
9ee6e8bb 11824 }
6ddbc6e4 11825 tmp2 = tcg_const_i32(imm);
9ee6e8bb
PB
11826 if (op & 4) {
11827 /* Unsigned. */
62b44f05
AR
11828 if ((op & 1) && shift == 0) {
11829 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11830 tcg_temp_free_i32(tmp);
11831 tcg_temp_free_i32(tmp2);
11832 goto illegal_op;
11833 }
9ef39277 11834 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
62b44f05 11835 } else {
9ef39277 11836 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
62b44f05 11837 }
2c0262af 11838 } else {
9ee6e8bb 11839 /* Signed. */
62b44f05
AR
11840 if ((op & 1) && shift == 0) {
11841 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11842 tcg_temp_free_i32(tmp);
11843 tcg_temp_free_i32(tmp2);
11844 goto illegal_op;
11845 }
9ef39277 11846 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
62b44f05 11847 } else {
9ef39277 11848 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
62b44f05 11849 }
2c0262af 11850 }
b75263d6 11851 tcg_temp_free_i32(tmp2);
9ee6e8bb 11852 break;
2c0262af 11853 }
6ddbc6e4 11854 store_reg(s, rd, tmp);
9ee6e8bb
PB
11855 } else {
11856 imm = ((insn & 0x04000000) >> 15)
11857 | ((insn & 0x7000) >> 4) | (insn & 0xff);
11858 if (insn & (1 << 22)) {
11859 /* 16-bit immediate. */
11860 imm |= (insn >> 4) & 0xf000;
11861 if (insn & (1 << 23)) {
11862 /* movt */
5e3f878a 11863 tmp = load_reg(s, rd);
86831435 11864 tcg_gen_ext16u_i32(tmp, tmp);
5e3f878a 11865 tcg_gen_ori_i32(tmp, tmp, imm << 16);
2c0262af 11866 } else {
9ee6e8bb 11867 /* movw */
7d1b0095 11868 tmp = tcg_temp_new_i32();
5e3f878a 11869 tcg_gen_movi_i32(tmp, imm);
2c0262af 11870 }
55203189 11871 store_reg(s, rd, tmp);
2c0262af 11872 } else {
9ee6e8bb
PB
11873 /* Add/sub 12-bit immediate. */
11874 if (rn == 15) {
b0109805 11875 offset = s->pc & ~(uint32_t)3;
9ee6e8bb 11876 if (insn & (1 << 23))
b0109805 11877 offset -= imm;
9ee6e8bb 11878 else
b0109805 11879 offset += imm;
7d1b0095 11880 tmp = tcg_temp_new_i32();
5e3f878a 11881 tcg_gen_movi_i32(tmp, offset);
55203189 11882 store_reg(s, rd, tmp);
2c0262af 11883 } else {
5e3f878a 11884 tmp = load_reg(s, rn);
9ee6e8bb 11885 if (insn & (1 << 23))
5e3f878a 11886 tcg_gen_subi_i32(tmp, tmp, imm);
9ee6e8bb 11887 else
5e3f878a 11888 tcg_gen_addi_i32(tmp, tmp, imm);
55203189
PM
11889 if (rn == 13 && rd == 13) {
11890 /* ADD SP, SP, imm or SUB SP, SP, imm */
11891 store_sp_checked(s, tmp);
11892 } else {
11893 store_reg(s, rd, tmp);
11894 }
2c0262af 11895 }
9ee6e8bb 11896 }
191abaa2 11897 }
9ee6e8bb 11898 } else {
55203189
PM
11899 /*
11900 * 0b1111_0x0x_xxxx_0xxx_xxxx_xxxx
11901 * - Data-processing (modified immediate)
11902 */
9ee6e8bb
PB
11903 int shifter_out = 0;
11904 /* modified 12-bit immediate. */
11905 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
11906 imm = (insn & 0xff);
11907 switch (shift) {
11908 case 0: /* XY */
11909 /* Nothing to do. */
11910 break;
11911 case 1: /* 00XY00XY */
11912 imm |= imm << 16;
11913 break;
11914 case 2: /* XY00XY00 */
11915 imm |= imm << 16;
11916 imm <<= 8;
11917 break;
11918 case 3: /* XYXYXYXY */
11919 imm |= imm << 16;
11920 imm |= imm << 8;
11921 break;
11922 default: /* Rotated constant. */
11923 shift = (shift << 1) | (imm >> 7);
11924 imm |= 0x80;
11925 imm = imm << (32 - shift);
11926 shifter_out = 1;
11927 break;
b5ff1b31 11928 }
7d1b0095 11929 tmp2 = tcg_temp_new_i32();
3174f8e9 11930 tcg_gen_movi_i32(tmp2, imm);
9ee6e8bb 11931 rn = (insn >> 16) & 0xf;
3174f8e9 11932 if (rn == 15) {
7d1b0095 11933 tmp = tcg_temp_new_i32();
3174f8e9
FN
11934 tcg_gen_movi_i32(tmp, 0);
11935 } else {
11936 tmp = load_reg(s, rn);
11937 }
9ee6e8bb
PB
11938 op = (insn >> 21) & 0xf;
11939 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
3174f8e9 11940 shifter_out, tmp, tmp2))
9ee6e8bb 11941 goto illegal_op;
7d1b0095 11942 tcg_temp_free_i32(tmp2);
9ee6e8bb 11943 rd = (insn >> 8) & 0xf;
55203189
PM
11944 if (rd == 13 && rn == 13
11945 && (op == 8 || op == 13)) {
11946 /* ADD(S) SP, SP, imm or SUB(S) SP, SP, imm */
11947 store_sp_checked(s, tmp);
11948 } else if (rd != 15) {
3174f8e9
FN
11949 store_reg(s, rd, tmp);
11950 } else {
7d1b0095 11951 tcg_temp_free_i32(tmp);
2c0262af 11952 }
2c0262af 11953 }
9ee6e8bb
PB
11954 }
11955 break;
11956 case 12: /* Load/store single data item. */
11957 {
11958 int postinc = 0;
11959 int writeback = 0;
a99caa48 11960 int memidx;
9bb6558a
PM
11961 ISSInfo issinfo;
11962
9ee6e8bb 11963 if ((insn & 0x01100000) == 0x01000000) {
7dcc1f89 11964 if (disas_neon_ls_insn(s, insn)) {
c1713132 11965 goto illegal_op;
7dcc1f89 11966 }
9ee6e8bb
PB
11967 break;
11968 }
a2fdc890
PM
11969 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
11970 if (rs == 15) {
11971 if (!(insn & (1 << 20))) {
11972 goto illegal_op;
11973 }
11974 if (op != 2) {
11975 /* Byte or halfword load space with dest == r15 : memory hints.
11976 * Catch them early so we don't emit pointless addressing code.
11977 * This space is a mix of:
11978 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
11979 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
11980 * cores)
11981 * unallocated hints, which must be treated as NOPs
11982 * UNPREDICTABLE space, which we NOP or UNDEF depending on
11983 * which is easiest for the decoding logic
11984 * Some space which must UNDEF
11985 */
11986 int op1 = (insn >> 23) & 3;
11987 int op2 = (insn >> 6) & 0x3f;
11988 if (op & 2) {
11989 goto illegal_op;
11990 }
11991 if (rn == 15) {
02afbf64
PM
11992 /* UNPREDICTABLE, unallocated hint or
11993 * PLD/PLDW/PLI (literal)
11994 */
2eea841c 11995 return;
a2fdc890
PM
11996 }
11997 if (op1 & 1) {
2eea841c 11998 return; /* PLD/PLDW/PLI or unallocated hint */
a2fdc890
PM
11999 }
12000 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
2eea841c 12001 return; /* PLD/PLDW/PLI or unallocated hint */
a2fdc890
PM
12002 }
12003 /* UNDEF space, or an UNPREDICTABLE */
2eea841c 12004 goto illegal_op;
a2fdc890
PM
12005 }
12006 }
a99caa48 12007 memidx = get_mem_index(s);
9ee6e8bb 12008 if (rn == 15) {
7d1b0095 12009 addr = tcg_temp_new_i32();
9ee6e8bb
PB
12010 /* PC relative. */
12011 /* s->pc has already been incremented by 4. */
12012 imm = s->pc & 0xfffffffc;
12013 if (insn & (1 << 23))
12014 imm += insn & 0xfff;
12015 else
12016 imm -= insn & 0xfff;
b0109805 12017 tcg_gen_movi_i32(addr, imm);
9ee6e8bb 12018 } else {
b0109805 12019 addr = load_reg(s, rn);
9ee6e8bb
PB
12020 if (insn & (1 << 23)) {
12021 /* Positive offset. */
12022 imm = insn & 0xfff;
b0109805 12023 tcg_gen_addi_i32(addr, addr, imm);
9ee6e8bb 12024 } else {
9ee6e8bb 12025 imm = insn & 0xff;
2a0308c5
PM
12026 switch ((insn >> 8) & 0xf) {
12027 case 0x0: /* Shifted Register. */
9ee6e8bb 12028 shift = (insn >> 4) & 0xf;
2a0308c5
PM
12029 if (shift > 3) {
12030 tcg_temp_free_i32(addr);
18c9b560 12031 goto illegal_op;
2a0308c5 12032 }
b26eefb6 12033 tmp = load_reg(s, rm);
9ee6e8bb 12034 if (shift)
b26eefb6 12035 tcg_gen_shli_i32(tmp, tmp, shift);
b0109805 12036 tcg_gen_add_i32(addr, addr, tmp);
7d1b0095 12037 tcg_temp_free_i32(tmp);
9ee6e8bb 12038 break;
2a0308c5 12039 case 0xc: /* Negative offset. */
b0109805 12040 tcg_gen_addi_i32(addr, addr, -imm);
9ee6e8bb 12041 break;
2a0308c5 12042 case 0xe: /* User privilege. */
b0109805 12043 tcg_gen_addi_i32(addr, addr, imm);
579d21cc 12044 memidx = get_a32_user_mem_index(s);
9ee6e8bb 12045 break;
2a0308c5 12046 case 0x9: /* Post-decrement. */
9ee6e8bb
PB
12047 imm = -imm;
12048 /* Fall through. */
2a0308c5 12049 case 0xb: /* Post-increment. */
9ee6e8bb
PB
12050 postinc = 1;
12051 writeback = 1;
12052 break;
2a0308c5 12053 case 0xd: /* Pre-decrement. */
9ee6e8bb
PB
12054 imm = -imm;
12055 /* Fall through. */
2a0308c5 12056 case 0xf: /* Pre-increment. */
9ee6e8bb
PB
12057 writeback = 1;
12058 break;
12059 default:
2a0308c5 12060 tcg_temp_free_i32(addr);
b7bcbe95 12061 goto illegal_op;
9ee6e8bb
PB
12062 }
12063 }
12064 }
9bb6558a
PM
12065
12066 issinfo = writeback ? ISSInvalid : rs;
12067
0bc003ba
PM
12068 if (s->v8m_stackcheck && rn == 13 && writeback) {
12069 /*
12070 * Stackcheck. Here we know 'addr' is the current SP;
12071 * if imm is +ve we're moving SP up, else down. It is
12072 * UNKNOWN whether the limit check triggers when SP starts
12073 * below the limit and ends up above it; we chose to do so.
12074 */
12075 if ((int32_t)imm < 0) {
12076 TCGv_i32 newsp = tcg_temp_new_i32();
12077
12078 tcg_gen_addi_i32(newsp, addr, imm);
12079 gen_helper_v8m_stackcheck(cpu_env, newsp);
12080 tcg_temp_free_i32(newsp);
12081 } else {
12082 gen_helper_v8m_stackcheck(cpu_env, addr);
12083 }
12084 }
12085
12086 if (writeback && !postinc) {
12087 tcg_gen_addi_i32(addr, addr, imm);
12088 }
12089
9ee6e8bb
PB
12090 if (insn & (1 << 20)) {
12091 /* Load. */
5a839c0d 12092 tmp = tcg_temp_new_i32();
a2fdc890 12093 switch (op) {
5a839c0d 12094 case 0:
9bb6558a 12095 gen_aa32_ld8u_iss(s, tmp, addr, memidx, issinfo);
5a839c0d
PM
12096 break;
12097 case 4:
9bb6558a 12098 gen_aa32_ld8s_iss(s, tmp, addr, memidx, issinfo);
5a839c0d
PM
12099 break;
12100 case 1:
9bb6558a 12101 gen_aa32_ld16u_iss(s, tmp, addr, memidx, issinfo);
5a839c0d
PM
12102 break;
12103 case 5:
9bb6558a 12104 gen_aa32_ld16s_iss(s, tmp, addr, memidx, issinfo);
5a839c0d
PM
12105 break;
12106 case 2:
9bb6558a 12107 gen_aa32_ld32u_iss(s, tmp, addr, memidx, issinfo);
5a839c0d 12108 break;
2a0308c5 12109 default:
5a839c0d 12110 tcg_temp_free_i32(tmp);
2a0308c5
PM
12111 tcg_temp_free_i32(addr);
12112 goto illegal_op;
a2fdc890
PM
12113 }
12114 if (rs == 15) {
3bb8a96f 12115 gen_bx_excret(s, tmp);
9ee6e8bb 12116 } else {
a2fdc890 12117 store_reg(s, rs, tmp);
9ee6e8bb
PB
12118 }
12119 } else {
12120 /* Store. */
b0109805 12121 tmp = load_reg(s, rs);
9ee6e8bb 12122 switch (op) {
5a839c0d 12123 case 0:
9bb6558a 12124 gen_aa32_st8_iss(s, tmp, addr, memidx, issinfo);
5a839c0d
PM
12125 break;
12126 case 1:
9bb6558a 12127 gen_aa32_st16_iss(s, tmp, addr, memidx, issinfo);
5a839c0d
PM
12128 break;
12129 case 2:
9bb6558a 12130 gen_aa32_st32_iss(s, tmp, addr, memidx, issinfo);
5a839c0d 12131 break;
2a0308c5 12132 default:
5a839c0d 12133 tcg_temp_free_i32(tmp);
2a0308c5
PM
12134 tcg_temp_free_i32(addr);
12135 goto illegal_op;
b7bcbe95 12136 }
5a839c0d 12137 tcg_temp_free_i32(tmp);
2c0262af 12138 }
9ee6e8bb 12139 if (postinc)
b0109805
PB
12140 tcg_gen_addi_i32(addr, addr, imm);
12141 if (writeback) {
12142 store_reg(s, rn, addr);
12143 } else {
7d1b0095 12144 tcg_temp_free_i32(addr);
b0109805 12145 }
9ee6e8bb
PB
12146 }
12147 break;
12148 default:
12149 goto illegal_op;
2c0262af 12150 }
2eea841c 12151 return;
9ee6e8bb 12152illegal_op:
2eea841c
PM
12153 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
12154 default_exception_el(s));
2c0262af
FB
12155}
12156
296e5a0a 12157static void disas_thumb_insn(DisasContext *s, uint32_t insn)
99c475ab 12158{
296e5a0a 12159 uint32_t val, op, rm, rn, rd, shift, cond;
99c475ab
FB
12160 int32_t offset;
12161 int i;
39d5492a
PM
12162 TCGv_i32 tmp;
12163 TCGv_i32 tmp2;
12164 TCGv_i32 addr;
99c475ab 12165
99c475ab
FB
12166 switch (insn >> 12) {
12167 case 0: case 1:
396e467c 12168
99c475ab
FB
12169 rd = insn & 7;
12170 op = (insn >> 11) & 3;
12171 if (op == 3) {
a2d12f0f
PM
12172 /*
12173 * 0b0001_1xxx_xxxx_xxxx
12174 * - Add, subtract (three low registers)
12175 * - Add, subtract (two low registers and immediate)
12176 */
99c475ab 12177 rn = (insn >> 3) & 7;
396e467c 12178 tmp = load_reg(s, rn);
99c475ab
FB
12179 if (insn & (1 << 10)) {
12180 /* immediate */
7d1b0095 12181 tmp2 = tcg_temp_new_i32();
396e467c 12182 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
99c475ab
FB
12183 } else {
12184 /* reg */
12185 rm = (insn >> 6) & 7;
396e467c 12186 tmp2 = load_reg(s, rm);
99c475ab 12187 }
9ee6e8bb
PB
12188 if (insn & (1 << 9)) {
12189 if (s->condexec_mask)
396e467c 12190 tcg_gen_sub_i32(tmp, tmp, tmp2);
9ee6e8bb 12191 else
72485ec4 12192 gen_sub_CC(tmp, tmp, tmp2);
9ee6e8bb
PB
12193 } else {
12194 if (s->condexec_mask)
396e467c 12195 tcg_gen_add_i32(tmp, tmp, tmp2);
9ee6e8bb 12196 else
72485ec4 12197 gen_add_CC(tmp, tmp, tmp2);
9ee6e8bb 12198 }
7d1b0095 12199 tcg_temp_free_i32(tmp2);
396e467c 12200 store_reg(s, rd, tmp);
99c475ab
FB
12201 } else {
12202 /* shift immediate */
12203 rm = (insn >> 3) & 7;
12204 shift = (insn >> 6) & 0x1f;
9a119ff6
PB
12205 tmp = load_reg(s, rm);
12206 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
12207 if (!s->condexec_mask)
12208 gen_logic_CC(tmp);
12209 store_reg(s, rd, tmp);
99c475ab
FB
12210 }
12211 break;
12212 case 2: case 3:
a2d12f0f
PM
12213 /*
12214 * 0b001x_xxxx_xxxx_xxxx
12215 * - Add, subtract, compare, move (one low register and immediate)
12216 */
99c475ab
FB
12217 op = (insn >> 11) & 3;
12218 rd = (insn >> 8) & 0x7;
396e467c 12219 if (op == 0) { /* mov */
7d1b0095 12220 tmp = tcg_temp_new_i32();
396e467c 12221 tcg_gen_movi_i32(tmp, insn & 0xff);
9ee6e8bb 12222 if (!s->condexec_mask)
396e467c
FN
12223 gen_logic_CC(tmp);
12224 store_reg(s, rd, tmp);
12225 } else {
12226 tmp = load_reg(s, rd);
7d1b0095 12227 tmp2 = tcg_temp_new_i32();
396e467c
FN
12228 tcg_gen_movi_i32(tmp2, insn & 0xff);
12229 switch (op) {
12230 case 1: /* cmp */
72485ec4 12231 gen_sub_CC(tmp, tmp, tmp2);
7d1b0095
PM
12232 tcg_temp_free_i32(tmp);
12233 tcg_temp_free_i32(tmp2);
396e467c
FN
12234 break;
12235 case 2: /* add */
12236 if (s->condexec_mask)
12237 tcg_gen_add_i32(tmp, tmp, tmp2);
12238 else
72485ec4 12239 gen_add_CC(tmp, tmp, tmp2);
7d1b0095 12240 tcg_temp_free_i32(tmp2);
396e467c
FN
12241 store_reg(s, rd, tmp);
12242 break;
12243 case 3: /* sub */
12244 if (s->condexec_mask)
12245 tcg_gen_sub_i32(tmp, tmp, tmp2);
12246 else
72485ec4 12247 gen_sub_CC(tmp, tmp, tmp2);
7d1b0095 12248 tcg_temp_free_i32(tmp2);
396e467c
FN
12249 store_reg(s, rd, tmp);
12250 break;
12251 }
99c475ab 12252 }
99c475ab
FB
12253 break;
12254 case 4:
12255 if (insn & (1 << 11)) {
12256 rd = (insn >> 8) & 7;
5899f386
FB
12257 /* load pc-relative. Bit 1 of PC is ignored. */
12258 val = s->pc + 2 + ((insn & 0xff) * 4);
12259 val &= ~(uint32_t)2;
7d1b0095 12260 addr = tcg_temp_new_i32();
b0109805 12261 tcg_gen_movi_i32(addr, val);
c40c8556 12262 tmp = tcg_temp_new_i32();
9bb6558a
PM
12263 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s),
12264 rd | ISSIs16Bit);
7d1b0095 12265 tcg_temp_free_i32(addr);
b0109805 12266 store_reg(s, rd, tmp);
99c475ab
FB
12267 break;
12268 }
12269 if (insn & (1 << 10)) {
ebfe27c5
PM
12270 /* 0b0100_01xx_xxxx_xxxx
12271 * - data processing extended, branch and exchange
12272 */
99c475ab
FB
12273 rd = (insn & 7) | ((insn >> 4) & 8);
12274 rm = (insn >> 3) & 0xf;
12275 op = (insn >> 8) & 3;
12276 switch (op) {
12277 case 0: /* add */
396e467c
FN
12278 tmp = load_reg(s, rd);
12279 tmp2 = load_reg(s, rm);
12280 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 12281 tcg_temp_free_i32(tmp2);
55203189
PM
12282 if (rd == 13) {
12283 /* ADD SP, SP, reg */
12284 store_sp_checked(s, tmp);
12285 } else {
12286 store_reg(s, rd, tmp);
12287 }
99c475ab
FB
12288 break;
12289 case 1: /* cmp */
396e467c
FN
12290 tmp = load_reg(s, rd);
12291 tmp2 = load_reg(s, rm);
72485ec4 12292 gen_sub_CC(tmp, tmp, tmp2);
7d1b0095
PM
12293 tcg_temp_free_i32(tmp2);
12294 tcg_temp_free_i32(tmp);
99c475ab
FB
12295 break;
12296 case 2: /* mov/cpy */
396e467c 12297 tmp = load_reg(s, rm);
55203189
PM
12298 if (rd == 13) {
12299 /* MOV SP, reg */
12300 store_sp_checked(s, tmp);
12301 } else {
12302 store_reg(s, rd, tmp);
12303 }
99c475ab 12304 break;
ebfe27c5
PM
12305 case 3:
12306 {
12307 /* 0b0100_0111_xxxx_xxxx
12308 * - branch [and link] exchange thumb register
12309 */
12310 bool link = insn & (1 << 7);
12311
fb602cb7 12312 if (insn & 3) {
ebfe27c5
PM
12313 goto undef;
12314 }
12315 if (link) {
be5e7a76 12316 ARCH(5);
ebfe27c5 12317 }
fb602cb7
PM
12318 if ((insn & 4)) {
12319 /* BXNS/BLXNS: only exists for v8M with the
12320 * security extensions, and always UNDEF if NonSecure.
12321 * We don't implement these in the user-only mode
12322 * either (in theory you can use them from Secure User
12323 * mode but they are too tied in to system emulation.)
12324 */
12325 if (!s->v8m_secure || IS_USER_ONLY) {
12326 goto undef;
12327 }
12328 if (link) {
3e3fa230 12329 gen_blxns(s, rm);
fb602cb7
PM
12330 } else {
12331 gen_bxns(s, rm);
12332 }
12333 break;
12334 }
12335 /* BLX/BX */
ebfe27c5
PM
12336 tmp = load_reg(s, rm);
12337 if (link) {
99c475ab 12338 val = (uint32_t)s->pc | 1;
7d1b0095 12339 tmp2 = tcg_temp_new_i32();
b0109805
PB
12340 tcg_gen_movi_i32(tmp2, val);
12341 store_reg(s, 14, tmp2);
3bb8a96f
PM
12342 gen_bx(s, tmp);
12343 } else {
12344 /* Only BX works as exception-return, not BLX */
12345 gen_bx_excret(s, tmp);
99c475ab 12346 }
99c475ab
FB
12347 break;
12348 }
ebfe27c5 12349 }
99c475ab
FB
12350 break;
12351 }
12352
a2d12f0f
PM
12353 /*
12354 * 0b0100_00xx_xxxx_xxxx
12355 * - Data-processing (two low registers)
12356 */
99c475ab
FB
12357 rd = insn & 7;
12358 rm = (insn >> 3) & 7;
12359 op = (insn >> 6) & 0xf;
12360 if (op == 2 || op == 3 || op == 4 || op == 7) {
12361 /* the shift/rotate ops want the operands backwards */
12362 val = rm;
12363 rm = rd;
12364 rd = val;
12365 val = 1;
12366 } else {
12367 val = 0;
12368 }
12369
396e467c 12370 if (op == 9) { /* neg */
7d1b0095 12371 tmp = tcg_temp_new_i32();
396e467c
FN
12372 tcg_gen_movi_i32(tmp, 0);
12373 } else if (op != 0xf) { /* mvn doesn't read its first operand */
12374 tmp = load_reg(s, rd);
12375 } else {
f764718d 12376 tmp = NULL;
396e467c 12377 }
99c475ab 12378
396e467c 12379 tmp2 = load_reg(s, rm);
5899f386 12380 switch (op) {
99c475ab 12381 case 0x0: /* and */
396e467c 12382 tcg_gen_and_i32(tmp, tmp, tmp2);
9ee6e8bb 12383 if (!s->condexec_mask)
396e467c 12384 gen_logic_CC(tmp);
99c475ab
FB
12385 break;
12386 case 0x1: /* eor */
396e467c 12387 tcg_gen_xor_i32(tmp, tmp, tmp2);
9ee6e8bb 12388 if (!s->condexec_mask)
396e467c 12389 gen_logic_CC(tmp);
99c475ab
FB
12390 break;
12391 case 0x2: /* lsl */
9ee6e8bb 12392 if (s->condexec_mask) {
365af80e 12393 gen_shl(tmp2, tmp2, tmp);
9ee6e8bb 12394 } else {
9ef39277 12395 gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
396e467c 12396 gen_logic_CC(tmp2);
9ee6e8bb 12397 }
99c475ab
FB
12398 break;
12399 case 0x3: /* lsr */
9ee6e8bb 12400 if (s->condexec_mask) {
365af80e 12401 gen_shr(tmp2, tmp2, tmp);
9ee6e8bb 12402 } else {
9ef39277 12403 gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
396e467c 12404 gen_logic_CC(tmp2);
9ee6e8bb 12405 }
99c475ab
FB
12406 break;
12407 case 0x4: /* asr */
9ee6e8bb 12408 if (s->condexec_mask) {
365af80e 12409 gen_sar(tmp2, tmp2, tmp);
9ee6e8bb 12410 } else {
9ef39277 12411 gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
396e467c 12412 gen_logic_CC(tmp2);
9ee6e8bb 12413 }
99c475ab
FB
12414 break;
12415 case 0x5: /* adc */
49b4c31e 12416 if (s->condexec_mask) {
396e467c 12417 gen_adc(tmp, tmp2);
49b4c31e
RH
12418 } else {
12419 gen_adc_CC(tmp, tmp, tmp2);
12420 }
99c475ab
FB
12421 break;
12422 case 0x6: /* sbc */
2de68a49 12423 if (s->condexec_mask) {
396e467c 12424 gen_sub_carry(tmp, tmp, tmp2);
2de68a49
RH
12425 } else {
12426 gen_sbc_CC(tmp, tmp, tmp2);
12427 }
99c475ab
FB
12428 break;
12429 case 0x7: /* ror */
9ee6e8bb 12430 if (s->condexec_mask) {
f669df27
AJ
12431 tcg_gen_andi_i32(tmp, tmp, 0x1f);
12432 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
9ee6e8bb 12433 } else {
9ef39277 12434 gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);
396e467c 12435 gen_logic_CC(tmp2);
9ee6e8bb 12436 }
99c475ab
FB
12437 break;
12438 case 0x8: /* tst */
396e467c
FN
12439 tcg_gen_and_i32(tmp, tmp, tmp2);
12440 gen_logic_CC(tmp);
99c475ab 12441 rd = 16;
5899f386 12442 break;
99c475ab 12443 case 0x9: /* neg */
9ee6e8bb 12444 if (s->condexec_mask)
396e467c 12445 tcg_gen_neg_i32(tmp, tmp2);
9ee6e8bb 12446 else
72485ec4 12447 gen_sub_CC(tmp, tmp, tmp2);
99c475ab
FB
12448 break;
12449 case 0xa: /* cmp */
72485ec4 12450 gen_sub_CC(tmp, tmp, tmp2);
99c475ab
FB
12451 rd = 16;
12452 break;
12453 case 0xb: /* cmn */
72485ec4 12454 gen_add_CC(tmp, tmp, tmp2);
99c475ab
FB
12455 rd = 16;
12456 break;
12457 case 0xc: /* orr */
396e467c 12458 tcg_gen_or_i32(tmp, tmp, tmp2);
9ee6e8bb 12459 if (!s->condexec_mask)
396e467c 12460 gen_logic_CC(tmp);
99c475ab
FB
12461 break;
12462 case 0xd: /* mul */
7b2919a0 12463 tcg_gen_mul_i32(tmp, tmp, tmp2);
9ee6e8bb 12464 if (!s->condexec_mask)
396e467c 12465 gen_logic_CC(tmp);
99c475ab
FB
12466 break;
12467 case 0xe: /* bic */
f669df27 12468 tcg_gen_andc_i32(tmp, tmp, tmp2);
9ee6e8bb 12469 if (!s->condexec_mask)
396e467c 12470 gen_logic_CC(tmp);
99c475ab
FB
12471 break;
12472 case 0xf: /* mvn */
396e467c 12473 tcg_gen_not_i32(tmp2, tmp2);
9ee6e8bb 12474 if (!s->condexec_mask)
396e467c 12475 gen_logic_CC(tmp2);
99c475ab 12476 val = 1;
5899f386 12477 rm = rd;
99c475ab
FB
12478 break;
12479 }
12480 if (rd != 16) {
396e467c
FN
12481 if (val) {
12482 store_reg(s, rm, tmp2);
12483 if (op != 0xf)
7d1b0095 12484 tcg_temp_free_i32(tmp);
396e467c
FN
12485 } else {
12486 store_reg(s, rd, tmp);
7d1b0095 12487 tcg_temp_free_i32(tmp2);
396e467c
FN
12488 }
12489 } else {
7d1b0095
PM
12490 tcg_temp_free_i32(tmp);
12491 tcg_temp_free_i32(tmp2);
99c475ab
FB
12492 }
12493 break;
12494
12495 case 5:
12496 /* load/store register offset. */
12497 rd = insn & 7;
12498 rn = (insn >> 3) & 7;
12499 rm = (insn >> 6) & 7;
12500 op = (insn >> 9) & 7;
b0109805 12501 addr = load_reg(s, rn);
b26eefb6 12502 tmp = load_reg(s, rm);
b0109805 12503 tcg_gen_add_i32(addr, addr, tmp);
7d1b0095 12504 tcg_temp_free_i32(tmp);
99c475ab 12505
c40c8556 12506 if (op < 3) { /* store */
b0109805 12507 tmp = load_reg(s, rd);
c40c8556
PM
12508 } else {
12509 tmp = tcg_temp_new_i32();
12510 }
99c475ab
FB
12511
12512 switch (op) {
12513 case 0: /* str */
9bb6558a 12514 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
12515 break;
12516 case 1: /* strh */
9bb6558a 12517 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
12518 break;
12519 case 2: /* strb */
9bb6558a 12520 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
12521 break;
12522 case 3: /* ldrsb */
9bb6558a 12523 gen_aa32_ld8s_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
12524 break;
12525 case 4: /* ldr */
9bb6558a 12526 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
12527 break;
12528 case 5: /* ldrh */
9bb6558a 12529 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
12530 break;
12531 case 6: /* ldrb */
9bb6558a 12532 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
12533 break;
12534 case 7: /* ldrsh */
9bb6558a 12535 gen_aa32_ld16s_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
12536 break;
12537 }
c40c8556 12538 if (op >= 3) { /* load */
b0109805 12539 store_reg(s, rd, tmp);
c40c8556
PM
12540 } else {
12541 tcg_temp_free_i32(tmp);
12542 }
7d1b0095 12543 tcg_temp_free_i32(addr);
99c475ab
FB
12544 break;
12545
12546 case 6:
12547 /* load/store word immediate offset */
12548 rd = insn & 7;
12549 rn = (insn >> 3) & 7;
b0109805 12550 addr = load_reg(s, rn);
99c475ab 12551 val = (insn >> 4) & 0x7c;
b0109805 12552 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
12553
12554 if (insn & (1 << 11)) {
12555 /* load */
c40c8556 12556 tmp = tcg_temp_new_i32();
12dcc321 12557 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 12558 store_reg(s, rd, tmp);
99c475ab
FB
12559 } else {
12560 /* store */
b0109805 12561 tmp = load_reg(s, rd);
12dcc321 12562 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
c40c8556 12563 tcg_temp_free_i32(tmp);
99c475ab 12564 }
7d1b0095 12565 tcg_temp_free_i32(addr);
99c475ab
FB
12566 break;
12567
12568 case 7:
12569 /* load/store byte immediate offset */
12570 rd = insn & 7;
12571 rn = (insn >> 3) & 7;
b0109805 12572 addr = load_reg(s, rn);
99c475ab 12573 val = (insn >> 6) & 0x1f;
b0109805 12574 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
12575
12576 if (insn & (1 << 11)) {
12577 /* load */
c40c8556 12578 tmp = tcg_temp_new_i32();
9bb6558a 12579 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
b0109805 12580 store_reg(s, rd, tmp);
99c475ab
FB
12581 } else {
12582 /* store */
b0109805 12583 tmp = load_reg(s, rd);
9bb6558a 12584 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
c40c8556 12585 tcg_temp_free_i32(tmp);
99c475ab 12586 }
7d1b0095 12587 tcg_temp_free_i32(addr);
99c475ab
FB
12588 break;
12589
12590 case 8:
12591 /* load/store halfword immediate offset */
12592 rd = insn & 7;
12593 rn = (insn >> 3) & 7;
b0109805 12594 addr = load_reg(s, rn);
99c475ab 12595 val = (insn >> 5) & 0x3e;
b0109805 12596 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
12597
12598 if (insn & (1 << 11)) {
12599 /* load */
c40c8556 12600 tmp = tcg_temp_new_i32();
9bb6558a 12601 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
b0109805 12602 store_reg(s, rd, tmp);
99c475ab
FB
12603 } else {
12604 /* store */
b0109805 12605 tmp = load_reg(s, rd);
9bb6558a 12606 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
c40c8556 12607 tcg_temp_free_i32(tmp);
99c475ab 12608 }
7d1b0095 12609 tcg_temp_free_i32(addr);
99c475ab
FB
12610 break;
12611
12612 case 9:
12613 /* load/store from stack */
12614 rd = (insn >> 8) & 7;
b0109805 12615 addr = load_reg(s, 13);
99c475ab 12616 val = (insn & 0xff) * 4;
b0109805 12617 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
12618
12619 if (insn & (1 << 11)) {
12620 /* load */
c40c8556 12621 tmp = tcg_temp_new_i32();
9bb6558a 12622 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
b0109805 12623 store_reg(s, rd, tmp);
99c475ab
FB
12624 } else {
12625 /* store */
b0109805 12626 tmp = load_reg(s, rd);
9bb6558a 12627 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
c40c8556 12628 tcg_temp_free_i32(tmp);
99c475ab 12629 }
7d1b0095 12630 tcg_temp_free_i32(addr);
99c475ab
FB
12631 break;
12632
12633 case 10:
55203189
PM
12634 /*
12635 * 0b1010_xxxx_xxxx_xxxx
12636 * - Add PC/SP (immediate)
12637 */
99c475ab 12638 rd = (insn >> 8) & 7;
5899f386
FB
12639 if (insn & (1 << 11)) {
12640 /* SP */
5e3f878a 12641 tmp = load_reg(s, 13);
5899f386
FB
12642 } else {
12643 /* PC. bit 1 is ignored. */
7d1b0095 12644 tmp = tcg_temp_new_i32();
5e3f878a 12645 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
5899f386 12646 }
99c475ab 12647 val = (insn & 0xff) * 4;
5e3f878a
PB
12648 tcg_gen_addi_i32(tmp, tmp, val);
12649 store_reg(s, rd, tmp);
99c475ab
FB
12650 break;
12651
12652 case 11:
12653 /* misc */
12654 op = (insn >> 8) & 0xf;
12655 switch (op) {
12656 case 0:
55203189
PM
12657 /*
12658 * 0b1011_0000_xxxx_xxxx
12659 * - ADD (SP plus immediate)
12660 * - SUB (SP minus immediate)
12661 */
b26eefb6 12662 tmp = load_reg(s, 13);
99c475ab
FB
12663 val = (insn & 0x7f) * 4;
12664 if (insn & (1 << 7))
6a0d8a1d 12665 val = -(int32_t)val;
b26eefb6 12666 tcg_gen_addi_i32(tmp, tmp, val);
55203189 12667 store_sp_checked(s, tmp);
99c475ab
FB
12668 break;
12669
9ee6e8bb
PB
12670 case 2: /* sign/zero extend. */
12671 ARCH(6);
12672 rd = insn & 7;
12673 rm = (insn >> 3) & 7;
b0109805 12674 tmp = load_reg(s, rm);
9ee6e8bb 12675 switch ((insn >> 6) & 3) {
b0109805
PB
12676 case 0: gen_sxth(tmp); break;
12677 case 1: gen_sxtb(tmp); break;
12678 case 2: gen_uxth(tmp); break;
12679 case 3: gen_uxtb(tmp); break;
9ee6e8bb 12680 }
b0109805 12681 store_reg(s, rd, tmp);
9ee6e8bb 12682 break;
99c475ab 12683 case 4: case 5: case 0xc: case 0xd:
aa369e5c
PM
12684 /*
12685 * 0b1011_x10x_xxxx_xxxx
12686 * - push/pop
12687 */
b0109805 12688 addr = load_reg(s, 13);
5899f386
FB
12689 if (insn & (1 << 8))
12690 offset = 4;
99c475ab 12691 else
5899f386
FB
12692 offset = 0;
12693 for (i = 0; i < 8; i++) {
12694 if (insn & (1 << i))
12695 offset += 4;
12696 }
12697 if ((insn & (1 << 11)) == 0) {
b0109805 12698 tcg_gen_addi_i32(addr, addr, -offset);
5899f386 12699 }
aa369e5c
PM
12700
12701 if (s->v8m_stackcheck) {
12702 /*
12703 * Here 'addr' is the lower of "old SP" and "new SP";
12704 * if this is a pop that starts below the limit and ends
12705 * above it, it is UNKNOWN whether the limit check triggers;
12706 * we choose to trigger.
12707 */
12708 gen_helper_v8m_stackcheck(cpu_env, addr);
12709 }
12710
99c475ab
FB
12711 for (i = 0; i < 8; i++) {
12712 if (insn & (1 << i)) {
12713 if (insn & (1 << 11)) {
12714 /* pop */
c40c8556 12715 tmp = tcg_temp_new_i32();
12dcc321 12716 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 12717 store_reg(s, i, tmp);
99c475ab
FB
12718 } else {
12719 /* push */
b0109805 12720 tmp = load_reg(s, i);
12dcc321 12721 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
c40c8556 12722 tcg_temp_free_i32(tmp);
99c475ab 12723 }
5899f386 12724 /* advance to the next address. */
b0109805 12725 tcg_gen_addi_i32(addr, addr, 4);
99c475ab
FB
12726 }
12727 }
f764718d 12728 tmp = NULL;
99c475ab
FB
12729 if (insn & (1 << 8)) {
12730 if (insn & (1 << 11)) {
12731 /* pop pc */
c40c8556 12732 tmp = tcg_temp_new_i32();
12dcc321 12733 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
99c475ab
FB
12734 /* don't set the pc until the rest of the instruction
12735 has completed */
12736 } else {
12737 /* push lr */
b0109805 12738 tmp = load_reg(s, 14);
12dcc321 12739 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
c40c8556 12740 tcg_temp_free_i32(tmp);
99c475ab 12741 }
b0109805 12742 tcg_gen_addi_i32(addr, addr, 4);
99c475ab 12743 }
5899f386 12744 if ((insn & (1 << 11)) == 0) {
b0109805 12745 tcg_gen_addi_i32(addr, addr, -offset);
5899f386 12746 }
99c475ab 12747 /* write back the new stack pointer */
b0109805 12748 store_reg(s, 13, addr);
99c475ab 12749 /* set the new PC value */
be5e7a76 12750 if ((insn & 0x0900) == 0x0900) {
7dcc1f89 12751 store_reg_from_load(s, 15, tmp);
be5e7a76 12752 }
99c475ab
FB
12753 break;
12754
9ee6e8bb
PB
12755 case 1: case 3: case 9: case 11: /* czb */
12756 rm = insn & 7;
d9ba4830 12757 tmp = load_reg(s, rm);
c2d9644e 12758 arm_gen_condlabel(s);
9ee6e8bb 12759 if (insn & (1 << 11))
cb63669a 12760 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
9ee6e8bb 12761 else
cb63669a 12762 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
7d1b0095 12763 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
12764 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
12765 val = (uint32_t)s->pc + 2;
12766 val += offset;
12767 gen_jmp(s, val);
12768 break;
12769
12770 case 15: /* IT, nop-hint. */
12771 if ((insn & 0xf) == 0) {
12772 gen_nop_hint(s, (insn >> 4) & 0xf);
12773 break;
12774 }
12775 /* If Then. */
12776 s->condexec_cond = (insn >> 4) & 0xe;
12777 s->condexec_mask = insn & 0x1f;
12778 /* No actual code generated for this insn, just setup state. */
12779 break;
12780
06c949e6 12781 case 0xe: /* bkpt */
d4a2dc67
PM
12782 {
12783 int imm8 = extract32(insn, 0, 8);
be5e7a76 12784 ARCH(5);
c900a2e6 12785 gen_exception_bkpt_insn(s, 2, syn_aa32_bkpt(imm8, true));
06c949e6 12786 break;
d4a2dc67 12787 }
06c949e6 12788
19a6e31c
PM
12789 case 0xa: /* rev, and hlt */
12790 {
12791 int op1 = extract32(insn, 6, 2);
12792
12793 if (op1 == 2) {
12794 /* HLT */
12795 int imm6 = extract32(insn, 0, 6);
12796
12797 gen_hlt(s, imm6);
12798 break;
12799 }
12800
12801 /* Otherwise this is rev */
9ee6e8bb
PB
12802 ARCH(6);
12803 rn = (insn >> 3) & 0x7;
12804 rd = insn & 0x7;
b0109805 12805 tmp = load_reg(s, rn);
19a6e31c 12806 switch (op1) {
66896cb8 12807 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
b0109805
PB
12808 case 1: gen_rev16(tmp); break;
12809 case 3: gen_revsh(tmp); break;
19a6e31c
PM
12810 default:
12811 g_assert_not_reached();
9ee6e8bb 12812 }
b0109805 12813 store_reg(s, rd, tmp);
9ee6e8bb 12814 break;
19a6e31c 12815 }
9ee6e8bb 12816
d9e028c1
PM
12817 case 6:
12818 switch ((insn >> 5) & 7) {
12819 case 2:
12820 /* setend */
12821 ARCH(6);
9886ecdf
PB
12822 if (((insn >> 3) & 1) != !!(s->be_data == MO_BE)) {
12823 gen_helper_setend(cpu_env);
dcba3a8d 12824 s->base.is_jmp = DISAS_UPDATE;
d9e028c1 12825 }
9ee6e8bb 12826 break;
d9e028c1
PM
12827 case 3:
12828 /* cps */
12829 ARCH(6);
12830 if (IS_USER(s)) {
12831 break;
8984bd2e 12832 }
b53d8923 12833 if (arm_dc_feature(s, ARM_FEATURE_M)) {
d9e028c1
PM
12834 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
12835 /* FAULTMASK */
12836 if (insn & 1) {
12837 addr = tcg_const_i32(19);
12838 gen_helper_v7m_msr(cpu_env, addr, tmp);
12839 tcg_temp_free_i32(addr);
12840 }
12841 /* PRIMASK */
12842 if (insn & 2) {
12843 addr = tcg_const_i32(16);
12844 gen_helper_v7m_msr(cpu_env, addr, tmp);
12845 tcg_temp_free_i32(addr);
12846 }
12847 tcg_temp_free_i32(tmp);
12848 gen_lookup_tb(s);
12849 } else {
12850 if (insn & (1 << 4)) {
12851 shift = CPSR_A | CPSR_I | CPSR_F;
12852 } else {
12853 shift = 0;
12854 }
12855 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
8984bd2e 12856 }
d9e028c1
PM
12857 break;
12858 default:
12859 goto undef;
9ee6e8bb
PB
12860 }
12861 break;
12862
99c475ab
FB
12863 default:
12864 goto undef;
12865 }
12866 break;
12867
12868 case 12:
a7d3970d 12869 {
99c475ab 12870 /* load/store multiple */
f764718d 12871 TCGv_i32 loaded_var = NULL;
99c475ab 12872 rn = (insn >> 8) & 0x7;
b0109805 12873 addr = load_reg(s, rn);
99c475ab
FB
12874 for (i = 0; i < 8; i++) {
12875 if (insn & (1 << i)) {
99c475ab
FB
12876 if (insn & (1 << 11)) {
12877 /* load */
c40c8556 12878 tmp = tcg_temp_new_i32();
12dcc321 12879 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
a7d3970d
PM
12880 if (i == rn) {
12881 loaded_var = tmp;
12882 } else {
12883 store_reg(s, i, tmp);
12884 }
99c475ab
FB
12885 } else {
12886 /* store */
b0109805 12887 tmp = load_reg(s, i);
12dcc321 12888 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
c40c8556 12889 tcg_temp_free_i32(tmp);
99c475ab 12890 }
5899f386 12891 /* advance to the next address */
b0109805 12892 tcg_gen_addi_i32(addr, addr, 4);
99c475ab
FB
12893 }
12894 }
b0109805 12895 if ((insn & (1 << rn)) == 0) {
a7d3970d 12896 /* base reg not in list: base register writeback */
b0109805
PB
12897 store_reg(s, rn, addr);
12898 } else {
a7d3970d
PM
12899 /* base reg in list: if load, complete it now */
12900 if (insn & (1 << 11)) {
12901 store_reg(s, rn, loaded_var);
12902 }
7d1b0095 12903 tcg_temp_free_i32(addr);
b0109805 12904 }
99c475ab 12905 break;
a7d3970d 12906 }
99c475ab
FB
12907 case 13:
12908 /* conditional branch or swi */
12909 cond = (insn >> 8) & 0xf;
12910 if (cond == 0xe)
12911 goto undef;
12912
12913 if (cond == 0xf) {
12914 /* swi */
eaed129d 12915 gen_set_pc_im(s, s->pc);
d4a2dc67 12916 s->svc_imm = extract32(insn, 0, 8);
dcba3a8d 12917 s->base.is_jmp = DISAS_SWI;
99c475ab
FB
12918 break;
12919 }
12920 /* generate a conditional jump to next instruction */
c2d9644e 12921 arm_skip_unless(s, cond);
99c475ab
FB
12922
12923 /* jump to the offset */
5899f386 12924 val = (uint32_t)s->pc + 2;
99c475ab 12925 offset = ((int32_t)insn << 24) >> 24;
5899f386 12926 val += offset << 1;
8aaca4c0 12927 gen_jmp(s, val);
99c475ab
FB
12928 break;
12929
12930 case 14:
358bf29e 12931 if (insn & (1 << 11)) {
296e5a0a
PM
12932 /* thumb_insn_is_16bit() ensures we can't get here for
12933 * a Thumb2 CPU, so this must be a thumb1 split BL/BLX:
12934 * 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF)
12935 */
12936 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
12937 ARCH(5);
12938 offset = ((insn & 0x7ff) << 1);
12939 tmp = load_reg(s, 14);
12940 tcg_gen_addi_i32(tmp, tmp, offset);
12941 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
12942
12943 tmp2 = tcg_temp_new_i32();
12944 tcg_gen_movi_i32(tmp2, s->pc | 1);
12945 store_reg(s, 14, tmp2);
12946 gen_bx(s, tmp);
358bf29e
PB
12947 break;
12948 }
9ee6e8bb 12949 /* unconditional branch */
99c475ab
FB
12950 val = (uint32_t)s->pc;
12951 offset = ((int32_t)insn << 21) >> 21;
12952 val += (offset << 1) + 2;
8aaca4c0 12953 gen_jmp(s, val);
99c475ab
FB
12954 break;
12955
12956 case 15:
296e5a0a
PM
12957 /* thumb_insn_is_16bit() ensures we can't get here for
12958 * a Thumb2 CPU, so this must be a thumb1 split BL/BLX.
12959 */
12960 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
12961
12962 if (insn & (1 << 11)) {
12963 /* 0b1111_1xxx_xxxx_xxxx : BL suffix */
12964 offset = ((insn & 0x7ff) << 1) | 1;
12965 tmp = load_reg(s, 14);
12966 tcg_gen_addi_i32(tmp, tmp, offset);
12967
12968 tmp2 = tcg_temp_new_i32();
12969 tcg_gen_movi_i32(tmp2, s->pc | 1);
12970 store_reg(s, 14, tmp2);
12971 gen_bx(s, tmp);
12972 } else {
12973 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix */
12974 uint32_t uoffset = ((int32_t)insn << 21) >> 9;
12975
12976 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + uoffset);
12977 }
9ee6e8bb 12978 break;
99c475ab
FB
12979 }
12980 return;
9ee6e8bb 12981illegal_op:
99c475ab 12982undef:
73710361
GB
12983 gen_exception_insn(s, 2, EXCP_UDEF, syn_uncategorized(),
12984 default_exception_el(s));
99c475ab
FB
12985}
12986
541ebcd4
PM
12987static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
12988{
12989 /* Return true if the insn at dc->pc might cross a page boundary.
12990 * (False positives are OK, false negatives are not.)
5b8d7289
PM
12991 * We know this is a Thumb insn, and our caller ensures we are
12992 * only called if dc->pc is less than 4 bytes from the page
12993 * boundary, so we cross the page if the first 16 bits indicate
12994 * that this is a 32 bit insn.
541ebcd4 12995 */
5b8d7289 12996 uint16_t insn = arm_lduw_code(env, s->pc, s->sctlr_b);
541ebcd4 12997
5b8d7289 12998 return !thumb_insn_is_16bit(s, insn);
541ebcd4
PM
12999}
13000
b542683d 13001static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
2c0262af 13002{
1d8a5535 13003 DisasContext *dc = container_of(dcbase, DisasContext, base);
9c489ea6 13004 CPUARMState *env = cs->env_ptr;
4e5e1215 13005 ARMCPU *cpu = arm_env_get_cpu(env);
3b46e624 13006
962fcbf2 13007 dc->isar = &cpu->isar;
dcba3a8d 13008 dc->pc = dc->base.pc_first;
e50e6a20 13009 dc->condjmp = 0;
3926cc84 13010
40f860cd 13011 dc->aarch64 = 0;
cef9ee70
SS
13012 /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
13013 * there is no secure EL1, so we route exceptions to EL3.
13014 */
13015 dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
13016 !arm_el_is_aa64(env, 3);
1d8a5535
LV
13017 dc->thumb = ARM_TBFLAG_THUMB(dc->base.tb->flags);
13018 dc->sctlr_b = ARM_TBFLAG_SCTLR_B(dc->base.tb->flags);
13019 dc->be_data = ARM_TBFLAG_BE_DATA(dc->base.tb->flags) ? MO_BE : MO_LE;
13020 dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(dc->base.tb->flags) & 0xf) << 1;
13021 dc->condexec_cond = ARM_TBFLAG_CONDEXEC(dc->base.tb->flags) >> 4;
13022 dc->mmu_idx = core_to_arm_mmu_idx(env, ARM_TBFLAG_MMUIDX(dc->base.tb->flags));
c1e37810 13023 dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
3926cc84 13024#if !defined(CONFIG_USER_ONLY)
c1e37810 13025 dc->user = (dc->current_el == 0);
3926cc84 13026#endif
1d8a5535
LV
13027 dc->ns = ARM_TBFLAG_NS(dc->base.tb->flags);
13028 dc->fp_excp_el = ARM_TBFLAG_FPEXC_EL(dc->base.tb->flags);
13029 dc->vfp_enabled = ARM_TBFLAG_VFPEN(dc->base.tb->flags);
13030 dc->vec_len = ARM_TBFLAG_VECLEN(dc->base.tb->flags);
13031 dc->vec_stride = ARM_TBFLAG_VECSTRIDE(dc->base.tb->flags);
13032 dc->c15_cpar = ARM_TBFLAG_XSCALE_CPAR(dc->base.tb->flags);
13033 dc->v7m_handler_mode = ARM_TBFLAG_HANDLER(dc->base.tb->flags);
fb602cb7
PM
13034 dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
13035 regime_is_secure(env, dc->mmu_idx);
4730fb85 13036 dc->v8m_stackcheck = ARM_TBFLAG_STACKCHECK(dc->base.tb->flags);
60322b39 13037 dc->cp_regs = cpu->cp_regs;
a984e42c 13038 dc->features = env->features;
40f860cd 13039
50225ad0
PM
13040 /* Single step state. The code-generation logic here is:
13041 * SS_ACTIVE == 0:
13042 * generate code with no special handling for single-stepping (except
13043 * that anything that can make us go to SS_ACTIVE == 1 must end the TB;
13044 * this happens anyway because those changes are all system register or
13045 * PSTATE writes).
13046 * SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
13047 * emit code for one insn
13048 * emit code to clear PSTATE.SS
13049 * emit code to generate software step exception for completed step
13050 * end TB (as usual for having generated an exception)
13051 * SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
13052 * emit code to generate a software step exception
13053 * end the TB
13054 */
1d8a5535
LV
13055 dc->ss_active = ARM_TBFLAG_SS_ACTIVE(dc->base.tb->flags);
13056 dc->pstate_ss = ARM_TBFLAG_PSTATE_SS(dc->base.tb->flags);
50225ad0
PM
13057 dc->is_ldex = false;
13058 dc->ss_same_el = false; /* Can't be true since EL_d must be AArch64 */
13059
bfe7ad5b 13060 dc->page_start = dc->base.pc_first & TARGET_PAGE_MASK;
1d8a5535 13061
f7708456
RH
13062 /* If architectural single step active, limit to 1. */
13063 if (is_singlestepping(dc)) {
b542683d 13064 dc->base.max_insns = 1;
f7708456
RH
13065 }
13066
d0264d86
RH
13067 /* ARM is a fixed-length ISA. Bound the number of insns to execute
13068 to those left on the page. */
13069 if (!dc->thumb) {
bfe7ad5b 13070 int bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
b542683d 13071 dc->base.max_insns = MIN(dc->base.max_insns, bound);
d0264d86
RH
13072 }
13073
a7812ae4
PB
13074 cpu_F0s = tcg_temp_new_i32();
13075 cpu_F1s = tcg_temp_new_i32();
13076 cpu_F0d = tcg_temp_new_i64();
13077 cpu_F1d = tcg_temp_new_i64();
ad69471c
PB
13078 cpu_V0 = cpu_F0d;
13079 cpu_V1 = cpu_F1d;
e677137d 13080 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
a7812ae4 13081 cpu_M0 = tcg_temp_new_i64();
1d8a5535
LV
13082}
13083
b1476854
LV
13084static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
13085{
13086 DisasContext *dc = container_of(dcbase, DisasContext, base);
13087
13088 /* A note on handling of the condexec (IT) bits:
13089 *
13090 * We want to avoid the overhead of having to write the updated condexec
13091 * bits back to the CPUARMState for every instruction in an IT block. So:
13092 * (1) if the condexec bits are not already zero then we write
13093 * zero back into the CPUARMState now. This avoids complications trying
13094 * to do it at the end of the block. (For example if we don't do this
13095 * it's hard to identify whether we can safely skip writing condexec
13096 * at the end of the TB, which we definitely want to do for the case
13097 * where a TB doesn't do anything with the IT state at all.)
13098 * (2) if we are going to leave the TB then we call gen_set_condexec()
13099 * which will write the correct value into CPUARMState if zero is wrong.
13100 * This is done both for leaving the TB at the end, and for leaving
13101 * it because of an exception we know will happen, which is done in
13102 * gen_exception_insn(). The latter is necessary because we need to
13103 * leave the TB with the PC/IT state just prior to execution of the
13104 * instruction which caused the exception.
13105 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
13106 * then the CPUARMState will be wrong and we need to reset it.
13107 * This is handled in the same way as restoration of the
13108 * PC in these situations; we save the value of the condexec bits
13109 * for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
13110 * then uses this to restore them after an exception.
13111 *
13112 * Note that there are no instructions which can read the condexec
13113 * bits, and none which can write non-static values to them, so
13114 * we don't need to care about whether CPUARMState is correct in the
13115 * middle of a TB.
13116 */
13117
13118 /* Reset the conditional execution bits immediately. This avoids
13119 complications trying to do it at the end of the block. */
13120 if (dc->condexec_mask || dc->condexec_cond) {
13121 TCGv_i32 tmp = tcg_temp_new_i32();
13122 tcg_gen_movi_i32(tmp, 0);
13123 store_cpu_field(tmp, condexec_bits);
13124 }
13125}
13126
f62bd897
LV
13127static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
13128{
13129 DisasContext *dc = container_of(dcbase, DisasContext, base);
13130
f62bd897
LV
13131 tcg_gen_insn_start(dc->pc,
13132 (dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
13133 0);
15fa08f8 13134 dc->insn_start = tcg_last_op();
f62bd897
LV
13135}
13136
a68956ad
LV
13137static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
13138 const CPUBreakpoint *bp)
13139{
13140 DisasContext *dc = container_of(dcbase, DisasContext, base);
13141
13142 if (bp->flags & BP_CPU) {
13143 gen_set_condexec(dc);
13144 gen_set_pc_im(dc, dc->pc);
13145 gen_helper_check_breakpoints(cpu_env);
13146 /* End the TB early; it's likely not going to be executed */
13147 dc->base.is_jmp = DISAS_TOO_MANY;
13148 } else {
13149 gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
13150 /* The address covered by the breakpoint must be
13151 included in [tb->pc, tb->pc + tb->size) in order
13152 to for it to be properly cleared -- thus we
13153 increment the PC here so that the logic setting
13154 tb->size below does the right thing. */
13155 /* TODO: Advance PC by correct instruction length to
13156 * avoid disassembler error messages */
13157 dc->pc += 2;
13158 dc->base.is_jmp = DISAS_NORETURN;
13159 }
13160
13161 return true;
13162}
13163
722ef0a5 13164static bool arm_pre_translate_insn(DisasContext *dc)
13189a90 13165{
13189a90
LV
13166#ifdef CONFIG_USER_ONLY
13167 /* Intercept jump to the magic kernel page. */
13168 if (dc->pc >= 0xffff0000) {
13169 /* We always get here via a jump, so know we are not in a
13170 conditional execution block. */
13171 gen_exception_internal(EXCP_KERNEL_TRAP);
13172 dc->base.is_jmp = DISAS_NORETURN;
722ef0a5 13173 return true;
13189a90
LV
13174 }
13175#endif
13176
13177 if (dc->ss_active && !dc->pstate_ss) {
13178 /* Singlestep state is Active-pending.
13179 * If we're in this state at the start of a TB then either
13180 * a) we just took an exception to an EL which is being debugged
13181 * and this is the first insn in the exception handler
13182 * b) debug exceptions were masked and we just unmasked them
13183 * without changing EL (eg by clearing PSTATE.D)
13184 * In either case we're going to take a swstep exception in the
13185 * "did not step an insn" case, and so the syndrome ISV and EX
13186 * bits should be zero.
13187 */
13188 assert(dc->base.num_insns == 1);
13189 gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
13190 default_exception_el(dc));
13191 dc->base.is_jmp = DISAS_NORETURN;
722ef0a5 13192 return true;
13189a90
LV
13193 }
13194
722ef0a5
RH
13195 return false;
13196}
13189a90 13197
d0264d86 13198static void arm_post_translate_insn(DisasContext *dc)
722ef0a5 13199{
13189a90
LV
13200 if (dc->condjmp && !dc->base.is_jmp) {
13201 gen_set_label(dc->condlabel);
13202 dc->condjmp = 0;
13203 }
13189a90 13204 dc->base.pc_next = dc->pc;
23169224 13205 translator_loop_temp_check(&dc->base);
13189a90
LV
13206}
13207
722ef0a5
RH
13208static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
13209{
13210 DisasContext *dc = container_of(dcbase, DisasContext, base);
13211 CPUARMState *env = cpu->env_ptr;
13212 unsigned int insn;
13213
13214 if (arm_pre_translate_insn(dc)) {
13215 return;
13216 }
13217
13218 insn = arm_ldl_code(env, dc->pc, dc->sctlr_b);
58803318 13219 dc->insn = insn;
722ef0a5
RH
13220 dc->pc += 4;
13221 disas_arm_insn(dc, insn);
13222
d0264d86
RH
13223 arm_post_translate_insn(dc);
13224
13225 /* ARM is a fixed-length ISA. We performed the cross-page check
13226 in init_disas_context by adjusting max_insns. */
722ef0a5
RH
13227}
13228
dcf14dfb
PM
13229static bool thumb_insn_is_unconditional(DisasContext *s, uint32_t insn)
13230{
13231 /* Return true if this Thumb insn is always unconditional,
13232 * even inside an IT block. This is true of only a very few
13233 * instructions: BKPT, HLT, and SG.
13234 *
13235 * A larger class of instructions are UNPREDICTABLE if used
13236 * inside an IT block; we do not need to detect those here, because
13237 * what we do by default (perform the cc check and update the IT
13238 * bits state machine) is a permitted CONSTRAINED UNPREDICTABLE
13239 * choice for those situations.
13240 *
13241 * insn is either a 16-bit or a 32-bit instruction; the two are
13242 * distinguishable because for the 16-bit case the top 16 bits
13243 * are zeroes, and that isn't a valid 32-bit encoding.
13244 */
13245 if ((insn & 0xffffff00) == 0xbe00) {
13246 /* BKPT */
13247 return true;
13248 }
13249
13250 if ((insn & 0xffffffc0) == 0xba80 && arm_dc_feature(s, ARM_FEATURE_V8) &&
13251 !arm_dc_feature(s, ARM_FEATURE_M)) {
13252 /* HLT: v8A only. This is unconditional even when it is going to
13253 * UNDEF; see the v8A ARM ARM DDI0487B.a H3.3.
13254 * For v7 cores this was a plain old undefined encoding and so
13255 * honours its cc check. (We might be using the encoding as
13256 * a semihosting trap, but we don't change the cc check behaviour
13257 * on that account, because a debugger connected to a real v7A
13258 * core and emulating semihosting traps by catching the UNDEF
13259 * exception would also only see cases where the cc check passed.
13260 * No guest code should be trying to do a HLT semihosting trap
13261 * in an IT block anyway.
13262 */
13263 return true;
13264 }
13265
13266 if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_V8) &&
13267 arm_dc_feature(s, ARM_FEATURE_M)) {
13268 /* SG: v8M only */
13269 return true;
13270 }
13271
13272 return false;
13273}
13274
722ef0a5
RH
13275static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
13276{
13277 DisasContext *dc = container_of(dcbase, DisasContext, base);
13278 CPUARMState *env = cpu->env_ptr;
296e5a0a
PM
13279 uint32_t insn;
13280 bool is_16bit;
722ef0a5
RH
13281
13282 if (arm_pre_translate_insn(dc)) {
13283 return;
13284 }
13285
296e5a0a
PM
13286 insn = arm_lduw_code(env, dc->pc, dc->sctlr_b);
13287 is_16bit = thumb_insn_is_16bit(dc, insn);
13288 dc->pc += 2;
13289 if (!is_16bit) {
13290 uint32_t insn2 = arm_lduw_code(env, dc->pc, dc->sctlr_b);
13291
13292 insn = insn << 16 | insn2;
13293 dc->pc += 2;
13294 }
58803318 13295 dc->insn = insn;
296e5a0a 13296
dcf14dfb 13297 if (dc->condexec_mask && !thumb_insn_is_unconditional(dc, insn)) {
296e5a0a
PM
13298 uint32_t cond = dc->condexec_cond;
13299
13300 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
c2d9644e 13301 arm_skip_unless(dc, cond);
296e5a0a
PM
13302 }
13303 }
13304
13305 if (is_16bit) {
13306 disas_thumb_insn(dc, insn);
13307 } else {
2eea841c 13308 disas_thumb2_insn(dc, insn);
296e5a0a 13309 }
722ef0a5
RH
13310
13311 /* Advance the Thumb condexec condition. */
13312 if (dc->condexec_mask) {
13313 dc->condexec_cond = ((dc->condexec_cond & 0xe) |
13314 ((dc->condexec_mask >> 4) & 1));
13315 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
13316 if (dc->condexec_mask == 0) {
13317 dc->condexec_cond = 0;
13318 }
13319 }
13320
d0264d86
RH
13321 arm_post_translate_insn(dc);
13322
13323 /* Thumb is a variable-length ISA. Stop translation when the next insn
13324 * will touch a new page. This ensures that prefetch aborts occur at
13325 * the right place.
13326 *
13327 * We want to stop the TB if the next insn starts in a new page,
13328 * or if it spans between this page and the next. This means that
13329 * if we're looking at the last halfword in the page we need to
13330 * see if it's a 16-bit Thumb insn (which will fit in this TB)
13331 * or a 32-bit Thumb insn (which won't).
13332 * This is to avoid generating a silly TB with a single 16-bit insn
13333 * in it at the end of this page (which would execute correctly
13334 * but isn't very efficient).
13335 */
13336 if (dc->base.is_jmp == DISAS_NEXT
bfe7ad5b
EC
13337 && (dc->pc - dc->page_start >= TARGET_PAGE_SIZE
13338 || (dc->pc - dc->page_start >= TARGET_PAGE_SIZE - 3
d0264d86
RH
13339 && insn_crosses_page(env, dc)))) {
13340 dc->base.is_jmp = DISAS_TOO_MANY;
13341 }
722ef0a5
RH
13342}
13343
70d3c035 13344static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
1d8a5535 13345{
70d3c035 13346 DisasContext *dc = container_of(dcbase, DisasContext, base);
2e70f6ef 13347
c5a49c63 13348 if (tb_cflags(dc->base.tb) & CF_LAST_IO && dc->condjmp) {
70d3c035
LV
13349 /* FIXME: This can theoretically happen with self-modifying code. */
13350 cpu_abort(cpu, "IO on conditional branch instruction");
2e70f6ef 13351 }
9ee6e8bb 13352
b5ff1b31 13353 /* At this stage dc->condjmp will only be set when the skipped
9ee6e8bb
PB
13354 instruction was a conditional branch or trap, and the PC has
13355 already been written. */
f021b2c4 13356 gen_set_condexec(dc);
dcba3a8d 13357 if (dc->base.is_jmp == DISAS_BX_EXCRET) {
3bb8a96f
PM
13358 /* Exception return branches need some special case code at the
13359 * end of the TB, which is complex enough that it has to
13360 * handle the single-step vs not and the condition-failed
13361 * insn codepath itself.
13362 */
13363 gen_bx_excret_final_code(dc);
13364 } else if (unlikely(is_singlestepping(dc))) {
7999a5c8 13365 /* Unconditional and "condition passed" instruction codepath. */
dcba3a8d 13366 switch (dc->base.is_jmp) {
7999a5c8 13367 case DISAS_SWI:
50225ad0 13368 gen_ss_advance(dc);
73710361
GB
13369 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
13370 default_exception_el(dc));
7999a5c8
SF
13371 break;
13372 case DISAS_HVC:
37e6456e 13373 gen_ss_advance(dc);
73710361 13374 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
7999a5c8
SF
13375 break;
13376 case DISAS_SMC:
37e6456e 13377 gen_ss_advance(dc);
73710361 13378 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
7999a5c8
SF
13379 break;
13380 case DISAS_NEXT:
a68956ad 13381 case DISAS_TOO_MANY:
7999a5c8
SF
13382 case DISAS_UPDATE:
13383 gen_set_pc_im(dc, dc->pc);
13384 /* fall through */
13385 default:
5425415e
PM
13386 /* FIXME: Single stepping a WFI insn will not halt the CPU. */
13387 gen_singlestep_exception(dc);
a0c231e6
RH
13388 break;
13389 case DISAS_NORETURN:
13390 break;
7999a5c8 13391 }
8aaca4c0 13392 } else {
9ee6e8bb
PB
13393 /* While branches must always occur at the end of an IT block,
13394 there are a few other things that can cause us to terminate
65626741 13395 the TB in the middle of an IT block:
9ee6e8bb
PB
13396 - Exception generating instructions (bkpt, swi, undefined).
13397 - Page boundaries.
13398 - Hardware watchpoints.
13399 Hardware breakpoints have already been handled and skip this code.
13400 */
dcba3a8d 13401 switch(dc->base.is_jmp) {
8aaca4c0 13402 case DISAS_NEXT:
a68956ad 13403 case DISAS_TOO_MANY:
6e256c93 13404 gen_goto_tb(dc, 1, dc->pc);
8aaca4c0 13405 break;
577bf808 13406 case DISAS_JUMP:
8a6b28c7
EC
13407 gen_goto_ptr();
13408 break;
e8d52302
AB
13409 case DISAS_UPDATE:
13410 gen_set_pc_im(dc, dc->pc);
13411 /* fall through */
577bf808 13412 default:
8aaca4c0 13413 /* indicate that the hash table must be used to find the next TB */
07ea28b4 13414 tcg_gen_exit_tb(NULL, 0);
8aaca4c0 13415 break;
a0c231e6 13416 case DISAS_NORETURN:
8aaca4c0
FB
13417 /* nothing more to generate */
13418 break;
9ee6e8bb 13419 case DISAS_WFI:
58803318
SS
13420 {
13421 TCGv_i32 tmp = tcg_const_i32((dc->thumb &&
13422 !(dc->insn & (1U << 31))) ? 2 : 4);
13423
13424 gen_helper_wfi(cpu_env, tmp);
13425 tcg_temp_free_i32(tmp);
84549b6d
PM
13426 /* The helper doesn't necessarily throw an exception, but we
13427 * must go back to the main loop to check for interrupts anyway.
13428 */
07ea28b4 13429 tcg_gen_exit_tb(NULL, 0);
9ee6e8bb 13430 break;
58803318 13431 }
72c1d3af
PM
13432 case DISAS_WFE:
13433 gen_helper_wfe(cpu_env);
13434 break;
c87e5a61
PM
13435 case DISAS_YIELD:
13436 gen_helper_yield(cpu_env);
13437 break;
9ee6e8bb 13438 case DISAS_SWI:
73710361
GB
13439 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
13440 default_exception_el(dc));
9ee6e8bb 13441 break;
37e6456e 13442 case DISAS_HVC:
73710361 13443 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
37e6456e
PM
13444 break;
13445 case DISAS_SMC:
73710361 13446 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
37e6456e 13447 break;
8aaca4c0 13448 }
f021b2c4
PM
13449 }
13450
13451 if (dc->condjmp) {
13452 /* "Condition failed" instruction codepath for the branch/trap insn */
13453 gen_set_label(dc->condlabel);
13454 gen_set_condexec(dc);
b636649f 13455 if (unlikely(is_singlestepping(dc))) {
f021b2c4
PM
13456 gen_set_pc_im(dc, dc->pc);
13457 gen_singlestep_exception(dc);
13458 } else {
6e256c93 13459 gen_goto_tb(dc, 1, dc->pc);
e50e6a20 13460 }
2c0262af 13461 }
23169224
LV
13462
13463 /* Functions above can change dc->pc, so re-align db->pc_next */
13464 dc->base.pc_next = dc->pc;
70d3c035
LV
13465}
13466
4013f7fc
LV
13467static void arm_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
13468{
13469 DisasContext *dc = container_of(dcbase, DisasContext, base);
13470
13471 qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
1d48474d 13472 log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
4013f7fc
LV
13473}
13474
23169224
LV
13475static const TranslatorOps arm_translator_ops = {
13476 .init_disas_context = arm_tr_init_disas_context,
13477 .tb_start = arm_tr_tb_start,
13478 .insn_start = arm_tr_insn_start,
13479 .breakpoint_check = arm_tr_breakpoint_check,
13480 .translate_insn = arm_tr_translate_insn,
13481 .tb_stop = arm_tr_tb_stop,
13482 .disas_log = arm_tr_disas_log,
13483};
13484
722ef0a5
RH
13485static const TranslatorOps thumb_translator_ops = {
13486 .init_disas_context = arm_tr_init_disas_context,
13487 .tb_start = arm_tr_tb_start,
13488 .insn_start = arm_tr_insn_start,
13489 .breakpoint_check = arm_tr_breakpoint_check,
13490 .translate_insn = thumb_tr_translate_insn,
13491 .tb_stop = arm_tr_tb_stop,
13492 .disas_log = arm_tr_disas_log,
13493};
13494
70d3c035 13495/* generate intermediate code for basic block 'tb'. */
23169224 13496void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
70d3c035 13497{
23169224
LV
13498 DisasContext dc;
13499 const TranslatorOps *ops = &arm_translator_ops;
70d3c035 13500
722ef0a5
RH
13501 if (ARM_TBFLAG_THUMB(tb->flags)) {
13502 ops = &thumb_translator_ops;
13503 }
23169224 13504#ifdef TARGET_AARCH64
70d3c035 13505 if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
23169224 13506 ops = &aarch64_translator_ops;
2c0262af
FB
13507 }
13508#endif
23169224
LV
13509
13510 translator_loop(ops, &dc.base, cpu, tb);
2c0262af
FB
13511}
13512
878096ee
AF
13513void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
13514 int flags)
2c0262af 13515{
878096ee
AF
13516 ARMCPU *cpu = ARM_CPU(cs);
13517 CPUARMState *env = &cpu->env;
2c0262af
FB
13518 int i;
13519
17731115
PM
13520 if (is_a64(env)) {
13521 aarch64_cpu_dump_state(cs, f, cpu_fprintf, flags);
13522 return;
13523 }
13524
2c0262af 13525 for(i=0;i<16;i++) {
7fe48483 13526 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
2c0262af 13527 if ((i % 4) == 3)
7fe48483 13528 cpu_fprintf(f, "\n");
2c0262af 13529 else
7fe48483 13530 cpu_fprintf(f, " ");
2c0262af 13531 }
06e5cf7a 13532
5b906f35
PM
13533 if (arm_feature(env, ARM_FEATURE_M)) {
13534 uint32_t xpsr = xpsr_read(env);
13535 const char *mode;
1e577cc7
PM
13536 const char *ns_status = "";
13537
13538 if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
13539 ns_status = env->v7m.secure ? "S " : "NS ";
13540 }
5b906f35
PM
13541
13542 if (xpsr & XPSR_EXCP) {
13543 mode = "handler";
13544 } else {
8bfc26ea 13545 if (env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_NPRIV_MASK) {
5b906f35
PM
13546 mode = "unpriv-thread";
13547 } else {
13548 mode = "priv-thread";
13549 }
13550 }
13551
1e577cc7 13552 cpu_fprintf(f, "XPSR=%08x %c%c%c%c %c %s%s\n",
5b906f35
PM
13553 xpsr,
13554 xpsr & XPSR_N ? 'N' : '-',
13555 xpsr & XPSR_Z ? 'Z' : '-',
13556 xpsr & XPSR_C ? 'C' : '-',
13557 xpsr & XPSR_V ? 'V' : '-',
13558 xpsr & XPSR_T ? 'T' : 'A',
1e577cc7 13559 ns_status,
5b906f35 13560 mode);
06e5cf7a 13561 } else {
5b906f35
PM
13562 uint32_t psr = cpsr_read(env);
13563 const char *ns_status = "";
13564
13565 if (arm_feature(env, ARM_FEATURE_EL3) &&
13566 (psr & CPSR_M) != ARM_CPU_MODE_MON) {
13567 ns_status = env->cp15.scr_el3 & SCR_NS ? "NS " : "S ";
13568 }
13569
13570 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%s%d\n",
13571 psr,
13572 psr & CPSR_N ? 'N' : '-',
13573 psr & CPSR_Z ? 'Z' : '-',
13574 psr & CPSR_C ? 'C' : '-',
13575 psr & CPSR_V ? 'V' : '-',
13576 psr & CPSR_T ? 'T' : 'A',
13577 ns_status,
81e37284 13578 aarch32_mode_name(psr), (psr & 0x10) ? 32 : 26);
5b906f35 13579 }
b7bcbe95 13580
f2617cfc
PM
13581 if (flags & CPU_DUMP_FPU) {
13582 int numvfpregs = 0;
13583 if (arm_feature(env, ARM_FEATURE_VFP)) {
13584 numvfpregs += 16;
13585 }
13586 if (arm_feature(env, ARM_FEATURE_VFP3)) {
13587 numvfpregs += 16;
13588 }
13589 for (i = 0; i < numvfpregs; i++) {
9a2b5256 13590 uint64_t v = *aa32_vfp_dreg(env, i);
f2617cfc
PM
13591 cpu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
13592 i * 2, (uint32_t)v,
13593 i * 2 + 1, (uint32_t)(v >> 32),
13594 i, v);
13595 }
13596 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
b7bcbe95 13597 }
2c0262af 13598}
a6b025d3 13599
bad729e2
RH
13600void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
13601 target_ulong *data)
d2856f1a 13602{
3926cc84 13603 if (is_a64(env)) {
bad729e2 13604 env->pc = data[0];
40f860cd 13605 env->condexec_bits = 0;
aaa1f954 13606 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
3926cc84 13607 } else {
bad729e2
RH
13608 env->regs[15] = data[0];
13609 env->condexec_bits = data[1];
aaa1f954 13610 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
3926cc84 13611 }
d2856f1a 13612}