]> git.proxmox.com Git - mirror_qemu.git/blame - target/arm/translate.c
Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20190903' into staging
[mirror_qemu.git] / target / arm / translate.c
CommitLineData
2c0262af
FB
1/*
2 * ARM translation
5fafdf24 3 *
2c0262af 4 * Copyright (c) 2003 Fabrice Bellard
9ee6e8bb 5 * Copyright (c) 2005-2007 CodeSourcery
18c9b560 6 * Copyright (c) 2007 OpenedHand, Ltd.
2c0262af
FB
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
8167ee88 19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
2c0262af 20 */
74c21bd0 21#include "qemu/osdep.h"
2c0262af
FB
22
23#include "cpu.h"
ccd38087 24#include "internals.h"
76cad711 25#include "disas/disas.h"
63c91552 26#include "exec/exec-all.h"
57fec1fe 27#include "tcg-op.h"
36a71934 28#include "tcg-op-gvec.h"
1de7afc9 29#include "qemu/log.h"
534df156 30#include "qemu/bitops.h"
1d854765 31#include "arm_ldst.h"
f1672e6f 32#include "hw/semihosting/semihost.h"
1497c961 33
2ef6175a
RH
34#include "exec/helper-proto.h"
35#include "exec/helper-gen.h"
2c0262af 36
a7e30d84 37#include "trace-tcg.h"
508127e2 38#include "exec/log.h"
a7e30d84
LV
39
40
2b51668f
PM
41#define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T)
42#define ENABLE_ARCH_5 arm_dc_feature(s, ARM_FEATURE_V5)
be5e7a76 43/* currently all emulated v5 cores are also v5TE, so don't bother */
2b51668f 44#define ENABLE_ARCH_5TE arm_dc_feature(s, ARM_FEATURE_V5)
09cbd501 45#define ENABLE_ARCH_5J dc_isar_feature(jazelle, s)
2b51668f
PM
46#define ENABLE_ARCH_6 arm_dc_feature(s, ARM_FEATURE_V6)
47#define ENABLE_ARCH_6K arm_dc_feature(s, ARM_FEATURE_V6K)
48#define ENABLE_ARCH_6T2 arm_dc_feature(s, ARM_FEATURE_THUMB2)
49#define ENABLE_ARCH_7 arm_dc_feature(s, ARM_FEATURE_V7)
50#define ENABLE_ARCH_8 arm_dc_feature(s, ARM_FEATURE_V8)
b5ff1b31 51
86753403 52#define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
b5ff1b31 53
f570c61e 54#include "translate.h"
e12ce78d 55
b5ff1b31
FB
56#if defined(CONFIG_USER_ONLY)
57#define IS_USER(s) 1
58#else
59#define IS_USER(s) (s->user)
60#endif
61
ad69471c 62/* We reuse the same 64-bit temporaries for efficiency. */
a7812ae4 63static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
155c3eac 64static TCGv_i32 cpu_R[16];
78bcaa3e
RH
65TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
66TCGv_i64 cpu_exclusive_addr;
67TCGv_i64 cpu_exclusive_val;
ad69471c 68
022c62cb 69#include "exec/gen-icount.h"
2e70f6ef 70
308e5636 71static const char * const regnames[] =
155c3eac
FN
72 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
73 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
74
61adacc8
RH
75/* Function prototypes for gen_ functions calling Neon helpers. */
76typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32,
77 TCGv_i32, TCGv_i32);
c253dd78
PM
78/* Function prototypes for gen_ functions for fix point conversions */
79typedef void VFPGenFixPointFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
61adacc8 80
b26eefb6
PB
81/* initialize TCG globals. */
82void arm_translate_init(void)
83{
155c3eac
FN
84 int i;
85
155c3eac 86 for (i = 0; i < 16; i++) {
e1ccc054 87 cpu_R[i] = tcg_global_mem_new_i32(cpu_env,
0ecb72a5 88 offsetof(CPUARMState, regs[i]),
155c3eac
FN
89 regnames[i]);
90 }
e1ccc054
RH
91 cpu_CF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, CF), "CF");
92 cpu_NF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, NF), "NF");
93 cpu_VF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, VF), "VF");
94 cpu_ZF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, ZF), "ZF");
66c374de 95
e1ccc054 96 cpu_exclusive_addr = tcg_global_mem_new_i64(cpu_env,
0ecb72a5 97 offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
e1ccc054 98 cpu_exclusive_val = tcg_global_mem_new_i64(cpu_env,
0ecb72a5 99 offsetof(CPUARMState, exclusive_val), "exclusive_val");
155c3eac 100
14ade10f 101 a64_translate_init();
b26eefb6
PB
102}
103
9bb6558a
PM
104/* Flags for the disas_set_da_iss info argument:
105 * lower bits hold the Rt register number, higher bits are flags.
106 */
107typedef enum ISSInfo {
108 ISSNone = 0,
109 ISSRegMask = 0x1f,
110 ISSInvalid = (1 << 5),
111 ISSIsAcqRel = (1 << 6),
112 ISSIsWrite = (1 << 7),
113 ISSIs16Bit = (1 << 8),
114} ISSInfo;
115
116/* Save the syndrome information for a Data Abort */
14776ab5 117static void disas_set_da_iss(DisasContext *s, MemOp memop, ISSInfo issinfo)
9bb6558a
PM
118{
119 uint32_t syn;
120 int sas = memop & MO_SIZE;
121 bool sse = memop & MO_SIGN;
122 bool is_acqrel = issinfo & ISSIsAcqRel;
123 bool is_write = issinfo & ISSIsWrite;
124 bool is_16bit = issinfo & ISSIs16Bit;
125 int srt = issinfo & ISSRegMask;
126
127 if (issinfo & ISSInvalid) {
128 /* Some callsites want to conditionally provide ISS info,
129 * eg "only if this was not a writeback"
130 */
131 return;
132 }
133
134 if (srt == 15) {
135 /* For AArch32, insns where the src/dest is R15 never generate
136 * ISS information. Catching that here saves checking at all
137 * the call sites.
138 */
139 return;
140 }
141
142 syn = syn_data_abort_with_iss(0, sas, sse, srt, 0, is_acqrel,
143 0, 0, 0, is_write, 0, is_16bit);
144 disas_set_insn_syndrome(s, syn);
145}
146
8bd5c820 147static inline int get_a32_user_mem_index(DisasContext *s)
579d21cc 148{
8bd5c820 149 /* Return the core mmu_idx to use for A32/T32 "unprivileged load/store"
579d21cc
PM
150 * insns:
151 * if PL2, UNPREDICTABLE (we choose to implement as if PL0)
152 * otherwise, access as if at PL0.
153 */
154 switch (s->mmu_idx) {
155 case ARMMMUIdx_S1E2: /* this one is UNPREDICTABLE */
156 case ARMMMUIdx_S12NSE0:
157 case ARMMMUIdx_S12NSE1:
8bd5c820 158 return arm_to_core_mmu_idx(ARMMMUIdx_S12NSE0);
579d21cc
PM
159 case ARMMMUIdx_S1E3:
160 case ARMMMUIdx_S1SE0:
161 case ARMMMUIdx_S1SE1:
8bd5c820 162 return arm_to_core_mmu_idx(ARMMMUIdx_S1SE0);
e7b921c2
PM
163 case ARMMMUIdx_MUser:
164 case ARMMMUIdx_MPriv:
165 return arm_to_core_mmu_idx(ARMMMUIdx_MUser);
62593718
PM
166 case ARMMMUIdx_MUserNegPri:
167 case ARMMMUIdx_MPrivNegPri:
168 return arm_to_core_mmu_idx(ARMMMUIdx_MUserNegPri);
b9f587d6
PM
169 case ARMMMUIdx_MSUser:
170 case ARMMMUIdx_MSPriv:
b9f587d6 171 return arm_to_core_mmu_idx(ARMMMUIdx_MSUser);
62593718
PM
172 case ARMMMUIdx_MSUserNegPri:
173 case ARMMMUIdx_MSPrivNegPri:
174 return arm_to_core_mmu_idx(ARMMMUIdx_MSUserNegPri);
579d21cc
PM
175 case ARMMMUIdx_S2NS:
176 default:
177 g_assert_not_reached();
178 }
179}
180
39d5492a 181static inline TCGv_i32 load_cpu_offset(int offset)
d9ba4830 182{
39d5492a 183 TCGv_i32 tmp = tcg_temp_new_i32();
d9ba4830
PB
184 tcg_gen_ld_i32(tmp, cpu_env, offset);
185 return tmp;
186}
187
0ecb72a5 188#define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
d9ba4830 189
39d5492a 190static inline void store_cpu_offset(TCGv_i32 var, int offset)
d9ba4830
PB
191{
192 tcg_gen_st_i32(var, cpu_env, offset);
7d1b0095 193 tcg_temp_free_i32(var);
d9ba4830
PB
194}
195
196#define store_cpu_field(var, name) \
0ecb72a5 197 store_cpu_offset(var, offsetof(CPUARMState, name))
d9ba4830 198
fdbcf632
RH
199/* The architectural value of PC. */
200static uint32_t read_pc(DisasContext *s)
201{
202 return s->pc_curr + (s->thumb ? 4 : 8);
203}
204
b26eefb6 205/* Set a variable to the value of a CPU register. */
39d5492a 206static void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
b26eefb6
PB
207{
208 if (reg == 15) {
fdbcf632 209 tcg_gen_movi_i32(var, read_pc(s));
b26eefb6 210 } else {
155c3eac 211 tcg_gen_mov_i32(var, cpu_R[reg]);
b26eefb6
PB
212 }
213}
214
215/* Create a new temporary and set it to the value of a CPU register. */
39d5492a 216static inline TCGv_i32 load_reg(DisasContext *s, int reg)
b26eefb6 217{
39d5492a 218 TCGv_i32 tmp = tcg_temp_new_i32();
b26eefb6
PB
219 load_reg_var(s, tmp, reg);
220 return tmp;
221}
222
16e0d823
RH
223/*
224 * Create a new temp, REG + OFS, except PC is ALIGN(PC, 4).
225 * This is used for load/store for which use of PC implies (literal),
226 * or ADD that implies ADR.
227 */
228static TCGv_i32 add_reg_for_lit(DisasContext *s, int reg, int ofs)
229{
230 TCGv_i32 tmp = tcg_temp_new_i32();
231
232 if (reg == 15) {
233 tcg_gen_movi_i32(tmp, (read_pc(s) & ~3) + ofs);
234 } else {
235 tcg_gen_addi_i32(tmp, cpu_R[reg], ofs);
236 }
237 return tmp;
238}
239
b26eefb6
PB
240/* Set a CPU register. The source must be a temporary and will be
241 marked as dead. */
39d5492a 242static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
b26eefb6
PB
243{
244 if (reg == 15) {
9b6a3ea7
PM
245 /* In Thumb mode, we must ignore bit 0.
246 * In ARM mode, for ARMv4 and ARMv5, it is UNPREDICTABLE if bits [1:0]
247 * are not 0b00, but for ARMv6 and above, we must ignore bits [1:0].
248 * We choose to ignore [1:0] in ARM mode for all architecture versions.
249 */
250 tcg_gen_andi_i32(var, var, s->thumb ? ~1 : ~3);
dcba3a8d 251 s->base.is_jmp = DISAS_JUMP;
b26eefb6 252 }
155c3eac 253 tcg_gen_mov_i32(cpu_R[reg], var);
7d1b0095 254 tcg_temp_free_i32(var);
b26eefb6
PB
255}
256
55203189
PM
257/*
258 * Variant of store_reg which applies v8M stack-limit checks before updating
259 * SP. If the check fails this will result in an exception being taken.
260 * We disable the stack checks for CONFIG_USER_ONLY because we have
261 * no idea what the stack limits should be in that case.
262 * If stack checking is not being done this just acts like store_reg().
263 */
264static void store_sp_checked(DisasContext *s, TCGv_i32 var)
265{
266#ifndef CONFIG_USER_ONLY
267 if (s->v8m_stackcheck) {
268 gen_helper_v8m_stackcheck(cpu_env, var);
269 }
270#endif
271 store_reg(s, 13, var);
272}
273
b26eefb6 274/* Value extensions. */
86831435
PB
275#define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
276#define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
b26eefb6
PB
277#define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
278#define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
279
1497c961
PB
280#define gen_sxtb16(var) gen_helper_sxtb16(var, var)
281#define gen_uxtb16(var) gen_helper_uxtb16(var, var)
8f01245e 282
b26eefb6 283
39d5492a 284static inline void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
b75263d6 285{
39d5492a 286 TCGv_i32 tmp_mask = tcg_const_i32(mask);
1ce94f81 287 gen_helper_cpsr_write(cpu_env, var, tmp_mask);
b75263d6
JR
288 tcg_temp_free_i32(tmp_mask);
289}
d9ba4830
PB
290/* Set NZCV flags from the high 4 bits of var. */
291#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
292
d4a2dc67 293static void gen_exception_internal(int excp)
d9ba4830 294{
d4a2dc67
PM
295 TCGv_i32 tcg_excp = tcg_const_i32(excp);
296
297 assert(excp_is_internal(excp));
298 gen_helper_exception_internal(cpu_env, tcg_excp);
299 tcg_temp_free_i32(tcg_excp);
300}
301
50225ad0
PM
302static void gen_step_complete_exception(DisasContext *s)
303{
304 /* We just completed step of an insn. Move from Active-not-pending
305 * to Active-pending, and then also take the swstep exception.
306 * This corresponds to making the (IMPDEF) choice to prioritize
307 * swstep exceptions over asynchronous exceptions taken to an exception
308 * level where debug is disabled. This choice has the advantage that
309 * we do not need to maintain internal state corresponding to the
310 * ISV/EX syndrome bits between completion of the step and generation
311 * of the exception, and our syndrome information is always correct.
312 */
313 gen_ss_advance(s);
c1d5f50f 314 gen_swstep_exception(s, 1, s->is_ldex);
dcba3a8d 315 s->base.is_jmp = DISAS_NORETURN;
50225ad0
PM
316}
317
5425415e
PM
318static void gen_singlestep_exception(DisasContext *s)
319{
320 /* Generate the right kind of exception for singlestep, which is
321 * either the architectural singlestep or EXCP_DEBUG for QEMU's
322 * gdb singlestepping.
323 */
324 if (s->ss_active) {
325 gen_step_complete_exception(s);
326 } else {
327 gen_exception_internal(EXCP_DEBUG);
328 }
329}
330
b636649f
PM
331static inline bool is_singlestepping(DisasContext *s)
332{
333 /* Return true if we are singlestepping either because of
334 * architectural singlestep or QEMU gdbstub singlestep. This does
335 * not include the command line '-singlestep' mode which is rather
336 * misnamed as it only means "one instruction per TB" and doesn't
337 * affect the code we generate.
338 */
dcba3a8d 339 return s->base.singlestep_enabled || s->ss_active;
b636649f
PM
340}
341
39d5492a 342static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
3670669c 343{
39d5492a
PM
344 TCGv_i32 tmp1 = tcg_temp_new_i32();
345 TCGv_i32 tmp2 = tcg_temp_new_i32();
22478e79
AZ
346 tcg_gen_ext16s_i32(tmp1, a);
347 tcg_gen_ext16s_i32(tmp2, b);
3670669c 348 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
7d1b0095 349 tcg_temp_free_i32(tmp2);
3670669c
PB
350 tcg_gen_sari_i32(a, a, 16);
351 tcg_gen_sari_i32(b, b, 16);
352 tcg_gen_mul_i32(b, b, a);
353 tcg_gen_mov_i32(a, tmp1);
7d1b0095 354 tcg_temp_free_i32(tmp1);
3670669c
PB
355}
356
357/* Byteswap each halfword. */
39d5492a 358static void gen_rev16(TCGv_i32 var)
3670669c 359{
39d5492a 360 TCGv_i32 tmp = tcg_temp_new_i32();
68cedf73 361 TCGv_i32 mask = tcg_const_i32(0x00ff00ff);
3670669c 362 tcg_gen_shri_i32(tmp, var, 8);
68cedf73
AJ
363 tcg_gen_and_i32(tmp, tmp, mask);
364 tcg_gen_and_i32(var, var, mask);
3670669c 365 tcg_gen_shli_i32(var, var, 8);
3670669c 366 tcg_gen_or_i32(var, var, tmp);
68cedf73 367 tcg_temp_free_i32(mask);
7d1b0095 368 tcg_temp_free_i32(tmp);
3670669c
PB
369}
370
371/* Byteswap low halfword and sign extend. */
39d5492a 372static void gen_revsh(TCGv_i32 var)
3670669c 373{
1a855029
AJ
374 tcg_gen_ext16u_i32(var, var);
375 tcg_gen_bswap16_i32(var, var);
376 tcg_gen_ext16s_i32(var, var);
3670669c
PB
377}
378
5e3f878a 379/* 32x32->64 multiply. Marks inputs as dead. */
39d5492a 380static TCGv_i64 gen_mulu_i64_i32(TCGv_i32 a, TCGv_i32 b)
5e3f878a 381{
39d5492a
PM
382 TCGv_i32 lo = tcg_temp_new_i32();
383 TCGv_i32 hi = tcg_temp_new_i32();
831d7fe8 384 TCGv_i64 ret;
5e3f878a 385
831d7fe8 386 tcg_gen_mulu2_i32(lo, hi, a, b);
7d1b0095 387 tcg_temp_free_i32(a);
7d1b0095 388 tcg_temp_free_i32(b);
831d7fe8
RH
389
390 ret = tcg_temp_new_i64();
391 tcg_gen_concat_i32_i64(ret, lo, hi);
39d5492a
PM
392 tcg_temp_free_i32(lo);
393 tcg_temp_free_i32(hi);
831d7fe8
RH
394
395 return ret;
5e3f878a
PB
396}
397
39d5492a 398static TCGv_i64 gen_muls_i64_i32(TCGv_i32 a, TCGv_i32 b)
5e3f878a 399{
39d5492a
PM
400 TCGv_i32 lo = tcg_temp_new_i32();
401 TCGv_i32 hi = tcg_temp_new_i32();
831d7fe8 402 TCGv_i64 ret;
5e3f878a 403
831d7fe8 404 tcg_gen_muls2_i32(lo, hi, a, b);
7d1b0095 405 tcg_temp_free_i32(a);
7d1b0095 406 tcg_temp_free_i32(b);
831d7fe8
RH
407
408 ret = tcg_temp_new_i64();
409 tcg_gen_concat_i32_i64(ret, lo, hi);
39d5492a
PM
410 tcg_temp_free_i32(lo);
411 tcg_temp_free_i32(hi);
831d7fe8
RH
412
413 return ret;
5e3f878a
PB
414}
415
8f01245e 416/* Swap low and high halfwords. */
39d5492a 417static void gen_swap_half(TCGv_i32 var)
8f01245e 418{
adefba76 419 tcg_gen_rotri_i32(var, var, 16);
8f01245e
PB
420}
421
b26eefb6
PB
422/* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
423 tmp = (t0 ^ t1) & 0x8000;
424 t0 &= ~0x8000;
425 t1 &= ~0x8000;
426 t0 = (t0 + t1) ^ tmp;
427 */
428
39d5492a 429static void gen_add16(TCGv_i32 t0, TCGv_i32 t1)
b26eefb6 430{
39d5492a 431 TCGv_i32 tmp = tcg_temp_new_i32();
b26eefb6
PB
432 tcg_gen_xor_i32(tmp, t0, t1);
433 tcg_gen_andi_i32(tmp, tmp, 0x8000);
434 tcg_gen_andi_i32(t0, t0, ~0x8000);
435 tcg_gen_andi_i32(t1, t1, ~0x8000);
436 tcg_gen_add_i32(t0, t0, t1);
437 tcg_gen_xor_i32(t0, t0, tmp);
7d1b0095
PM
438 tcg_temp_free_i32(tmp);
439 tcg_temp_free_i32(t1);
b26eefb6
PB
440}
441
442/* Set CF to the top bit of var. */
39d5492a 443static void gen_set_CF_bit31(TCGv_i32 var)
b26eefb6 444{
66c374de 445 tcg_gen_shri_i32(cpu_CF, var, 31);
b26eefb6
PB
446}
447
448/* Set N and Z flags from var. */
39d5492a 449static inline void gen_logic_CC(TCGv_i32 var)
b26eefb6 450{
66c374de
AJ
451 tcg_gen_mov_i32(cpu_NF, var);
452 tcg_gen_mov_i32(cpu_ZF, var);
b26eefb6
PB
453}
454
455/* T0 += T1 + CF. */
39d5492a 456static void gen_adc(TCGv_i32 t0, TCGv_i32 t1)
b26eefb6 457{
396e467c 458 tcg_gen_add_i32(t0, t0, t1);
66c374de 459 tcg_gen_add_i32(t0, t0, cpu_CF);
b26eefb6
PB
460}
461
e9bb4aa9 462/* dest = T0 + T1 + CF. */
39d5492a 463static void gen_add_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
e9bb4aa9 464{
e9bb4aa9 465 tcg_gen_add_i32(dest, t0, t1);
66c374de 466 tcg_gen_add_i32(dest, dest, cpu_CF);
e9bb4aa9
JR
467}
468
3670669c 469/* dest = T0 - T1 + CF - 1. */
39d5492a 470static void gen_sub_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
3670669c 471{
3670669c 472 tcg_gen_sub_i32(dest, t0, t1);
66c374de 473 tcg_gen_add_i32(dest, dest, cpu_CF);
3670669c 474 tcg_gen_subi_i32(dest, dest, 1);
3670669c
PB
475}
476
72485ec4 477/* dest = T0 + T1. Compute C, N, V and Z flags */
39d5492a 478static void gen_add_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
72485ec4 479{
39d5492a 480 TCGv_i32 tmp = tcg_temp_new_i32();
e3482cb8
RH
481 tcg_gen_movi_i32(tmp, 0);
482 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, t1, tmp);
72485ec4 483 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
72485ec4 484 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
72485ec4
AJ
485 tcg_gen_xor_i32(tmp, t0, t1);
486 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
487 tcg_temp_free_i32(tmp);
488 tcg_gen_mov_i32(dest, cpu_NF);
489}
490
49b4c31e 491/* dest = T0 + T1 + CF. Compute C, N, V and Z flags */
39d5492a 492static void gen_adc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
49b4c31e 493{
39d5492a 494 TCGv_i32 tmp = tcg_temp_new_i32();
49b4c31e
RH
495 if (TCG_TARGET_HAS_add2_i32) {
496 tcg_gen_movi_i32(tmp, 0);
497 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp);
8c3ac601 498 tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1, tmp);
49b4c31e
RH
499 } else {
500 TCGv_i64 q0 = tcg_temp_new_i64();
501 TCGv_i64 q1 = tcg_temp_new_i64();
502 tcg_gen_extu_i32_i64(q0, t0);
503 tcg_gen_extu_i32_i64(q1, t1);
504 tcg_gen_add_i64(q0, q0, q1);
505 tcg_gen_extu_i32_i64(q1, cpu_CF);
506 tcg_gen_add_i64(q0, q0, q1);
507 tcg_gen_extr_i64_i32(cpu_NF, cpu_CF, q0);
508 tcg_temp_free_i64(q0);
509 tcg_temp_free_i64(q1);
510 }
511 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
512 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
513 tcg_gen_xor_i32(tmp, t0, t1);
514 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
515 tcg_temp_free_i32(tmp);
516 tcg_gen_mov_i32(dest, cpu_NF);
517}
518
72485ec4 519/* dest = T0 - T1. Compute C, N, V and Z flags */
39d5492a 520static void gen_sub_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
72485ec4 521{
39d5492a 522 TCGv_i32 tmp;
72485ec4
AJ
523 tcg_gen_sub_i32(cpu_NF, t0, t1);
524 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
525 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0, t1);
526 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
527 tmp = tcg_temp_new_i32();
528 tcg_gen_xor_i32(tmp, t0, t1);
529 tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
530 tcg_temp_free_i32(tmp);
531 tcg_gen_mov_i32(dest, cpu_NF);
532}
533
e77f0832 534/* dest = T0 + ~T1 + CF. Compute C, N, V and Z flags */
39d5492a 535static void gen_sbc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
2de68a49 536{
39d5492a 537 TCGv_i32 tmp = tcg_temp_new_i32();
e77f0832
RH
538 tcg_gen_not_i32(tmp, t1);
539 gen_adc_CC(dest, t0, tmp);
39d5492a 540 tcg_temp_free_i32(tmp);
2de68a49
RH
541}
542
365af80e 543#define GEN_SHIFT(name) \
39d5492a 544static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \
365af80e 545{ \
39d5492a 546 TCGv_i32 tmp1, tmp2, tmp3; \
365af80e
AJ
547 tmp1 = tcg_temp_new_i32(); \
548 tcg_gen_andi_i32(tmp1, t1, 0xff); \
549 tmp2 = tcg_const_i32(0); \
550 tmp3 = tcg_const_i32(0x1f); \
551 tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
552 tcg_temp_free_i32(tmp3); \
553 tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
554 tcg_gen_##name##_i32(dest, tmp2, tmp1); \
555 tcg_temp_free_i32(tmp2); \
556 tcg_temp_free_i32(tmp1); \
557}
558GEN_SHIFT(shl)
559GEN_SHIFT(shr)
560#undef GEN_SHIFT
561
39d5492a 562static void gen_sar(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
365af80e 563{
39d5492a 564 TCGv_i32 tmp1, tmp2;
365af80e
AJ
565 tmp1 = tcg_temp_new_i32();
566 tcg_gen_andi_i32(tmp1, t1, 0xff);
567 tmp2 = tcg_const_i32(0x1f);
568 tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1);
569 tcg_temp_free_i32(tmp2);
570 tcg_gen_sar_i32(dest, t0, tmp1);
571 tcg_temp_free_i32(tmp1);
572}
573
39d5492a 574static void shifter_out_im(TCGv_i32 var, int shift)
b26eefb6 575{
191f4bfe 576 tcg_gen_extract_i32(cpu_CF, var, shift, 1);
9a119ff6 577}
b26eefb6 578
9a119ff6 579/* Shift by immediate. Includes special handling for shift == 0. */
39d5492a
PM
580static inline void gen_arm_shift_im(TCGv_i32 var, int shiftop,
581 int shift, int flags)
9a119ff6
PB
582{
583 switch (shiftop) {
584 case 0: /* LSL */
585 if (shift != 0) {
586 if (flags)
587 shifter_out_im(var, 32 - shift);
588 tcg_gen_shli_i32(var, var, shift);
589 }
590 break;
591 case 1: /* LSR */
592 if (shift == 0) {
593 if (flags) {
66c374de 594 tcg_gen_shri_i32(cpu_CF, var, 31);
9a119ff6
PB
595 }
596 tcg_gen_movi_i32(var, 0);
597 } else {
598 if (flags)
599 shifter_out_im(var, shift - 1);
600 tcg_gen_shri_i32(var, var, shift);
601 }
602 break;
603 case 2: /* ASR */
604 if (shift == 0)
605 shift = 32;
606 if (flags)
607 shifter_out_im(var, shift - 1);
608 if (shift == 32)
609 shift = 31;
610 tcg_gen_sari_i32(var, var, shift);
611 break;
612 case 3: /* ROR/RRX */
613 if (shift != 0) {
614 if (flags)
615 shifter_out_im(var, shift - 1);
f669df27 616 tcg_gen_rotri_i32(var, var, shift); break;
9a119ff6 617 } else {
39d5492a 618 TCGv_i32 tmp = tcg_temp_new_i32();
b6348f29 619 tcg_gen_shli_i32(tmp, cpu_CF, 31);
9a119ff6
PB
620 if (flags)
621 shifter_out_im(var, 0);
622 tcg_gen_shri_i32(var, var, 1);
b26eefb6 623 tcg_gen_or_i32(var, var, tmp);
7d1b0095 624 tcg_temp_free_i32(tmp);
b26eefb6
PB
625 }
626 }
627};
628
39d5492a
PM
629static inline void gen_arm_shift_reg(TCGv_i32 var, int shiftop,
630 TCGv_i32 shift, int flags)
8984bd2e
PB
631{
632 if (flags) {
633 switch (shiftop) {
9ef39277
BS
634 case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break;
635 case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break;
636 case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break;
637 case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break;
8984bd2e
PB
638 }
639 } else {
640 switch (shiftop) {
365af80e
AJ
641 case 0:
642 gen_shl(var, var, shift);
643 break;
644 case 1:
645 gen_shr(var, var, shift);
646 break;
647 case 2:
648 gen_sar(var, var, shift);
649 break;
f669df27
AJ
650 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
651 tcg_gen_rotr_i32(var, var, shift); break;
8984bd2e
PB
652 }
653 }
7d1b0095 654 tcg_temp_free_i32(shift);
8984bd2e
PB
655}
656
6ddbc6e4
PB
657#define PAS_OP(pfx) \
658 switch (op2) { \
659 case 0: gen_pas_helper(glue(pfx,add16)); break; \
660 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
661 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
662 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
663 case 4: gen_pas_helper(glue(pfx,add8)); break; \
664 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
665 }
39d5492a 666static void gen_arm_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
6ddbc6e4 667{
a7812ae4 668 TCGv_ptr tmp;
6ddbc6e4
PB
669
670 switch (op1) {
671#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
672 case 1:
a7812ae4 673 tmp = tcg_temp_new_ptr();
0ecb72a5 674 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 675 PAS_OP(s)
b75263d6 676 tcg_temp_free_ptr(tmp);
6ddbc6e4
PB
677 break;
678 case 5:
a7812ae4 679 tmp = tcg_temp_new_ptr();
0ecb72a5 680 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 681 PAS_OP(u)
b75263d6 682 tcg_temp_free_ptr(tmp);
6ddbc6e4
PB
683 break;
684#undef gen_pas_helper
685#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
686 case 2:
687 PAS_OP(q);
688 break;
689 case 3:
690 PAS_OP(sh);
691 break;
692 case 6:
693 PAS_OP(uq);
694 break;
695 case 7:
696 PAS_OP(uh);
697 break;
698#undef gen_pas_helper
699 }
700}
9ee6e8bb
PB
701#undef PAS_OP
702
6ddbc6e4
PB
703/* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
704#define PAS_OP(pfx) \
ed89a2f1 705 switch (op1) { \
6ddbc6e4
PB
706 case 0: gen_pas_helper(glue(pfx,add8)); break; \
707 case 1: gen_pas_helper(glue(pfx,add16)); break; \
708 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
709 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
710 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
711 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
712 }
39d5492a 713static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
6ddbc6e4 714{
a7812ae4 715 TCGv_ptr tmp;
6ddbc6e4 716
ed89a2f1 717 switch (op2) {
6ddbc6e4
PB
718#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
719 case 0:
a7812ae4 720 tmp = tcg_temp_new_ptr();
0ecb72a5 721 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 722 PAS_OP(s)
b75263d6 723 tcg_temp_free_ptr(tmp);
6ddbc6e4
PB
724 break;
725 case 4:
a7812ae4 726 tmp = tcg_temp_new_ptr();
0ecb72a5 727 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 728 PAS_OP(u)
b75263d6 729 tcg_temp_free_ptr(tmp);
6ddbc6e4
PB
730 break;
731#undef gen_pas_helper
732#define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
733 case 1:
734 PAS_OP(q);
735 break;
736 case 2:
737 PAS_OP(sh);
738 break;
739 case 5:
740 PAS_OP(uq);
741 break;
742 case 6:
743 PAS_OP(uh);
744 break;
745#undef gen_pas_helper
746 }
747}
9ee6e8bb
PB
748#undef PAS_OP
749
39fb730a 750/*
6c2c63d3 751 * Generate a conditional based on ARM condition code cc.
39fb730a
AG
752 * This is common between ARM and Aarch64 targets.
753 */
6c2c63d3 754void arm_test_cc(DisasCompare *cmp, int cc)
d9ba4830 755{
6c2c63d3
RH
756 TCGv_i32 value;
757 TCGCond cond;
758 bool global = true;
d9ba4830 759
d9ba4830
PB
760 switch (cc) {
761 case 0: /* eq: Z */
d9ba4830 762 case 1: /* ne: !Z */
6c2c63d3
RH
763 cond = TCG_COND_EQ;
764 value = cpu_ZF;
d9ba4830 765 break;
6c2c63d3 766
d9ba4830 767 case 2: /* cs: C */
d9ba4830 768 case 3: /* cc: !C */
6c2c63d3
RH
769 cond = TCG_COND_NE;
770 value = cpu_CF;
d9ba4830 771 break;
6c2c63d3 772
d9ba4830 773 case 4: /* mi: N */
d9ba4830 774 case 5: /* pl: !N */
6c2c63d3
RH
775 cond = TCG_COND_LT;
776 value = cpu_NF;
d9ba4830 777 break;
6c2c63d3 778
d9ba4830 779 case 6: /* vs: V */
d9ba4830 780 case 7: /* vc: !V */
6c2c63d3
RH
781 cond = TCG_COND_LT;
782 value = cpu_VF;
d9ba4830 783 break;
6c2c63d3 784
d9ba4830 785 case 8: /* hi: C && !Z */
6c2c63d3
RH
786 case 9: /* ls: !C || Z -> !(C && !Z) */
787 cond = TCG_COND_NE;
788 value = tcg_temp_new_i32();
789 global = false;
790 /* CF is 1 for C, so -CF is an all-bits-set mask for C;
791 ZF is non-zero for !Z; so AND the two subexpressions. */
792 tcg_gen_neg_i32(value, cpu_CF);
793 tcg_gen_and_i32(value, value, cpu_ZF);
d9ba4830 794 break;
6c2c63d3 795
d9ba4830 796 case 10: /* ge: N == V -> N ^ V == 0 */
d9ba4830 797 case 11: /* lt: N != V -> N ^ V != 0 */
6c2c63d3
RH
798 /* Since we're only interested in the sign bit, == 0 is >= 0. */
799 cond = TCG_COND_GE;
800 value = tcg_temp_new_i32();
801 global = false;
802 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
d9ba4830 803 break;
6c2c63d3 804
d9ba4830 805 case 12: /* gt: !Z && N == V */
d9ba4830 806 case 13: /* le: Z || N != V */
6c2c63d3
RH
807 cond = TCG_COND_NE;
808 value = tcg_temp_new_i32();
809 global = false;
810 /* (N == V) is equal to the sign bit of ~(NF ^ VF). Propagate
811 * the sign bit then AND with ZF to yield the result. */
812 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
813 tcg_gen_sari_i32(value, value, 31);
814 tcg_gen_andc_i32(value, cpu_ZF, value);
d9ba4830 815 break;
6c2c63d3 816
9305eac0
RH
817 case 14: /* always */
818 case 15: /* always */
819 /* Use the ALWAYS condition, which will fold early.
820 * It doesn't matter what we use for the value. */
821 cond = TCG_COND_ALWAYS;
822 value = cpu_ZF;
823 goto no_invert;
824
d9ba4830
PB
825 default:
826 fprintf(stderr, "Bad condition code 0x%x\n", cc);
827 abort();
828 }
6c2c63d3
RH
829
830 if (cc & 1) {
831 cond = tcg_invert_cond(cond);
832 }
833
9305eac0 834 no_invert:
6c2c63d3
RH
835 cmp->cond = cond;
836 cmp->value = value;
837 cmp->value_global = global;
838}
839
840void arm_free_cc(DisasCompare *cmp)
841{
842 if (!cmp->value_global) {
843 tcg_temp_free_i32(cmp->value);
844 }
845}
846
847void arm_jump_cc(DisasCompare *cmp, TCGLabel *label)
848{
849 tcg_gen_brcondi_i32(cmp->cond, cmp->value, 0, label);
850}
851
852void arm_gen_test_cc(int cc, TCGLabel *label)
853{
854 DisasCompare cmp;
855 arm_test_cc(&cmp, cc);
856 arm_jump_cc(&cmp, label);
857 arm_free_cc(&cmp);
d9ba4830 858}
2c0262af 859
b1d8e52e 860static const uint8_t table_logic_cc[16] = {
2c0262af
FB
861 1, /* and */
862 1, /* xor */
863 0, /* sub */
864 0, /* rsb */
865 0, /* add */
866 0, /* adc */
867 0, /* sbc */
868 0, /* rsc */
869 1, /* andl */
870 1, /* xorl */
871 0, /* cmp */
872 0, /* cmn */
873 1, /* orr */
874 1, /* mov */
875 1, /* bic */
876 1, /* mvn */
877};
3b46e624 878
4d5e8c96
PM
879static inline void gen_set_condexec(DisasContext *s)
880{
881 if (s->condexec_mask) {
882 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
883 TCGv_i32 tmp = tcg_temp_new_i32();
884 tcg_gen_movi_i32(tmp, val);
885 store_cpu_field(tmp, condexec_bits);
886 }
887}
888
889static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
890{
891 tcg_gen_movi_i32(cpu_R[15], val);
892}
893
d9ba4830
PB
894/* Set PC and Thumb state from an immediate address. */
895static inline void gen_bx_im(DisasContext *s, uint32_t addr)
99c475ab 896{
39d5492a 897 TCGv_i32 tmp;
99c475ab 898
dcba3a8d 899 s->base.is_jmp = DISAS_JUMP;
d9ba4830 900 if (s->thumb != (addr & 1)) {
7d1b0095 901 tmp = tcg_temp_new_i32();
d9ba4830 902 tcg_gen_movi_i32(tmp, addr & 1);
0ecb72a5 903 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, thumb));
7d1b0095 904 tcg_temp_free_i32(tmp);
d9ba4830 905 }
155c3eac 906 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
d9ba4830
PB
907}
908
909/* Set PC and Thumb state from var. var is marked as dead. */
39d5492a 910static inline void gen_bx(DisasContext *s, TCGv_i32 var)
d9ba4830 911{
dcba3a8d 912 s->base.is_jmp = DISAS_JUMP;
155c3eac
FN
913 tcg_gen_andi_i32(cpu_R[15], var, ~1);
914 tcg_gen_andi_i32(var, var, 1);
915 store_cpu_field(var, thumb);
d9ba4830
PB
916}
917
5e5584c8
PM
918/*
919 * Set PC and Thumb state from var. var is marked as dead.
3bb8a96f
PM
920 * For M-profile CPUs, include logic to detect exception-return
921 * branches and handle them. This is needed for Thumb POP/LDM to PC, LDR to PC,
922 * and BX reg, and no others, and happens only for code in Handler mode.
5e5584c8
PM
923 * The Security Extension also requires us to check for the FNC_RETURN
924 * which signals a function return from non-secure state; this can happen
925 * in both Handler and Thread mode.
926 * To avoid having to do multiple comparisons in inline generated code,
927 * we make the check we do here loose, so it will match for EXC_RETURN
928 * in Thread mode. For system emulation do_v7m_exception_exit() checks
929 * for these spurious cases and returns without doing anything (giving
930 * the same behaviour as for a branch to a non-magic address).
931 *
932 * In linux-user mode it is unclear what the right behaviour for an
933 * attempted FNC_RETURN should be, because in real hardware this will go
934 * directly to Secure code (ie not the Linux kernel) which will then treat
935 * the error in any way it chooses. For QEMU we opt to make the FNC_RETURN
936 * attempt behave the way it would on a CPU without the security extension,
937 * which is to say "like a normal branch". That means we can simply treat
938 * all branches as normal with no magic address behaviour.
3bb8a96f
PM
939 */
940static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var)
941{
942 /* Generate the same code here as for a simple bx, but flag via
dcba3a8d 943 * s->base.is_jmp that we need to do the rest of the work later.
3bb8a96f
PM
944 */
945 gen_bx(s, var);
5e5584c8 946#ifndef CONFIG_USER_ONLY
d02a8698
PM
947 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY) ||
948 (s->v7m_handler_mode && arm_dc_feature(s, ARM_FEATURE_M))) {
dcba3a8d 949 s->base.is_jmp = DISAS_BX_EXCRET;
3bb8a96f 950 }
5e5584c8 951#endif
3bb8a96f
PM
952}
953
954static inline void gen_bx_excret_final_code(DisasContext *s)
955{
956 /* Generate the code to finish possible exception return and end the TB */
957 TCGLabel *excret_label = gen_new_label();
d02a8698
PM
958 uint32_t min_magic;
959
960 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY)) {
961 /* Covers FNC_RETURN and EXC_RETURN magic */
962 min_magic = FNC_RETURN_MIN_MAGIC;
963 } else {
964 /* EXC_RETURN magic only */
965 min_magic = EXC_RETURN_MIN_MAGIC;
966 }
3bb8a96f
PM
967
968 /* Is the new PC value in the magic range indicating exception return? */
d02a8698 969 tcg_gen_brcondi_i32(TCG_COND_GEU, cpu_R[15], min_magic, excret_label);
3bb8a96f
PM
970 /* No: end the TB as we would for a DISAS_JMP */
971 if (is_singlestepping(s)) {
972 gen_singlestep_exception(s);
973 } else {
07ea28b4 974 tcg_gen_exit_tb(NULL, 0);
3bb8a96f
PM
975 }
976 gen_set_label(excret_label);
977 /* Yes: this is an exception return.
978 * At this point in runtime env->regs[15] and env->thumb will hold
979 * the exception-return magic number, which do_v7m_exception_exit()
980 * will read. Nothing else will be able to see those values because
981 * the cpu-exec main loop guarantees that we will always go straight
982 * from raising the exception to the exception-handling code.
983 *
984 * gen_ss_advance(s) does nothing on M profile currently but
985 * calling it is conceptually the right thing as we have executed
986 * this instruction (compare SWI, HVC, SMC handling).
987 */
988 gen_ss_advance(s);
989 gen_exception_internal(EXCP_EXCEPTION_EXIT);
990}
991
fb602cb7
PM
992static inline void gen_bxns(DisasContext *s, int rm)
993{
994 TCGv_i32 var = load_reg(s, rm);
995
996 /* The bxns helper may raise an EXCEPTION_EXIT exception, so in theory
997 * we need to sync state before calling it, but:
998 * - we don't need to do gen_set_pc_im() because the bxns helper will
999 * always set the PC itself
1000 * - we don't need to do gen_set_condexec() because BXNS is UNPREDICTABLE
1001 * unless it's outside an IT block or the last insn in an IT block,
1002 * so we know that condexec == 0 (already set at the top of the TB)
1003 * is correct in the non-UNPREDICTABLE cases, and we can choose
1004 * "zeroes the IT bits" as our UNPREDICTABLE behaviour otherwise.
1005 */
1006 gen_helper_v7m_bxns(cpu_env, var);
1007 tcg_temp_free_i32(var);
ef475b5d 1008 s->base.is_jmp = DISAS_EXIT;
fb602cb7
PM
1009}
1010
3e3fa230
PM
1011static inline void gen_blxns(DisasContext *s, int rm)
1012{
1013 TCGv_i32 var = load_reg(s, rm);
1014
1015 /* We don't need to sync condexec state, for the same reason as bxns.
1016 * We do however need to set the PC, because the blxns helper reads it.
1017 * The blxns helper may throw an exception.
1018 */
a0415916 1019 gen_set_pc_im(s, s->base.pc_next);
3e3fa230
PM
1020 gen_helper_v7m_blxns(cpu_env, var);
1021 tcg_temp_free_i32(var);
1022 s->base.is_jmp = DISAS_EXIT;
1023}
1024
21aeb343
JR
1025/* Variant of store_reg which uses branch&exchange logic when storing
1026 to r15 in ARM architecture v7 and above. The source must be a temporary
1027 and will be marked as dead. */
7dcc1f89 1028static inline void store_reg_bx(DisasContext *s, int reg, TCGv_i32 var)
21aeb343
JR
1029{
1030 if (reg == 15 && ENABLE_ARCH_7) {
1031 gen_bx(s, var);
1032 } else {
1033 store_reg(s, reg, var);
1034 }
1035}
1036
be5e7a76
DES
1037/* Variant of store_reg which uses branch&exchange logic when storing
1038 * to r15 in ARM architecture v5T and above. This is used for storing
1039 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
1040 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
7dcc1f89 1041static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
be5e7a76
DES
1042{
1043 if (reg == 15 && ENABLE_ARCH_5) {
3bb8a96f 1044 gen_bx_excret(s, var);
be5e7a76
DES
1045 } else {
1046 store_reg(s, reg, var);
1047 }
1048}
1049
e334bd31
PB
1050#ifdef CONFIG_USER_ONLY
1051#define IS_USER_ONLY 1
1052#else
1053#define IS_USER_ONLY 0
1054#endif
1055
08307563
PM
1056/* Abstractions of "generate code to do a guest load/store for
1057 * AArch32", where a vaddr is always 32 bits (and is zero
1058 * extended if we're a 64 bit core) and data is also
1059 * 32 bits unless specifically doing a 64 bit access.
1060 * These functions work like tcg_gen_qemu_{ld,st}* except
09f78135 1061 * that the address argument is TCGv_i32 rather than TCGv.
08307563 1062 */
08307563 1063
14776ab5 1064static inline TCGv gen_aa32_addr(DisasContext *s, TCGv_i32 a32, MemOp op)
08307563 1065{
7f5616f5
RH
1066 TCGv addr = tcg_temp_new();
1067 tcg_gen_extu_i32_tl(addr, a32);
1068
e334bd31 1069 /* Not needed for user-mode BE32, where we use MO_BE instead. */
7f5616f5
RH
1070 if (!IS_USER_ONLY && s->sctlr_b && (op & MO_SIZE) < MO_32) {
1071 tcg_gen_xori_tl(addr, addr, 4 - (1 << (op & MO_SIZE)));
e334bd31 1072 }
7f5616f5 1073 return addr;
08307563
PM
1074}
1075
7f5616f5 1076static void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
14776ab5 1077 int index, MemOp opc)
08307563 1078{
2aeba0d0
JS
1079 TCGv addr;
1080
1081 if (arm_dc_feature(s, ARM_FEATURE_M) &&
1082 !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
1083 opc |= MO_ALIGN;
1084 }
1085
1086 addr = gen_aa32_addr(s, a32, opc);
7f5616f5
RH
1087 tcg_gen_qemu_ld_i32(val, addr, index, opc);
1088 tcg_temp_free(addr);
08307563
PM
1089}
1090
7f5616f5 1091static void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
14776ab5 1092 int index, MemOp opc)
7f5616f5 1093{
2aeba0d0
JS
1094 TCGv addr;
1095
1096 if (arm_dc_feature(s, ARM_FEATURE_M) &&
1097 !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
1098 opc |= MO_ALIGN;
1099 }
1100
1101 addr = gen_aa32_addr(s, a32, opc);
7f5616f5
RH
1102 tcg_gen_qemu_st_i32(val, addr, index, opc);
1103 tcg_temp_free(addr);
1104}
08307563 1105
7f5616f5 1106#define DO_GEN_LD(SUFF, OPC) \
12dcc321 1107static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
7f5616f5 1108 TCGv_i32 a32, int index) \
08307563 1109{ \
7f5616f5 1110 gen_aa32_ld_i32(s, val, a32, index, OPC | s->be_data); \
9bb6558a
PM
1111} \
1112static inline void gen_aa32_ld##SUFF##_iss(DisasContext *s, \
1113 TCGv_i32 val, \
1114 TCGv_i32 a32, int index, \
1115 ISSInfo issinfo) \
1116{ \
1117 gen_aa32_ld##SUFF(s, val, a32, index); \
1118 disas_set_da_iss(s, OPC, issinfo); \
08307563
PM
1119}
1120
7f5616f5 1121#define DO_GEN_ST(SUFF, OPC) \
12dcc321 1122static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
7f5616f5 1123 TCGv_i32 a32, int index) \
08307563 1124{ \
7f5616f5 1125 gen_aa32_st_i32(s, val, a32, index, OPC | s->be_data); \
9bb6558a
PM
1126} \
1127static inline void gen_aa32_st##SUFF##_iss(DisasContext *s, \
1128 TCGv_i32 val, \
1129 TCGv_i32 a32, int index, \
1130 ISSInfo issinfo) \
1131{ \
1132 gen_aa32_st##SUFF(s, val, a32, index); \
1133 disas_set_da_iss(s, OPC, issinfo | ISSIsWrite); \
08307563
PM
1134}
1135
7f5616f5 1136static inline void gen_aa32_frob64(DisasContext *s, TCGv_i64 val)
08307563 1137{
e334bd31
PB
1138 /* Not needed for user-mode BE32, where we use MO_BE instead. */
1139 if (!IS_USER_ONLY && s->sctlr_b) {
1140 tcg_gen_rotri_i64(val, val, 32);
1141 }
08307563
PM
1142}
1143
7f5616f5 1144static void gen_aa32_ld_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
14776ab5 1145 int index, MemOp opc)
08307563 1146{
7f5616f5
RH
1147 TCGv addr = gen_aa32_addr(s, a32, opc);
1148 tcg_gen_qemu_ld_i64(val, addr, index, opc);
1149 gen_aa32_frob64(s, val);
1150 tcg_temp_free(addr);
1151}
1152
1153static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
1154 TCGv_i32 a32, int index)
1155{
1156 gen_aa32_ld_i64(s, val, a32, index, MO_Q | s->be_data);
1157}
1158
1159static void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
14776ab5 1160 int index, MemOp opc)
7f5616f5
RH
1161{
1162 TCGv addr = gen_aa32_addr(s, a32, opc);
e334bd31
PB
1163
1164 /* Not needed for user-mode BE32, where we use MO_BE instead. */
1165 if (!IS_USER_ONLY && s->sctlr_b) {
7f5616f5 1166 TCGv_i64 tmp = tcg_temp_new_i64();
e334bd31 1167 tcg_gen_rotri_i64(tmp, val, 32);
7f5616f5
RH
1168 tcg_gen_qemu_st_i64(tmp, addr, index, opc);
1169 tcg_temp_free_i64(tmp);
e334bd31 1170 } else {
7f5616f5 1171 tcg_gen_qemu_st_i64(val, addr, index, opc);
e334bd31 1172 }
7f5616f5 1173 tcg_temp_free(addr);
08307563
PM
1174}
1175
7f5616f5
RH
1176static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
1177 TCGv_i32 a32, int index)
1178{
1179 gen_aa32_st_i64(s, val, a32, index, MO_Q | s->be_data);
1180}
08307563 1181
7f5616f5
RH
1182DO_GEN_LD(8s, MO_SB)
1183DO_GEN_LD(8u, MO_UB)
1184DO_GEN_LD(16s, MO_SW)
1185DO_GEN_LD(16u, MO_UW)
1186DO_GEN_LD(32u, MO_UL)
7f5616f5
RH
1187DO_GEN_ST(8, MO_UB)
1188DO_GEN_ST(16, MO_UW)
1189DO_GEN_ST(32, MO_UL)
08307563 1190
37e6456e
PM
1191static inline void gen_hvc(DisasContext *s, int imm16)
1192{
1193 /* The pre HVC helper handles cases when HVC gets trapped
1194 * as an undefined insn by runtime configuration (ie before
1195 * the insn really executes).
1196 */
43722a6d 1197 gen_set_pc_im(s, s->pc_curr);
37e6456e
PM
1198 gen_helper_pre_hvc(cpu_env);
1199 /* Otherwise we will treat this as a real exception which
1200 * happens after execution of the insn. (The distinction matters
1201 * for the PC value reported to the exception handler and also
1202 * for single stepping.)
1203 */
1204 s->svc_imm = imm16;
a0415916 1205 gen_set_pc_im(s, s->base.pc_next);
dcba3a8d 1206 s->base.is_jmp = DISAS_HVC;
37e6456e
PM
1207}
1208
1209static inline void gen_smc(DisasContext *s)
1210{
1211 /* As with HVC, we may take an exception either before or after
1212 * the insn executes.
1213 */
1214 TCGv_i32 tmp;
1215
43722a6d 1216 gen_set_pc_im(s, s->pc_curr);
37e6456e
PM
1217 tmp = tcg_const_i32(syn_aa32_smc());
1218 gen_helper_pre_smc(cpu_env, tmp);
1219 tcg_temp_free_i32(tmp);
a0415916 1220 gen_set_pc_im(s, s->base.pc_next);
dcba3a8d 1221 s->base.is_jmp = DISAS_SMC;
37e6456e
PM
1222}
1223
aee828e7 1224static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp)
d4a2dc67
PM
1225{
1226 gen_set_condexec(s);
aee828e7 1227 gen_set_pc_im(s, pc);
d4a2dc67 1228 gen_exception_internal(excp);
dcba3a8d 1229 s->base.is_jmp = DISAS_NORETURN;
d4a2dc67
PM
1230}
1231
a767fac8 1232static void gen_exception_insn(DisasContext *s, uint32_t pc, int excp,
73710361 1233 int syn, uint32_t target_el)
d4a2dc67
PM
1234{
1235 gen_set_condexec(s);
a767fac8 1236 gen_set_pc_im(s, pc);
73710361 1237 gen_exception(excp, syn, target_el);
dcba3a8d 1238 s->base.is_jmp = DISAS_NORETURN;
d4a2dc67
PM
1239}
1240
06bcbda3 1241static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
c900a2e6
PM
1242{
1243 TCGv_i32 tcg_syn;
1244
1245 gen_set_condexec(s);
06bcbda3 1246 gen_set_pc_im(s, s->pc_curr);
c900a2e6
PM
1247 tcg_syn = tcg_const_i32(syn);
1248 gen_helper_exception_bkpt_insn(cpu_env, tcg_syn);
1249 tcg_temp_free_i32(tcg_syn);
1250 s->base.is_jmp = DISAS_NORETURN;
1251}
1252
1ce21ba1
RH
1253static void unallocated_encoding(DisasContext *s)
1254{
1255 /* Unallocated and reserved encodings are uncategorized */
1256 gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(),
1257 default_exception_el(s));
1258}
1259
b5ff1b31
FB
1260/* Force a TB lookup after an instruction that changes the CPU state. */
1261static inline void gen_lookup_tb(DisasContext *s)
1262{
a0415916 1263 tcg_gen_movi_i32(cpu_R[15], s->base.pc_next);
dcba3a8d 1264 s->base.is_jmp = DISAS_EXIT;
b5ff1b31
FB
1265}
1266
19a6e31c
PM
1267static inline void gen_hlt(DisasContext *s, int imm)
1268{
1269 /* HLT. This has two purposes.
1270 * Architecturally, it is an external halting debug instruction.
1271 * Since QEMU doesn't implement external debug, we treat this as
1272 * it is required for halting debug disabled: it will UNDEF.
1273 * Secondly, "HLT 0x3C" is a T32 semihosting trap instruction,
1274 * and "HLT 0xF000" is an A32 semihosting syscall. These traps
1275 * must trigger semihosting even for ARMv7 and earlier, where
1276 * HLT was an undefined encoding.
1277 * In system mode, we don't allow userspace access to
1278 * semihosting, to provide some semblance of security
1279 * (and for consistency with our 32-bit semihosting).
1280 */
1281 if (semihosting_enabled() &&
1282#ifndef CONFIG_USER_ONLY
1283 s->current_el != 0 &&
1284#endif
1285 (imm == (s->thumb ? 0x3c : 0xf000))) {
aee828e7 1286 gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST);
19a6e31c
PM
1287 return;
1288 }
1289
1ce21ba1 1290 unallocated_encoding(s);
19a6e31c
PM
1291}
1292
b0109805 1293static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
39d5492a 1294 TCGv_i32 var)
2c0262af 1295{
1e8d4eec 1296 int val, rm, shift, shiftop;
39d5492a 1297 TCGv_i32 offset;
2c0262af
FB
1298
1299 if (!(insn & (1 << 25))) {
1300 /* immediate */
1301 val = insn & 0xfff;
1302 if (!(insn & (1 << 23)))
1303 val = -val;
537730b9 1304 if (val != 0)
b0109805 1305 tcg_gen_addi_i32(var, var, val);
2c0262af
FB
1306 } else {
1307 /* shift/register */
1308 rm = (insn) & 0xf;
1309 shift = (insn >> 7) & 0x1f;
1e8d4eec 1310 shiftop = (insn >> 5) & 3;
b26eefb6 1311 offset = load_reg(s, rm);
9a119ff6 1312 gen_arm_shift_im(offset, shiftop, shift, 0);
2c0262af 1313 if (!(insn & (1 << 23)))
b0109805 1314 tcg_gen_sub_i32(var, var, offset);
2c0262af 1315 else
b0109805 1316 tcg_gen_add_i32(var, var, offset);
7d1b0095 1317 tcg_temp_free_i32(offset);
2c0262af
FB
1318 }
1319}
1320
191f9a93 1321static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
39d5492a 1322 int extra, TCGv_i32 var)
2c0262af
FB
1323{
1324 int val, rm;
39d5492a 1325 TCGv_i32 offset;
3b46e624 1326
2c0262af
FB
1327 if (insn & (1 << 22)) {
1328 /* immediate */
1329 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
1330 if (!(insn & (1 << 23)))
1331 val = -val;
18acad92 1332 val += extra;
537730b9 1333 if (val != 0)
b0109805 1334 tcg_gen_addi_i32(var, var, val);
2c0262af
FB
1335 } else {
1336 /* register */
191f9a93 1337 if (extra)
b0109805 1338 tcg_gen_addi_i32(var, var, extra);
2c0262af 1339 rm = (insn) & 0xf;
b26eefb6 1340 offset = load_reg(s, rm);
2c0262af 1341 if (!(insn & (1 << 23)))
b0109805 1342 tcg_gen_sub_i32(var, var, offset);
2c0262af 1343 else
b0109805 1344 tcg_gen_add_i32(var, var, offset);
7d1b0095 1345 tcg_temp_free_i32(offset);
2c0262af
FB
1346 }
1347}
1348
5aaebd13
PM
1349static TCGv_ptr get_fpstatus_ptr(int neon)
1350{
1351 TCGv_ptr statusptr = tcg_temp_new_ptr();
1352 int offset;
1353 if (neon) {
0ecb72a5 1354 offset = offsetof(CPUARMState, vfp.standard_fp_status);
5aaebd13 1355 } else {
0ecb72a5 1356 offset = offsetof(CPUARMState, vfp.fp_status);
5aaebd13
PM
1357 }
1358 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
1359 return statusptr;
1360}
1361
c39c2b90 1362static inline long vfp_reg_offset(bool dp, unsigned reg)
8e96005d 1363{
9a2b5256 1364 if (dp) {
c39c2b90 1365 return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]);
8e96005d 1366 } else {
c39c2b90 1367 long ofs = offsetof(CPUARMState, vfp.zregs[reg >> 2].d[(reg >> 1) & 1]);
9a2b5256
RH
1368 if (reg & 1) {
1369 ofs += offsetof(CPU_DoubleU, l.upper);
1370 } else {
1371 ofs += offsetof(CPU_DoubleU, l.lower);
1372 }
1373 return ofs;
8e96005d
FB
1374 }
1375}
9ee6e8bb
PB
1376
1377/* Return the offset of a 32-bit piece of a NEON register.
1378 zero is the least significant end of the register. */
1379static inline long
1380neon_reg_offset (int reg, int n)
1381{
1382 int sreg;
1383 sreg = reg * 2 + n;
1384 return vfp_reg_offset(0, sreg);
1385}
1386
32f91fb7
RH
1387/* Return the offset of a 2**SIZE piece of a NEON register, at index ELE,
1388 * where 0 is the least significant end of the register.
1389 */
1390static inline long
14776ab5 1391neon_element_offset(int reg, int element, MemOp size)
32f91fb7
RH
1392{
1393 int element_size = 1 << size;
1394 int ofs = element * element_size;
1395#ifdef HOST_WORDS_BIGENDIAN
1396 /* Calculate the offset assuming fully little-endian,
1397 * then XOR to account for the order of the 8-byte units.
1398 */
1399 if (element_size < 8) {
1400 ofs ^= 8 - element_size;
1401 }
1402#endif
1403 return neon_reg_offset(reg, 0) + ofs;
1404}
1405
39d5492a 1406static TCGv_i32 neon_load_reg(int reg, int pass)
8f8e3aa4 1407{
39d5492a 1408 TCGv_i32 tmp = tcg_temp_new_i32();
8f8e3aa4
PB
1409 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1410 return tmp;
1411}
1412
14776ab5 1413static void neon_load_element(TCGv_i32 var, int reg, int ele, MemOp mop)
2d6ac920
RH
1414{
1415 long offset = neon_element_offset(reg, ele, mop & MO_SIZE);
1416
1417 switch (mop) {
1418 case MO_UB:
1419 tcg_gen_ld8u_i32(var, cpu_env, offset);
1420 break;
1421 case MO_UW:
1422 tcg_gen_ld16u_i32(var, cpu_env, offset);
1423 break;
1424 case MO_UL:
1425 tcg_gen_ld_i32(var, cpu_env, offset);
1426 break;
1427 default:
1428 g_assert_not_reached();
1429 }
1430}
1431
14776ab5 1432static void neon_load_element64(TCGv_i64 var, int reg, int ele, MemOp mop)
ac55d007
RH
1433{
1434 long offset = neon_element_offset(reg, ele, mop & MO_SIZE);
1435
1436 switch (mop) {
1437 case MO_UB:
1438 tcg_gen_ld8u_i64(var, cpu_env, offset);
1439 break;
1440 case MO_UW:
1441 tcg_gen_ld16u_i64(var, cpu_env, offset);
1442 break;
1443 case MO_UL:
1444 tcg_gen_ld32u_i64(var, cpu_env, offset);
1445 break;
1446 case MO_Q:
1447 tcg_gen_ld_i64(var, cpu_env, offset);
1448 break;
1449 default:
1450 g_assert_not_reached();
1451 }
1452}
1453
39d5492a 1454static void neon_store_reg(int reg, int pass, TCGv_i32 var)
8f8e3aa4
PB
1455{
1456 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
7d1b0095 1457 tcg_temp_free_i32(var);
8f8e3aa4
PB
1458}
1459
14776ab5 1460static void neon_store_element(int reg, int ele, MemOp size, TCGv_i32 var)
2d6ac920
RH
1461{
1462 long offset = neon_element_offset(reg, ele, size);
1463
1464 switch (size) {
1465 case MO_8:
1466 tcg_gen_st8_i32(var, cpu_env, offset);
1467 break;
1468 case MO_16:
1469 tcg_gen_st16_i32(var, cpu_env, offset);
1470 break;
1471 case MO_32:
1472 tcg_gen_st_i32(var, cpu_env, offset);
1473 break;
1474 default:
1475 g_assert_not_reached();
1476 }
1477}
1478
14776ab5 1479static void neon_store_element64(int reg, int ele, MemOp size, TCGv_i64 var)
ac55d007
RH
1480{
1481 long offset = neon_element_offset(reg, ele, size);
1482
1483 switch (size) {
1484 case MO_8:
1485 tcg_gen_st8_i64(var, cpu_env, offset);
1486 break;
1487 case MO_16:
1488 tcg_gen_st16_i64(var, cpu_env, offset);
1489 break;
1490 case MO_32:
1491 tcg_gen_st32_i64(var, cpu_env, offset);
1492 break;
1493 case MO_64:
1494 tcg_gen_st_i64(var, cpu_env, offset);
1495 break;
1496 default:
1497 g_assert_not_reached();
1498 }
1499}
1500
a7812ae4 1501static inline void neon_load_reg64(TCGv_i64 var, int reg)
ad69471c
PB
1502{
1503 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1504}
1505
a7812ae4 1506static inline void neon_store_reg64(TCGv_i64 var, int reg)
ad69471c
PB
1507{
1508 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1509}
1510
160f3b64
PM
1511static inline void neon_load_reg32(TCGv_i32 var, int reg)
1512{
1513 tcg_gen_ld_i32(var, cpu_env, vfp_reg_offset(false, reg));
1514}
1515
1516static inline void neon_store_reg32(TCGv_i32 var, int reg)
1517{
1518 tcg_gen_st_i32(var, cpu_env, vfp_reg_offset(false, reg));
1519}
1520
1a66ac61
RH
1521static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
1522{
1523 TCGv_ptr ret = tcg_temp_new_ptr();
1524 tcg_gen_addi_ptr(ret, cpu_env, vfp_reg_offset(dp, reg));
1525 return ret;
1526}
1527
d00584b7 1528#define ARM_CP_RW_BIT (1 << 20)
18c9b560 1529
78e138bc
PM
1530/* Include the VFP decoder */
1531#include "translate-vfp.inc.c"
1532
a7812ae4 1533static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
e677137d 1534{
0ecb72a5 1535 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
e677137d
PB
1536}
1537
a7812ae4 1538static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
e677137d 1539{
0ecb72a5 1540 tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
e677137d
PB
1541}
1542
39d5492a 1543static inline TCGv_i32 iwmmxt_load_creg(int reg)
e677137d 1544{
39d5492a 1545 TCGv_i32 var = tcg_temp_new_i32();
0ecb72a5 1546 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
da6b5335 1547 return var;
e677137d
PB
1548}
1549
39d5492a 1550static inline void iwmmxt_store_creg(int reg, TCGv_i32 var)
e677137d 1551{
0ecb72a5 1552 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
7d1b0095 1553 tcg_temp_free_i32(var);
e677137d
PB
1554}
1555
1556static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1557{
1558 iwmmxt_store_reg(cpu_M0, rn);
1559}
1560
1561static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1562{
1563 iwmmxt_load_reg(cpu_M0, rn);
1564}
1565
1566static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1567{
1568 iwmmxt_load_reg(cpu_V1, rn);
1569 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1570}
1571
1572static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1573{
1574 iwmmxt_load_reg(cpu_V1, rn);
1575 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1576}
1577
1578static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1579{
1580 iwmmxt_load_reg(cpu_V1, rn);
1581 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1582}
1583
1584#define IWMMXT_OP(name) \
1585static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1586{ \
1587 iwmmxt_load_reg(cpu_V1, rn); \
1588 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1589}
1590
477955bd
PM
1591#define IWMMXT_OP_ENV(name) \
1592static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1593{ \
1594 iwmmxt_load_reg(cpu_V1, rn); \
1595 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1596}
1597
1598#define IWMMXT_OP_ENV_SIZE(name) \
1599IWMMXT_OP_ENV(name##b) \
1600IWMMXT_OP_ENV(name##w) \
1601IWMMXT_OP_ENV(name##l)
e677137d 1602
477955bd 1603#define IWMMXT_OP_ENV1(name) \
e677137d
PB
1604static inline void gen_op_iwmmxt_##name##_M0(void) \
1605{ \
477955bd 1606 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
e677137d
PB
1607}
1608
1609IWMMXT_OP(maddsq)
1610IWMMXT_OP(madduq)
1611IWMMXT_OP(sadb)
1612IWMMXT_OP(sadw)
1613IWMMXT_OP(mulslw)
1614IWMMXT_OP(mulshw)
1615IWMMXT_OP(mululw)
1616IWMMXT_OP(muluhw)
1617IWMMXT_OP(macsw)
1618IWMMXT_OP(macuw)
1619
477955bd
PM
1620IWMMXT_OP_ENV_SIZE(unpackl)
1621IWMMXT_OP_ENV_SIZE(unpackh)
1622
1623IWMMXT_OP_ENV1(unpacklub)
1624IWMMXT_OP_ENV1(unpackluw)
1625IWMMXT_OP_ENV1(unpacklul)
1626IWMMXT_OP_ENV1(unpackhub)
1627IWMMXT_OP_ENV1(unpackhuw)
1628IWMMXT_OP_ENV1(unpackhul)
1629IWMMXT_OP_ENV1(unpacklsb)
1630IWMMXT_OP_ENV1(unpacklsw)
1631IWMMXT_OP_ENV1(unpacklsl)
1632IWMMXT_OP_ENV1(unpackhsb)
1633IWMMXT_OP_ENV1(unpackhsw)
1634IWMMXT_OP_ENV1(unpackhsl)
1635
1636IWMMXT_OP_ENV_SIZE(cmpeq)
1637IWMMXT_OP_ENV_SIZE(cmpgtu)
1638IWMMXT_OP_ENV_SIZE(cmpgts)
1639
1640IWMMXT_OP_ENV_SIZE(mins)
1641IWMMXT_OP_ENV_SIZE(minu)
1642IWMMXT_OP_ENV_SIZE(maxs)
1643IWMMXT_OP_ENV_SIZE(maxu)
1644
1645IWMMXT_OP_ENV_SIZE(subn)
1646IWMMXT_OP_ENV_SIZE(addn)
1647IWMMXT_OP_ENV_SIZE(subu)
1648IWMMXT_OP_ENV_SIZE(addu)
1649IWMMXT_OP_ENV_SIZE(subs)
1650IWMMXT_OP_ENV_SIZE(adds)
1651
1652IWMMXT_OP_ENV(avgb0)
1653IWMMXT_OP_ENV(avgb1)
1654IWMMXT_OP_ENV(avgw0)
1655IWMMXT_OP_ENV(avgw1)
e677137d 1656
477955bd
PM
1657IWMMXT_OP_ENV(packuw)
1658IWMMXT_OP_ENV(packul)
1659IWMMXT_OP_ENV(packuq)
1660IWMMXT_OP_ENV(packsw)
1661IWMMXT_OP_ENV(packsl)
1662IWMMXT_OP_ENV(packsq)
e677137d 1663
e677137d
PB
1664static void gen_op_iwmmxt_set_mup(void)
1665{
39d5492a 1666 TCGv_i32 tmp;
e677137d
PB
1667 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1668 tcg_gen_ori_i32(tmp, tmp, 2);
1669 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1670}
1671
1672static void gen_op_iwmmxt_set_cup(void)
1673{
39d5492a 1674 TCGv_i32 tmp;
e677137d
PB
1675 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1676 tcg_gen_ori_i32(tmp, tmp, 1);
1677 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1678}
1679
1680static void gen_op_iwmmxt_setpsr_nz(void)
1681{
39d5492a 1682 TCGv_i32 tmp = tcg_temp_new_i32();
e677137d
PB
1683 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1684 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1685}
1686
1687static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1688{
1689 iwmmxt_load_reg(cpu_V1, rn);
86831435 1690 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
e677137d
PB
1691 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1692}
1693
39d5492a
PM
1694static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn,
1695 TCGv_i32 dest)
18c9b560
AZ
1696{
1697 int rd;
1698 uint32_t offset;
39d5492a 1699 TCGv_i32 tmp;
18c9b560
AZ
1700
1701 rd = (insn >> 16) & 0xf;
da6b5335 1702 tmp = load_reg(s, rd);
18c9b560
AZ
1703
1704 offset = (insn & 0xff) << ((insn >> 7) & 2);
1705 if (insn & (1 << 24)) {
1706 /* Pre indexed */
1707 if (insn & (1 << 23))
da6b5335 1708 tcg_gen_addi_i32(tmp, tmp, offset);
18c9b560 1709 else
da6b5335
FN
1710 tcg_gen_addi_i32(tmp, tmp, -offset);
1711 tcg_gen_mov_i32(dest, tmp);
18c9b560 1712 if (insn & (1 << 21))
da6b5335
FN
1713 store_reg(s, rd, tmp);
1714 else
7d1b0095 1715 tcg_temp_free_i32(tmp);
18c9b560
AZ
1716 } else if (insn & (1 << 21)) {
1717 /* Post indexed */
da6b5335 1718 tcg_gen_mov_i32(dest, tmp);
18c9b560 1719 if (insn & (1 << 23))
da6b5335 1720 tcg_gen_addi_i32(tmp, tmp, offset);
18c9b560 1721 else
da6b5335
FN
1722 tcg_gen_addi_i32(tmp, tmp, -offset);
1723 store_reg(s, rd, tmp);
18c9b560
AZ
1724 } else if (!(insn & (1 << 23)))
1725 return 1;
1726 return 0;
1727}
1728
39d5492a 1729static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest)
18c9b560
AZ
1730{
1731 int rd = (insn >> 0) & 0xf;
39d5492a 1732 TCGv_i32 tmp;
18c9b560 1733
da6b5335
FN
1734 if (insn & (1 << 8)) {
1735 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
18c9b560 1736 return 1;
da6b5335
FN
1737 } else {
1738 tmp = iwmmxt_load_creg(rd);
1739 }
1740 } else {
7d1b0095 1741 tmp = tcg_temp_new_i32();
da6b5335 1742 iwmmxt_load_reg(cpu_V0, rd);
ecc7b3aa 1743 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
da6b5335
FN
1744 }
1745 tcg_gen_andi_i32(tmp, tmp, mask);
1746 tcg_gen_mov_i32(dest, tmp);
7d1b0095 1747 tcg_temp_free_i32(tmp);
18c9b560
AZ
1748 return 0;
1749}
1750
a1c7273b 1751/* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
18c9b560 1752 (ie. an undefined instruction). */
7dcc1f89 1753static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
18c9b560
AZ
1754{
1755 int rd, wrd;
1756 int rdhi, rdlo, rd0, rd1, i;
39d5492a
PM
1757 TCGv_i32 addr;
1758 TCGv_i32 tmp, tmp2, tmp3;
18c9b560
AZ
1759
1760 if ((insn & 0x0e000e00) == 0x0c000000) {
1761 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1762 wrd = insn & 0xf;
1763 rdlo = (insn >> 12) & 0xf;
1764 rdhi = (insn >> 16) & 0xf;
d00584b7 1765 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
da6b5335 1766 iwmmxt_load_reg(cpu_V0, wrd);
ecc7b3aa 1767 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
664b7e3b 1768 tcg_gen_extrh_i64_i32(cpu_R[rdhi], cpu_V0);
d00584b7 1769 } else { /* TMCRR */
da6b5335
FN
1770 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1771 iwmmxt_store_reg(cpu_V0, wrd);
18c9b560
AZ
1772 gen_op_iwmmxt_set_mup();
1773 }
1774 return 0;
1775 }
1776
1777 wrd = (insn >> 12) & 0xf;
7d1b0095 1778 addr = tcg_temp_new_i32();
da6b5335 1779 if (gen_iwmmxt_address(s, insn, addr)) {
7d1b0095 1780 tcg_temp_free_i32(addr);
18c9b560 1781 return 1;
da6b5335 1782 }
18c9b560 1783 if (insn & ARM_CP_RW_BIT) {
d00584b7 1784 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
7d1b0095 1785 tmp = tcg_temp_new_i32();
12dcc321 1786 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
da6b5335 1787 iwmmxt_store_creg(wrd, tmp);
18c9b560 1788 } else {
e677137d
PB
1789 i = 1;
1790 if (insn & (1 << 8)) {
d00584b7 1791 if (insn & (1 << 22)) { /* WLDRD */
12dcc321 1792 gen_aa32_ld64(s, cpu_M0, addr, get_mem_index(s));
e677137d 1793 i = 0;
d00584b7 1794 } else { /* WLDRW wRd */
29531141 1795 tmp = tcg_temp_new_i32();
12dcc321 1796 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
e677137d
PB
1797 }
1798 } else {
29531141 1799 tmp = tcg_temp_new_i32();
d00584b7 1800 if (insn & (1 << 22)) { /* WLDRH */
12dcc321 1801 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
d00584b7 1802 } else { /* WLDRB */
12dcc321 1803 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
e677137d
PB
1804 }
1805 }
1806 if (i) {
1807 tcg_gen_extu_i32_i64(cpu_M0, tmp);
7d1b0095 1808 tcg_temp_free_i32(tmp);
e677137d 1809 }
18c9b560
AZ
1810 gen_op_iwmmxt_movq_wRn_M0(wrd);
1811 }
1812 } else {
d00584b7 1813 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
da6b5335 1814 tmp = iwmmxt_load_creg(wrd);
12dcc321 1815 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
18c9b560
AZ
1816 } else {
1817 gen_op_iwmmxt_movq_M0_wRn(wrd);
7d1b0095 1818 tmp = tcg_temp_new_i32();
e677137d 1819 if (insn & (1 << 8)) {
d00584b7 1820 if (insn & (1 << 22)) { /* WSTRD */
12dcc321 1821 gen_aa32_st64(s, cpu_M0, addr, get_mem_index(s));
d00584b7 1822 } else { /* WSTRW wRd */
ecc7b3aa 1823 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
12dcc321 1824 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
e677137d
PB
1825 }
1826 } else {
d00584b7 1827 if (insn & (1 << 22)) { /* WSTRH */
ecc7b3aa 1828 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
12dcc321 1829 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
d00584b7 1830 } else { /* WSTRB */
ecc7b3aa 1831 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
12dcc321 1832 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
e677137d
PB
1833 }
1834 }
18c9b560 1835 }
29531141 1836 tcg_temp_free_i32(tmp);
18c9b560 1837 }
7d1b0095 1838 tcg_temp_free_i32(addr);
18c9b560
AZ
1839 return 0;
1840 }
1841
1842 if ((insn & 0x0f000000) != 0x0e000000)
1843 return 1;
1844
1845 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
d00584b7 1846 case 0x000: /* WOR */
18c9b560
AZ
1847 wrd = (insn >> 12) & 0xf;
1848 rd0 = (insn >> 0) & 0xf;
1849 rd1 = (insn >> 16) & 0xf;
1850 gen_op_iwmmxt_movq_M0_wRn(rd0);
1851 gen_op_iwmmxt_orq_M0_wRn(rd1);
1852 gen_op_iwmmxt_setpsr_nz();
1853 gen_op_iwmmxt_movq_wRn_M0(wrd);
1854 gen_op_iwmmxt_set_mup();
1855 gen_op_iwmmxt_set_cup();
1856 break;
d00584b7 1857 case 0x011: /* TMCR */
18c9b560
AZ
1858 if (insn & 0xf)
1859 return 1;
1860 rd = (insn >> 12) & 0xf;
1861 wrd = (insn >> 16) & 0xf;
1862 switch (wrd) {
1863 case ARM_IWMMXT_wCID:
1864 case ARM_IWMMXT_wCASF:
1865 break;
1866 case ARM_IWMMXT_wCon:
1867 gen_op_iwmmxt_set_cup();
1868 /* Fall through. */
1869 case ARM_IWMMXT_wCSSF:
da6b5335
FN
1870 tmp = iwmmxt_load_creg(wrd);
1871 tmp2 = load_reg(s, rd);
f669df27 1872 tcg_gen_andc_i32(tmp, tmp, tmp2);
7d1b0095 1873 tcg_temp_free_i32(tmp2);
da6b5335 1874 iwmmxt_store_creg(wrd, tmp);
18c9b560
AZ
1875 break;
1876 case ARM_IWMMXT_wCGR0:
1877 case ARM_IWMMXT_wCGR1:
1878 case ARM_IWMMXT_wCGR2:
1879 case ARM_IWMMXT_wCGR3:
1880 gen_op_iwmmxt_set_cup();
da6b5335
FN
1881 tmp = load_reg(s, rd);
1882 iwmmxt_store_creg(wrd, tmp);
18c9b560
AZ
1883 break;
1884 default:
1885 return 1;
1886 }
1887 break;
d00584b7 1888 case 0x100: /* WXOR */
18c9b560
AZ
1889 wrd = (insn >> 12) & 0xf;
1890 rd0 = (insn >> 0) & 0xf;
1891 rd1 = (insn >> 16) & 0xf;
1892 gen_op_iwmmxt_movq_M0_wRn(rd0);
1893 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1894 gen_op_iwmmxt_setpsr_nz();
1895 gen_op_iwmmxt_movq_wRn_M0(wrd);
1896 gen_op_iwmmxt_set_mup();
1897 gen_op_iwmmxt_set_cup();
1898 break;
d00584b7 1899 case 0x111: /* TMRC */
18c9b560
AZ
1900 if (insn & 0xf)
1901 return 1;
1902 rd = (insn >> 12) & 0xf;
1903 wrd = (insn >> 16) & 0xf;
da6b5335
FN
1904 tmp = iwmmxt_load_creg(wrd);
1905 store_reg(s, rd, tmp);
18c9b560 1906 break;
d00584b7 1907 case 0x300: /* WANDN */
18c9b560
AZ
1908 wrd = (insn >> 12) & 0xf;
1909 rd0 = (insn >> 0) & 0xf;
1910 rd1 = (insn >> 16) & 0xf;
1911 gen_op_iwmmxt_movq_M0_wRn(rd0);
e677137d 1912 tcg_gen_neg_i64(cpu_M0, cpu_M0);
18c9b560
AZ
1913 gen_op_iwmmxt_andq_M0_wRn(rd1);
1914 gen_op_iwmmxt_setpsr_nz();
1915 gen_op_iwmmxt_movq_wRn_M0(wrd);
1916 gen_op_iwmmxt_set_mup();
1917 gen_op_iwmmxt_set_cup();
1918 break;
d00584b7 1919 case 0x200: /* WAND */
18c9b560
AZ
1920 wrd = (insn >> 12) & 0xf;
1921 rd0 = (insn >> 0) & 0xf;
1922 rd1 = (insn >> 16) & 0xf;
1923 gen_op_iwmmxt_movq_M0_wRn(rd0);
1924 gen_op_iwmmxt_andq_M0_wRn(rd1);
1925 gen_op_iwmmxt_setpsr_nz();
1926 gen_op_iwmmxt_movq_wRn_M0(wrd);
1927 gen_op_iwmmxt_set_mup();
1928 gen_op_iwmmxt_set_cup();
1929 break;
d00584b7 1930 case 0x810: case 0xa10: /* WMADD */
18c9b560
AZ
1931 wrd = (insn >> 12) & 0xf;
1932 rd0 = (insn >> 0) & 0xf;
1933 rd1 = (insn >> 16) & 0xf;
1934 gen_op_iwmmxt_movq_M0_wRn(rd0);
1935 if (insn & (1 << 21))
1936 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1937 else
1938 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1939 gen_op_iwmmxt_movq_wRn_M0(wrd);
1940 gen_op_iwmmxt_set_mup();
1941 break;
d00584b7 1942 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
18c9b560
AZ
1943 wrd = (insn >> 12) & 0xf;
1944 rd0 = (insn >> 16) & 0xf;
1945 rd1 = (insn >> 0) & 0xf;
1946 gen_op_iwmmxt_movq_M0_wRn(rd0);
1947 switch ((insn >> 22) & 3) {
1948 case 0:
1949 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1950 break;
1951 case 1:
1952 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1953 break;
1954 case 2:
1955 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1956 break;
1957 case 3:
1958 return 1;
1959 }
1960 gen_op_iwmmxt_movq_wRn_M0(wrd);
1961 gen_op_iwmmxt_set_mup();
1962 gen_op_iwmmxt_set_cup();
1963 break;
d00584b7 1964 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
18c9b560
AZ
1965 wrd = (insn >> 12) & 0xf;
1966 rd0 = (insn >> 16) & 0xf;
1967 rd1 = (insn >> 0) & 0xf;
1968 gen_op_iwmmxt_movq_M0_wRn(rd0);
1969 switch ((insn >> 22) & 3) {
1970 case 0:
1971 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1972 break;
1973 case 1:
1974 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1975 break;
1976 case 2:
1977 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1978 break;
1979 case 3:
1980 return 1;
1981 }
1982 gen_op_iwmmxt_movq_wRn_M0(wrd);
1983 gen_op_iwmmxt_set_mup();
1984 gen_op_iwmmxt_set_cup();
1985 break;
d00584b7 1986 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
18c9b560
AZ
1987 wrd = (insn >> 12) & 0xf;
1988 rd0 = (insn >> 16) & 0xf;
1989 rd1 = (insn >> 0) & 0xf;
1990 gen_op_iwmmxt_movq_M0_wRn(rd0);
1991 if (insn & (1 << 22))
1992 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1993 else
1994 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1995 if (!(insn & (1 << 20)))
1996 gen_op_iwmmxt_addl_M0_wRn(wrd);
1997 gen_op_iwmmxt_movq_wRn_M0(wrd);
1998 gen_op_iwmmxt_set_mup();
1999 break;
d00584b7 2000 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
18c9b560
AZ
2001 wrd = (insn >> 12) & 0xf;
2002 rd0 = (insn >> 16) & 0xf;
2003 rd1 = (insn >> 0) & 0xf;
2004 gen_op_iwmmxt_movq_M0_wRn(rd0);
e677137d
PB
2005 if (insn & (1 << 21)) {
2006 if (insn & (1 << 20))
2007 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
2008 else
2009 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
2010 } else {
2011 if (insn & (1 << 20))
2012 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
2013 else
2014 gen_op_iwmmxt_mululw_M0_wRn(rd1);
2015 }
18c9b560
AZ
2016 gen_op_iwmmxt_movq_wRn_M0(wrd);
2017 gen_op_iwmmxt_set_mup();
2018 break;
d00584b7 2019 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
18c9b560
AZ
2020 wrd = (insn >> 12) & 0xf;
2021 rd0 = (insn >> 16) & 0xf;
2022 rd1 = (insn >> 0) & 0xf;
2023 gen_op_iwmmxt_movq_M0_wRn(rd0);
2024 if (insn & (1 << 21))
2025 gen_op_iwmmxt_macsw_M0_wRn(rd1);
2026 else
2027 gen_op_iwmmxt_macuw_M0_wRn(rd1);
2028 if (!(insn & (1 << 20))) {
e677137d
PB
2029 iwmmxt_load_reg(cpu_V1, wrd);
2030 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
18c9b560
AZ
2031 }
2032 gen_op_iwmmxt_movq_wRn_M0(wrd);
2033 gen_op_iwmmxt_set_mup();
2034 break;
d00584b7 2035 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
18c9b560
AZ
2036 wrd = (insn >> 12) & 0xf;
2037 rd0 = (insn >> 16) & 0xf;
2038 rd1 = (insn >> 0) & 0xf;
2039 gen_op_iwmmxt_movq_M0_wRn(rd0);
2040 switch ((insn >> 22) & 3) {
2041 case 0:
2042 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
2043 break;
2044 case 1:
2045 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
2046 break;
2047 case 2:
2048 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
2049 break;
2050 case 3:
2051 return 1;
2052 }
2053 gen_op_iwmmxt_movq_wRn_M0(wrd);
2054 gen_op_iwmmxt_set_mup();
2055 gen_op_iwmmxt_set_cup();
2056 break;
d00584b7 2057 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
18c9b560
AZ
2058 wrd = (insn >> 12) & 0xf;
2059 rd0 = (insn >> 16) & 0xf;
2060 rd1 = (insn >> 0) & 0xf;
2061 gen_op_iwmmxt_movq_M0_wRn(rd0);
e677137d
PB
2062 if (insn & (1 << 22)) {
2063 if (insn & (1 << 20))
2064 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
2065 else
2066 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
2067 } else {
2068 if (insn & (1 << 20))
2069 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
2070 else
2071 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
2072 }
18c9b560
AZ
2073 gen_op_iwmmxt_movq_wRn_M0(wrd);
2074 gen_op_iwmmxt_set_mup();
2075 gen_op_iwmmxt_set_cup();
2076 break;
d00584b7 2077 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
18c9b560
AZ
2078 wrd = (insn >> 12) & 0xf;
2079 rd0 = (insn >> 16) & 0xf;
2080 rd1 = (insn >> 0) & 0xf;
2081 gen_op_iwmmxt_movq_M0_wRn(rd0);
da6b5335
FN
2082 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
2083 tcg_gen_andi_i32(tmp, tmp, 7);
2084 iwmmxt_load_reg(cpu_V1, rd1);
2085 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
7d1b0095 2086 tcg_temp_free_i32(tmp);
18c9b560
AZ
2087 gen_op_iwmmxt_movq_wRn_M0(wrd);
2088 gen_op_iwmmxt_set_mup();
2089 break;
d00584b7 2090 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
da6b5335
FN
2091 if (((insn >> 6) & 3) == 3)
2092 return 1;
18c9b560
AZ
2093 rd = (insn >> 12) & 0xf;
2094 wrd = (insn >> 16) & 0xf;
da6b5335 2095 tmp = load_reg(s, rd);
18c9b560
AZ
2096 gen_op_iwmmxt_movq_M0_wRn(wrd);
2097 switch ((insn >> 6) & 3) {
2098 case 0:
da6b5335
FN
2099 tmp2 = tcg_const_i32(0xff);
2100 tmp3 = tcg_const_i32((insn & 7) << 3);
18c9b560
AZ
2101 break;
2102 case 1:
da6b5335
FN
2103 tmp2 = tcg_const_i32(0xffff);
2104 tmp3 = tcg_const_i32((insn & 3) << 4);
18c9b560
AZ
2105 break;
2106 case 2:
da6b5335
FN
2107 tmp2 = tcg_const_i32(0xffffffff);
2108 tmp3 = tcg_const_i32((insn & 1) << 5);
18c9b560 2109 break;
da6b5335 2110 default:
f764718d
RH
2111 tmp2 = NULL;
2112 tmp3 = NULL;
18c9b560 2113 }
da6b5335 2114 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
39d5492a
PM
2115 tcg_temp_free_i32(tmp3);
2116 tcg_temp_free_i32(tmp2);
7d1b0095 2117 tcg_temp_free_i32(tmp);
18c9b560
AZ
2118 gen_op_iwmmxt_movq_wRn_M0(wrd);
2119 gen_op_iwmmxt_set_mup();
2120 break;
d00584b7 2121 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
18c9b560
AZ
2122 rd = (insn >> 12) & 0xf;
2123 wrd = (insn >> 16) & 0xf;
da6b5335 2124 if (rd == 15 || ((insn >> 22) & 3) == 3)
18c9b560
AZ
2125 return 1;
2126 gen_op_iwmmxt_movq_M0_wRn(wrd);
7d1b0095 2127 tmp = tcg_temp_new_i32();
18c9b560
AZ
2128 switch ((insn >> 22) & 3) {
2129 case 0:
da6b5335 2130 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
ecc7b3aa 2131 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
da6b5335
FN
2132 if (insn & 8) {
2133 tcg_gen_ext8s_i32(tmp, tmp);
2134 } else {
2135 tcg_gen_andi_i32(tmp, tmp, 0xff);
18c9b560
AZ
2136 }
2137 break;
2138 case 1:
da6b5335 2139 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
ecc7b3aa 2140 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
da6b5335
FN
2141 if (insn & 8) {
2142 tcg_gen_ext16s_i32(tmp, tmp);
2143 } else {
2144 tcg_gen_andi_i32(tmp, tmp, 0xffff);
18c9b560
AZ
2145 }
2146 break;
2147 case 2:
da6b5335 2148 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
ecc7b3aa 2149 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
18c9b560 2150 break;
18c9b560 2151 }
da6b5335 2152 store_reg(s, rd, tmp);
18c9b560 2153 break;
d00584b7 2154 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
da6b5335 2155 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
18c9b560 2156 return 1;
da6b5335 2157 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
18c9b560
AZ
2158 switch ((insn >> 22) & 3) {
2159 case 0:
da6b5335 2160 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
18c9b560
AZ
2161 break;
2162 case 1:
da6b5335 2163 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
18c9b560
AZ
2164 break;
2165 case 2:
da6b5335 2166 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
18c9b560 2167 break;
18c9b560 2168 }
da6b5335
FN
2169 tcg_gen_shli_i32(tmp, tmp, 28);
2170 gen_set_nzcv(tmp);
7d1b0095 2171 tcg_temp_free_i32(tmp);
18c9b560 2172 break;
d00584b7 2173 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
da6b5335
FN
2174 if (((insn >> 6) & 3) == 3)
2175 return 1;
18c9b560
AZ
2176 rd = (insn >> 12) & 0xf;
2177 wrd = (insn >> 16) & 0xf;
da6b5335 2178 tmp = load_reg(s, rd);
18c9b560
AZ
2179 switch ((insn >> 6) & 3) {
2180 case 0:
da6b5335 2181 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
18c9b560
AZ
2182 break;
2183 case 1:
da6b5335 2184 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
18c9b560
AZ
2185 break;
2186 case 2:
da6b5335 2187 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
18c9b560 2188 break;
18c9b560 2189 }
7d1b0095 2190 tcg_temp_free_i32(tmp);
18c9b560
AZ
2191 gen_op_iwmmxt_movq_wRn_M0(wrd);
2192 gen_op_iwmmxt_set_mup();
2193 break;
d00584b7 2194 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
da6b5335 2195 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
18c9b560 2196 return 1;
da6b5335 2197 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
7d1b0095 2198 tmp2 = tcg_temp_new_i32();
da6b5335 2199 tcg_gen_mov_i32(tmp2, tmp);
18c9b560
AZ
2200 switch ((insn >> 22) & 3) {
2201 case 0:
2202 for (i = 0; i < 7; i ++) {
da6b5335
FN
2203 tcg_gen_shli_i32(tmp2, tmp2, 4);
2204 tcg_gen_and_i32(tmp, tmp, tmp2);
18c9b560
AZ
2205 }
2206 break;
2207 case 1:
2208 for (i = 0; i < 3; i ++) {
da6b5335
FN
2209 tcg_gen_shli_i32(tmp2, tmp2, 8);
2210 tcg_gen_and_i32(tmp, tmp, tmp2);
18c9b560
AZ
2211 }
2212 break;
2213 case 2:
da6b5335
FN
2214 tcg_gen_shli_i32(tmp2, tmp2, 16);
2215 tcg_gen_and_i32(tmp, tmp, tmp2);
18c9b560 2216 break;
18c9b560 2217 }
da6b5335 2218 gen_set_nzcv(tmp);
7d1b0095
PM
2219 tcg_temp_free_i32(tmp2);
2220 tcg_temp_free_i32(tmp);
18c9b560 2221 break;
d00584b7 2222 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
18c9b560
AZ
2223 wrd = (insn >> 12) & 0xf;
2224 rd0 = (insn >> 16) & 0xf;
2225 gen_op_iwmmxt_movq_M0_wRn(rd0);
2226 switch ((insn >> 22) & 3) {
2227 case 0:
e677137d 2228 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
18c9b560
AZ
2229 break;
2230 case 1:
e677137d 2231 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
18c9b560
AZ
2232 break;
2233 case 2:
e677137d 2234 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
18c9b560
AZ
2235 break;
2236 case 3:
2237 return 1;
2238 }
2239 gen_op_iwmmxt_movq_wRn_M0(wrd);
2240 gen_op_iwmmxt_set_mup();
2241 break;
d00584b7 2242 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
da6b5335 2243 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
18c9b560 2244 return 1;
da6b5335 2245 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
7d1b0095 2246 tmp2 = tcg_temp_new_i32();
da6b5335 2247 tcg_gen_mov_i32(tmp2, tmp);
18c9b560
AZ
2248 switch ((insn >> 22) & 3) {
2249 case 0:
2250 for (i = 0; i < 7; i ++) {
da6b5335
FN
2251 tcg_gen_shli_i32(tmp2, tmp2, 4);
2252 tcg_gen_or_i32(tmp, tmp, tmp2);
18c9b560
AZ
2253 }
2254 break;
2255 case 1:
2256 for (i = 0; i < 3; i ++) {
da6b5335
FN
2257 tcg_gen_shli_i32(tmp2, tmp2, 8);
2258 tcg_gen_or_i32(tmp, tmp, tmp2);
18c9b560
AZ
2259 }
2260 break;
2261 case 2:
da6b5335
FN
2262 tcg_gen_shli_i32(tmp2, tmp2, 16);
2263 tcg_gen_or_i32(tmp, tmp, tmp2);
18c9b560 2264 break;
18c9b560 2265 }
da6b5335 2266 gen_set_nzcv(tmp);
7d1b0095
PM
2267 tcg_temp_free_i32(tmp2);
2268 tcg_temp_free_i32(tmp);
18c9b560 2269 break;
d00584b7 2270 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
18c9b560
AZ
2271 rd = (insn >> 12) & 0xf;
2272 rd0 = (insn >> 16) & 0xf;
da6b5335 2273 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
18c9b560
AZ
2274 return 1;
2275 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2276 tmp = tcg_temp_new_i32();
18c9b560
AZ
2277 switch ((insn >> 22) & 3) {
2278 case 0:
da6b5335 2279 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
18c9b560
AZ
2280 break;
2281 case 1:
da6b5335 2282 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
18c9b560
AZ
2283 break;
2284 case 2:
da6b5335 2285 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
18c9b560 2286 break;
18c9b560 2287 }
da6b5335 2288 store_reg(s, rd, tmp);
18c9b560 2289 break;
d00584b7 2290 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
18c9b560
AZ
2291 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2292 wrd = (insn >> 12) & 0xf;
2293 rd0 = (insn >> 16) & 0xf;
2294 rd1 = (insn >> 0) & 0xf;
2295 gen_op_iwmmxt_movq_M0_wRn(rd0);
2296 switch ((insn >> 22) & 3) {
2297 case 0:
2298 if (insn & (1 << 21))
2299 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2300 else
2301 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2302 break;
2303 case 1:
2304 if (insn & (1 << 21))
2305 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2306 else
2307 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2308 break;
2309 case 2:
2310 if (insn & (1 << 21))
2311 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2312 else
2313 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2314 break;
2315 case 3:
2316 return 1;
2317 }
2318 gen_op_iwmmxt_movq_wRn_M0(wrd);
2319 gen_op_iwmmxt_set_mup();
2320 gen_op_iwmmxt_set_cup();
2321 break;
d00584b7 2322 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
18c9b560
AZ
2323 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2324 wrd = (insn >> 12) & 0xf;
2325 rd0 = (insn >> 16) & 0xf;
2326 gen_op_iwmmxt_movq_M0_wRn(rd0);
2327 switch ((insn >> 22) & 3) {
2328 case 0:
2329 if (insn & (1 << 21))
2330 gen_op_iwmmxt_unpacklsb_M0();
2331 else
2332 gen_op_iwmmxt_unpacklub_M0();
2333 break;
2334 case 1:
2335 if (insn & (1 << 21))
2336 gen_op_iwmmxt_unpacklsw_M0();
2337 else
2338 gen_op_iwmmxt_unpackluw_M0();
2339 break;
2340 case 2:
2341 if (insn & (1 << 21))
2342 gen_op_iwmmxt_unpacklsl_M0();
2343 else
2344 gen_op_iwmmxt_unpacklul_M0();
2345 break;
2346 case 3:
2347 return 1;
2348 }
2349 gen_op_iwmmxt_movq_wRn_M0(wrd);
2350 gen_op_iwmmxt_set_mup();
2351 gen_op_iwmmxt_set_cup();
2352 break;
d00584b7 2353 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
18c9b560
AZ
2354 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2355 wrd = (insn >> 12) & 0xf;
2356 rd0 = (insn >> 16) & 0xf;
2357 gen_op_iwmmxt_movq_M0_wRn(rd0);
2358 switch ((insn >> 22) & 3) {
2359 case 0:
2360 if (insn & (1 << 21))
2361 gen_op_iwmmxt_unpackhsb_M0();
2362 else
2363 gen_op_iwmmxt_unpackhub_M0();
2364 break;
2365 case 1:
2366 if (insn & (1 << 21))
2367 gen_op_iwmmxt_unpackhsw_M0();
2368 else
2369 gen_op_iwmmxt_unpackhuw_M0();
2370 break;
2371 case 2:
2372 if (insn & (1 << 21))
2373 gen_op_iwmmxt_unpackhsl_M0();
2374 else
2375 gen_op_iwmmxt_unpackhul_M0();
2376 break;
2377 case 3:
2378 return 1;
2379 }
2380 gen_op_iwmmxt_movq_wRn_M0(wrd);
2381 gen_op_iwmmxt_set_mup();
2382 gen_op_iwmmxt_set_cup();
2383 break;
d00584b7 2384 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
18c9b560 2385 case 0x214: case 0x614: case 0xa14: case 0xe14:
da6b5335
FN
2386 if (((insn >> 22) & 3) == 0)
2387 return 1;
18c9b560
AZ
2388 wrd = (insn >> 12) & 0xf;
2389 rd0 = (insn >> 16) & 0xf;
2390 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2391 tmp = tcg_temp_new_i32();
da6b5335 2392 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
7d1b0095 2393 tcg_temp_free_i32(tmp);
18c9b560 2394 return 1;
da6b5335 2395 }
18c9b560 2396 switch ((insn >> 22) & 3) {
18c9b560 2397 case 1:
477955bd 2398 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2399 break;
2400 case 2:
477955bd 2401 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2402 break;
2403 case 3:
477955bd 2404 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2405 break;
2406 }
7d1b0095 2407 tcg_temp_free_i32(tmp);
18c9b560
AZ
2408 gen_op_iwmmxt_movq_wRn_M0(wrd);
2409 gen_op_iwmmxt_set_mup();
2410 gen_op_iwmmxt_set_cup();
2411 break;
d00584b7 2412 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
18c9b560 2413 case 0x014: case 0x414: case 0x814: case 0xc14:
da6b5335
FN
2414 if (((insn >> 22) & 3) == 0)
2415 return 1;
18c9b560
AZ
2416 wrd = (insn >> 12) & 0xf;
2417 rd0 = (insn >> 16) & 0xf;
2418 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2419 tmp = tcg_temp_new_i32();
da6b5335 2420 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
7d1b0095 2421 tcg_temp_free_i32(tmp);
18c9b560 2422 return 1;
da6b5335 2423 }
18c9b560 2424 switch ((insn >> 22) & 3) {
18c9b560 2425 case 1:
477955bd 2426 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2427 break;
2428 case 2:
477955bd 2429 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2430 break;
2431 case 3:
477955bd 2432 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2433 break;
2434 }
7d1b0095 2435 tcg_temp_free_i32(tmp);
18c9b560
AZ
2436 gen_op_iwmmxt_movq_wRn_M0(wrd);
2437 gen_op_iwmmxt_set_mup();
2438 gen_op_iwmmxt_set_cup();
2439 break;
d00584b7 2440 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
18c9b560 2441 case 0x114: case 0x514: case 0x914: case 0xd14:
da6b5335
FN
2442 if (((insn >> 22) & 3) == 0)
2443 return 1;
18c9b560
AZ
2444 wrd = (insn >> 12) & 0xf;
2445 rd0 = (insn >> 16) & 0xf;
2446 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2447 tmp = tcg_temp_new_i32();
da6b5335 2448 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
7d1b0095 2449 tcg_temp_free_i32(tmp);
18c9b560 2450 return 1;
da6b5335 2451 }
18c9b560 2452 switch ((insn >> 22) & 3) {
18c9b560 2453 case 1:
477955bd 2454 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2455 break;
2456 case 2:
477955bd 2457 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2458 break;
2459 case 3:
477955bd 2460 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2461 break;
2462 }
7d1b0095 2463 tcg_temp_free_i32(tmp);
18c9b560
AZ
2464 gen_op_iwmmxt_movq_wRn_M0(wrd);
2465 gen_op_iwmmxt_set_mup();
2466 gen_op_iwmmxt_set_cup();
2467 break;
d00584b7 2468 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
18c9b560 2469 case 0x314: case 0x714: case 0xb14: case 0xf14:
da6b5335
FN
2470 if (((insn >> 22) & 3) == 0)
2471 return 1;
18c9b560
AZ
2472 wrd = (insn >> 12) & 0xf;
2473 rd0 = (insn >> 16) & 0xf;
2474 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2475 tmp = tcg_temp_new_i32();
18c9b560 2476 switch ((insn >> 22) & 3) {
18c9b560 2477 case 1:
da6b5335 2478 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
7d1b0095 2479 tcg_temp_free_i32(tmp);
18c9b560 2480 return 1;
da6b5335 2481 }
477955bd 2482 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2483 break;
2484 case 2:
da6b5335 2485 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
7d1b0095 2486 tcg_temp_free_i32(tmp);
18c9b560 2487 return 1;
da6b5335 2488 }
477955bd 2489 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2490 break;
2491 case 3:
da6b5335 2492 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
7d1b0095 2493 tcg_temp_free_i32(tmp);
18c9b560 2494 return 1;
da6b5335 2495 }
477955bd 2496 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2497 break;
2498 }
7d1b0095 2499 tcg_temp_free_i32(tmp);
18c9b560
AZ
2500 gen_op_iwmmxt_movq_wRn_M0(wrd);
2501 gen_op_iwmmxt_set_mup();
2502 gen_op_iwmmxt_set_cup();
2503 break;
d00584b7 2504 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
18c9b560
AZ
2505 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2506 wrd = (insn >> 12) & 0xf;
2507 rd0 = (insn >> 16) & 0xf;
2508 rd1 = (insn >> 0) & 0xf;
2509 gen_op_iwmmxt_movq_M0_wRn(rd0);
2510 switch ((insn >> 22) & 3) {
2511 case 0:
2512 if (insn & (1 << 21))
2513 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2514 else
2515 gen_op_iwmmxt_minub_M0_wRn(rd1);
2516 break;
2517 case 1:
2518 if (insn & (1 << 21))
2519 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2520 else
2521 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2522 break;
2523 case 2:
2524 if (insn & (1 << 21))
2525 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2526 else
2527 gen_op_iwmmxt_minul_M0_wRn(rd1);
2528 break;
2529 case 3:
2530 return 1;
2531 }
2532 gen_op_iwmmxt_movq_wRn_M0(wrd);
2533 gen_op_iwmmxt_set_mup();
2534 break;
d00584b7 2535 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
18c9b560
AZ
2536 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2537 wrd = (insn >> 12) & 0xf;
2538 rd0 = (insn >> 16) & 0xf;
2539 rd1 = (insn >> 0) & 0xf;
2540 gen_op_iwmmxt_movq_M0_wRn(rd0);
2541 switch ((insn >> 22) & 3) {
2542 case 0:
2543 if (insn & (1 << 21))
2544 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2545 else
2546 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2547 break;
2548 case 1:
2549 if (insn & (1 << 21))
2550 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2551 else
2552 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2553 break;
2554 case 2:
2555 if (insn & (1 << 21))
2556 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2557 else
2558 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2559 break;
2560 case 3:
2561 return 1;
2562 }
2563 gen_op_iwmmxt_movq_wRn_M0(wrd);
2564 gen_op_iwmmxt_set_mup();
2565 break;
d00584b7 2566 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
18c9b560
AZ
2567 case 0x402: case 0x502: case 0x602: case 0x702:
2568 wrd = (insn >> 12) & 0xf;
2569 rd0 = (insn >> 16) & 0xf;
2570 rd1 = (insn >> 0) & 0xf;
2571 gen_op_iwmmxt_movq_M0_wRn(rd0);
da6b5335
FN
2572 tmp = tcg_const_i32((insn >> 20) & 3);
2573 iwmmxt_load_reg(cpu_V1, rd1);
2574 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
39d5492a 2575 tcg_temp_free_i32(tmp);
18c9b560
AZ
2576 gen_op_iwmmxt_movq_wRn_M0(wrd);
2577 gen_op_iwmmxt_set_mup();
2578 break;
d00584b7 2579 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
18c9b560
AZ
2580 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2581 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2582 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2583 wrd = (insn >> 12) & 0xf;
2584 rd0 = (insn >> 16) & 0xf;
2585 rd1 = (insn >> 0) & 0xf;
2586 gen_op_iwmmxt_movq_M0_wRn(rd0);
2587 switch ((insn >> 20) & 0xf) {
2588 case 0x0:
2589 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2590 break;
2591 case 0x1:
2592 gen_op_iwmmxt_subub_M0_wRn(rd1);
2593 break;
2594 case 0x3:
2595 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2596 break;
2597 case 0x4:
2598 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2599 break;
2600 case 0x5:
2601 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2602 break;
2603 case 0x7:
2604 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2605 break;
2606 case 0x8:
2607 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2608 break;
2609 case 0x9:
2610 gen_op_iwmmxt_subul_M0_wRn(rd1);
2611 break;
2612 case 0xb:
2613 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2614 break;
2615 default:
2616 return 1;
2617 }
2618 gen_op_iwmmxt_movq_wRn_M0(wrd);
2619 gen_op_iwmmxt_set_mup();
2620 gen_op_iwmmxt_set_cup();
2621 break;
d00584b7 2622 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
18c9b560
AZ
2623 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2624 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2625 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2626 wrd = (insn >> 12) & 0xf;
2627 rd0 = (insn >> 16) & 0xf;
2628 gen_op_iwmmxt_movq_M0_wRn(rd0);
da6b5335 2629 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
477955bd 2630 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
39d5492a 2631 tcg_temp_free_i32(tmp);
18c9b560
AZ
2632 gen_op_iwmmxt_movq_wRn_M0(wrd);
2633 gen_op_iwmmxt_set_mup();
2634 gen_op_iwmmxt_set_cup();
2635 break;
d00584b7 2636 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
18c9b560
AZ
2637 case 0x418: case 0x518: case 0x618: case 0x718:
2638 case 0x818: case 0x918: case 0xa18: case 0xb18:
2639 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2640 wrd = (insn >> 12) & 0xf;
2641 rd0 = (insn >> 16) & 0xf;
2642 rd1 = (insn >> 0) & 0xf;
2643 gen_op_iwmmxt_movq_M0_wRn(rd0);
2644 switch ((insn >> 20) & 0xf) {
2645 case 0x0:
2646 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2647 break;
2648 case 0x1:
2649 gen_op_iwmmxt_addub_M0_wRn(rd1);
2650 break;
2651 case 0x3:
2652 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2653 break;
2654 case 0x4:
2655 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2656 break;
2657 case 0x5:
2658 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2659 break;
2660 case 0x7:
2661 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2662 break;
2663 case 0x8:
2664 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2665 break;
2666 case 0x9:
2667 gen_op_iwmmxt_addul_M0_wRn(rd1);
2668 break;
2669 case 0xb:
2670 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2671 break;
2672 default:
2673 return 1;
2674 }
2675 gen_op_iwmmxt_movq_wRn_M0(wrd);
2676 gen_op_iwmmxt_set_mup();
2677 gen_op_iwmmxt_set_cup();
2678 break;
d00584b7 2679 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
18c9b560
AZ
2680 case 0x408: case 0x508: case 0x608: case 0x708:
2681 case 0x808: case 0x908: case 0xa08: case 0xb08:
2682 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
da6b5335
FN
2683 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2684 return 1;
18c9b560
AZ
2685 wrd = (insn >> 12) & 0xf;
2686 rd0 = (insn >> 16) & 0xf;
2687 rd1 = (insn >> 0) & 0xf;
2688 gen_op_iwmmxt_movq_M0_wRn(rd0);
18c9b560 2689 switch ((insn >> 22) & 3) {
18c9b560
AZ
2690 case 1:
2691 if (insn & (1 << 21))
2692 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2693 else
2694 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2695 break;
2696 case 2:
2697 if (insn & (1 << 21))
2698 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2699 else
2700 gen_op_iwmmxt_packul_M0_wRn(rd1);
2701 break;
2702 case 3:
2703 if (insn & (1 << 21))
2704 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2705 else
2706 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2707 break;
2708 }
2709 gen_op_iwmmxt_movq_wRn_M0(wrd);
2710 gen_op_iwmmxt_set_mup();
2711 gen_op_iwmmxt_set_cup();
2712 break;
2713 case 0x201: case 0x203: case 0x205: case 0x207:
2714 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2715 case 0x211: case 0x213: case 0x215: case 0x217:
2716 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2717 wrd = (insn >> 5) & 0xf;
2718 rd0 = (insn >> 12) & 0xf;
2719 rd1 = (insn >> 0) & 0xf;
2720 if (rd0 == 0xf || rd1 == 0xf)
2721 return 1;
2722 gen_op_iwmmxt_movq_M0_wRn(wrd);
da6b5335
FN
2723 tmp = load_reg(s, rd0);
2724 tmp2 = load_reg(s, rd1);
18c9b560 2725 switch ((insn >> 16) & 0xf) {
d00584b7 2726 case 0x0: /* TMIA */
da6b5335 2727 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560 2728 break;
d00584b7 2729 case 0x8: /* TMIAPH */
da6b5335 2730 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560 2731 break;
d00584b7 2732 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
18c9b560 2733 if (insn & (1 << 16))
da6b5335 2734 tcg_gen_shri_i32(tmp, tmp, 16);
18c9b560 2735 if (insn & (1 << 17))
da6b5335
FN
2736 tcg_gen_shri_i32(tmp2, tmp2, 16);
2737 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2738 break;
2739 default:
7d1b0095
PM
2740 tcg_temp_free_i32(tmp2);
2741 tcg_temp_free_i32(tmp);
18c9b560
AZ
2742 return 1;
2743 }
7d1b0095
PM
2744 tcg_temp_free_i32(tmp2);
2745 tcg_temp_free_i32(tmp);
18c9b560
AZ
2746 gen_op_iwmmxt_movq_wRn_M0(wrd);
2747 gen_op_iwmmxt_set_mup();
2748 break;
2749 default:
2750 return 1;
2751 }
2752
2753 return 0;
2754}
2755
a1c7273b 2756/* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
18c9b560 2757 (ie. an undefined instruction). */
7dcc1f89 2758static int disas_dsp_insn(DisasContext *s, uint32_t insn)
18c9b560
AZ
2759{
2760 int acc, rd0, rd1, rdhi, rdlo;
39d5492a 2761 TCGv_i32 tmp, tmp2;
18c9b560
AZ
2762
2763 if ((insn & 0x0ff00f10) == 0x0e200010) {
2764 /* Multiply with Internal Accumulate Format */
2765 rd0 = (insn >> 12) & 0xf;
2766 rd1 = insn & 0xf;
2767 acc = (insn >> 5) & 7;
2768
2769 if (acc != 0)
2770 return 1;
2771
3a554c0f
FN
2772 tmp = load_reg(s, rd0);
2773 tmp2 = load_reg(s, rd1);
18c9b560 2774 switch ((insn >> 16) & 0xf) {
d00584b7 2775 case 0x0: /* MIA */
3a554c0f 2776 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560 2777 break;
d00584b7 2778 case 0x8: /* MIAPH */
3a554c0f 2779 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560 2780 break;
d00584b7
PM
2781 case 0xc: /* MIABB */
2782 case 0xd: /* MIABT */
2783 case 0xe: /* MIATB */
2784 case 0xf: /* MIATT */
18c9b560 2785 if (insn & (1 << 16))
3a554c0f 2786 tcg_gen_shri_i32(tmp, tmp, 16);
18c9b560 2787 if (insn & (1 << 17))
3a554c0f
FN
2788 tcg_gen_shri_i32(tmp2, tmp2, 16);
2789 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2790 break;
2791 default:
2792 return 1;
2793 }
7d1b0095
PM
2794 tcg_temp_free_i32(tmp2);
2795 tcg_temp_free_i32(tmp);
18c9b560
AZ
2796
2797 gen_op_iwmmxt_movq_wRn_M0(acc);
2798 return 0;
2799 }
2800
2801 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2802 /* Internal Accumulator Access Format */
2803 rdhi = (insn >> 16) & 0xf;
2804 rdlo = (insn >> 12) & 0xf;
2805 acc = insn & 7;
2806
2807 if (acc != 0)
2808 return 1;
2809
d00584b7 2810 if (insn & ARM_CP_RW_BIT) { /* MRA */
3a554c0f 2811 iwmmxt_load_reg(cpu_V0, acc);
ecc7b3aa 2812 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
664b7e3b 2813 tcg_gen_extrh_i64_i32(cpu_R[rdhi], cpu_V0);
3a554c0f 2814 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
d00584b7 2815 } else { /* MAR */
3a554c0f
FN
2816 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2817 iwmmxt_store_reg(cpu_V0, acc);
18c9b560
AZ
2818 }
2819 return 0;
2820 }
2821
2822 return 1;
2823}
2824
9ee6e8bb
PB
2825#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2826#define VFP_SREG(insn, bigbit, smallbit) \
2827 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2828#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
d614a513 2829 if (arm_dc_feature(s, ARM_FEATURE_VFP3)) { \
9ee6e8bb
PB
2830 reg = (((insn) >> (bigbit)) & 0x0f) \
2831 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2832 } else { \
2833 if (insn & (1 << (smallbit))) \
2834 return 1; \
2835 reg = ((insn) >> (bigbit)) & 0x0f; \
2836 }} while (0)
2837
2838#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2839#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2840#define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2841#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2842#define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2843#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2844
39d5492a 2845static void gen_neon_dup_low16(TCGv_i32 var)
ad69471c 2846{
39d5492a 2847 TCGv_i32 tmp = tcg_temp_new_i32();
86831435 2848 tcg_gen_ext16u_i32(var, var);
ad69471c
PB
2849 tcg_gen_shli_i32(tmp, var, 16);
2850 tcg_gen_or_i32(var, var, tmp);
7d1b0095 2851 tcg_temp_free_i32(tmp);
ad69471c
PB
2852}
2853
39d5492a 2854static void gen_neon_dup_high16(TCGv_i32 var)
ad69471c 2855{
39d5492a 2856 TCGv_i32 tmp = tcg_temp_new_i32();
ad69471c
PB
2857 tcg_gen_andi_i32(var, var, 0xffff0000);
2858 tcg_gen_shri_i32(tmp, var, 16);
2859 tcg_gen_or_i32(var, var, tmp);
7d1b0095 2860 tcg_temp_free_i32(tmp);
ad69471c
PB
2861}
2862
06db8196
PM
2863/*
2864 * Disassemble a VFP instruction. Returns nonzero if an error occurred
2865 * (ie. an undefined instruction).
2866 */
7dcc1f89 2867static int disas_vfp_insn(DisasContext *s, uint32_t insn)
b7bcbe95 2868{
d614a513 2869 if (!arm_dc_feature(s, ARM_FEATURE_VFP)) {
40f137e1 2870 return 1;
d614a513 2871 }
40f137e1 2872
78e138bc
PM
2873 /*
2874 * If the decodetree decoder handles this insn it will always
2875 * emit code to either execute the insn or generate an appropriate
2876 * exception; so we don't need to ever return non-zero to tell
2877 * the calling code to emit an UNDEF exception.
2878 */
2879 if (extract32(insn, 28, 4) == 0xf) {
2880 if (disas_vfp_uncond(s, insn)) {
2881 return 0;
2882 }
2883 } else {
2884 if (disas_vfp(s, insn)) {
2885 return 0;
2886 }
2887 }
3111bfc2
PM
2888 /* If the decodetree decoder didn't handle this insn, it must be UNDEF */
2889 return 1;
b7bcbe95
FB
2890}
2891
90aa39a1 2892static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
c53be334 2893{
90aa39a1 2894#ifndef CONFIG_USER_ONLY
dcba3a8d 2895 return (s->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
a0415916 2896 ((s->base.pc_next - 1) & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
90aa39a1
SF
2897#else
2898 return true;
2899#endif
2900}
6e256c93 2901
8a6b28c7
EC
2902static void gen_goto_ptr(void)
2903{
7f11636d 2904 tcg_gen_lookup_and_goto_ptr();
8a6b28c7
EC
2905}
2906
4cae8f56
AB
2907/* This will end the TB but doesn't guarantee we'll return to
2908 * cpu_loop_exec. Any live exit_requests will be processed as we
2909 * enter the next TB.
2910 */
8a6b28c7 2911static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
90aa39a1
SF
2912{
2913 if (use_goto_tb(s, dest)) {
57fec1fe 2914 tcg_gen_goto_tb(n);
eaed129d 2915 gen_set_pc_im(s, dest);
07ea28b4 2916 tcg_gen_exit_tb(s->base.tb, n);
6e256c93 2917 } else {
eaed129d 2918 gen_set_pc_im(s, dest);
8a6b28c7 2919 gen_goto_ptr();
6e256c93 2920 }
dcba3a8d 2921 s->base.is_jmp = DISAS_NORETURN;
c53be334
FB
2922}
2923
8aaca4c0
FB
2924static inline void gen_jmp (DisasContext *s, uint32_t dest)
2925{
b636649f 2926 if (unlikely(is_singlestepping(s))) {
8aaca4c0 2927 /* An indirect jump so that we still trigger the debug exception. */
5899f386 2928 if (s->thumb)
d9ba4830
PB
2929 dest |= 1;
2930 gen_bx_im(s, dest);
8aaca4c0 2931 } else {
6e256c93 2932 gen_goto_tb(s, 0, dest);
8aaca4c0
FB
2933 }
2934}
2935
39d5492a 2936static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
b5ff1b31 2937{
ee097184 2938 if (x)
d9ba4830 2939 tcg_gen_sari_i32(t0, t0, 16);
b5ff1b31 2940 else
d9ba4830 2941 gen_sxth(t0);
ee097184 2942 if (y)
d9ba4830 2943 tcg_gen_sari_i32(t1, t1, 16);
b5ff1b31 2944 else
d9ba4830
PB
2945 gen_sxth(t1);
2946 tcg_gen_mul_i32(t0, t0, t1);
b5ff1b31
FB
2947}
2948
2949/* Return the mask of PSR bits set by a MSR instruction. */
7dcc1f89
PM
2950static uint32_t msr_mask(DisasContext *s, int flags, int spsr)
2951{
b5ff1b31
FB
2952 uint32_t mask;
2953
2954 mask = 0;
2955 if (flags & (1 << 0))
2956 mask |= 0xff;
2957 if (flags & (1 << 1))
2958 mask |= 0xff00;
2959 if (flags & (1 << 2))
2960 mask |= 0xff0000;
2961 if (flags & (1 << 3))
2962 mask |= 0xff000000;
9ee6e8bb 2963
2ae23e75 2964 /* Mask out undefined bits. */
9ee6e8bb 2965 mask &= ~CPSR_RESERVED;
d614a513 2966 if (!arm_dc_feature(s, ARM_FEATURE_V4T)) {
be5e7a76 2967 mask &= ~CPSR_T;
d614a513
PM
2968 }
2969 if (!arm_dc_feature(s, ARM_FEATURE_V5)) {
be5e7a76 2970 mask &= ~CPSR_Q; /* V5TE in reality*/
d614a513
PM
2971 }
2972 if (!arm_dc_feature(s, ARM_FEATURE_V6)) {
e160c51c 2973 mask &= ~(CPSR_E | CPSR_GE);
d614a513
PM
2974 }
2975 if (!arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
e160c51c 2976 mask &= ~CPSR_IT;
d614a513 2977 }
4051e12c
PM
2978 /* Mask out execution state and reserved bits. */
2979 if (!spsr) {
2980 mask &= ~(CPSR_EXEC | CPSR_RESERVED);
2981 }
b5ff1b31
FB
2982 /* Mask out privileged bits. */
2983 if (IS_USER(s))
9ee6e8bb 2984 mask &= CPSR_USER;
b5ff1b31
FB
2985 return mask;
2986}
2987
2fbac54b 2988/* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
39d5492a 2989static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
b5ff1b31 2990{
39d5492a 2991 TCGv_i32 tmp;
b5ff1b31
FB
2992 if (spsr) {
2993 /* ??? This is also undefined in system mode. */
2994 if (IS_USER(s))
2995 return 1;
d9ba4830
PB
2996
2997 tmp = load_cpu_field(spsr);
2998 tcg_gen_andi_i32(tmp, tmp, ~mask);
2fbac54b
FN
2999 tcg_gen_andi_i32(t0, t0, mask);
3000 tcg_gen_or_i32(tmp, tmp, t0);
d9ba4830 3001 store_cpu_field(tmp, spsr);
b5ff1b31 3002 } else {
2fbac54b 3003 gen_set_cpsr(t0, mask);
b5ff1b31 3004 }
7d1b0095 3005 tcg_temp_free_i32(t0);
b5ff1b31
FB
3006 gen_lookup_tb(s);
3007 return 0;
3008}
3009
2fbac54b
FN
3010/* Returns nonzero if access to the PSR is not permitted. */
3011static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3012{
39d5492a 3013 TCGv_i32 tmp;
7d1b0095 3014 tmp = tcg_temp_new_i32();
2fbac54b
FN
3015 tcg_gen_movi_i32(tmp, val);
3016 return gen_set_psr(s, mask, spsr, tmp);
3017}
3018
8bfd0550
PM
3019static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
3020 int *tgtmode, int *regno)
3021{
3022 /* Decode the r and sysm fields of MSR/MRS banked accesses into
3023 * the target mode and register number, and identify the various
3024 * unpredictable cases.
3025 * MSR (banked) and MRS (banked) are CONSTRAINED UNPREDICTABLE if:
3026 * + executed in user mode
3027 * + using R15 as the src/dest register
3028 * + accessing an unimplemented register
3029 * + accessing a register that's inaccessible at current PL/security state*
3030 * + accessing a register that you could access with a different insn
3031 * We choose to UNDEF in all these cases.
3032 * Since we don't know which of the various AArch32 modes we are in
3033 * we have to defer some checks to runtime.
3034 * Accesses to Monitor mode registers from Secure EL1 (which implies
3035 * that EL3 is AArch64) must trap to EL3.
3036 *
3037 * If the access checks fail this function will emit code to take
3038 * an exception and return false. Otherwise it will return true,
3039 * and set *tgtmode and *regno appropriately.
3040 */
3041 int exc_target = default_exception_el(s);
3042
3043 /* These instructions are present only in ARMv8, or in ARMv7 with the
3044 * Virtualization Extensions.
3045 */
3046 if (!arm_dc_feature(s, ARM_FEATURE_V8) &&
3047 !arm_dc_feature(s, ARM_FEATURE_EL2)) {
3048 goto undef;
3049 }
3050
3051 if (IS_USER(s) || rn == 15) {
3052 goto undef;
3053 }
3054
3055 /* The table in the v8 ARM ARM section F5.2.3 describes the encoding
3056 * of registers into (r, sysm).
3057 */
3058 if (r) {
3059 /* SPSRs for other modes */
3060 switch (sysm) {
3061 case 0xe: /* SPSR_fiq */
3062 *tgtmode = ARM_CPU_MODE_FIQ;
3063 break;
3064 case 0x10: /* SPSR_irq */
3065 *tgtmode = ARM_CPU_MODE_IRQ;
3066 break;
3067 case 0x12: /* SPSR_svc */
3068 *tgtmode = ARM_CPU_MODE_SVC;
3069 break;
3070 case 0x14: /* SPSR_abt */
3071 *tgtmode = ARM_CPU_MODE_ABT;
3072 break;
3073 case 0x16: /* SPSR_und */
3074 *tgtmode = ARM_CPU_MODE_UND;
3075 break;
3076 case 0x1c: /* SPSR_mon */
3077 *tgtmode = ARM_CPU_MODE_MON;
3078 break;
3079 case 0x1e: /* SPSR_hyp */
3080 *tgtmode = ARM_CPU_MODE_HYP;
3081 break;
3082 default: /* unallocated */
3083 goto undef;
3084 }
3085 /* We arbitrarily assign SPSR a register number of 16. */
3086 *regno = 16;
3087 } else {
3088 /* general purpose registers for other modes */
3089 switch (sysm) {
3090 case 0x0 ... 0x6: /* 0b00xxx : r8_usr ... r14_usr */
3091 *tgtmode = ARM_CPU_MODE_USR;
3092 *regno = sysm + 8;
3093 break;
3094 case 0x8 ... 0xe: /* 0b01xxx : r8_fiq ... r14_fiq */
3095 *tgtmode = ARM_CPU_MODE_FIQ;
3096 *regno = sysm;
3097 break;
3098 case 0x10 ... 0x11: /* 0b1000x : r14_irq, r13_irq */
3099 *tgtmode = ARM_CPU_MODE_IRQ;
3100 *regno = sysm & 1 ? 13 : 14;
3101 break;
3102 case 0x12 ... 0x13: /* 0b1001x : r14_svc, r13_svc */
3103 *tgtmode = ARM_CPU_MODE_SVC;
3104 *regno = sysm & 1 ? 13 : 14;
3105 break;
3106 case 0x14 ... 0x15: /* 0b1010x : r14_abt, r13_abt */
3107 *tgtmode = ARM_CPU_MODE_ABT;
3108 *regno = sysm & 1 ? 13 : 14;
3109 break;
3110 case 0x16 ... 0x17: /* 0b1011x : r14_und, r13_und */
3111 *tgtmode = ARM_CPU_MODE_UND;
3112 *regno = sysm & 1 ? 13 : 14;
3113 break;
3114 case 0x1c ... 0x1d: /* 0b1110x : r14_mon, r13_mon */
3115 *tgtmode = ARM_CPU_MODE_MON;
3116 *regno = sysm & 1 ? 13 : 14;
3117 break;
3118 case 0x1e ... 0x1f: /* 0b1111x : elr_hyp, r13_hyp */
3119 *tgtmode = ARM_CPU_MODE_HYP;
3120 /* Arbitrarily pick 17 for ELR_Hyp (which is not a banked LR!) */
3121 *regno = sysm & 1 ? 13 : 17;
3122 break;
3123 default: /* unallocated */
3124 goto undef;
3125 }
3126 }
3127
3128 /* Catch the 'accessing inaccessible register' cases we can detect
3129 * at translate time.
3130 */
3131 switch (*tgtmode) {
3132 case ARM_CPU_MODE_MON:
3133 if (!arm_dc_feature(s, ARM_FEATURE_EL3) || s->ns) {
3134 goto undef;
3135 }
3136 if (s->current_el == 1) {
3137 /* If we're in Secure EL1 (which implies that EL3 is AArch64)
3138 * then accesses to Mon registers trap to EL3
3139 */
3140 exc_target = 3;
3141 goto undef;
3142 }
3143 break;
3144 case ARM_CPU_MODE_HYP:
aec4dd09
PM
3145 /*
3146 * SPSR_hyp and r13_hyp can only be accessed from Monitor mode
3147 * (and so we can forbid accesses from EL2 or below). elr_hyp
3148 * can be accessed also from Hyp mode, so forbid accesses from
3149 * EL0 or EL1.
8bfd0550 3150 */
aec4dd09
PM
3151 if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el < 2 ||
3152 (s->current_el < 3 && *regno != 17)) {
8bfd0550
PM
3153 goto undef;
3154 }
3155 break;
3156 default:
3157 break;
3158 }
3159
3160 return true;
3161
3162undef:
3163 /* If we get here then some access check did not pass */
a767fac8
RH
3164 gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
3165 syn_uncategorized(), exc_target);
8bfd0550
PM
3166 return false;
3167}
3168
3169static void gen_msr_banked(DisasContext *s, int r, int sysm, int rn)
3170{
3171 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
3172 int tgtmode = 0, regno = 0;
3173
3174 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
3175 return;
3176 }
3177
3178 /* Sync state because msr_banked() can raise exceptions */
3179 gen_set_condexec(s);
43722a6d 3180 gen_set_pc_im(s, s->pc_curr);
8bfd0550
PM
3181 tcg_reg = load_reg(s, rn);
3182 tcg_tgtmode = tcg_const_i32(tgtmode);
3183 tcg_regno = tcg_const_i32(regno);
3184 gen_helper_msr_banked(cpu_env, tcg_reg, tcg_tgtmode, tcg_regno);
3185 tcg_temp_free_i32(tcg_tgtmode);
3186 tcg_temp_free_i32(tcg_regno);
3187 tcg_temp_free_i32(tcg_reg);
dcba3a8d 3188 s->base.is_jmp = DISAS_UPDATE;
8bfd0550
PM
3189}
3190
3191static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn)
3192{
3193 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
3194 int tgtmode = 0, regno = 0;
3195
3196 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
3197 return;
3198 }
3199
3200 /* Sync state because mrs_banked() can raise exceptions */
3201 gen_set_condexec(s);
43722a6d 3202 gen_set_pc_im(s, s->pc_curr);
8bfd0550
PM
3203 tcg_reg = tcg_temp_new_i32();
3204 tcg_tgtmode = tcg_const_i32(tgtmode);
3205 tcg_regno = tcg_const_i32(regno);
3206 gen_helper_mrs_banked(tcg_reg, cpu_env, tcg_tgtmode, tcg_regno);
3207 tcg_temp_free_i32(tcg_tgtmode);
3208 tcg_temp_free_i32(tcg_regno);
3209 store_reg(s, rn, tcg_reg);
dcba3a8d 3210 s->base.is_jmp = DISAS_UPDATE;
8bfd0550
PM
3211}
3212
fb0e8e79
PM
3213/* Store value to PC as for an exception return (ie don't
3214 * mask bits). The subsequent call to gen_helper_cpsr_write_eret()
3215 * will do the masking based on the new value of the Thumb bit.
3216 */
3217static void store_pc_exc_ret(DisasContext *s, TCGv_i32 pc)
b5ff1b31 3218{
fb0e8e79
PM
3219 tcg_gen_mov_i32(cpu_R[15], pc);
3220 tcg_temp_free_i32(pc);
b5ff1b31
FB
3221}
3222
b0109805 3223/* Generate a v6 exception return. Marks both values as dead. */
39d5492a 3224static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
2c0262af 3225{
fb0e8e79
PM
3226 store_pc_exc_ret(s, pc);
3227 /* The cpsr_write_eret helper will mask the low bits of PC
3228 * appropriately depending on the new Thumb bit, so it must
3229 * be called after storing the new PC.
3230 */
e69ad9df
AL
3231 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
3232 gen_io_start();
3233 }
235ea1f5 3234 gen_helper_cpsr_write_eret(cpu_env, cpsr);
7d1b0095 3235 tcg_temp_free_i32(cpsr);
b29fd33d 3236 /* Must exit loop to check un-masked IRQs */
dcba3a8d 3237 s->base.is_jmp = DISAS_EXIT;
9ee6e8bb 3238}
3b46e624 3239
fb0e8e79
PM
3240/* Generate an old-style exception return. Marks pc as dead. */
3241static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
3242{
3243 gen_rfe(s, pc, load_cpu_field(spsr));
3244}
3245
c22edfeb
AB
3246/*
3247 * For WFI we will halt the vCPU until an IRQ. For WFE and YIELD we
3248 * only call the helper when running single threaded TCG code to ensure
3249 * the next round-robin scheduled vCPU gets a crack. In MTTCG mode we
3250 * just skip this instruction. Currently the SEV/SEVL instructions
3251 * which are *one* of many ways to wake the CPU from WFE are not
3252 * implemented so we can't sleep like WFI does.
3253 */
9ee6e8bb
PB
3254static void gen_nop_hint(DisasContext *s, int val)
3255{
3256 switch (val) {
2399d4e7
EC
3257 /* When running in MTTCG we don't generate jumps to the yield and
3258 * WFE helpers as it won't affect the scheduling of other vCPUs.
3259 * If we wanted to more completely model WFE/SEV so we don't busy
3260 * spin unnecessarily we would need to do something more involved.
3261 */
c87e5a61 3262 case 1: /* yield */
2399d4e7 3263 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
a0415916 3264 gen_set_pc_im(s, s->base.pc_next);
dcba3a8d 3265 s->base.is_jmp = DISAS_YIELD;
c22edfeb 3266 }
c87e5a61 3267 break;
9ee6e8bb 3268 case 3: /* wfi */
a0415916 3269 gen_set_pc_im(s, s->base.pc_next);
dcba3a8d 3270 s->base.is_jmp = DISAS_WFI;
9ee6e8bb
PB
3271 break;
3272 case 2: /* wfe */
2399d4e7 3273 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
a0415916 3274 gen_set_pc_im(s, s->base.pc_next);
dcba3a8d 3275 s->base.is_jmp = DISAS_WFE;
c22edfeb 3276 }
72c1d3af 3277 break;
9ee6e8bb 3278 case 4: /* sev */
12b10571
MR
3279 case 5: /* sevl */
3280 /* TODO: Implement SEV, SEVL and WFE. May help SMP performance. */
9ee6e8bb
PB
3281 default: /* nop */
3282 break;
3283 }
3284}
99c475ab 3285
ad69471c 3286#define CPU_V001 cpu_V0, cpu_V0, cpu_V1
9ee6e8bb 3287
39d5492a 3288static inline void gen_neon_add(int size, TCGv_i32 t0, TCGv_i32 t1)
9ee6e8bb
PB
3289{
3290 switch (size) {
dd8fbd78
FN
3291 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
3292 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
3293 case 2: tcg_gen_add_i32(t0, t0, t1); break;
62698be3 3294 default: abort();
9ee6e8bb 3295 }
9ee6e8bb
PB
3296}
3297
39d5492a 3298static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
ad69471c
PB
3299{
3300 switch (size) {
dd8fbd78
FN
3301 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
3302 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
3303 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
ad69471c
PB
3304 default: return;
3305 }
3306}
3307
3308/* 32-bit pairwise ops end up the same as the elementwise versions. */
9ecd3c5c
RH
3309#define gen_helper_neon_pmax_s32 tcg_gen_smax_i32
3310#define gen_helper_neon_pmax_u32 tcg_gen_umax_i32
3311#define gen_helper_neon_pmin_s32 tcg_gen_smin_i32
3312#define gen_helper_neon_pmin_u32 tcg_gen_umin_i32
ad69471c 3313
ad69471c
PB
3314#define GEN_NEON_INTEGER_OP_ENV(name) do { \
3315 switch ((size << 1) | u) { \
3316 case 0: \
dd8fbd78 3317 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
3318 break; \
3319 case 1: \
dd8fbd78 3320 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
3321 break; \
3322 case 2: \
dd8fbd78 3323 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
3324 break; \
3325 case 3: \
dd8fbd78 3326 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
3327 break; \
3328 case 4: \
dd8fbd78 3329 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
3330 break; \
3331 case 5: \
dd8fbd78 3332 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
3333 break; \
3334 default: return 1; \
3335 }} while (0)
9ee6e8bb
PB
3336
3337#define GEN_NEON_INTEGER_OP(name) do { \
3338 switch ((size << 1) | u) { \
ad69471c 3339 case 0: \
dd8fbd78 3340 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
ad69471c
PB
3341 break; \
3342 case 1: \
dd8fbd78 3343 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
ad69471c
PB
3344 break; \
3345 case 2: \
dd8fbd78 3346 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
ad69471c
PB
3347 break; \
3348 case 3: \
dd8fbd78 3349 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
ad69471c
PB
3350 break; \
3351 case 4: \
dd8fbd78 3352 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
ad69471c
PB
3353 break; \
3354 case 5: \
dd8fbd78 3355 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
ad69471c 3356 break; \
9ee6e8bb
PB
3357 default: return 1; \
3358 }} while (0)
3359
39d5492a 3360static TCGv_i32 neon_load_scratch(int scratch)
9ee6e8bb 3361{
39d5492a 3362 TCGv_i32 tmp = tcg_temp_new_i32();
dd8fbd78
FN
3363 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3364 return tmp;
9ee6e8bb
PB
3365}
3366
39d5492a 3367static void neon_store_scratch(int scratch, TCGv_i32 var)
9ee6e8bb 3368{
dd8fbd78 3369 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
7d1b0095 3370 tcg_temp_free_i32(var);
9ee6e8bb
PB
3371}
3372
39d5492a 3373static inline TCGv_i32 neon_get_scalar(int size, int reg)
9ee6e8bb 3374{
39d5492a 3375 TCGv_i32 tmp;
9ee6e8bb 3376 if (size == 1) {
0fad6efc
PM
3377 tmp = neon_load_reg(reg & 7, reg >> 4);
3378 if (reg & 8) {
dd8fbd78 3379 gen_neon_dup_high16(tmp);
0fad6efc
PM
3380 } else {
3381 gen_neon_dup_low16(tmp);
dd8fbd78 3382 }
0fad6efc
PM
3383 } else {
3384 tmp = neon_load_reg(reg & 15, reg >> 4);
9ee6e8bb 3385 }
dd8fbd78 3386 return tmp;
9ee6e8bb
PB
3387}
3388
02acedf9 3389static int gen_neon_unzip(int rd, int rm, int size, int q)
19457615 3390{
b13708bb
RH
3391 TCGv_ptr pd, pm;
3392
600b828c 3393 if (!q && size == 2) {
02acedf9
PM
3394 return 1;
3395 }
b13708bb
RH
3396 pd = vfp_reg_ptr(true, rd);
3397 pm = vfp_reg_ptr(true, rm);
02acedf9
PM
3398 if (q) {
3399 switch (size) {
3400 case 0:
b13708bb 3401 gen_helper_neon_qunzip8(pd, pm);
02acedf9
PM
3402 break;
3403 case 1:
b13708bb 3404 gen_helper_neon_qunzip16(pd, pm);
02acedf9
PM
3405 break;
3406 case 2:
b13708bb 3407 gen_helper_neon_qunzip32(pd, pm);
02acedf9
PM
3408 break;
3409 default:
3410 abort();
3411 }
3412 } else {
3413 switch (size) {
3414 case 0:
b13708bb 3415 gen_helper_neon_unzip8(pd, pm);
02acedf9
PM
3416 break;
3417 case 1:
b13708bb 3418 gen_helper_neon_unzip16(pd, pm);
02acedf9
PM
3419 break;
3420 default:
3421 abort();
3422 }
3423 }
b13708bb
RH
3424 tcg_temp_free_ptr(pd);
3425 tcg_temp_free_ptr(pm);
02acedf9 3426 return 0;
19457615
FN
3427}
3428
d68a6f3a 3429static int gen_neon_zip(int rd, int rm, int size, int q)
19457615 3430{
b13708bb
RH
3431 TCGv_ptr pd, pm;
3432
600b828c 3433 if (!q && size == 2) {
d68a6f3a
PM
3434 return 1;
3435 }
b13708bb
RH
3436 pd = vfp_reg_ptr(true, rd);
3437 pm = vfp_reg_ptr(true, rm);
d68a6f3a
PM
3438 if (q) {
3439 switch (size) {
3440 case 0:
b13708bb 3441 gen_helper_neon_qzip8(pd, pm);
d68a6f3a
PM
3442 break;
3443 case 1:
b13708bb 3444 gen_helper_neon_qzip16(pd, pm);
d68a6f3a
PM
3445 break;
3446 case 2:
b13708bb 3447 gen_helper_neon_qzip32(pd, pm);
d68a6f3a
PM
3448 break;
3449 default:
3450 abort();
3451 }
3452 } else {
3453 switch (size) {
3454 case 0:
b13708bb 3455 gen_helper_neon_zip8(pd, pm);
d68a6f3a
PM
3456 break;
3457 case 1:
b13708bb 3458 gen_helper_neon_zip16(pd, pm);
d68a6f3a
PM
3459 break;
3460 default:
3461 abort();
3462 }
3463 }
b13708bb
RH
3464 tcg_temp_free_ptr(pd);
3465 tcg_temp_free_ptr(pm);
d68a6f3a 3466 return 0;
19457615
FN
3467}
3468
39d5492a 3469static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
19457615 3470{
39d5492a 3471 TCGv_i32 rd, tmp;
19457615 3472
7d1b0095
PM
3473 rd = tcg_temp_new_i32();
3474 tmp = tcg_temp_new_i32();
19457615
FN
3475
3476 tcg_gen_shli_i32(rd, t0, 8);
3477 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3478 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3479 tcg_gen_or_i32(rd, rd, tmp);
3480
3481 tcg_gen_shri_i32(t1, t1, 8);
3482 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3483 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3484 tcg_gen_or_i32(t1, t1, tmp);
3485 tcg_gen_mov_i32(t0, rd);
3486
7d1b0095
PM
3487 tcg_temp_free_i32(tmp);
3488 tcg_temp_free_i32(rd);
19457615
FN
3489}
3490
39d5492a 3491static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
19457615 3492{
39d5492a 3493 TCGv_i32 rd, tmp;
19457615 3494
7d1b0095
PM
3495 rd = tcg_temp_new_i32();
3496 tmp = tcg_temp_new_i32();
19457615
FN
3497
3498 tcg_gen_shli_i32(rd, t0, 16);
3499 tcg_gen_andi_i32(tmp, t1, 0xffff);
3500 tcg_gen_or_i32(rd, rd, tmp);
3501 tcg_gen_shri_i32(t1, t1, 16);
3502 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3503 tcg_gen_or_i32(t1, t1, tmp);
3504 tcg_gen_mov_i32(t0, rd);
3505
7d1b0095
PM
3506 tcg_temp_free_i32(tmp);
3507 tcg_temp_free_i32(rd);
19457615
FN
3508}
3509
3510
9ee6e8bb
PB
3511static struct {
3512 int nregs;
3513 int interleave;
3514 int spacing;
308e5636 3515} const neon_ls_element_type[11] = {
ac55d007
RH
3516 {1, 4, 1},
3517 {1, 4, 2},
9ee6e8bb 3518 {4, 1, 1},
ac55d007
RH
3519 {2, 2, 2},
3520 {1, 3, 1},
3521 {1, 3, 2},
9ee6e8bb
PB
3522 {3, 1, 1},
3523 {1, 1, 1},
ac55d007
RH
3524 {1, 2, 1},
3525 {1, 2, 2},
9ee6e8bb
PB
3526 {2, 1, 1}
3527};
3528
3529/* Translate a NEON load/store element instruction. Return nonzero if the
3530 instruction is invalid. */
7dcc1f89 3531static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
9ee6e8bb
PB
3532{
3533 int rd, rn, rm;
3534 int op;
3535 int nregs;
3536 int interleave;
84496233 3537 int spacing;
9ee6e8bb
PB
3538 int stride;
3539 int size;
3540 int reg;
9ee6e8bb 3541 int load;
9ee6e8bb 3542 int n;
7377c2c9 3543 int vec_size;
ac55d007 3544 int mmu_idx;
14776ab5 3545 MemOp endian;
39d5492a
PM
3546 TCGv_i32 addr;
3547 TCGv_i32 tmp;
3548 TCGv_i32 tmp2;
84496233 3549 TCGv_i64 tmp64;
9ee6e8bb 3550
2c7ffc41
PM
3551 /* FIXME: this access check should not take precedence over UNDEF
3552 * for invalid encodings; we will generate incorrect syndrome information
3553 * for attempts to execute invalid vfp/neon encodings with FP disabled.
3554 */
9dbbc748 3555 if (s->fp_excp_el) {
a767fac8 3556 gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
4be42f40 3557 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
2c7ffc41
PM
3558 return 0;
3559 }
3560
5df8bac1 3561 if (!s->vfp_enabled)
9ee6e8bb
PB
3562 return 1;
3563 VFP_DREG_D(rd, insn);
3564 rn = (insn >> 16) & 0xf;
3565 rm = insn & 0xf;
3566 load = (insn & (1 << 21)) != 0;
ac55d007
RH
3567 endian = s->be_data;
3568 mmu_idx = get_mem_index(s);
9ee6e8bb
PB
3569 if ((insn & (1 << 23)) == 0) {
3570 /* Load store all elements. */
3571 op = (insn >> 8) & 0xf;
3572 size = (insn >> 6) & 3;
84496233 3573 if (op > 10)
9ee6e8bb 3574 return 1;
f2dd89d0
PM
3575 /* Catch UNDEF cases for bad values of align field */
3576 switch (op & 0xc) {
3577 case 4:
3578 if (((insn >> 5) & 1) == 1) {
3579 return 1;
3580 }
3581 break;
3582 case 8:
3583 if (((insn >> 4) & 3) == 3) {
3584 return 1;
3585 }
3586 break;
3587 default:
3588 break;
3589 }
9ee6e8bb
PB
3590 nregs = neon_ls_element_type[op].nregs;
3591 interleave = neon_ls_element_type[op].interleave;
84496233 3592 spacing = neon_ls_element_type[op].spacing;
ac55d007 3593 if (size == 3 && (interleave | spacing) != 1) {
84496233 3594 return 1;
ac55d007 3595 }
e23f12b3
RH
3596 /* For our purposes, bytes are always little-endian. */
3597 if (size == 0) {
3598 endian = MO_LE;
3599 }
3600 /* Consecutive little-endian elements from a single register
3601 * can be promoted to a larger little-endian operation.
3602 */
3603 if (interleave == 1 && endian == MO_LE) {
3604 size = 3;
3605 }
ac55d007 3606 tmp64 = tcg_temp_new_i64();
e318a60b 3607 addr = tcg_temp_new_i32();
ac55d007 3608 tmp2 = tcg_const_i32(1 << size);
dcc65026 3609 load_reg_var(s, addr, rn);
9ee6e8bb 3610 for (reg = 0; reg < nregs; reg++) {
ac55d007
RH
3611 for (n = 0; n < 8 >> size; n++) {
3612 int xs;
3613 for (xs = 0; xs < interleave; xs++) {
3614 int tt = rd + reg + spacing * xs;
3615
3616 if (load) {
3617 gen_aa32_ld_i64(s, tmp64, addr, mmu_idx, endian | size);
3618 neon_store_element64(tt, n, size, tmp64);
3619 } else {
3620 neon_load_element64(tmp64, tt, n, size);
3621 gen_aa32_st_i64(s, tmp64, addr, mmu_idx, endian | size);
9ee6e8bb 3622 }
ac55d007 3623 tcg_gen_add_i32(addr, addr, tmp2);
9ee6e8bb
PB
3624 }
3625 }
9ee6e8bb 3626 }
e318a60b 3627 tcg_temp_free_i32(addr);
ac55d007
RH
3628 tcg_temp_free_i32(tmp2);
3629 tcg_temp_free_i64(tmp64);
3630 stride = nregs * interleave * 8;
9ee6e8bb
PB
3631 } else {
3632 size = (insn >> 10) & 3;
3633 if (size == 3) {
3634 /* Load single element to all lanes. */
8e18cde3
PM
3635 int a = (insn >> 4) & 1;
3636 if (!load) {
9ee6e8bb 3637 return 1;
8e18cde3 3638 }
9ee6e8bb
PB
3639 size = (insn >> 6) & 3;
3640 nregs = ((insn >> 8) & 3) + 1;
8e18cde3
PM
3641
3642 if (size == 3) {
3643 if (nregs != 4 || a == 0) {
9ee6e8bb 3644 return 1;
99c475ab 3645 }
8e18cde3
PM
3646 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
3647 size = 2;
3648 }
3649 if (nregs == 1 && a == 1 && size == 0) {
3650 return 1;
3651 }
3652 if (nregs == 3 && a == 1) {
3653 return 1;
3654 }
e318a60b 3655 addr = tcg_temp_new_i32();
8e18cde3 3656 load_reg_var(s, addr, rn);
7377c2c9
RH
3657
3658 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write.
3659 * VLD2/3/4 to all lanes: bit 5 indicates register stride.
3660 */
3661 stride = (insn & (1 << 5)) ? 2 : 1;
3662 vec_size = nregs == 1 ? stride * 8 : 8;
3663
3664 tmp = tcg_temp_new_i32();
3665 for (reg = 0; reg < nregs; reg++) {
3666 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
3667 s->be_data | size);
3668 if ((rd & 1) && vec_size == 16) {
3669 /* We cannot write 16 bytes at once because the
3670 * destination is unaligned.
3671 */
3672 tcg_gen_gvec_dup_i32(size, neon_reg_offset(rd, 0),
3673 8, 8, tmp);
3674 tcg_gen_gvec_mov(0, neon_reg_offset(rd + 1, 0),
3675 neon_reg_offset(rd, 0), 8, 8);
3676 } else {
3677 tcg_gen_gvec_dup_i32(size, neon_reg_offset(rd, 0),
3678 vec_size, vec_size, tmp);
8e18cde3 3679 }
7377c2c9
RH
3680 tcg_gen_addi_i32(addr, addr, 1 << size);
3681 rd += stride;
9ee6e8bb 3682 }
7377c2c9 3683 tcg_temp_free_i32(tmp);
e318a60b 3684 tcg_temp_free_i32(addr);
9ee6e8bb
PB
3685 stride = (1 << size) * nregs;
3686 } else {
3687 /* Single element. */
93262b16 3688 int idx = (insn >> 4) & 0xf;
2d6ac920 3689 int reg_idx;
9ee6e8bb
PB
3690 switch (size) {
3691 case 0:
2d6ac920 3692 reg_idx = (insn >> 5) & 7;
9ee6e8bb
PB
3693 stride = 1;
3694 break;
3695 case 1:
2d6ac920 3696 reg_idx = (insn >> 6) & 3;
9ee6e8bb
PB
3697 stride = (insn & (1 << 5)) ? 2 : 1;
3698 break;
3699 case 2:
2d6ac920 3700 reg_idx = (insn >> 7) & 1;
9ee6e8bb
PB
3701 stride = (insn & (1 << 6)) ? 2 : 1;
3702 break;
3703 default:
3704 abort();
3705 }
3706 nregs = ((insn >> 8) & 3) + 1;
93262b16
PM
3707 /* Catch the UNDEF cases. This is unavoidably a bit messy. */
3708 switch (nregs) {
3709 case 1:
3710 if (((idx & (1 << size)) != 0) ||
3711 (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
3712 return 1;
3713 }
3714 break;
3715 case 3:
3716 if ((idx & 1) != 0) {
3717 return 1;
3718 }
3719 /* fall through */
3720 case 2:
3721 if (size == 2 && (idx & 2) != 0) {
3722 return 1;
3723 }
3724 break;
3725 case 4:
3726 if ((size == 2) && ((idx & 3) == 3)) {
3727 return 1;
3728 }
3729 break;
3730 default:
3731 abort();
3732 }
3733 if ((rd + stride * (nregs - 1)) > 31) {
3734 /* Attempts to write off the end of the register file
3735 * are UNPREDICTABLE; we choose to UNDEF because otherwise
3736 * the neon_load_reg() would write off the end of the array.
3737 */
3738 return 1;
3739 }
2d6ac920 3740 tmp = tcg_temp_new_i32();
e318a60b 3741 addr = tcg_temp_new_i32();
dcc65026 3742 load_reg_var(s, addr, rn);
9ee6e8bb
PB
3743 for (reg = 0; reg < nregs; reg++) {
3744 if (load) {
2d6ac920
RH
3745 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
3746 s->be_data | size);
3747 neon_store_element(rd, reg_idx, size, tmp);
9ee6e8bb 3748 } else { /* Store */
2d6ac920
RH
3749 neon_load_element(tmp, rd, reg_idx, size);
3750 gen_aa32_st_i32(s, tmp, addr, get_mem_index(s),
3751 s->be_data | size);
99c475ab 3752 }
9ee6e8bb 3753 rd += stride;
1b2b1e54 3754 tcg_gen_addi_i32(addr, addr, 1 << size);
99c475ab 3755 }
e318a60b 3756 tcg_temp_free_i32(addr);
2d6ac920 3757 tcg_temp_free_i32(tmp);
9ee6e8bb 3758 stride = nregs * (1 << size);
99c475ab 3759 }
9ee6e8bb
PB
3760 }
3761 if (rm != 15) {
39d5492a 3762 TCGv_i32 base;
b26eefb6
PB
3763
3764 base = load_reg(s, rn);
9ee6e8bb 3765 if (rm == 13) {
b26eefb6 3766 tcg_gen_addi_i32(base, base, stride);
9ee6e8bb 3767 } else {
39d5492a 3768 TCGv_i32 index;
b26eefb6
PB
3769 index = load_reg(s, rm);
3770 tcg_gen_add_i32(base, base, index);
7d1b0095 3771 tcg_temp_free_i32(index);
9ee6e8bb 3772 }
b26eefb6 3773 store_reg(s, rn, base);
9ee6e8bb
PB
3774 }
3775 return 0;
3776}
3b46e624 3777
39d5492a 3778static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src)
ad69471c
PB
3779{
3780 switch (size) {
3781 case 0: gen_helper_neon_narrow_u8(dest, src); break;
3782 case 1: gen_helper_neon_narrow_u16(dest, src); break;
ecc7b3aa 3783 case 2: tcg_gen_extrl_i64_i32(dest, src); break;
ad69471c
PB
3784 default: abort();
3785 }
3786}
3787
39d5492a 3788static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
ad69471c
PB
3789{
3790 switch (size) {
02da0b2d
PM
3791 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
3792 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
3793 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
ad69471c
PB
3794 default: abort();
3795 }
3796}
3797
39d5492a 3798static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src)
ad69471c
PB
3799{
3800 switch (size) {
02da0b2d
PM
3801 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
3802 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
3803 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
ad69471c
PB
3804 default: abort();
3805 }
3806}
3807
39d5492a 3808static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
af1bbf30
JR
3809{
3810 switch (size) {
02da0b2d
PM
3811 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
3812 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
3813 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
af1bbf30
JR
3814 default: abort();
3815 }
3816}
3817
39d5492a 3818static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift,
ad69471c
PB
3819 int q, int u)
3820{
3821 if (q) {
3822 if (u) {
3823 switch (size) {
3824 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3825 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3826 default: abort();
3827 }
3828 } else {
3829 switch (size) {
3830 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
3831 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
3832 default: abort();
3833 }
3834 }
3835 } else {
3836 if (u) {
3837 switch (size) {
b408a9b0
CL
3838 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
3839 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
ad69471c
PB
3840 default: abort();
3841 }
3842 } else {
3843 switch (size) {
3844 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
3845 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
3846 default: abort();
3847 }
3848 }
3849 }
3850}
3851
39d5492a 3852static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
ad69471c
PB
3853{
3854 if (u) {
3855 switch (size) {
3856 case 0: gen_helper_neon_widen_u8(dest, src); break;
3857 case 1: gen_helper_neon_widen_u16(dest, src); break;
3858 case 2: tcg_gen_extu_i32_i64(dest, src); break;
3859 default: abort();
3860 }
3861 } else {
3862 switch (size) {
3863 case 0: gen_helper_neon_widen_s8(dest, src); break;
3864 case 1: gen_helper_neon_widen_s16(dest, src); break;
3865 case 2: tcg_gen_ext_i32_i64(dest, src); break;
3866 default: abort();
3867 }
3868 }
7d1b0095 3869 tcg_temp_free_i32(src);
ad69471c
PB
3870}
3871
3872static inline void gen_neon_addl(int size)
3873{
3874 switch (size) {
3875 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
3876 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
3877 case 2: tcg_gen_add_i64(CPU_V001); break;
3878 default: abort();
3879 }
3880}
3881
3882static inline void gen_neon_subl(int size)
3883{
3884 switch (size) {
3885 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
3886 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
3887 case 2: tcg_gen_sub_i64(CPU_V001); break;
3888 default: abort();
3889 }
3890}
3891
a7812ae4 3892static inline void gen_neon_negl(TCGv_i64 var, int size)
ad69471c
PB
3893{
3894 switch (size) {
3895 case 0: gen_helper_neon_negl_u16(var, var); break;
3896 case 1: gen_helper_neon_negl_u32(var, var); break;
ee6fa559
PM
3897 case 2:
3898 tcg_gen_neg_i64(var, var);
3899 break;
ad69471c
PB
3900 default: abort();
3901 }
3902}
3903
a7812ae4 3904static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
ad69471c
PB
3905{
3906 switch (size) {
02da0b2d
PM
3907 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
3908 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
ad69471c
PB
3909 default: abort();
3910 }
3911}
3912
39d5492a
PM
3913static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b,
3914 int size, int u)
ad69471c 3915{
a7812ae4 3916 TCGv_i64 tmp;
ad69471c
PB
3917
3918 switch ((size << 1) | u) {
3919 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
3920 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
3921 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
3922 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
3923 case 4:
3924 tmp = gen_muls_i64_i32(a, b);
3925 tcg_gen_mov_i64(dest, tmp);
7d2aabe2 3926 tcg_temp_free_i64(tmp);
ad69471c
PB
3927 break;
3928 case 5:
3929 tmp = gen_mulu_i64_i32(a, b);
3930 tcg_gen_mov_i64(dest, tmp);
7d2aabe2 3931 tcg_temp_free_i64(tmp);
ad69471c
PB
3932 break;
3933 default: abort();
3934 }
c6067f04
CL
3935
3936 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
3937 Don't forget to clean them now. */
3938 if (size < 2) {
7d1b0095
PM
3939 tcg_temp_free_i32(a);
3940 tcg_temp_free_i32(b);
c6067f04 3941 }
ad69471c
PB
3942}
3943
39d5492a
PM
3944static void gen_neon_narrow_op(int op, int u, int size,
3945 TCGv_i32 dest, TCGv_i64 src)
c33171c7
PM
3946{
3947 if (op) {
3948 if (u) {
3949 gen_neon_unarrow_sats(size, dest, src);
3950 } else {
3951 gen_neon_narrow(size, dest, src);
3952 }
3953 } else {
3954 if (u) {
3955 gen_neon_narrow_satu(size, dest, src);
3956 } else {
3957 gen_neon_narrow_sats(size, dest, src);
3958 }
3959 }
3960}
3961
62698be3
PM
3962/* Symbolic constants for op fields for Neon 3-register same-length.
3963 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
3964 * table A7-9.
3965 */
3966#define NEON_3R_VHADD 0
3967#define NEON_3R_VQADD 1
3968#define NEON_3R_VRHADD 2
3969#define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
3970#define NEON_3R_VHSUB 4
3971#define NEON_3R_VQSUB 5
3972#define NEON_3R_VCGT 6
3973#define NEON_3R_VCGE 7
3974#define NEON_3R_VSHL 8
3975#define NEON_3R_VQSHL 9
3976#define NEON_3R_VRSHL 10
3977#define NEON_3R_VQRSHL 11
3978#define NEON_3R_VMAX 12
3979#define NEON_3R_VMIN 13
3980#define NEON_3R_VABD 14
3981#define NEON_3R_VABA 15
3982#define NEON_3R_VADD_VSUB 16
3983#define NEON_3R_VTST_VCEQ 17
4a7832b0 3984#define NEON_3R_VML 18 /* VMLA, VMLS */
62698be3
PM
3985#define NEON_3R_VMUL 19
3986#define NEON_3R_VPMAX 20
3987#define NEON_3R_VPMIN 21
3988#define NEON_3R_VQDMULH_VQRDMULH 22
36a71934 3989#define NEON_3R_VPADD_VQRDMLAH 23
f1ecb913 3990#define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */
36a71934 3991#define NEON_3R_VFM_VQRDMLSH 25 /* VFMA, VFMS, VQRDMLSH */
62698be3
PM
3992#define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
3993#define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
3994#define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
3995#define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
3996#define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
505935fc 3997#define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */
62698be3
PM
3998
3999static const uint8_t neon_3r_sizes[] = {
4000 [NEON_3R_VHADD] = 0x7,
4001 [NEON_3R_VQADD] = 0xf,
4002 [NEON_3R_VRHADD] = 0x7,
4003 [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
4004 [NEON_3R_VHSUB] = 0x7,
4005 [NEON_3R_VQSUB] = 0xf,
4006 [NEON_3R_VCGT] = 0x7,
4007 [NEON_3R_VCGE] = 0x7,
4008 [NEON_3R_VSHL] = 0xf,
4009 [NEON_3R_VQSHL] = 0xf,
4010 [NEON_3R_VRSHL] = 0xf,
4011 [NEON_3R_VQRSHL] = 0xf,
4012 [NEON_3R_VMAX] = 0x7,
4013 [NEON_3R_VMIN] = 0x7,
4014 [NEON_3R_VABD] = 0x7,
4015 [NEON_3R_VABA] = 0x7,
4016 [NEON_3R_VADD_VSUB] = 0xf,
4017 [NEON_3R_VTST_VCEQ] = 0x7,
4018 [NEON_3R_VML] = 0x7,
4019 [NEON_3R_VMUL] = 0x7,
4020 [NEON_3R_VPMAX] = 0x7,
4021 [NEON_3R_VPMIN] = 0x7,
4022 [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
36a71934 4023 [NEON_3R_VPADD_VQRDMLAH] = 0x7,
f1ecb913 4024 [NEON_3R_SHA] = 0xf, /* size field encodes op type */
36a71934 4025 [NEON_3R_VFM_VQRDMLSH] = 0x7, /* For VFM, size bit 1 encodes op */
62698be3
PM
4026 [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
4027 [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
4028 [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
4029 [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
4030 [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
505935fc 4031 [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */
62698be3
PM
4032};
4033
600b828c
PM
4034/* Symbolic constants for op fields for Neon 2-register miscellaneous.
4035 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
4036 * table A7-13.
4037 */
4038#define NEON_2RM_VREV64 0
4039#define NEON_2RM_VREV32 1
4040#define NEON_2RM_VREV16 2
4041#define NEON_2RM_VPADDL 4
4042#define NEON_2RM_VPADDL_U 5
9d935509
AB
4043#define NEON_2RM_AESE 6 /* Includes AESD */
4044#define NEON_2RM_AESMC 7 /* Includes AESIMC */
600b828c
PM
4045#define NEON_2RM_VCLS 8
4046#define NEON_2RM_VCLZ 9
4047#define NEON_2RM_VCNT 10
4048#define NEON_2RM_VMVN 11
4049#define NEON_2RM_VPADAL 12
4050#define NEON_2RM_VPADAL_U 13
4051#define NEON_2RM_VQABS 14
4052#define NEON_2RM_VQNEG 15
4053#define NEON_2RM_VCGT0 16
4054#define NEON_2RM_VCGE0 17
4055#define NEON_2RM_VCEQ0 18
4056#define NEON_2RM_VCLE0 19
4057#define NEON_2RM_VCLT0 20
f1ecb913 4058#define NEON_2RM_SHA1H 21
600b828c
PM
4059#define NEON_2RM_VABS 22
4060#define NEON_2RM_VNEG 23
4061#define NEON_2RM_VCGT0_F 24
4062#define NEON_2RM_VCGE0_F 25
4063#define NEON_2RM_VCEQ0_F 26
4064#define NEON_2RM_VCLE0_F 27
4065#define NEON_2RM_VCLT0_F 28
4066#define NEON_2RM_VABS_F 30
4067#define NEON_2RM_VNEG_F 31
4068#define NEON_2RM_VSWP 32
4069#define NEON_2RM_VTRN 33
4070#define NEON_2RM_VUZP 34
4071#define NEON_2RM_VZIP 35
4072#define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
4073#define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
4074#define NEON_2RM_VSHLL 38
f1ecb913 4075#define NEON_2RM_SHA1SU1 39 /* Includes SHA256SU0 */
34f7b0a2 4076#define NEON_2RM_VRINTN 40
2ce70625 4077#define NEON_2RM_VRINTX 41
34f7b0a2
WN
4078#define NEON_2RM_VRINTA 42
4079#define NEON_2RM_VRINTZ 43
600b828c 4080#define NEON_2RM_VCVT_F16_F32 44
34f7b0a2 4081#define NEON_2RM_VRINTM 45
600b828c 4082#define NEON_2RM_VCVT_F32_F16 46
34f7b0a2 4083#define NEON_2RM_VRINTP 47
901ad525
WN
4084#define NEON_2RM_VCVTAU 48
4085#define NEON_2RM_VCVTAS 49
4086#define NEON_2RM_VCVTNU 50
4087#define NEON_2RM_VCVTNS 51
4088#define NEON_2RM_VCVTPU 52
4089#define NEON_2RM_VCVTPS 53
4090#define NEON_2RM_VCVTMU 54
4091#define NEON_2RM_VCVTMS 55
600b828c
PM
4092#define NEON_2RM_VRECPE 56
4093#define NEON_2RM_VRSQRTE 57
4094#define NEON_2RM_VRECPE_F 58
4095#define NEON_2RM_VRSQRTE_F 59
4096#define NEON_2RM_VCVT_FS 60
4097#define NEON_2RM_VCVT_FU 61
4098#define NEON_2RM_VCVT_SF 62
4099#define NEON_2RM_VCVT_UF 63
4100
fe8fcf3d
PM
4101static bool neon_2rm_is_v8_op(int op)
4102{
4103 /* Return true if this neon 2reg-misc op is ARMv8 and up */
4104 switch (op) {
4105 case NEON_2RM_VRINTN:
4106 case NEON_2RM_VRINTA:
4107 case NEON_2RM_VRINTM:
4108 case NEON_2RM_VRINTP:
4109 case NEON_2RM_VRINTZ:
4110 case NEON_2RM_VRINTX:
4111 case NEON_2RM_VCVTAU:
4112 case NEON_2RM_VCVTAS:
4113 case NEON_2RM_VCVTNU:
4114 case NEON_2RM_VCVTNS:
4115 case NEON_2RM_VCVTPU:
4116 case NEON_2RM_VCVTPS:
4117 case NEON_2RM_VCVTMU:
4118 case NEON_2RM_VCVTMS:
4119 return true;
4120 default:
4121 return false;
4122 }
4123}
4124
600b828c
PM
4125/* Each entry in this array has bit n set if the insn allows
4126 * size value n (otherwise it will UNDEF). Since unallocated
4127 * op values will have no bits set they always UNDEF.
4128 */
4129static const uint8_t neon_2rm_sizes[] = {
4130 [NEON_2RM_VREV64] = 0x7,
4131 [NEON_2RM_VREV32] = 0x3,
4132 [NEON_2RM_VREV16] = 0x1,
4133 [NEON_2RM_VPADDL] = 0x7,
4134 [NEON_2RM_VPADDL_U] = 0x7,
9d935509
AB
4135 [NEON_2RM_AESE] = 0x1,
4136 [NEON_2RM_AESMC] = 0x1,
600b828c
PM
4137 [NEON_2RM_VCLS] = 0x7,
4138 [NEON_2RM_VCLZ] = 0x7,
4139 [NEON_2RM_VCNT] = 0x1,
4140 [NEON_2RM_VMVN] = 0x1,
4141 [NEON_2RM_VPADAL] = 0x7,
4142 [NEON_2RM_VPADAL_U] = 0x7,
4143 [NEON_2RM_VQABS] = 0x7,
4144 [NEON_2RM_VQNEG] = 0x7,
4145 [NEON_2RM_VCGT0] = 0x7,
4146 [NEON_2RM_VCGE0] = 0x7,
4147 [NEON_2RM_VCEQ0] = 0x7,
4148 [NEON_2RM_VCLE0] = 0x7,
4149 [NEON_2RM_VCLT0] = 0x7,
f1ecb913 4150 [NEON_2RM_SHA1H] = 0x4,
600b828c
PM
4151 [NEON_2RM_VABS] = 0x7,
4152 [NEON_2RM_VNEG] = 0x7,
4153 [NEON_2RM_VCGT0_F] = 0x4,
4154 [NEON_2RM_VCGE0_F] = 0x4,
4155 [NEON_2RM_VCEQ0_F] = 0x4,
4156 [NEON_2RM_VCLE0_F] = 0x4,
4157 [NEON_2RM_VCLT0_F] = 0x4,
4158 [NEON_2RM_VABS_F] = 0x4,
4159 [NEON_2RM_VNEG_F] = 0x4,
4160 [NEON_2RM_VSWP] = 0x1,
4161 [NEON_2RM_VTRN] = 0x7,
4162 [NEON_2RM_VUZP] = 0x7,
4163 [NEON_2RM_VZIP] = 0x7,
4164 [NEON_2RM_VMOVN] = 0x7,
4165 [NEON_2RM_VQMOVN] = 0x7,
4166 [NEON_2RM_VSHLL] = 0x7,
f1ecb913 4167 [NEON_2RM_SHA1SU1] = 0x4,
34f7b0a2 4168 [NEON_2RM_VRINTN] = 0x4,
2ce70625 4169 [NEON_2RM_VRINTX] = 0x4,
34f7b0a2
WN
4170 [NEON_2RM_VRINTA] = 0x4,
4171 [NEON_2RM_VRINTZ] = 0x4,
600b828c 4172 [NEON_2RM_VCVT_F16_F32] = 0x2,
34f7b0a2 4173 [NEON_2RM_VRINTM] = 0x4,
600b828c 4174 [NEON_2RM_VCVT_F32_F16] = 0x2,
34f7b0a2 4175 [NEON_2RM_VRINTP] = 0x4,
901ad525
WN
4176 [NEON_2RM_VCVTAU] = 0x4,
4177 [NEON_2RM_VCVTAS] = 0x4,
4178 [NEON_2RM_VCVTNU] = 0x4,
4179 [NEON_2RM_VCVTNS] = 0x4,
4180 [NEON_2RM_VCVTPU] = 0x4,
4181 [NEON_2RM_VCVTPS] = 0x4,
4182 [NEON_2RM_VCVTMU] = 0x4,
4183 [NEON_2RM_VCVTMS] = 0x4,
600b828c
PM
4184 [NEON_2RM_VRECPE] = 0x4,
4185 [NEON_2RM_VRSQRTE] = 0x4,
4186 [NEON_2RM_VRECPE_F] = 0x4,
4187 [NEON_2RM_VRSQRTE_F] = 0x4,
4188 [NEON_2RM_VCVT_FS] = 0x4,
4189 [NEON_2RM_VCVT_FU] = 0x4,
4190 [NEON_2RM_VCVT_SF] = 0x4,
4191 [NEON_2RM_VCVT_UF] = 0x4,
4192};
4193
36a71934
RH
4194
4195/* Expand v8.1 simd helper. */
4196static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
4197 int q, int rd, int rn, int rm)
4198{
962fcbf2 4199 if (dc_isar_feature(aa32_rdm, s)) {
36a71934
RH
4200 int opr_sz = (1 + q) * 8;
4201 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
4202 vfp_reg_offset(1, rn),
4203 vfp_reg_offset(1, rm), cpu_env,
4204 opr_sz, opr_sz, 0, fn);
4205 return 0;
4206 }
4207 return 1;
4208}
4209
41f6c113
RH
4210static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4211{
4212 tcg_gen_vec_sar8i_i64(a, a, shift);
4213 tcg_gen_vec_add8_i64(d, d, a);
4214}
4215
4216static void gen_ssra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4217{
4218 tcg_gen_vec_sar16i_i64(a, a, shift);
4219 tcg_gen_vec_add16_i64(d, d, a);
4220}
4221
4222static void gen_ssra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
4223{
4224 tcg_gen_sari_i32(a, a, shift);
4225 tcg_gen_add_i32(d, d, a);
4226}
4227
4228static void gen_ssra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4229{
4230 tcg_gen_sari_i64(a, a, shift);
4231 tcg_gen_add_i64(d, d, a);
4232}
4233
4234static void gen_ssra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
4235{
4236 tcg_gen_sari_vec(vece, a, a, sh);
4237 tcg_gen_add_vec(vece, d, d, a);
4238}
4239
53229a77
RH
4240static const TCGOpcode vecop_list_ssra[] = {
4241 INDEX_op_sari_vec, INDEX_op_add_vec, 0
4242};
4243
41f6c113
RH
4244const GVecGen2i ssra_op[4] = {
4245 { .fni8 = gen_ssra8_i64,
4246 .fniv = gen_ssra_vec,
4247 .load_dest = true,
53229a77 4248 .opt_opc = vecop_list_ssra,
41f6c113
RH
4249 .vece = MO_8 },
4250 { .fni8 = gen_ssra16_i64,
4251 .fniv = gen_ssra_vec,
4252 .load_dest = true,
53229a77 4253 .opt_opc = vecop_list_ssra,
41f6c113
RH
4254 .vece = MO_16 },
4255 { .fni4 = gen_ssra32_i32,
4256 .fniv = gen_ssra_vec,
4257 .load_dest = true,
53229a77 4258 .opt_opc = vecop_list_ssra,
41f6c113
RH
4259 .vece = MO_32 },
4260 { .fni8 = gen_ssra64_i64,
4261 .fniv = gen_ssra_vec,
4262 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
53229a77 4263 .opt_opc = vecop_list_ssra,
41f6c113 4264 .load_dest = true,
41f6c113
RH
4265 .vece = MO_64 },
4266};
4267
4268static void gen_usra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4269{
4270 tcg_gen_vec_shr8i_i64(a, a, shift);
4271 tcg_gen_vec_add8_i64(d, d, a);
4272}
4273
4274static void gen_usra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4275{
4276 tcg_gen_vec_shr16i_i64(a, a, shift);
4277 tcg_gen_vec_add16_i64(d, d, a);
4278}
4279
4280static void gen_usra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
4281{
4282 tcg_gen_shri_i32(a, a, shift);
4283 tcg_gen_add_i32(d, d, a);
4284}
4285
4286static void gen_usra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4287{
4288 tcg_gen_shri_i64(a, a, shift);
4289 tcg_gen_add_i64(d, d, a);
4290}
4291
4292static void gen_usra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
4293{
4294 tcg_gen_shri_vec(vece, a, a, sh);
4295 tcg_gen_add_vec(vece, d, d, a);
4296}
4297
53229a77
RH
4298static const TCGOpcode vecop_list_usra[] = {
4299 INDEX_op_shri_vec, INDEX_op_add_vec, 0
4300};
4301
41f6c113
RH
4302const GVecGen2i usra_op[4] = {
4303 { .fni8 = gen_usra8_i64,
4304 .fniv = gen_usra_vec,
4305 .load_dest = true,
53229a77 4306 .opt_opc = vecop_list_usra,
41f6c113
RH
4307 .vece = MO_8, },
4308 { .fni8 = gen_usra16_i64,
4309 .fniv = gen_usra_vec,
4310 .load_dest = true,
53229a77 4311 .opt_opc = vecop_list_usra,
41f6c113
RH
4312 .vece = MO_16, },
4313 { .fni4 = gen_usra32_i32,
4314 .fniv = gen_usra_vec,
4315 .load_dest = true,
53229a77 4316 .opt_opc = vecop_list_usra,
41f6c113
RH
4317 .vece = MO_32, },
4318 { .fni8 = gen_usra64_i64,
4319 .fniv = gen_usra_vec,
4320 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4321 .load_dest = true,
53229a77 4322 .opt_opc = vecop_list_usra,
41f6c113
RH
4323 .vece = MO_64, },
4324};
eabcd6fa 4325
f3cd8218
RH
4326static void gen_shr8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4327{
4328 uint64_t mask = dup_const(MO_8, 0xff >> shift);
4329 TCGv_i64 t = tcg_temp_new_i64();
4330
4331 tcg_gen_shri_i64(t, a, shift);
4332 tcg_gen_andi_i64(t, t, mask);
4333 tcg_gen_andi_i64(d, d, ~mask);
4334 tcg_gen_or_i64(d, d, t);
4335 tcg_temp_free_i64(t);
4336}
4337
4338static void gen_shr16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4339{
4340 uint64_t mask = dup_const(MO_16, 0xffff >> shift);
4341 TCGv_i64 t = tcg_temp_new_i64();
4342
4343 tcg_gen_shri_i64(t, a, shift);
4344 tcg_gen_andi_i64(t, t, mask);
4345 tcg_gen_andi_i64(d, d, ~mask);
4346 tcg_gen_or_i64(d, d, t);
4347 tcg_temp_free_i64(t);
4348}
4349
4350static void gen_shr32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
4351{
4352 tcg_gen_shri_i32(a, a, shift);
4353 tcg_gen_deposit_i32(d, d, a, 0, 32 - shift);
4354}
4355
4356static void gen_shr64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4357{
4358 tcg_gen_shri_i64(a, a, shift);
4359 tcg_gen_deposit_i64(d, d, a, 0, 64 - shift);
4360}
4361
4362static void gen_shr_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
4363{
4364 if (sh == 0) {
4365 tcg_gen_mov_vec(d, a);
4366 } else {
4367 TCGv_vec t = tcg_temp_new_vec_matching(d);
4368 TCGv_vec m = tcg_temp_new_vec_matching(d);
4369
4370 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK((8 << vece) - sh, sh));
4371 tcg_gen_shri_vec(vece, t, a, sh);
4372 tcg_gen_and_vec(vece, d, d, m);
4373 tcg_gen_or_vec(vece, d, d, t);
4374
4375 tcg_temp_free_vec(t);
4376 tcg_temp_free_vec(m);
4377 }
4378}
4379
53229a77
RH
4380static const TCGOpcode vecop_list_sri[] = { INDEX_op_shri_vec, 0 };
4381
f3cd8218
RH
4382const GVecGen2i sri_op[4] = {
4383 { .fni8 = gen_shr8_ins_i64,
4384 .fniv = gen_shr_ins_vec,
4385 .load_dest = true,
53229a77 4386 .opt_opc = vecop_list_sri,
f3cd8218
RH
4387 .vece = MO_8 },
4388 { .fni8 = gen_shr16_ins_i64,
4389 .fniv = gen_shr_ins_vec,
4390 .load_dest = true,
53229a77 4391 .opt_opc = vecop_list_sri,
f3cd8218
RH
4392 .vece = MO_16 },
4393 { .fni4 = gen_shr32_ins_i32,
4394 .fniv = gen_shr_ins_vec,
4395 .load_dest = true,
53229a77 4396 .opt_opc = vecop_list_sri,
f3cd8218
RH
4397 .vece = MO_32 },
4398 { .fni8 = gen_shr64_ins_i64,
4399 .fniv = gen_shr_ins_vec,
4400 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4401 .load_dest = true,
53229a77 4402 .opt_opc = vecop_list_sri,
f3cd8218
RH
4403 .vece = MO_64 },
4404};
4405
4406static void gen_shl8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4407{
4408 uint64_t mask = dup_const(MO_8, 0xff << shift);
4409 TCGv_i64 t = tcg_temp_new_i64();
4410
4411 tcg_gen_shli_i64(t, a, shift);
4412 tcg_gen_andi_i64(t, t, mask);
4413 tcg_gen_andi_i64(d, d, ~mask);
4414 tcg_gen_or_i64(d, d, t);
4415 tcg_temp_free_i64(t);
4416}
4417
4418static void gen_shl16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4419{
4420 uint64_t mask = dup_const(MO_16, 0xffff << shift);
4421 TCGv_i64 t = tcg_temp_new_i64();
4422
4423 tcg_gen_shli_i64(t, a, shift);
4424 tcg_gen_andi_i64(t, t, mask);
4425 tcg_gen_andi_i64(d, d, ~mask);
4426 tcg_gen_or_i64(d, d, t);
4427 tcg_temp_free_i64(t);
4428}
4429
4430static void gen_shl32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
4431{
4432 tcg_gen_deposit_i32(d, d, a, shift, 32 - shift);
4433}
4434
4435static void gen_shl64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4436{
4437 tcg_gen_deposit_i64(d, d, a, shift, 64 - shift);
4438}
4439
4440static void gen_shl_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
4441{
4442 if (sh == 0) {
4443 tcg_gen_mov_vec(d, a);
4444 } else {
4445 TCGv_vec t = tcg_temp_new_vec_matching(d);
4446 TCGv_vec m = tcg_temp_new_vec_matching(d);
4447
4448 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK(0, sh));
4449 tcg_gen_shli_vec(vece, t, a, sh);
4450 tcg_gen_and_vec(vece, d, d, m);
4451 tcg_gen_or_vec(vece, d, d, t);
4452
4453 tcg_temp_free_vec(t);
4454 tcg_temp_free_vec(m);
4455 }
4456}
4457
53229a77
RH
4458static const TCGOpcode vecop_list_sli[] = { INDEX_op_shli_vec, 0 };
4459
f3cd8218
RH
4460const GVecGen2i sli_op[4] = {
4461 { .fni8 = gen_shl8_ins_i64,
4462 .fniv = gen_shl_ins_vec,
4463 .load_dest = true,
53229a77 4464 .opt_opc = vecop_list_sli,
f3cd8218
RH
4465 .vece = MO_8 },
4466 { .fni8 = gen_shl16_ins_i64,
4467 .fniv = gen_shl_ins_vec,
4468 .load_dest = true,
53229a77 4469 .opt_opc = vecop_list_sli,
f3cd8218
RH
4470 .vece = MO_16 },
4471 { .fni4 = gen_shl32_ins_i32,
4472 .fniv = gen_shl_ins_vec,
4473 .load_dest = true,
53229a77 4474 .opt_opc = vecop_list_sli,
f3cd8218
RH
4475 .vece = MO_32 },
4476 { .fni8 = gen_shl64_ins_i64,
4477 .fniv = gen_shl_ins_vec,
4478 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4479 .load_dest = true,
53229a77 4480 .opt_opc = vecop_list_sli,
f3cd8218
RH
4481 .vece = MO_64 },
4482};
4483
4a7832b0
RH
4484static void gen_mla8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4485{
4486 gen_helper_neon_mul_u8(a, a, b);
4487 gen_helper_neon_add_u8(d, d, a);
4488}
4489
4490static void gen_mls8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4491{
4492 gen_helper_neon_mul_u8(a, a, b);
4493 gen_helper_neon_sub_u8(d, d, a);
4494}
4495
4496static void gen_mla16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4497{
4498 gen_helper_neon_mul_u16(a, a, b);
4499 gen_helper_neon_add_u16(d, d, a);
4500}
4501
4502static void gen_mls16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4503{
4504 gen_helper_neon_mul_u16(a, a, b);
4505 gen_helper_neon_sub_u16(d, d, a);
4506}
4507
4508static void gen_mla32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4509{
4510 tcg_gen_mul_i32(a, a, b);
4511 tcg_gen_add_i32(d, d, a);
4512}
4513
4514static void gen_mls32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4515{
4516 tcg_gen_mul_i32(a, a, b);
4517 tcg_gen_sub_i32(d, d, a);
4518}
4519
4520static void gen_mla64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4521{
4522 tcg_gen_mul_i64(a, a, b);
4523 tcg_gen_add_i64(d, d, a);
4524}
4525
4526static void gen_mls64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4527{
4528 tcg_gen_mul_i64(a, a, b);
4529 tcg_gen_sub_i64(d, d, a);
4530}
4531
4532static void gen_mla_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4533{
4534 tcg_gen_mul_vec(vece, a, a, b);
4535 tcg_gen_add_vec(vece, d, d, a);
4536}
4537
4538static void gen_mls_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4539{
4540 tcg_gen_mul_vec(vece, a, a, b);
4541 tcg_gen_sub_vec(vece, d, d, a);
4542}
4543
4544/* Note that while NEON does not support VMLA and VMLS as 64-bit ops,
4545 * these tables are shared with AArch64 which does support them.
4546 */
53229a77
RH
4547
4548static const TCGOpcode vecop_list_mla[] = {
4549 INDEX_op_mul_vec, INDEX_op_add_vec, 0
4550};
4551
4552static const TCGOpcode vecop_list_mls[] = {
4553 INDEX_op_mul_vec, INDEX_op_sub_vec, 0
4554};
4555
4a7832b0
RH
4556const GVecGen3 mla_op[4] = {
4557 { .fni4 = gen_mla8_i32,
4558 .fniv = gen_mla_vec,
4a7832b0 4559 .load_dest = true,
53229a77 4560 .opt_opc = vecop_list_mla,
4a7832b0
RH
4561 .vece = MO_8 },
4562 { .fni4 = gen_mla16_i32,
4563 .fniv = gen_mla_vec,
4a7832b0 4564 .load_dest = true,
53229a77 4565 .opt_opc = vecop_list_mla,
4a7832b0
RH
4566 .vece = MO_16 },
4567 { .fni4 = gen_mla32_i32,
4568 .fniv = gen_mla_vec,
4a7832b0 4569 .load_dest = true,
53229a77 4570 .opt_opc = vecop_list_mla,
4a7832b0
RH
4571 .vece = MO_32 },
4572 { .fni8 = gen_mla64_i64,
4573 .fniv = gen_mla_vec,
4a7832b0
RH
4574 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4575 .load_dest = true,
53229a77 4576 .opt_opc = vecop_list_mla,
4a7832b0
RH
4577 .vece = MO_64 },
4578};
4579
4580const GVecGen3 mls_op[4] = {
4581 { .fni4 = gen_mls8_i32,
4582 .fniv = gen_mls_vec,
4a7832b0 4583 .load_dest = true,
53229a77 4584 .opt_opc = vecop_list_mls,
4a7832b0
RH
4585 .vece = MO_8 },
4586 { .fni4 = gen_mls16_i32,
4587 .fniv = gen_mls_vec,
4a7832b0 4588 .load_dest = true,
53229a77 4589 .opt_opc = vecop_list_mls,
4a7832b0
RH
4590 .vece = MO_16 },
4591 { .fni4 = gen_mls32_i32,
4592 .fniv = gen_mls_vec,
4a7832b0 4593 .load_dest = true,
53229a77 4594 .opt_opc = vecop_list_mls,
4a7832b0
RH
4595 .vece = MO_32 },
4596 { .fni8 = gen_mls64_i64,
4597 .fniv = gen_mls_vec,
4a7832b0
RH
4598 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4599 .load_dest = true,
53229a77 4600 .opt_opc = vecop_list_mls,
4a7832b0
RH
4601 .vece = MO_64 },
4602};
4603
ea580fa3
RH
4604/* CMTST : test is "if (X & Y != 0)". */
4605static void gen_cmtst_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4606{
4607 tcg_gen_and_i32(d, a, b);
4608 tcg_gen_setcondi_i32(TCG_COND_NE, d, d, 0);
4609 tcg_gen_neg_i32(d, d);
4610}
4611
4612void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4613{
4614 tcg_gen_and_i64(d, a, b);
4615 tcg_gen_setcondi_i64(TCG_COND_NE, d, d, 0);
4616 tcg_gen_neg_i64(d, d);
4617}
4618
4619static void gen_cmtst_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4620{
4621 tcg_gen_and_vec(vece, d, a, b);
4622 tcg_gen_dupi_vec(vece, a, 0);
4623 tcg_gen_cmp_vec(TCG_COND_NE, vece, d, d, a);
4624}
4625
53229a77
RH
4626static const TCGOpcode vecop_list_cmtst[] = { INDEX_op_cmp_vec, 0 };
4627
ea580fa3
RH
4628const GVecGen3 cmtst_op[4] = {
4629 { .fni4 = gen_helper_neon_tst_u8,
4630 .fniv = gen_cmtst_vec,
53229a77 4631 .opt_opc = vecop_list_cmtst,
ea580fa3
RH
4632 .vece = MO_8 },
4633 { .fni4 = gen_helper_neon_tst_u16,
4634 .fniv = gen_cmtst_vec,
53229a77 4635 .opt_opc = vecop_list_cmtst,
ea580fa3
RH
4636 .vece = MO_16 },
4637 { .fni4 = gen_cmtst_i32,
4638 .fniv = gen_cmtst_vec,
53229a77 4639 .opt_opc = vecop_list_cmtst,
ea580fa3
RH
4640 .vece = MO_32 },
4641 { .fni8 = gen_cmtst_i64,
4642 .fniv = gen_cmtst_vec,
4643 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
53229a77 4644 .opt_opc = vecop_list_cmtst,
ea580fa3
RH
4645 .vece = MO_64 },
4646};
4647
89e68b57
RH
4648static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4649 TCGv_vec a, TCGv_vec b)
4650{
4651 TCGv_vec x = tcg_temp_new_vec_matching(t);
4652 tcg_gen_add_vec(vece, x, a, b);
4653 tcg_gen_usadd_vec(vece, t, a, b);
4654 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4655 tcg_gen_or_vec(vece, sat, sat, x);
4656 tcg_temp_free_vec(x);
4657}
4658
53229a77
RH
4659static const TCGOpcode vecop_list_uqadd[] = {
4660 INDEX_op_usadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
4661};
4662
89e68b57
RH
4663const GVecGen4 uqadd_op[4] = {
4664 { .fniv = gen_uqadd_vec,
4665 .fno = gen_helper_gvec_uqadd_b,
89e68b57 4666 .write_aofs = true,
53229a77 4667 .opt_opc = vecop_list_uqadd,
89e68b57
RH
4668 .vece = MO_8 },
4669 { .fniv = gen_uqadd_vec,
4670 .fno = gen_helper_gvec_uqadd_h,
89e68b57 4671 .write_aofs = true,
53229a77 4672 .opt_opc = vecop_list_uqadd,
89e68b57
RH
4673 .vece = MO_16 },
4674 { .fniv = gen_uqadd_vec,
4675 .fno = gen_helper_gvec_uqadd_s,
89e68b57 4676 .write_aofs = true,
53229a77 4677 .opt_opc = vecop_list_uqadd,
89e68b57
RH
4678 .vece = MO_32 },
4679 { .fniv = gen_uqadd_vec,
4680 .fno = gen_helper_gvec_uqadd_d,
89e68b57 4681 .write_aofs = true,
53229a77 4682 .opt_opc = vecop_list_uqadd,
89e68b57
RH
4683 .vece = MO_64 },
4684};
4685
4686static void gen_sqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4687 TCGv_vec a, TCGv_vec b)
4688{
4689 TCGv_vec x = tcg_temp_new_vec_matching(t);
4690 tcg_gen_add_vec(vece, x, a, b);
4691 tcg_gen_ssadd_vec(vece, t, a, b);
4692 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4693 tcg_gen_or_vec(vece, sat, sat, x);
4694 tcg_temp_free_vec(x);
4695}
4696
53229a77
RH
4697static const TCGOpcode vecop_list_sqadd[] = {
4698 INDEX_op_ssadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
4699};
4700
89e68b57
RH
4701const GVecGen4 sqadd_op[4] = {
4702 { .fniv = gen_sqadd_vec,
4703 .fno = gen_helper_gvec_sqadd_b,
53229a77 4704 .opt_opc = vecop_list_sqadd,
89e68b57
RH
4705 .write_aofs = true,
4706 .vece = MO_8 },
4707 { .fniv = gen_sqadd_vec,
4708 .fno = gen_helper_gvec_sqadd_h,
53229a77 4709 .opt_opc = vecop_list_sqadd,
89e68b57
RH
4710 .write_aofs = true,
4711 .vece = MO_16 },
4712 { .fniv = gen_sqadd_vec,
4713 .fno = gen_helper_gvec_sqadd_s,
53229a77 4714 .opt_opc = vecop_list_sqadd,
89e68b57
RH
4715 .write_aofs = true,
4716 .vece = MO_32 },
4717 { .fniv = gen_sqadd_vec,
4718 .fno = gen_helper_gvec_sqadd_d,
53229a77 4719 .opt_opc = vecop_list_sqadd,
89e68b57
RH
4720 .write_aofs = true,
4721 .vece = MO_64 },
4722};
4723
4724static void gen_uqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4725 TCGv_vec a, TCGv_vec b)
4726{
4727 TCGv_vec x = tcg_temp_new_vec_matching(t);
4728 tcg_gen_sub_vec(vece, x, a, b);
4729 tcg_gen_ussub_vec(vece, t, a, b);
4730 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4731 tcg_gen_or_vec(vece, sat, sat, x);
4732 tcg_temp_free_vec(x);
4733}
4734
53229a77
RH
4735static const TCGOpcode vecop_list_uqsub[] = {
4736 INDEX_op_ussub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
4737};
4738
89e68b57
RH
4739const GVecGen4 uqsub_op[4] = {
4740 { .fniv = gen_uqsub_vec,
4741 .fno = gen_helper_gvec_uqsub_b,
53229a77 4742 .opt_opc = vecop_list_uqsub,
89e68b57
RH
4743 .write_aofs = true,
4744 .vece = MO_8 },
4745 { .fniv = gen_uqsub_vec,
4746 .fno = gen_helper_gvec_uqsub_h,
53229a77 4747 .opt_opc = vecop_list_uqsub,
89e68b57
RH
4748 .write_aofs = true,
4749 .vece = MO_16 },
4750 { .fniv = gen_uqsub_vec,
4751 .fno = gen_helper_gvec_uqsub_s,
53229a77 4752 .opt_opc = vecop_list_uqsub,
89e68b57
RH
4753 .write_aofs = true,
4754 .vece = MO_32 },
4755 { .fniv = gen_uqsub_vec,
4756 .fno = gen_helper_gvec_uqsub_d,
53229a77 4757 .opt_opc = vecop_list_uqsub,
89e68b57
RH
4758 .write_aofs = true,
4759 .vece = MO_64 },
4760};
4761
4762static void gen_sqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4763 TCGv_vec a, TCGv_vec b)
4764{
4765 TCGv_vec x = tcg_temp_new_vec_matching(t);
4766 tcg_gen_sub_vec(vece, x, a, b);
4767 tcg_gen_sssub_vec(vece, t, a, b);
4768 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4769 tcg_gen_or_vec(vece, sat, sat, x);
4770 tcg_temp_free_vec(x);
4771}
4772
53229a77
RH
4773static const TCGOpcode vecop_list_sqsub[] = {
4774 INDEX_op_sssub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
4775};
4776
89e68b57
RH
4777const GVecGen4 sqsub_op[4] = {
4778 { .fniv = gen_sqsub_vec,
4779 .fno = gen_helper_gvec_sqsub_b,
53229a77 4780 .opt_opc = vecop_list_sqsub,
89e68b57
RH
4781 .write_aofs = true,
4782 .vece = MO_8 },
4783 { .fniv = gen_sqsub_vec,
4784 .fno = gen_helper_gvec_sqsub_h,
53229a77 4785 .opt_opc = vecop_list_sqsub,
89e68b57
RH
4786 .write_aofs = true,
4787 .vece = MO_16 },
4788 { .fniv = gen_sqsub_vec,
4789 .fno = gen_helper_gvec_sqsub_s,
53229a77 4790 .opt_opc = vecop_list_sqsub,
89e68b57
RH
4791 .write_aofs = true,
4792 .vece = MO_32 },
4793 { .fniv = gen_sqsub_vec,
4794 .fno = gen_helper_gvec_sqsub_d,
53229a77 4795 .opt_opc = vecop_list_sqsub,
89e68b57
RH
4796 .write_aofs = true,
4797 .vece = MO_64 },
4798};
4799
9ee6e8bb
PB
4800/* Translate a NEON data processing instruction. Return nonzero if the
4801 instruction is invalid.
ad69471c
PB
4802 We process data in a mixture of 32-bit and 64-bit chunks.
4803 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
2c0262af 4804
7dcc1f89 4805static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
9ee6e8bb
PB
4806{
4807 int op;
4808 int q;
eabcd6fa 4809 int rd, rn, rm, rd_ofs, rn_ofs, rm_ofs;
9ee6e8bb
PB
4810 int size;
4811 int shift;
4812 int pass;
4813 int count;
4814 int pairwise;
4815 int u;
eabcd6fa 4816 int vec_size;
f3cd8218 4817 uint32_t imm;
39d5492a 4818 TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
1a66ac61 4819 TCGv_ptr ptr1, ptr2, ptr3;
a7812ae4 4820 TCGv_i64 tmp64;
9ee6e8bb 4821
2c7ffc41
PM
4822 /* FIXME: this access check should not take precedence over UNDEF
4823 * for invalid encodings; we will generate incorrect syndrome information
4824 * for attempts to execute invalid vfp/neon encodings with FP disabled.
4825 */
9dbbc748 4826 if (s->fp_excp_el) {
a767fac8 4827 gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
4be42f40 4828 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
2c7ffc41
PM
4829 return 0;
4830 }
4831
5df8bac1 4832 if (!s->vfp_enabled)
9ee6e8bb
PB
4833 return 1;
4834 q = (insn & (1 << 6)) != 0;
4835 u = (insn >> 24) & 1;
4836 VFP_DREG_D(rd, insn);
4837 VFP_DREG_N(rn, insn);
4838 VFP_DREG_M(rm, insn);
4839 size = (insn >> 20) & 3;
eabcd6fa
RH
4840 vec_size = q ? 16 : 8;
4841 rd_ofs = neon_reg_offset(rd, 0);
4842 rn_ofs = neon_reg_offset(rn, 0);
4843 rm_ofs = neon_reg_offset(rm, 0);
4844
9ee6e8bb
PB
4845 if ((insn & (1 << 23)) == 0) {
4846 /* Three register same length. */
4847 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
62698be3
PM
4848 /* Catch invalid op and bad size combinations: UNDEF */
4849 if ((neon_3r_sizes[op] & (1 << size)) == 0) {
4850 return 1;
4851 }
25f84f79
PM
4852 /* All insns of this form UNDEF for either this condition or the
4853 * superset of cases "Q==1"; we catch the latter later.
4854 */
4855 if (q && ((rd | rn | rm) & 1)) {
4856 return 1;
4857 }
36a71934
RH
4858 switch (op) {
4859 case NEON_3R_SHA:
4860 /* The SHA-1/SHA-256 3-register instructions require special
4861 * treatment here, as their size field is overloaded as an
4862 * op type selector, and they all consume their input in a
4863 * single pass.
4864 */
f1ecb913
AB
4865 if (!q) {
4866 return 1;
4867 }
4868 if (!u) { /* SHA-1 */
962fcbf2 4869 if (!dc_isar_feature(aa32_sha1, s)) {
f1ecb913
AB
4870 return 1;
4871 }
1a66ac61
RH
4872 ptr1 = vfp_reg_ptr(true, rd);
4873 ptr2 = vfp_reg_ptr(true, rn);
4874 ptr3 = vfp_reg_ptr(true, rm);
f1ecb913 4875 tmp4 = tcg_const_i32(size);
1a66ac61 4876 gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp4);
f1ecb913
AB
4877 tcg_temp_free_i32(tmp4);
4878 } else { /* SHA-256 */
962fcbf2 4879 if (!dc_isar_feature(aa32_sha2, s) || size == 3) {
f1ecb913
AB
4880 return 1;
4881 }
1a66ac61
RH
4882 ptr1 = vfp_reg_ptr(true, rd);
4883 ptr2 = vfp_reg_ptr(true, rn);
4884 ptr3 = vfp_reg_ptr(true, rm);
f1ecb913
AB
4885 switch (size) {
4886 case 0:
1a66ac61 4887 gen_helper_crypto_sha256h(ptr1, ptr2, ptr3);
f1ecb913
AB
4888 break;
4889 case 1:
1a66ac61 4890 gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3);
f1ecb913
AB
4891 break;
4892 case 2:
1a66ac61 4893 gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3);
f1ecb913
AB
4894 break;
4895 }
4896 }
1a66ac61
RH
4897 tcg_temp_free_ptr(ptr1);
4898 tcg_temp_free_ptr(ptr2);
4899 tcg_temp_free_ptr(ptr3);
f1ecb913 4900 return 0;
36a71934
RH
4901
4902 case NEON_3R_VPADD_VQRDMLAH:
4903 if (!u) {
4904 break; /* VPADD */
4905 }
4906 /* VQRDMLAH */
4907 switch (size) {
4908 case 1:
4909 return do_v81_helper(s, gen_helper_gvec_qrdmlah_s16,
4910 q, rd, rn, rm);
4911 case 2:
4912 return do_v81_helper(s, gen_helper_gvec_qrdmlah_s32,
4913 q, rd, rn, rm);
4914 }
4915 return 1;
4916
4917 case NEON_3R_VFM_VQRDMLSH:
4918 if (!u) {
4919 /* VFM, VFMS */
4920 if (size == 1) {
4921 return 1;
4922 }
4923 break;
4924 }
4925 /* VQRDMLSH */
4926 switch (size) {
4927 case 1:
4928 return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s16,
4929 q, rd, rn, rm);
4930 case 2:
4931 return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s32,
4932 q, rd, rn, rm);
4933 }
4934 return 1;
eabcd6fa
RH
4935
4936 case NEON_3R_LOGIC: /* Logic ops. */
4937 switch ((u << 2) | size) {
4938 case 0: /* VAND */
4939 tcg_gen_gvec_and(0, rd_ofs, rn_ofs, rm_ofs,
4940 vec_size, vec_size);
4941 break;
4942 case 1: /* VBIC */
4943 tcg_gen_gvec_andc(0, rd_ofs, rn_ofs, rm_ofs,
4944 vec_size, vec_size);
4945 break;
2900847f
RH
4946 case 2: /* VORR */
4947 tcg_gen_gvec_or(0, rd_ofs, rn_ofs, rm_ofs,
4948 vec_size, vec_size);
eabcd6fa
RH
4949 break;
4950 case 3: /* VORN */
4951 tcg_gen_gvec_orc(0, rd_ofs, rn_ofs, rm_ofs,
4952 vec_size, vec_size);
4953 break;
4954 case 4: /* VEOR */
4955 tcg_gen_gvec_xor(0, rd_ofs, rn_ofs, rm_ofs,
4956 vec_size, vec_size);
4957 break;
4958 case 5: /* VBSL */
3a7a2b4e
RH
4959 tcg_gen_gvec_bitsel(MO_8, rd_ofs, rd_ofs, rn_ofs, rm_ofs,
4960 vec_size, vec_size);
eabcd6fa
RH
4961 break;
4962 case 6: /* VBIT */
3a7a2b4e
RH
4963 tcg_gen_gvec_bitsel(MO_8, rd_ofs, rm_ofs, rn_ofs, rd_ofs,
4964 vec_size, vec_size);
eabcd6fa
RH
4965 break;
4966 case 7: /* VBIF */
3a7a2b4e
RH
4967 tcg_gen_gvec_bitsel(MO_8, rd_ofs, rm_ofs, rd_ofs, rn_ofs,
4968 vec_size, vec_size);
eabcd6fa
RH
4969 break;
4970 }
4971 return 0;
e4717ae0
RH
4972
4973 case NEON_3R_VADD_VSUB:
4974 if (u) {
4975 tcg_gen_gvec_sub(size, rd_ofs, rn_ofs, rm_ofs,
4976 vec_size, vec_size);
4977 } else {
4978 tcg_gen_gvec_add(size, rd_ofs, rn_ofs, rm_ofs,
4979 vec_size, vec_size);
4980 }
4981 return 0;
82083184 4982
89e68b57
RH
4983 case NEON_3R_VQADD:
4984 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4985 rn_ofs, rm_ofs, vec_size, vec_size,
4986 (u ? uqadd_op : sqadd_op) + size);
2f143d3a 4987 return 0;
89e68b57
RH
4988
4989 case NEON_3R_VQSUB:
4990 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4991 rn_ofs, rm_ofs, vec_size, vec_size,
4992 (u ? uqsub_op : sqsub_op) + size);
2f143d3a 4993 return 0;
89e68b57 4994
82083184
RH
4995 case NEON_3R_VMUL: /* VMUL */
4996 if (u) {
4997 /* Polynomial case allows only P8 and is handled below. */
4998 if (size != 0) {
4999 return 1;
5000 }
5001 } else {
5002 tcg_gen_gvec_mul(size, rd_ofs, rn_ofs, rm_ofs,
5003 vec_size, vec_size);
5004 return 0;
5005 }
5006 break;
4a7832b0
RH
5007
5008 case NEON_3R_VML: /* VMLA, VMLS */
5009 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size,
5010 u ? &mls_op[size] : &mla_op[size]);
5011 return 0;
ea580fa3
RH
5012
5013 case NEON_3R_VTST_VCEQ:
5014 if (u) { /* VCEQ */
5015 tcg_gen_gvec_cmp(TCG_COND_EQ, size, rd_ofs, rn_ofs, rm_ofs,
5016 vec_size, vec_size);
5017 } else { /* VTST */
5018 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
5019 vec_size, vec_size, &cmtst_op[size]);
5020 }
5021 return 0;
5022
5023 case NEON_3R_VCGT:
5024 tcg_gen_gvec_cmp(u ? TCG_COND_GTU : TCG_COND_GT, size,
5025 rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
5026 return 0;
5027
5028 case NEON_3R_VCGE:
5029 tcg_gen_gvec_cmp(u ? TCG_COND_GEU : TCG_COND_GE, size,
5030 rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
5031 return 0;
6f278221
RH
5032
5033 case NEON_3R_VMAX:
5034 if (u) {
5035 tcg_gen_gvec_umax(size, rd_ofs, rn_ofs, rm_ofs,
5036 vec_size, vec_size);
5037 } else {
5038 tcg_gen_gvec_smax(size, rd_ofs, rn_ofs, rm_ofs,
5039 vec_size, vec_size);
5040 }
5041 return 0;
5042 case NEON_3R_VMIN:
5043 if (u) {
5044 tcg_gen_gvec_umin(size, rd_ofs, rn_ofs, rm_ofs,
5045 vec_size, vec_size);
5046 } else {
5047 tcg_gen_gvec_smin(size, rd_ofs, rn_ofs, rm_ofs,
5048 vec_size, vec_size);
5049 }
5050 return 0;
f1ecb913 5051 }
4a7832b0 5052
eabcd6fa 5053 if (size == 3) {
62698be3 5054 /* 64-bit element instructions. */
9ee6e8bb 5055 for (pass = 0; pass < (q ? 2 : 1); pass++) {
ad69471c
PB
5056 neon_load_reg64(cpu_V0, rn + pass);
5057 neon_load_reg64(cpu_V1, rm + pass);
9ee6e8bb 5058 switch (op) {
62698be3 5059 case NEON_3R_VSHL:
ad69471c
PB
5060 if (u) {
5061 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
5062 } else {
5063 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
5064 }
5065 break;
62698be3 5066 case NEON_3R_VQSHL:
ad69471c 5067 if (u) {
02da0b2d
PM
5068 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
5069 cpu_V1, cpu_V0);
ad69471c 5070 } else {
02da0b2d
PM
5071 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
5072 cpu_V1, cpu_V0);
ad69471c
PB
5073 }
5074 break;
62698be3 5075 case NEON_3R_VRSHL:
ad69471c
PB
5076 if (u) {
5077 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
1e8d4eec 5078 } else {
ad69471c
PB
5079 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
5080 }
5081 break;
62698be3 5082 case NEON_3R_VQRSHL:
ad69471c 5083 if (u) {
02da0b2d
PM
5084 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
5085 cpu_V1, cpu_V0);
ad69471c 5086 } else {
02da0b2d
PM
5087 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
5088 cpu_V1, cpu_V0);
1e8d4eec 5089 }
9ee6e8bb 5090 break;
9ee6e8bb
PB
5091 default:
5092 abort();
2c0262af 5093 }
ad69471c 5094 neon_store_reg64(cpu_V0, rd + pass);
2c0262af 5095 }
9ee6e8bb 5096 return 0;
2c0262af 5097 }
25f84f79 5098 pairwise = 0;
9ee6e8bb 5099 switch (op) {
62698be3
PM
5100 case NEON_3R_VSHL:
5101 case NEON_3R_VQSHL:
5102 case NEON_3R_VRSHL:
5103 case NEON_3R_VQRSHL:
9ee6e8bb 5104 {
ad69471c
PB
5105 int rtmp;
5106 /* Shift instruction operands are reversed. */
5107 rtmp = rn;
9ee6e8bb 5108 rn = rm;
ad69471c 5109 rm = rtmp;
9ee6e8bb 5110 }
2c0262af 5111 break;
36a71934 5112 case NEON_3R_VPADD_VQRDMLAH:
62698be3
PM
5113 case NEON_3R_VPMAX:
5114 case NEON_3R_VPMIN:
9ee6e8bb 5115 pairwise = 1;
2c0262af 5116 break;
25f84f79
PM
5117 case NEON_3R_FLOAT_ARITH:
5118 pairwise = (u && size < 2); /* if VPADD (float) */
5119 break;
5120 case NEON_3R_FLOAT_MINMAX:
5121 pairwise = u; /* if VPMIN/VPMAX (float) */
5122 break;
5123 case NEON_3R_FLOAT_CMP:
5124 if (!u && size) {
5125 /* no encoding for U=0 C=1x */
5126 return 1;
5127 }
5128 break;
5129 case NEON_3R_FLOAT_ACMP:
5130 if (!u) {
5131 return 1;
5132 }
5133 break;
505935fc
WN
5134 case NEON_3R_FLOAT_MISC:
5135 /* VMAXNM/VMINNM in ARMv8 */
d614a513 5136 if (u && !arm_dc_feature(s, ARM_FEATURE_V8)) {
25f84f79
PM
5137 return 1;
5138 }
2c0262af 5139 break;
36a71934
RH
5140 case NEON_3R_VFM_VQRDMLSH:
5141 if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
da97f52c
PM
5142 return 1;
5143 }
5144 break;
9ee6e8bb 5145 default:
2c0262af 5146 break;
9ee6e8bb 5147 }
dd8fbd78 5148
25f84f79
PM
5149 if (pairwise && q) {
5150 /* All the pairwise insns UNDEF if Q is set */
5151 return 1;
5152 }
5153
9ee6e8bb
PB
5154 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5155
5156 if (pairwise) {
5157 /* Pairwise. */
a5a14945
JR
5158 if (pass < 1) {
5159 tmp = neon_load_reg(rn, 0);
5160 tmp2 = neon_load_reg(rn, 1);
9ee6e8bb 5161 } else {
a5a14945
JR
5162 tmp = neon_load_reg(rm, 0);
5163 tmp2 = neon_load_reg(rm, 1);
9ee6e8bb
PB
5164 }
5165 } else {
5166 /* Elementwise. */
dd8fbd78
FN
5167 tmp = neon_load_reg(rn, pass);
5168 tmp2 = neon_load_reg(rm, pass);
9ee6e8bb
PB
5169 }
5170 switch (op) {
62698be3 5171 case NEON_3R_VHADD:
9ee6e8bb
PB
5172 GEN_NEON_INTEGER_OP(hadd);
5173 break;
62698be3 5174 case NEON_3R_VRHADD:
9ee6e8bb 5175 GEN_NEON_INTEGER_OP(rhadd);
2c0262af 5176 break;
62698be3 5177 case NEON_3R_VHSUB:
9ee6e8bb
PB
5178 GEN_NEON_INTEGER_OP(hsub);
5179 break;
62698be3 5180 case NEON_3R_VSHL:
ad69471c 5181 GEN_NEON_INTEGER_OP(shl);
2c0262af 5182 break;
62698be3 5183 case NEON_3R_VQSHL:
02da0b2d 5184 GEN_NEON_INTEGER_OP_ENV(qshl);
2c0262af 5185 break;
62698be3 5186 case NEON_3R_VRSHL:
ad69471c 5187 GEN_NEON_INTEGER_OP(rshl);
2c0262af 5188 break;
62698be3 5189 case NEON_3R_VQRSHL:
02da0b2d 5190 GEN_NEON_INTEGER_OP_ENV(qrshl);
9ee6e8bb 5191 break;
62698be3 5192 case NEON_3R_VABD:
9ee6e8bb
PB
5193 GEN_NEON_INTEGER_OP(abd);
5194 break;
62698be3 5195 case NEON_3R_VABA:
9ee6e8bb 5196 GEN_NEON_INTEGER_OP(abd);
7d1b0095 5197 tcg_temp_free_i32(tmp2);
dd8fbd78
FN
5198 tmp2 = neon_load_reg(rd, pass);
5199 gen_neon_add(size, tmp, tmp2);
9ee6e8bb 5200 break;
62698be3 5201 case NEON_3R_VMUL:
82083184
RH
5202 /* VMUL.P8; other cases already eliminated. */
5203 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
9ee6e8bb 5204 break;
62698be3 5205 case NEON_3R_VPMAX:
9ee6e8bb
PB
5206 GEN_NEON_INTEGER_OP(pmax);
5207 break;
62698be3 5208 case NEON_3R_VPMIN:
9ee6e8bb
PB
5209 GEN_NEON_INTEGER_OP(pmin);
5210 break;
62698be3 5211 case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
9ee6e8bb
PB
5212 if (!u) { /* VQDMULH */
5213 switch (size) {
02da0b2d
PM
5214 case 1:
5215 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5216 break;
5217 case 2:
5218 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5219 break;
62698be3 5220 default: abort();
9ee6e8bb 5221 }
62698be3 5222 } else { /* VQRDMULH */
9ee6e8bb 5223 switch (size) {
02da0b2d
PM
5224 case 1:
5225 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5226 break;
5227 case 2:
5228 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5229 break;
62698be3 5230 default: abort();
9ee6e8bb
PB
5231 }
5232 }
5233 break;
36a71934 5234 case NEON_3R_VPADD_VQRDMLAH:
9ee6e8bb 5235 switch (size) {
dd8fbd78
FN
5236 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
5237 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
5238 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
62698be3 5239 default: abort();
9ee6e8bb
PB
5240 }
5241 break;
62698be3 5242 case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
aa47cfdd
PM
5243 {
5244 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
9ee6e8bb
PB
5245 switch ((u << 2) | size) {
5246 case 0: /* VADD */
aa47cfdd
PM
5247 case 4: /* VPADD */
5248 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
9ee6e8bb
PB
5249 break;
5250 case 2: /* VSUB */
aa47cfdd 5251 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
9ee6e8bb
PB
5252 break;
5253 case 6: /* VABD */
aa47cfdd 5254 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
9ee6e8bb
PB
5255 break;
5256 default:
62698be3 5257 abort();
9ee6e8bb 5258 }
aa47cfdd 5259 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 5260 break;
aa47cfdd 5261 }
62698be3 5262 case NEON_3R_FLOAT_MULTIPLY:
aa47cfdd
PM
5263 {
5264 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5265 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
9ee6e8bb 5266 if (!u) {
7d1b0095 5267 tcg_temp_free_i32(tmp2);
dd8fbd78 5268 tmp2 = neon_load_reg(rd, pass);
9ee6e8bb 5269 if (size == 0) {
aa47cfdd 5270 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
9ee6e8bb 5271 } else {
aa47cfdd 5272 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
9ee6e8bb
PB
5273 }
5274 }
aa47cfdd 5275 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 5276 break;
aa47cfdd 5277 }
62698be3 5278 case NEON_3R_FLOAT_CMP:
aa47cfdd
PM
5279 {
5280 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
9ee6e8bb 5281 if (!u) {
aa47cfdd 5282 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
b5ff1b31 5283 } else {
aa47cfdd
PM
5284 if (size == 0) {
5285 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
5286 } else {
5287 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
5288 }
b5ff1b31 5289 }
aa47cfdd 5290 tcg_temp_free_ptr(fpstatus);
2c0262af 5291 break;
aa47cfdd 5292 }
62698be3 5293 case NEON_3R_FLOAT_ACMP:
aa47cfdd
PM
5294 {
5295 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5296 if (size == 0) {
5297 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
5298 } else {
5299 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
5300 }
5301 tcg_temp_free_ptr(fpstatus);
2c0262af 5302 break;
aa47cfdd 5303 }
62698be3 5304 case NEON_3R_FLOAT_MINMAX:
aa47cfdd
PM
5305 {
5306 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5307 if (size == 0) {
f71a2ae5 5308 gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus);
aa47cfdd 5309 } else {
f71a2ae5 5310 gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus);
aa47cfdd
PM
5311 }
5312 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 5313 break;
aa47cfdd 5314 }
505935fc
WN
5315 case NEON_3R_FLOAT_MISC:
5316 if (u) {
5317 /* VMAXNM/VMINNM */
5318 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5319 if (size == 0) {
f71a2ae5 5320 gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus);
505935fc 5321 } else {
f71a2ae5 5322 gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus);
505935fc
WN
5323 }
5324 tcg_temp_free_ptr(fpstatus);
5325 } else {
5326 if (size == 0) {
5327 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
5328 } else {
5329 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
5330 }
5331 }
2c0262af 5332 break;
36a71934 5333 case NEON_3R_VFM_VQRDMLSH:
da97f52c
PM
5334 {
5335 /* VFMA, VFMS: fused multiply-add */
5336 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5337 TCGv_i32 tmp3 = neon_load_reg(rd, pass);
5338 if (size) {
5339 /* VFMS */
5340 gen_helper_vfp_negs(tmp, tmp);
5341 }
5342 gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus);
5343 tcg_temp_free_i32(tmp3);
5344 tcg_temp_free_ptr(fpstatus);
5345 break;
5346 }
9ee6e8bb
PB
5347 default:
5348 abort();
2c0262af 5349 }
7d1b0095 5350 tcg_temp_free_i32(tmp2);
dd8fbd78 5351
9ee6e8bb
PB
5352 /* Save the result. For elementwise operations we can put it
5353 straight into the destination register. For pairwise operations
5354 we have to be careful to avoid clobbering the source operands. */
5355 if (pairwise && rd == rm) {
dd8fbd78 5356 neon_store_scratch(pass, tmp);
9ee6e8bb 5357 } else {
dd8fbd78 5358 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
5359 }
5360
5361 } /* for pass */
5362 if (pairwise && rd == rm) {
5363 for (pass = 0; pass < (q ? 4 : 2); pass++) {
dd8fbd78
FN
5364 tmp = neon_load_scratch(pass);
5365 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
5366 }
5367 }
ad69471c 5368 /* End of 3 register same size operations. */
9ee6e8bb
PB
5369 } else if (insn & (1 << 4)) {
5370 if ((insn & 0x00380080) != 0) {
5371 /* Two registers and shift. */
5372 op = (insn >> 8) & 0xf;
5373 if (insn & (1 << 7)) {
cc13115b
PM
5374 /* 64-bit shift. */
5375 if (op > 7) {
5376 return 1;
5377 }
9ee6e8bb
PB
5378 size = 3;
5379 } else {
5380 size = 2;
5381 while ((insn & (1 << (size + 19))) == 0)
5382 size--;
5383 }
5384 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
9ee6e8bb
PB
5385 if (op < 8) {
5386 /* Shift by immediate:
5387 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
cc13115b
PM
5388 if (q && ((rd | rm) & 1)) {
5389 return 1;
5390 }
5391 if (!u && (op == 4 || op == 6)) {
5392 return 1;
5393 }
9ee6e8bb
PB
5394 /* Right shifts are encoded as N - shift, where N is the
5395 element size in bits. */
1dc8425e 5396 if (op <= 4) {
9ee6e8bb 5397 shift = shift - (1 << (size + 3));
1dc8425e
RH
5398 }
5399
5400 switch (op) {
5401 case 0: /* VSHR */
5402 /* Right shift comes here negative. */
5403 shift = -shift;
5404 /* Shifts larger than the element size are architecturally
5405 * valid. Unsigned results in all zeros; signed results
5406 * in all sign bits.
5407 */
5408 if (!u) {
5409 tcg_gen_gvec_sari(size, rd_ofs, rm_ofs,
5410 MIN(shift, (8 << size) - 1),
5411 vec_size, vec_size);
5412 } else if (shift >= 8 << size) {
5413 tcg_gen_gvec_dup8i(rd_ofs, vec_size, vec_size, 0);
5414 } else {
5415 tcg_gen_gvec_shri(size, rd_ofs, rm_ofs, shift,
5416 vec_size, vec_size);
5417 }
5418 return 0;
5419
41f6c113
RH
5420 case 1: /* VSRA */
5421 /* Right shift comes here negative. */
5422 shift = -shift;
5423 /* Shifts larger than the element size are architecturally
5424 * valid. Unsigned results in all zeros; signed results
5425 * in all sign bits.
5426 */
5427 if (!u) {
5428 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
5429 MIN(shift, (8 << size) - 1),
5430 &ssra_op[size]);
5431 } else if (shift >= 8 << size) {
5432 /* rd += 0 */
5433 } else {
5434 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
5435 shift, &usra_op[size]);
5436 }
5437 return 0;
5438
f3cd8218
RH
5439 case 4: /* VSRI */
5440 if (!u) {
5441 return 1;
5442 }
5443 /* Right shift comes here negative. */
5444 shift = -shift;
5445 /* Shift out of range leaves destination unchanged. */
5446 if (shift < 8 << size) {
5447 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
5448 shift, &sri_op[size]);
5449 }
5450 return 0;
5451
1dc8425e 5452 case 5: /* VSHL, VSLI */
f3cd8218
RH
5453 if (u) { /* VSLI */
5454 /* Shift out of range leaves destination unchanged. */
5455 if (shift < 8 << size) {
5456 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size,
5457 vec_size, shift, &sli_op[size]);
5458 }
5459 } else { /* VSHL */
1dc8425e
RH
5460 /* Shifts larger than the element size are
5461 * architecturally valid and results in zero.
5462 */
5463 if (shift >= 8 << size) {
5464 tcg_gen_gvec_dup8i(rd_ofs, vec_size, vec_size, 0);
5465 } else {
5466 tcg_gen_gvec_shli(size, rd_ofs, rm_ofs, shift,
5467 vec_size, vec_size);
5468 }
1dc8425e 5469 }
f3cd8218 5470 return 0;
1dc8425e
RH
5471 }
5472
9ee6e8bb
PB
5473 if (size == 3) {
5474 count = q + 1;
5475 } else {
5476 count = q ? 4: 2;
5477 }
1dc8425e
RH
5478
5479 /* To avoid excessive duplication of ops we implement shift
5480 * by immediate using the variable shift operations.
5481 */
5482 imm = dup_const(size, shift);
9ee6e8bb
PB
5483
5484 for (pass = 0; pass < count; pass++) {
ad69471c
PB
5485 if (size == 3) {
5486 neon_load_reg64(cpu_V0, rm + pass);
5487 tcg_gen_movi_i64(cpu_V1, imm);
5488 switch (op) {
ad69471c
PB
5489 case 2: /* VRSHR */
5490 case 3: /* VRSRA */
5491 if (u)
5492 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
9ee6e8bb 5493 else
ad69471c 5494 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
9ee6e8bb 5495 break;
0322b26e 5496 case 6: /* VQSHLU */
02da0b2d
PM
5497 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
5498 cpu_V0, cpu_V1);
ad69471c 5499 break;
0322b26e
PM
5500 case 7: /* VQSHL */
5501 if (u) {
02da0b2d 5502 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
0322b26e
PM
5503 cpu_V0, cpu_V1);
5504 } else {
02da0b2d 5505 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
0322b26e
PM
5506 cpu_V0, cpu_V1);
5507 }
9ee6e8bb 5508 break;
1dc8425e
RH
5509 default:
5510 g_assert_not_reached();
9ee6e8bb 5511 }
41f6c113 5512 if (op == 3) {
ad69471c 5513 /* Accumulate. */
5371cb81 5514 neon_load_reg64(cpu_V1, rd + pass);
ad69471c 5515 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
ad69471c
PB
5516 }
5517 neon_store_reg64(cpu_V0, rd + pass);
5518 } else { /* size < 3 */
5519 /* Operands in T0 and T1. */
dd8fbd78 5520 tmp = neon_load_reg(rm, pass);
7d1b0095 5521 tmp2 = tcg_temp_new_i32();
dd8fbd78 5522 tcg_gen_movi_i32(tmp2, imm);
ad69471c 5523 switch (op) {
ad69471c
PB
5524 case 2: /* VRSHR */
5525 case 3: /* VRSRA */
5526 GEN_NEON_INTEGER_OP(rshl);
5527 break;
0322b26e 5528 case 6: /* VQSHLU */
ad69471c 5529 switch (size) {
0322b26e 5530 case 0:
02da0b2d
PM
5531 gen_helper_neon_qshlu_s8(tmp, cpu_env,
5532 tmp, tmp2);
0322b26e
PM
5533 break;
5534 case 1:
02da0b2d
PM
5535 gen_helper_neon_qshlu_s16(tmp, cpu_env,
5536 tmp, tmp2);
0322b26e
PM
5537 break;
5538 case 2:
02da0b2d
PM
5539 gen_helper_neon_qshlu_s32(tmp, cpu_env,
5540 tmp, tmp2);
0322b26e
PM
5541 break;
5542 default:
cc13115b 5543 abort();
ad69471c
PB
5544 }
5545 break;
0322b26e 5546 case 7: /* VQSHL */
02da0b2d 5547 GEN_NEON_INTEGER_OP_ENV(qshl);
0322b26e 5548 break;
1dc8425e
RH
5549 default:
5550 g_assert_not_reached();
ad69471c 5551 }
7d1b0095 5552 tcg_temp_free_i32(tmp2);
ad69471c 5553
41f6c113 5554 if (op == 3) {
ad69471c 5555 /* Accumulate. */
dd8fbd78 5556 tmp2 = neon_load_reg(rd, pass);
5371cb81 5557 gen_neon_add(size, tmp, tmp2);
7d1b0095 5558 tcg_temp_free_i32(tmp2);
ad69471c 5559 }
dd8fbd78 5560 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
5561 }
5562 } /* for pass */
5563 } else if (op < 10) {
ad69471c 5564 /* Shift by immediate and narrow:
9ee6e8bb 5565 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
0b36f4cd 5566 int input_unsigned = (op == 8) ? !u : u;
cc13115b
PM
5567 if (rm & 1) {
5568 return 1;
5569 }
9ee6e8bb
PB
5570 shift = shift - (1 << (size + 3));
5571 size++;
92cdfaeb 5572 if (size == 3) {
a7812ae4 5573 tmp64 = tcg_const_i64(shift);
92cdfaeb
PM
5574 neon_load_reg64(cpu_V0, rm);
5575 neon_load_reg64(cpu_V1, rm + 1);
5576 for (pass = 0; pass < 2; pass++) {
5577 TCGv_i64 in;
5578 if (pass == 0) {
5579 in = cpu_V0;
5580 } else {
5581 in = cpu_V1;
5582 }
ad69471c 5583 if (q) {
0b36f4cd 5584 if (input_unsigned) {
92cdfaeb 5585 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
0b36f4cd 5586 } else {
92cdfaeb 5587 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
0b36f4cd 5588 }
ad69471c 5589 } else {
0b36f4cd 5590 if (input_unsigned) {
92cdfaeb 5591 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
0b36f4cd 5592 } else {
92cdfaeb 5593 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
0b36f4cd 5594 }
ad69471c 5595 }
7d1b0095 5596 tmp = tcg_temp_new_i32();
92cdfaeb
PM
5597 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5598 neon_store_reg(rd, pass, tmp);
5599 } /* for pass */
5600 tcg_temp_free_i64(tmp64);
5601 } else {
5602 if (size == 1) {
5603 imm = (uint16_t)shift;
5604 imm |= imm << 16;
2c0262af 5605 } else {
92cdfaeb
PM
5606 /* size == 2 */
5607 imm = (uint32_t)shift;
5608 }
5609 tmp2 = tcg_const_i32(imm);
5610 tmp4 = neon_load_reg(rm + 1, 0);
5611 tmp5 = neon_load_reg(rm + 1, 1);
5612 for (pass = 0; pass < 2; pass++) {
5613 if (pass == 0) {
5614 tmp = neon_load_reg(rm, 0);
5615 } else {
5616 tmp = tmp4;
5617 }
0b36f4cd
CL
5618 gen_neon_shift_narrow(size, tmp, tmp2, q,
5619 input_unsigned);
92cdfaeb
PM
5620 if (pass == 0) {
5621 tmp3 = neon_load_reg(rm, 1);
5622 } else {
5623 tmp3 = tmp5;
5624 }
0b36f4cd
CL
5625 gen_neon_shift_narrow(size, tmp3, tmp2, q,
5626 input_unsigned);
36aa55dc 5627 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
7d1b0095
PM
5628 tcg_temp_free_i32(tmp);
5629 tcg_temp_free_i32(tmp3);
5630 tmp = tcg_temp_new_i32();
92cdfaeb
PM
5631 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5632 neon_store_reg(rd, pass, tmp);
5633 } /* for pass */
c6067f04 5634 tcg_temp_free_i32(tmp2);
b75263d6 5635 }
9ee6e8bb 5636 } else if (op == 10) {
cc13115b
PM
5637 /* VSHLL, VMOVL */
5638 if (q || (rd & 1)) {
9ee6e8bb 5639 return 1;
cc13115b 5640 }
ad69471c
PB
5641 tmp = neon_load_reg(rm, 0);
5642 tmp2 = neon_load_reg(rm, 1);
9ee6e8bb 5643 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
5644 if (pass == 1)
5645 tmp = tmp2;
5646
5647 gen_neon_widen(cpu_V0, tmp, size, u);
9ee6e8bb 5648
9ee6e8bb
PB
5649 if (shift != 0) {
5650 /* The shift is less than the width of the source
ad69471c
PB
5651 type, so we can just shift the whole register. */
5652 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
acdf01ef
CL
5653 /* Widen the result of shift: we need to clear
5654 * the potential overflow bits resulting from
5655 * left bits of the narrow input appearing as
5656 * right bits of left the neighbour narrow
5657 * input. */
ad69471c
PB
5658 if (size < 2 || !u) {
5659 uint64_t imm64;
5660 if (size == 0) {
5661 imm = (0xffu >> (8 - shift));
5662 imm |= imm << 16;
acdf01ef 5663 } else if (size == 1) {
ad69471c 5664 imm = 0xffff >> (16 - shift);
acdf01ef
CL
5665 } else {
5666 /* size == 2 */
5667 imm = 0xffffffff >> (32 - shift);
5668 }
5669 if (size < 2) {
5670 imm64 = imm | (((uint64_t)imm) << 32);
5671 } else {
5672 imm64 = imm;
9ee6e8bb 5673 }
acdf01ef 5674 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
9ee6e8bb
PB
5675 }
5676 }
ad69471c 5677 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb 5678 }
f73534a5 5679 } else if (op >= 14) {
9ee6e8bb 5680 /* VCVT fixed-point. */
c253dd78
PM
5681 TCGv_ptr fpst;
5682 TCGv_i32 shiftv;
5683 VFPGenFixPointFn *fn;
5684
cc13115b
PM
5685 if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
5686 return 1;
5687 }
c253dd78
PM
5688
5689 if (!(op & 1)) {
5690 if (u) {
5691 fn = gen_helper_vfp_ultos;
5692 } else {
5693 fn = gen_helper_vfp_sltos;
5694 }
5695 } else {
5696 if (u) {
5697 fn = gen_helper_vfp_touls_round_to_zero;
5698 } else {
5699 fn = gen_helper_vfp_tosls_round_to_zero;
5700 }
5701 }
5702
f73534a5
PM
5703 /* We have already masked out the must-be-1 top bit of imm6,
5704 * hence this 32-shift where the ARM ARM has 64-imm6.
5705 */
5706 shift = 32 - shift;
c253dd78
PM
5707 fpst = get_fpstatus_ptr(1);
5708 shiftv = tcg_const_i32(shift);
9ee6e8bb 5709 for (pass = 0; pass < (q ? 4 : 2); pass++) {
c253dd78
PM
5710 TCGv_i32 tmpf = neon_load_reg(rm, pass);
5711 fn(tmpf, tmpf, shiftv, fpst);
5712 neon_store_reg(rd, pass, tmpf);
2c0262af 5713 }
c253dd78
PM
5714 tcg_temp_free_ptr(fpst);
5715 tcg_temp_free_i32(shiftv);
2c0262af 5716 } else {
9ee6e8bb
PB
5717 return 1;
5718 }
5719 } else { /* (insn & 0x00380080) == 0 */
246fa4ac
RH
5720 int invert, reg_ofs, vec_size;
5721
7d80fee5
PM
5722 if (q && (rd & 1)) {
5723 return 1;
5724 }
9ee6e8bb
PB
5725
5726 op = (insn >> 8) & 0xf;
5727 /* One register and immediate. */
5728 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
5729 invert = (insn & (1 << 5)) != 0;
7d80fee5
PM
5730 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
5731 * We choose to not special-case this and will behave as if a
5732 * valid constant encoding of 0 had been given.
5733 */
9ee6e8bb
PB
5734 switch (op) {
5735 case 0: case 1:
5736 /* no-op */
5737 break;
5738 case 2: case 3:
5739 imm <<= 8;
5740 break;
5741 case 4: case 5:
5742 imm <<= 16;
5743 break;
5744 case 6: case 7:
5745 imm <<= 24;
5746 break;
5747 case 8: case 9:
5748 imm |= imm << 16;
5749 break;
5750 case 10: case 11:
5751 imm = (imm << 8) | (imm << 24);
5752 break;
5753 case 12:
8e31209e 5754 imm = (imm << 8) | 0xff;
9ee6e8bb
PB
5755 break;
5756 case 13:
5757 imm = (imm << 16) | 0xffff;
5758 break;
5759 case 14:
5760 imm |= (imm << 8) | (imm << 16) | (imm << 24);
246fa4ac 5761 if (invert) {
9ee6e8bb 5762 imm = ~imm;
246fa4ac 5763 }
9ee6e8bb
PB
5764 break;
5765 case 15:
7d80fee5
PM
5766 if (invert) {
5767 return 1;
5768 }
9ee6e8bb
PB
5769 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
5770 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
5771 break;
5772 }
246fa4ac 5773 if (invert) {
9ee6e8bb 5774 imm = ~imm;
246fa4ac 5775 }
9ee6e8bb 5776
246fa4ac
RH
5777 reg_ofs = neon_reg_offset(rd, 0);
5778 vec_size = q ? 16 : 8;
5779
5780 if (op & 1 && op < 12) {
5781 if (invert) {
5782 /* The immediate value has already been inverted,
5783 * so BIC becomes AND.
5784 */
5785 tcg_gen_gvec_andi(MO_32, reg_ofs, reg_ofs, imm,
5786 vec_size, vec_size);
9ee6e8bb 5787 } else {
246fa4ac
RH
5788 tcg_gen_gvec_ori(MO_32, reg_ofs, reg_ofs, imm,
5789 vec_size, vec_size);
5790 }
5791 } else {
5792 /* VMOV, VMVN. */
5793 if (op == 14 && invert) {
5794 TCGv_i64 t64 = tcg_temp_new_i64();
5795
5796 for (pass = 0; pass <= q; ++pass) {
5797 uint64_t val = 0;
a5a14945 5798 int n;
246fa4ac
RH
5799
5800 for (n = 0; n < 8; n++) {
5801 if (imm & (1 << (n + pass * 8))) {
5802 val |= 0xffull << (n * 8);
5803 }
9ee6e8bb 5804 }
246fa4ac
RH
5805 tcg_gen_movi_i64(t64, val);
5806 neon_store_reg64(t64, rd + pass);
9ee6e8bb 5807 }
246fa4ac
RH
5808 tcg_temp_free_i64(t64);
5809 } else {
5810 tcg_gen_gvec_dup32i(reg_ofs, vec_size, vec_size, imm);
9ee6e8bb
PB
5811 }
5812 }
5813 }
e4b3861d 5814 } else { /* (insn & 0x00800010 == 0x00800000) */
9ee6e8bb
PB
5815 if (size != 3) {
5816 op = (insn >> 8) & 0xf;
5817 if ((insn & (1 << 6)) == 0) {
5818 /* Three registers of different lengths. */
5819 int src1_wide;
5820 int src2_wide;
5821 int prewiden;
526d0096
PM
5822 /* undefreq: bit 0 : UNDEF if size == 0
5823 * bit 1 : UNDEF if size == 1
5824 * bit 2 : UNDEF if size == 2
5825 * bit 3 : UNDEF if U == 1
5826 * Note that [2:0] set implies 'always UNDEF'
695272dc
PM
5827 */
5828 int undefreq;
5829 /* prewiden, src1_wide, src2_wide, undefreq */
5830 static const int neon_3reg_wide[16][4] = {
5831 {1, 0, 0, 0}, /* VADDL */
5832 {1, 1, 0, 0}, /* VADDW */
5833 {1, 0, 0, 0}, /* VSUBL */
5834 {1, 1, 0, 0}, /* VSUBW */
5835 {0, 1, 1, 0}, /* VADDHN */
5836 {0, 0, 0, 0}, /* VABAL */
5837 {0, 1, 1, 0}, /* VSUBHN */
5838 {0, 0, 0, 0}, /* VABDL */
5839 {0, 0, 0, 0}, /* VMLAL */
526d0096 5840 {0, 0, 0, 9}, /* VQDMLAL */
695272dc 5841 {0, 0, 0, 0}, /* VMLSL */
526d0096 5842 {0, 0, 0, 9}, /* VQDMLSL */
695272dc 5843 {0, 0, 0, 0}, /* Integer VMULL */
526d0096 5844 {0, 0, 0, 1}, /* VQDMULL */
4e624eda 5845 {0, 0, 0, 0xa}, /* Polynomial VMULL */
526d0096 5846 {0, 0, 0, 7}, /* Reserved: always UNDEF */
9ee6e8bb
PB
5847 };
5848
5849 prewiden = neon_3reg_wide[op][0];
5850 src1_wide = neon_3reg_wide[op][1];
5851 src2_wide = neon_3reg_wide[op][2];
695272dc 5852 undefreq = neon_3reg_wide[op][3];
9ee6e8bb 5853
526d0096
PM
5854 if ((undefreq & (1 << size)) ||
5855 ((undefreq & 8) && u)) {
695272dc
PM
5856 return 1;
5857 }
5858 if ((src1_wide && (rn & 1)) ||
5859 (src2_wide && (rm & 1)) ||
5860 (!src2_wide && (rd & 1))) {
ad69471c 5861 return 1;
695272dc 5862 }
ad69471c 5863
4e624eda
PM
5864 /* Handle VMULL.P64 (Polynomial 64x64 to 128 bit multiply)
5865 * outside the loop below as it only performs a single pass.
5866 */
5867 if (op == 14 && size == 2) {
5868 TCGv_i64 tcg_rn, tcg_rm, tcg_rd;
5869
962fcbf2 5870 if (!dc_isar_feature(aa32_pmull, s)) {
4e624eda
PM
5871 return 1;
5872 }
5873 tcg_rn = tcg_temp_new_i64();
5874 tcg_rm = tcg_temp_new_i64();
5875 tcg_rd = tcg_temp_new_i64();
5876 neon_load_reg64(tcg_rn, rn);
5877 neon_load_reg64(tcg_rm, rm);
5878 gen_helper_neon_pmull_64_lo(tcg_rd, tcg_rn, tcg_rm);
5879 neon_store_reg64(tcg_rd, rd);
5880 gen_helper_neon_pmull_64_hi(tcg_rd, tcg_rn, tcg_rm);
5881 neon_store_reg64(tcg_rd, rd + 1);
5882 tcg_temp_free_i64(tcg_rn);
5883 tcg_temp_free_i64(tcg_rm);
5884 tcg_temp_free_i64(tcg_rd);
5885 return 0;
5886 }
5887
9ee6e8bb
PB
5888 /* Avoid overlapping operands. Wide source operands are
5889 always aligned so will never overlap with wide
5890 destinations in problematic ways. */
8f8e3aa4 5891 if (rd == rm && !src2_wide) {
dd8fbd78
FN
5892 tmp = neon_load_reg(rm, 1);
5893 neon_store_scratch(2, tmp);
8f8e3aa4 5894 } else if (rd == rn && !src1_wide) {
dd8fbd78
FN
5895 tmp = neon_load_reg(rn, 1);
5896 neon_store_scratch(2, tmp);
9ee6e8bb 5897 }
f764718d 5898 tmp3 = NULL;
9ee6e8bb 5899 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
5900 if (src1_wide) {
5901 neon_load_reg64(cpu_V0, rn + pass);
f764718d 5902 tmp = NULL;
9ee6e8bb 5903 } else {
ad69471c 5904 if (pass == 1 && rd == rn) {
dd8fbd78 5905 tmp = neon_load_scratch(2);
9ee6e8bb 5906 } else {
ad69471c
PB
5907 tmp = neon_load_reg(rn, pass);
5908 }
5909 if (prewiden) {
5910 gen_neon_widen(cpu_V0, tmp, size, u);
9ee6e8bb
PB
5911 }
5912 }
ad69471c
PB
5913 if (src2_wide) {
5914 neon_load_reg64(cpu_V1, rm + pass);
f764718d 5915 tmp2 = NULL;
9ee6e8bb 5916 } else {
ad69471c 5917 if (pass == 1 && rd == rm) {
dd8fbd78 5918 tmp2 = neon_load_scratch(2);
9ee6e8bb 5919 } else {
ad69471c
PB
5920 tmp2 = neon_load_reg(rm, pass);
5921 }
5922 if (prewiden) {
5923 gen_neon_widen(cpu_V1, tmp2, size, u);
9ee6e8bb 5924 }
9ee6e8bb
PB
5925 }
5926 switch (op) {
5927 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
ad69471c 5928 gen_neon_addl(size);
9ee6e8bb 5929 break;
79b0e534 5930 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
ad69471c 5931 gen_neon_subl(size);
9ee6e8bb
PB
5932 break;
5933 case 5: case 7: /* VABAL, VABDL */
5934 switch ((size << 1) | u) {
ad69471c
PB
5935 case 0:
5936 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
5937 break;
5938 case 1:
5939 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
5940 break;
5941 case 2:
5942 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
5943 break;
5944 case 3:
5945 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
5946 break;
5947 case 4:
5948 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
5949 break;
5950 case 5:
5951 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
5952 break;
9ee6e8bb
PB
5953 default: abort();
5954 }
7d1b0095
PM
5955 tcg_temp_free_i32(tmp2);
5956 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
5957 break;
5958 case 8: case 9: case 10: case 11: case 12: case 13:
5959 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
ad69471c 5960 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
9ee6e8bb
PB
5961 break;
5962 case 14: /* Polynomial VMULL */
e5ca24cb 5963 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
7d1b0095
PM
5964 tcg_temp_free_i32(tmp2);
5965 tcg_temp_free_i32(tmp);
e5ca24cb 5966 break;
695272dc
PM
5967 default: /* 15 is RESERVED: caught earlier */
5968 abort();
9ee6e8bb 5969 }
ebcd88ce
PM
5970 if (op == 13) {
5971 /* VQDMULL */
5972 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5973 neon_store_reg64(cpu_V0, rd + pass);
5974 } else if (op == 5 || (op >= 8 && op <= 11)) {
9ee6e8bb 5975 /* Accumulate. */
ebcd88ce 5976 neon_load_reg64(cpu_V1, rd + pass);
9ee6e8bb 5977 switch (op) {
4dc064e6
PM
5978 case 10: /* VMLSL */
5979 gen_neon_negl(cpu_V0, size);
5980 /* Fall through */
5981 case 5: case 8: /* VABAL, VMLAL */
ad69471c 5982 gen_neon_addl(size);
9ee6e8bb
PB
5983 break;
5984 case 9: case 11: /* VQDMLAL, VQDMLSL */
ad69471c 5985 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4dc064e6
PM
5986 if (op == 11) {
5987 gen_neon_negl(cpu_V0, size);
5988 }
ad69471c
PB
5989 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5990 break;
9ee6e8bb
PB
5991 default:
5992 abort();
5993 }
ad69471c 5994 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
5995 } else if (op == 4 || op == 6) {
5996 /* Narrowing operation. */
7d1b0095 5997 tmp = tcg_temp_new_i32();
79b0e534 5998 if (!u) {
9ee6e8bb 5999 switch (size) {
ad69471c
PB
6000 case 0:
6001 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
6002 break;
6003 case 1:
6004 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
6005 break;
6006 case 2:
664b7e3b 6007 tcg_gen_extrh_i64_i32(tmp, cpu_V0);
ad69471c 6008 break;
9ee6e8bb
PB
6009 default: abort();
6010 }
6011 } else {
6012 switch (size) {
ad69471c
PB
6013 case 0:
6014 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
6015 break;
6016 case 1:
6017 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
6018 break;
6019 case 2:
6020 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
664b7e3b 6021 tcg_gen_extrh_i64_i32(tmp, cpu_V0);
ad69471c 6022 break;
9ee6e8bb
PB
6023 default: abort();
6024 }
6025 }
ad69471c
PB
6026 if (pass == 0) {
6027 tmp3 = tmp;
6028 } else {
6029 neon_store_reg(rd, 0, tmp3);
6030 neon_store_reg(rd, 1, tmp);
6031 }
9ee6e8bb
PB
6032 } else {
6033 /* Write back the result. */
ad69471c 6034 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
6035 }
6036 }
6037 } else {
3e3326df
PM
6038 /* Two registers and a scalar. NB that for ops of this form
6039 * the ARM ARM labels bit 24 as Q, but it is in our variable
6040 * 'u', not 'q'.
6041 */
6042 if (size == 0) {
6043 return 1;
6044 }
9ee6e8bb 6045 switch (op) {
9ee6e8bb 6046 case 1: /* Float VMLA scalar */
9ee6e8bb 6047 case 5: /* Floating point VMLS scalar */
9ee6e8bb 6048 case 9: /* Floating point VMUL scalar */
3e3326df
PM
6049 if (size == 1) {
6050 return 1;
6051 }
6052 /* fall through */
6053 case 0: /* Integer VMLA scalar */
6054 case 4: /* Integer VMLS scalar */
6055 case 8: /* Integer VMUL scalar */
9ee6e8bb
PB
6056 case 12: /* VQDMULH scalar */
6057 case 13: /* VQRDMULH scalar */
3e3326df
PM
6058 if (u && ((rd | rn) & 1)) {
6059 return 1;
6060 }
dd8fbd78
FN
6061 tmp = neon_get_scalar(size, rm);
6062 neon_store_scratch(0, tmp);
9ee6e8bb 6063 for (pass = 0; pass < (u ? 4 : 2); pass++) {
dd8fbd78
FN
6064 tmp = neon_load_scratch(0);
6065 tmp2 = neon_load_reg(rn, pass);
9ee6e8bb
PB
6066 if (op == 12) {
6067 if (size == 1) {
02da0b2d 6068 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 6069 } else {
02da0b2d 6070 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
9ee6e8bb
PB
6071 }
6072 } else if (op == 13) {
6073 if (size == 1) {
02da0b2d 6074 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 6075 } else {
02da0b2d 6076 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
9ee6e8bb
PB
6077 }
6078 } else if (op & 1) {
aa47cfdd
PM
6079 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6080 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
6081 tcg_temp_free_ptr(fpstatus);
9ee6e8bb
PB
6082 } else {
6083 switch (size) {
dd8fbd78
FN
6084 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
6085 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
6086 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
3e3326df 6087 default: abort();
9ee6e8bb
PB
6088 }
6089 }
7d1b0095 6090 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
6091 if (op < 8) {
6092 /* Accumulate. */
dd8fbd78 6093 tmp2 = neon_load_reg(rd, pass);
9ee6e8bb
PB
6094 switch (op) {
6095 case 0:
dd8fbd78 6096 gen_neon_add(size, tmp, tmp2);
9ee6e8bb
PB
6097 break;
6098 case 1:
aa47cfdd
PM
6099 {
6100 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6101 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
6102 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6103 break;
aa47cfdd 6104 }
9ee6e8bb 6105 case 4:
dd8fbd78 6106 gen_neon_rsb(size, tmp, tmp2);
9ee6e8bb
PB
6107 break;
6108 case 5:
aa47cfdd
PM
6109 {
6110 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6111 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
6112 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6113 break;
aa47cfdd 6114 }
9ee6e8bb
PB
6115 default:
6116 abort();
6117 }
7d1b0095 6118 tcg_temp_free_i32(tmp2);
9ee6e8bb 6119 }
dd8fbd78 6120 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
6121 }
6122 break;
9ee6e8bb 6123 case 3: /* VQDMLAL scalar */
9ee6e8bb 6124 case 7: /* VQDMLSL scalar */
9ee6e8bb 6125 case 11: /* VQDMULL scalar */
3e3326df 6126 if (u == 1) {
ad69471c 6127 return 1;
3e3326df
PM
6128 }
6129 /* fall through */
6130 case 2: /* VMLAL sclar */
6131 case 6: /* VMLSL scalar */
6132 case 10: /* VMULL scalar */
6133 if (rd & 1) {
6134 return 1;
6135 }
dd8fbd78 6136 tmp2 = neon_get_scalar(size, rm);
c6067f04
CL
6137 /* We need a copy of tmp2 because gen_neon_mull
6138 * deletes it during pass 0. */
7d1b0095 6139 tmp4 = tcg_temp_new_i32();
c6067f04 6140 tcg_gen_mov_i32(tmp4, tmp2);
dd8fbd78 6141 tmp3 = neon_load_reg(rn, 1);
ad69471c 6142
9ee6e8bb 6143 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
6144 if (pass == 0) {
6145 tmp = neon_load_reg(rn, 0);
9ee6e8bb 6146 } else {
dd8fbd78 6147 tmp = tmp3;
c6067f04 6148 tmp2 = tmp4;
9ee6e8bb 6149 }
ad69471c 6150 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
ad69471c
PB
6151 if (op != 11) {
6152 neon_load_reg64(cpu_V1, rd + pass);
9ee6e8bb 6153 }
9ee6e8bb 6154 switch (op) {
4dc064e6
PM
6155 case 6:
6156 gen_neon_negl(cpu_V0, size);
6157 /* Fall through */
6158 case 2:
ad69471c 6159 gen_neon_addl(size);
9ee6e8bb
PB
6160 break;
6161 case 3: case 7:
ad69471c 6162 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4dc064e6
PM
6163 if (op == 7) {
6164 gen_neon_negl(cpu_V0, size);
6165 }
ad69471c 6166 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
9ee6e8bb
PB
6167 break;
6168 case 10:
6169 /* no-op */
6170 break;
6171 case 11:
ad69471c 6172 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
9ee6e8bb
PB
6173 break;
6174 default:
6175 abort();
6176 }
ad69471c 6177 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb 6178 }
61adacc8
RH
6179 break;
6180 case 14: /* VQRDMLAH scalar */
6181 case 15: /* VQRDMLSH scalar */
6182 {
6183 NeonGenThreeOpEnvFn *fn;
dd8fbd78 6184
962fcbf2 6185 if (!dc_isar_feature(aa32_rdm, s)) {
61adacc8
RH
6186 return 1;
6187 }
6188 if (u && ((rd | rn) & 1)) {
6189 return 1;
6190 }
6191 if (op == 14) {
6192 if (size == 1) {
6193 fn = gen_helper_neon_qrdmlah_s16;
6194 } else {
6195 fn = gen_helper_neon_qrdmlah_s32;
6196 }
6197 } else {
6198 if (size == 1) {
6199 fn = gen_helper_neon_qrdmlsh_s16;
6200 } else {
6201 fn = gen_helper_neon_qrdmlsh_s32;
6202 }
6203 }
dd8fbd78 6204
61adacc8
RH
6205 tmp2 = neon_get_scalar(size, rm);
6206 for (pass = 0; pass < (u ? 4 : 2); pass++) {
6207 tmp = neon_load_reg(rn, pass);
6208 tmp3 = neon_load_reg(rd, pass);
6209 fn(tmp, cpu_env, tmp, tmp2, tmp3);
6210 tcg_temp_free_i32(tmp3);
6211 neon_store_reg(rd, pass, tmp);
6212 }
6213 tcg_temp_free_i32(tmp2);
6214 }
9ee6e8bb 6215 break;
61adacc8
RH
6216 default:
6217 g_assert_not_reached();
9ee6e8bb
PB
6218 }
6219 }
6220 } else { /* size == 3 */
6221 if (!u) {
6222 /* Extract. */
9ee6e8bb 6223 imm = (insn >> 8) & 0xf;
ad69471c
PB
6224
6225 if (imm > 7 && !q)
6226 return 1;
6227
52579ea1
PM
6228 if (q && ((rd | rn | rm) & 1)) {
6229 return 1;
6230 }
6231
ad69471c
PB
6232 if (imm == 0) {
6233 neon_load_reg64(cpu_V0, rn);
6234 if (q) {
6235 neon_load_reg64(cpu_V1, rn + 1);
9ee6e8bb 6236 }
ad69471c
PB
6237 } else if (imm == 8) {
6238 neon_load_reg64(cpu_V0, rn + 1);
6239 if (q) {
6240 neon_load_reg64(cpu_V1, rm);
9ee6e8bb 6241 }
ad69471c 6242 } else if (q) {
a7812ae4 6243 tmp64 = tcg_temp_new_i64();
ad69471c
PB
6244 if (imm < 8) {
6245 neon_load_reg64(cpu_V0, rn);
a7812ae4 6246 neon_load_reg64(tmp64, rn + 1);
ad69471c
PB
6247 } else {
6248 neon_load_reg64(cpu_V0, rn + 1);
a7812ae4 6249 neon_load_reg64(tmp64, rm);
ad69471c
PB
6250 }
6251 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
a7812ae4 6252 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
ad69471c
PB
6253 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6254 if (imm < 8) {
6255 neon_load_reg64(cpu_V1, rm);
9ee6e8bb 6256 } else {
ad69471c
PB
6257 neon_load_reg64(cpu_V1, rm + 1);
6258 imm -= 8;
9ee6e8bb 6259 }
ad69471c 6260 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
a7812ae4
PB
6261 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
6262 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
b75263d6 6263 tcg_temp_free_i64(tmp64);
ad69471c 6264 } else {
a7812ae4 6265 /* BUGFIX */
ad69471c 6266 neon_load_reg64(cpu_V0, rn);
a7812ae4 6267 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
ad69471c 6268 neon_load_reg64(cpu_V1, rm);
a7812ae4 6269 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
ad69471c
PB
6270 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6271 }
6272 neon_store_reg64(cpu_V0, rd);
6273 if (q) {
6274 neon_store_reg64(cpu_V1, rd + 1);
9ee6e8bb
PB
6275 }
6276 } else if ((insn & (1 << 11)) == 0) {
6277 /* Two register misc. */
6278 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
6279 size = (insn >> 18) & 3;
600b828c
PM
6280 /* UNDEF for unknown op values and bad op-size combinations */
6281 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
6282 return 1;
6283 }
fe8fcf3d
PM
6284 if (neon_2rm_is_v8_op(op) &&
6285 !arm_dc_feature(s, ARM_FEATURE_V8)) {
6286 return 1;
6287 }
fc2a9b37
PM
6288 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
6289 q && ((rm | rd) & 1)) {
6290 return 1;
6291 }
9ee6e8bb 6292 switch (op) {
600b828c 6293 case NEON_2RM_VREV64:
9ee6e8bb 6294 for (pass = 0; pass < (q ? 2 : 1); pass++) {
dd8fbd78
FN
6295 tmp = neon_load_reg(rm, pass * 2);
6296 tmp2 = neon_load_reg(rm, pass * 2 + 1);
9ee6e8bb 6297 switch (size) {
dd8fbd78
FN
6298 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6299 case 1: gen_swap_half(tmp); break;
9ee6e8bb
PB
6300 case 2: /* no-op */ break;
6301 default: abort();
6302 }
dd8fbd78 6303 neon_store_reg(rd, pass * 2 + 1, tmp);
9ee6e8bb 6304 if (size == 2) {
dd8fbd78 6305 neon_store_reg(rd, pass * 2, tmp2);
9ee6e8bb 6306 } else {
9ee6e8bb 6307 switch (size) {
dd8fbd78
FN
6308 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
6309 case 1: gen_swap_half(tmp2); break;
9ee6e8bb
PB
6310 default: abort();
6311 }
dd8fbd78 6312 neon_store_reg(rd, pass * 2, tmp2);
9ee6e8bb
PB
6313 }
6314 }
6315 break;
600b828c
PM
6316 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
6317 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
ad69471c
PB
6318 for (pass = 0; pass < q + 1; pass++) {
6319 tmp = neon_load_reg(rm, pass * 2);
6320 gen_neon_widen(cpu_V0, tmp, size, op & 1);
6321 tmp = neon_load_reg(rm, pass * 2 + 1);
6322 gen_neon_widen(cpu_V1, tmp, size, op & 1);
6323 switch (size) {
6324 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
6325 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
6326 case 2: tcg_gen_add_i64(CPU_V001); break;
6327 default: abort();
6328 }
600b828c 6329 if (op >= NEON_2RM_VPADAL) {
9ee6e8bb 6330 /* Accumulate. */
ad69471c
PB
6331 neon_load_reg64(cpu_V1, rd + pass);
6332 gen_neon_addl(size);
9ee6e8bb 6333 }
ad69471c 6334 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
6335 }
6336 break;
600b828c 6337 case NEON_2RM_VTRN:
9ee6e8bb 6338 if (size == 2) {
a5a14945 6339 int n;
9ee6e8bb 6340 for (n = 0; n < (q ? 4 : 2); n += 2) {
dd8fbd78
FN
6341 tmp = neon_load_reg(rm, n);
6342 tmp2 = neon_load_reg(rd, n + 1);
6343 neon_store_reg(rm, n, tmp2);
6344 neon_store_reg(rd, n + 1, tmp);
9ee6e8bb
PB
6345 }
6346 } else {
6347 goto elementwise;
6348 }
6349 break;
600b828c 6350 case NEON_2RM_VUZP:
02acedf9 6351 if (gen_neon_unzip(rd, rm, size, q)) {
9ee6e8bb 6352 return 1;
9ee6e8bb
PB
6353 }
6354 break;
600b828c 6355 case NEON_2RM_VZIP:
d68a6f3a 6356 if (gen_neon_zip(rd, rm, size, q)) {
9ee6e8bb 6357 return 1;
9ee6e8bb
PB
6358 }
6359 break;
600b828c
PM
6360 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
6361 /* also VQMOVUN; op field and mnemonics don't line up */
fc2a9b37
PM
6362 if (rm & 1) {
6363 return 1;
6364 }
f764718d 6365 tmp2 = NULL;
9ee6e8bb 6366 for (pass = 0; pass < 2; pass++) {
ad69471c 6367 neon_load_reg64(cpu_V0, rm + pass);
7d1b0095 6368 tmp = tcg_temp_new_i32();
600b828c
PM
6369 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
6370 tmp, cpu_V0);
ad69471c
PB
6371 if (pass == 0) {
6372 tmp2 = tmp;
6373 } else {
6374 neon_store_reg(rd, 0, tmp2);
6375 neon_store_reg(rd, 1, tmp);
9ee6e8bb 6376 }
9ee6e8bb
PB
6377 }
6378 break;
600b828c 6379 case NEON_2RM_VSHLL:
fc2a9b37 6380 if (q || (rd & 1)) {
9ee6e8bb 6381 return 1;
600b828c 6382 }
ad69471c
PB
6383 tmp = neon_load_reg(rm, 0);
6384 tmp2 = neon_load_reg(rm, 1);
9ee6e8bb 6385 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
6386 if (pass == 1)
6387 tmp = tmp2;
6388 gen_neon_widen(cpu_V0, tmp, size, 1);
30d11a2a 6389 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
ad69471c 6390 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
6391 }
6392 break;
600b828c 6393 case NEON_2RM_VCVT_F16_F32:
486624fc
AB
6394 {
6395 TCGv_ptr fpst;
6396 TCGv_i32 ahp;
6397
602f6e42 6398 if (!dc_isar_feature(aa32_fp16_spconv, s) ||
fc2a9b37
PM
6399 q || (rm & 1)) {
6400 return 1;
6401 }
486624fc
AB
6402 fpst = get_fpstatus_ptr(true);
6403 ahp = get_ahp_flag();
58f2682e
PM
6404 tmp = neon_load_reg(rm, 0);
6405 gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp);
6406 tmp2 = neon_load_reg(rm, 1);
6407 gen_helper_vfp_fcvt_f32_to_f16(tmp2, tmp2, fpst, ahp);
60011498
PB
6408 tcg_gen_shli_i32(tmp2, tmp2, 16);
6409 tcg_gen_or_i32(tmp2, tmp2, tmp);
58f2682e
PM
6410 tcg_temp_free_i32(tmp);
6411 tmp = neon_load_reg(rm, 2);
6412 gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp);
6413 tmp3 = neon_load_reg(rm, 3);
60011498 6414 neon_store_reg(rd, 0, tmp2);
58f2682e
PM
6415 gen_helper_vfp_fcvt_f32_to_f16(tmp3, tmp3, fpst, ahp);
6416 tcg_gen_shli_i32(tmp3, tmp3, 16);
6417 tcg_gen_or_i32(tmp3, tmp3, tmp);
6418 neon_store_reg(rd, 1, tmp3);
7d1b0095 6419 tcg_temp_free_i32(tmp);
486624fc
AB
6420 tcg_temp_free_i32(ahp);
6421 tcg_temp_free_ptr(fpst);
60011498 6422 break;
486624fc 6423 }
600b828c 6424 case NEON_2RM_VCVT_F32_F16:
486624fc
AB
6425 {
6426 TCGv_ptr fpst;
6427 TCGv_i32 ahp;
602f6e42 6428 if (!dc_isar_feature(aa32_fp16_spconv, s) ||
fc2a9b37
PM
6429 q || (rd & 1)) {
6430 return 1;
6431 }
486624fc
AB
6432 fpst = get_fpstatus_ptr(true);
6433 ahp = get_ahp_flag();
7d1b0095 6434 tmp3 = tcg_temp_new_i32();
60011498
PB
6435 tmp = neon_load_reg(rm, 0);
6436 tmp2 = neon_load_reg(rm, 1);
6437 tcg_gen_ext16u_i32(tmp3, tmp);
b66f6b99
PM
6438 gen_helper_vfp_fcvt_f16_to_f32(tmp3, tmp3, fpst, ahp);
6439 neon_store_reg(rd, 0, tmp3);
6440 tcg_gen_shri_i32(tmp, tmp, 16);
6441 gen_helper_vfp_fcvt_f16_to_f32(tmp, tmp, fpst, ahp);
6442 neon_store_reg(rd, 1, tmp);
6443 tmp3 = tcg_temp_new_i32();
60011498 6444 tcg_gen_ext16u_i32(tmp3, tmp2);
b66f6b99
PM
6445 gen_helper_vfp_fcvt_f16_to_f32(tmp3, tmp3, fpst, ahp);
6446 neon_store_reg(rd, 2, tmp3);
6447 tcg_gen_shri_i32(tmp2, tmp2, 16);
6448 gen_helper_vfp_fcvt_f16_to_f32(tmp2, tmp2, fpst, ahp);
6449 neon_store_reg(rd, 3, tmp2);
486624fc
AB
6450 tcg_temp_free_i32(ahp);
6451 tcg_temp_free_ptr(fpst);
60011498 6452 break;
486624fc 6453 }
9d935509 6454 case NEON_2RM_AESE: case NEON_2RM_AESMC:
962fcbf2 6455 if (!dc_isar_feature(aa32_aes, s) || ((rm | rd) & 1)) {
9d935509
AB
6456 return 1;
6457 }
1a66ac61
RH
6458 ptr1 = vfp_reg_ptr(true, rd);
6459 ptr2 = vfp_reg_ptr(true, rm);
9d935509
AB
6460
6461 /* Bit 6 is the lowest opcode bit; it distinguishes between
6462 * encryption (AESE/AESMC) and decryption (AESD/AESIMC)
6463 */
6464 tmp3 = tcg_const_i32(extract32(insn, 6, 1));
6465
6466 if (op == NEON_2RM_AESE) {
1a66ac61 6467 gen_helper_crypto_aese(ptr1, ptr2, tmp3);
9d935509 6468 } else {
1a66ac61 6469 gen_helper_crypto_aesmc(ptr1, ptr2, tmp3);
9d935509 6470 }
1a66ac61
RH
6471 tcg_temp_free_ptr(ptr1);
6472 tcg_temp_free_ptr(ptr2);
9d935509
AB
6473 tcg_temp_free_i32(tmp3);
6474 break;
f1ecb913 6475 case NEON_2RM_SHA1H:
962fcbf2 6476 if (!dc_isar_feature(aa32_sha1, s) || ((rm | rd) & 1)) {
f1ecb913
AB
6477 return 1;
6478 }
1a66ac61
RH
6479 ptr1 = vfp_reg_ptr(true, rd);
6480 ptr2 = vfp_reg_ptr(true, rm);
f1ecb913 6481
1a66ac61 6482 gen_helper_crypto_sha1h(ptr1, ptr2);
f1ecb913 6483
1a66ac61
RH
6484 tcg_temp_free_ptr(ptr1);
6485 tcg_temp_free_ptr(ptr2);
f1ecb913
AB
6486 break;
6487 case NEON_2RM_SHA1SU1:
6488 if ((rm | rd) & 1) {
6489 return 1;
6490 }
6491 /* bit 6 (q): set -> SHA256SU0, cleared -> SHA1SU1 */
6492 if (q) {
962fcbf2 6493 if (!dc_isar_feature(aa32_sha2, s)) {
f1ecb913
AB
6494 return 1;
6495 }
962fcbf2 6496 } else if (!dc_isar_feature(aa32_sha1, s)) {
f1ecb913
AB
6497 return 1;
6498 }
1a66ac61
RH
6499 ptr1 = vfp_reg_ptr(true, rd);
6500 ptr2 = vfp_reg_ptr(true, rm);
f1ecb913 6501 if (q) {
1a66ac61 6502 gen_helper_crypto_sha256su0(ptr1, ptr2);
f1ecb913 6503 } else {
1a66ac61 6504 gen_helper_crypto_sha1su1(ptr1, ptr2);
f1ecb913 6505 }
1a66ac61
RH
6506 tcg_temp_free_ptr(ptr1);
6507 tcg_temp_free_ptr(ptr2);
f1ecb913 6508 break;
4bf940be
RH
6509
6510 case NEON_2RM_VMVN:
6511 tcg_gen_gvec_not(0, rd_ofs, rm_ofs, vec_size, vec_size);
6512 break;
6513 case NEON_2RM_VNEG:
6514 tcg_gen_gvec_neg(size, rd_ofs, rm_ofs, vec_size, vec_size);
6515 break;
4e027a71
RH
6516 case NEON_2RM_VABS:
6517 tcg_gen_gvec_abs(size, rd_ofs, rm_ofs, vec_size, vec_size);
6518 break;
4bf940be 6519
9ee6e8bb
PB
6520 default:
6521 elementwise:
6522 for (pass = 0; pass < (q ? 4 : 2); pass++) {
60737ed5 6523 tmp = neon_load_reg(rm, pass);
9ee6e8bb 6524 switch (op) {
600b828c 6525 case NEON_2RM_VREV32:
9ee6e8bb 6526 switch (size) {
dd8fbd78
FN
6527 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6528 case 1: gen_swap_half(tmp); break;
600b828c 6529 default: abort();
9ee6e8bb
PB
6530 }
6531 break;
600b828c 6532 case NEON_2RM_VREV16:
dd8fbd78 6533 gen_rev16(tmp);
9ee6e8bb 6534 break;
600b828c 6535 case NEON_2RM_VCLS:
9ee6e8bb 6536 switch (size) {
dd8fbd78
FN
6537 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
6538 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
6539 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
600b828c 6540 default: abort();
9ee6e8bb
PB
6541 }
6542 break;
600b828c 6543 case NEON_2RM_VCLZ:
9ee6e8bb 6544 switch (size) {
dd8fbd78
FN
6545 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
6546 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
7539a012 6547 case 2: tcg_gen_clzi_i32(tmp, tmp, 32); break;
600b828c 6548 default: abort();
9ee6e8bb
PB
6549 }
6550 break;
600b828c 6551 case NEON_2RM_VCNT:
dd8fbd78 6552 gen_helper_neon_cnt_u8(tmp, tmp);
9ee6e8bb 6553 break;
600b828c 6554 case NEON_2RM_VQABS:
9ee6e8bb 6555 switch (size) {
02da0b2d
PM
6556 case 0:
6557 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
6558 break;
6559 case 1:
6560 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
6561 break;
6562 case 2:
6563 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
6564 break;
600b828c 6565 default: abort();
9ee6e8bb
PB
6566 }
6567 break;
600b828c 6568 case NEON_2RM_VQNEG:
9ee6e8bb 6569 switch (size) {
02da0b2d
PM
6570 case 0:
6571 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
6572 break;
6573 case 1:
6574 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
6575 break;
6576 case 2:
6577 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
6578 break;
600b828c 6579 default: abort();
9ee6e8bb
PB
6580 }
6581 break;
600b828c 6582 case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
dd8fbd78 6583 tmp2 = tcg_const_i32(0);
9ee6e8bb 6584 switch(size) {
dd8fbd78
FN
6585 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
6586 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
6587 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
600b828c 6588 default: abort();
9ee6e8bb 6589 }
39d5492a 6590 tcg_temp_free_i32(tmp2);
600b828c 6591 if (op == NEON_2RM_VCLE0) {
dd8fbd78 6592 tcg_gen_not_i32(tmp, tmp);
600b828c 6593 }
9ee6e8bb 6594 break;
600b828c 6595 case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
dd8fbd78 6596 tmp2 = tcg_const_i32(0);
9ee6e8bb 6597 switch(size) {
dd8fbd78
FN
6598 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
6599 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
6600 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
600b828c 6601 default: abort();
9ee6e8bb 6602 }
39d5492a 6603 tcg_temp_free_i32(tmp2);
600b828c 6604 if (op == NEON_2RM_VCLT0) {
dd8fbd78 6605 tcg_gen_not_i32(tmp, tmp);
600b828c 6606 }
9ee6e8bb 6607 break;
600b828c 6608 case NEON_2RM_VCEQ0:
dd8fbd78 6609 tmp2 = tcg_const_i32(0);
9ee6e8bb 6610 switch(size) {
dd8fbd78
FN
6611 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
6612 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
6613 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
600b828c 6614 default: abort();
9ee6e8bb 6615 }
39d5492a 6616 tcg_temp_free_i32(tmp2);
9ee6e8bb 6617 break;
600b828c 6618 case NEON_2RM_VCGT0_F:
aa47cfdd
PM
6619 {
6620 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
dd8fbd78 6621 tmp2 = tcg_const_i32(0);
aa47cfdd 6622 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
39d5492a 6623 tcg_temp_free_i32(tmp2);
aa47cfdd 6624 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6625 break;
aa47cfdd 6626 }
600b828c 6627 case NEON_2RM_VCGE0_F:
aa47cfdd
PM
6628 {
6629 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
dd8fbd78 6630 tmp2 = tcg_const_i32(0);
aa47cfdd 6631 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
39d5492a 6632 tcg_temp_free_i32(tmp2);
aa47cfdd 6633 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6634 break;
aa47cfdd 6635 }
600b828c 6636 case NEON_2RM_VCEQ0_F:
aa47cfdd
PM
6637 {
6638 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
dd8fbd78 6639 tmp2 = tcg_const_i32(0);
aa47cfdd 6640 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
39d5492a 6641 tcg_temp_free_i32(tmp2);
aa47cfdd 6642 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6643 break;
aa47cfdd 6644 }
600b828c 6645 case NEON_2RM_VCLE0_F:
aa47cfdd
PM
6646 {
6647 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
0e326109 6648 tmp2 = tcg_const_i32(0);
aa47cfdd 6649 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
39d5492a 6650 tcg_temp_free_i32(tmp2);
aa47cfdd 6651 tcg_temp_free_ptr(fpstatus);
0e326109 6652 break;
aa47cfdd 6653 }
600b828c 6654 case NEON_2RM_VCLT0_F:
aa47cfdd
PM
6655 {
6656 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
0e326109 6657 tmp2 = tcg_const_i32(0);
aa47cfdd 6658 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
39d5492a 6659 tcg_temp_free_i32(tmp2);
aa47cfdd 6660 tcg_temp_free_ptr(fpstatus);
0e326109 6661 break;
aa47cfdd 6662 }
600b828c 6663 case NEON_2RM_VABS_F:
fd8a68cd 6664 gen_helper_vfp_abss(tmp, tmp);
9ee6e8bb 6665 break;
600b828c 6666 case NEON_2RM_VNEG_F:
cedcc96f 6667 gen_helper_vfp_negs(tmp, tmp);
9ee6e8bb 6668 break;
600b828c 6669 case NEON_2RM_VSWP:
dd8fbd78
FN
6670 tmp2 = neon_load_reg(rd, pass);
6671 neon_store_reg(rm, pass, tmp2);
9ee6e8bb 6672 break;
600b828c 6673 case NEON_2RM_VTRN:
dd8fbd78 6674 tmp2 = neon_load_reg(rd, pass);
9ee6e8bb 6675 switch (size) {
dd8fbd78
FN
6676 case 0: gen_neon_trn_u8(tmp, tmp2); break;
6677 case 1: gen_neon_trn_u16(tmp, tmp2); break;
600b828c 6678 default: abort();
9ee6e8bb 6679 }
dd8fbd78 6680 neon_store_reg(rm, pass, tmp2);
9ee6e8bb 6681 break;
34f7b0a2
WN
6682 case NEON_2RM_VRINTN:
6683 case NEON_2RM_VRINTA:
6684 case NEON_2RM_VRINTM:
6685 case NEON_2RM_VRINTP:
6686 case NEON_2RM_VRINTZ:
6687 {
6688 TCGv_i32 tcg_rmode;
6689 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6690 int rmode;
6691
6692 if (op == NEON_2RM_VRINTZ) {
6693 rmode = FPROUNDING_ZERO;
6694 } else {
6695 rmode = fp_decode_rm[((op & 0x6) >> 1) ^ 1];
6696 }
6697
6698 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
6699 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6700 cpu_env);
3b52ad1f 6701 gen_helper_rints(tmp, tmp, fpstatus);
34f7b0a2
WN
6702 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6703 cpu_env);
6704 tcg_temp_free_ptr(fpstatus);
6705 tcg_temp_free_i32(tcg_rmode);
6706 break;
6707 }
2ce70625
WN
6708 case NEON_2RM_VRINTX:
6709 {
6710 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
3b52ad1f 6711 gen_helper_rints_exact(tmp, tmp, fpstatus);
2ce70625
WN
6712 tcg_temp_free_ptr(fpstatus);
6713 break;
6714 }
901ad525
WN
6715 case NEON_2RM_VCVTAU:
6716 case NEON_2RM_VCVTAS:
6717 case NEON_2RM_VCVTNU:
6718 case NEON_2RM_VCVTNS:
6719 case NEON_2RM_VCVTPU:
6720 case NEON_2RM_VCVTPS:
6721 case NEON_2RM_VCVTMU:
6722 case NEON_2RM_VCVTMS:
6723 {
6724 bool is_signed = !extract32(insn, 7, 1);
6725 TCGv_ptr fpst = get_fpstatus_ptr(1);
6726 TCGv_i32 tcg_rmode, tcg_shift;
6727 int rmode = fp_decode_rm[extract32(insn, 8, 2)];
6728
6729 tcg_shift = tcg_const_i32(0);
6730 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
6731 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6732 cpu_env);
6733
6734 if (is_signed) {
30bf0a01 6735 gen_helper_vfp_tosls(tmp, tmp,
901ad525
WN
6736 tcg_shift, fpst);
6737 } else {
30bf0a01 6738 gen_helper_vfp_touls(tmp, tmp,
901ad525
WN
6739 tcg_shift, fpst);
6740 }
6741
6742 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6743 cpu_env);
6744 tcg_temp_free_i32(tcg_rmode);
6745 tcg_temp_free_i32(tcg_shift);
6746 tcg_temp_free_ptr(fpst);
6747 break;
6748 }
600b828c 6749 case NEON_2RM_VRECPE:
b6d4443a
AB
6750 {
6751 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6752 gen_helper_recpe_u32(tmp, tmp, fpstatus);
6753 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6754 break;
b6d4443a 6755 }
600b828c 6756 case NEON_2RM_VRSQRTE:
c2fb418e
AB
6757 {
6758 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6759 gen_helper_rsqrte_u32(tmp, tmp, fpstatus);
6760 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6761 break;
c2fb418e 6762 }
600b828c 6763 case NEON_2RM_VRECPE_F:
b6d4443a
AB
6764 {
6765 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
9a011fec 6766 gen_helper_recpe_f32(tmp, tmp, fpstatus);
b6d4443a 6767 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6768 break;
b6d4443a 6769 }
600b828c 6770 case NEON_2RM_VRSQRTE_F:
c2fb418e
AB
6771 {
6772 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
9a011fec 6773 gen_helper_rsqrte_f32(tmp, tmp, fpstatus);
c2fb418e 6774 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6775 break;
c2fb418e 6776 }
600b828c 6777 case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
60737ed5
PM
6778 {
6779 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6780 gen_helper_vfp_sitos(tmp, tmp, fpstatus);
6781 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6782 break;
60737ed5 6783 }
600b828c 6784 case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
60737ed5
PM
6785 {
6786 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6787 gen_helper_vfp_uitos(tmp, tmp, fpstatus);
6788 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6789 break;
60737ed5 6790 }
600b828c 6791 case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
60737ed5
PM
6792 {
6793 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6794 gen_helper_vfp_tosizs(tmp, tmp, fpstatus);
6795 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6796 break;
60737ed5 6797 }
600b828c 6798 case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
60737ed5
PM
6799 {
6800 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6801 gen_helper_vfp_touizs(tmp, tmp, fpstatus);
6802 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6803 break;
60737ed5 6804 }
9ee6e8bb 6805 default:
600b828c
PM
6806 /* Reserved op values were caught by the
6807 * neon_2rm_sizes[] check earlier.
6808 */
6809 abort();
9ee6e8bb 6810 }
60737ed5 6811 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
6812 }
6813 break;
6814 }
6815 } else if ((insn & (1 << 10)) == 0) {
6816 /* VTBL, VTBX. */
56907d77
PM
6817 int n = ((insn >> 8) & 3) + 1;
6818 if ((rn + n) > 32) {
6819 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
6820 * helper function running off the end of the register file.
6821 */
6822 return 1;
6823 }
6824 n <<= 3;
9ee6e8bb 6825 if (insn & (1 << 6)) {
8f8e3aa4 6826 tmp = neon_load_reg(rd, 0);
9ee6e8bb 6827 } else {
7d1b0095 6828 tmp = tcg_temp_new_i32();
8f8e3aa4 6829 tcg_gen_movi_i32(tmp, 0);
9ee6e8bb 6830 }
8f8e3aa4 6831 tmp2 = neon_load_reg(rm, 0);
e7c06c4e 6832 ptr1 = vfp_reg_ptr(true, rn);
b75263d6 6833 tmp5 = tcg_const_i32(n);
e7c06c4e 6834 gen_helper_neon_tbl(tmp2, tmp2, tmp, ptr1, tmp5);
7d1b0095 6835 tcg_temp_free_i32(tmp);
9ee6e8bb 6836 if (insn & (1 << 6)) {
8f8e3aa4 6837 tmp = neon_load_reg(rd, 1);
9ee6e8bb 6838 } else {
7d1b0095 6839 tmp = tcg_temp_new_i32();
8f8e3aa4 6840 tcg_gen_movi_i32(tmp, 0);
9ee6e8bb 6841 }
8f8e3aa4 6842 tmp3 = neon_load_reg(rm, 1);
e7c06c4e 6843 gen_helper_neon_tbl(tmp3, tmp3, tmp, ptr1, tmp5);
25aeb69b 6844 tcg_temp_free_i32(tmp5);
e7c06c4e 6845 tcg_temp_free_ptr(ptr1);
8f8e3aa4 6846 neon_store_reg(rd, 0, tmp2);
3018f259 6847 neon_store_reg(rd, 1, tmp3);
7d1b0095 6848 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
6849 } else if ((insn & 0x380) == 0) {
6850 /* VDUP */
32f91fb7 6851 int element;
14776ab5 6852 MemOp size;
32f91fb7 6853
133da6aa
JR
6854 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
6855 return 1;
6856 }
9ee6e8bb 6857 if (insn & (1 << 16)) {
32f91fb7
RH
6858 size = MO_8;
6859 element = (insn >> 17) & 7;
9ee6e8bb 6860 } else if (insn & (1 << 17)) {
32f91fb7
RH
6861 size = MO_16;
6862 element = (insn >> 18) & 3;
6863 } else {
6864 size = MO_32;
6865 element = (insn >> 19) & 1;
9ee6e8bb 6866 }
32f91fb7
RH
6867 tcg_gen_gvec_dup_mem(size, neon_reg_offset(rd, 0),
6868 neon_element_offset(rm, element, size),
6869 q ? 16 : 8, q ? 16 : 8);
9ee6e8bb
PB
6870 } else {
6871 return 1;
6872 }
6873 }
6874 }
6875 return 0;
6876}
6877
8b7209fa
RH
6878/* Advanced SIMD three registers of the same length extension.
6879 * 31 25 23 22 20 16 12 11 10 9 8 3 0
6880 * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
6881 * | 1 1 1 1 1 1 0 | op1 | D | op2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
6882 * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
6883 */
6884static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
6885{
26c470a7
RH
6886 gen_helper_gvec_3 *fn_gvec = NULL;
6887 gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
6888 int rd, rn, rm, opr_sz;
6889 int data = 0;
87732318
RH
6890 int off_rn, off_rm;
6891 bool is_long = false, q = extract32(insn, 6, 1);
6892 bool ptr_is_env = false;
8b7209fa
RH
6893
6894 if ((insn & 0xfe200f10) == 0xfc200800) {
6895 /* VCMLA -- 1111 110R R.1S .... .... 1000 ...0 .... */
26c470a7
RH
6896 int size = extract32(insn, 20, 1);
6897 data = extract32(insn, 23, 2); /* rot */
962fcbf2 6898 if (!dc_isar_feature(aa32_vcma, s)
5763190f 6899 || (!size && !dc_isar_feature(aa32_fp16_arith, s))) {
8b7209fa
RH
6900 return 1;
6901 }
6902 fn_gvec_ptr = size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
6903 } else if ((insn & 0xfea00f10) == 0xfc800800) {
6904 /* VCADD -- 1111 110R 1.0S .... .... 1000 ...0 .... */
26c470a7
RH
6905 int size = extract32(insn, 20, 1);
6906 data = extract32(insn, 24, 1); /* rot */
962fcbf2 6907 if (!dc_isar_feature(aa32_vcma, s)
5763190f 6908 || (!size && !dc_isar_feature(aa32_fp16_arith, s))) {
8b7209fa
RH
6909 return 1;
6910 }
6911 fn_gvec_ptr = size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
26c470a7
RH
6912 } else if ((insn & 0xfeb00f00) == 0xfc200d00) {
6913 /* V[US]DOT -- 1111 1100 0.10 .... .... 1101 .Q.U .... */
6914 bool u = extract32(insn, 4, 1);
962fcbf2 6915 if (!dc_isar_feature(aa32_dp, s)) {
26c470a7
RH
6916 return 1;
6917 }
6918 fn_gvec = u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b;
87732318
RH
6919 } else if ((insn & 0xff300f10) == 0xfc200810) {
6920 /* VFM[AS]L -- 1111 1100 S.10 .... .... 1000 .Q.1 .... */
6921 int is_s = extract32(insn, 23, 1);
6922 if (!dc_isar_feature(aa32_fhm, s)) {
6923 return 1;
6924 }
6925 is_long = true;
6926 data = is_s; /* is_2 == 0 */
6927 fn_gvec_ptr = gen_helper_gvec_fmlal_a32;
6928 ptr_is_env = true;
8b7209fa
RH
6929 } else {
6930 return 1;
6931 }
6932
87732318
RH
6933 VFP_DREG_D(rd, insn);
6934 if (rd & q) {
6935 return 1;
6936 }
6937 if (q || !is_long) {
6938 VFP_DREG_N(rn, insn);
6939 VFP_DREG_M(rm, insn);
6940 if ((rn | rm) & q & !is_long) {
6941 return 1;
6942 }
6943 off_rn = vfp_reg_offset(1, rn);
6944 off_rm = vfp_reg_offset(1, rm);
6945 } else {
6946 rn = VFP_SREG_N(insn);
6947 rm = VFP_SREG_M(insn);
6948 off_rn = vfp_reg_offset(0, rn);
6949 off_rm = vfp_reg_offset(0, rm);
6950 }
6951
8b7209fa 6952 if (s->fp_excp_el) {
a767fac8 6953 gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
4be42f40 6954 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
8b7209fa
RH
6955 return 0;
6956 }
6957 if (!s->vfp_enabled) {
6958 return 1;
6959 }
6960
6961 opr_sz = (1 + q) * 8;
26c470a7 6962 if (fn_gvec_ptr) {
87732318
RH
6963 TCGv_ptr ptr;
6964 if (ptr_is_env) {
6965 ptr = cpu_env;
6966 } else {
6967 ptr = get_fpstatus_ptr(1);
6968 }
6969 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
26c470a7 6970 opr_sz, opr_sz, data, fn_gvec_ptr);
87732318
RH
6971 if (!ptr_is_env) {
6972 tcg_temp_free_ptr(ptr);
6973 }
26c470a7 6974 } else {
87732318 6975 tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
26c470a7
RH
6976 opr_sz, opr_sz, data, fn_gvec);
6977 }
8b7209fa
RH
6978 return 0;
6979}
6980
638808ff
RH
6981/* Advanced SIMD two registers and a scalar extension.
6982 * 31 24 23 22 20 16 12 11 10 9 8 3 0
6983 * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
6984 * | 1 1 1 1 1 1 1 0 | o1 | D | o2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
6985 * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
6986 *
6987 */
6988
6989static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
6990{
26c470a7
RH
6991 gen_helper_gvec_3 *fn_gvec = NULL;
6992 gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
2cc99919 6993 int rd, rn, rm, opr_sz, data;
87732318
RH
6994 int off_rn, off_rm;
6995 bool is_long = false, q = extract32(insn, 6, 1);
6996 bool ptr_is_env = false;
638808ff
RH
6997
6998 if ((insn & 0xff000f10) == 0xfe000800) {
6999 /* VCMLA (indexed) -- 1111 1110 S.RR .... .... 1000 ...0 .... */
2cc99919
RH
7000 int rot = extract32(insn, 20, 2);
7001 int size = extract32(insn, 23, 1);
7002 int index;
7003
962fcbf2 7004 if (!dc_isar_feature(aa32_vcma, s)) {
638808ff
RH
7005 return 1;
7006 }
2cc99919 7007 if (size == 0) {
5763190f 7008 if (!dc_isar_feature(aa32_fp16_arith, s)) {
2cc99919
RH
7009 return 1;
7010 }
7011 /* For fp16, rm is just Vm, and index is M. */
7012 rm = extract32(insn, 0, 4);
7013 index = extract32(insn, 5, 1);
7014 } else {
7015 /* For fp32, rm is the usual M:Vm, and index is 0. */
7016 VFP_DREG_M(rm, insn);
7017 index = 0;
7018 }
7019 data = (index << 2) | rot;
7020 fn_gvec_ptr = (size ? gen_helper_gvec_fcmlas_idx
7021 : gen_helper_gvec_fcmlah_idx);
26c470a7
RH
7022 } else if ((insn & 0xffb00f00) == 0xfe200d00) {
7023 /* V[US]DOT -- 1111 1110 0.10 .... .... 1101 .Q.U .... */
7024 int u = extract32(insn, 4, 1);
87732318 7025
962fcbf2 7026 if (!dc_isar_feature(aa32_dp, s)) {
26c470a7
RH
7027 return 1;
7028 }
7029 fn_gvec = u ? gen_helper_gvec_udot_idx_b : gen_helper_gvec_sdot_idx_b;
7030 /* rm is just Vm, and index is M. */
7031 data = extract32(insn, 5, 1); /* index */
7032 rm = extract32(insn, 0, 4);
87732318
RH
7033 } else if ((insn & 0xffa00f10) == 0xfe000810) {
7034 /* VFM[AS]L -- 1111 1110 0.0S .... .... 1000 .Q.1 .... */
7035 int is_s = extract32(insn, 20, 1);
7036 int vm20 = extract32(insn, 0, 3);
7037 int vm3 = extract32(insn, 3, 1);
7038 int m = extract32(insn, 5, 1);
7039 int index;
7040
7041 if (!dc_isar_feature(aa32_fhm, s)) {
7042 return 1;
7043 }
7044 if (q) {
7045 rm = vm20;
7046 index = m * 2 + vm3;
7047 } else {
7048 rm = vm20 * 2 + m;
7049 index = vm3;
7050 }
7051 is_long = true;
7052 data = (index << 2) | is_s; /* is_2 == 0 */
7053 fn_gvec_ptr = gen_helper_gvec_fmlal_idx_a32;
7054 ptr_is_env = true;
638808ff
RH
7055 } else {
7056 return 1;
7057 }
7058
87732318
RH
7059 VFP_DREG_D(rd, insn);
7060 if (rd & q) {
7061 return 1;
7062 }
7063 if (q || !is_long) {
7064 VFP_DREG_N(rn, insn);
7065 if (rn & q & !is_long) {
7066 return 1;
7067 }
7068 off_rn = vfp_reg_offset(1, rn);
7069 off_rm = vfp_reg_offset(1, rm);
7070 } else {
7071 rn = VFP_SREG_N(insn);
7072 off_rn = vfp_reg_offset(0, rn);
7073 off_rm = vfp_reg_offset(0, rm);
7074 }
638808ff 7075 if (s->fp_excp_el) {
a767fac8 7076 gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
4be42f40 7077 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
638808ff
RH
7078 return 0;
7079 }
7080 if (!s->vfp_enabled) {
7081 return 1;
7082 }
7083
7084 opr_sz = (1 + q) * 8;
26c470a7 7085 if (fn_gvec_ptr) {
87732318
RH
7086 TCGv_ptr ptr;
7087 if (ptr_is_env) {
7088 ptr = cpu_env;
7089 } else {
7090 ptr = get_fpstatus_ptr(1);
7091 }
7092 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
26c470a7 7093 opr_sz, opr_sz, data, fn_gvec_ptr);
87732318
RH
7094 if (!ptr_is_env) {
7095 tcg_temp_free_ptr(ptr);
7096 }
26c470a7 7097 } else {
87732318 7098 tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
26c470a7
RH
7099 opr_sz, opr_sz, data, fn_gvec);
7100 }
638808ff
RH
7101 return 0;
7102}
7103
7dcc1f89 7104static int disas_coproc_insn(DisasContext *s, uint32_t insn)
9ee6e8bb 7105{
4b6a83fb
PM
7106 int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
7107 const ARMCPRegInfo *ri;
9ee6e8bb
PB
7108
7109 cpnum = (insn >> 8) & 0xf;
c0f4af17
PM
7110
7111 /* First check for coprocessor space used for XScale/iwMMXt insns */
d614a513 7112 if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cpnum < 2)) {
c0f4af17
PM
7113 if (extract32(s->c15_cpar, cpnum, 1) == 0) {
7114 return 1;
7115 }
d614a513 7116 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
7dcc1f89 7117 return disas_iwmmxt_insn(s, insn);
d614a513 7118 } else if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
7dcc1f89 7119 return disas_dsp_insn(s, insn);
c0f4af17
PM
7120 }
7121 return 1;
4b6a83fb
PM
7122 }
7123
7124 /* Otherwise treat as a generic register access */
7125 is64 = (insn & (1 << 25)) == 0;
7126 if (!is64 && ((insn & (1 << 4)) == 0)) {
7127 /* cdp */
7128 return 1;
7129 }
7130
7131 crm = insn & 0xf;
7132 if (is64) {
7133 crn = 0;
7134 opc1 = (insn >> 4) & 0xf;
7135 opc2 = 0;
7136 rt2 = (insn >> 16) & 0xf;
7137 } else {
7138 crn = (insn >> 16) & 0xf;
7139 opc1 = (insn >> 21) & 7;
7140 opc2 = (insn >> 5) & 7;
7141 rt2 = 0;
7142 }
7143 isread = (insn >> 20) & 1;
7144 rt = (insn >> 12) & 0xf;
7145
60322b39 7146 ri = get_arm_cp_reginfo(s->cp_regs,
51a79b03 7147 ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
4b6a83fb
PM
7148 if (ri) {
7149 /* Check access permissions */
dcbff19b 7150 if (!cp_access_ok(s->current_el, ri, isread)) {
4b6a83fb
PM
7151 return 1;
7152 }
7153
c0f4af17 7154 if (ri->accessfn ||
d614a513 7155 (arm_dc_feature(s, ARM_FEATURE_XSCALE) && cpnum < 14)) {
f59df3f2
PM
7156 /* Emit code to perform further access permissions checks at
7157 * runtime; this may result in an exception.
c0f4af17
PM
7158 * Note that on XScale all cp0..c13 registers do an access check
7159 * call in order to handle c15_cpar.
f59df3f2
PM
7160 */
7161 TCGv_ptr tmpptr;
3f208fd7 7162 TCGv_i32 tcg_syn, tcg_isread;
8bcbf37c
PM
7163 uint32_t syndrome;
7164
7165 /* Note that since we are an implementation which takes an
7166 * exception on a trapped conditional instruction only if the
7167 * instruction passes its condition code check, we can take
7168 * advantage of the clause in the ARM ARM that allows us to set
7169 * the COND field in the instruction to 0xE in all cases.
7170 * We could fish the actual condition out of the insn (ARM)
7171 * or the condexec bits (Thumb) but it isn't necessary.
7172 */
7173 switch (cpnum) {
7174 case 14:
7175 if (is64) {
7176 syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
4df32259 7177 isread, false);
8bcbf37c
PM
7178 } else {
7179 syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
4df32259 7180 rt, isread, false);
8bcbf37c
PM
7181 }
7182 break;
7183 case 15:
7184 if (is64) {
7185 syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
4df32259 7186 isread, false);
8bcbf37c
PM
7187 } else {
7188 syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
4df32259 7189 rt, isread, false);
8bcbf37c
PM
7190 }
7191 break;
7192 default:
7193 /* ARMv8 defines that only coprocessors 14 and 15 exist,
7194 * so this can only happen if this is an ARMv7 or earlier CPU,
7195 * in which case the syndrome information won't actually be
7196 * guest visible.
7197 */
d614a513 7198 assert(!arm_dc_feature(s, ARM_FEATURE_V8));
8bcbf37c
PM
7199 syndrome = syn_uncategorized();
7200 break;
7201 }
7202
43bfa4a1 7203 gen_set_condexec(s);
43722a6d 7204 gen_set_pc_im(s, s->pc_curr);
f59df3f2 7205 tmpptr = tcg_const_ptr(ri);
8bcbf37c 7206 tcg_syn = tcg_const_i32(syndrome);
3f208fd7
PM
7207 tcg_isread = tcg_const_i32(isread);
7208 gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn,
7209 tcg_isread);
f59df3f2 7210 tcg_temp_free_ptr(tmpptr);
8bcbf37c 7211 tcg_temp_free_i32(tcg_syn);
3f208fd7 7212 tcg_temp_free_i32(tcg_isread);
37ff584c
PM
7213 } else if (ri->type & ARM_CP_RAISES_EXC) {
7214 /*
7215 * The readfn or writefn might raise an exception;
7216 * synchronize the CPU state in case it does.
7217 */
7218 gen_set_condexec(s);
7219 gen_set_pc_im(s, s->pc_curr);
f59df3f2
PM
7220 }
7221
4b6a83fb
PM
7222 /* Handle special cases first */
7223 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
7224 case ARM_CP_NOP:
7225 return 0;
7226 case ARM_CP_WFI:
7227 if (isread) {
7228 return 1;
7229 }
a0415916 7230 gen_set_pc_im(s, s->base.pc_next);
dcba3a8d 7231 s->base.is_jmp = DISAS_WFI;
2bee5105 7232 return 0;
4b6a83fb
PM
7233 default:
7234 break;
7235 }
7236
c5a49c63 7237 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
2452731c
PM
7238 gen_io_start();
7239 }
7240
4b6a83fb
PM
7241 if (isread) {
7242 /* Read */
7243 if (is64) {
7244 TCGv_i64 tmp64;
7245 TCGv_i32 tmp;
7246 if (ri->type & ARM_CP_CONST) {
7247 tmp64 = tcg_const_i64(ri->resetvalue);
7248 } else if (ri->readfn) {
7249 TCGv_ptr tmpptr;
4b6a83fb
PM
7250 tmp64 = tcg_temp_new_i64();
7251 tmpptr = tcg_const_ptr(ri);
7252 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
7253 tcg_temp_free_ptr(tmpptr);
7254 } else {
7255 tmp64 = tcg_temp_new_i64();
7256 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
7257 }
7258 tmp = tcg_temp_new_i32();
ecc7b3aa 7259 tcg_gen_extrl_i64_i32(tmp, tmp64);
4b6a83fb 7260 store_reg(s, rt, tmp);
ed336850 7261 tmp = tcg_temp_new_i32();
664b7e3b 7262 tcg_gen_extrh_i64_i32(tmp, tmp64);
ed336850 7263 tcg_temp_free_i64(tmp64);
4b6a83fb
PM
7264 store_reg(s, rt2, tmp);
7265 } else {
39d5492a 7266 TCGv_i32 tmp;
4b6a83fb
PM
7267 if (ri->type & ARM_CP_CONST) {
7268 tmp = tcg_const_i32(ri->resetvalue);
7269 } else if (ri->readfn) {
7270 TCGv_ptr tmpptr;
4b6a83fb
PM
7271 tmp = tcg_temp_new_i32();
7272 tmpptr = tcg_const_ptr(ri);
7273 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
7274 tcg_temp_free_ptr(tmpptr);
7275 } else {
7276 tmp = load_cpu_offset(ri->fieldoffset);
7277 }
7278 if (rt == 15) {
7279 /* Destination register of r15 for 32 bit loads sets
7280 * the condition codes from the high 4 bits of the value
7281 */
7282 gen_set_nzcv(tmp);
7283 tcg_temp_free_i32(tmp);
7284 } else {
7285 store_reg(s, rt, tmp);
7286 }
7287 }
7288 } else {
7289 /* Write */
7290 if (ri->type & ARM_CP_CONST) {
7291 /* If not forbidden by access permissions, treat as WI */
7292 return 0;
7293 }
7294
7295 if (is64) {
39d5492a 7296 TCGv_i32 tmplo, tmphi;
4b6a83fb
PM
7297 TCGv_i64 tmp64 = tcg_temp_new_i64();
7298 tmplo = load_reg(s, rt);
7299 tmphi = load_reg(s, rt2);
7300 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
7301 tcg_temp_free_i32(tmplo);
7302 tcg_temp_free_i32(tmphi);
7303 if (ri->writefn) {
7304 TCGv_ptr tmpptr = tcg_const_ptr(ri);
4b6a83fb
PM
7305 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
7306 tcg_temp_free_ptr(tmpptr);
7307 } else {
7308 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
7309 }
7310 tcg_temp_free_i64(tmp64);
7311 } else {
7312 if (ri->writefn) {
39d5492a 7313 TCGv_i32 tmp;
4b6a83fb 7314 TCGv_ptr tmpptr;
4b6a83fb
PM
7315 tmp = load_reg(s, rt);
7316 tmpptr = tcg_const_ptr(ri);
7317 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
7318 tcg_temp_free_ptr(tmpptr);
7319 tcg_temp_free_i32(tmp);
7320 } else {
39d5492a 7321 TCGv_i32 tmp = load_reg(s, rt);
4b6a83fb
PM
7322 store_cpu_offset(tmp, ri->fieldoffset);
7323 }
7324 }
2452731c
PM
7325 }
7326
c5a49c63 7327 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
2452731c 7328 /* I/O operations must end the TB here (whether read or write) */
2452731c
PM
7329 gen_lookup_tb(s);
7330 } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
4b6a83fb
PM
7331 /* We default to ending the TB on a coprocessor register write,
7332 * but allow this to be suppressed by the register definition
7333 * (usually only necessary to work around guest bugs).
7334 */
2452731c 7335 gen_lookup_tb(s);
4b6a83fb 7336 }
2452731c 7337
4b6a83fb
PM
7338 return 0;
7339 }
7340
626187d8
PM
7341 /* Unknown register; this might be a guest error or a QEMU
7342 * unimplemented feature.
7343 */
7344 if (is64) {
7345 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
51a79b03
PM
7346 "64 bit system register cp:%d opc1: %d crm:%d "
7347 "(%s)\n",
7348 isread ? "read" : "write", cpnum, opc1, crm,
7349 s->ns ? "non-secure" : "secure");
626187d8
PM
7350 } else {
7351 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
51a79b03
PM
7352 "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d "
7353 "(%s)\n",
7354 isread ? "read" : "write", cpnum, opc1, crn, crm, opc2,
7355 s->ns ? "non-secure" : "secure");
626187d8
PM
7356 }
7357
4a9a539f 7358 return 1;
9ee6e8bb
PB
7359}
7360
5e3f878a
PB
7361
7362/* Store a 64-bit value to a register pair. Clobbers val. */
a7812ae4 7363static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5e3f878a 7364{
39d5492a 7365 TCGv_i32 tmp;
7d1b0095 7366 tmp = tcg_temp_new_i32();
ecc7b3aa 7367 tcg_gen_extrl_i64_i32(tmp, val);
5e3f878a 7368 store_reg(s, rlow, tmp);
7d1b0095 7369 tmp = tcg_temp_new_i32();
664b7e3b 7370 tcg_gen_extrh_i64_i32(tmp, val);
5e3f878a
PB
7371 store_reg(s, rhigh, tmp);
7372}
7373
7374/* load a 32-bit value from a register and perform a 64-bit accumulate. */
a7812ae4 7375static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5e3f878a 7376{
a7812ae4 7377 TCGv_i64 tmp;
39d5492a 7378 TCGv_i32 tmp2;
5e3f878a 7379
36aa55dc 7380 /* Load value and extend to 64 bits. */
a7812ae4 7381 tmp = tcg_temp_new_i64();
5e3f878a
PB
7382 tmp2 = load_reg(s, rlow);
7383 tcg_gen_extu_i32_i64(tmp, tmp2);
7d1b0095 7384 tcg_temp_free_i32(tmp2);
5e3f878a 7385 tcg_gen_add_i64(val, val, tmp);
b75263d6 7386 tcg_temp_free_i64(tmp);
5e3f878a
PB
7387}
7388
7389/* load and add a 64-bit value from a register pair. */
a7812ae4 7390static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5e3f878a 7391{
a7812ae4 7392 TCGv_i64 tmp;
39d5492a
PM
7393 TCGv_i32 tmpl;
7394 TCGv_i32 tmph;
5e3f878a
PB
7395
7396 /* Load 64-bit value rd:rn. */
36aa55dc
PB
7397 tmpl = load_reg(s, rlow);
7398 tmph = load_reg(s, rhigh);
a7812ae4 7399 tmp = tcg_temp_new_i64();
36aa55dc 7400 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
7d1b0095
PM
7401 tcg_temp_free_i32(tmpl);
7402 tcg_temp_free_i32(tmph);
5e3f878a 7403 tcg_gen_add_i64(val, val, tmp);
b75263d6 7404 tcg_temp_free_i64(tmp);
5e3f878a
PB
7405}
7406
c9f10124 7407/* Set N and Z flags from hi|lo. */
39d5492a 7408static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
5e3f878a 7409{
c9f10124
RH
7410 tcg_gen_mov_i32(cpu_NF, hi);
7411 tcg_gen_or_i32(cpu_ZF, lo, hi);
5e3f878a
PB
7412}
7413
426f5abc
PB
7414/* Load/Store exclusive instructions are implemented by remembering
7415 the value/address loaded, and seeing if these are the same
354161b3 7416 when the store is performed. This should be sufficient to implement
426f5abc 7417 the architecturally mandated semantics, and avoids having to monitor
354161b3
EC
7418 regular stores. The compare vs the remembered value is done during
7419 the cmpxchg operation, but we must compare the addresses manually. */
426f5abc 7420static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
39d5492a 7421 TCGv_i32 addr, int size)
426f5abc 7422{
94ee24e7 7423 TCGv_i32 tmp = tcg_temp_new_i32();
14776ab5 7424 MemOp opc = size | MO_ALIGN | s->be_data;
426f5abc 7425
50225ad0
PM
7426 s->is_ldex = true;
7427
426f5abc 7428 if (size == 3) {
39d5492a 7429 TCGv_i32 tmp2 = tcg_temp_new_i32();
354161b3 7430 TCGv_i64 t64 = tcg_temp_new_i64();
03d05e2d 7431
3448d47b
PM
7432 /* For AArch32, architecturally the 32-bit word at the lowest
7433 * address is always Rt and the one at addr+4 is Rt2, even if
7434 * the CPU is big-endian. That means we don't want to do a
7435 * gen_aa32_ld_i64(), which invokes gen_aa32_frob64() as if
7436 * for an architecturally 64-bit access, but instead do a
7437 * 64-bit access using MO_BE if appropriate and then split
7438 * the two halves.
7439 * This only makes a difference for BE32 user-mode, where
7440 * frob64() must not flip the two halves of the 64-bit data
7441 * but this code must treat BE32 user-mode like BE32 system.
7442 */
7443 TCGv taddr = gen_aa32_addr(s, addr, opc);
7444
7445 tcg_gen_qemu_ld_i64(t64, taddr, get_mem_index(s), opc);
7446 tcg_temp_free(taddr);
354161b3 7447 tcg_gen_mov_i64(cpu_exclusive_val, t64);
3448d47b
PM
7448 if (s->be_data == MO_BE) {
7449 tcg_gen_extr_i64_i32(tmp2, tmp, t64);
7450 } else {
7451 tcg_gen_extr_i64_i32(tmp, tmp2, t64);
7452 }
354161b3
EC
7453 tcg_temp_free_i64(t64);
7454
7455 store_reg(s, rt2, tmp2);
03d05e2d 7456 } else {
354161b3 7457 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), opc);
03d05e2d 7458 tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
426f5abc 7459 }
03d05e2d
PM
7460
7461 store_reg(s, rt, tmp);
7462 tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
426f5abc
PB
7463}
7464
7465static void gen_clrex(DisasContext *s)
7466{
03d05e2d 7467 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
426f5abc
PB
7468}
7469
426f5abc 7470static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
39d5492a 7471 TCGv_i32 addr, int size)
426f5abc 7472{
354161b3
EC
7473 TCGv_i32 t0, t1, t2;
7474 TCGv_i64 extaddr;
7475 TCGv taddr;
42a268c2
RH
7476 TCGLabel *done_label;
7477 TCGLabel *fail_label;
14776ab5 7478 MemOp opc = size | MO_ALIGN | s->be_data;
426f5abc
PB
7479
7480 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
7481 [addr] = {Rt};
7482 {Rd} = 0;
7483 } else {
7484 {Rd} = 1;
7485 } */
7486 fail_label = gen_new_label();
7487 done_label = gen_new_label();
03d05e2d
PM
7488 extaddr = tcg_temp_new_i64();
7489 tcg_gen_extu_i32_i64(extaddr, addr);
7490 tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
7491 tcg_temp_free_i64(extaddr);
7492
354161b3
EC
7493 taddr = gen_aa32_addr(s, addr, opc);
7494 t0 = tcg_temp_new_i32();
7495 t1 = load_reg(s, rt);
426f5abc 7496 if (size == 3) {
354161b3
EC
7497 TCGv_i64 o64 = tcg_temp_new_i64();
7498 TCGv_i64 n64 = tcg_temp_new_i64();
03d05e2d 7499
354161b3 7500 t2 = load_reg(s, rt2);
3448d47b
PM
7501 /* For AArch32, architecturally the 32-bit word at the lowest
7502 * address is always Rt and the one at addr+4 is Rt2, even if
7503 * the CPU is big-endian. Since we're going to treat this as a
7504 * single 64-bit BE store, we need to put the two halves in the
7505 * opposite order for BE to LE, so that they end up in the right
7506 * places.
7507 * We don't want gen_aa32_frob64() because that does the wrong
7508 * thing for BE32 usermode.
7509 */
7510 if (s->be_data == MO_BE) {
7511 tcg_gen_concat_i32_i64(n64, t2, t1);
7512 } else {
7513 tcg_gen_concat_i32_i64(n64, t1, t2);
7514 }
354161b3 7515 tcg_temp_free_i32(t2);
03d05e2d 7516
354161b3
EC
7517 tcg_gen_atomic_cmpxchg_i64(o64, taddr, cpu_exclusive_val, n64,
7518 get_mem_index(s), opc);
7519 tcg_temp_free_i64(n64);
7520
354161b3
EC
7521 tcg_gen_setcond_i64(TCG_COND_NE, o64, o64, cpu_exclusive_val);
7522 tcg_gen_extrl_i64_i32(t0, o64);
7523
7524 tcg_temp_free_i64(o64);
7525 } else {
7526 t2 = tcg_temp_new_i32();
7527 tcg_gen_extrl_i64_i32(t2, cpu_exclusive_val);
7528 tcg_gen_atomic_cmpxchg_i32(t0, taddr, t2, t1, get_mem_index(s), opc);
7529 tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t2);
7530 tcg_temp_free_i32(t2);
426f5abc 7531 }
354161b3
EC
7532 tcg_temp_free_i32(t1);
7533 tcg_temp_free(taddr);
7534 tcg_gen_mov_i32(cpu_R[rd], t0);
7535 tcg_temp_free_i32(t0);
426f5abc 7536 tcg_gen_br(done_label);
354161b3 7537
426f5abc
PB
7538 gen_set_label(fail_label);
7539 tcg_gen_movi_i32(cpu_R[rd], 1);
7540 gen_set_label(done_label);
03d05e2d 7541 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
426f5abc 7542}
426f5abc 7543
81465888
PM
7544/* gen_srs:
7545 * @env: CPUARMState
7546 * @s: DisasContext
7547 * @mode: mode field from insn (which stack to store to)
7548 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
7549 * @writeback: true if writeback bit set
7550 *
7551 * Generate code for the SRS (Store Return State) insn.
7552 */
7553static void gen_srs(DisasContext *s,
7554 uint32_t mode, uint32_t amode, bool writeback)
7555{
7556 int32_t offset;
cbc0326b
PM
7557 TCGv_i32 addr, tmp;
7558 bool undef = false;
7559
7560 /* SRS is:
7561 * - trapped to EL3 if EL3 is AArch64 and we are at Secure EL1
ba63cf47 7562 * and specified mode is monitor mode
cbc0326b
PM
7563 * - UNDEFINED in Hyp mode
7564 * - UNPREDICTABLE in User or System mode
7565 * - UNPREDICTABLE if the specified mode is:
7566 * -- not implemented
7567 * -- not a valid mode number
7568 * -- a mode that's at a higher exception level
7569 * -- Monitor, if we are Non-secure
f01377f5 7570 * For the UNPREDICTABLE cases we choose to UNDEF.
cbc0326b 7571 */
ba63cf47 7572 if (s->current_el == 1 && !s->ns && mode == ARM_CPU_MODE_MON) {
a767fac8 7573 gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(), 3);
cbc0326b
PM
7574 return;
7575 }
7576
7577 if (s->current_el == 0 || s->current_el == 2) {
7578 undef = true;
7579 }
7580
7581 switch (mode) {
7582 case ARM_CPU_MODE_USR:
7583 case ARM_CPU_MODE_FIQ:
7584 case ARM_CPU_MODE_IRQ:
7585 case ARM_CPU_MODE_SVC:
7586 case ARM_CPU_MODE_ABT:
7587 case ARM_CPU_MODE_UND:
7588 case ARM_CPU_MODE_SYS:
7589 break;
7590 case ARM_CPU_MODE_HYP:
7591 if (s->current_el == 1 || !arm_dc_feature(s, ARM_FEATURE_EL2)) {
7592 undef = true;
7593 }
7594 break;
7595 case ARM_CPU_MODE_MON:
7596 /* No need to check specifically for "are we non-secure" because
7597 * we've already made EL0 UNDEF and handled the trap for S-EL1;
7598 * so if this isn't EL3 then we must be non-secure.
7599 */
7600 if (s->current_el != 3) {
7601 undef = true;
7602 }
7603 break;
7604 default:
7605 undef = true;
7606 }
7607
7608 if (undef) {
1ce21ba1 7609 unallocated_encoding(s);
cbc0326b
PM
7610 return;
7611 }
7612
7613 addr = tcg_temp_new_i32();
7614 tmp = tcg_const_i32(mode);
f01377f5
PM
7615 /* get_r13_banked() will raise an exception if called from System mode */
7616 gen_set_condexec(s);
43722a6d 7617 gen_set_pc_im(s, s->pc_curr);
81465888
PM
7618 gen_helper_get_r13_banked(addr, cpu_env, tmp);
7619 tcg_temp_free_i32(tmp);
7620 switch (amode) {
7621 case 0: /* DA */
7622 offset = -4;
7623 break;
7624 case 1: /* IA */
7625 offset = 0;
7626 break;
7627 case 2: /* DB */
7628 offset = -8;
7629 break;
7630 case 3: /* IB */
7631 offset = 4;
7632 break;
7633 default:
7634 abort();
7635 }
7636 tcg_gen_addi_i32(addr, addr, offset);
7637 tmp = load_reg(s, 14);
12dcc321 7638 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 7639 tcg_temp_free_i32(tmp);
81465888
PM
7640 tmp = load_cpu_field(spsr);
7641 tcg_gen_addi_i32(addr, addr, 4);
12dcc321 7642 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 7643 tcg_temp_free_i32(tmp);
81465888
PM
7644 if (writeback) {
7645 switch (amode) {
7646 case 0:
7647 offset = -8;
7648 break;
7649 case 1:
7650 offset = 4;
7651 break;
7652 case 2:
7653 offset = -4;
7654 break;
7655 case 3:
7656 offset = 0;
7657 break;
7658 default:
7659 abort();
7660 }
7661 tcg_gen_addi_i32(addr, addr, offset);
7662 tmp = tcg_const_i32(mode);
7663 gen_helper_set_r13_banked(cpu_env, tmp, addr);
7664 tcg_temp_free_i32(tmp);
7665 }
7666 tcg_temp_free_i32(addr);
dcba3a8d 7667 s->base.is_jmp = DISAS_UPDATE;
81465888
PM
7668}
7669
c2d9644e
RK
7670/* Generate a label used for skipping this instruction */
7671static void arm_gen_condlabel(DisasContext *s)
7672{
7673 if (!s->condjmp) {
7674 s->condlabel = gen_new_label();
7675 s->condjmp = 1;
7676 }
7677}
7678
7679/* Skip this instruction if the ARM condition is false */
7680static void arm_skip_unless(DisasContext *s, uint32_t cond)
7681{
7682 arm_gen_condlabel(s);
7683 arm_gen_test_cc(cond ^ 1, s->condlabel);
7684}
7685
f4df2210 7686static void disas_arm_insn(DisasContext *s, unsigned int insn)
9ee6e8bb 7687{
f4df2210 7688 unsigned int cond, val, op1, i, shift, rm, rs, rn, rd, sh;
39d5492a
PM
7689 TCGv_i32 tmp;
7690 TCGv_i32 tmp2;
7691 TCGv_i32 tmp3;
7692 TCGv_i32 addr;
a7812ae4 7693 TCGv_i64 tmp64;
9ee6e8bb 7694
e13886e3
PM
7695 /* M variants do not implement ARM mode; this must raise the INVSTATE
7696 * UsageFault exception.
7697 */
b53d8923 7698 if (arm_dc_feature(s, ARM_FEATURE_M)) {
a767fac8 7699 gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
e13886e3
PM
7700 default_exception_el(s));
7701 return;
b53d8923 7702 }
9ee6e8bb
PB
7703 cond = insn >> 28;
7704 if (cond == 0xf){
be5e7a76
DES
7705 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
7706 * choose to UNDEF. In ARMv5 and above the space is used
7707 * for miscellaneous unconditional instructions.
7708 */
7709 ARCH(5);
7710
9ee6e8bb
PB
7711 /* Unconditional instructions. */
7712 if (((insn >> 25) & 7) == 1) {
7713 /* NEON Data processing. */
d614a513 7714 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
9ee6e8bb 7715 goto illegal_op;
d614a513 7716 }
9ee6e8bb 7717
7dcc1f89 7718 if (disas_neon_data_insn(s, insn)) {
9ee6e8bb 7719 goto illegal_op;
7dcc1f89 7720 }
9ee6e8bb
PB
7721 return;
7722 }
7723 if ((insn & 0x0f100000) == 0x04000000) {
7724 /* NEON load/store. */
d614a513 7725 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
9ee6e8bb 7726 goto illegal_op;
d614a513 7727 }
9ee6e8bb 7728
7dcc1f89 7729 if (disas_neon_ls_insn(s, insn)) {
9ee6e8bb 7730 goto illegal_op;
7dcc1f89 7731 }
9ee6e8bb
PB
7732 return;
7733 }
6a57f3eb
WN
7734 if ((insn & 0x0f000e10) == 0x0e000a00) {
7735 /* VFP. */
7dcc1f89 7736 if (disas_vfp_insn(s, insn)) {
6a57f3eb
WN
7737 goto illegal_op;
7738 }
7739 return;
7740 }
3d185e5d
PM
7741 if (((insn & 0x0f30f000) == 0x0510f000) ||
7742 ((insn & 0x0f30f010) == 0x0710f000)) {
7743 if ((insn & (1 << 22)) == 0) {
7744 /* PLDW; v7MP */
d614a513 7745 if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
3d185e5d
PM
7746 goto illegal_op;
7747 }
7748 }
7749 /* Otherwise PLD; v5TE+ */
be5e7a76 7750 ARCH(5TE);
3d185e5d
PM
7751 return;
7752 }
7753 if (((insn & 0x0f70f000) == 0x0450f000) ||
7754 ((insn & 0x0f70f010) == 0x0650f000)) {
7755 ARCH(7);
7756 return; /* PLI; V7 */
7757 }
7758 if (((insn & 0x0f700000) == 0x04100000) ||
7759 ((insn & 0x0f700010) == 0x06100000)) {
d614a513 7760 if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
3d185e5d
PM
7761 goto illegal_op;
7762 }
7763 return; /* v7MP: Unallocated memory hint: must NOP */
7764 }
7765
7766 if ((insn & 0x0ffffdff) == 0x01010000) {
9ee6e8bb
PB
7767 ARCH(6);
7768 /* setend */
9886ecdf
PB
7769 if (((insn >> 9) & 1) != !!(s->be_data == MO_BE)) {
7770 gen_helper_setend(cpu_env);
dcba3a8d 7771 s->base.is_jmp = DISAS_UPDATE;
9ee6e8bb
PB
7772 }
7773 return;
7774 } else if ((insn & 0x0fffff00) == 0x057ff000) {
7775 switch ((insn >> 4) & 0xf) {
7776 case 1: /* clrex */
7777 ARCH(6K);
426f5abc 7778 gen_clrex(s);
9ee6e8bb
PB
7779 return;
7780 case 4: /* dsb */
7781 case 5: /* dmb */
9ee6e8bb 7782 ARCH(7);
61e4c432 7783 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
9ee6e8bb 7784 return;
6df99dec
SS
7785 case 6: /* isb */
7786 /* We need to break the TB after this insn to execute
7787 * self-modifying code correctly and also to take
7788 * any pending interrupts immediately.
7789 */
a0415916 7790 gen_goto_tb(s, 0, s->base.pc_next);
6df99dec 7791 return;
9888bd1e
RH
7792 case 7: /* sb */
7793 if ((insn & 0xf) || !dc_isar_feature(aa32_sb, s)) {
7794 goto illegal_op;
7795 }
7796 /*
7797 * TODO: There is no speculation barrier opcode
7798 * for TCG; MB and end the TB instead.
7799 */
7800 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
a0415916 7801 gen_goto_tb(s, 0, s->base.pc_next);
9888bd1e 7802 return;
9ee6e8bb
PB
7803 default:
7804 goto illegal_op;
7805 }
7806 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
7807 /* srs */
81465888
PM
7808 ARCH(6);
7809 gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21));
3b328448 7810 return;
ea825eee 7811 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
9ee6e8bb 7812 /* rfe */
c67b6b71 7813 int32_t offset;
9ee6e8bb
PB
7814 if (IS_USER(s))
7815 goto illegal_op;
7816 ARCH(6);
7817 rn = (insn >> 16) & 0xf;
b0109805 7818 addr = load_reg(s, rn);
9ee6e8bb
PB
7819 i = (insn >> 23) & 3;
7820 switch (i) {
b0109805 7821 case 0: offset = -4; break; /* DA */
c67b6b71
FN
7822 case 1: offset = 0; break; /* IA */
7823 case 2: offset = -8; break; /* DB */
b0109805 7824 case 3: offset = 4; break; /* IB */
9ee6e8bb
PB
7825 default: abort();
7826 }
7827 if (offset)
b0109805
PB
7828 tcg_gen_addi_i32(addr, addr, offset);
7829 /* Load PC into tmp and CPSR into tmp2. */
5a839c0d 7830 tmp = tcg_temp_new_i32();
12dcc321 7831 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 7832 tcg_gen_addi_i32(addr, addr, 4);
5a839c0d 7833 tmp2 = tcg_temp_new_i32();
12dcc321 7834 gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
9ee6e8bb
PB
7835 if (insn & (1 << 21)) {
7836 /* Base writeback. */
7837 switch (i) {
b0109805 7838 case 0: offset = -8; break;
c67b6b71
FN
7839 case 1: offset = 4; break;
7840 case 2: offset = -4; break;
b0109805 7841 case 3: offset = 0; break;
9ee6e8bb
PB
7842 default: abort();
7843 }
7844 if (offset)
b0109805
PB
7845 tcg_gen_addi_i32(addr, addr, offset);
7846 store_reg(s, rn, addr);
7847 } else {
7d1b0095 7848 tcg_temp_free_i32(addr);
9ee6e8bb 7849 }
b0109805 7850 gen_rfe(s, tmp, tmp2);
c67b6b71 7851 return;
9ee6e8bb
PB
7852 } else if ((insn & 0x0e000000) == 0x0a000000) {
7853 /* branch link and change to thumb (blx <offset>) */
7854 int32_t offset;
7855
7d1b0095 7856 tmp = tcg_temp_new_i32();
a0415916 7857 tcg_gen_movi_i32(tmp, s->base.pc_next);
d9ba4830 7858 store_reg(s, 14, tmp);
9ee6e8bb
PB
7859 /* Sign-extend the 24-bit offset */
7860 offset = (((int32_t)insn) << 8) >> 8;
fdbcf632 7861 val = read_pc(s);
9ee6e8bb
PB
7862 /* offset * 4 + bit24 * 2 + (thumb bit) */
7863 val += (offset << 2) | ((insn >> 23) & 2) | 1;
be5e7a76 7864 /* protected by ARCH(5); above, near the start of uncond block */
d9ba4830 7865 gen_bx_im(s, val);
9ee6e8bb
PB
7866 return;
7867 } else if ((insn & 0x0e000f00) == 0x0c000100) {
d614a513 7868 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
9ee6e8bb 7869 /* iWMMXt register transfer. */
c0f4af17 7870 if (extract32(s->c15_cpar, 1, 1)) {
7dcc1f89 7871 if (!disas_iwmmxt_insn(s, insn)) {
9ee6e8bb 7872 return;
c0f4af17
PM
7873 }
7874 }
9ee6e8bb 7875 }
8b7209fa
RH
7876 } else if ((insn & 0x0e000a00) == 0x0c000800
7877 && arm_dc_feature(s, ARM_FEATURE_V8)) {
7878 if (disas_neon_insn_3same_ext(s, insn)) {
7879 goto illegal_op;
7880 }
7881 return;
638808ff
RH
7882 } else if ((insn & 0x0f000a00) == 0x0e000800
7883 && arm_dc_feature(s, ARM_FEATURE_V8)) {
7884 if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
7885 goto illegal_op;
7886 }
7887 return;
9ee6e8bb
PB
7888 } else if ((insn & 0x0fe00000) == 0x0c400000) {
7889 /* Coprocessor double register transfer. */
be5e7a76 7890 ARCH(5TE);
9ee6e8bb
PB
7891 } else if ((insn & 0x0f000010) == 0x0e000010) {
7892 /* Additional coprocessor register transfer. */
7997d92f 7893 } else if ((insn & 0x0ff10020) == 0x01000000) {
9ee6e8bb
PB
7894 uint32_t mask;
7895 uint32_t val;
7896 /* cps (privileged) */
7897 if (IS_USER(s))
7898 return;
7899 mask = val = 0;
7900 if (insn & (1 << 19)) {
7901 if (insn & (1 << 8))
7902 mask |= CPSR_A;
7903 if (insn & (1 << 7))
7904 mask |= CPSR_I;
7905 if (insn & (1 << 6))
7906 mask |= CPSR_F;
7907 if (insn & (1 << 18))
7908 val |= mask;
7909 }
7997d92f 7910 if (insn & (1 << 17)) {
9ee6e8bb
PB
7911 mask |= CPSR_M;
7912 val |= (insn & 0x1f);
7913 }
7914 if (mask) {
2fbac54b 7915 gen_set_psr_im(s, mask, 0, val);
9ee6e8bb
PB
7916 }
7917 return;
7918 }
7919 goto illegal_op;
7920 }
7921 if (cond != 0xe) {
7922 /* if not always execute, we generate a conditional jump to
7923 next instruction */
c2d9644e 7924 arm_skip_unless(s, cond);
9ee6e8bb
PB
7925 }
7926 if ((insn & 0x0f900000) == 0x03000000) {
7927 if ((insn & (1 << 21)) == 0) {
7928 ARCH(6T2);
7929 rd = (insn >> 12) & 0xf;
7930 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
7931 if ((insn & (1 << 22)) == 0) {
7932 /* MOVW */
7d1b0095 7933 tmp = tcg_temp_new_i32();
5e3f878a 7934 tcg_gen_movi_i32(tmp, val);
9ee6e8bb
PB
7935 } else {
7936 /* MOVT */
5e3f878a 7937 tmp = load_reg(s, rd);
86831435 7938 tcg_gen_ext16u_i32(tmp, tmp);
5e3f878a 7939 tcg_gen_ori_i32(tmp, tmp, val << 16);
9ee6e8bb 7940 }
5e3f878a 7941 store_reg(s, rd, tmp);
9ee6e8bb
PB
7942 } else {
7943 if (((insn >> 12) & 0xf) != 0xf)
7944 goto illegal_op;
7945 if (((insn >> 16) & 0xf) == 0) {
7946 gen_nop_hint(s, insn & 0xff);
7947 } else {
7948 /* CPSR = immediate */
7949 val = insn & 0xff;
7950 shift = ((insn >> 8) & 0xf) * 2;
dd861b3f 7951 val = ror32(val, shift);
9ee6e8bb 7952 i = ((insn & (1 << 22)) != 0);
7dcc1f89
PM
7953 if (gen_set_psr_im(s, msr_mask(s, (insn >> 16) & 0xf, i),
7954 i, val)) {
9ee6e8bb 7955 goto illegal_op;
7dcc1f89 7956 }
9ee6e8bb
PB
7957 }
7958 }
7959 } else if ((insn & 0x0f900000) == 0x01000000
7960 && (insn & 0x00000090) != 0x00000090) {
7961 /* miscellaneous instructions */
7962 op1 = (insn >> 21) & 3;
7963 sh = (insn >> 4) & 0xf;
7964 rm = insn & 0xf;
7965 switch (sh) {
8bfd0550
PM
7966 case 0x0: /* MSR, MRS */
7967 if (insn & (1 << 9)) {
7968 /* MSR (banked) and MRS (banked) */
7969 int sysm = extract32(insn, 16, 4) |
7970 (extract32(insn, 8, 1) << 4);
7971 int r = extract32(insn, 22, 1);
7972
7973 if (op1 & 1) {
7974 /* MSR (banked) */
7975 gen_msr_banked(s, r, sysm, rm);
7976 } else {
7977 /* MRS (banked) */
7978 int rd = extract32(insn, 12, 4);
7979
7980 gen_mrs_banked(s, r, sysm, rd);
7981 }
7982 break;
7983 }
7984
7985 /* MSR, MRS (for PSRs) */
9ee6e8bb
PB
7986 if (op1 & 1) {
7987 /* PSR = reg */
2fbac54b 7988 tmp = load_reg(s, rm);
9ee6e8bb 7989 i = ((op1 & 2) != 0);
7dcc1f89 7990 if (gen_set_psr(s, msr_mask(s, (insn >> 16) & 0xf, i), i, tmp))
9ee6e8bb
PB
7991 goto illegal_op;
7992 } else {
7993 /* reg = PSR */
7994 rd = (insn >> 12) & 0xf;
7995 if (op1 & 2) {
7996 if (IS_USER(s))
7997 goto illegal_op;
d9ba4830 7998 tmp = load_cpu_field(spsr);
9ee6e8bb 7999 } else {
7d1b0095 8000 tmp = tcg_temp_new_i32();
9ef39277 8001 gen_helper_cpsr_read(tmp, cpu_env);
9ee6e8bb 8002 }
d9ba4830 8003 store_reg(s, rd, tmp);
9ee6e8bb
PB
8004 }
8005 break;
8006 case 0x1:
8007 if (op1 == 1) {
8008 /* branch/exchange thumb (bx). */
be5e7a76 8009 ARCH(4T);
d9ba4830
PB
8010 tmp = load_reg(s, rm);
8011 gen_bx(s, tmp);
9ee6e8bb
PB
8012 } else if (op1 == 3) {
8013 /* clz */
be5e7a76 8014 ARCH(5);
9ee6e8bb 8015 rd = (insn >> 12) & 0xf;
1497c961 8016 tmp = load_reg(s, rm);
7539a012 8017 tcg_gen_clzi_i32(tmp, tmp, 32);
1497c961 8018 store_reg(s, rd, tmp);
9ee6e8bb
PB
8019 } else {
8020 goto illegal_op;
8021 }
8022 break;
8023 case 0x2:
8024 if (op1 == 1) {
8025 ARCH(5J); /* bxj */
8026 /* Trivial implementation equivalent to bx. */
d9ba4830
PB
8027 tmp = load_reg(s, rm);
8028 gen_bx(s, tmp);
9ee6e8bb
PB
8029 } else {
8030 goto illegal_op;
8031 }
8032 break;
8033 case 0x3:
8034 if (op1 != 1)
8035 goto illegal_op;
8036
be5e7a76 8037 ARCH(5);
9ee6e8bb 8038 /* branch link/exchange thumb (blx) */
d9ba4830 8039 tmp = load_reg(s, rm);
7d1b0095 8040 tmp2 = tcg_temp_new_i32();
a0415916 8041 tcg_gen_movi_i32(tmp2, s->base.pc_next);
d9ba4830
PB
8042 store_reg(s, 14, tmp2);
8043 gen_bx(s, tmp);
9ee6e8bb 8044 break;
eb0ecd5a
WN
8045 case 0x4:
8046 {
8047 /* crc32/crc32c */
8048 uint32_t c = extract32(insn, 8, 4);
8049
8050 /* Check this CPU supports ARMv8 CRC instructions.
8051 * op1 == 3 is UNPREDICTABLE but handle as UNDEFINED.
8052 * Bits 8, 10 and 11 should be zero.
8053 */
962fcbf2 8054 if (!dc_isar_feature(aa32_crc32, s) || op1 == 0x3 || (c & 0xd) != 0) {
eb0ecd5a
WN
8055 goto illegal_op;
8056 }
8057
8058 rn = extract32(insn, 16, 4);
8059 rd = extract32(insn, 12, 4);
8060
8061 tmp = load_reg(s, rn);
8062 tmp2 = load_reg(s, rm);
aa633469
PM
8063 if (op1 == 0) {
8064 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
8065 } else if (op1 == 1) {
8066 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
8067 }
eb0ecd5a
WN
8068 tmp3 = tcg_const_i32(1 << op1);
8069 if (c & 0x2) {
8070 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
8071 } else {
8072 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
8073 }
8074 tcg_temp_free_i32(tmp2);
8075 tcg_temp_free_i32(tmp3);
8076 store_reg(s, rd, tmp);
8077 break;
8078 }
9ee6e8bb 8079 case 0x5: /* saturating add/subtract */
be5e7a76 8080 ARCH(5TE);
9ee6e8bb
PB
8081 rd = (insn >> 12) & 0xf;
8082 rn = (insn >> 16) & 0xf;
b40d0353 8083 tmp = load_reg(s, rm);
5e3f878a 8084 tmp2 = load_reg(s, rn);
9ee6e8bb 8085 if (op1 & 2)
640581a0 8086 gen_helper_add_saturate(tmp2, cpu_env, tmp2, tmp2);
9ee6e8bb 8087 if (op1 & 1)
9ef39277 8088 gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 8089 else
9ef39277 8090 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
7d1b0095 8091 tcg_temp_free_i32(tmp2);
5e3f878a 8092 store_reg(s, rd, tmp);
9ee6e8bb 8093 break;
55c544ed
PM
8094 case 0x6: /* ERET */
8095 if (op1 != 3) {
8096 goto illegal_op;
8097 }
8098 if (!arm_dc_feature(s, ARM_FEATURE_V7VE)) {
8099 goto illegal_op;
8100 }
8101 if ((insn & 0x000fff0f) != 0x0000000e) {
8102 /* UNPREDICTABLE; we choose to UNDEF */
8103 goto illegal_op;
8104 }
8105
8106 if (s->current_el == 2) {
8107 tmp = load_cpu_field(elr_el[2]);
8108 } else {
8109 tmp = load_reg(s, 14);
8110 }
8111 gen_exception_return(s, tmp);
8112 break;
49e14940 8113 case 7:
d4a2dc67
PM
8114 {
8115 int imm16 = extract32(insn, 0, 4) | (extract32(insn, 8, 12) << 4);
37e6456e 8116 switch (op1) {
19a6e31c
PM
8117 case 0:
8118 /* HLT */
8119 gen_hlt(s, imm16);
8120 break;
37e6456e
PM
8121 case 1:
8122 /* bkpt */
8123 ARCH(5);
06bcbda3 8124 gen_exception_bkpt_insn(s, syn_aa32_bkpt(imm16, false));
37e6456e
PM
8125 break;
8126 case 2:
8127 /* Hypervisor call (v7) */
8128 ARCH(7);
8129 if (IS_USER(s)) {
8130 goto illegal_op;
8131 }
8132 gen_hvc(s, imm16);
8133 break;
8134 case 3:
8135 /* Secure monitor call (v6+) */
8136 ARCH(6K);
8137 if (IS_USER(s)) {
8138 goto illegal_op;
8139 }
8140 gen_smc(s);
8141 break;
8142 default:
19a6e31c 8143 g_assert_not_reached();
49e14940 8144 }
9ee6e8bb 8145 break;
d4a2dc67 8146 }
9ee6e8bb
PB
8147 case 0x8: /* signed multiply */
8148 case 0xa:
8149 case 0xc:
8150 case 0xe:
be5e7a76 8151 ARCH(5TE);
9ee6e8bb
PB
8152 rs = (insn >> 8) & 0xf;
8153 rn = (insn >> 12) & 0xf;
8154 rd = (insn >> 16) & 0xf;
8155 if (op1 == 1) {
8156 /* (32 * 16) >> 16 */
5e3f878a
PB
8157 tmp = load_reg(s, rm);
8158 tmp2 = load_reg(s, rs);
9ee6e8bb 8159 if (sh & 4)
5e3f878a 8160 tcg_gen_sari_i32(tmp2, tmp2, 16);
9ee6e8bb 8161 else
5e3f878a 8162 gen_sxth(tmp2);
a7812ae4
PB
8163 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8164 tcg_gen_shri_i64(tmp64, tmp64, 16);
7d1b0095 8165 tmp = tcg_temp_new_i32();
ecc7b3aa 8166 tcg_gen_extrl_i64_i32(tmp, tmp64);
b75263d6 8167 tcg_temp_free_i64(tmp64);
9ee6e8bb 8168 if ((sh & 2) == 0) {
5e3f878a 8169 tmp2 = load_reg(s, rn);
9ef39277 8170 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 8171 tcg_temp_free_i32(tmp2);
9ee6e8bb 8172 }
5e3f878a 8173 store_reg(s, rd, tmp);
9ee6e8bb
PB
8174 } else {
8175 /* 16 * 16 */
5e3f878a
PB
8176 tmp = load_reg(s, rm);
8177 tmp2 = load_reg(s, rs);
8178 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
7d1b0095 8179 tcg_temp_free_i32(tmp2);
9ee6e8bb 8180 if (op1 == 2) {
a7812ae4
PB
8181 tmp64 = tcg_temp_new_i64();
8182 tcg_gen_ext_i32_i64(tmp64, tmp);
7d1b0095 8183 tcg_temp_free_i32(tmp);
a7812ae4
PB
8184 gen_addq(s, tmp64, rn, rd);
8185 gen_storeq_reg(s, rn, rd, tmp64);
b75263d6 8186 tcg_temp_free_i64(tmp64);
9ee6e8bb
PB
8187 } else {
8188 if (op1 == 0) {
5e3f878a 8189 tmp2 = load_reg(s, rn);
9ef39277 8190 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 8191 tcg_temp_free_i32(tmp2);
9ee6e8bb 8192 }
5e3f878a 8193 store_reg(s, rd, tmp);
9ee6e8bb
PB
8194 }
8195 }
8196 break;
8197 default:
8198 goto illegal_op;
8199 }
8200 } else if (((insn & 0x0e000000) == 0 &&
8201 (insn & 0x00000090) != 0x90) ||
8202 ((insn & 0x0e000000) == (1 << 25))) {
8203 int set_cc, logic_cc, shiftop;
8204
8205 op1 = (insn >> 21) & 0xf;
8206 set_cc = (insn >> 20) & 1;
8207 logic_cc = table_logic_cc[op1] & set_cc;
8208
8209 /* data processing instruction */
8210 if (insn & (1 << 25)) {
8211 /* immediate operand */
8212 val = insn & 0xff;
8213 shift = ((insn >> 8) & 0xf) * 2;
dd861b3f 8214 val = ror32(val, shift);
7d1b0095 8215 tmp2 = tcg_temp_new_i32();
e9bb4aa9
JR
8216 tcg_gen_movi_i32(tmp2, val);
8217 if (logic_cc && shift) {
8218 gen_set_CF_bit31(tmp2);
8219 }
9ee6e8bb
PB
8220 } else {
8221 /* register */
8222 rm = (insn) & 0xf;
e9bb4aa9 8223 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
8224 shiftop = (insn >> 5) & 3;
8225 if (!(insn & (1 << 4))) {
8226 shift = (insn >> 7) & 0x1f;
e9bb4aa9 8227 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
9ee6e8bb
PB
8228 } else {
8229 rs = (insn >> 8) & 0xf;
8984bd2e 8230 tmp = load_reg(s, rs);
e9bb4aa9 8231 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
9ee6e8bb
PB
8232 }
8233 }
8234 if (op1 != 0x0f && op1 != 0x0d) {
8235 rn = (insn >> 16) & 0xf;
e9bb4aa9
JR
8236 tmp = load_reg(s, rn);
8237 } else {
f764718d 8238 tmp = NULL;
9ee6e8bb
PB
8239 }
8240 rd = (insn >> 12) & 0xf;
8241 switch(op1) {
8242 case 0x00:
e9bb4aa9
JR
8243 tcg_gen_and_i32(tmp, tmp, tmp2);
8244 if (logic_cc) {
8245 gen_logic_CC(tmp);
8246 }
7dcc1f89 8247 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8248 break;
8249 case 0x01:
e9bb4aa9
JR
8250 tcg_gen_xor_i32(tmp, tmp, tmp2);
8251 if (logic_cc) {
8252 gen_logic_CC(tmp);
8253 }
7dcc1f89 8254 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8255 break;
8256 case 0x02:
8257 if (set_cc && rd == 15) {
8258 /* SUBS r15, ... is used for exception return. */
e9bb4aa9 8259 if (IS_USER(s)) {
9ee6e8bb 8260 goto illegal_op;
e9bb4aa9 8261 }
72485ec4 8262 gen_sub_CC(tmp, tmp, tmp2);
e9bb4aa9 8263 gen_exception_return(s, tmp);
9ee6e8bb 8264 } else {
e9bb4aa9 8265 if (set_cc) {
72485ec4 8266 gen_sub_CC(tmp, tmp, tmp2);
e9bb4aa9
JR
8267 } else {
8268 tcg_gen_sub_i32(tmp, tmp, tmp2);
8269 }
7dcc1f89 8270 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8271 }
8272 break;
8273 case 0x03:
e9bb4aa9 8274 if (set_cc) {
72485ec4 8275 gen_sub_CC(tmp, tmp2, tmp);
e9bb4aa9
JR
8276 } else {
8277 tcg_gen_sub_i32(tmp, tmp2, tmp);
8278 }
7dcc1f89 8279 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8280 break;
8281 case 0x04:
e9bb4aa9 8282 if (set_cc) {
72485ec4 8283 gen_add_CC(tmp, tmp, tmp2);
e9bb4aa9
JR
8284 } else {
8285 tcg_gen_add_i32(tmp, tmp, tmp2);
8286 }
7dcc1f89 8287 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8288 break;
8289 case 0x05:
e9bb4aa9 8290 if (set_cc) {
49b4c31e 8291 gen_adc_CC(tmp, tmp, tmp2);
e9bb4aa9
JR
8292 } else {
8293 gen_add_carry(tmp, tmp, tmp2);
8294 }
7dcc1f89 8295 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8296 break;
8297 case 0x06:
e9bb4aa9 8298 if (set_cc) {
2de68a49 8299 gen_sbc_CC(tmp, tmp, tmp2);
e9bb4aa9
JR
8300 } else {
8301 gen_sub_carry(tmp, tmp, tmp2);
8302 }
7dcc1f89 8303 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8304 break;
8305 case 0x07:
e9bb4aa9 8306 if (set_cc) {
2de68a49 8307 gen_sbc_CC(tmp, tmp2, tmp);
e9bb4aa9
JR
8308 } else {
8309 gen_sub_carry(tmp, tmp2, tmp);
8310 }
7dcc1f89 8311 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8312 break;
8313 case 0x08:
8314 if (set_cc) {
e9bb4aa9
JR
8315 tcg_gen_and_i32(tmp, tmp, tmp2);
8316 gen_logic_CC(tmp);
9ee6e8bb 8317 }
7d1b0095 8318 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8319 break;
8320 case 0x09:
8321 if (set_cc) {
e9bb4aa9
JR
8322 tcg_gen_xor_i32(tmp, tmp, tmp2);
8323 gen_logic_CC(tmp);
9ee6e8bb 8324 }
7d1b0095 8325 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8326 break;
8327 case 0x0a:
8328 if (set_cc) {
72485ec4 8329 gen_sub_CC(tmp, tmp, tmp2);
9ee6e8bb 8330 }
7d1b0095 8331 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8332 break;
8333 case 0x0b:
8334 if (set_cc) {
72485ec4 8335 gen_add_CC(tmp, tmp, tmp2);
9ee6e8bb 8336 }
7d1b0095 8337 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8338 break;
8339 case 0x0c:
e9bb4aa9
JR
8340 tcg_gen_or_i32(tmp, tmp, tmp2);
8341 if (logic_cc) {
8342 gen_logic_CC(tmp);
8343 }
7dcc1f89 8344 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8345 break;
8346 case 0x0d:
8347 if (logic_cc && rd == 15) {
8348 /* MOVS r15, ... is used for exception return. */
e9bb4aa9 8349 if (IS_USER(s)) {
9ee6e8bb 8350 goto illegal_op;
e9bb4aa9
JR
8351 }
8352 gen_exception_return(s, tmp2);
9ee6e8bb 8353 } else {
e9bb4aa9
JR
8354 if (logic_cc) {
8355 gen_logic_CC(tmp2);
8356 }
7dcc1f89 8357 store_reg_bx(s, rd, tmp2);
9ee6e8bb
PB
8358 }
8359 break;
8360 case 0x0e:
f669df27 8361 tcg_gen_andc_i32(tmp, tmp, tmp2);
e9bb4aa9
JR
8362 if (logic_cc) {
8363 gen_logic_CC(tmp);
8364 }
7dcc1f89 8365 store_reg_bx(s, rd, tmp);
9ee6e8bb
PB
8366 break;
8367 default:
8368 case 0x0f:
e9bb4aa9
JR
8369 tcg_gen_not_i32(tmp2, tmp2);
8370 if (logic_cc) {
8371 gen_logic_CC(tmp2);
8372 }
7dcc1f89 8373 store_reg_bx(s, rd, tmp2);
9ee6e8bb
PB
8374 break;
8375 }
e9bb4aa9 8376 if (op1 != 0x0f && op1 != 0x0d) {
7d1b0095 8377 tcg_temp_free_i32(tmp2);
e9bb4aa9 8378 }
9ee6e8bb
PB
8379 } else {
8380 /* other instructions */
8381 op1 = (insn >> 24) & 0xf;
8382 switch(op1) {
8383 case 0x0:
8384 case 0x1:
8385 /* multiplies, extra load/stores */
8386 sh = (insn >> 5) & 3;
8387 if (sh == 0) {
8388 if (op1 == 0x0) {
8389 rd = (insn >> 16) & 0xf;
8390 rn = (insn >> 12) & 0xf;
8391 rs = (insn >> 8) & 0xf;
8392 rm = (insn) & 0xf;
8393 op1 = (insn >> 20) & 0xf;
8394 switch (op1) {
8395 case 0: case 1: case 2: case 3: case 6:
8396 /* 32 bit mul */
5e3f878a
PB
8397 tmp = load_reg(s, rs);
8398 tmp2 = load_reg(s, rm);
8399 tcg_gen_mul_i32(tmp, tmp, tmp2);
7d1b0095 8400 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
8401 if (insn & (1 << 22)) {
8402 /* Subtract (mls) */
8403 ARCH(6T2);
5e3f878a
PB
8404 tmp2 = load_reg(s, rn);
8405 tcg_gen_sub_i32(tmp, tmp2, tmp);
7d1b0095 8406 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
8407 } else if (insn & (1 << 21)) {
8408 /* Add */
5e3f878a
PB
8409 tmp2 = load_reg(s, rn);
8410 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 8411 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
8412 }
8413 if (insn & (1 << 20))
5e3f878a
PB
8414 gen_logic_CC(tmp);
8415 store_reg(s, rd, tmp);
9ee6e8bb 8416 break;
8aac08b1
AJ
8417 case 4:
8418 /* 64 bit mul double accumulate (UMAAL) */
8419 ARCH(6);
8420 tmp = load_reg(s, rs);
8421 tmp2 = load_reg(s, rm);
8422 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
8423 gen_addq_lo(s, tmp64, rn);
8424 gen_addq_lo(s, tmp64, rd);
8425 gen_storeq_reg(s, rn, rd, tmp64);
8426 tcg_temp_free_i64(tmp64);
8427 break;
8428 case 8: case 9: case 10: case 11:
8429 case 12: case 13: case 14: case 15:
8430 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
5e3f878a
PB
8431 tmp = load_reg(s, rs);
8432 tmp2 = load_reg(s, rm);
8aac08b1 8433 if (insn & (1 << 22)) {
c9f10124 8434 tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2);
8aac08b1 8435 } else {
c9f10124 8436 tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2);
8aac08b1
AJ
8437 }
8438 if (insn & (1 << 21)) { /* mult accumulate */
39d5492a
PM
8439 TCGv_i32 al = load_reg(s, rn);
8440 TCGv_i32 ah = load_reg(s, rd);
c9f10124 8441 tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, al, ah);
39d5492a
PM
8442 tcg_temp_free_i32(al);
8443 tcg_temp_free_i32(ah);
9ee6e8bb 8444 }
8aac08b1 8445 if (insn & (1 << 20)) {
c9f10124 8446 gen_logicq_cc(tmp, tmp2);
8aac08b1 8447 }
c9f10124
RH
8448 store_reg(s, rn, tmp);
8449 store_reg(s, rd, tmp2);
9ee6e8bb 8450 break;
8aac08b1
AJ
8451 default:
8452 goto illegal_op;
9ee6e8bb
PB
8453 }
8454 } else {
8455 rn = (insn >> 16) & 0xf;
8456 rd = (insn >> 12) & 0xf;
8457 if (insn & (1 << 23)) {
8458 /* load/store exclusive */
96c55295
PM
8459 bool is_ld = extract32(insn, 20, 1);
8460 bool is_lasr = !extract32(insn, 8, 1);
2359bf80 8461 int op2 = (insn >> 8) & 3;
86753403 8462 op1 = (insn >> 21) & 0x3;
2359bf80
MR
8463
8464 switch (op2) {
8465 case 0: /* lda/stl */
8466 if (op1 == 1) {
8467 goto illegal_op;
8468 }
8469 ARCH(8);
8470 break;
8471 case 1: /* reserved */
8472 goto illegal_op;
8473 case 2: /* ldaex/stlex */
8474 ARCH(8);
8475 break;
8476 case 3: /* ldrex/strex */
8477 if (op1) {
8478 ARCH(6K);
8479 } else {
8480 ARCH(6);
8481 }
8482 break;
8483 }
8484
3174f8e9 8485 addr = tcg_temp_local_new_i32();
98a46317 8486 load_reg_var(s, addr, rn);
2359bf80 8487
96c55295
PM
8488 if (is_lasr && !is_ld) {
8489 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
8490 }
8491
2359bf80 8492 if (op2 == 0) {
96c55295 8493 if (is_ld) {
2359bf80
MR
8494 tmp = tcg_temp_new_i32();
8495 switch (op1) {
8496 case 0: /* lda */
9bb6558a
PM
8497 gen_aa32_ld32u_iss(s, tmp, addr,
8498 get_mem_index(s),
8499 rd | ISSIsAcqRel);
2359bf80
MR
8500 break;
8501 case 2: /* ldab */
9bb6558a
PM
8502 gen_aa32_ld8u_iss(s, tmp, addr,
8503 get_mem_index(s),
8504 rd | ISSIsAcqRel);
2359bf80
MR
8505 break;
8506 case 3: /* ldah */
9bb6558a
PM
8507 gen_aa32_ld16u_iss(s, tmp, addr,
8508 get_mem_index(s),
8509 rd | ISSIsAcqRel);
2359bf80
MR
8510 break;
8511 default:
8512 abort();
8513 }
8514 store_reg(s, rd, tmp);
8515 } else {
8516 rm = insn & 0xf;
8517 tmp = load_reg(s, rm);
8518 switch (op1) {
8519 case 0: /* stl */
9bb6558a
PM
8520 gen_aa32_st32_iss(s, tmp, addr,
8521 get_mem_index(s),
8522 rm | ISSIsAcqRel);
2359bf80
MR
8523 break;
8524 case 2: /* stlb */
9bb6558a
PM
8525 gen_aa32_st8_iss(s, tmp, addr,
8526 get_mem_index(s),
8527 rm | ISSIsAcqRel);
2359bf80
MR
8528 break;
8529 case 3: /* stlh */
9bb6558a
PM
8530 gen_aa32_st16_iss(s, tmp, addr,
8531 get_mem_index(s),
8532 rm | ISSIsAcqRel);
2359bf80
MR
8533 break;
8534 default:
8535 abort();
8536 }
8537 tcg_temp_free_i32(tmp);
8538 }
96c55295 8539 } else if (is_ld) {
86753403
PB
8540 switch (op1) {
8541 case 0: /* ldrex */
426f5abc 8542 gen_load_exclusive(s, rd, 15, addr, 2);
86753403
PB
8543 break;
8544 case 1: /* ldrexd */
426f5abc 8545 gen_load_exclusive(s, rd, rd + 1, addr, 3);
86753403
PB
8546 break;
8547 case 2: /* ldrexb */
426f5abc 8548 gen_load_exclusive(s, rd, 15, addr, 0);
86753403
PB
8549 break;
8550 case 3: /* ldrexh */
426f5abc 8551 gen_load_exclusive(s, rd, 15, addr, 1);
86753403
PB
8552 break;
8553 default:
8554 abort();
8555 }
9ee6e8bb
PB
8556 } else {
8557 rm = insn & 0xf;
86753403
PB
8558 switch (op1) {
8559 case 0: /* strex */
426f5abc 8560 gen_store_exclusive(s, rd, rm, 15, addr, 2);
86753403
PB
8561 break;
8562 case 1: /* strexd */
502e64fe 8563 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
86753403
PB
8564 break;
8565 case 2: /* strexb */
426f5abc 8566 gen_store_exclusive(s, rd, rm, 15, addr, 0);
86753403
PB
8567 break;
8568 case 3: /* strexh */
426f5abc 8569 gen_store_exclusive(s, rd, rm, 15, addr, 1);
86753403
PB
8570 break;
8571 default:
8572 abort();
8573 }
9ee6e8bb 8574 }
39d5492a 8575 tcg_temp_free_i32(addr);
96c55295
PM
8576
8577 if (is_lasr && is_ld) {
8578 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
8579 }
c4869ca6
OS
8580 } else if ((insn & 0x00300f00) == 0) {
8581 /* 0bcccc_0001_0x00_xxxx_xxxx_0000_1001_xxxx
8582 * - SWP, SWPB
8583 */
8584
cf12bce0 8585 TCGv taddr;
14776ab5 8586 MemOp opc = s->be_data;
cf12bce0 8587
9ee6e8bb
PB
8588 rm = (insn) & 0xf;
8589
9ee6e8bb 8590 if (insn & (1 << 22)) {
cf12bce0 8591 opc |= MO_UB;
9ee6e8bb 8592 } else {
cf12bce0 8593 opc |= MO_UL | MO_ALIGN;
9ee6e8bb 8594 }
cf12bce0
EC
8595
8596 addr = load_reg(s, rn);
8597 taddr = gen_aa32_addr(s, addr, opc);
7d1b0095 8598 tcg_temp_free_i32(addr);
cf12bce0
EC
8599
8600 tmp = load_reg(s, rm);
8601 tcg_gen_atomic_xchg_i32(tmp, taddr, tmp,
8602 get_mem_index(s), opc);
8603 tcg_temp_free(taddr);
8604 store_reg(s, rd, tmp);
c4869ca6
OS
8605 } else {
8606 goto illegal_op;
9ee6e8bb
PB
8607 }
8608 }
8609 } else {
8610 int address_offset;
3960c336 8611 bool load = insn & (1 << 20);
63f26fcf
PM
8612 bool wbit = insn & (1 << 21);
8613 bool pbit = insn & (1 << 24);
3960c336 8614 bool doubleword = false;
9bb6558a
PM
8615 ISSInfo issinfo;
8616
9ee6e8bb
PB
8617 /* Misc load/store */
8618 rn = (insn >> 16) & 0xf;
8619 rd = (insn >> 12) & 0xf;
3960c336 8620
9bb6558a
PM
8621 /* ISS not valid if writeback */
8622 issinfo = (pbit & !wbit) ? rd : ISSInvalid;
8623
3960c336
PM
8624 if (!load && (sh & 2)) {
8625 /* doubleword */
8626 ARCH(5TE);
8627 if (rd & 1) {
8628 /* UNPREDICTABLE; we choose to UNDEF */
8629 goto illegal_op;
8630 }
8631 load = (sh & 1) == 0;
8632 doubleword = true;
8633 }
8634
b0109805 8635 addr = load_reg(s, rn);
63f26fcf 8636 if (pbit) {
b0109805 8637 gen_add_datah_offset(s, insn, 0, addr);
63f26fcf 8638 }
9ee6e8bb 8639 address_offset = 0;
3960c336
PM
8640
8641 if (doubleword) {
8642 if (!load) {
9ee6e8bb 8643 /* store */
b0109805 8644 tmp = load_reg(s, rd);
12dcc321 8645 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 8646 tcg_temp_free_i32(tmp);
b0109805
PB
8647 tcg_gen_addi_i32(addr, addr, 4);
8648 tmp = load_reg(s, rd + 1);
12dcc321 8649 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 8650 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8651 } else {
8652 /* load */
5a839c0d 8653 tmp = tcg_temp_new_i32();
12dcc321 8654 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805
PB
8655 store_reg(s, rd, tmp);
8656 tcg_gen_addi_i32(addr, addr, 4);
5a839c0d 8657 tmp = tcg_temp_new_i32();
12dcc321 8658 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9ee6e8bb 8659 rd++;
9ee6e8bb
PB
8660 }
8661 address_offset = -4;
3960c336
PM
8662 } else if (load) {
8663 /* load */
8664 tmp = tcg_temp_new_i32();
8665 switch (sh) {
8666 case 1:
9bb6558a
PM
8667 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s),
8668 issinfo);
3960c336
PM
8669 break;
8670 case 2:
9bb6558a
PM
8671 gen_aa32_ld8s_iss(s, tmp, addr, get_mem_index(s),
8672 issinfo);
3960c336
PM
8673 break;
8674 default:
8675 case 3:
9bb6558a
PM
8676 gen_aa32_ld16s_iss(s, tmp, addr, get_mem_index(s),
8677 issinfo);
3960c336
PM
8678 break;
8679 }
9ee6e8bb
PB
8680 } else {
8681 /* store */
b0109805 8682 tmp = load_reg(s, rd);
9bb6558a 8683 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), issinfo);
5a839c0d 8684 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
8685 }
8686 /* Perform base writeback before the loaded value to
8687 ensure correct behavior with overlapping index registers.
b6af0975 8688 ldrd with base writeback is undefined if the
9ee6e8bb 8689 destination and index registers overlap. */
63f26fcf 8690 if (!pbit) {
b0109805
PB
8691 gen_add_datah_offset(s, insn, address_offset, addr);
8692 store_reg(s, rn, addr);
63f26fcf 8693 } else if (wbit) {
9ee6e8bb 8694 if (address_offset)
b0109805
PB
8695 tcg_gen_addi_i32(addr, addr, address_offset);
8696 store_reg(s, rn, addr);
8697 } else {
7d1b0095 8698 tcg_temp_free_i32(addr);
9ee6e8bb
PB
8699 }
8700 if (load) {
8701 /* Complete the load. */
b0109805 8702 store_reg(s, rd, tmp);
9ee6e8bb
PB
8703 }
8704 }
8705 break;
8706 case 0x4:
8707 case 0x5:
8708 goto do_ldst;
8709 case 0x6:
8710 case 0x7:
8711 if (insn & (1 << 4)) {
8712 ARCH(6);
8713 /* Armv6 Media instructions. */
8714 rm = insn & 0xf;
8715 rn = (insn >> 16) & 0xf;
2c0262af 8716 rd = (insn >> 12) & 0xf;
9ee6e8bb
PB
8717 rs = (insn >> 8) & 0xf;
8718 switch ((insn >> 23) & 3) {
8719 case 0: /* Parallel add/subtract. */
8720 op1 = (insn >> 20) & 7;
6ddbc6e4
PB
8721 tmp = load_reg(s, rn);
8722 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
8723 sh = (insn >> 5) & 7;
8724 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
8725 goto illegal_op;
6ddbc6e4 8726 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
7d1b0095 8727 tcg_temp_free_i32(tmp2);
6ddbc6e4 8728 store_reg(s, rd, tmp);
9ee6e8bb
PB
8729 break;
8730 case 1:
8731 if ((insn & 0x00700020) == 0) {
6c95676b 8732 /* Halfword pack. */
3670669c
PB
8733 tmp = load_reg(s, rn);
8734 tmp2 = load_reg(s, rm);
9ee6e8bb 8735 shift = (insn >> 7) & 0x1f;
3670669c
PB
8736 if (insn & (1 << 6)) {
8737 /* pkhtb */
d1f8755f 8738 if (shift == 0) {
22478e79 8739 shift = 31;
d1f8755f 8740 }
22478e79 8741 tcg_gen_sari_i32(tmp2, tmp2, shift);
d1f8755f 8742 tcg_gen_deposit_i32(tmp, tmp, tmp2, 0, 16);
3670669c
PB
8743 } else {
8744 /* pkhbt */
d1f8755f
RH
8745 tcg_gen_shli_i32(tmp2, tmp2, shift);
8746 tcg_gen_deposit_i32(tmp, tmp2, tmp, 0, 16);
3670669c 8747 }
7d1b0095 8748 tcg_temp_free_i32(tmp2);
3670669c 8749 store_reg(s, rd, tmp);
9ee6e8bb
PB
8750 } else if ((insn & 0x00200020) == 0x00200000) {
8751 /* [us]sat */
6ddbc6e4 8752 tmp = load_reg(s, rm);
9ee6e8bb
PB
8753 shift = (insn >> 7) & 0x1f;
8754 if (insn & (1 << 6)) {
8755 if (shift == 0)
8756 shift = 31;
6ddbc6e4 8757 tcg_gen_sari_i32(tmp, tmp, shift);
9ee6e8bb 8758 } else {
6ddbc6e4 8759 tcg_gen_shli_i32(tmp, tmp, shift);
9ee6e8bb
PB
8760 }
8761 sh = (insn >> 16) & 0x1f;
40d3c433
CL
8762 tmp2 = tcg_const_i32(sh);
8763 if (insn & (1 << 22))
9ef39277 8764 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
40d3c433 8765 else
9ef39277 8766 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
40d3c433 8767 tcg_temp_free_i32(tmp2);
6ddbc6e4 8768 store_reg(s, rd, tmp);
9ee6e8bb
PB
8769 } else if ((insn & 0x00300fe0) == 0x00200f20) {
8770 /* [us]sat16 */
6ddbc6e4 8771 tmp = load_reg(s, rm);
9ee6e8bb 8772 sh = (insn >> 16) & 0x1f;
40d3c433
CL
8773 tmp2 = tcg_const_i32(sh);
8774 if (insn & (1 << 22))
9ef39277 8775 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
40d3c433 8776 else
9ef39277 8777 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
40d3c433 8778 tcg_temp_free_i32(tmp2);
6ddbc6e4 8779 store_reg(s, rd, tmp);
9ee6e8bb
PB
8780 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
8781 /* Select bytes. */
6ddbc6e4
PB
8782 tmp = load_reg(s, rn);
8783 tmp2 = load_reg(s, rm);
7d1b0095 8784 tmp3 = tcg_temp_new_i32();
0ecb72a5 8785 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
6ddbc6e4 8786 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7d1b0095
PM
8787 tcg_temp_free_i32(tmp3);
8788 tcg_temp_free_i32(tmp2);
6ddbc6e4 8789 store_reg(s, rd, tmp);
9ee6e8bb 8790 } else if ((insn & 0x000003e0) == 0x00000060) {
5e3f878a 8791 tmp = load_reg(s, rm);
9ee6e8bb 8792 shift = (insn >> 10) & 3;
1301f322 8793 /* ??? In many cases it's not necessary to do a
9ee6e8bb 8794 rotate, a shift is sufficient. */
464eaa95 8795 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
9ee6e8bb
PB
8796 op1 = (insn >> 20) & 7;
8797 switch (op1) {
5e3f878a
PB
8798 case 0: gen_sxtb16(tmp); break;
8799 case 2: gen_sxtb(tmp); break;
8800 case 3: gen_sxth(tmp); break;
8801 case 4: gen_uxtb16(tmp); break;
8802 case 6: gen_uxtb(tmp); break;
8803 case 7: gen_uxth(tmp); break;
9ee6e8bb
PB
8804 default: goto illegal_op;
8805 }
8806 if (rn != 15) {
5e3f878a 8807 tmp2 = load_reg(s, rn);
9ee6e8bb 8808 if ((op1 & 3) == 0) {
5e3f878a 8809 gen_add16(tmp, tmp2);
9ee6e8bb 8810 } else {
5e3f878a 8811 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 8812 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
8813 }
8814 }
6c95676b 8815 store_reg(s, rd, tmp);
9ee6e8bb
PB
8816 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
8817 /* rev */
b0109805 8818 tmp = load_reg(s, rm);
9ee6e8bb
PB
8819 if (insn & (1 << 22)) {
8820 if (insn & (1 << 7)) {
b0109805 8821 gen_revsh(tmp);
9ee6e8bb
PB
8822 } else {
8823 ARCH(6T2);
b0109805 8824 gen_helper_rbit(tmp, tmp);
9ee6e8bb
PB
8825 }
8826 } else {
8827 if (insn & (1 << 7))
b0109805 8828 gen_rev16(tmp);
9ee6e8bb 8829 else
66896cb8 8830 tcg_gen_bswap32_i32(tmp, tmp);
9ee6e8bb 8831 }
b0109805 8832 store_reg(s, rd, tmp);
9ee6e8bb
PB
8833 } else {
8834 goto illegal_op;
8835 }
8836 break;
8837 case 2: /* Multiplies (Type 3). */
41e9564d
PM
8838 switch ((insn >> 20) & 0x7) {
8839 case 5:
8840 if (((insn >> 6) ^ (insn >> 7)) & 1) {
8841 /* op2 not 00x or 11x : UNDEF */
8842 goto illegal_op;
8843 }
838fa72d
AJ
8844 /* Signed multiply most significant [accumulate].
8845 (SMMUL, SMMLA, SMMLS) */
41e9564d
PM
8846 tmp = load_reg(s, rm);
8847 tmp2 = load_reg(s, rs);
5f8cd06e 8848 tcg_gen_muls2_i32(tmp2, tmp, tmp, tmp2);
838fa72d 8849
955a7dd5 8850 if (rd != 15) {
5f8cd06e 8851 tmp3 = load_reg(s, rd);
9ee6e8bb 8852 if (insn & (1 << 6)) {
e0a0c832
RH
8853 /*
8854 * For SMMLS, we need a 64-bit subtract.
8855 * Borrow caused by a non-zero multiplicand
8856 * lowpart, and the correct result lowpart
8857 * for rounding.
8858 */
8859 TCGv_i32 zero = tcg_const_i32(0);
8860 tcg_gen_sub2_i32(tmp2, tmp, zero, tmp3,
8861 tmp2, tmp);
8862 tcg_temp_free_i32(zero);
9ee6e8bb 8863 } else {
5f8cd06e 8864 tcg_gen_add_i32(tmp, tmp, tmp3);
9ee6e8bb 8865 }
5f8cd06e 8866 tcg_temp_free_i32(tmp3);
9ee6e8bb 8867 }
838fa72d 8868 if (insn & (1 << 5)) {
5f8cd06e
RH
8869 /*
8870 * Adding 0x80000000 to the 64-bit quantity
8871 * means that we have carry in to the high
8872 * word when the low word has the high bit set.
8873 */
8874 tcg_gen_shri_i32(tmp2, tmp2, 31);
8875 tcg_gen_add_i32(tmp, tmp, tmp2);
838fa72d 8876 }
5f8cd06e 8877 tcg_temp_free_i32(tmp2);
955a7dd5 8878 store_reg(s, rn, tmp);
41e9564d
PM
8879 break;
8880 case 0:
8881 case 4:
8882 /* SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD */
8883 if (insn & (1 << 7)) {
8884 goto illegal_op;
8885 }
8886 tmp = load_reg(s, rm);
8887 tmp2 = load_reg(s, rs);
9ee6e8bb 8888 if (insn & (1 << 5))
5e3f878a
PB
8889 gen_swap_half(tmp2);
8890 gen_smul_dual(tmp, tmp2);
9ee6e8bb 8891 if (insn & (1 << 22)) {
5e3f878a 8892 /* smlald, smlsld */
33bbd75a
PC
8893 TCGv_i64 tmp64_2;
8894
a7812ae4 8895 tmp64 = tcg_temp_new_i64();
33bbd75a 8896 tmp64_2 = tcg_temp_new_i64();
a7812ae4 8897 tcg_gen_ext_i32_i64(tmp64, tmp);
33bbd75a 8898 tcg_gen_ext_i32_i64(tmp64_2, tmp2);
7d1b0095 8899 tcg_temp_free_i32(tmp);
33bbd75a
PC
8900 tcg_temp_free_i32(tmp2);
8901 if (insn & (1 << 6)) {
8902 tcg_gen_sub_i64(tmp64, tmp64, tmp64_2);
8903 } else {
8904 tcg_gen_add_i64(tmp64, tmp64, tmp64_2);
8905 }
8906 tcg_temp_free_i64(tmp64_2);
a7812ae4
PB
8907 gen_addq(s, tmp64, rd, rn);
8908 gen_storeq_reg(s, rd, rn, tmp64);
b75263d6 8909 tcg_temp_free_i64(tmp64);
9ee6e8bb 8910 } else {
5e3f878a 8911 /* smuad, smusd, smlad, smlsd */
33bbd75a
PC
8912 if (insn & (1 << 6)) {
8913 /* This subtraction cannot overflow. */
8914 tcg_gen_sub_i32(tmp, tmp, tmp2);
8915 } else {
8916 /* This addition cannot overflow 32 bits;
8917 * however it may overflow considered as a
8918 * signed operation, in which case we must set
8919 * the Q flag.
8920 */
8921 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8922 }
8923 tcg_temp_free_i32(tmp2);
22478e79 8924 if (rd != 15)
9ee6e8bb 8925 {
22478e79 8926 tmp2 = load_reg(s, rd);
9ef39277 8927 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 8928 tcg_temp_free_i32(tmp2);
9ee6e8bb 8929 }
22478e79 8930 store_reg(s, rn, tmp);
9ee6e8bb 8931 }
41e9564d 8932 break;
b8b8ea05
PM
8933 case 1:
8934 case 3:
8935 /* SDIV, UDIV */
7e0cf8b4 8936 if (!dc_isar_feature(arm_div, s)) {
b8b8ea05
PM
8937 goto illegal_op;
8938 }
8939 if (((insn >> 5) & 7) || (rd != 15)) {
8940 goto illegal_op;
8941 }
8942 tmp = load_reg(s, rm);
8943 tmp2 = load_reg(s, rs);
8944 if (insn & (1 << 21)) {
8945 gen_helper_udiv(tmp, tmp, tmp2);
8946 } else {
8947 gen_helper_sdiv(tmp, tmp, tmp2);
8948 }
8949 tcg_temp_free_i32(tmp2);
8950 store_reg(s, rn, tmp);
8951 break;
41e9564d
PM
8952 default:
8953 goto illegal_op;
9ee6e8bb
PB
8954 }
8955 break;
8956 case 3:
8957 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
8958 switch (op1) {
8959 case 0: /* Unsigned sum of absolute differences. */
6ddbc6e4
PB
8960 ARCH(6);
8961 tmp = load_reg(s, rm);
8962 tmp2 = load_reg(s, rs);
8963 gen_helper_usad8(tmp, tmp, tmp2);
7d1b0095 8964 tcg_temp_free_i32(tmp2);
ded9d295
AZ
8965 if (rd != 15) {
8966 tmp2 = load_reg(s, rd);
6ddbc6e4 8967 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 8968 tcg_temp_free_i32(tmp2);
9ee6e8bb 8969 }
ded9d295 8970 store_reg(s, rn, tmp);
9ee6e8bb
PB
8971 break;
8972 case 0x20: case 0x24: case 0x28: case 0x2c:
8973 /* Bitfield insert/clear. */
8974 ARCH(6T2);
8975 shift = (insn >> 7) & 0x1f;
8976 i = (insn >> 16) & 0x1f;
45140a57
KB
8977 if (i < shift) {
8978 /* UNPREDICTABLE; we choose to UNDEF */
8979 goto illegal_op;
8980 }
9ee6e8bb
PB
8981 i = i + 1 - shift;
8982 if (rm == 15) {
7d1b0095 8983 tmp = tcg_temp_new_i32();
5e3f878a 8984 tcg_gen_movi_i32(tmp, 0);
9ee6e8bb 8985 } else {
5e3f878a 8986 tmp = load_reg(s, rm);
9ee6e8bb
PB
8987 }
8988 if (i != 32) {
5e3f878a 8989 tmp2 = load_reg(s, rd);
d593c48e 8990 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, i);
7d1b0095 8991 tcg_temp_free_i32(tmp2);
9ee6e8bb 8992 }
5e3f878a 8993 store_reg(s, rd, tmp);
9ee6e8bb
PB
8994 break;
8995 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
8996 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
4cc633c3 8997 ARCH(6T2);
5e3f878a 8998 tmp = load_reg(s, rm);
9ee6e8bb
PB
8999 shift = (insn >> 7) & 0x1f;
9000 i = ((insn >> 16) & 0x1f) + 1;
9001 if (shift + i > 32)
9002 goto illegal_op;
9003 if (i < 32) {
9004 if (op1 & 0x20) {
59a71b4c 9005 tcg_gen_extract_i32(tmp, tmp, shift, i);
9ee6e8bb 9006 } else {
59a71b4c 9007 tcg_gen_sextract_i32(tmp, tmp, shift, i);
9ee6e8bb
PB
9008 }
9009 }
5e3f878a 9010 store_reg(s, rd, tmp);
9ee6e8bb
PB
9011 break;
9012 default:
9013 goto illegal_op;
9014 }
9015 break;
9016 }
9017 break;
9018 }
9019 do_ldst:
9020 /* Check for undefined extension instructions
9021 * per the ARM Bible IE:
9022 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
9023 */
9024 sh = (0xf << 20) | (0xf << 4);
9025 if (op1 == 0x7 && ((insn & sh) == sh))
9026 {
9027 goto illegal_op;
9028 }
9029 /* load/store byte/word */
9030 rn = (insn >> 16) & 0xf;
9031 rd = (insn >> 12) & 0xf;
b0109805 9032 tmp2 = load_reg(s, rn);
a99caa48
PM
9033 if ((insn & 0x01200000) == 0x00200000) {
9034 /* ldrt/strt */
579d21cc 9035 i = get_a32_user_mem_index(s);
a99caa48
PM
9036 } else {
9037 i = get_mem_index(s);
9038 }
9ee6e8bb 9039 if (insn & (1 << 24))
b0109805 9040 gen_add_data_offset(s, insn, tmp2);
9ee6e8bb
PB
9041 if (insn & (1 << 20)) {
9042 /* load */
5a839c0d 9043 tmp = tcg_temp_new_i32();
9ee6e8bb 9044 if (insn & (1 << 22)) {
9bb6558a 9045 gen_aa32_ld8u_iss(s, tmp, tmp2, i, rd);
9ee6e8bb 9046 } else {
9bb6558a 9047 gen_aa32_ld32u_iss(s, tmp, tmp2, i, rd);
9ee6e8bb 9048 }
9ee6e8bb
PB
9049 } else {
9050 /* store */
b0109805 9051 tmp = load_reg(s, rd);
5a839c0d 9052 if (insn & (1 << 22)) {
9bb6558a 9053 gen_aa32_st8_iss(s, tmp, tmp2, i, rd);
5a839c0d 9054 } else {
9bb6558a 9055 gen_aa32_st32_iss(s, tmp, tmp2, i, rd);
5a839c0d
PM
9056 }
9057 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
9058 }
9059 if (!(insn & (1 << 24))) {
b0109805
PB
9060 gen_add_data_offset(s, insn, tmp2);
9061 store_reg(s, rn, tmp2);
9062 } else if (insn & (1 << 21)) {
9063 store_reg(s, rn, tmp2);
9064 } else {
7d1b0095 9065 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
9066 }
9067 if (insn & (1 << 20)) {
9068 /* Complete the load. */
7dcc1f89 9069 store_reg_from_load(s, rd, tmp);
9ee6e8bb
PB
9070 }
9071 break;
9072 case 0x08:
9073 case 0x09:
9074 {
da3e53dd
PM
9075 int j, n, loaded_base;
9076 bool exc_return = false;
9077 bool is_load = extract32(insn, 20, 1);
9078 bool user = false;
39d5492a 9079 TCGv_i32 loaded_var;
9ee6e8bb
PB
9080 /* load/store multiple words */
9081 /* XXX: store correct base if write back */
9ee6e8bb 9082 if (insn & (1 << 22)) {
da3e53dd 9083 /* LDM (user), LDM (exception return) and STM (user) */
9ee6e8bb
PB
9084 if (IS_USER(s))
9085 goto illegal_op; /* only usable in supervisor mode */
9086
da3e53dd
PM
9087 if (is_load && extract32(insn, 15, 1)) {
9088 exc_return = true;
9089 } else {
9090 user = true;
9091 }
9ee6e8bb
PB
9092 }
9093 rn = (insn >> 16) & 0xf;
b0109805 9094 addr = load_reg(s, rn);
9ee6e8bb
PB
9095
9096 /* compute total size */
9097 loaded_base = 0;
f764718d 9098 loaded_var = NULL;
9ee6e8bb 9099 n = 0;
9798ac71 9100 for (i = 0; i < 16; i++) {
9ee6e8bb
PB
9101 if (insn & (1 << i))
9102 n++;
9103 }
9104 /* XXX: test invalid n == 0 case ? */
9105 if (insn & (1 << 23)) {
9106 if (insn & (1 << 24)) {
9107 /* pre increment */
b0109805 9108 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb
PB
9109 } else {
9110 /* post increment */
9111 }
9112 } else {
9113 if (insn & (1 << 24)) {
9114 /* pre decrement */
b0109805 9115 tcg_gen_addi_i32(addr, addr, -(n * 4));
9ee6e8bb
PB
9116 } else {
9117 /* post decrement */
9118 if (n != 1)
b0109805 9119 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
9ee6e8bb
PB
9120 }
9121 }
9122 j = 0;
9798ac71 9123 for (i = 0; i < 16; i++) {
9ee6e8bb 9124 if (insn & (1 << i)) {
da3e53dd 9125 if (is_load) {
9ee6e8bb 9126 /* load */
5a839c0d 9127 tmp = tcg_temp_new_i32();
12dcc321 9128 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
be5e7a76 9129 if (user) {
b75263d6 9130 tmp2 = tcg_const_i32(i);
1ce94f81 9131 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
b75263d6 9132 tcg_temp_free_i32(tmp2);
7d1b0095 9133 tcg_temp_free_i32(tmp);
9ee6e8bb 9134 } else if (i == rn) {
b0109805 9135 loaded_var = tmp;
9ee6e8bb 9136 loaded_base = 1;
9d090d17 9137 } else if (i == 15 && exc_return) {
fb0e8e79 9138 store_pc_exc_ret(s, tmp);
9ee6e8bb 9139 } else {
7dcc1f89 9140 store_reg_from_load(s, i, tmp);
9ee6e8bb
PB
9141 }
9142 } else {
9143 /* store */
9144 if (i == 15) {
7d1b0095 9145 tmp = tcg_temp_new_i32();
fdbcf632 9146 tcg_gen_movi_i32(tmp, read_pc(s));
9ee6e8bb 9147 } else if (user) {
7d1b0095 9148 tmp = tcg_temp_new_i32();
b75263d6 9149 tmp2 = tcg_const_i32(i);
9ef39277 9150 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
b75263d6 9151 tcg_temp_free_i32(tmp2);
9ee6e8bb 9152 } else {
b0109805 9153 tmp = load_reg(s, i);
9ee6e8bb 9154 }
12dcc321 9155 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 9156 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
9157 }
9158 j++;
9159 /* no need to add after the last transfer */
9160 if (j != n)
b0109805 9161 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb
PB
9162 }
9163 }
9164 if (insn & (1 << 21)) {
9165 /* write back */
9166 if (insn & (1 << 23)) {
9167 if (insn & (1 << 24)) {
9168 /* pre increment */
9169 } else {
9170 /* post increment */
b0109805 9171 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb
PB
9172 }
9173 } else {
9174 if (insn & (1 << 24)) {
9175 /* pre decrement */
9176 if (n != 1)
b0109805 9177 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
9ee6e8bb
PB
9178 } else {
9179 /* post decrement */
b0109805 9180 tcg_gen_addi_i32(addr, addr, -(n * 4));
9ee6e8bb
PB
9181 }
9182 }
b0109805
PB
9183 store_reg(s, rn, addr);
9184 } else {
7d1b0095 9185 tcg_temp_free_i32(addr);
9ee6e8bb
PB
9186 }
9187 if (loaded_base) {
b0109805 9188 store_reg(s, rn, loaded_var);
9ee6e8bb 9189 }
da3e53dd 9190 if (exc_return) {
9ee6e8bb 9191 /* Restore CPSR from SPSR. */
d9ba4830 9192 tmp = load_cpu_field(spsr);
e69ad9df
AL
9193 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
9194 gen_io_start();
9195 }
235ea1f5 9196 gen_helper_cpsr_write_eret(cpu_env, tmp);
7d1b0095 9197 tcg_temp_free_i32(tmp);
b29fd33d 9198 /* Must exit loop to check un-masked IRQs */
dcba3a8d 9199 s->base.is_jmp = DISAS_EXIT;
9ee6e8bb
PB
9200 }
9201 }
9202 break;
9203 case 0xa:
9204 case 0xb:
9205 {
9206 int32_t offset;
9207
9208 /* branch (and link) */
9ee6e8bb 9209 if (insn & (1 << 24)) {
7d1b0095 9210 tmp = tcg_temp_new_i32();
a0415916 9211 tcg_gen_movi_i32(tmp, s->base.pc_next);
5e3f878a 9212 store_reg(s, 14, tmp);
9ee6e8bb 9213 }
534df156 9214 offset = sextract32(insn << 2, 0, 26);
fdbcf632 9215 gen_jmp(s, read_pc(s) + offset);
9ee6e8bb
PB
9216 }
9217 break;
9218 case 0xc:
9219 case 0xd:
9220 case 0xe:
6a57f3eb
WN
9221 if (((insn >> 8) & 0xe) == 10) {
9222 /* VFP. */
7dcc1f89 9223 if (disas_vfp_insn(s, insn)) {
6a57f3eb
WN
9224 goto illegal_op;
9225 }
7dcc1f89 9226 } else if (disas_coproc_insn(s, insn)) {
6a57f3eb 9227 /* Coprocessor. */
9ee6e8bb 9228 goto illegal_op;
6a57f3eb 9229 }
9ee6e8bb
PB
9230 break;
9231 case 0xf:
9232 /* swi */
a0415916 9233 gen_set_pc_im(s, s->base.pc_next);
d4a2dc67 9234 s->svc_imm = extract32(insn, 0, 24);
dcba3a8d 9235 s->base.is_jmp = DISAS_SWI;
9ee6e8bb
PB
9236 break;
9237 default:
9238 illegal_op:
1ce21ba1 9239 unallocated_encoding(s);
9ee6e8bb
PB
9240 break;
9241 }
9242 }
9243}
9244
331b1ca6 9245static bool thumb_insn_is_16bit(DisasContext *s, uint32_t pc, uint32_t insn)
296e5a0a 9246{
331b1ca6
RH
9247 /*
9248 * Return true if this is a 16 bit instruction. We must be precise
9249 * about this (matching the decode).
296e5a0a
PM
9250 */
9251 if ((insn >> 11) < 0x1d) {
9252 /* Definitely a 16-bit instruction */
9253 return true;
9254 }
9255
9256 /* Top five bits 0b11101 / 0b11110 / 0b11111 : this is the
9257 * first half of a 32-bit Thumb insn. Thumb-1 cores might
9258 * end up actually treating this as two 16-bit insns, though,
9259 * if it's half of a bl/blx pair that might span a page boundary.
9260 */
14120108
JS
9261 if (arm_dc_feature(s, ARM_FEATURE_THUMB2) ||
9262 arm_dc_feature(s, ARM_FEATURE_M)) {
296e5a0a
PM
9263 /* Thumb2 cores (including all M profile ones) always treat
9264 * 32-bit insns as 32-bit.
9265 */
9266 return false;
9267 }
9268
331b1ca6 9269 if ((insn >> 11) == 0x1e && pc - s->page_start < TARGET_PAGE_SIZE - 3) {
296e5a0a
PM
9270 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix, and the suffix
9271 * is not on the next page; we merge this into a 32-bit
9272 * insn.
9273 */
9274 return false;
9275 }
9276 /* 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF);
9277 * 0b1111_1xxx_xxxx_xxxx : BL suffix;
9278 * 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix on the end of a page
9279 * -- handle as single 16 bit insn
9280 */
9281 return true;
9282}
9283
9ee6e8bb
PB
9284/* Return true if this is a Thumb-2 logical op. */
9285static int
9286thumb2_logic_op(int op)
9287{
9288 return (op < 8);
9289}
9290
9291/* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
9292 then set condition code flags based on the result of the operation.
9293 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
9294 to the high bit of T1.
9295 Returns zero if the opcode is valid. */
9296
9297static int
39d5492a
PM
9298gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out,
9299 TCGv_i32 t0, TCGv_i32 t1)
9ee6e8bb
PB
9300{
9301 int logic_cc;
9302
9303 logic_cc = 0;
9304 switch (op) {
9305 case 0: /* and */
396e467c 9306 tcg_gen_and_i32(t0, t0, t1);
9ee6e8bb
PB
9307 logic_cc = conds;
9308 break;
9309 case 1: /* bic */
f669df27 9310 tcg_gen_andc_i32(t0, t0, t1);
9ee6e8bb
PB
9311 logic_cc = conds;
9312 break;
9313 case 2: /* orr */
396e467c 9314 tcg_gen_or_i32(t0, t0, t1);
9ee6e8bb
PB
9315 logic_cc = conds;
9316 break;
9317 case 3: /* orn */
29501f1b 9318 tcg_gen_orc_i32(t0, t0, t1);
9ee6e8bb
PB
9319 logic_cc = conds;
9320 break;
9321 case 4: /* eor */
396e467c 9322 tcg_gen_xor_i32(t0, t0, t1);
9ee6e8bb
PB
9323 logic_cc = conds;
9324 break;
9325 case 8: /* add */
9326 if (conds)
72485ec4 9327 gen_add_CC(t0, t0, t1);
9ee6e8bb 9328 else
396e467c 9329 tcg_gen_add_i32(t0, t0, t1);
9ee6e8bb
PB
9330 break;
9331 case 10: /* adc */
9332 if (conds)
49b4c31e 9333 gen_adc_CC(t0, t0, t1);
9ee6e8bb 9334 else
396e467c 9335 gen_adc(t0, t1);
9ee6e8bb
PB
9336 break;
9337 case 11: /* sbc */
2de68a49
RH
9338 if (conds) {
9339 gen_sbc_CC(t0, t0, t1);
9340 } else {
396e467c 9341 gen_sub_carry(t0, t0, t1);
2de68a49 9342 }
9ee6e8bb
PB
9343 break;
9344 case 13: /* sub */
9345 if (conds)
72485ec4 9346 gen_sub_CC(t0, t0, t1);
9ee6e8bb 9347 else
396e467c 9348 tcg_gen_sub_i32(t0, t0, t1);
9ee6e8bb
PB
9349 break;
9350 case 14: /* rsb */
9351 if (conds)
72485ec4 9352 gen_sub_CC(t0, t1, t0);
9ee6e8bb 9353 else
396e467c 9354 tcg_gen_sub_i32(t0, t1, t0);
9ee6e8bb
PB
9355 break;
9356 default: /* 5, 6, 7, 9, 12, 15. */
9357 return 1;
9358 }
9359 if (logic_cc) {
396e467c 9360 gen_logic_CC(t0);
9ee6e8bb 9361 if (shifter_out)
396e467c 9362 gen_set_CF_bit31(t1);
9ee6e8bb
PB
9363 }
9364 return 0;
9365}
9366
2eea841c
PM
9367/* Translate a 32-bit thumb instruction. */
9368static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
9ee6e8bb 9369{
296e5a0a 9370 uint32_t imm, shift, offset;
9ee6e8bb 9371 uint32_t rd, rn, rm, rs;
39d5492a
PM
9372 TCGv_i32 tmp;
9373 TCGv_i32 tmp2;
9374 TCGv_i32 tmp3;
9375 TCGv_i32 addr;
a7812ae4 9376 TCGv_i64 tmp64;
9ee6e8bb
PB
9377 int op;
9378 int shiftop;
9379 int conds;
9380 int logic_cc;
9381
14120108
JS
9382 /*
9383 * ARMv6-M supports a limited subset of Thumb2 instructions.
9384 * Other Thumb1 architectures allow only 32-bit
9385 * combined BL/BLX prefix and suffix.
296e5a0a 9386 */
14120108
JS
9387 if (arm_dc_feature(s, ARM_FEATURE_M) &&
9388 !arm_dc_feature(s, ARM_FEATURE_V7)) {
9389 int i;
9390 bool found = false;
8297cb13
JS
9391 static const uint32_t armv6m_insn[] = {0xf3808000 /* msr */,
9392 0xf3b08040 /* dsb */,
9393 0xf3b08050 /* dmb */,
9394 0xf3b08060 /* isb */,
9395 0xf3e08000 /* mrs */,
9396 0xf000d000 /* bl */};
9397 static const uint32_t armv6m_mask[] = {0xffe0d000,
9398 0xfff0d0f0,
9399 0xfff0d0f0,
9400 0xfff0d0f0,
9401 0xffe0d000,
9402 0xf800d000};
14120108
JS
9403
9404 for (i = 0; i < ARRAY_SIZE(armv6m_insn); i++) {
9405 if ((insn & armv6m_mask[i]) == armv6m_insn[i]) {
9406 found = true;
9407 break;
9408 }
9409 }
9410 if (!found) {
9411 goto illegal_op;
9412 }
9413 } else if ((insn & 0xf800e800) != 0xf000e800) {
9ee6e8bb
PB
9414 ARCH(6T2);
9415 }
9416
9417 rn = (insn >> 16) & 0xf;
9418 rs = (insn >> 12) & 0xf;
9419 rd = (insn >> 8) & 0xf;
9420 rm = insn & 0xf;
9421 switch ((insn >> 25) & 0xf) {
9422 case 0: case 1: case 2: case 3:
9423 /* 16-bit instructions. Should never happen. */
9424 abort();
9425 case 4:
9426 if (insn & (1 << 22)) {
ebfe27c5
PM
9427 /* 0b1110_100x_x1xx_xxxx_xxxx_xxxx_xxxx_xxxx
9428 * - load/store doubleword, load/store exclusive, ldacq/strel,
5158de24 9429 * table branch, TT.
ebfe27c5 9430 */
76eff04d
PM
9431 if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_M) &&
9432 arm_dc_feature(s, ARM_FEATURE_V8)) {
9433 /* 0b1110_1001_0111_1111_1110_1001_0111_111
9434 * - SG (v8M only)
9435 * The bulk of the behaviour for this instruction is implemented
9436 * in v7m_handle_execute_nsc(), which deals with the insn when
9437 * it is executed by a CPU in non-secure state from memory
9438 * which is Secure & NonSecure-Callable.
9439 * Here we only need to handle the remaining cases:
9440 * * in NS memory (including the "security extension not
9441 * implemented" case) : NOP
9442 * * in S memory but CPU already secure (clear IT bits)
9443 * We know that the attribute for the memory this insn is
9444 * in must match the current CPU state, because otherwise
9445 * get_phys_addr_pmsav8 would have generated an exception.
9446 */
9447 if (s->v8m_secure) {
9448 /* Like the IT insn, we don't need to generate any code */
9449 s->condexec_cond = 0;
9450 s->condexec_mask = 0;
9451 }
9452 } else if (insn & 0x01200000) {
ebfe27c5
PM
9453 /* 0b1110_1000_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
9454 * - load/store dual (post-indexed)
9455 * 0b1111_1001_x10x_xxxx_xxxx_xxxx_xxxx_xxxx
9456 * - load/store dual (literal and immediate)
9457 * 0b1111_1001_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
9458 * - load/store dual (pre-indexed)
9459 */
910d7692
PM
9460 bool wback = extract32(insn, 21, 1);
9461
16e0d823
RH
9462 if (rn == 15 && (insn & (1 << 21))) {
9463 /* UNPREDICTABLE */
9464 goto illegal_op;
9ee6e8bb 9465 }
16e0d823
RH
9466
9467 addr = add_reg_for_lit(s, rn, 0);
9ee6e8bb 9468 offset = (insn & 0xff) * 4;
910d7692 9469 if ((insn & (1 << 23)) == 0) {
9ee6e8bb 9470 offset = -offset;
910d7692
PM
9471 }
9472
9473 if (s->v8m_stackcheck && rn == 13 && wback) {
9474 /*
9475 * Here 'addr' is the current SP; if offset is +ve we're
9476 * moving SP up, else down. It is UNKNOWN whether the limit
9477 * check triggers when SP starts below the limit and ends
9478 * up above it; check whichever of the current and final
9479 * SP is lower, so QEMU will trigger in that situation.
9480 */
9481 if ((int32_t)offset < 0) {
9482 TCGv_i32 newsp = tcg_temp_new_i32();
9483
9484 tcg_gen_addi_i32(newsp, addr, offset);
9485 gen_helper_v8m_stackcheck(cpu_env, newsp);
9486 tcg_temp_free_i32(newsp);
9487 } else {
9488 gen_helper_v8m_stackcheck(cpu_env, addr);
9489 }
9490 }
9491
9ee6e8bb 9492 if (insn & (1 << 24)) {
b0109805 9493 tcg_gen_addi_i32(addr, addr, offset);
9ee6e8bb
PB
9494 offset = 0;
9495 }
9496 if (insn & (1 << 20)) {
9497 /* ldrd */
e2592fad 9498 tmp = tcg_temp_new_i32();
12dcc321 9499 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805
PB
9500 store_reg(s, rs, tmp);
9501 tcg_gen_addi_i32(addr, addr, 4);
e2592fad 9502 tmp = tcg_temp_new_i32();
12dcc321 9503 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 9504 store_reg(s, rd, tmp);
9ee6e8bb
PB
9505 } else {
9506 /* strd */
b0109805 9507 tmp = load_reg(s, rs);
12dcc321 9508 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
e2592fad 9509 tcg_temp_free_i32(tmp);
b0109805
PB
9510 tcg_gen_addi_i32(addr, addr, 4);
9511 tmp = load_reg(s, rd);
12dcc321 9512 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
e2592fad 9513 tcg_temp_free_i32(tmp);
9ee6e8bb 9514 }
910d7692 9515 if (wback) {
9ee6e8bb 9516 /* Base writeback. */
b0109805
PB
9517 tcg_gen_addi_i32(addr, addr, offset - 4);
9518 store_reg(s, rn, addr);
9519 } else {
7d1b0095 9520 tcg_temp_free_i32(addr);
9ee6e8bb
PB
9521 }
9522 } else if ((insn & (1 << 23)) == 0) {
ebfe27c5
PM
9523 /* 0b1110_1000_010x_xxxx_xxxx_xxxx_xxxx_xxxx
9524 * - load/store exclusive word
5158de24 9525 * - TT (v8M only)
ebfe27c5
PM
9526 */
9527 if (rs == 15) {
5158de24
PM
9528 if (!(insn & (1 << 20)) &&
9529 arm_dc_feature(s, ARM_FEATURE_M) &&
9530 arm_dc_feature(s, ARM_FEATURE_V8)) {
9531 /* 0b1110_1000_0100_xxxx_1111_xxxx_xxxx_xxxx
9532 * - TT (v8M only)
9533 */
9534 bool alt = insn & (1 << 7);
9535 TCGv_i32 addr, op, ttresp;
9536
9537 if ((insn & 0x3f) || rd == 13 || rd == 15 || rn == 15) {
9538 /* we UNDEF for these UNPREDICTABLE cases */
9539 goto illegal_op;
9540 }
9541
9542 if (alt && !s->v8m_secure) {
9543 goto illegal_op;
9544 }
9545
9546 addr = load_reg(s, rn);
9547 op = tcg_const_i32(extract32(insn, 6, 2));
9548 ttresp = tcg_temp_new_i32();
9549 gen_helper_v7m_tt(ttresp, cpu_env, addr, op);
9550 tcg_temp_free_i32(addr);
9551 tcg_temp_free_i32(op);
9552 store_reg(s, rd, ttresp);
384c6c03 9553 break;
5158de24 9554 }
ebfe27c5
PM
9555 goto illegal_op;
9556 }
39d5492a 9557 addr = tcg_temp_local_new_i32();
98a46317 9558 load_reg_var(s, addr, rn);
426f5abc 9559 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
2c0262af 9560 if (insn & (1 << 20)) {
426f5abc 9561 gen_load_exclusive(s, rs, 15, addr, 2);
9ee6e8bb 9562 } else {
426f5abc 9563 gen_store_exclusive(s, rd, rs, 15, addr, 2);
9ee6e8bb 9564 }
39d5492a 9565 tcg_temp_free_i32(addr);
2359bf80 9566 } else if ((insn & (7 << 5)) == 0) {
9ee6e8bb 9567 /* Table Branch. */
fdbcf632 9568 addr = load_reg(s, rn);
b26eefb6 9569 tmp = load_reg(s, rm);
b0109805 9570 tcg_gen_add_i32(addr, addr, tmp);
9ee6e8bb
PB
9571 if (insn & (1 << 4)) {
9572 /* tbh */
b0109805 9573 tcg_gen_add_i32(addr, addr, tmp);
7d1b0095 9574 tcg_temp_free_i32(tmp);
e2592fad 9575 tmp = tcg_temp_new_i32();
12dcc321 9576 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
9ee6e8bb 9577 } else { /* tbb */
7d1b0095 9578 tcg_temp_free_i32(tmp);
e2592fad 9579 tmp = tcg_temp_new_i32();
12dcc321 9580 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
9ee6e8bb 9581 }
7d1b0095 9582 tcg_temp_free_i32(addr);
b0109805 9583 tcg_gen_shli_i32(tmp, tmp, 1);
fdbcf632 9584 tcg_gen_addi_i32(tmp, tmp, read_pc(s));
b0109805 9585 store_reg(s, 15, tmp);
9ee6e8bb 9586 } else {
96c55295
PM
9587 bool is_lasr = false;
9588 bool is_ld = extract32(insn, 20, 1);
2359bf80 9589 int op2 = (insn >> 6) & 0x3;
9ee6e8bb 9590 op = (insn >> 4) & 0x3;
2359bf80
MR
9591 switch (op2) {
9592 case 0:
426f5abc 9593 goto illegal_op;
2359bf80
MR
9594 case 1:
9595 /* Load/store exclusive byte/halfword/doubleword */
9596 if (op == 2) {
9597 goto illegal_op;
9598 }
9599 ARCH(7);
9600 break;
9601 case 2:
9602 /* Load-acquire/store-release */
9603 if (op == 3) {
9604 goto illegal_op;
9605 }
9606 /* Fall through */
9607 case 3:
9608 /* Load-acquire/store-release exclusive */
9609 ARCH(8);
96c55295 9610 is_lasr = true;
2359bf80 9611 break;
426f5abc 9612 }
96c55295
PM
9613
9614 if (is_lasr && !is_ld) {
9615 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
9616 }
9617
39d5492a 9618 addr = tcg_temp_local_new_i32();
98a46317 9619 load_reg_var(s, addr, rn);
2359bf80 9620 if (!(op2 & 1)) {
96c55295 9621 if (is_ld) {
2359bf80
MR
9622 tmp = tcg_temp_new_i32();
9623 switch (op) {
9624 case 0: /* ldab */
9bb6558a
PM
9625 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s),
9626 rs | ISSIsAcqRel);
2359bf80
MR
9627 break;
9628 case 1: /* ldah */
9bb6558a
PM
9629 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s),
9630 rs | ISSIsAcqRel);
2359bf80
MR
9631 break;
9632 case 2: /* lda */
9bb6558a
PM
9633 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s),
9634 rs | ISSIsAcqRel);
2359bf80
MR
9635 break;
9636 default:
9637 abort();
9638 }
9639 store_reg(s, rs, tmp);
9640 } else {
9641 tmp = load_reg(s, rs);
9642 switch (op) {
9643 case 0: /* stlb */
9bb6558a
PM
9644 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s),
9645 rs | ISSIsAcqRel);
2359bf80
MR
9646 break;
9647 case 1: /* stlh */
9bb6558a
PM
9648 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s),
9649 rs | ISSIsAcqRel);
2359bf80
MR
9650 break;
9651 case 2: /* stl */
9bb6558a
PM
9652 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s),
9653 rs | ISSIsAcqRel);
2359bf80
MR
9654 break;
9655 default:
9656 abort();
9657 }
9658 tcg_temp_free_i32(tmp);
9659 }
96c55295 9660 } else if (is_ld) {
426f5abc 9661 gen_load_exclusive(s, rs, rd, addr, op);
9ee6e8bb 9662 } else {
426f5abc 9663 gen_store_exclusive(s, rm, rs, rd, addr, op);
9ee6e8bb 9664 }
39d5492a 9665 tcg_temp_free_i32(addr);
96c55295
PM
9666
9667 if (is_lasr && is_ld) {
9668 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
9669 }
9ee6e8bb
PB
9670 }
9671 } else {
9672 /* Load/store multiple, RFE, SRS. */
9673 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
00115976 9674 /* RFE, SRS: not available in user mode or on M profile */
b53d8923 9675 if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
9ee6e8bb 9676 goto illegal_op;
00115976 9677 }
9ee6e8bb
PB
9678 if (insn & (1 << 20)) {
9679 /* rfe */
b0109805
PB
9680 addr = load_reg(s, rn);
9681 if ((insn & (1 << 24)) == 0)
9682 tcg_gen_addi_i32(addr, addr, -8);
9683 /* Load PC into tmp and CPSR into tmp2. */
e2592fad 9684 tmp = tcg_temp_new_i32();
12dcc321 9685 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 9686 tcg_gen_addi_i32(addr, addr, 4);
e2592fad 9687 tmp2 = tcg_temp_new_i32();
12dcc321 9688 gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
9ee6e8bb
PB
9689 if (insn & (1 << 21)) {
9690 /* Base writeback. */
b0109805
PB
9691 if (insn & (1 << 24)) {
9692 tcg_gen_addi_i32(addr, addr, 4);
9693 } else {
9694 tcg_gen_addi_i32(addr, addr, -4);
9695 }
9696 store_reg(s, rn, addr);
9697 } else {
7d1b0095 9698 tcg_temp_free_i32(addr);
9ee6e8bb 9699 }
b0109805 9700 gen_rfe(s, tmp, tmp2);
9ee6e8bb
PB
9701 } else {
9702 /* srs */
81465888
PM
9703 gen_srs(s, (insn & 0x1f), (insn & (1 << 24)) ? 1 : 2,
9704 insn & (1 << 21));
9ee6e8bb
PB
9705 }
9706 } else {
5856d44e 9707 int i, loaded_base = 0;
39d5492a 9708 TCGv_i32 loaded_var;
7c0ed88e 9709 bool wback = extract32(insn, 21, 1);
9ee6e8bb 9710 /* Load/store multiple. */
b0109805 9711 addr = load_reg(s, rn);
9ee6e8bb
PB
9712 offset = 0;
9713 for (i = 0; i < 16; i++) {
9714 if (insn & (1 << i))
9715 offset += 4;
9716 }
7c0ed88e 9717
9ee6e8bb 9718 if (insn & (1 << 24)) {
b0109805 9719 tcg_gen_addi_i32(addr, addr, -offset);
9ee6e8bb
PB
9720 }
9721
7c0ed88e
PM
9722 if (s->v8m_stackcheck && rn == 13 && wback) {
9723 /*
9724 * If the writeback is incrementing SP rather than
9725 * decrementing it, and the initial SP is below the
9726 * stack limit but the final written-back SP would
9727 * be above, then then we must not perform any memory
9728 * accesses, but it is IMPDEF whether we generate
9729 * an exception. We choose to do so in this case.
9730 * At this point 'addr' is the lowest address, so
9731 * either the original SP (if incrementing) or our
9732 * final SP (if decrementing), so that's what we check.
9733 */
9734 gen_helper_v8m_stackcheck(cpu_env, addr);
9735 }
9736
f764718d 9737 loaded_var = NULL;
9ee6e8bb
PB
9738 for (i = 0; i < 16; i++) {
9739 if ((insn & (1 << i)) == 0)
9740 continue;
9741 if (insn & (1 << 20)) {
9742 /* Load. */
e2592fad 9743 tmp = tcg_temp_new_i32();
12dcc321 9744 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9ee6e8bb 9745 if (i == 15) {
3bb8a96f 9746 gen_bx_excret(s, tmp);
5856d44e
YO
9747 } else if (i == rn) {
9748 loaded_var = tmp;
9749 loaded_base = 1;
9ee6e8bb 9750 } else {
b0109805 9751 store_reg(s, i, tmp);
9ee6e8bb
PB
9752 }
9753 } else {
9754 /* Store. */
b0109805 9755 tmp = load_reg(s, i);
12dcc321 9756 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
e2592fad 9757 tcg_temp_free_i32(tmp);
9ee6e8bb 9758 }
b0109805 9759 tcg_gen_addi_i32(addr, addr, 4);
9ee6e8bb 9760 }
5856d44e
YO
9761 if (loaded_base) {
9762 store_reg(s, rn, loaded_var);
9763 }
7c0ed88e 9764 if (wback) {
9ee6e8bb
PB
9765 /* Base register writeback. */
9766 if (insn & (1 << 24)) {
b0109805 9767 tcg_gen_addi_i32(addr, addr, -offset);
9ee6e8bb
PB
9768 }
9769 /* Fault if writeback register is in register list. */
9770 if (insn & (1 << rn))
9771 goto illegal_op;
b0109805
PB
9772 store_reg(s, rn, addr);
9773 } else {
7d1b0095 9774 tcg_temp_free_i32(addr);
9ee6e8bb
PB
9775 }
9776 }
9777 }
9778 break;
2af9ab77
JB
9779 case 5:
9780
9ee6e8bb 9781 op = (insn >> 21) & 0xf;
2af9ab77 9782 if (op == 6) {
62b44f05
AR
9783 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9784 goto illegal_op;
9785 }
2af9ab77
JB
9786 /* Halfword pack. */
9787 tmp = load_reg(s, rn);
9788 tmp2 = load_reg(s, rm);
9789 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
9790 if (insn & (1 << 5)) {
9791 /* pkhtb */
d1f8755f 9792 if (shift == 0) {
2af9ab77 9793 shift = 31;
d1f8755f 9794 }
2af9ab77 9795 tcg_gen_sari_i32(tmp2, tmp2, shift);
d1f8755f 9796 tcg_gen_deposit_i32(tmp, tmp, tmp2, 0, 16);
2af9ab77
JB
9797 } else {
9798 /* pkhbt */
d1f8755f
RH
9799 tcg_gen_shli_i32(tmp2, tmp2, shift);
9800 tcg_gen_deposit_i32(tmp, tmp2, tmp, 0, 16);
2af9ab77 9801 }
7d1b0095 9802 tcg_temp_free_i32(tmp2);
3174f8e9
FN
9803 store_reg(s, rd, tmp);
9804 } else {
2af9ab77
JB
9805 /* Data processing register constant shift. */
9806 if (rn == 15) {
7d1b0095 9807 tmp = tcg_temp_new_i32();
2af9ab77
JB
9808 tcg_gen_movi_i32(tmp, 0);
9809 } else {
9810 tmp = load_reg(s, rn);
9811 }
9812 tmp2 = load_reg(s, rm);
9813
9814 shiftop = (insn >> 4) & 3;
9815 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
9816 conds = (insn & (1 << 20)) != 0;
9817 logic_cc = (conds && thumb2_logic_op(op));
9818 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
9819 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
9820 goto illegal_op;
7d1b0095 9821 tcg_temp_free_i32(tmp2);
55203189
PM
9822 if (rd == 13 &&
9823 ((op == 2 && rn == 15) ||
9824 (op == 8 && rn == 13) ||
9825 (op == 13 && rn == 13))) {
9826 /* MOV SP, ... or ADD SP, SP, ... or SUB SP, SP, ... */
9827 store_sp_checked(s, tmp);
9828 } else if (rd != 15) {
2af9ab77
JB
9829 store_reg(s, rd, tmp);
9830 } else {
7d1b0095 9831 tcg_temp_free_i32(tmp);
2af9ab77 9832 }
3174f8e9 9833 }
9ee6e8bb
PB
9834 break;
9835 case 13: /* Misc data processing. */
9836 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
9837 if (op < 4 && (insn & 0xf000) != 0xf000)
9838 goto illegal_op;
9839 switch (op) {
9840 case 0: /* Register controlled shift. */
8984bd2e
PB
9841 tmp = load_reg(s, rn);
9842 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
9843 if ((insn & 0x70) != 0)
9844 goto illegal_op;
a2d12f0f
PM
9845 /*
9846 * 0b1111_1010_0xxx_xxxx_1111_xxxx_0000_xxxx:
9847 * - MOV, MOVS (register-shifted register), flagsetting
9848 */
9ee6e8bb 9849 op = (insn >> 21) & 3;
8984bd2e
PB
9850 logic_cc = (insn & (1 << 20)) != 0;
9851 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
9852 if (logic_cc)
9853 gen_logic_CC(tmp);
bedb8a6b 9854 store_reg(s, rd, tmp);
9ee6e8bb
PB
9855 break;
9856 case 1: /* Sign/zero extend. */
62b44f05
AR
9857 op = (insn >> 20) & 7;
9858 switch (op) {
9859 case 0: /* SXTAH, SXTH */
9860 case 1: /* UXTAH, UXTH */
9861 case 4: /* SXTAB, SXTB */
9862 case 5: /* UXTAB, UXTB */
9863 break;
9864 case 2: /* SXTAB16, SXTB16 */
9865 case 3: /* UXTAB16, UXTB16 */
9866 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9867 goto illegal_op;
9868 }
9869 break;
9870 default:
9871 goto illegal_op;
9872 }
9873 if (rn != 15) {
9874 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9875 goto illegal_op;
9876 }
9877 }
5e3f878a 9878 tmp = load_reg(s, rm);
9ee6e8bb 9879 shift = (insn >> 4) & 3;
1301f322 9880 /* ??? In many cases it's not necessary to do a
9ee6e8bb 9881 rotate, a shift is sufficient. */
464eaa95 9882 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
9ee6e8bb
PB
9883 op = (insn >> 20) & 7;
9884 switch (op) {
5e3f878a
PB
9885 case 0: gen_sxth(tmp); break;
9886 case 1: gen_uxth(tmp); break;
9887 case 2: gen_sxtb16(tmp); break;
9888 case 3: gen_uxtb16(tmp); break;
9889 case 4: gen_sxtb(tmp); break;
9890 case 5: gen_uxtb(tmp); break;
62b44f05
AR
9891 default:
9892 g_assert_not_reached();
9ee6e8bb
PB
9893 }
9894 if (rn != 15) {
5e3f878a 9895 tmp2 = load_reg(s, rn);
9ee6e8bb 9896 if ((op >> 1) == 1) {
5e3f878a 9897 gen_add16(tmp, tmp2);
9ee6e8bb 9898 } else {
5e3f878a 9899 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 9900 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
9901 }
9902 }
5e3f878a 9903 store_reg(s, rd, tmp);
9ee6e8bb
PB
9904 break;
9905 case 2: /* SIMD add/subtract. */
62b44f05
AR
9906 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9907 goto illegal_op;
9908 }
9ee6e8bb
PB
9909 op = (insn >> 20) & 7;
9910 shift = (insn >> 4) & 7;
9911 if ((op & 3) == 3 || (shift & 3) == 3)
9912 goto illegal_op;
6ddbc6e4
PB
9913 tmp = load_reg(s, rn);
9914 tmp2 = load_reg(s, rm);
9915 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7d1b0095 9916 tcg_temp_free_i32(tmp2);
6ddbc6e4 9917 store_reg(s, rd, tmp);
9ee6e8bb
PB
9918 break;
9919 case 3: /* Other data processing. */
9920 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
9921 if (op < 4) {
9922 /* Saturating add/subtract. */
62b44f05
AR
9923 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9924 goto illegal_op;
9925 }
d9ba4830
PB
9926 tmp = load_reg(s, rn);
9927 tmp2 = load_reg(s, rm);
9ee6e8bb 9928 if (op & 1)
640581a0 9929 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp);
4809c612 9930 if (op & 2)
9ef39277 9931 gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);
9ee6e8bb 9932 else
9ef39277 9933 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
7d1b0095 9934 tcg_temp_free_i32(tmp2);
9ee6e8bb 9935 } else {
62b44f05
AR
9936 switch (op) {
9937 case 0x0a: /* rbit */
9938 case 0x08: /* rev */
9939 case 0x09: /* rev16 */
9940 case 0x0b: /* revsh */
9941 case 0x18: /* clz */
9942 break;
9943 case 0x10: /* sel */
9944 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9945 goto illegal_op;
9946 }
9947 break;
9948 case 0x20: /* crc32/crc32c */
9949 case 0x21:
9950 case 0x22:
9951 case 0x28:
9952 case 0x29:
9953 case 0x2a:
962fcbf2 9954 if (!dc_isar_feature(aa32_crc32, s)) {
62b44f05
AR
9955 goto illegal_op;
9956 }
9957 break;
9958 default:
9959 goto illegal_op;
9960 }
d9ba4830 9961 tmp = load_reg(s, rn);
9ee6e8bb
PB
9962 switch (op) {
9963 case 0x0a: /* rbit */
d9ba4830 9964 gen_helper_rbit(tmp, tmp);
9ee6e8bb
PB
9965 break;
9966 case 0x08: /* rev */
66896cb8 9967 tcg_gen_bswap32_i32(tmp, tmp);
9ee6e8bb
PB
9968 break;
9969 case 0x09: /* rev16 */
d9ba4830 9970 gen_rev16(tmp);
9ee6e8bb
PB
9971 break;
9972 case 0x0b: /* revsh */
d9ba4830 9973 gen_revsh(tmp);
9ee6e8bb
PB
9974 break;
9975 case 0x10: /* sel */
d9ba4830 9976 tmp2 = load_reg(s, rm);
7d1b0095 9977 tmp3 = tcg_temp_new_i32();
0ecb72a5 9978 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
d9ba4830 9979 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7d1b0095
PM
9980 tcg_temp_free_i32(tmp3);
9981 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
9982 break;
9983 case 0x18: /* clz */
7539a012 9984 tcg_gen_clzi_i32(tmp, tmp, 32);
9ee6e8bb 9985 break;
eb0ecd5a
WN
9986 case 0x20:
9987 case 0x21:
9988 case 0x22:
9989 case 0x28:
9990 case 0x29:
9991 case 0x2a:
9992 {
9993 /* crc32/crc32c */
9994 uint32_t sz = op & 0x3;
9995 uint32_t c = op & 0x8;
9996
eb0ecd5a 9997 tmp2 = load_reg(s, rm);
aa633469
PM
9998 if (sz == 0) {
9999 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
10000 } else if (sz == 1) {
10001 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
10002 }
eb0ecd5a
WN
10003 tmp3 = tcg_const_i32(1 << sz);
10004 if (c) {
10005 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
10006 } else {
10007 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
10008 }
10009 tcg_temp_free_i32(tmp2);
10010 tcg_temp_free_i32(tmp3);
10011 break;
10012 }
9ee6e8bb 10013 default:
62b44f05 10014 g_assert_not_reached();
9ee6e8bb
PB
10015 }
10016 }
d9ba4830 10017 store_reg(s, rd, tmp);
9ee6e8bb
PB
10018 break;
10019 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
62b44f05
AR
10020 switch ((insn >> 20) & 7) {
10021 case 0: /* 32 x 32 -> 32 */
10022 case 7: /* Unsigned sum of absolute differences. */
10023 break;
10024 case 1: /* 16 x 16 -> 32 */
10025 case 2: /* Dual multiply add. */
10026 case 3: /* 32 * 16 -> 32msb */
10027 case 4: /* Dual multiply subtract. */
10028 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
10029 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10030 goto illegal_op;
10031 }
10032 break;
10033 }
9ee6e8bb 10034 op = (insn >> 4) & 0xf;
d9ba4830
PB
10035 tmp = load_reg(s, rn);
10036 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
10037 switch ((insn >> 20) & 7) {
10038 case 0: /* 32 x 32 -> 32 */
d9ba4830 10039 tcg_gen_mul_i32(tmp, tmp, tmp2);
7d1b0095 10040 tcg_temp_free_i32(tmp2);
9ee6e8bb 10041 if (rs != 15) {
d9ba4830 10042 tmp2 = load_reg(s, rs);
9ee6e8bb 10043 if (op)
d9ba4830 10044 tcg_gen_sub_i32(tmp, tmp2, tmp);
9ee6e8bb 10045 else
d9ba4830 10046 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 10047 tcg_temp_free_i32(tmp2);
9ee6e8bb 10048 }
9ee6e8bb
PB
10049 break;
10050 case 1: /* 16 x 16 -> 32 */
d9ba4830 10051 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7d1b0095 10052 tcg_temp_free_i32(tmp2);
9ee6e8bb 10053 if (rs != 15) {
d9ba4830 10054 tmp2 = load_reg(s, rs);
9ef39277 10055 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 10056 tcg_temp_free_i32(tmp2);
9ee6e8bb 10057 }
9ee6e8bb
PB
10058 break;
10059 case 2: /* Dual multiply add. */
10060 case 4: /* Dual multiply subtract. */
10061 if (op)
d9ba4830
PB
10062 gen_swap_half(tmp2);
10063 gen_smul_dual(tmp, tmp2);
9ee6e8bb 10064 if (insn & (1 << 22)) {
e1d177b9 10065 /* This subtraction cannot overflow. */
d9ba4830 10066 tcg_gen_sub_i32(tmp, tmp, tmp2);
9ee6e8bb 10067 } else {
e1d177b9
PM
10068 /* This addition cannot overflow 32 bits;
10069 * however it may overflow considered as a signed
10070 * operation, in which case we must set the Q flag.
10071 */
9ef39277 10072 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 10073 }
7d1b0095 10074 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
10075 if (rs != 15)
10076 {
d9ba4830 10077 tmp2 = load_reg(s, rs);
9ef39277 10078 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 10079 tcg_temp_free_i32(tmp2);
9ee6e8bb 10080 }
9ee6e8bb
PB
10081 break;
10082 case 3: /* 32 * 16 -> 32msb */
10083 if (op)
d9ba4830 10084 tcg_gen_sari_i32(tmp2, tmp2, 16);
9ee6e8bb 10085 else
d9ba4830 10086 gen_sxth(tmp2);
a7812ae4
PB
10087 tmp64 = gen_muls_i64_i32(tmp, tmp2);
10088 tcg_gen_shri_i64(tmp64, tmp64, 16);
7d1b0095 10089 tmp = tcg_temp_new_i32();
ecc7b3aa 10090 tcg_gen_extrl_i64_i32(tmp, tmp64);
b75263d6 10091 tcg_temp_free_i64(tmp64);
9ee6e8bb
PB
10092 if (rs != 15)
10093 {
d9ba4830 10094 tmp2 = load_reg(s, rs);
9ef39277 10095 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7d1b0095 10096 tcg_temp_free_i32(tmp2);
9ee6e8bb 10097 }
9ee6e8bb 10098 break;
838fa72d 10099 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
5f8cd06e 10100 tcg_gen_muls2_i32(tmp2, tmp, tmp, tmp2);
9ee6e8bb 10101 if (rs != 15) {
5f8cd06e 10102 tmp3 = load_reg(s, rs);
838fa72d 10103 if (insn & (1 << 20)) {
5f8cd06e 10104 tcg_gen_add_i32(tmp, tmp, tmp3);
99c475ab 10105 } else {
e0a0c832
RH
10106 /*
10107 * For SMMLS, we need a 64-bit subtract.
10108 * Borrow caused by a non-zero multiplicand lowpart,
10109 * and the correct result lowpart for rounding.
10110 */
10111 TCGv_i32 zero = tcg_const_i32(0);
10112 tcg_gen_sub2_i32(tmp2, tmp, zero, tmp3, tmp2, tmp);
10113 tcg_temp_free_i32(zero);
99c475ab 10114 }
5f8cd06e 10115 tcg_temp_free_i32(tmp3);
2c0262af 10116 }
838fa72d 10117 if (insn & (1 << 4)) {
5f8cd06e
RH
10118 /*
10119 * Adding 0x80000000 to the 64-bit quantity
10120 * means that we have carry in to the high
10121 * word when the low word has the high bit set.
10122 */
10123 tcg_gen_shri_i32(tmp2, tmp2, 31);
10124 tcg_gen_add_i32(tmp, tmp, tmp2);
838fa72d 10125 }
5f8cd06e 10126 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
10127 break;
10128 case 7: /* Unsigned sum of absolute differences. */
d9ba4830 10129 gen_helper_usad8(tmp, tmp, tmp2);
7d1b0095 10130 tcg_temp_free_i32(tmp2);
9ee6e8bb 10131 if (rs != 15) {
d9ba4830
PB
10132 tmp2 = load_reg(s, rs);
10133 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 10134 tcg_temp_free_i32(tmp2);
5fd46862 10135 }
9ee6e8bb 10136 break;
2c0262af 10137 }
d9ba4830 10138 store_reg(s, rd, tmp);
2c0262af 10139 break;
9ee6e8bb
PB
10140 case 6: case 7: /* 64-bit multiply, Divide. */
10141 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
5e3f878a
PB
10142 tmp = load_reg(s, rn);
10143 tmp2 = load_reg(s, rm);
9ee6e8bb
PB
10144 if ((op & 0x50) == 0x10) {
10145 /* sdiv, udiv */
7e0cf8b4 10146 if (!dc_isar_feature(thumb_div, s)) {
9ee6e8bb 10147 goto illegal_op;
47789990 10148 }
9ee6e8bb 10149 if (op & 0x20)
5e3f878a 10150 gen_helper_udiv(tmp, tmp, tmp2);
2c0262af 10151 else
5e3f878a 10152 gen_helper_sdiv(tmp, tmp, tmp2);
7d1b0095 10153 tcg_temp_free_i32(tmp2);
5e3f878a 10154 store_reg(s, rd, tmp);
9ee6e8bb
PB
10155 } else if ((op & 0xe) == 0xc) {
10156 /* Dual multiply accumulate long. */
62b44f05
AR
10157 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10158 tcg_temp_free_i32(tmp);
10159 tcg_temp_free_i32(tmp2);
10160 goto illegal_op;
10161 }
9ee6e8bb 10162 if (op & 1)
5e3f878a
PB
10163 gen_swap_half(tmp2);
10164 gen_smul_dual(tmp, tmp2);
9ee6e8bb 10165 if (op & 0x10) {
5e3f878a 10166 tcg_gen_sub_i32(tmp, tmp, tmp2);
b5ff1b31 10167 } else {
5e3f878a 10168 tcg_gen_add_i32(tmp, tmp, tmp2);
b5ff1b31 10169 }
7d1b0095 10170 tcg_temp_free_i32(tmp2);
a7812ae4
PB
10171 /* BUGFIX */
10172 tmp64 = tcg_temp_new_i64();
10173 tcg_gen_ext_i32_i64(tmp64, tmp);
7d1b0095 10174 tcg_temp_free_i32(tmp);
a7812ae4
PB
10175 gen_addq(s, tmp64, rs, rd);
10176 gen_storeq_reg(s, rs, rd, tmp64);
b75263d6 10177 tcg_temp_free_i64(tmp64);
2c0262af 10178 } else {
9ee6e8bb
PB
10179 if (op & 0x20) {
10180 /* Unsigned 64-bit multiply */
a7812ae4 10181 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
b5ff1b31 10182 } else {
9ee6e8bb
PB
10183 if (op & 8) {
10184 /* smlalxy */
62b44f05
AR
10185 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10186 tcg_temp_free_i32(tmp2);
10187 tcg_temp_free_i32(tmp);
10188 goto illegal_op;
10189 }
5e3f878a 10190 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7d1b0095 10191 tcg_temp_free_i32(tmp2);
a7812ae4
PB
10192 tmp64 = tcg_temp_new_i64();
10193 tcg_gen_ext_i32_i64(tmp64, tmp);
7d1b0095 10194 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
10195 } else {
10196 /* Signed 64-bit multiply */
a7812ae4 10197 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9ee6e8bb 10198 }
b5ff1b31 10199 }
9ee6e8bb
PB
10200 if (op & 4) {
10201 /* umaal */
62b44f05
AR
10202 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10203 tcg_temp_free_i64(tmp64);
10204 goto illegal_op;
10205 }
a7812ae4
PB
10206 gen_addq_lo(s, tmp64, rs);
10207 gen_addq_lo(s, tmp64, rd);
9ee6e8bb
PB
10208 } else if (op & 0x40) {
10209 /* 64-bit accumulate. */
a7812ae4 10210 gen_addq(s, tmp64, rs, rd);
9ee6e8bb 10211 }
a7812ae4 10212 gen_storeq_reg(s, rs, rd, tmp64);
b75263d6 10213 tcg_temp_free_i64(tmp64);
5fd46862 10214 }
2c0262af 10215 break;
9ee6e8bb
PB
10216 }
10217 break;
10218 case 6: case 7: case 14: case 15:
10219 /* Coprocessor. */
7517748e 10220 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8859ba3c
PM
10221 /* 0b111x_11xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx */
10222 if (extract32(insn, 24, 2) == 3) {
10223 goto illegal_op; /* op0 = 0b11 : unallocated */
10224 }
10225
10226 /*
10227 * Decode VLLDM and VLSTM first: these are nonstandard because:
10228 * * if there is no FPU then these insns must NOP in
10229 * Secure state and UNDEF in Nonsecure state
10230 * * if there is an FPU then these insns do not have
10231 * the usual behaviour that disas_vfp_insn() provides of
10232 * being controlled by CPACR/NSACR enable bits or the
10233 * lazy-stacking logic.
7517748e 10234 */
b1e5336a
PM
10235 if (arm_dc_feature(s, ARM_FEATURE_V8) &&
10236 (insn & 0xffa00f00) == 0xec200a00) {
10237 /* 0b1110_1100_0x1x_xxxx_xxxx_1010_xxxx_xxxx
10238 * - VLLDM, VLSTM
10239 * We choose to UNDEF if the RAZ bits are non-zero.
10240 */
10241 if (!s->v8m_secure || (insn & 0x0040f0ff)) {
10242 goto illegal_op;
10243 }
019076b0
PM
10244
10245 if (arm_dc_feature(s, ARM_FEATURE_VFP)) {
10246 TCGv_i32 fptr = load_reg(s, rn);
10247
10248 if (extract32(insn, 20, 1)) {
956fe143 10249 gen_helper_v7m_vlldm(cpu_env, fptr);
019076b0
PM
10250 } else {
10251 gen_helper_v7m_vlstm(cpu_env, fptr);
10252 }
10253 tcg_temp_free_i32(fptr);
10254
10255 /* End the TB, because we have updated FP control bits */
10256 s->base.is_jmp = DISAS_UPDATE;
10257 }
b1e5336a
PM
10258 break;
10259 }
8859ba3c
PM
10260 if (arm_dc_feature(s, ARM_FEATURE_VFP) &&
10261 ((insn >> 8) & 0xe) == 10) {
10262 /* FP, and the CPU supports it */
10263 if (disas_vfp_insn(s, insn)) {
10264 goto illegal_op;
10265 }
10266 break;
10267 }
10268
b1e5336a 10269 /* All other insns: NOCP */
a767fac8 10270 gen_exception_insn(s, s->pc_curr, EXCP_NOCP, syn_uncategorized(),
7517748e
PM
10271 default_exception_el(s));
10272 break;
10273 }
0052087e
RH
10274 if ((insn & 0xfe000a00) == 0xfc000800
10275 && arm_dc_feature(s, ARM_FEATURE_V8)) {
10276 /* The Thumb2 and ARM encodings are identical. */
10277 if (disas_neon_insn_3same_ext(s, insn)) {
10278 goto illegal_op;
10279 }
10280 } else if ((insn & 0xff000a00) == 0xfe000800
10281 && arm_dc_feature(s, ARM_FEATURE_V8)) {
10282 /* The Thumb2 and ARM encodings are identical. */
10283 if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
10284 goto illegal_op;
10285 }
10286 } else if (((insn >> 24) & 3) == 3) {
9ee6e8bb 10287 /* Translate into the equivalent ARM encoding. */
f06053e3 10288 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
7dcc1f89 10289 if (disas_neon_data_insn(s, insn)) {
9ee6e8bb 10290 goto illegal_op;
7dcc1f89 10291 }
6a57f3eb 10292 } else if (((insn >> 8) & 0xe) == 10) {
7dcc1f89 10293 if (disas_vfp_insn(s, insn)) {
6a57f3eb
WN
10294 goto illegal_op;
10295 }
9ee6e8bb
PB
10296 } else {
10297 if (insn & (1 << 28))
10298 goto illegal_op;
7dcc1f89 10299 if (disas_coproc_insn(s, insn)) {
9ee6e8bb 10300 goto illegal_op;
7dcc1f89 10301 }
9ee6e8bb
PB
10302 }
10303 break;
10304 case 8: case 9: case 10: case 11:
10305 if (insn & (1 << 15)) {
10306 /* Branches, misc control. */
10307 if (insn & 0x5000) {
10308 /* Unconditional branch. */
10309 /* signextend(hw1[10:0]) -> offset[:12]. */
10310 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
10311 /* hw1[10:0] -> offset[11:1]. */
10312 offset |= (insn & 0x7ff) << 1;
10313 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
10314 offset[24:22] already have the same value because of the
10315 sign extension above. */
10316 offset ^= ((~insn) & (1 << 13)) << 10;
10317 offset ^= ((~insn) & (1 << 11)) << 11;
10318
9ee6e8bb
PB
10319 if (insn & (1 << 14)) {
10320 /* Branch and link. */
a0415916 10321 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | 1);
b5ff1b31 10322 }
3b46e624 10323
fdbcf632 10324 offset += read_pc(s);
9ee6e8bb
PB
10325 if (insn & (1 << 12)) {
10326 /* b/bl */
b0109805 10327 gen_jmp(s, offset);
9ee6e8bb
PB
10328 } else {
10329 /* blx */
b0109805 10330 offset &= ~(uint32_t)2;
be5e7a76 10331 /* thumb2 bx, no need to check */
b0109805 10332 gen_bx_im(s, offset);
2c0262af 10333 }
9ee6e8bb
PB
10334 } else if (((insn >> 23) & 7) == 7) {
10335 /* Misc control */
10336 if (insn & (1 << 13))
10337 goto illegal_op;
10338
10339 if (insn & (1 << 26)) {
001b3cab
PM
10340 if (arm_dc_feature(s, ARM_FEATURE_M)) {
10341 goto illegal_op;
10342 }
37e6456e
PM
10343 if (!(insn & (1 << 20))) {
10344 /* Hypervisor call (v7) */
10345 int imm16 = extract32(insn, 16, 4) << 12
10346 | extract32(insn, 0, 12);
10347 ARCH(7);
10348 if (IS_USER(s)) {
10349 goto illegal_op;
10350 }
10351 gen_hvc(s, imm16);
10352 } else {
10353 /* Secure monitor call (v6+) */
10354 ARCH(6K);
10355 if (IS_USER(s)) {
10356 goto illegal_op;
10357 }
10358 gen_smc(s);
10359 }
2c0262af 10360 } else {
9ee6e8bb
PB
10361 op = (insn >> 20) & 7;
10362 switch (op) {
10363 case 0: /* msr cpsr. */
b53d8923 10364 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8984bd2e 10365 tmp = load_reg(s, rn);
b28b3377
PM
10366 /* the constant is the mask and SYSm fields */
10367 addr = tcg_const_i32(insn & 0xfff);
8984bd2e 10368 gen_helper_v7m_msr(cpu_env, addr, tmp);
b75263d6 10369 tcg_temp_free_i32(addr);
7d1b0095 10370 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
10371 gen_lookup_tb(s);
10372 break;
10373 }
10374 /* fall through */
10375 case 1: /* msr spsr. */
b53d8923 10376 if (arm_dc_feature(s, ARM_FEATURE_M)) {
9ee6e8bb 10377 goto illegal_op;
b53d8923 10378 }
8bfd0550
PM
10379
10380 if (extract32(insn, 5, 1)) {
10381 /* MSR (banked) */
10382 int sysm = extract32(insn, 8, 4) |
10383 (extract32(insn, 4, 1) << 4);
10384 int r = op & 1;
10385
10386 gen_msr_banked(s, r, sysm, rm);
10387 break;
10388 }
10389
10390 /* MSR (for PSRs) */
2fbac54b
FN
10391 tmp = load_reg(s, rn);
10392 if (gen_set_psr(s,
7dcc1f89 10393 msr_mask(s, (insn >> 8) & 0xf, op == 1),
2fbac54b 10394 op == 1, tmp))
9ee6e8bb
PB
10395 goto illegal_op;
10396 break;
10397 case 2: /* cps, nop-hint. */
10398 if (((insn >> 8) & 7) == 0) {
10399 gen_nop_hint(s, insn & 0xff);
10400 }
10401 /* Implemented as NOP in user mode. */
10402 if (IS_USER(s))
10403 break;
10404 offset = 0;
10405 imm = 0;
10406 if (insn & (1 << 10)) {
10407 if (insn & (1 << 7))
10408 offset |= CPSR_A;
10409 if (insn & (1 << 6))
10410 offset |= CPSR_I;
10411 if (insn & (1 << 5))
10412 offset |= CPSR_F;
10413 if (insn & (1 << 9))
10414 imm = CPSR_A | CPSR_I | CPSR_F;
10415 }
10416 if (insn & (1 << 8)) {
10417 offset |= 0x1f;
10418 imm |= (insn & 0x1f);
10419 }
10420 if (offset) {
2fbac54b 10421 gen_set_psr_im(s, offset, 0, imm);
9ee6e8bb
PB
10422 }
10423 break;
10424 case 3: /* Special control operations. */
14120108 10425 if (!arm_dc_feature(s, ARM_FEATURE_V7) &&
8297cb13 10426 !arm_dc_feature(s, ARM_FEATURE_M)) {
14120108
JS
10427 goto illegal_op;
10428 }
9ee6e8bb
PB
10429 op = (insn >> 4) & 0xf;
10430 switch (op) {
10431 case 2: /* clrex */
426f5abc 10432 gen_clrex(s);
9ee6e8bb
PB
10433 break;
10434 case 4: /* dsb */
10435 case 5: /* dmb */
61e4c432 10436 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
9ee6e8bb 10437 break;
6df99dec
SS
10438 case 6: /* isb */
10439 /* We need to break the TB after this insn
10440 * to execute self-modifying code correctly
10441 * and also to take any pending interrupts
10442 * immediately.
10443 */
a0415916 10444 gen_goto_tb(s, 0, s->base.pc_next);
6df99dec 10445 break;
9888bd1e
RH
10446 case 7: /* sb */
10447 if ((insn & 0xf) || !dc_isar_feature(aa32_sb, s)) {
10448 goto illegal_op;
10449 }
10450 /*
10451 * TODO: There is no speculation barrier opcode
10452 * for TCG; MB and end the TB instead.
10453 */
10454 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
a0415916 10455 gen_goto_tb(s, 0, s->base.pc_next);
9888bd1e 10456 break;
9ee6e8bb
PB
10457 default:
10458 goto illegal_op;
10459 }
10460 break;
10461 case 4: /* bxj */
9d7c59c8
PM
10462 /* Trivial implementation equivalent to bx.
10463 * This instruction doesn't exist at all for M-profile.
10464 */
10465 if (arm_dc_feature(s, ARM_FEATURE_M)) {
10466 goto illegal_op;
10467 }
d9ba4830
PB
10468 tmp = load_reg(s, rn);
10469 gen_bx(s, tmp);
9ee6e8bb
PB
10470 break;
10471 case 5: /* Exception return. */
b8b45b68
RV
10472 if (IS_USER(s)) {
10473 goto illegal_op;
10474 }
10475 if (rn != 14 || rd != 15) {
10476 goto illegal_op;
10477 }
55c544ed
PM
10478 if (s->current_el == 2) {
10479 /* ERET from Hyp uses ELR_Hyp, not LR */
10480 if (insn & 0xff) {
10481 goto illegal_op;
10482 }
10483 tmp = load_cpu_field(elr_el[2]);
10484 } else {
10485 tmp = load_reg(s, rn);
10486 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
10487 }
b8b45b68
RV
10488 gen_exception_return(s, tmp);
10489 break;
8bfd0550 10490 case 6: /* MRS */
43ac6574
PM
10491 if (extract32(insn, 5, 1) &&
10492 !arm_dc_feature(s, ARM_FEATURE_M)) {
8bfd0550
PM
10493 /* MRS (banked) */
10494 int sysm = extract32(insn, 16, 4) |
10495 (extract32(insn, 4, 1) << 4);
10496
10497 gen_mrs_banked(s, 0, sysm, rd);
10498 break;
10499 }
10500
3d54026f
PM
10501 if (extract32(insn, 16, 4) != 0xf) {
10502 goto illegal_op;
10503 }
10504 if (!arm_dc_feature(s, ARM_FEATURE_M) &&
10505 extract32(insn, 0, 8) != 0) {
10506 goto illegal_op;
10507 }
10508
8bfd0550 10509 /* mrs cpsr */
7d1b0095 10510 tmp = tcg_temp_new_i32();
b53d8923 10511 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8984bd2e
PB
10512 addr = tcg_const_i32(insn & 0xff);
10513 gen_helper_v7m_mrs(tmp, cpu_env, addr);
b75263d6 10514 tcg_temp_free_i32(addr);
9ee6e8bb 10515 } else {
9ef39277 10516 gen_helper_cpsr_read(tmp, cpu_env);
9ee6e8bb 10517 }
8984bd2e 10518 store_reg(s, rd, tmp);
9ee6e8bb 10519 break;
8bfd0550 10520 case 7: /* MRS */
43ac6574
PM
10521 if (extract32(insn, 5, 1) &&
10522 !arm_dc_feature(s, ARM_FEATURE_M)) {
8bfd0550
PM
10523 /* MRS (banked) */
10524 int sysm = extract32(insn, 16, 4) |
10525 (extract32(insn, 4, 1) << 4);
10526
10527 gen_mrs_banked(s, 1, sysm, rd);
10528 break;
10529 }
10530
10531 /* mrs spsr. */
9ee6e8bb 10532 /* Not accessible in user mode. */
b53d8923 10533 if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
9ee6e8bb 10534 goto illegal_op;
b53d8923 10535 }
3d54026f
PM
10536
10537 if (extract32(insn, 16, 4) != 0xf ||
10538 extract32(insn, 0, 8) != 0) {
10539 goto illegal_op;
10540 }
10541
d9ba4830
PB
10542 tmp = load_cpu_field(spsr);
10543 store_reg(s, rd, tmp);
9ee6e8bb 10544 break;
2c0262af
FB
10545 }
10546 }
9ee6e8bb
PB
10547 } else {
10548 /* Conditional branch. */
10549 op = (insn >> 22) & 0xf;
10550 /* Generate a conditional jump to next instruction. */
c2d9644e 10551 arm_skip_unless(s, op);
9ee6e8bb
PB
10552
10553 /* offset[11:1] = insn[10:0] */
10554 offset = (insn & 0x7ff) << 1;
10555 /* offset[17:12] = insn[21:16]. */
10556 offset |= (insn & 0x003f0000) >> 4;
10557 /* offset[31:20] = insn[26]. */
10558 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
10559 /* offset[18] = insn[13]. */
10560 offset |= (insn & (1 << 13)) << 5;
10561 /* offset[19] = insn[11]. */
10562 offset |= (insn & (1 << 11)) << 8;
10563
10564 /* jump to the offset */
fdbcf632 10565 gen_jmp(s, read_pc(s) + offset);
9ee6e8bb
PB
10566 }
10567 } else {
55203189
PM
10568 /*
10569 * 0b1111_0xxx_xxxx_0xxx_xxxx_xxxx
10570 * - Data-processing (modified immediate, plain binary immediate)
10571 */
9ee6e8bb 10572 if (insn & (1 << 25)) {
55203189
PM
10573 /*
10574 * 0b1111_0x1x_xxxx_0xxx_xxxx_xxxx
10575 * - Data-processing (plain binary immediate)
10576 */
9ee6e8bb
PB
10577 if (insn & (1 << 24)) {
10578 if (insn & (1 << 20))
10579 goto illegal_op;
10580 /* Bitfield/Saturate. */
10581 op = (insn >> 21) & 7;
10582 imm = insn & 0x1f;
10583 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
6ddbc6e4 10584 if (rn == 15) {
7d1b0095 10585 tmp = tcg_temp_new_i32();
6ddbc6e4
PB
10586 tcg_gen_movi_i32(tmp, 0);
10587 } else {
10588 tmp = load_reg(s, rn);
10589 }
9ee6e8bb
PB
10590 switch (op) {
10591 case 2: /* Signed bitfield extract. */
10592 imm++;
10593 if (shift + imm > 32)
10594 goto illegal_op;
59a71b4c
RH
10595 if (imm < 32) {
10596 tcg_gen_sextract_i32(tmp, tmp, shift, imm);
10597 }
9ee6e8bb
PB
10598 break;
10599 case 6: /* Unsigned bitfield extract. */
10600 imm++;
10601 if (shift + imm > 32)
10602 goto illegal_op;
59a71b4c
RH
10603 if (imm < 32) {
10604 tcg_gen_extract_i32(tmp, tmp, shift, imm);
10605 }
9ee6e8bb
PB
10606 break;
10607 case 3: /* Bitfield insert/clear. */
10608 if (imm < shift)
10609 goto illegal_op;
10610 imm = imm + 1 - shift;
10611 if (imm != 32) {
6ddbc6e4 10612 tmp2 = load_reg(s, rd);
d593c48e 10613 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, imm);
7d1b0095 10614 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
10615 }
10616 break;
10617 case 7:
10618 goto illegal_op;
10619 default: /* Saturate. */
464eaa95
RH
10620 if (op & 1) {
10621 tcg_gen_sari_i32(tmp, tmp, shift);
10622 } else {
10623 tcg_gen_shli_i32(tmp, tmp, shift);
9ee6e8bb 10624 }
6ddbc6e4 10625 tmp2 = tcg_const_i32(imm);
9ee6e8bb
PB
10626 if (op & 4) {
10627 /* Unsigned. */
62b44f05
AR
10628 if ((op & 1) && shift == 0) {
10629 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10630 tcg_temp_free_i32(tmp);
10631 tcg_temp_free_i32(tmp2);
10632 goto illegal_op;
10633 }
9ef39277 10634 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
62b44f05 10635 } else {
9ef39277 10636 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
62b44f05 10637 }
2c0262af 10638 } else {
9ee6e8bb 10639 /* Signed. */
62b44f05
AR
10640 if ((op & 1) && shift == 0) {
10641 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10642 tcg_temp_free_i32(tmp);
10643 tcg_temp_free_i32(tmp2);
10644 goto illegal_op;
10645 }
9ef39277 10646 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
62b44f05 10647 } else {
9ef39277 10648 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
62b44f05 10649 }
2c0262af 10650 }
b75263d6 10651 tcg_temp_free_i32(tmp2);
9ee6e8bb 10652 break;
2c0262af 10653 }
6ddbc6e4 10654 store_reg(s, rd, tmp);
9ee6e8bb
PB
10655 } else {
10656 imm = ((insn & 0x04000000) >> 15)
10657 | ((insn & 0x7000) >> 4) | (insn & 0xff);
10658 if (insn & (1 << 22)) {
10659 /* 16-bit immediate. */
10660 imm |= (insn >> 4) & 0xf000;
10661 if (insn & (1 << 23)) {
10662 /* movt */
5e3f878a 10663 tmp = load_reg(s, rd);
86831435 10664 tcg_gen_ext16u_i32(tmp, tmp);
5e3f878a 10665 tcg_gen_ori_i32(tmp, tmp, imm << 16);
2c0262af 10666 } else {
9ee6e8bb 10667 /* movw */
7d1b0095 10668 tmp = tcg_temp_new_i32();
5e3f878a 10669 tcg_gen_movi_i32(tmp, imm);
2c0262af 10670 }
55203189 10671 store_reg(s, rd, tmp);
2c0262af 10672 } else {
9ee6e8bb 10673 /* Add/sub 12-bit immediate. */
16e0d823
RH
10674 if (insn & (1 << 23)) {
10675 imm = -imm;
10676 }
10677 tmp = add_reg_for_lit(s, rn, imm);
10678 if (rn == 13 && rd == 13) {
10679 /* ADD SP, SP, imm or SUB SP, SP, imm */
10680 store_sp_checked(s, tmp);
2c0262af 10681 } else {
16e0d823 10682 store_reg(s, rd, tmp);
2c0262af 10683 }
9ee6e8bb 10684 }
191abaa2 10685 }
9ee6e8bb 10686 } else {
55203189
PM
10687 /*
10688 * 0b1111_0x0x_xxxx_0xxx_xxxx_xxxx
10689 * - Data-processing (modified immediate)
10690 */
9ee6e8bb
PB
10691 int shifter_out = 0;
10692 /* modified 12-bit immediate. */
10693 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
10694 imm = (insn & 0xff);
10695 switch (shift) {
10696 case 0: /* XY */
10697 /* Nothing to do. */
10698 break;
10699 case 1: /* 00XY00XY */
10700 imm |= imm << 16;
10701 break;
10702 case 2: /* XY00XY00 */
10703 imm |= imm << 16;
10704 imm <<= 8;
10705 break;
10706 case 3: /* XYXYXYXY */
10707 imm |= imm << 16;
10708 imm |= imm << 8;
10709 break;
10710 default: /* Rotated constant. */
10711 shift = (shift << 1) | (imm >> 7);
10712 imm |= 0x80;
10713 imm = imm << (32 - shift);
10714 shifter_out = 1;
10715 break;
b5ff1b31 10716 }
7d1b0095 10717 tmp2 = tcg_temp_new_i32();
3174f8e9 10718 tcg_gen_movi_i32(tmp2, imm);
9ee6e8bb 10719 rn = (insn >> 16) & 0xf;
3174f8e9 10720 if (rn == 15) {
7d1b0095 10721 tmp = tcg_temp_new_i32();
3174f8e9
FN
10722 tcg_gen_movi_i32(tmp, 0);
10723 } else {
10724 tmp = load_reg(s, rn);
10725 }
9ee6e8bb
PB
10726 op = (insn >> 21) & 0xf;
10727 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
3174f8e9 10728 shifter_out, tmp, tmp2))
9ee6e8bb 10729 goto illegal_op;
7d1b0095 10730 tcg_temp_free_i32(tmp2);
9ee6e8bb 10731 rd = (insn >> 8) & 0xf;
55203189
PM
10732 if (rd == 13 && rn == 13
10733 && (op == 8 || op == 13)) {
10734 /* ADD(S) SP, SP, imm or SUB(S) SP, SP, imm */
10735 store_sp_checked(s, tmp);
10736 } else if (rd != 15) {
3174f8e9
FN
10737 store_reg(s, rd, tmp);
10738 } else {
7d1b0095 10739 tcg_temp_free_i32(tmp);
2c0262af 10740 }
2c0262af 10741 }
9ee6e8bb
PB
10742 }
10743 break;
10744 case 12: /* Load/store single data item. */
10745 {
10746 int postinc = 0;
10747 int writeback = 0;
a99caa48 10748 int memidx;
9bb6558a
PM
10749 ISSInfo issinfo;
10750
9ee6e8bb 10751 if ((insn & 0x01100000) == 0x01000000) {
7dcc1f89 10752 if (disas_neon_ls_insn(s, insn)) {
c1713132 10753 goto illegal_op;
7dcc1f89 10754 }
9ee6e8bb
PB
10755 break;
10756 }
a2fdc890
PM
10757 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
10758 if (rs == 15) {
10759 if (!(insn & (1 << 20))) {
10760 goto illegal_op;
10761 }
10762 if (op != 2) {
10763 /* Byte or halfword load space with dest == r15 : memory hints.
10764 * Catch them early so we don't emit pointless addressing code.
10765 * This space is a mix of:
10766 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
10767 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
10768 * cores)
10769 * unallocated hints, which must be treated as NOPs
10770 * UNPREDICTABLE space, which we NOP or UNDEF depending on
10771 * which is easiest for the decoding logic
10772 * Some space which must UNDEF
10773 */
10774 int op1 = (insn >> 23) & 3;
10775 int op2 = (insn >> 6) & 0x3f;
10776 if (op & 2) {
10777 goto illegal_op;
10778 }
10779 if (rn == 15) {
02afbf64
PM
10780 /* UNPREDICTABLE, unallocated hint or
10781 * PLD/PLDW/PLI (literal)
10782 */
2eea841c 10783 return;
a2fdc890
PM
10784 }
10785 if (op1 & 1) {
2eea841c 10786 return; /* PLD/PLDW/PLI or unallocated hint */
a2fdc890
PM
10787 }
10788 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
2eea841c 10789 return; /* PLD/PLDW/PLI or unallocated hint */
a2fdc890
PM
10790 }
10791 /* UNDEF space, or an UNPREDICTABLE */
2eea841c 10792 goto illegal_op;
a2fdc890
PM
10793 }
10794 }
a99caa48 10795 memidx = get_mem_index(s);
16e0d823
RH
10796 imm = insn & 0xfff;
10797 if (insn & (1 << 23)) {
10798 /* PC relative or Positive offset. */
10799 addr = add_reg_for_lit(s, rn, imm);
10800 } else if (rn == 15) {
10801 /* PC relative with negative offset. */
10802 addr = add_reg_for_lit(s, rn, -imm);
9ee6e8bb 10803 } else {
b0109805 10804 addr = load_reg(s, rn);
16e0d823
RH
10805 imm = insn & 0xff;
10806 switch ((insn >> 8) & 0xf) {
10807 case 0x0: /* Shifted Register. */
10808 shift = (insn >> 4) & 0xf;
10809 if (shift > 3) {
2a0308c5 10810 tcg_temp_free_i32(addr);
b7bcbe95 10811 goto illegal_op;
9ee6e8bb 10812 }
16e0d823 10813 tmp = load_reg(s, rm);
464eaa95 10814 tcg_gen_shli_i32(tmp, tmp, shift);
16e0d823
RH
10815 tcg_gen_add_i32(addr, addr, tmp);
10816 tcg_temp_free_i32(tmp);
10817 break;
10818 case 0xc: /* Negative offset. */
10819 tcg_gen_addi_i32(addr, addr, -imm);
10820 break;
10821 case 0xe: /* User privilege. */
10822 tcg_gen_addi_i32(addr, addr, imm);
10823 memidx = get_a32_user_mem_index(s);
10824 break;
10825 case 0x9: /* Post-decrement. */
10826 imm = -imm;
10827 /* Fall through. */
10828 case 0xb: /* Post-increment. */
10829 postinc = 1;
10830 writeback = 1;
10831 break;
10832 case 0xd: /* Pre-decrement. */
10833 imm = -imm;
10834 /* Fall through. */
10835 case 0xf: /* Pre-increment. */
10836 writeback = 1;
10837 break;
10838 default:
10839 tcg_temp_free_i32(addr);
10840 goto illegal_op;
9ee6e8bb
PB
10841 }
10842 }
9bb6558a
PM
10843
10844 issinfo = writeback ? ISSInvalid : rs;
10845
0bc003ba
PM
10846 if (s->v8m_stackcheck && rn == 13 && writeback) {
10847 /*
10848 * Stackcheck. Here we know 'addr' is the current SP;
10849 * if imm is +ve we're moving SP up, else down. It is
10850 * UNKNOWN whether the limit check triggers when SP starts
10851 * below the limit and ends up above it; we chose to do so.
10852 */
10853 if ((int32_t)imm < 0) {
10854 TCGv_i32 newsp = tcg_temp_new_i32();
10855
10856 tcg_gen_addi_i32(newsp, addr, imm);
10857 gen_helper_v8m_stackcheck(cpu_env, newsp);
10858 tcg_temp_free_i32(newsp);
10859 } else {
10860 gen_helper_v8m_stackcheck(cpu_env, addr);
10861 }
10862 }
10863
10864 if (writeback && !postinc) {
10865 tcg_gen_addi_i32(addr, addr, imm);
10866 }
10867
9ee6e8bb
PB
10868 if (insn & (1 << 20)) {
10869 /* Load. */
5a839c0d 10870 tmp = tcg_temp_new_i32();
a2fdc890 10871 switch (op) {
5a839c0d 10872 case 0:
9bb6558a 10873 gen_aa32_ld8u_iss(s, tmp, addr, memidx, issinfo);
5a839c0d
PM
10874 break;
10875 case 4:
9bb6558a 10876 gen_aa32_ld8s_iss(s, tmp, addr, memidx, issinfo);
5a839c0d
PM
10877 break;
10878 case 1:
9bb6558a 10879 gen_aa32_ld16u_iss(s, tmp, addr, memidx, issinfo);
5a839c0d
PM
10880 break;
10881 case 5:
9bb6558a 10882 gen_aa32_ld16s_iss(s, tmp, addr, memidx, issinfo);
5a839c0d
PM
10883 break;
10884 case 2:
9bb6558a 10885 gen_aa32_ld32u_iss(s, tmp, addr, memidx, issinfo);
5a839c0d 10886 break;
2a0308c5 10887 default:
5a839c0d 10888 tcg_temp_free_i32(tmp);
2a0308c5
PM
10889 tcg_temp_free_i32(addr);
10890 goto illegal_op;
a2fdc890
PM
10891 }
10892 if (rs == 15) {
3bb8a96f 10893 gen_bx_excret(s, tmp);
9ee6e8bb 10894 } else {
a2fdc890 10895 store_reg(s, rs, tmp);
9ee6e8bb
PB
10896 }
10897 } else {
10898 /* Store. */
b0109805 10899 tmp = load_reg(s, rs);
9ee6e8bb 10900 switch (op) {
5a839c0d 10901 case 0:
9bb6558a 10902 gen_aa32_st8_iss(s, tmp, addr, memidx, issinfo);
5a839c0d
PM
10903 break;
10904 case 1:
9bb6558a 10905 gen_aa32_st16_iss(s, tmp, addr, memidx, issinfo);
5a839c0d
PM
10906 break;
10907 case 2:
9bb6558a 10908 gen_aa32_st32_iss(s, tmp, addr, memidx, issinfo);
5a839c0d 10909 break;
2a0308c5 10910 default:
5a839c0d 10911 tcg_temp_free_i32(tmp);
2a0308c5
PM
10912 tcg_temp_free_i32(addr);
10913 goto illegal_op;
b7bcbe95 10914 }
5a839c0d 10915 tcg_temp_free_i32(tmp);
2c0262af 10916 }
9ee6e8bb 10917 if (postinc)
b0109805
PB
10918 tcg_gen_addi_i32(addr, addr, imm);
10919 if (writeback) {
10920 store_reg(s, rn, addr);
10921 } else {
7d1b0095 10922 tcg_temp_free_i32(addr);
b0109805 10923 }
9ee6e8bb
PB
10924 }
10925 break;
10926 default:
10927 goto illegal_op;
2c0262af 10928 }
2eea841c 10929 return;
9ee6e8bb 10930illegal_op:
1ce21ba1 10931 unallocated_encoding(s);
2c0262af
FB
10932}
10933
296e5a0a 10934static void disas_thumb_insn(DisasContext *s, uint32_t insn)
99c475ab 10935{
296e5a0a 10936 uint32_t val, op, rm, rn, rd, shift, cond;
99c475ab
FB
10937 int32_t offset;
10938 int i;
39d5492a
PM
10939 TCGv_i32 tmp;
10940 TCGv_i32 tmp2;
10941 TCGv_i32 addr;
99c475ab 10942
99c475ab
FB
10943 switch (insn >> 12) {
10944 case 0: case 1:
396e467c 10945
99c475ab
FB
10946 rd = insn & 7;
10947 op = (insn >> 11) & 3;
10948 if (op == 3) {
a2d12f0f
PM
10949 /*
10950 * 0b0001_1xxx_xxxx_xxxx
10951 * - Add, subtract (three low registers)
10952 * - Add, subtract (two low registers and immediate)
10953 */
99c475ab 10954 rn = (insn >> 3) & 7;
396e467c 10955 tmp = load_reg(s, rn);
99c475ab
FB
10956 if (insn & (1 << 10)) {
10957 /* immediate */
7d1b0095 10958 tmp2 = tcg_temp_new_i32();
396e467c 10959 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
99c475ab
FB
10960 } else {
10961 /* reg */
10962 rm = (insn >> 6) & 7;
396e467c 10963 tmp2 = load_reg(s, rm);
99c475ab 10964 }
9ee6e8bb
PB
10965 if (insn & (1 << 9)) {
10966 if (s->condexec_mask)
396e467c 10967 tcg_gen_sub_i32(tmp, tmp, tmp2);
9ee6e8bb 10968 else
72485ec4 10969 gen_sub_CC(tmp, tmp, tmp2);
9ee6e8bb
PB
10970 } else {
10971 if (s->condexec_mask)
396e467c 10972 tcg_gen_add_i32(tmp, tmp, tmp2);
9ee6e8bb 10973 else
72485ec4 10974 gen_add_CC(tmp, tmp, tmp2);
9ee6e8bb 10975 }
7d1b0095 10976 tcg_temp_free_i32(tmp2);
396e467c 10977 store_reg(s, rd, tmp);
99c475ab
FB
10978 } else {
10979 /* shift immediate */
10980 rm = (insn >> 3) & 7;
10981 shift = (insn >> 6) & 0x1f;
9a119ff6
PB
10982 tmp = load_reg(s, rm);
10983 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
10984 if (!s->condexec_mask)
10985 gen_logic_CC(tmp);
10986 store_reg(s, rd, tmp);
99c475ab
FB
10987 }
10988 break;
10989 case 2: case 3:
a2d12f0f
PM
10990 /*
10991 * 0b001x_xxxx_xxxx_xxxx
10992 * - Add, subtract, compare, move (one low register and immediate)
10993 */
99c475ab
FB
10994 op = (insn >> 11) & 3;
10995 rd = (insn >> 8) & 0x7;
396e467c 10996 if (op == 0) { /* mov */
7d1b0095 10997 tmp = tcg_temp_new_i32();
396e467c 10998 tcg_gen_movi_i32(tmp, insn & 0xff);
9ee6e8bb 10999 if (!s->condexec_mask)
396e467c
FN
11000 gen_logic_CC(tmp);
11001 store_reg(s, rd, tmp);
11002 } else {
11003 tmp = load_reg(s, rd);
7d1b0095 11004 tmp2 = tcg_temp_new_i32();
396e467c
FN
11005 tcg_gen_movi_i32(tmp2, insn & 0xff);
11006 switch (op) {
11007 case 1: /* cmp */
72485ec4 11008 gen_sub_CC(tmp, tmp, tmp2);
7d1b0095
PM
11009 tcg_temp_free_i32(tmp);
11010 tcg_temp_free_i32(tmp2);
396e467c
FN
11011 break;
11012 case 2: /* add */
11013 if (s->condexec_mask)
11014 tcg_gen_add_i32(tmp, tmp, tmp2);
11015 else
72485ec4 11016 gen_add_CC(tmp, tmp, tmp2);
7d1b0095 11017 tcg_temp_free_i32(tmp2);
396e467c
FN
11018 store_reg(s, rd, tmp);
11019 break;
11020 case 3: /* sub */
11021 if (s->condexec_mask)
11022 tcg_gen_sub_i32(tmp, tmp, tmp2);
11023 else
72485ec4 11024 gen_sub_CC(tmp, tmp, tmp2);
7d1b0095 11025 tcg_temp_free_i32(tmp2);
396e467c
FN
11026 store_reg(s, rd, tmp);
11027 break;
11028 }
99c475ab 11029 }
99c475ab
FB
11030 break;
11031 case 4:
11032 if (insn & (1 << 11)) {
11033 rd = (insn >> 8) & 7;
5899f386 11034 /* load pc-relative. Bit 1 of PC is ignored. */
16e0d823 11035 addr = add_reg_for_lit(s, 15, (insn & 0xff) * 4);
c40c8556 11036 tmp = tcg_temp_new_i32();
9bb6558a
PM
11037 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s),
11038 rd | ISSIs16Bit);
7d1b0095 11039 tcg_temp_free_i32(addr);
b0109805 11040 store_reg(s, rd, tmp);
99c475ab
FB
11041 break;
11042 }
11043 if (insn & (1 << 10)) {
ebfe27c5
PM
11044 /* 0b0100_01xx_xxxx_xxxx
11045 * - data processing extended, branch and exchange
11046 */
99c475ab
FB
11047 rd = (insn & 7) | ((insn >> 4) & 8);
11048 rm = (insn >> 3) & 0xf;
11049 op = (insn >> 8) & 3;
11050 switch (op) {
11051 case 0: /* add */
396e467c
FN
11052 tmp = load_reg(s, rd);
11053 tmp2 = load_reg(s, rm);
11054 tcg_gen_add_i32(tmp, tmp, tmp2);
7d1b0095 11055 tcg_temp_free_i32(tmp2);
55203189
PM
11056 if (rd == 13) {
11057 /* ADD SP, SP, reg */
11058 store_sp_checked(s, tmp);
11059 } else {
11060 store_reg(s, rd, tmp);
11061 }
99c475ab
FB
11062 break;
11063 case 1: /* cmp */
396e467c
FN
11064 tmp = load_reg(s, rd);
11065 tmp2 = load_reg(s, rm);
72485ec4 11066 gen_sub_CC(tmp, tmp, tmp2);
7d1b0095
PM
11067 tcg_temp_free_i32(tmp2);
11068 tcg_temp_free_i32(tmp);
99c475ab
FB
11069 break;
11070 case 2: /* mov/cpy */
396e467c 11071 tmp = load_reg(s, rm);
55203189
PM
11072 if (rd == 13) {
11073 /* MOV SP, reg */
11074 store_sp_checked(s, tmp);
11075 } else {
11076 store_reg(s, rd, tmp);
11077 }
99c475ab 11078 break;
ebfe27c5
PM
11079 case 3:
11080 {
11081 /* 0b0100_0111_xxxx_xxxx
11082 * - branch [and link] exchange thumb register
11083 */
11084 bool link = insn & (1 << 7);
11085
fb602cb7 11086 if (insn & 3) {
ebfe27c5
PM
11087 goto undef;
11088 }
11089 if (link) {
be5e7a76 11090 ARCH(5);
ebfe27c5 11091 }
fb602cb7
PM
11092 if ((insn & 4)) {
11093 /* BXNS/BLXNS: only exists for v8M with the
11094 * security extensions, and always UNDEF if NonSecure.
11095 * We don't implement these in the user-only mode
11096 * either (in theory you can use them from Secure User
11097 * mode but they are too tied in to system emulation.)
11098 */
11099 if (!s->v8m_secure || IS_USER_ONLY) {
11100 goto undef;
11101 }
11102 if (link) {
3e3fa230 11103 gen_blxns(s, rm);
fb602cb7
PM
11104 } else {
11105 gen_bxns(s, rm);
11106 }
11107 break;
11108 }
11109 /* BLX/BX */
ebfe27c5
PM
11110 tmp = load_reg(s, rm);
11111 if (link) {
a0415916 11112 val = (uint32_t)s->base.pc_next | 1;
7d1b0095 11113 tmp2 = tcg_temp_new_i32();
b0109805
PB
11114 tcg_gen_movi_i32(tmp2, val);
11115 store_reg(s, 14, tmp2);
3bb8a96f
PM
11116 gen_bx(s, tmp);
11117 } else {
11118 /* Only BX works as exception-return, not BLX */
11119 gen_bx_excret(s, tmp);
99c475ab 11120 }
99c475ab
FB
11121 break;
11122 }
ebfe27c5 11123 }
99c475ab
FB
11124 break;
11125 }
11126
a2d12f0f
PM
11127 /*
11128 * 0b0100_00xx_xxxx_xxxx
11129 * - Data-processing (two low registers)
11130 */
99c475ab
FB
11131 rd = insn & 7;
11132 rm = (insn >> 3) & 7;
11133 op = (insn >> 6) & 0xf;
11134 if (op == 2 || op == 3 || op == 4 || op == 7) {
11135 /* the shift/rotate ops want the operands backwards */
11136 val = rm;
11137 rm = rd;
11138 rd = val;
11139 val = 1;
11140 } else {
11141 val = 0;
11142 }
11143
396e467c 11144 if (op == 9) { /* neg */
7d1b0095 11145 tmp = tcg_temp_new_i32();
396e467c
FN
11146 tcg_gen_movi_i32(tmp, 0);
11147 } else if (op != 0xf) { /* mvn doesn't read its first operand */
11148 tmp = load_reg(s, rd);
11149 } else {
f764718d 11150 tmp = NULL;
396e467c 11151 }
99c475ab 11152
396e467c 11153 tmp2 = load_reg(s, rm);
5899f386 11154 switch (op) {
99c475ab 11155 case 0x0: /* and */
396e467c 11156 tcg_gen_and_i32(tmp, tmp, tmp2);
9ee6e8bb 11157 if (!s->condexec_mask)
396e467c 11158 gen_logic_CC(tmp);
99c475ab
FB
11159 break;
11160 case 0x1: /* eor */
396e467c 11161 tcg_gen_xor_i32(tmp, tmp, tmp2);
9ee6e8bb 11162 if (!s->condexec_mask)
396e467c 11163 gen_logic_CC(tmp);
99c475ab
FB
11164 break;
11165 case 0x2: /* lsl */
9ee6e8bb 11166 if (s->condexec_mask) {
365af80e 11167 gen_shl(tmp2, tmp2, tmp);
9ee6e8bb 11168 } else {
9ef39277 11169 gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
396e467c 11170 gen_logic_CC(tmp2);
9ee6e8bb 11171 }
99c475ab
FB
11172 break;
11173 case 0x3: /* lsr */
9ee6e8bb 11174 if (s->condexec_mask) {
365af80e 11175 gen_shr(tmp2, tmp2, tmp);
9ee6e8bb 11176 } else {
9ef39277 11177 gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
396e467c 11178 gen_logic_CC(tmp2);
9ee6e8bb 11179 }
99c475ab
FB
11180 break;
11181 case 0x4: /* asr */
9ee6e8bb 11182 if (s->condexec_mask) {
365af80e 11183 gen_sar(tmp2, tmp2, tmp);
9ee6e8bb 11184 } else {
9ef39277 11185 gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
396e467c 11186 gen_logic_CC(tmp2);
9ee6e8bb 11187 }
99c475ab
FB
11188 break;
11189 case 0x5: /* adc */
49b4c31e 11190 if (s->condexec_mask) {
396e467c 11191 gen_adc(tmp, tmp2);
49b4c31e
RH
11192 } else {
11193 gen_adc_CC(tmp, tmp, tmp2);
11194 }
99c475ab
FB
11195 break;
11196 case 0x6: /* sbc */
2de68a49 11197 if (s->condexec_mask) {
396e467c 11198 gen_sub_carry(tmp, tmp, tmp2);
2de68a49
RH
11199 } else {
11200 gen_sbc_CC(tmp, tmp, tmp2);
11201 }
99c475ab
FB
11202 break;
11203 case 0x7: /* ror */
9ee6e8bb 11204 if (s->condexec_mask) {
f669df27
AJ
11205 tcg_gen_andi_i32(tmp, tmp, 0x1f);
11206 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
9ee6e8bb 11207 } else {
9ef39277 11208 gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);
396e467c 11209 gen_logic_CC(tmp2);
9ee6e8bb 11210 }
99c475ab
FB
11211 break;
11212 case 0x8: /* tst */
396e467c
FN
11213 tcg_gen_and_i32(tmp, tmp, tmp2);
11214 gen_logic_CC(tmp);
99c475ab 11215 rd = 16;
5899f386 11216 break;
99c475ab 11217 case 0x9: /* neg */
9ee6e8bb 11218 if (s->condexec_mask)
396e467c 11219 tcg_gen_neg_i32(tmp, tmp2);
9ee6e8bb 11220 else
72485ec4 11221 gen_sub_CC(tmp, tmp, tmp2);
99c475ab
FB
11222 break;
11223 case 0xa: /* cmp */
72485ec4 11224 gen_sub_CC(tmp, tmp, tmp2);
99c475ab
FB
11225 rd = 16;
11226 break;
11227 case 0xb: /* cmn */
72485ec4 11228 gen_add_CC(tmp, tmp, tmp2);
99c475ab
FB
11229 rd = 16;
11230 break;
11231 case 0xc: /* orr */
396e467c 11232 tcg_gen_or_i32(tmp, tmp, tmp2);
9ee6e8bb 11233 if (!s->condexec_mask)
396e467c 11234 gen_logic_CC(tmp);
99c475ab
FB
11235 break;
11236 case 0xd: /* mul */
7b2919a0 11237 tcg_gen_mul_i32(tmp, tmp, tmp2);
9ee6e8bb 11238 if (!s->condexec_mask)
396e467c 11239 gen_logic_CC(tmp);
99c475ab
FB
11240 break;
11241 case 0xe: /* bic */
f669df27 11242 tcg_gen_andc_i32(tmp, tmp, tmp2);
9ee6e8bb 11243 if (!s->condexec_mask)
396e467c 11244 gen_logic_CC(tmp);
99c475ab
FB
11245 break;
11246 case 0xf: /* mvn */
396e467c 11247 tcg_gen_not_i32(tmp2, tmp2);
9ee6e8bb 11248 if (!s->condexec_mask)
396e467c 11249 gen_logic_CC(tmp2);
99c475ab 11250 val = 1;
5899f386 11251 rm = rd;
99c475ab
FB
11252 break;
11253 }
11254 if (rd != 16) {
396e467c
FN
11255 if (val) {
11256 store_reg(s, rm, tmp2);
11257 if (op != 0xf)
7d1b0095 11258 tcg_temp_free_i32(tmp);
396e467c
FN
11259 } else {
11260 store_reg(s, rd, tmp);
7d1b0095 11261 tcg_temp_free_i32(tmp2);
396e467c
FN
11262 }
11263 } else {
7d1b0095
PM
11264 tcg_temp_free_i32(tmp);
11265 tcg_temp_free_i32(tmp2);
99c475ab
FB
11266 }
11267 break;
11268
11269 case 5:
11270 /* load/store register offset. */
11271 rd = insn & 7;
11272 rn = (insn >> 3) & 7;
11273 rm = (insn >> 6) & 7;
11274 op = (insn >> 9) & 7;
b0109805 11275 addr = load_reg(s, rn);
b26eefb6 11276 tmp = load_reg(s, rm);
b0109805 11277 tcg_gen_add_i32(addr, addr, tmp);
7d1b0095 11278 tcg_temp_free_i32(tmp);
99c475ab 11279
c40c8556 11280 if (op < 3) { /* store */
b0109805 11281 tmp = load_reg(s, rd);
c40c8556
PM
11282 } else {
11283 tmp = tcg_temp_new_i32();
11284 }
99c475ab
FB
11285
11286 switch (op) {
11287 case 0: /* str */
9bb6558a 11288 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
11289 break;
11290 case 1: /* strh */
9bb6558a 11291 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
11292 break;
11293 case 2: /* strb */
9bb6558a 11294 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
11295 break;
11296 case 3: /* ldrsb */
9bb6558a 11297 gen_aa32_ld8s_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
11298 break;
11299 case 4: /* ldr */
9bb6558a 11300 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
11301 break;
11302 case 5: /* ldrh */
9bb6558a 11303 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
11304 break;
11305 case 6: /* ldrb */
9bb6558a 11306 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
11307 break;
11308 case 7: /* ldrsh */
9bb6558a 11309 gen_aa32_ld16s_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
99c475ab
FB
11310 break;
11311 }
c40c8556 11312 if (op >= 3) { /* load */
b0109805 11313 store_reg(s, rd, tmp);
c40c8556
PM
11314 } else {
11315 tcg_temp_free_i32(tmp);
11316 }
7d1b0095 11317 tcg_temp_free_i32(addr);
99c475ab
FB
11318 break;
11319
11320 case 6:
11321 /* load/store word immediate offset */
11322 rd = insn & 7;
11323 rn = (insn >> 3) & 7;
b0109805 11324 addr = load_reg(s, rn);
99c475ab 11325 val = (insn >> 4) & 0x7c;
b0109805 11326 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
11327
11328 if (insn & (1 << 11)) {
11329 /* load */
c40c8556 11330 tmp = tcg_temp_new_i32();
12dcc321 11331 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 11332 store_reg(s, rd, tmp);
99c475ab
FB
11333 } else {
11334 /* store */
b0109805 11335 tmp = load_reg(s, rd);
12dcc321 11336 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
c40c8556 11337 tcg_temp_free_i32(tmp);
99c475ab 11338 }
7d1b0095 11339 tcg_temp_free_i32(addr);
99c475ab
FB
11340 break;
11341
11342 case 7:
11343 /* load/store byte immediate offset */
11344 rd = insn & 7;
11345 rn = (insn >> 3) & 7;
b0109805 11346 addr = load_reg(s, rn);
99c475ab 11347 val = (insn >> 6) & 0x1f;
b0109805 11348 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
11349
11350 if (insn & (1 << 11)) {
11351 /* load */
c40c8556 11352 tmp = tcg_temp_new_i32();
9bb6558a 11353 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
b0109805 11354 store_reg(s, rd, tmp);
99c475ab
FB
11355 } else {
11356 /* store */
b0109805 11357 tmp = load_reg(s, rd);
9bb6558a 11358 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
c40c8556 11359 tcg_temp_free_i32(tmp);
99c475ab 11360 }
7d1b0095 11361 tcg_temp_free_i32(addr);
99c475ab
FB
11362 break;
11363
11364 case 8:
11365 /* load/store halfword immediate offset */
11366 rd = insn & 7;
11367 rn = (insn >> 3) & 7;
b0109805 11368 addr = load_reg(s, rn);
99c475ab 11369 val = (insn >> 5) & 0x3e;
b0109805 11370 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
11371
11372 if (insn & (1 << 11)) {
11373 /* load */
c40c8556 11374 tmp = tcg_temp_new_i32();
9bb6558a 11375 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
b0109805 11376 store_reg(s, rd, tmp);
99c475ab
FB
11377 } else {
11378 /* store */
b0109805 11379 tmp = load_reg(s, rd);
9bb6558a 11380 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
c40c8556 11381 tcg_temp_free_i32(tmp);
99c475ab 11382 }
7d1b0095 11383 tcg_temp_free_i32(addr);
99c475ab
FB
11384 break;
11385
11386 case 9:
11387 /* load/store from stack */
11388 rd = (insn >> 8) & 7;
b0109805 11389 addr = load_reg(s, 13);
99c475ab 11390 val = (insn & 0xff) * 4;
b0109805 11391 tcg_gen_addi_i32(addr, addr, val);
99c475ab
FB
11392
11393 if (insn & (1 << 11)) {
11394 /* load */
c40c8556 11395 tmp = tcg_temp_new_i32();
9bb6558a 11396 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
b0109805 11397 store_reg(s, rd, tmp);
99c475ab
FB
11398 } else {
11399 /* store */
b0109805 11400 tmp = load_reg(s, rd);
9bb6558a 11401 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
c40c8556 11402 tcg_temp_free_i32(tmp);
99c475ab 11403 }
7d1b0095 11404 tcg_temp_free_i32(addr);
99c475ab
FB
11405 break;
11406
11407 case 10:
55203189
PM
11408 /*
11409 * 0b1010_xxxx_xxxx_xxxx
11410 * - Add PC/SP (immediate)
11411 */
99c475ab 11412 rd = (insn >> 8) & 7;
99c475ab 11413 val = (insn & 0xff) * 4;
16e0d823 11414 tmp = add_reg_for_lit(s, insn & (1 << 11) ? 13 : 15, val);
5e3f878a 11415 store_reg(s, rd, tmp);
99c475ab
FB
11416 break;
11417
11418 case 11:
11419 /* misc */
11420 op = (insn >> 8) & 0xf;
11421 switch (op) {
11422 case 0:
55203189
PM
11423 /*
11424 * 0b1011_0000_xxxx_xxxx
11425 * - ADD (SP plus immediate)
11426 * - SUB (SP minus immediate)
11427 */
b26eefb6 11428 tmp = load_reg(s, 13);
99c475ab
FB
11429 val = (insn & 0x7f) * 4;
11430 if (insn & (1 << 7))
6a0d8a1d 11431 val = -(int32_t)val;
b26eefb6 11432 tcg_gen_addi_i32(tmp, tmp, val);
55203189 11433 store_sp_checked(s, tmp);
99c475ab
FB
11434 break;
11435
9ee6e8bb
PB
11436 case 2: /* sign/zero extend. */
11437 ARCH(6);
11438 rd = insn & 7;
11439 rm = (insn >> 3) & 7;
b0109805 11440 tmp = load_reg(s, rm);
9ee6e8bb 11441 switch ((insn >> 6) & 3) {
b0109805
PB
11442 case 0: gen_sxth(tmp); break;
11443 case 1: gen_sxtb(tmp); break;
11444 case 2: gen_uxth(tmp); break;
11445 case 3: gen_uxtb(tmp); break;
9ee6e8bb 11446 }
b0109805 11447 store_reg(s, rd, tmp);
9ee6e8bb 11448 break;
99c475ab 11449 case 4: case 5: case 0xc: case 0xd:
aa369e5c
PM
11450 /*
11451 * 0b1011_x10x_xxxx_xxxx
11452 * - push/pop
11453 */
b0109805 11454 addr = load_reg(s, 13);
5899f386
FB
11455 if (insn & (1 << 8))
11456 offset = 4;
99c475ab 11457 else
5899f386
FB
11458 offset = 0;
11459 for (i = 0; i < 8; i++) {
11460 if (insn & (1 << i))
11461 offset += 4;
11462 }
11463 if ((insn & (1 << 11)) == 0) {
b0109805 11464 tcg_gen_addi_i32(addr, addr, -offset);
5899f386 11465 }
aa369e5c
PM
11466
11467 if (s->v8m_stackcheck) {
11468 /*
11469 * Here 'addr' is the lower of "old SP" and "new SP";
11470 * if this is a pop that starts below the limit and ends
11471 * above it, it is UNKNOWN whether the limit check triggers;
11472 * we choose to trigger.
11473 */
11474 gen_helper_v8m_stackcheck(cpu_env, addr);
11475 }
11476
99c475ab
FB
11477 for (i = 0; i < 8; i++) {
11478 if (insn & (1 << i)) {
11479 if (insn & (1 << 11)) {
11480 /* pop */
c40c8556 11481 tmp = tcg_temp_new_i32();
12dcc321 11482 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 11483 store_reg(s, i, tmp);
99c475ab
FB
11484 } else {
11485 /* push */
b0109805 11486 tmp = load_reg(s, i);
12dcc321 11487 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
c40c8556 11488 tcg_temp_free_i32(tmp);
99c475ab 11489 }
5899f386 11490 /* advance to the next address. */
b0109805 11491 tcg_gen_addi_i32(addr, addr, 4);
99c475ab
FB
11492 }
11493 }
f764718d 11494 tmp = NULL;
99c475ab
FB
11495 if (insn & (1 << 8)) {
11496 if (insn & (1 << 11)) {
11497 /* pop pc */
c40c8556 11498 tmp = tcg_temp_new_i32();
12dcc321 11499 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
99c475ab
FB
11500 /* don't set the pc until the rest of the instruction
11501 has completed */
11502 } else {
11503 /* push lr */
b0109805 11504 tmp = load_reg(s, 14);
12dcc321 11505 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
c40c8556 11506 tcg_temp_free_i32(tmp);
99c475ab 11507 }
b0109805 11508 tcg_gen_addi_i32(addr, addr, 4);
99c475ab 11509 }
5899f386 11510 if ((insn & (1 << 11)) == 0) {
b0109805 11511 tcg_gen_addi_i32(addr, addr, -offset);
5899f386 11512 }
99c475ab 11513 /* write back the new stack pointer */
b0109805 11514 store_reg(s, 13, addr);
99c475ab 11515 /* set the new PC value */
be5e7a76 11516 if ((insn & 0x0900) == 0x0900) {
7dcc1f89 11517 store_reg_from_load(s, 15, tmp);
be5e7a76 11518 }
99c475ab
FB
11519 break;
11520
9ee6e8bb
PB
11521 case 1: case 3: case 9: case 11: /* czb */
11522 rm = insn & 7;
d9ba4830 11523 tmp = load_reg(s, rm);
c2d9644e 11524 arm_gen_condlabel(s);
9ee6e8bb 11525 if (insn & (1 << 11))
cb63669a 11526 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
9ee6e8bb 11527 else
cb63669a 11528 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
7d1b0095 11529 tcg_temp_free_i32(tmp);
9ee6e8bb 11530 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
fdbcf632 11531 gen_jmp(s, read_pc(s) + offset);
9ee6e8bb
PB
11532 break;
11533
11534 case 15: /* IT, nop-hint. */
11535 if ((insn & 0xf) == 0) {
11536 gen_nop_hint(s, (insn >> 4) & 0xf);
11537 break;
11538 }
5529de1e
PM
11539 /*
11540 * IT (If-Then)
11541 *
11542 * Combinations of firstcond and mask which set up an 0b1111
11543 * condition are UNPREDICTABLE; we take the CONSTRAINED
11544 * UNPREDICTABLE choice to treat 0b1111 the same as 0b1110,
11545 * i.e. both meaning "execute always".
11546 */
9ee6e8bb
PB
11547 s->condexec_cond = (insn >> 4) & 0xe;
11548 s->condexec_mask = insn & 0x1f;
11549 /* No actual code generated for this insn, just setup state. */
11550 break;
11551
06c949e6 11552 case 0xe: /* bkpt */
d4a2dc67
PM
11553 {
11554 int imm8 = extract32(insn, 0, 8);
be5e7a76 11555 ARCH(5);
06bcbda3 11556 gen_exception_bkpt_insn(s, syn_aa32_bkpt(imm8, true));
06c949e6 11557 break;
d4a2dc67 11558 }
06c949e6 11559
19a6e31c
PM
11560 case 0xa: /* rev, and hlt */
11561 {
11562 int op1 = extract32(insn, 6, 2);
11563
11564 if (op1 == 2) {
11565 /* HLT */
11566 int imm6 = extract32(insn, 0, 6);
11567
11568 gen_hlt(s, imm6);
11569 break;
11570 }
11571
11572 /* Otherwise this is rev */
9ee6e8bb
PB
11573 ARCH(6);
11574 rn = (insn >> 3) & 0x7;
11575 rd = insn & 0x7;
b0109805 11576 tmp = load_reg(s, rn);
19a6e31c 11577 switch (op1) {
66896cb8 11578 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
b0109805
PB
11579 case 1: gen_rev16(tmp); break;
11580 case 3: gen_revsh(tmp); break;
19a6e31c
PM
11581 default:
11582 g_assert_not_reached();
9ee6e8bb 11583 }
b0109805 11584 store_reg(s, rd, tmp);
9ee6e8bb 11585 break;
19a6e31c 11586 }
9ee6e8bb 11587
d9e028c1
PM
11588 case 6:
11589 switch ((insn >> 5) & 7) {
11590 case 2:
11591 /* setend */
11592 ARCH(6);
9886ecdf
PB
11593 if (((insn >> 3) & 1) != !!(s->be_data == MO_BE)) {
11594 gen_helper_setend(cpu_env);
dcba3a8d 11595 s->base.is_jmp = DISAS_UPDATE;
d9e028c1 11596 }
9ee6e8bb 11597 break;
d9e028c1
PM
11598 case 3:
11599 /* cps */
11600 ARCH(6);
11601 if (IS_USER(s)) {
11602 break;
8984bd2e 11603 }
b53d8923 11604 if (arm_dc_feature(s, ARM_FEATURE_M)) {
d9e028c1
PM
11605 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
11606 /* FAULTMASK */
11607 if (insn & 1) {
11608 addr = tcg_const_i32(19);
11609 gen_helper_v7m_msr(cpu_env, addr, tmp);
11610 tcg_temp_free_i32(addr);
11611 }
11612 /* PRIMASK */
11613 if (insn & 2) {
11614 addr = tcg_const_i32(16);
11615 gen_helper_v7m_msr(cpu_env, addr, tmp);
11616 tcg_temp_free_i32(addr);
11617 }
11618 tcg_temp_free_i32(tmp);
11619 gen_lookup_tb(s);
11620 } else {
11621 if (insn & (1 << 4)) {
11622 shift = CPSR_A | CPSR_I | CPSR_F;
11623 } else {
11624 shift = 0;
11625 }
11626 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
8984bd2e 11627 }
d9e028c1
PM
11628 break;
11629 default:
11630 goto undef;
9ee6e8bb
PB
11631 }
11632 break;
11633
99c475ab
FB
11634 default:
11635 goto undef;
11636 }
11637 break;
11638
11639 case 12:
a7d3970d 11640 {
99c475ab 11641 /* load/store multiple */
f764718d 11642 TCGv_i32 loaded_var = NULL;
99c475ab 11643 rn = (insn >> 8) & 0x7;
b0109805 11644 addr = load_reg(s, rn);
99c475ab
FB
11645 for (i = 0; i < 8; i++) {
11646 if (insn & (1 << i)) {
99c475ab
FB
11647 if (insn & (1 << 11)) {
11648 /* load */
c40c8556 11649 tmp = tcg_temp_new_i32();
12dcc321 11650 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
a7d3970d
PM
11651 if (i == rn) {
11652 loaded_var = tmp;
11653 } else {
11654 store_reg(s, i, tmp);
11655 }
99c475ab
FB
11656 } else {
11657 /* store */
b0109805 11658 tmp = load_reg(s, i);
12dcc321 11659 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
c40c8556 11660 tcg_temp_free_i32(tmp);
99c475ab 11661 }
5899f386 11662 /* advance to the next address */
b0109805 11663 tcg_gen_addi_i32(addr, addr, 4);
99c475ab
FB
11664 }
11665 }
b0109805 11666 if ((insn & (1 << rn)) == 0) {
a7d3970d 11667 /* base reg not in list: base register writeback */
b0109805
PB
11668 store_reg(s, rn, addr);
11669 } else {
a7d3970d
PM
11670 /* base reg in list: if load, complete it now */
11671 if (insn & (1 << 11)) {
11672 store_reg(s, rn, loaded_var);
11673 }
7d1b0095 11674 tcg_temp_free_i32(addr);
b0109805 11675 }
99c475ab 11676 break;
a7d3970d 11677 }
99c475ab
FB
11678 case 13:
11679 /* conditional branch or swi */
11680 cond = (insn >> 8) & 0xf;
11681 if (cond == 0xe)
11682 goto undef;
11683
11684 if (cond == 0xf) {
11685 /* swi */
a0415916 11686 gen_set_pc_im(s, s->base.pc_next);
d4a2dc67 11687 s->svc_imm = extract32(insn, 0, 8);
dcba3a8d 11688 s->base.is_jmp = DISAS_SWI;
99c475ab
FB
11689 break;
11690 }
11691 /* generate a conditional jump to next instruction */
c2d9644e 11692 arm_skip_unless(s, cond);
99c475ab
FB
11693
11694 /* jump to the offset */
fdbcf632 11695 val = read_pc(s);
99c475ab 11696 offset = ((int32_t)insn << 24) >> 24;
5899f386 11697 val += offset << 1;
8aaca4c0 11698 gen_jmp(s, val);
99c475ab
FB
11699 break;
11700
11701 case 14:
358bf29e 11702 if (insn & (1 << 11)) {
296e5a0a
PM
11703 /* thumb_insn_is_16bit() ensures we can't get here for
11704 * a Thumb2 CPU, so this must be a thumb1 split BL/BLX:
11705 * 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF)
11706 */
11707 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
11708 ARCH(5);
11709 offset = ((insn & 0x7ff) << 1);
11710 tmp = load_reg(s, 14);
11711 tcg_gen_addi_i32(tmp, tmp, offset);
11712 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
11713
11714 tmp2 = tcg_temp_new_i32();
a0415916 11715 tcg_gen_movi_i32(tmp2, s->base.pc_next | 1);
296e5a0a
PM
11716 store_reg(s, 14, tmp2);
11717 gen_bx(s, tmp);
358bf29e
PB
11718 break;
11719 }
9ee6e8bb 11720 /* unconditional branch */
fdbcf632 11721 val = read_pc(s);
99c475ab 11722 offset = ((int32_t)insn << 21) >> 21;
fdbcf632 11723 val += offset << 1;
8aaca4c0 11724 gen_jmp(s, val);
99c475ab
FB
11725 break;
11726
11727 case 15:
296e5a0a
PM
11728 /* thumb_insn_is_16bit() ensures we can't get here for
11729 * a Thumb2 CPU, so this must be a thumb1 split BL/BLX.
11730 */
11731 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
11732
11733 if (insn & (1 << 11)) {
11734 /* 0b1111_1xxx_xxxx_xxxx : BL suffix */
11735 offset = ((insn & 0x7ff) << 1) | 1;
11736 tmp = load_reg(s, 14);
11737 tcg_gen_addi_i32(tmp, tmp, offset);
11738
11739 tmp2 = tcg_temp_new_i32();
a0415916 11740 tcg_gen_movi_i32(tmp2, s->base.pc_next | 1);
296e5a0a
PM
11741 store_reg(s, 14, tmp2);
11742 gen_bx(s, tmp);
11743 } else {
11744 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix */
11745 uint32_t uoffset = ((int32_t)insn << 21) >> 9;
11746
fdbcf632 11747 tcg_gen_movi_i32(cpu_R[14], read_pc(s) + uoffset);
296e5a0a 11748 }
9ee6e8bb 11749 break;
99c475ab
FB
11750 }
11751 return;
9ee6e8bb 11752illegal_op:
99c475ab 11753undef:
1ce21ba1 11754 unallocated_encoding(s);
99c475ab
FB
11755}
11756
541ebcd4
PM
11757static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
11758{
a0415916 11759 /* Return true if the insn at dc->base.pc_next might cross a page boundary.
541ebcd4 11760 * (False positives are OK, false negatives are not.)
5b8d7289 11761 * We know this is a Thumb insn, and our caller ensures we are
a0415916 11762 * only called if dc->base.pc_next is less than 4 bytes from the page
5b8d7289
PM
11763 * boundary, so we cross the page if the first 16 bits indicate
11764 * that this is a 32 bit insn.
541ebcd4 11765 */
a0415916 11766 uint16_t insn = arm_lduw_code(env, s->base.pc_next, s->sctlr_b);
541ebcd4 11767
a0415916 11768 return !thumb_insn_is_16bit(s, s->base.pc_next, insn);
541ebcd4
PM
11769}
11770
b542683d 11771static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
2c0262af 11772{
1d8a5535 11773 DisasContext *dc = container_of(dcbase, DisasContext, base);
9c489ea6 11774 CPUARMState *env = cs->env_ptr;
2fc0cc0e 11775 ARMCPU *cpu = env_archcpu(env);
aad821ac
RH
11776 uint32_t tb_flags = dc->base.tb->flags;
11777 uint32_t condexec, core_mmu_idx;
3b46e624 11778
962fcbf2 11779 dc->isar = &cpu->isar;
e50e6a20 11780 dc->condjmp = 0;
3926cc84 11781
40f860cd 11782 dc->aarch64 = 0;
cef9ee70
SS
11783 /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
11784 * there is no secure EL1, so we route exceptions to EL3.
11785 */
11786 dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
11787 !arm_el_is_aa64(env, 3);
aad821ac
RH
11788 dc->thumb = FIELD_EX32(tb_flags, TBFLAG_A32, THUMB);
11789 dc->sctlr_b = FIELD_EX32(tb_flags, TBFLAG_A32, SCTLR_B);
11790 dc->be_data = FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
11791 condexec = FIELD_EX32(tb_flags, TBFLAG_A32, CONDEXEC);
11792 dc->condexec_mask = (condexec & 0xf) << 1;
11793 dc->condexec_cond = condexec >> 4;
11794 core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX);
11795 dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
c1e37810 11796 dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
3926cc84 11797#if !defined(CONFIG_USER_ONLY)
c1e37810 11798 dc->user = (dc->current_el == 0);
3926cc84 11799#endif
aad821ac
RH
11800 dc->ns = FIELD_EX32(tb_flags, TBFLAG_A32, NS);
11801 dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL);
11802 dc->vfp_enabled = FIELD_EX32(tb_flags, TBFLAG_A32, VFPEN);
11803 dc->vec_len = FIELD_EX32(tb_flags, TBFLAG_A32, VECLEN);
ea7ac69d
PM
11804 if (arm_feature(env, ARM_FEATURE_XSCALE)) {
11805 dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
11806 dc->vec_stride = 0;
11807 } else {
11808 dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
11809 dc->c15_cpar = 0;
11810 }
aad821ac 11811 dc->v7m_handler_mode = FIELD_EX32(tb_flags, TBFLAG_A32, HANDLER);
fb602cb7
PM
11812 dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
11813 regime_is_secure(env, dc->mmu_idx);
aad821ac 11814 dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_A32, STACKCHECK);
6d60c67a 11815 dc->v8m_fpccr_s_wrong = FIELD_EX32(tb_flags, TBFLAG_A32, FPCCR_S_WRONG);
6000531e
PM
11816 dc->v7m_new_fp_ctxt_needed =
11817 FIELD_EX32(tb_flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED);
e33cf0f8 11818 dc->v7m_lspact = FIELD_EX32(tb_flags, TBFLAG_A32, LSPACT);
60322b39 11819 dc->cp_regs = cpu->cp_regs;
a984e42c 11820 dc->features = env->features;
40f860cd 11821
50225ad0
PM
11822 /* Single step state. The code-generation logic here is:
11823 * SS_ACTIVE == 0:
11824 * generate code with no special handling for single-stepping (except
11825 * that anything that can make us go to SS_ACTIVE == 1 must end the TB;
11826 * this happens anyway because those changes are all system register or
11827 * PSTATE writes).
11828 * SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
11829 * emit code for one insn
11830 * emit code to clear PSTATE.SS
11831 * emit code to generate software step exception for completed step
11832 * end TB (as usual for having generated an exception)
11833 * SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
11834 * emit code to generate a software step exception
11835 * end the TB
11836 */
aad821ac
RH
11837 dc->ss_active = FIELD_EX32(tb_flags, TBFLAG_ANY, SS_ACTIVE);
11838 dc->pstate_ss = FIELD_EX32(tb_flags, TBFLAG_ANY, PSTATE_SS);
50225ad0 11839 dc->is_ldex = false;
8bd587c1
PM
11840 if (!arm_feature(env, ARM_FEATURE_M)) {
11841 dc->debug_target_el = FIELD_EX32(tb_flags, TBFLAG_ANY, DEBUG_TARGET_EL);
11842 }
50225ad0 11843
bfe7ad5b 11844 dc->page_start = dc->base.pc_first & TARGET_PAGE_MASK;
1d8a5535 11845
f7708456
RH
11846 /* If architectural single step active, limit to 1. */
11847 if (is_singlestepping(dc)) {
b542683d 11848 dc->base.max_insns = 1;
f7708456
RH
11849 }
11850
d0264d86
RH
11851 /* ARM is a fixed-length ISA. Bound the number of insns to execute
11852 to those left on the page. */
11853 if (!dc->thumb) {
bfe7ad5b 11854 int bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
b542683d 11855 dc->base.max_insns = MIN(dc->base.max_insns, bound);
d0264d86
RH
11856 }
11857
d9eea52c
PM
11858 cpu_V0 = tcg_temp_new_i64();
11859 cpu_V1 = tcg_temp_new_i64();
e677137d 11860 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
a7812ae4 11861 cpu_M0 = tcg_temp_new_i64();
1d8a5535
LV
11862}
11863
b1476854
LV
11864static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
11865{
11866 DisasContext *dc = container_of(dcbase, DisasContext, base);
11867
11868 /* A note on handling of the condexec (IT) bits:
11869 *
11870 * We want to avoid the overhead of having to write the updated condexec
11871 * bits back to the CPUARMState for every instruction in an IT block. So:
11872 * (1) if the condexec bits are not already zero then we write
11873 * zero back into the CPUARMState now. This avoids complications trying
11874 * to do it at the end of the block. (For example if we don't do this
11875 * it's hard to identify whether we can safely skip writing condexec
11876 * at the end of the TB, which we definitely want to do for the case
11877 * where a TB doesn't do anything with the IT state at all.)
11878 * (2) if we are going to leave the TB then we call gen_set_condexec()
11879 * which will write the correct value into CPUARMState if zero is wrong.
11880 * This is done both for leaving the TB at the end, and for leaving
11881 * it because of an exception we know will happen, which is done in
11882 * gen_exception_insn(). The latter is necessary because we need to
11883 * leave the TB with the PC/IT state just prior to execution of the
11884 * instruction which caused the exception.
11885 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
11886 * then the CPUARMState will be wrong and we need to reset it.
11887 * This is handled in the same way as restoration of the
11888 * PC in these situations; we save the value of the condexec bits
11889 * for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
11890 * then uses this to restore them after an exception.
11891 *
11892 * Note that there are no instructions which can read the condexec
11893 * bits, and none which can write non-static values to them, so
11894 * we don't need to care about whether CPUARMState is correct in the
11895 * middle of a TB.
11896 */
11897
11898 /* Reset the conditional execution bits immediately. This avoids
11899 complications trying to do it at the end of the block. */
11900 if (dc->condexec_mask || dc->condexec_cond) {
11901 TCGv_i32 tmp = tcg_temp_new_i32();
11902 tcg_gen_movi_i32(tmp, 0);
11903 store_cpu_field(tmp, condexec_bits);
11904 }
11905}
11906
f62bd897
LV
11907static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
11908{
11909 DisasContext *dc = container_of(dcbase, DisasContext, base);
11910
a0415916 11911 tcg_gen_insn_start(dc->base.pc_next,
f62bd897
LV
11912 (dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
11913 0);
15fa08f8 11914 dc->insn_start = tcg_last_op();
f62bd897
LV
11915}
11916
a68956ad
LV
11917static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
11918 const CPUBreakpoint *bp)
11919{
11920 DisasContext *dc = container_of(dcbase, DisasContext, base);
11921
11922 if (bp->flags & BP_CPU) {
11923 gen_set_condexec(dc);
a0415916 11924 gen_set_pc_im(dc, dc->base.pc_next);
a68956ad
LV
11925 gen_helper_check_breakpoints(cpu_env);
11926 /* End the TB early; it's likely not going to be executed */
11927 dc->base.is_jmp = DISAS_TOO_MANY;
11928 } else {
aee828e7 11929 gen_exception_internal_insn(dc, dc->base.pc_next, EXCP_DEBUG);
a68956ad
LV
11930 /* The address covered by the breakpoint must be
11931 included in [tb->pc, tb->pc + tb->size) in order
11932 to for it to be properly cleared -- thus we
11933 increment the PC here so that the logic setting
11934 tb->size below does the right thing. */
11935 /* TODO: Advance PC by correct instruction length to
11936 * avoid disassembler error messages */
a0415916 11937 dc->base.pc_next += 2;
a68956ad
LV
11938 dc->base.is_jmp = DISAS_NORETURN;
11939 }
11940
11941 return true;
11942}
11943
722ef0a5 11944static bool arm_pre_translate_insn(DisasContext *dc)
13189a90 11945{
13189a90
LV
11946#ifdef CONFIG_USER_ONLY
11947 /* Intercept jump to the magic kernel page. */
a0415916 11948 if (dc->base.pc_next >= 0xffff0000) {
13189a90
LV
11949 /* We always get here via a jump, so know we are not in a
11950 conditional execution block. */
11951 gen_exception_internal(EXCP_KERNEL_TRAP);
11952 dc->base.is_jmp = DISAS_NORETURN;
722ef0a5 11953 return true;
13189a90
LV
11954 }
11955#endif
11956
11957 if (dc->ss_active && !dc->pstate_ss) {
11958 /* Singlestep state is Active-pending.
11959 * If we're in this state at the start of a TB then either
11960 * a) we just took an exception to an EL which is being debugged
11961 * and this is the first insn in the exception handler
11962 * b) debug exceptions were masked and we just unmasked them
11963 * without changing EL (eg by clearing PSTATE.D)
11964 * In either case we're going to take a swstep exception in the
11965 * "did not step an insn" case, and so the syndrome ISV and EX
11966 * bits should be zero.
11967 */
11968 assert(dc->base.num_insns == 1);
c1d5f50f 11969 gen_swstep_exception(dc, 0, 0);
13189a90 11970 dc->base.is_jmp = DISAS_NORETURN;
722ef0a5 11971 return true;
13189a90
LV
11972 }
11973
722ef0a5
RH
11974 return false;
11975}
13189a90 11976
d0264d86 11977static void arm_post_translate_insn(DisasContext *dc)
722ef0a5 11978{
13189a90
LV
11979 if (dc->condjmp && !dc->base.is_jmp) {
11980 gen_set_label(dc->condlabel);
11981 dc->condjmp = 0;
11982 }
23169224 11983 translator_loop_temp_check(&dc->base);
13189a90
LV
11984}
11985
722ef0a5
RH
11986static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
11987{
11988 DisasContext *dc = container_of(dcbase, DisasContext, base);
11989 CPUARMState *env = cpu->env_ptr;
11990 unsigned int insn;
11991
11992 if (arm_pre_translate_insn(dc)) {
11993 return;
11994 }
11995
a0415916
RH
11996 dc->pc_curr = dc->base.pc_next;
11997 insn = arm_ldl_code(env, dc->base.pc_next, dc->sctlr_b);
58803318 11998 dc->insn = insn;
a0415916 11999 dc->base.pc_next += 4;
722ef0a5
RH
12000 disas_arm_insn(dc, insn);
12001
d0264d86
RH
12002 arm_post_translate_insn(dc);
12003
12004 /* ARM is a fixed-length ISA. We performed the cross-page check
12005 in init_disas_context by adjusting max_insns. */
722ef0a5
RH
12006}
12007
dcf14dfb
PM
12008static bool thumb_insn_is_unconditional(DisasContext *s, uint32_t insn)
12009{
12010 /* Return true if this Thumb insn is always unconditional,
12011 * even inside an IT block. This is true of only a very few
12012 * instructions: BKPT, HLT, and SG.
12013 *
12014 * A larger class of instructions are UNPREDICTABLE if used
12015 * inside an IT block; we do not need to detect those here, because
12016 * what we do by default (perform the cc check and update the IT
12017 * bits state machine) is a permitted CONSTRAINED UNPREDICTABLE
12018 * choice for those situations.
12019 *
12020 * insn is either a 16-bit or a 32-bit instruction; the two are
12021 * distinguishable because for the 16-bit case the top 16 bits
12022 * are zeroes, and that isn't a valid 32-bit encoding.
12023 */
12024 if ((insn & 0xffffff00) == 0xbe00) {
12025 /* BKPT */
12026 return true;
12027 }
12028
12029 if ((insn & 0xffffffc0) == 0xba80 && arm_dc_feature(s, ARM_FEATURE_V8) &&
12030 !arm_dc_feature(s, ARM_FEATURE_M)) {
12031 /* HLT: v8A only. This is unconditional even when it is going to
12032 * UNDEF; see the v8A ARM ARM DDI0487B.a H3.3.
12033 * For v7 cores this was a plain old undefined encoding and so
12034 * honours its cc check. (We might be using the encoding as
12035 * a semihosting trap, but we don't change the cc check behaviour
12036 * on that account, because a debugger connected to a real v7A
12037 * core and emulating semihosting traps by catching the UNDEF
12038 * exception would also only see cases where the cc check passed.
12039 * No guest code should be trying to do a HLT semihosting trap
12040 * in an IT block anyway.
12041 */
12042 return true;
12043 }
12044
12045 if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_V8) &&
12046 arm_dc_feature(s, ARM_FEATURE_M)) {
12047 /* SG: v8M only */
12048 return true;
12049 }
12050
12051 return false;
12052}
12053
722ef0a5
RH
12054static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
12055{
12056 DisasContext *dc = container_of(dcbase, DisasContext, base);
12057 CPUARMState *env = cpu->env_ptr;
296e5a0a
PM
12058 uint32_t insn;
12059 bool is_16bit;
722ef0a5
RH
12060
12061 if (arm_pre_translate_insn(dc)) {
12062 return;
12063 }
12064
a0415916
RH
12065 dc->pc_curr = dc->base.pc_next;
12066 insn = arm_lduw_code(env, dc->base.pc_next, dc->sctlr_b);
12067 is_16bit = thumb_insn_is_16bit(dc, dc->base.pc_next, insn);
12068 dc->base.pc_next += 2;
296e5a0a 12069 if (!is_16bit) {
a0415916 12070 uint32_t insn2 = arm_lduw_code(env, dc->base.pc_next, dc->sctlr_b);
296e5a0a
PM
12071
12072 insn = insn << 16 | insn2;
a0415916 12073 dc->base.pc_next += 2;
296e5a0a 12074 }
58803318 12075 dc->insn = insn;
296e5a0a 12076
dcf14dfb 12077 if (dc->condexec_mask && !thumb_insn_is_unconditional(dc, insn)) {
296e5a0a
PM
12078 uint32_t cond = dc->condexec_cond;
12079
5529de1e
PM
12080 /*
12081 * Conditionally skip the insn. Note that both 0xe and 0xf mean
12082 * "always"; 0xf is not "never".
12083 */
12084 if (cond < 0x0e) {
c2d9644e 12085 arm_skip_unless(dc, cond);
296e5a0a
PM
12086 }
12087 }
12088
12089 if (is_16bit) {
12090 disas_thumb_insn(dc, insn);
12091 } else {
2eea841c 12092 disas_thumb2_insn(dc, insn);
296e5a0a 12093 }
722ef0a5
RH
12094
12095 /* Advance the Thumb condexec condition. */
12096 if (dc->condexec_mask) {
12097 dc->condexec_cond = ((dc->condexec_cond & 0xe) |
12098 ((dc->condexec_mask >> 4) & 1));
12099 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
12100 if (dc->condexec_mask == 0) {
12101 dc->condexec_cond = 0;
12102 }
12103 }
12104
d0264d86
RH
12105 arm_post_translate_insn(dc);
12106
12107 /* Thumb is a variable-length ISA. Stop translation when the next insn
12108 * will touch a new page. This ensures that prefetch aborts occur at
12109 * the right place.
12110 *
12111 * We want to stop the TB if the next insn starts in a new page,
12112 * or if it spans between this page and the next. This means that
12113 * if we're looking at the last halfword in the page we need to
12114 * see if it's a 16-bit Thumb insn (which will fit in this TB)
12115 * or a 32-bit Thumb insn (which won't).
12116 * This is to avoid generating a silly TB with a single 16-bit insn
12117 * in it at the end of this page (which would execute correctly
12118 * but isn't very efficient).
12119 */
12120 if (dc->base.is_jmp == DISAS_NEXT
a0415916
RH
12121 && (dc->base.pc_next - dc->page_start >= TARGET_PAGE_SIZE
12122 || (dc->base.pc_next - dc->page_start >= TARGET_PAGE_SIZE - 3
d0264d86
RH
12123 && insn_crosses_page(env, dc)))) {
12124 dc->base.is_jmp = DISAS_TOO_MANY;
12125 }
722ef0a5
RH
12126}
12127
70d3c035 12128static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
1d8a5535 12129{
70d3c035 12130 DisasContext *dc = container_of(dcbase, DisasContext, base);
2e70f6ef 12131
c5a49c63 12132 if (tb_cflags(dc->base.tb) & CF_LAST_IO && dc->condjmp) {
70d3c035
LV
12133 /* FIXME: This can theoretically happen with self-modifying code. */
12134 cpu_abort(cpu, "IO on conditional branch instruction");
2e70f6ef 12135 }
9ee6e8bb 12136
b5ff1b31 12137 /* At this stage dc->condjmp will only be set when the skipped
9ee6e8bb
PB
12138 instruction was a conditional branch or trap, and the PC has
12139 already been written. */
f021b2c4 12140 gen_set_condexec(dc);
dcba3a8d 12141 if (dc->base.is_jmp == DISAS_BX_EXCRET) {
3bb8a96f
PM
12142 /* Exception return branches need some special case code at the
12143 * end of the TB, which is complex enough that it has to
12144 * handle the single-step vs not and the condition-failed
12145 * insn codepath itself.
12146 */
12147 gen_bx_excret_final_code(dc);
12148 } else if (unlikely(is_singlestepping(dc))) {
7999a5c8 12149 /* Unconditional and "condition passed" instruction codepath. */
dcba3a8d 12150 switch (dc->base.is_jmp) {
7999a5c8 12151 case DISAS_SWI:
50225ad0 12152 gen_ss_advance(dc);
73710361
GB
12153 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
12154 default_exception_el(dc));
7999a5c8
SF
12155 break;
12156 case DISAS_HVC:
37e6456e 12157 gen_ss_advance(dc);
73710361 12158 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
7999a5c8
SF
12159 break;
12160 case DISAS_SMC:
37e6456e 12161 gen_ss_advance(dc);
73710361 12162 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
7999a5c8
SF
12163 break;
12164 case DISAS_NEXT:
a68956ad 12165 case DISAS_TOO_MANY:
7999a5c8 12166 case DISAS_UPDATE:
a0415916 12167 gen_set_pc_im(dc, dc->base.pc_next);
7999a5c8
SF
12168 /* fall through */
12169 default:
5425415e
PM
12170 /* FIXME: Single stepping a WFI insn will not halt the CPU. */
12171 gen_singlestep_exception(dc);
a0c231e6
RH
12172 break;
12173 case DISAS_NORETURN:
12174 break;
7999a5c8 12175 }
8aaca4c0 12176 } else {
9ee6e8bb
PB
12177 /* While branches must always occur at the end of an IT block,
12178 there are a few other things that can cause us to terminate
65626741 12179 the TB in the middle of an IT block:
9ee6e8bb
PB
12180 - Exception generating instructions (bkpt, swi, undefined).
12181 - Page boundaries.
12182 - Hardware watchpoints.
12183 Hardware breakpoints have already been handled and skip this code.
12184 */
dcba3a8d 12185 switch(dc->base.is_jmp) {
8aaca4c0 12186 case DISAS_NEXT:
a68956ad 12187 case DISAS_TOO_MANY:
a0415916 12188 gen_goto_tb(dc, 1, dc->base.pc_next);
8aaca4c0 12189 break;
577bf808 12190 case DISAS_JUMP:
8a6b28c7
EC
12191 gen_goto_ptr();
12192 break;
e8d52302 12193 case DISAS_UPDATE:
a0415916 12194 gen_set_pc_im(dc, dc->base.pc_next);
e8d52302 12195 /* fall through */
577bf808 12196 default:
8aaca4c0 12197 /* indicate that the hash table must be used to find the next TB */
07ea28b4 12198 tcg_gen_exit_tb(NULL, 0);
8aaca4c0 12199 break;
a0c231e6 12200 case DISAS_NORETURN:
8aaca4c0
FB
12201 /* nothing more to generate */
12202 break;
9ee6e8bb 12203 case DISAS_WFI:
58803318
SS
12204 {
12205 TCGv_i32 tmp = tcg_const_i32((dc->thumb &&
12206 !(dc->insn & (1U << 31))) ? 2 : 4);
12207
12208 gen_helper_wfi(cpu_env, tmp);
12209 tcg_temp_free_i32(tmp);
84549b6d
PM
12210 /* The helper doesn't necessarily throw an exception, but we
12211 * must go back to the main loop to check for interrupts anyway.
12212 */
07ea28b4 12213 tcg_gen_exit_tb(NULL, 0);
9ee6e8bb 12214 break;
58803318 12215 }
72c1d3af
PM
12216 case DISAS_WFE:
12217 gen_helper_wfe(cpu_env);
12218 break;
c87e5a61
PM
12219 case DISAS_YIELD:
12220 gen_helper_yield(cpu_env);
12221 break;
9ee6e8bb 12222 case DISAS_SWI:
73710361
GB
12223 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
12224 default_exception_el(dc));
9ee6e8bb 12225 break;
37e6456e 12226 case DISAS_HVC:
73710361 12227 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
37e6456e
PM
12228 break;
12229 case DISAS_SMC:
73710361 12230 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
37e6456e 12231 break;
8aaca4c0 12232 }
f021b2c4
PM
12233 }
12234
12235 if (dc->condjmp) {
12236 /* "Condition failed" instruction codepath for the branch/trap insn */
12237 gen_set_label(dc->condlabel);
12238 gen_set_condexec(dc);
b636649f 12239 if (unlikely(is_singlestepping(dc))) {
a0415916 12240 gen_set_pc_im(dc, dc->base.pc_next);
f021b2c4
PM
12241 gen_singlestep_exception(dc);
12242 } else {
a0415916 12243 gen_goto_tb(dc, 1, dc->base.pc_next);
e50e6a20 12244 }
2c0262af 12245 }
70d3c035
LV
12246}
12247
4013f7fc
LV
12248static void arm_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
12249{
12250 DisasContext *dc = container_of(dcbase, DisasContext, base);
12251
12252 qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
1d48474d 12253 log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
4013f7fc
LV
12254}
12255
23169224
LV
12256static const TranslatorOps arm_translator_ops = {
12257 .init_disas_context = arm_tr_init_disas_context,
12258 .tb_start = arm_tr_tb_start,
12259 .insn_start = arm_tr_insn_start,
12260 .breakpoint_check = arm_tr_breakpoint_check,
12261 .translate_insn = arm_tr_translate_insn,
12262 .tb_stop = arm_tr_tb_stop,
12263 .disas_log = arm_tr_disas_log,
12264};
12265
722ef0a5
RH
12266static const TranslatorOps thumb_translator_ops = {
12267 .init_disas_context = arm_tr_init_disas_context,
12268 .tb_start = arm_tr_tb_start,
12269 .insn_start = arm_tr_insn_start,
12270 .breakpoint_check = arm_tr_breakpoint_check,
12271 .translate_insn = thumb_tr_translate_insn,
12272 .tb_stop = arm_tr_tb_stop,
12273 .disas_log = arm_tr_disas_log,
12274};
12275
70d3c035 12276/* generate intermediate code for basic block 'tb'. */
8b86d6d2 12277void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
70d3c035 12278{
23169224
LV
12279 DisasContext dc;
12280 const TranslatorOps *ops = &arm_translator_ops;
70d3c035 12281
aad821ac 12282 if (FIELD_EX32(tb->flags, TBFLAG_A32, THUMB)) {
722ef0a5
RH
12283 ops = &thumb_translator_ops;
12284 }
23169224 12285#ifdef TARGET_AARCH64
aad821ac 12286 if (FIELD_EX32(tb->flags, TBFLAG_ANY, AARCH64_STATE)) {
23169224 12287 ops = &aarch64_translator_ops;
2c0262af
FB
12288 }
12289#endif
23169224 12290
8b86d6d2 12291 translator_loop(ops, &dc.base, cpu, tb, max_insns);
2c0262af
FB
12292}
12293
bad729e2
RH
12294void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
12295 target_ulong *data)
d2856f1a 12296{
3926cc84 12297 if (is_a64(env)) {
bad729e2 12298 env->pc = data[0];
40f860cd 12299 env->condexec_bits = 0;
aaa1f954 12300 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
3926cc84 12301 } else {
bad729e2
RH
12302 env->regs[15] = data[0];
12303 env->condexec_bits = data[1];
aaa1f954 12304 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
3926cc84 12305 }
d2856f1a 12306}