]> git.proxmox.com Git - mirror_qemu.git/blame - target/arm/translate.c
target/arm: Convert T16 add, compare, move (two high registers)
[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. */
46497f6a 358static void gen_rev16(TCGv_i32 dest, 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);
46497f6a 366 tcg_gen_or_i32(dest, 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. */
46497f6a 372static void gen_revsh(TCGv_i32 dest, TCGv_i32 var)
3670669c 373{
1a855029
AJ
374 tcg_gen_ext16u_i32(var, var);
375 tcg_gen_bswap16_i32(var, var);
46497f6a 376 tcg_gen_ext16s_i32(dest, 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
46497f6a 429static void gen_add16(TCGv_i32 dest, 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);
46497f6a 437 tcg_gen_xor_i32(dest, t0, tmp);
7d1b0095 438 tcg_temp_free_i32(tmp);
b26eefb6
PB
439}
440
b26eefb6 441/* Set N and Z flags from var. */
39d5492a 442static inline void gen_logic_CC(TCGv_i32 var)
b26eefb6 443{
66c374de
AJ
444 tcg_gen_mov_i32(cpu_NF, var);
445 tcg_gen_mov_i32(cpu_ZF, var);
b26eefb6
PB
446}
447
e9bb4aa9 448/* dest = T0 + T1 + CF. */
39d5492a 449static void gen_add_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
e9bb4aa9 450{
e9bb4aa9 451 tcg_gen_add_i32(dest, t0, t1);
66c374de 452 tcg_gen_add_i32(dest, dest, cpu_CF);
e9bb4aa9
JR
453}
454
3670669c 455/* dest = T0 - T1 + CF - 1. */
39d5492a 456static void gen_sub_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
3670669c 457{
3670669c 458 tcg_gen_sub_i32(dest, t0, t1);
66c374de 459 tcg_gen_add_i32(dest, dest, cpu_CF);
3670669c 460 tcg_gen_subi_i32(dest, dest, 1);
3670669c
PB
461}
462
72485ec4 463/* dest = T0 + T1. Compute C, N, V and Z flags */
39d5492a 464static void gen_add_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
72485ec4 465{
39d5492a 466 TCGv_i32 tmp = tcg_temp_new_i32();
e3482cb8
RH
467 tcg_gen_movi_i32(tmp, 0);
468 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, t1, tmp);
72485ec4 469 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
72485ec4 470 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
72485ec4
AJ
471 tcg_gen_xor_i32(tmp, t0, t1);
472 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
473 tcg_temp_free_i32(tmp);
474 tcg_gen_mov_i32(dest, cpu_NF);
475}
476
49b4c31e 477/* dest = T0 + T1 + CF. Compute C, N, V and Z flags */
39d5492a 478static void gen_adc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
49b4c31e 479{
39d5492a 480 TCGv_i32 tmp = tcg_temp_new_i32();
49b4c31e
RH
481 if (TCG_TARGET_HAS_add2_i32) {
482 tcg_gen_movi_i32(tmp, 0);
483 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp);
8c3ac601 484 tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1, tmp);
49b4c31e
RH
485 } else {
486 TCGv_i64 q0 = tcg_temp_new_i64();
487 TCGv_i64 q1 = tcg_temp_new_i64();
488 tcg_gen_extu_i32_i64(q0, t0);
489 tcg_gen_extu_i32_i64(q1, t1);
490 tcg_gen_add_i64(q0, q0, q1);
491 tcg_gen_extu_i32_i64(q1, cpu_CF);
492 tcg_gen_add_i64(q0, q0, q1);
493 tcg_gen_extr_i64_i32(cpu_NF, cpu_CF, q0);
494 tcg_temp_free_i64(q0);
495 tcg_temp_free_i64(q1);
496 }
497 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
498 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
499 tcg_gen_xor_i32(tmp, t0, t1);
500 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
501 tcg_temp_free_i32(tmp);
502 tcg_gen_mov_i32(dest, cpu_NF);
503}
504
72485ec4 505/* dest = T0 - T1. Compute C, N, V and Z flags */
39d5492a 506static void gen_sub_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
72485ec4 507{
39d5492a 508 TCGv_i32 tmp;
72485ec4
AJ
509 tcg_gen_sub_i32(cpu_NF, t0, t1);
510 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
511 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0, t1);
512 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
513 tmp = tcg_temp_new_i32();
514 tcg_gen_xor_i32(tmp, t0, t1);
515 tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
516 tcg_temp_free_i32(tmp);
517 tcg_gen_mov_i32(dest, cpu_NF);
518}
519
e77f0832 520/* dest = T0 + ~T1 + CF. Compute C, N, V and Z flags */
39d5492a 521static void gen_sbc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
2de68a49 522{
39d5492a 523 TCGv_i32 tmp = tcg_temp_new_i32();
e77f0832
RH
524 tcg_gen_not_i32(tmp, t1);
525 gen_adc_CC(dest, t0, tmp);
39d5492a 526 tcg_temp_free_i32(tmp);
2de68a49
RH
527}
528
365af80e 529#define GEN_SHIFT(name) \
39d5492a 530static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \
365af80e 531{ \
39d5492a 532 TCGv_i32 tmp1, tmp2, tmp3; \
365af80e
AJ
533 tmp1 = tcg_temp_new_i32(); \
534 tcg_gen_andi_i32(tmp1, t1, 0xff); \
535 tmp2 = tcg_const_i32(0); \
536 tmp3 = tcg_const_i32(0x1f); \
537 tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
538 tcg_temp_free_i32(tmp3); \
539 tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
540 tcg_gen_##name##_i32(dest, tmp2, tmp1); \
541 tcg_temp_free_i32(tmp2); \
542 tcg_temp_free_i32(tmp1); \
543}
544GEN_SHIFT(shl)
545GEN_SHIFT(shr)
546#undef GEN_SHIFT
547
39d5492a 548static void gen_sar(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
365af80e 549{
39d5492a 550 TCGv_i32 tmp1, tmp2;
365af80e
AJ
551 tmp1 = tcg_temp_new_i32();
552 tcg_gen_andi_i32(tmp1, t1, 0xff);
553 tmp2 = tcg_const_i32(0x1f);
554 tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1);
555 tcg_temp_free_i32(tmp2);
556 tcg_gen_sar_i32(dest, t0, tmp1);
557 tcg_temp_free_i32(tmp1);
558}
559
39d5492a 560static void shifter_out_im(TCGv_i32 var, int shift)
b26eefb6 561{
191f4bfe 562 tcg_gen_extract_i32(cpu_CF, var, shift, 1);
9a119ff6 563}
b26eefb6 564
9a119ff6 565/* Shift by immediate. Includes special handling for shift == 0. */
39d5492a
PM
566static inline void gen_arm_shift_im(TCGv_i32 var, int shiftop,
567 int shift, int flags)
9a119ff6
PB
568{
569 switch (shiftop) {
570 case 0: /* LSL */
571 if (shift != 0) {
572 if (flags)
573 shifter_out_im(var, 32 - shift);
574 tcg_gen_shli_i32(var, var, shift);
575 }
576 break;
577 case 1: /* LSR */
578 if (shift == 0) {
579 if (flags) {
66c374de 580 tcg_gen_shri_i32(cpu_CF, var, 31);
9a119ff6
PB
581 }
582 tcg_gen_movi_i32(var, 0);
583 } else {
584 if (flags)
585 shifter_out_im(var, shift - 1);
586 tcg_gen_shri_i32(var, var, shift);
587 }
588 break;
589 case 2: /* ASR */
590 if (shift == 0)
591 shift = 32;
592 if (flags)
593 shifter_out_im(var, shift - 1);
594 if (shift == 32)
595 shift = 31;
596 tcg_gen_sari_i32(var, var, shift);
597 break;
598 case 3: /* ROR/RRX */
599 if (shift != 0) {
600 if (flags)
601 shifter_out_im(var, shift - 1);
f669df27 602 tcg_gen_rotri_i32(var, var, shift); break;
9a119ff6 603 } else {
39d5492a 604 TCGv_i32 tmp = tcg_temp_new_i32();
b6348f29 605 tcg_gen_shli_i32(tmp, cpu_CF, 31);
9a119ff6
PB
606 if (flags)
607 shifter_out_im(var, 0);
608 tcg_gen_shri_i32(var, var, 1);
b26eefb6 609 tcg_gen_or_i32(var, var, tmp);
7d1b0095 610 tcg_temp_free_i32(tmp);
b26eefb6
PB
611 }
612 }
613};
614
39d5492a
PM
615static inline void gen_arm_shift_reg(TCGv_i32 var, int shiftop,
616 TCGv_i32 shift, int flags)
8984bd2e
PB
617{
618 if (flags) {
619 switch (shiftop) {
9ef39277
BS
620 case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break;
621 case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break;
622 case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break;
623 case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break;
8984bd2e
PB
624 }
625 } else {
626 switch (shiftop) {
365af80e
AJ
627 case 0:
628 gen_shl(var, var, shift);
629 break;
630 case 1:
631 gen_shr(var, var, shift);
632 break;
633 case 2:
634 gen_sar(var, var, shift);
635 break;
f669df27
AJ
636 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
637 tcg_gen_rotr_i32(var, var, shift); break;
8984bd2e
PB
638 }
639 }
7d1b0095 640 tcg_temp_free_i32(shift);
8984bd2e
PB
641}
642
39fb730a 643/*
6c2c63d3 644 * Generate a conditional based on ARM condition code cc.
39fb730a
AG
645 * This is common between ARM and Aarch64 targets.
646 */
6c2c63d3 647void arm_test_cc(DisasCompare *cmp, int cc)
d9ba4830 648{
6c2c63d3
RH
649 TCGv_i32 value;
650 TCGCond cond;
651 bool global = true;
d9ba4830 652
d9ba4830
PB
653 switch (cc) {
654 case 0: /* eq: Z */
d9ba4830 655 case 1: /* ne: !Z */
6c2c63d3
RH
656 cond = TCG_COND_EQ;
657 value = cpu_ZF;
d9ba4830 658 break;
6c2c63d3 659
d9ba4830 660 case 2: /* cs: C */
d9ba4830 661 case 3: /* cc: !C */
6c2c63d3
RH
662 cond = TCG_COND_NE;
663 value = cpu_CF;
d9ba4830 664 break;
6c2c63d3 665
d9ba4830 666 case 4: /* mi: N */
d9ba4830 667 case 5: /* pl: !N */
6c2c63d3
RH
668 cond = TCG_COND_LT;
669 value = cpu_NF;
d9ba4830 670 break;
6c2c63d3 671
d9ba4830 672 case 6: /* vs: V */
d9ba4830 673 case 7: /* vc: !V */
6c2c63d3
RH
674 cond = TCG_COND_LT;
675 value = cpu_VF;
d9ba4830 676 break;
6c2c63d3 677
d9ba4830 678 case 8: /* hi: C && !Z */
6c2c63d3
RH
679 case 9: /* ls: !C || Z -> !(C && !Z) */
680 cond = TCG_COND_NE;
681 value = tcg_temp_new_i32();
682 global = false;
683 /* CF is 1 for C, so -CF is an all-bits-set mask for C;
684 ZF is non-zero for !Z; so AND the two subexpressions. */
685 tcg_gen_neg_i32(value, cpu_CF);
686 tcg_gen_and_i32(value, value, cpu_ZF);
d9ba4830 687 break;
6c2c63d3 688
d9ba4830 689 case 10: /* ge: N == V -> N ^ V == 0 */
d9ba4830 690 case 11: /* lt: N != V -> N ^ V != 0 */
6c2c63d3
RH
691 /* Since we're only interested in the sign bit, == 0 is >= 0. */
692 cond = TCG_COND_GE;
693 value = tcg_temp_new_i32();
694 global = false;
695 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
d9ba4830 696 break;
6c2c63d3 697
d9ba4830 698 case 12: /* gt: !Z && N == V */
d9ba4830 699 case 13: /* le: Z || N != V */
6c2c63d3
RH
700 cond = TCG_COND_NE;
701 value = tcg_temp_new_i32();
702 global = false;
703 /* (N == V) is equal to the sign bit of ~(NF ^ VF). Propagate
704 * the sign bit then AND with ZF to yield the result. */
705 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
706 tcg_gen_sari_i32(value, value, 31);
707 tcg_gen_andc_i32(value, cpu_ZF, value);
d9ba4830 708 break;
6c2c63d3 709
9305eac0
RH
710 case 14: /* always */
711 case 15: /* always */
712 /* Use the ALWAYS condition, which will fold early.
713 * It doesn't matter what we use for the value. */
714 cond = TCG_COND_ALWAYS;
715 value = cpu_ZF;
716 goto no_invert;
717
d9ba4830
PB
718 default:
719 fprintf(stderr, "Bad condition code 0x%x\n", cc);
720 abort();
721 }
6c2c63d3
RH
722
723 if (cc & 1) {
724 cond = tcg_invert_cond(cond);
725 }
726
9305eac0 727 no_invert:
6c2c63d3
RH
728 cmp->cond = cond;
729 cmp->value = value;
730 cmp->value_global = global;
731}
732
733void arm_free_cc(DisasCompare *cmp)
734{
735 if (!cmp->value_global) {
736 tcg_temp_free_i32(cmp->value);
737 }
738}
739
740void arm_jump_cc(DisasCompare *cmp, TCGLabel *label)
741{
742 tcg_gen_brcondi_i32(cmp->cond, cmp->value, 0, label);
743}
744
745void arm_gen_test_cc(int cc, TCGLabel *label)
746{
747 DisasCompare cmp;
748 arm_test_cc(&cmp, cc);
749 arm_jump_cc(&cmp, label);
750 arm_free_cc(&cmp);
d9ba4830 751}
2c0262af 752
4d5e8c96
PM
753static inline void gen_set_condexec(DisasContext *s)
754{
755 if (s->condexec_mask) {
756 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
757 TCGv_i32 tmp = tcg_temp_new_i32();
758 tcg_gen_movi_i32(tmp, val);
759 store_cpu_field(tmp, condexec_bits);
760 }
761}
762
763static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
764{
765 tcg_gen_movi_i32(cpu_R[15], val);
766}
767
d9ba4830
PB
768/* Set PC and Thumb state from an immediate address. */
769static inline void gen_bx_im(DisasContext *s, uint32_t addr)
99c475ab 770{
39d5492a 771 TCGv_i32 tmp;
99c475ab 772
dcba3a8d 773 s->base.is_jmp = DISAS_JUMP;
d9ba4830 774 if (s->thumb != (addr & 1)) {
7d1b0095 775 tmp = tcg_temp_new_i32();
d9ba4830 776 tcg_gen_movi_i32(tmp, addr & 1);
0ecb72a5 777 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, thumb));
7d1b0095 778 tcg_temp_free_i32(tmp);
d9ba4830 779 }
155c3eac 780 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
d9ba4830
PB
781}
782
783/* Set PC and Thumb state from var. var is marked as dead. */
39d5492a 784static inline void gen_bx(DisasContext *s, TCGv_i32 var)
d9ba4830 785{
dcba3a8d 786 s->base.is_jmp = DISAS_JUMP;
155c3eac
FN
787 tcg_gen_andi_i32(cpu_R[15], var, ~1);
788 tcg_gen_andi_i32(var, var, 1);
789 store_cpu_field(var, thumb);
d9ba4830
PB
790}
791
5e5584c8
PM
792/*
793 * Set PC and Thumb state from var. var is marked as dead.
3bb8a96f
PM
794 * For M-profile CPUs, include logic to detect exception-return
795 * branches and handle them. This is needed for Thumb POP/LDM to PC, LDR to PC,
796 * and BX reg, and no others, and happens only for code in Handler mode.
5e5584c8
PM
797 * The Security Extension also requires us to check for the FNC_RETURN
798 * which signals a function return from non-secure state; this can happen
799 * in both Handler and Thread mode.
800 * To avoid having to do multiple comparisons in inline generated code,
801 * we make the check we do here loose, so it will match for EXC_RETURN
802 * in Thread mode. For system emulation do_v7m_exception_exit() checks
803 * for these spurious cases and returns without doing anything (giving
804 * the same behaviour as for a branch to a non-magic address).
805 *
806 * In linux-user mode it is unclear what the right behaviour for an
807 * attempted FNC_RETURN should be, because in real hardware this will go
808 * directly to Secure code (ie not the Linux kernel) which will then treat
809 * the error in any way it chooses. For QEMU we opt to make the FNC_RETURN
810 * attempt behave the way it would on a CPU without the security extension,
811 * which is to say "like a normal branch". That means we can simply treat
812 * all branches as normal with no magic address behaviour.
3bb8a96f
PM
813 */
814static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var)
815{
816 /* Generate the same code here as for a simple bx, but flag via
dcba3a8d 817 * s->base.is_jmp that we need to do the rest of the work later.
3bb8a96f
PM
818 */
819 gen_bx(s, var);
5e5584c8 820#ifndef CONFIG_USER_ONLY
d02a8698
PM
821 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY) ||
822 (s->v7m_handler_mode && arm_dc_feature(s, ARM_FEATURE_M))) {
dcba3a8d 823 s->base.is_jmp = DISAS_BX_EXCRET;
3bb8a96f 824 }
5e5584c8 825#endif
3bb8a96f
PM
826}
827
828static inline void gen_bx_excret_final_code(DisasContext *s)
829{
830 /* Generate the code to finish possible exception return and end the TB */
831 TCGLabel *excret_label = gen_new_label();
d02a8698
PM
832 uint32_t min_magic;
833
834 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY)) {
835 /* Covers FNC_RETURN and EXC_RETURN magic */
836 min_magic = FNC_RETURN_MIN_MAGIC;
837 } else {
838 /* EXC_RETURN magic only */
839 min_magic = EXC_RETURN_MIN_MAGIC;
840 }
3bb8a96f
PM
841
842 /* Is the new PC value in the magic range indicating exception return? */
d02a8698 843 tcg_gen_brcondi_i32(TCG_COND_GEU, cpu_R[15], min_magic, excret_label);
3bb8a96f
PM
844 /* No: end the TB as we would for a DISAS_JMP */
845 if (is_singlestepping(s)) {
846 gen_singlestep_exception(s);
847 } else {
07ea28b4 848 tcg_gen_exit_tb(NULL, 0);
3bb8a96f
PM
849 }
850 gen_set_label(excret_label);
851 /* Yes: this is an exception return.
852 * At this point in runtime env->regs[15] and env->thumb will hold
853 * the exception-return magic number, which do_v7m_exception_exit()
854 * will read. Nothing else will be able to see those values because
855 * the cpu-exec main loop guarantees that we will always go straight
856 * from raising the exception to the exception-handling code.
857 *
858 * gen_ss_advance(s) does nothing on M profile currently but
859 * calling it is conceptually the right thing as we have executed
860 * this instruction (compare SWI, HVC, SMC handling).
861 */
862 gen_ss_advance(s);
863 gen_exception_internal(EXCP_EXCEPTION_EXIT);
864}
865
fb602cb7
PM
866static inline void gen_bxns(DisasContext *s, int rm)
867{
868 TCGv_i32 var = load_reg(s, rm);
869
870 /* The bxns helper may raise an EXCEPTION_EXIT exception, so in theory
871 * we need to sync state before calling it, but:
872 * - we don't need to do gen_set_pc_im() because the bxns helper will
873 * always set the PC itself
874 * - we don't need to do gen_set_condexec() because BXNS is UNPREDICTABLE
875 * unless it's outside an IT block or the last insn in an IT block,
876 * so we know that condexec == 0 (already set at the top of the TB)
877 * is correct in the non-UNPREDICTABLE cases, and we can choose
878 * "zeroes the IT bits" as our UNPREDICTABLE behaviour otherwise.
879 */
880 gen_helper_v7m_bxns(cpu_env, var);
881 tcg_temp_free_i32(var);
ef475b5d 882 s->base.is_jmp = DISAS_EXIT;
fb602cb7
PM
883}
884
3e3fa230
PM
885static inline void gen_blxns(DisasContext *s, int rm)
886{
887 TCGv_i32 var = load_reg(s, rm);
888
889 /* We don't need to sync condexec state, for the same reason as bxns.
890 * We do however need to set the PC, because the blxns helper reads it.
891 * The blxns helper may throw an exception.
892 */
a0415916 893 gen_set_pc_im(s, s->base.pc_next);
3e3fa230
PM
894 gen_helper_v7m_blxns(cpu_env, var);
895 tcg_temp_free_i32(var);
896 s->base.is_jmp = DISAS_EXIT;
897}
898
21aeb343
JR
899/* Variant of store_reg which uses branch&exchange logic when storing
900 to r15 in ARM architecture v7 and above. The source must be a temporary
901 and will be marked as dead. */
7dcc1f89 902static inline void store_reg_bx(DisasContext *s, int reg, TCGv_i32 var)
21aeb343
JR
903{
904 if (reg == 15 && ENABLE_ARCH_7) {
905 gen_bx(s, var);
906 } else {
907 store_reg(s, reg, var);
908 }
909}
910
be5e7a76
DES
911/* Variant of store_reg which uses branch&exchange logic when storing
912 * to r15 in ARM architecture v5T and above. This is used for storing
913 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
914 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
7dcc1f89 915static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
be5e7a76
DES
916{
917 if (reg == 15 && ENABLE_ARCH_5) {
3bb8a96f 918 gen_bx_excret(s, var);
be5e7a76
DES
919 } else {
920 store_reg(s, reg, var);
921 }
922}
923
e334bd31
PB
924#ifdef CONFIG_USER_ONLY
925#define IS_USER_ONLY 1
926#else
927#define IS_USER_ONLY 0
928#endif
929
08307563
PM
930/* Abstractions of "generate code to do a guest load/store for
931 * AArch32", where a vaddr is always 32 bits (and is zero
932 * extended if we're a 64 bit core) and data is also
933 * 32 bits unless specifically doing a 64 bit access.
934 * These functions work like tcg_gen_qemu_{ld,st}* except
09f78135 935 * that the address argument is TCGv_i32 rather than TCGv.
08307563 936 */
08307563 937
14776ab5 938static inline TCGv gen_aa32_addr(DisasContext *s, TCGv_i32 a32, MemOp op)
08307563 939{
7f5616f5
RH
940 TCGv addr = tcg_temp_new();
941 tcg_gen_extu_i32_tl(addr, a32);
942
e334bd31 943 /* Not needed for user-mode BE32, where we use MO_BE instead. */
7f5616f5
RH
944 if (!IS_USER_ONLY && s->sctlr_b && (op & MO_SIZE) < MO_32) {
945 tcg_gen_xori_tl(addr, addr, 4 - (1 << (op & MO_SIZE)));
e334bd31 946 }
7f5616f5 947 return addr;
08307563
PM
948}
949
7f5616f5 950static void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
14776ab5 951 int index, MemOp opc)
08307563 952{
2aeba0d0
JS
953 TCGv addr;
954
955 if (arm_dc_feature(s, ARM_FEATURE_M) &&
956 !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
957 opc |= MO_ALIGN;
958 }
959
960 addr = gen_aa32_addr(s, a32, opc);
7f5616f5
RH
961 tcg_gen_qemu_ld_i32(val, addr, index, opc);
962 tcg_temp_free(addr);
08307563
PM
963}
964
7f5616f5 965static void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
14776ab5 966 int index, MemOp opc)
7f5616f5 967{
2aeba0d0
JS
968 TCGv addr;
969
970 if (arm_dc_feature(s, ARM_FEATURE_M) &&
971 !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
972 opc |= MO_ALIGN;
973 }
974
975 addr = gen_aa32_addr(s, a32, opc);
7f5616f5
RH
976 tcg_gen_qemu_st_i32(val, addr, index, opc);
977 tcg_temp_free(addr);
978}
08307563 979
7f5616f5 980#define DO_GEN_LD(SUFF, OPC) \
12dcc321 981static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
7f5616f5 982 TCGv_i32 a32, int index) \
08307563 983{ \
7f5616f5 984 gen_aa32_ld_i32(s, val, a32, index, OPC | s->be_data); \
9bb6558a
PM
985} \
986static inline void gen_aa32_ld##SUFF##_iss(DisasContext *s, \
987 TCGv_i32 val, \
988 TCGv_i32 a32, int index, \
989 ISSInfo issinfo) \
990{ \
991 gen_aa32_ld##SUFF(s, val, a32, index); \
992 disas_set_da_iss(s, OPC, issinfo); \
08307563
PM
993}
994
7f5616f5 995#define DO_GEN_ST(SUFF, OPC) \
12dcc321 996static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
7f5616f5 997 TCGv_i32 a32, int index) \
08307563 998{ \
7f5616f5 999 gen_aa32_st_i32(s, val, a32, index, OPC | s->be_data); \
9bb6558a
PM
1000} \
1001static inline void gen_aa32_st##SUFF##_iss(DisasContext *s, \
1002 TCGv_i32 val, \
1003 TCGv_i32 a32, int index, \
1004 ISSInfo issinfo) \
1005{ \
1006 gen_aa32_st##SUFF(s, val, a32, index); \
1007 disas_set_da_iss(s, OPC, issinfo | ISSIsWrite); \
08307563
PM
1008}
1009
7f5616f5 1010static inline void gen_aa32_frob64(DisasContext *s, TCGv_i64 val)
08307563 1011{
e334bd31
PB
1012 /* Not needed for user-mode BE32, where we use MO_BE instead. */
1013 if (!IS_USER_ONLY && s->sctlr_b) {
1014 tcg_gen_rotri_i64(val, val, 32);
1015 }
08307563
PM
1016}
1017
7f5616f5 1018static void gen_aa32_ld_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
14776ab5 1019 int index, MemOp opc)
08307563 1020{
7f5616f5
RH
1021 TCGv addr = gen_aa32_addr(s, a32, opc);
1022 tcg_gen_qemu_ld_i64(val, addr, index, opc);
1023 gen_aa32_frob64(s, val);
1024 tcg_temp_free(addr);
1025}
1026
1027static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
1028 TCGv_i32 a32, int index)
1029{
1030 gen_aa32_ld_i64(s, val, a32, index, MO_Q | s->be_data);
1031}
1032
1033static void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
14776ab5 1034 int index, MemOp opc)
7f5616f5
RH
1035{
1036 TCGv addr = gen_aa32_addr(s, a32, opc);
e334bd31
PB
1037
1038 /* Not needed for user-mode BE32, where we use MO_BE instead. */
1039 if (!IS_USER_ONLY && s->sctlr_b) {
7f5616f5 1040 TCGv_i64 tmp = tcg_temp_new_i64();
e334bd31 1041 tcg_gen_rotri_i64(tmp, val, 32);
7f5616f5
RH
1042 tcg_gen_qemu_st_i64(tmp, addr, index, opc);
1043 tcg_temp_free_i64(tmp);
e334bd31 1044 } else {
7f5616f5 1045 tcg_gen_qemu_st_i64(val, addr, index, opc);
e334bd31 1046 }
7f5616f5 1047 tcg_temp_free(addr);
08307563
PM
1048}
1049
7f5616f5
RH
1050static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
1051 TCGv_i32 a32, int index)
1052{
1053 gen_aa32_st_i64(s, val, a32, index, MO_Q | s->be_data);
1054}
08307563 1055
7f5616f5
RH
1056DO_GEN_LD(8s, MO_SB)
1057DO_GEN_LD(8u, MO_UB)
1058DO_GEN_LD(16s, MO_SW)
1059DO_GEN_LD(16u, MO_UW)
1060DO_GEN_LD(32u, MO_UL)
7f5616f5
RH
1061DO_GEN_ST(8, MO_UB)
1062DO_GEN_ST(16, MO_UW)
1063DO_GEN_ST(32, MO_UL)
08307563 1064
37e6456e
PM
1065static inline void gen_hvc(DisasContext *s, int imm16)
1066{
1067 /* The pre HVC helper handles cases when HVC gets trapped
1068 * as an undefined insn by runtime configuration (ie before
1069 * the insn really executes).
1070 */
43722a6d 1071 gen_set_pc_im(s, s->pc_curr);
37e6456e
PM
1072 gen_helper_pre_hvc(cpu_env);
1073 /* Otherwise we will treat this as a real exception which
1074 * happens after execution of the insn. (The distinction matters
1075 * for the PC value reported to the exception handler and also
1076 * for single stepping.)
1077 */
1078 s->svc_imm = imm16;
a0415916 1079 gen_set_pc_im(s, s->base.pc_next);
dcba3a8d 1080 s->base.is_jmp = DISAS_HVC;
37e6456e
PM
1081}
1082
1083static inline void gen_smc(DisasContext *s)
1084{
1085 /* As with HVC, we may take an exception either before or after
1086 * the insn executes.
1087 */
1088 TCGv_i32 tmp;
1089
43722a6d 1090 gen_set_pc_im(s, s->pc_curr);
37e6456e
PM
1091 tmp = tcg_const_i32(syn_aa32_smc());
1092 gen_helper_pre_smc(cpu_env, tmp);
1093 tcg_temp_free_i32(tmp);
a0415916 1094 gen_set_pc_im(s, s->base.pc_next);
dcba3a8d 1095 s->base.is_jmp = DISAS_SMC;
37e6456e
PM
1096}
1097
aee828e7 1098static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp)
d4a2dc67
PM
1099{
1100 gen_set_condexec(s);
aee828e7 1101 gen_set_pc_im(s, pc);
d4a2dc67 1102 gen_exception_internal(excp);
dcba3a8d 1103 s->base.is_jmp = DISAS_NORETURN;
d4a2dc67
PM
1104}
1105
a767fac8 1106static void gen_exception_insn(DisasContext *s, uint32_t pc, int excp,
73710361 1107 int syn, uint32_t target_el)
d4a2dc67
PM
1108{
1109 gen_set_condexec(s);
a767fac8 1110 gen_set_pc_im(s, pc);
73710361 1111 gen_exception(excp, syn, target_el);
dcba3a8d 1112 s->base.is_jmp = DISAS_NORETURN;
d4a2dc67
PM
1113}
1114
06bcbda3 1115static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
c900a2e6
PM
1116{
1117 TCGv_i32 tcg_syn;
1118
1119 gen_set_condexec(s);
06bcbda3 1120 gen_set_pc_im(s, s->pc_curr);
c900a2e6
PM
1121 tcg_syn = tcg_const_i32(syn);
1122 gen_helper_exception_bkpt_insn(cpu_env, tcg_syn);
1123 tcg_temp_free_i32(tcg_syn);
1124 s->base.is_jmp = DISAS_NORETURN;
1125}
1126
1ce21ba1
RH
1127static void unallocated_encoding(DisasContext *s)
1128{
1129 /* Unallocated and reserved encodings are uncategorized */
1130 gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(),
1131 default_exception_el(s));
1132}
1133
b5ff1b31
FB
1134/* Force a TB lookup after an instruction that changes the CPU state. */
1135static inline void gen_lookup_tb(DisasContext *s)
1136{
a0415916 1137 tcg_gen_movi_i32(cpu_R[15], s->base.pc_next);
dcba3a8d 1138 s->base.is_jmp = DISAS_EXIT;
b5ff1b31
FB
1139}
1140
19a6e31c
PM
1141static inline void gen_hlt(DisasContext *s, int imm)
1142{
1143 /* HLT. This has two purposes.
1144 * Architecturally, it is an external halting debug instruction.
1145 * Since QEMU doesn't implement external debug, we treat this as
1146 * it is required for halting debug disabled: it will UNDEF.
1147 * Secondly, "HLT 0x3C" is a T32 semihosting trap instruction,
1148 * and "HLT 0xF000" is an A32 semihosting syscall. These traps
1149 * must trigger semihosting even for ARMv7 and earlier, where
1150 * HLT was an undefined encoding.
1151 * In system mode, we don't allow userspace access to
1152 * semihosting, to provide some semblance of security
1153 * (and for consistency with our 32-bit semihosting).
1154 */
1155 if (semihosting_enabled() &&
1156#ifndef CONFIG_USER_ONLY
1157 s->current_el != 0 &&
1158#endif
1159 (imm == (s->thumb ? 0x3c : 0xf000))) {
aee828e7 1160 gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST);
19a6e31c
PM
1161 return;
1162 }
1163
1ce21ba1 1164 unallocated_encoding(s);
19a6e31c
PM
1165}
1166
5aaebd13
PM
1167static TCGv_ptr get_fpstatus_ptr(int neon)
1168{
1169 TCGv_ptr statusptr = tcg_temp_new_ptr();
1170 int offset;
1171 if (neon) {
0ecb72a5 1172 offset = offsetof(CPUARMState, vfp.standard_fp_status);
5aaebd13 1173 } else {
0ecb72a5 1174 offset = offsetof(CPUARMState, vfp.fp_status);
5aaebd13
PM
1175 }
1176 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
1177 return statusptr;
1178}
1179
c39c2b90 1180static inline long vfp_reg_offset(bool dp, unsigned reg)
8e96005d 1181{
9a2b5256 1182 if (dp) {
c39c2b90 1183 return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]);
8e96005d 1184 } else {
c39c2b90 1185 long ofs = offsetof(CPUARMState, vfp.zregs[reg >> 2].d[(reg >> 1) & 1]);
9a2b5256
RH
1186 if (reg & 1) {
1187 ofs += offsetof(CPU_DoubleU, l.upper);
1188 } else {
1189 ofs += offsetof(CPU_DoubleU, l.lower);
1190 }
1191 return ofs;
8e96005d
FB
1192 }
1193}
9ee6e8bb
PB
1194
1195/* Return the offset of a 32-bit piece of a NEON register.
1196 zero is the least significant end of the register. */
1197static inline long
1198neon_reg_offset (int reg, int n)
1199{
1200 int sreg;
1201 sreg = reg * 2 + n;
1202 return vfp_reg_offset(0, sreg);
1203}
1204
32f91fb7
RH
1205/* Return the offset of a 2**SIZE piece of a NEON register, at index ELE,
1206 * where 0 is the least significant end of the register.
1207 */
1208static inline long
14776ab5 1209neon_element_offset(int reg, int element, MemOp size)
32f91fb7
RH
1210{
1211 int element_size = 1 << size;
1212 int ofs = element * element_size;
1213#ifdef HOST_WORDS_BIGENDIAN
1214 /* Calculate the offset assuming fully little-endian,
1215 * then XOR to account for the order of the 8-byte units.
1216 */
1217 if (element_size < 8) {
1218 ofs ^= 8 - element_size;
1219 }
1220#endif
1221 return neon_reg_offset(reg, 0) + ofs;
1222}
1223
39d5492a 1224static TCGv_i32 neon_load_reg(int reg, int pass)
8f8e3aa4 1225{
39d5492a 1226 TCGv_i32 tmp = tcg_temp_new_i32();
8f8e3aa4
PB
1227 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1228 return tmp;
1229}
1230
14776ab5 1231static void neon_load_element(TCGv_i32 var, int reg, int ele, MemOp mop)
2d6ac920
RH
1232{
1233 long offset = neon_element_offset(reg, ele, mop & MO_SIZE);
1234
1235 switch (mop) {
1236 case MO_UB:
1237 tcg_gen_ld8u_i32(var, cpu_env, offset);
1238 break;
1239 case MO_UW:
1240 tcg_gen_ld16u_i32(var, cpu_env, offset);
1241 break;
1242 case MO_UL:
1243 tcg_gen_ld_i32(var, cpu_env, offset);
1244 break;
1245 default:
1246 g_assert_not_reached();
1247 }
1248}
1249
14776ab5 1250static void neon_load_element64(TCGv_i64 var, int reg, int ele, MemOp mop)
ac55d007
RH
1251{
1252 long offset = neon_element_offset(reg, ele, mop & MO_SIZE);
1253
1254 switch (mop) {
1255 case MO_UB:
1256 tcg_gen_ld8u_i64(var, cpu_env, offset);
1257 break;
1258 case MO_UW:
1259 tcg_gen_ld16u_i64(var, cpu_env, offset);
1260 break;
1261 case MO_UL:
1262 tcg_gen_ld32u_i64(var, cpu_env, offset);
1263 break;
1264 case MO_Q:
1265 tcg_gen_ld_i64(var, cpu_env, offset);
1266 break;
1267 default:
1268 g_assert_not_reached();
1269 }
1270}
1271
39d5492a 1272static void neon_store_reg(int reg, int pass, TCGv_i32 var)
8f8e3aa4
PB
1273{
1274 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
7d1b0095 1275 tcg_temp_free_i32(var);
8f8e3aa4
PB
1276}
1277
14776ab5 1278static void neon_store_element(int reg, int ele, MemOp size, TCGv_i32 var)
2d6ac920
RH
1279{
1280 long offset = neon_element_offset(reg, ele, size);
1281
1282 switch (size) {
1283 case MO_8:
1284 tcg_gen_st8_i32(var, cpu_env, offset);
1285 break;
1286 case MO_16:
1287 tcg_gen_st16_i32(var, cpu_env, offset);
1288 break;
1289 case MO_32:
1290 tcg_gen_st_i32(var, cpu_env, offset);
1291 break;
1292 default:
1293 g_assert_not_reached();
1294 }
1295}
1296
14776ab5 1297static void neon_store_element64(int reg, int ele, MemOp size, TCGv_i64 var)
ac55d007
RH
1298{
1299 long offset = neon_element_offset(reg, ele, size);
1300
1301 switch (size) {
1302 case MO_8:
1303 tcg_gen_st8_i64(var, cpu_env, offset);
1304 break;
1305 case MO_16:
1306 tcg_gen_st16_i64(var, cpu_env, offset);
1307 break;
1308 case MO_32:
1309 tcg_gen_st32_i64(var, cpu_env, offset);
1310 break;
1311 case MO_64:
1312 tcg_gen_st_i64(var, cpu_env, offset);
1313 break;
1314 default:
1315 g_assert_not_reached();
1316 }
1317}
1318
a7812ae4 1319static inline void neon_load_reg64(TCGv_i64 var, int reg)
ad69471c
PB
1320{
1321 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1322}
1323
a7812ae4 1324static inline void neon_store_reg64(TCGv_i64 var, int reg)
ad69471c
PB
1325{
1326 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1327}
1328
160f3b64
PM
1329static inline void neon_load_reg32(TCGv_i32 var, int reg)
1330{
1331 tcg_gen_ld_i32(var, cpu_env, vfp_reg_offset(false, reg));
1332}
1333
1334static inline void neon_store_reg32(TCGv_i32 var, int reg)
1335{
1336 tcg_gen_st_i32(var, cpu_env, vfp_reg_offset(false, reg));
1337}
1338
1a66ac61
RH
1339static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
1340{
1341 TCGv_ptr ret = tcg_temp_new_ptr();
1342 tcg_gen_addi_ptr(ret, cpu_env, vfp_reg_offset(dp, reg));
1343 return ret;
1344}
1345
d00584b7 1346#define ARM_CP_RW_BIT (1 << 20)
18c9b560 1347
78e138bc
PM
1348/* Include the VFP decoder */
1349#include "translate-vfp.inc.c"
1350
a7812ae4 1351static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
e677137d 1352{
0ecb72a5 1353 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
e677137d
PB
1354}
1355
a7812ae4 1356static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
e677137d 1357{
0ecb72a5 1358 tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
e677137d
PB
1359}
1360
39d5492a 1361static inline TCGv_i32 iwmmxt_load_creg(int reg)
e677137d 1362{
39d5492a 1363 TCGv_i32 var = tcg_temp_new_i32();
0ecb72a5 1364 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
da6b5335 1365 return var;
e677137d
PB
1366}
1367
39d5492a 1368static inline void iwmmxt_store_creg(int reg, TCGv_i32 var)
e677137d 1369{
0ecb72a5 1370 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
7d1b0095 1371 tcg_temp_free_i32(var);
e677137d
PB
1372}
1373
1374static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1375{
1376 iwmmxt_store_reg(cpu_M0, rn);
1377}
1378
1379static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1380{
1381 iwmmxt_load_reg(cpu_M0, rn);
1382}
1383
1384static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1385{
1386 iwmmxt_load_reg(cpu_V1, rn);
1387 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1388}
1389
1390static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1391{
1392 iwmmxt_load_reg(cpu_V1, rn);
1393 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1394}
1395
1396static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1397{
1398 iwmmxt_load_reg(cpu_V1, rn);
1399 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1400}
1401
1402#define IWMMXT_OP(name) \
1403static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1404{ \
1405 iwmmxt_load_reg(cpu_V1, rn); \
1406 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1407}
1408
477955bd
PM
1409#define IWMMXT_OP_ENV(name) \
1410static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1411{ \
1412 iwmmxt_load_reg(cpu_V1, rn); \
1413 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1414}
1415
1416#define IWMMXT_OP_ENV_SIZE(name) \
1417IWMMXT_OP_ENV(name##b) \
1418IWMMXT_OP_ENV(name##w) \
1419IWMMXT_OP_ENV(name##l)
e677137d 1420
477955bd 1421#define IWMMXT_OP_ENV1(name) \
e677137d
PB
1422static inline void gen_op_iwmmxt_##name##_M0(void) \
1423{ \
477955bd 1424 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
e677137d
PB
1425}
1426
1427IWMMXT_OP(maddsq)
1428IWMMXT_OP(madduq)
1429IWMMXT_OP(sadb)
1430IWMMXT_OP(sadw)
1431IWMMXT_OP(mulslw)
1432IWMMXT_OP(mulshw)
1433IWMMXT_OP(mululw)
1434IWMMXT_OP(muluhw)
1435IWMMXT_OP(macsw)
1436IWMMXT_OP(macuw)
1437
477955bd
PM
1438IWMMXT_OP_ENV_SIZE(unpackl)
1439IWMMXT_OP_ENV_SIZE(unpackh)
1440
1441IWMMXT_OP_ENV1(unpacklub)
1442IWMMXT_OP_ENV1(unpackluw)
1443IWMMXT_OP_ENV1(unpacklul)
1444IWMMXT_OP_ENV1(unpackhub)
1445IWMMXT_OP_ENV1(unpackhuw)
1446IWMMXT_OP_ENV1(unpackhul)
1447IWMMXT_OP_ENV1(unpacklsb)
1448IWMMXT_OP_ENV1(unpacklsw)
1449IWMMXT_OP_ENV1(unpacklsl)
1450IWMMXT_OP_ENV1(unpackhsb)
1451IWMMXT_OP_ENV1(unpackhsw)
1452IWMMXT_OP_ENV1(unpackhsl)
1453
1454IWMMXT_OP_ENV_SIZE(cmpeq)
1455IWMMXT_OP_ENV_SIZE(cmpgtu)
1456IWMMXT_OP_ENV_SIZE(cmpgts)
1457
1458IWMMXT_OP_ENV_SIZE(mins)
1459IWMMXT_OP_ENV_SIZE(minu)
1460IWMMXT_OP_ENV_SIZE(maxs)
1461IWMMXT_OP_ENV_SIZE(maxu)
1462
1463IWMMXT_OP_ENV_SIZE(subn)
1464IWMMXT_OP_ENV_SIZE(addn)
1465IWMMXT_OP_ENV_SIZE(subu)
1466IWMMXT_OP_ENV_SIZE(addu)
1467IWMMXT_OP_ENV_SIZE(subs)
1468IWMMXT_OP_ENV_SIZE(adds)
1469
1470IWMMXT_OP_ENV(avgb0)
1471IWMMXT_OP_ENV(avgb1)
1472IWMMXT_OP_ENV(avgw0)
1473IWMMXT_OP_ENV(avgw1)
e677137d 1474
477955bd
PM
1475IWMMXT_OP_ENV(packuw)
1476IWMMXT_OP_ENV(packul)
1477IWMMXT_OP_ENV(packuq)
1478IWMMXT_OP_ENV(packsw)
1479IWMMXT_OP_ENV(packsl)
1480IWMMXT_OP_ENV(packsq)
e677137d 1481
e677137d
PB
1482static void gen_op_iwmmxt_set_mup(void)
1483{
39d5492a 1484 TCGv_i32 tmp;
e677137d
PB
1485 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1486 tcg_gen_ori_i32(tmp, tmp, 2);
1487 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1488}
1489
1490static void gen_op_iwmmxt_set_cup(void)
1491{
39d5492a 1492 TCGv_i32 tmp;
e677137d
PB
1493 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1494 tcg_gen_ori_i32(tmp, tmp, 1);
1495 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1496}
1497
1498static void gen_op_iwmmxt_setpsr_nz(void)
1499{
39d5492a 1500 TCGv_i32 tmp = tcg_temp_new_i32();
e677137d
PB
1501 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1502 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1503}
1504
1505static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1506{
1507 iwmmxt_load_reg(cpu_V1, rn);
86831435 1508 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
e677137d
PB
1509 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1510}
1511
39d5492a
PM
1512static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn,
1513 TCGv_i32 dest)
18c9b560
AZ
1514{
1515 int rd;
1516 uint32_t offset;
39d5492a 1517 TCGv_i32 tmp;
18c9b560
AZ
1518
1519 rd = (insn >> 16) & 0xf;
da6b5335 1520 tmp = load_reg(s, rd);
18c9b560
AZ
1521
1522 offset = (insn & 0xff) << ((insn >> 7) & 2);
1523 if (insn & (1 << 24)) {
1524 /* Pre indexed */
1525 if (insn & (1 << 23))
da6b5335 1526 tcg_gen_addi_i32(tmp, tmp, offset);
18c9b560 1527 else
da6b5335
FN
1528 tcg_gen_addi_i32(tmp, tmp, -offset);
1529 tcg_gen_mov_i32(dest, tmp);
18c9b560 1530 if (insn & (1 << 21))
da6b5335
FN
1531 store_reg(s, rd, tmp);
1532 else
7d1b0095 1533 tcg_temp_free_i32(tmp);
18c9b560
AZ
1534 } else if (insn & (1 << 21)) {
1535 /* Post indexed */
da6b5335 1536 tcg_gen_mov_i32(dest, tmp);
18c9b560 1537 if (insn & (1 << 23))
da6b5335 1538 tcg_gen_addi_i32(tmp, tmp, offset);
18c9b560 1539 else
da6b5335
FN
1540 tcg_gen_addi_i32(tmp, tmp, -offset);
1541 store_reg(s, rd, tmp);
18c9b560
AZ
1542 } else if (!(insn & (1 << 23)))
1543 return 1;
1544 return 0;
1545}
1546
39d5492a 1547static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest)
18c9b560
AZ
1548{
1549 int rd = (insn >> 0) & 0xf;
39d5492a 1550 TCGv_i32 tmp;
18c9b560 1551
da6b5335
FN
1552 if (insn & (1 << 8)) {
1553 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
18c9b560 1554 return 1;
da6b5335
FN
1555 } else {
1556 tmp = iwmmxt_load_creg(rd);
1557 }
1558 } else {
7d1b0095 1559 tmp = tcg_temp_new_i32();
da6b5335 1560 iwmmxt_load_reg(cpu_V0, rd);
ecc7b3aa 1561 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
da6b5335
FN
1562 }
1563 tcg_gen_andi_i32(tmp, tmp, mask);
1564 tcg_gen_mov_i32(dest, tmp);
7d1b0095 1565 tcg_temp_free_i32(tmp);
18c9b560
AZ
1566 return 0;
1567}
1568
a1c7273b 1569/* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
18c9b560 1570 (ie. an undefined instruction). */
7dcc1f89 1571static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
18c9b560
AZ
1572{
1573 int rd, wrd;
1574 int rdhi, rdlo, rd0, rd1, i;
39d5492a
PM
1575 TCGv_i32 addr;
1576 TCGv_i32 tmp, tmp2, tmp3;
18c9b560
AZ
1577
1578 if ((insn & 0x0e000e00) == 0x0c000000) {
1579 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1580 wrd = insn & 0xf;
1581 rdlo = (insn >> 12) & 0xf;
1582 rdhi = (insn >> 16) & 0xf;
d00584b7 1583 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
da6b5335 1584 iwmmxt_load_reg(cpu_V0, wrd);
ecc7b3aa 1585 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
664b7e3b 1586 tcg_gen_extrh_i64_i32(cpu_R[rdhi], cpu_V0);
d00584b7 1587 } else { /* TMCRR */
da6b5335
FN
1588 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1589 iwmmxt_store_reg(cpu_V0, wrd);
18c9b560
AZ
1590 gen_op_iwmmxt_set_mup();
1591 }
1592 return 0;
1593 }
1594
1595 wrd = (insn >> 12) & 0xf;
7d1b0095 1596 addr = tcg_temp_new_i32();
da6b5335 1597 if (gen_iwmmxt_address(s, insn, addr)) {
7d1b0095 1598 tcg_temp_free_i32(addr);
18c9b560 1599 return 1;
da6b5335 1600 }
18c9b560 1601 if (insn & ARM_CP_RW_BIT) {
d00584b7 1602 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
7d1b0095 1603 tmp = tcg_temp_new_i32();
12dcc321 1604 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
da6b5335 1605 iwmmxt_store_creg(wrd, tmp);
18c9b560 1606 } else {
e677137d
PB
1607 i = 1;
1608 if (insn & (1 << 8)) {
d00584b7 1609 if (insn & (1 << 22)) { /* WLDRD */
12dcc321 1610 gen_aa32_ld64(s, cpu_M0, addr, get_mem_index(s));
e677137d 1611 i = 0;
d00584b7 1612 } else { /* WLDRW wRd */
29531141 1613 tmp = tcg_temp_new_i32();
12dcc321 1614 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
e677137d
PB
1615 }
1616 } else {
29531141 1617 tmp = tcg_temp_new_i32();
d00584b7 1618 if (insn & (1 << 22)) { /* WLDRH */
12dcc321 1619 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
d00584b7 1620 } else { /* WLDRB */
12dcc321 1621 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
e677137d
PB
1622 }
1623 }
1624 if (i) {
1625 tcg_gen_extu_i32_i64(cpu_M0, tmp);
7d1b0095 1626 tcg_temp_free_i32(tmp);
e677137d 1627 }
18c9b560
AZ
1628 gen_op_iwmmxt_movq_wRn_M0(wrd);
1629 }
1630 } else {
d00584b7 1631 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
da6b5335 1632 tmp = iwmmxt_load_creg(wrd);
12dcc321 1633 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
18c9b560
AZ
1634 } else {
1635 gen_op_iwmmxt_movq_M0_wRn(wrd);
7d1b0095 1636 tmp = tcg_temp_new_i32();
e677137d 1637 if (insn & (1 << 8)) {
d00584b7 1638 if (insn & (1 << 22)) { /* WSTRD */
12dcc321 1639 gen_aa32_st64(s, cpu_M0, addr, get_mem_index(s));
d00584b7 1640 } else { /* WSTRW wRd */
ecc7b3aa 1641 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
12dcc321 1642 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
e677137d
PB
1643 }
1644 } else {
d00584b7 1645 if (insn & (1 << 22)) { /* WSTRH */
ecc7b3aa 1646 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
12dcc321 1647 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
d00584b7 1648 } else { /* WSTRB */
ecc7b3aa 1649 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
12dcc321 1650 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
e677137d
PB
1651 }
1652 }
18c9b560 1653 }
29531141 1654 tcg_temp_free_i32(tmp);
18c9b560 1655 }
7d1b0095 1656 tcg_temp_free_i32(addr);
18c9b560
AZ
1657 return 0;
1658 }
1659
1660 if ((insn & 0x0f000000) != 0x0e000000)
1661 return 1;
1662
1663 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
d00584b7 1664 case 0x000: /* WOR */
18c9b560
AZ
1665 wrd = (insn >> 12) & 0xf;
1666 rd0 = (insn >> 0) & 0xf;
1667 rd1 = (insn >> 16) & 0xf;
1668 gen_op_iwmmxt_movq_M0_wRn(rd0);
1669 gen_op_iwmmxt_orq_M0_wRn(rd1);
1670 gen_op_iwmmxt_setpsr_nz();
1671 gen_op_iwmmxt_movq_wRn_M0(wrd);
1672 gen_op_iwmmxt_set_mup();
1673 gen_op_iwmmxt_set_cup();
1674 break;
d00584b7 1675 case 0x011: /* TMCR */
18c9b560
AZ
1676 if (insn & 0xf)
1677 return 1;
1678 rd = (insn >> 12) & 0xf;
1679 wrd = (insn >> 16) & 0xf;
1680 switch (wrd) {
1681 case ARM_IWMMXT_wCID:
1682 case ARM_IWMMXT_wCASF:
1683 break;
1684 case ARM_IWMMXT_wCon:
1685 gen_op_iwmmxt_set_cup();
1686 /* Fall through. */
1687 case ARM_IWMMXT_wCSSF:
da6b5335
FN
1688 tmp = iwmmxt_load_creg(wrd);
1689 tmp2 = load_reg(s, rd);
f669df27 1690 tcg_gen_andc_i32(tmp, tmp, tmp2);
7d1b0095 1691 tcg_temp_free_i32(tmp2);
da6b5335 1692 iwmmxt_store_creg(wrd, tmp);
18c9b560
AZ
1693 break;
1694 case ARM_IWMMXT_wCGR0:
1695 case ARM_IWMMXT_wCGR1:
1696 case ARM_IWMMXT_wCGR2:
1697 case ARM_IWMMXT_wCGR3:
1698 gen_op_iwmmxt_set_cup();
da6b5335
FN
1699 tmp = load_reg(s, rd);
1700 iwmmxt_store_creg(wrd, tmp);
18c9b560
AZ
1701 break;
1702 default:
1703 return 1;
1704 }
1705 break;
d00584b7 1706 case 0x100: /* WXOR */
18c9b560
AZ
1707 wrd = (insn >> 12) & 0xf;
1708 rd0 = (insn >> 0) & 0xf;
1709 rd1 = (insn >> 16) & 0xf;
1710 gen_op_iwmmxt_movq_M0_wRn(rd0);
1711 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1712 gen_op_iwmmxt_setpsr_nz();
1713 gen_op_iwmmxt_movq_wRn_M0(wrd);
1714 gen_op_iwmmxt_set_mup();
1715 gen_op_iwmmxt_set_cup();
1716 break;
d00584b7 1717 case 0x111: /* TMRC */
18c9b560
AZ
1718 if (insn & 0xf)
1719 return 1;
1720 rd = (insn >> 12) & 0xf;
1721 wrd = (insn >> 16) & 0xf;
da6b5335
FN
1722 tmp = iwmmxt_load_creg(wrd);
1723 store_reg(s, rd, tmp);
18c9b560 1724 break;
d00584b7 1725 case 0x300: /* WANDN */
18c9b560
AZ
1726 wrd = (insn >> 12) & 0xf;
1727 rd0 = (insn >> 0) & 0xf;
1728 rd1 = (insn >> 16) & 0xf;
1729 gen_op_iwmmxt_movq_M0_wRn(rd0);
e677137d 1730 tcg_gen_neg_i64(cpu_M0, cpu_M0);
18c9b560
AZ
1731 gen_op_iwmmxt_andq_M0_wRn(rd1);
1732 gen_op_iwmmxt_setpsr_nz();
1733 gen_op_iwmmxt_movq_wRn_M0(wrd);
1734 gen_op_iwmmxt_set_mup();
1735 gen_op_iwmmxt_set_cup();
1736 break;
d00584b7 1737 case 0x200: /* WAND */
18c9b560
AZ
1738 wrd = (insn >> 12) & 0xf;
1739 rd0 = (insn >> 0) & 0xf;
1740 rd1 = (insn >> 16) & 0xf;
1741 gen_op_iwmmxt_movq_M0_wRn(rd0);
1742 gen_op_iwmmxt_andq_M0_wRn(rd1);
1743 gen_op_iwmmxt_setpsr_nz();
1744 gen_op_iwmmxt_movq_wRn_M0(wrd);
1745 gen_op_iwmmxt_set_mup();
1746 gen_op_iwmmxt_set_cup();
1747 break;
d00584b7 1748 case 0x810: case 0xa10: /* WMADD */
18c9b560
AZ
1749 wrd = (insn >> 12) & 0xf;
1750 rd0 = (insn >> 0) & 0xf;
1751 rd1 = (insn >> 16) & 0xf;
1752 gen_op_iwmmxt_movq_M0_wRn(rd0);
1753 if (insn & (1 << 21))
1754 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1755 else
1756 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1757 gen_op_iwmmxt_movq_wRn_M0(wrd);
1758 gen_op_iwmmxt_set_mup();
1759 break;
d00584b7 1760 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
18c9b560
AZ
1761 wrd = (insn >> 12) & 0xf;
1762 rd0 = (insn >> 16) & 0xf;
1763 rd1 = (insn >> 0) & 0xf;
1764 gen_op_iwmmxt_movq_M0_wRn(rd0);
1765 switch ((insn >> 22) & 3) {
1766 case 0:
1767 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1768 break;
1769 case 1:
1770 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1771 break;
1772 case 2:
1773 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1774 break;
1775 case 3:
1776 return 1;
1777 }
1778 gen_op_iwmmxt_movq_wRn_M0(wrd);
1779 gen_op_iwmmxt_set_mup();
1780 gen_op_iwmmxt_set_cup();
1781 break;
d00584b7 1782 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
18c9b560
AZ
1783 wrd = (insn >> 12) & 0xf;
1784 rd0 = (insn >> 16) & 0xf;
1785 rd1 = (insn >> 0) & 0xf;
1786 gen_op_iwmmxt_movq_M0_wRn(rd0);
1787 switch ((insn >> 22) & 3) {
1788 case 0:
1789 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1790 break;
1791 case 1:
1792 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1793 break;
1794 case 2:
1795 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1796 break;
1797 case 3:
1798 return 1;
1799 }
1800 gen_op_iwmmxt_movq_wRn_M0(wrd);
1801 gen_op_iwmmxt_set_mup();
1802 gen_op_iwmmxt_set_cup();
1803 break;
d00584b7 1804 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
18c9b560
AZ
1805 wrd = (insn >> 12) & 0xf;
1806 rd0 = (insn >> 16) & 0xf;
1807 rd1 = (insn >> 0) & 0xf;
1808 gen_op_iwmmxt_movq_M0_wRn(rd0);
1809 if (insn & (1 << 22))
1810 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1811 else
1812 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1813 if (!(insn & (1 << 20)))
1814 gen_op_iwmmxt_addl_M0_wRn(wrd);
1815 gen_op_iwmmxt_movq_wRn_M0(wrd);
1816 gen_op_iwmmxt_set_mup();
1817 break;
d00584b7 1818 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
18c9b560
AZ
1819 wrd = (insn >> 12) & 0xf;
1820 rd0 = (insn >> 16) & 0xf;
1821 rd1 = (insn >> 0) & 0xf;
1822 gen_op_iwmmxt_movq_M0_wRn(rd0);
e677137d
PB
1823 if (insn & (1 << 21)) {
1824 if (insn & (1 << 20))
1825 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1826 else
1827 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1828 } else {
1829 if (insn & (1 << 20))
1830 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1831 else
1832 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1833 }
18c9b560
AZ
1834 gen_op_iwmmxt_movq_wRn_M0(wrd);
1835 gen_op_iwmmxt_set_mup();
1836 break;
d00584b7 1837 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
18c9b560
AZ
1838 wrd = (insn >> 12) & 0xf;
1839 rd0 = (insn >> 16) & 0xf;
1840 rd1 = (insn >> 0) & 0xf;
1841 gen_op_iwmmxt_movq_M0_wRn(rd0);
1842 if (insn & (1 << 21))
1843 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1844 else
1845 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1846 if (!(insn & (1 << 20))) {
e677137d
PB
1847 iwmmxt_load_reg(cpu_V1, wrd);
1848 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
18c9b560
AZ
1849 }
1850 gen_op_iwmmxt_movq_wRn_M0(wrd);
1851 gen_op_iwmmxt_set_mup();
1852 break;
d00584b7 1853 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
18c9b560
AZ
1854 wrd = (insn >> 12) & 0xf;
1855 rd0 = (insn >> 16) & 0xf;
1856 rd1 = (insn >> 0) & 0xf;
1857 gen_op_iwmmxt_movq_M0_wRn(rd0);
1858 switch ((insn >> 22) & 3) {
1859 case 0:
1860 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1861 break;
1862 case 1:
1863 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1864 break;
1865 case 2:
1866 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1867 break;
1868 case 3:
1869 return 1;
1870 }
1871 gen_op_iwmmxt_movq_wRn_M0(wrd);
1872 gen_op_iwmmxt_set_mup();
1873 gen_op_iwmmxt_set_cup();
1874 break;
d00584b7 1875 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
18c9b560
AZ
1876 wrd = (insn >> 12) & 0xf;
1877 rd0 = (insn >> 16) & 0xf;
1878 rd1 = (insn >> 0) & 0xf;
1879 gen_op_iwmmxt_movq_M0_wRn(rd0);
e677137d
PB
1880 if (insn & (1 << 22)) {
1881 if (insn & (1 << 20))
1882 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1883 else
1884 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1885 } else {
1886 if (insn & (1 << 20))
1887 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1888 else
1889 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1890 }
18c9b560
AZ
1891 gen_op_iwmmxt_movq_wRn_M0(wrd);
1892 gen_op_iwmmxt_set_mup();
1893 gen_op_iwmmxt_set_cup();
1894 break;
d00584b7 1895 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
18c9b560
AZ
1896 wrd = (insn >> 12) & 0xf;
1897 rd0 = (insn >> 16) & 0xf;
1898 rd1 = (insn >> 0) & 0xf;
1899 gen_op_iwmmxt_movq_M0_wRn(rd0);
da6b5335
FN
1900 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1901 tcg_gen_andi_i32(tmp, tmp, 7);
1902 iwmmxt_load_reg(cpu_V1, rd1);
1903 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
7d1b0095 1904 tcg_temp_free_i32(tmp);
18c9b560
AZ
1905 gen_op_iwmmxt_movq_wRn_M0(wrd);
1906 gen_op_iwmmxt_set_mup();
1907 break;
d00584b7 1908 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
da6b5335
FN
1909 if (((insn >> 6) & 3) == 3)
1910 return 1;
18c9b560
AZ
1911 rd = (insn >> 12) & 0xf;
1912 wrd = (insn >> 16) & 0xf;
da6b5335 1913 tmp = load_reg(s, rd);
18c9b560
AZ
1914 gen_op_iwmmxt_movq_M0_wRn(wrd);
1915 switch ((insn >> 6) & 3) {
1916 case 0:
da6b5335
FN
1917 tmp2 = tcg_const_i32(0xff);
1918 tmp3 = tcg_const_i32((insn & 7) << 3);
18c9b560
AZ
1919 break;
1920 case 1:
da6b5335
FN
1921 tmp2 = tcg_const_i32(0xffff);
1922 tmp3 = tcg_const_i32((insn & 3) << 4);
18c9b560
AZ
1923 break;
1924 case 2:
da6b5335
FN
1925 tmp2 = tcg_const_i32(0xffffffff);
1926 tmp3 = tcg_const_i32((insn & 1) << 5);
18c9b560 1927 break;
da6b5335 1928 default:
f764718d
RH
1929 tmp2 = NULL;
1930 tmp3 = NULL;
18c9b560 1931 }
da6b5335 1932 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
39d5492a
PM
1933 tcg_temp_free_i32(tmp3);
1934 tcg_temp_free_i32(tmp2);
7d1b0095 1935 tcg_temp_free_i32(tmp);
18c9b560
AZ
1936 gen_op_iwmmxt_movq_wRn_M0(wrd);
1937 gen_op_iwmmxt_set_mup();
1938 break;
d00584b7 1939 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
18c9b560
AZ
1940 rd = (insn >> 12) & 0xf;
1941 wrd = (insn >> 16) & 0xf;
da6b5335 1942 if (rd == 15 || ((insn >> 22) & 3) == 3)
18c9b560
AZ
1943 return 1;
1944 gen_op_iwmmxt_movq_M0_wRn(wrd);
7d1b0095 1945 tmp = tcg_temp_new_i32();
18c9b560
AZ
1946 switch ((insn >> 22) & 3) {
1947 case 0:
da6b5335 1948 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
ecc7b3aa 1949 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
da6b5335
FN
1950 if (insn & 8) {
1951 tcg_gen_ext8s_i32(tmp, tmp);
1952 } else {
1953 tcg_gen_andi_i32(tmp, tmp, 0xff);
18c9b560
AZ
1954 }
1955 break;
1956 case 1:
da6b5335 1957 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
ecc7b3aa 1958 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
da6b5335
FN
1959 if (insn & 8) {
1960 tcg_gen_ext16s_i32(tmp, tmp);
1961 } else {
1962 tcg_gen_andi_i32(tmp, tmp, 0xffff);
18c9b560
AZ
1963 }
1964 break;
1965 case 2:
da6b5335 1966 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
ecc7b3aa 1967 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
18c9b560 1968 break;
18c9b560 1969 }
da6b5335 1970 store_reg(s, rd, tmp);
18c9b560 1971 break;
d00584b7 1972 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
da6b5335 1973 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
18c9b560 1974 return 1;
da6b5335 1975 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
18c9b560
AZ
1976 switch ((insn >> 22) & 3) {
1977 case 0:
da6b5335 1978 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
18c9b560
AZ
1979 break;
1980 case 1:
da6b5335 1981 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
18c9b560
AZ
1982 break;
1983 case 2:
da6b5335 1984 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
18c9b560 1985 break;
18c9b560 1986 }
da6b5335
FN
1987 tcg_gen_shli_i32(tmp, tmp, 28);
1988 gen_set_nzcv(tmp);
7d1b0095 1989 tcg_temp_free_i32(tmp);
18c9b560 1990 break;
d00584b7 1991 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
da6b5335
FN
1992 if (((insn >> 6) & 3) == 3)
1993 return 1;
18c9b560
AZ
1994 rd = (insn >> 12) & 0xf;
1995 wrd = (insn >> 16) & 0xf;
da6b5335 1996 tmp = load_reg(s, rd);
18c9b560
AZ
1997 switch ((insn >> 6) & 3) {
1998 case 0:
da6b5335 1999 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
18c9b560
AZ
2000 break;
2001 case 1:
da6b5335 2002 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
18c9b560
AZ
2003 break;
2004 case 2:
da6b5335 2005 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
18c9b560 2006 break;
18c9b560 2007 }
7d1b0095 2008 tcg_temp_free_i32(tmp);
18c9b560
AZ
2009 gen_op_iwmmxt_movq_wRn_M0(wrd);
2010 gen_op_iwmmxt_set_mup();
2011 break;
d00584b7 2012 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
da6b5335 2013 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
18c9b560 2014 return 1;
da6b5335 2015 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
7d1b0095 2016 tmp2 = tcg_temp_new_i32();
da6b5335 2017 tcg_gen_mov_i32(tmp2, tmp);
18c9b560
AZ
2018 switch ((insn >> 22) & 3) {
2019 case 0:
2020 for (i = 0; i < 7; i ++) {
da6b5335
FN
2021 tcg_gen_shli_i32(tmp2, tmp2, 4);
2022 tcg_gen_and_i32(tmp, tmp, tmp2);
18c9b560
AZ
2023 }
2024 break;
2025 case 1:
2026 for (i = 0; i < 3; i ++) {
da6b5335
FN
2027 tcg_gen_shli_i32(tmp2, tmp2, 8);
2028 tcg_gen_and_i32(tmp, tmp, tmp2);
18c9b560
AZ
2029 }
2030 break;
2031 case 2:
da6b5335
FN
2032 tcg_gen_shli_i32(tmp2, tmp2, 16);
2033 tcg_gen_and_i32(tmp, tmp, tmp2);
18c9b560 2034 break;
18c9b560 2035 }
da6b5335 2036 gen_set_nzcv(tmp);
7d1b0095
PM
2037 tcg_temp_free_i32(tmp2);
2038 tcg_temp_free_i32(tmp);
18c9b560 2039 break;
d00584b7 2040 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
18c9b560
AZ
2041 wrd = (insn >> 12) & 0xf;
2042 rd0 = (insn >> 16) & 0xf;
2043 gen_op_iwmmxt_movq_M0_wRn(rd0);
2044 switch ((insn >> 22) & 3) {
2045 case 0:
e677137d 2046 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
18c9b560
AZ
2047 break;
2048 case 1:
e677137d 2049 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
18c9b560
AZ
2050 break;
2051 case 2:
e677137d 2052 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
18c9b560
AZ
2053 break;
2054 case 3:
2055 return 1;
2056 }
2057 gen_op_iwmmxt_movq_wRn_M0(wrd);
2058 gen_op_iwmmxt_set_mup();
2059 break;
d00584b7 2060 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
da6b5335 2061 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
18c9b560 2062 return 1;
da6b5335 2063 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
7d1b0095 2064 tmp2 = tcg_temp_new_i32();
da6b5335 2065 tcg_gen_mov_i32(tmp2, tmp);
18c9b560
AZ
2066 switch ((insn >> 22) & 3) {
2067 case 0:
2068 for (i = 0; i < 7; i ++) {
da6b5335
FN
2069 tcg_gen_shli_i32(tmp2, tmp2, 4);
2070 tcg_gen_or_i32(tmp, tmp, tmp2);
18c9b560
AZ
2071 }
2072 break;
2073 case 1:
2074 for (i = 0; i < 3; i ++) {
da6b5335
FN
2075 tcg_gen_shli_i32(tmp2, tmp2, 8);
2076 tcg_gen_or_i32(tmp, tmp, tmp2);
18c9b560
AZ
2077 }
2078 break;
2079 case 2:
da6b5335
FN
2080 tcg_gen_shli_i32(tmp2, tmp2, 16);
2081 tcg_gen_or_i32(tmp, tmp, tmp2);
18c9b560 2082 break;
18c9b560 2083 }
da6b5335 2084 gen_set_nzcv(tmp);
7d1b0095
PM
2085 tcg_temp_free_i32(tmp2);
2086 tcg_temp_free_i32(tmp);
18c9b560 2087 break;
d00584b7 2088 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
18c9b560
AZ
2089 rd = (insn >> 12) & 0xf;
2090 rd0 = (insn >> 16) & 0xf;
da6b5335 2091 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
18c9b560
AZ
2092 return 1;
2093 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2094 tmp = tcg_temp_new_i32();
18c9b560
AZ
2095 switch ((insn >> 22) & 3) {
2096 case 0:
da6b5335 2097 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
18c9b560
AZ
2098 break;
2099 case 1:
da6b5335 2100 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
18c9b560
AZ
2101 break;
2102 case 2:
da6b5335 2103 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
18c9b560 2104 break;
18c9b560 2105 }
da6b5335 2106 store_reg(s, rd, tmp);
18c9b560 2107 break;
d00584b7 2108 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
18c9b560
AZ
2109 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2110 wrd = (insn >> 12) & 0xf;
2111 rd0 = (insn >> 16) & 0xf;
2112 rd1 = (insn >> 0) & 0xf;
2113 gen_op_iwmmxt_movq_M0_wRn(rd0);
2114 switch ((insn >> 22) & 3) {
2115 case 0:
2116 if (insn & (1 << 21))
2117 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2118 else
2119 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2120 break;
2121 case 1:
2122 if (insn & (1 << 21))
2123 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2124 else
2125 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2126 break;
2127 case 2:
2128 if (insn & (1 << 21))
2129 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2130 else
2131 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2132 break;
2133 case 3:
2134 return 1;
2135 }
2136 gen_op_iwmmxt_movq_wRn_M0(wrd);
2137 gen_op_iwmmxt_set_mup();
2138 gen_op_iwmmxt_set_cup();
2139 break;
d00584b7 2140 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
18c9b560
AZ
2141 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2142 wrd = (insn >> 12) & 0xf;
2143 rd0 = (insn >> 16) & 0xf;
2144 gen_op_iwmmxt_movq_M0_wRn(rd0);
2145 switch ((insn >> 22) & 3) {
2146 case 0:
2147 if (insn & (1 << 21))
2148 gen_op_iwmmxt_unpacklsb_M0();
2149 else
2150 gen_op_iwmmxt_unpacklub_M0();
2151 break;
2152 case 1:
2153 if (insn & (1 << 21))
2154 gen_op_iwmmxt_unpacklsw_M0();
2155 else
2156 gen_op_iwmmxt_unpackluw_M0();
2157 break;
2158 case 2:
2159 if (insn & (1 << 21))
2160 gen_op_iwmmxt_unpacklsl_M0();
2161 else
2162 gen_op_iwmmxt_unpacklul_M0();
2163 break;
2164 case 3:
2165 return 1;
2166 }
2167 gen_op_iwmmxt_movq_wRn_M0(wrd);
2168 gen_op_iwmmxt_set_mup();
2169 gen_op_iwmmxt_set_cup();
2170 break;
d00584b7 2171 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
18c9b560
AZ
2172 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2173 wrd = (insn >> 12) & 0xf;
2174 rd0 = (insn >> 16) & 0xf;
2175 gen_op_iwmmxt_movq_M0_wRn(rd0);
2176 switch ((insn >> 22) & 3) {
2177 case 0:
2178 if (insn & (1 << 21))
2179 gen_op_iwmmxt_unpackhsb_M0();
2180 else
2181 gen_op_iwmmxt_unpackhub_M0();
2182 break;
2183 case 1:
2184 if (insn & (1 << 21))
2185 gen_op_iwmmxt_unpackhsw_M0();
2186 else
2187 gen_op_iwmmxt_unpackhuw_M0();
2188 break;
2189 case 2:
2190 if (insn & (1 << 21))
2191 gen_op_iwmmxt_unpackhsl_M0();
2192 else
2193 gen_op_iwmmxt_unpackhul_M0();
2194 break;
2195 case 3:
2196 return 1;
2197 }
2198 gen_op_iwmmxt_movq_wRn_M0(wrd);
2199 gen_op_iwmmxt_set_mup();
2200 gen_op_iwmmxt_set_cup();
2201 break;
d00584b7 2202 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
18c9b560 2203 case 0x214: case 0x614: case 0xa14: case 0xe14:
da6b5335
FN
2204 if (((insn >> 22) & 3) == 0)
2205 return 1;
18c9b560
AZ
2206 wrd = (insn >> 12) & 0xf;
2207 rd0 = (insn >> 16) & 0xf;
2208 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2209 tmp = tcg_temp_new_i32();
da6b5335 2210 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
7d1b0095 2211 tcg_temp_free_i32(tmp);
18c9b560 2212 return 1;
da6b5335 2213 }
18c9b560 2214 switch ((insn >> 22) & 3) {
18c9b560 2215 case 1:
477955bd 2216 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2217 break;
2218 case 2:
477955bd 2219 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2220 break;
2221 case 3:
477955bd 2222 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2223 break;
2224 }
7d1b0095 2225 tcg_temp_free_i32(tmp);
18c9b560
AZ
2226 gen_op_iwmmxt_movq_wRn_M0(wrd);
2227 gen_op_iwmmxt_set_mup();
2228 gen_op_iwmmxt_set_cup();
2229 break;
d00584b7 2230 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
18c9b560 2231 case 0x014: case 0x414: case 0x814: case 0xc14:
da6b5335
FN
2232 if (((insn >> 22) & 3) == 0)
2233 return 1;
18c9b560
AZ
2234 wrd = (insn >> 12) & 0xf;
2235 rd0 = (insn >> 16) & 0xf;
2236 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2237 tmp = tcg_temp_new_i32();
da6b5335 2238 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
7d1b0095 2239 tcg_temp_free_i32(tmp);
18c9b560 2240 return 1;
da6b5335 2241 }
18c9b560 2242 switch ((insn >> 22) & 3) {
18c9b560 2243 case 1:
477955bd 2244 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2245 break;
2246 case 2:
477955bd 2247 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2248 break;
2249 case 3:
477955bd 2250 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2251 break;
2252 }
7d1b0095 2253 tcg_temp_free_i32(tmp);
18c9b560
AZ
2254 gen_op_iwmmxt_movq_wRn_M0(wrd);
2255 gen_op_iwmmxt_set_mup();
2256 gen_op_iwmmxt_set_cup();
2257 break;
d00584b7 2258 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
18c9b560 2259 case 0x114: case 0x514: case 0x914: case 0xd14:
da6b5335
FN
2260 if (((insn >> 22) & 3) == 0)
2261 return 1;
18c9b560
AZ
2262 wrd = (insn >> 12) & 0xf;
2263 rd0 = (insn >> 16) & 0xf;
2264 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2265 tmp = tcg_temp_new_i32();
da6b5335 2266 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
7d1b0095 2267 tcg_temp_free_i32(tmp);
18c9b560 2268 return 1;
da6b5335 2269 }
18c9b560 2270 switch ((insn >> 22) & 3) {
18c9b560 2271 case 1:
477955bd 2272 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2273 break;
2274 case 2:
477955bd 2275 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2276 break;
2277 case 3:
477955bd 2278 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2279 break;
2280 }
7d1b0095 2281 tcg_temp_free_i32(tmp);
18c9b560
AZ
2282 gen_op_iwmmxt_movq_wRn_M0(wrd);
2283 gen_op_iwmmxt_set_mup();
2284 gen_op_iwmmxt_set_cup();
2285 break;
d00584b7 2286 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
18c9b560 2287 case 0x314: case 0x714: case 0xb14: case 0xf14:
da6b5335
FN
2288 if (((insn >> 22) & 3) == 0)
2289 return 1;
18c9b560
AZ
2290 wrd = (insn >> 12) & 0xf;
2291 rd0 = (insn >> 16) & 0xf;
2292 gen_op_iwmmxt_movq_M0_wRn(rd0);
7d1b0095 2293 tmp = tcg_temp_new_i32();
18c9b560 2294 switch ((insn >> 22) & 3) {
18c9b560 2295 case 1:
da6b5335 2296 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
7d1b0095 2297 tcg_temp_free_i32(tmp);
18c9b560 2298 return 1;
da6b5335 2299 }
477955bd 2300 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2301 break;
2302 case 2:
da6b5335 2303 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
7d1b0095 2304 tcg_temp_free_i32(tmp);
18c9b560 2305 return 1;
da6b5335 2306 }
477955bd 2307 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2308 break;
2309 case 3:
da6b5335 2310 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
7d1b0095 2311 tcg_temp_free_i32(tmp);
18c9b560 2312 return 1;
da6b5335 2313 }
477955bd 2314 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
18c9b560
AZ
2315 break;
2316 }
7d1b0095 2317 tcg_temp_free_i32(tmp);
18c9b560
AZ
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 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
18c9b560
AZ
2323 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2324 wrd = (insn >> 12) & 0xf;
2325 rd0 = (insn >> 16) & 0xf;
2326 rd1 = (insn >> 0) & 0xf;
2327 gen_op_iwmmxt_movq_M0_wRn(rd0);
2328 switch ((insn >> 22) & 3) {
2329 case 0:
2330 if (insn & (1 << 21))
2331 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2332 else
2333 gen_op_iwmmxt_minub_M0_wRn(rd1);
2334 break;
2335 case 1:
2336 if (insn & (1 << 21))
2337 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2338 else
2339 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2340 break;
2341 case 2:
2342 if (insn & (1 << 21))
2343 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2344 else
2345 gen_op_iwmmxt_minul_M0_wRn(rd1);
2346 break;
2347 case 3:
2348 return 1;
2349 }
2350 gen_op_iwmmxt_movq_wRn_M0(wrd);
2351 gen_op_iwmmxt_set_mup();
2352 break;
d00584b7 2353 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
18c9b560
AZ
2354 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2355 wrd = (insn >> 12) & 0xf;
2356 rd0 = (insn >> 16) & 0xf;
2357 rd1 = (insn >> 0) & 0xf;
2358 gen_op_iwmmxt_movq_M0_wRn(rd0);
2359 switch ((insn >> 22) & 3) {
2360 case 0:
2361 if (insn & (1 << 21))
2362 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2363 else
2364 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2365 break;
2366 case 1:
2367 if (insn & (1 << 21))
2368 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2369 else
2370 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2371 break;
2372 case 2:
2373 if (insn & (1 << 21))
2374 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2375 else
2376 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2377 break;
2378 case 3:
2379 return 1;
2380 }
2381 gen_op_iwmmxt_movq_wRn_M0(wrd);
2382 gen_op_iwmmxt_set_mup();
2383 break;
d00584b7 2384 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
18c9b560
AZ
2385 case 0x402: case 0x502: case 0x602: case 0x702:
2386 wrd = (insn >> 12) & 0xf;
2387 rd0 = (insn >> 16) & 0xf;
2388 rd1 = (insn >> 0) & 0xf;
2389 gen_op_iwmmxt_movq_M0_wRn(rd0);
da6b5335
FN
2390 tmp = tcg_const_i32((insn >> 20) & 3);
2391 iwmmxt_load_reg(cpu_V1, rd1);
2392 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
39d5492a 2393 tcg_temp_free_i32(tmp);
18c9b560
AZ
2394 gen_op_iwmmxt_movq_wRn_M0(wrd);
2395 gen_op_iwmmxt_set_mup();
2396 break;
d00584b7 2397 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
18c9b560
AZ
2398 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2399 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2400 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2401 wrd = (insn >> 12) & 0xf;
2402 rd0 = (insn >> 16) & 0xf;
2403 rd1 = (insn >> 0) & 0xf;
2404 gen_op_iwmmxt_movq_M0_wRn(rd0);
2405 switch ((insn >> 20) & 0xf) {
2406 case 0x0:
2407 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2408 break;
2409 case 0x1:
2410 gen_op_iwmmxt_subub_M0_wRn(rd1);
2411 break;
2412 case 0x3:
2413 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2414 break;
2415 case 0x4:
2416 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2417 break;
2418 case 0x5:
2419 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2420 break;
2421 case 0x7:
2422 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2423 break;
2424 case 0x8:
2425 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2426 break;
2427 case 0x9:
2428 gen_op_iwmmxt_subul_M0_wRn(rd1);
2429 break;
2430 case 0xb:
2431 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2432 break;
2433 default:
2434 return 1;
2435 }
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 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
18c9b560
AZ
2441 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2442 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2443 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2444 wrd = (insn >> 12) & 0xf;
2445 rd0 = (insn >> 16) & 0xf;
2446 gen_op_iwmmxt_movq_M0_wRn(rd0);
da6b5335 2447 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
477955bd 2448 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
39d5492a 2449 tcg_temp_free_i32(tmp);
18c9b560
AZ
2450 gen_op_iwmmxt_movq_wRn_M0(wrd);
2451 gen_op_iwmmxt_set_mup();
2452 gen_op_iwmmxt_set_cup();
2453 break;
d00584b7 2454 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
18c9b560
AZ
2455 case 0x418: case 0x518: case 0x618: case 0x718:
2456 case 0x818: case 0x918: case 0xa18: case 0xb18:
2457 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2458 wrd = (insn >> 12) & 0xf;
2459 rd0 = (insn >> 16) & 0xf;
2460 rd1 = (insn >> 0) & 0xf;
2461 gen_op_iwmmxt_movq_M0_wRn(rd0);
2462 switch ((insn >> 20) & 0xf) {
2463 case 0x0:
2464 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2465 break;
2466 case 0x1:
2467 gen_op_iwmmxt_addub_M0_wRn(rd1);
2468 break;
2469 case 0x3:
2470 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2471 break;
2472 case 0x4:
2473 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2474 break;
2475 case 0x5:
2476 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2477 break;
2478 case 0x7:
2479 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2480 break;
2481 case 0x8:
2482 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2483 break;
2484 case 0x9:
2485 gen_op_iwmmxt_addul_M0_wRn(rd1);
2486 break;
2487 case 0xb:
2488 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2489 break;
2490 default:
2491 return 1;
2492 }
2493 gen_op_iwmmxt_movq_wRn_M0(wrd);
2494 gen_op_iwmmxt_set_mup();
2495 gen_op_iwmmxt_set_cup();
2496 break;
d00584b7 2497 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
18c9b560
AZ
2498 case 0x408: case 0x508: case 0x608: case 0x708:
2499 case 0x808: case 0x908: case 0xa08: case 0xb08:
2500 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
da6b5335
FN
2501 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2502 return 1;
18c9b560
AZ
2503 wrd = (insn >> 12) & 0xf;
2504 rd0 = (insn >> 16) & 0xf;
2505 rd1 = (insn >> 0) & 0xf;
2506 gen_op_iwmmxt_movq_M0_wRn(rd0);
18c9b560 2507 switch ((insn >> 22) & 3) {
18c9b560
AZ
2508 case 1:
2509 if (insn & (1 << 21))
2510 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2511 else
2512 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2513 break;
2514 case 2:
2515 if (insn & (1 << 21))
2516 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2517 else
2518 gen_op_iwmmxt_packul_M0_wRn(rd1);
2519 break;
2520 case 3:
2521 if (insn & (1 << 21))
2522 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2523 else
2524 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2525 break;
2526 }
2527 gen_op_iwmmxt_movq_wRn_M0(wrd);
2528 gen_op_iwmmxt_set_mup();
2529 gen_op_iwmmxt_set_cup();
2530 break;
2531 case 0x201: case 0x203: case 0x205: case 0x207:
2532 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2533 case 0x211: case 0x213: case 0x215: case 0x217:
2534 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2535 wrd = (insn >> 5) & 0xf;
2536 rd0 = (insn >> 12) & 0xf;
2537 rd1 = (insn >> 0) & 0xf;
2538 if (rd0 == 0xf || rd1 == 0xf)
2539 return 1;
2540 gen_op_iwmmxt_movq_M0_wRn(wrd);
da6b5335
FN
2541 tmp = load_reg(s, rd0);
2542 tmp2 = load_reg(s, rd1);
18c9b560 2543 switch ((insn >> 16) & 0xf) {
d00584b7 2544 case 0x0: /* TMIA */
da6b5335 2545 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560 2546 break;
d00584b7 2547 case 0x8: /* TMIAPH */
da6b5335 2548 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560 2549 break;
d00584b7 2550 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
18c9b560 2551 if (insn & (1 << 16))
da6b5335 2552 tcg_gen_shri_i32(tmp, tmp, 16);
18c9b560 2553 if (insn & (1 << 17))
da6b5335
FN
2554 tcg_gen_shri_i32(tmp2, tmp2, 16);
2555 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2556 break;
2557 default:
7d1b0095
PM
2558 tcg_temp_free_i32(tmp2);
2559 tcg_temp_free_i32(tmp);
18c9b560
AZ
2560 return 1;
2561 }
7d1b0095
PM
2562 tcg_temp_free_i32(tmp2);
2563 tcg_temp_free_i32(tmp);
18c9b560
AZ
2564 gen_op_iwmmxt_movq_wRn_M0(wrd);
2565 gen_op_iwmmxt_set_mup();
2566 break;
2567 default:
2568 return 1;
2569 }
2570
2571 return 0;
2572}
2573
a1c7273b 2574/* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
18c9b560 2575 (ie. an undefined instruction). */
7dcc1f89 2576static int disas_dsp_insn(DisasContext *s, uint32_t insn)
18c9b560
AZ
2577{
2578 int acc, rd0, rd1, rdhi, rdlo;
39d5492a 2579 TCGv_i32 tmp, tmp2;
18c9b560
AZ
2580
2581 if ((insn & 0x0ff00f10) == 0x0e200010) {
2582 /* Multiply with Internal Accumulate Format */
2583 rd0 = (insn >> 12) & 0xf;
2584 rd1 = insn & 0xf;
2585 acc = (insn >> 5) & 7;
2586
2587 if (acc != 0)
2588 return 1;
2589
3a554c0f
FN
2590 tmp = load_reg(s, rd0);
2591 tmp2 = load_reg(s, rd1);
18c9b560 2592 switch ((insn >> 16) & 0xf) {
d00584b7 2593 case 0x0: /* MIA */
3a554c0f 2594 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560 2595 break;
d00584b7 2596 case 0x8: /* MIAPH */
3a554c0f 2597 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560 2598 break;
d00584b7
PM
2599 case 0xc: /* MIABB */
2600 case 0xd: /* MIABT */
2601 case 0xe: /* MIATB */
2602 case 0xf: /* MIATT */
18c9b560 2603 if (insn & (1 << 16))
3a554c0f 2604 tcg_gen_shri_i32(tmp, tmp, 16);
18c9b560 2605 if (insn & (1 << 17))
3a554c0f
FN
2606 tcg_gen_shri_i32(tmp2, tmp2, 16);
2607 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
18c9b560
AZ
2608 break;
2609 default:
2610 return 1;
2611 }
7d1b0095
PM
2612 tcg_temp_free_i32(tmp2);
2613 tcg_temp_free_i32(tmp);
18c9b560
AZ
2614
2615 gen_op_iwmmxt_movq_wRn_M0(acc);
2616 return 0;
2617 }
2618
2619 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2620 /* Internal Accumulator Access Format */
2621 rdhi = (insn >> 16) & 0xf;
2622 rdlo = (insn >> 12) & 0xf;
2623 acc = insn & 7;
2624
2625 if (acc != 0)
2626 return 1;
2627
d00584b7 2628 if (insn & ARM_CP_RW_BIT) { /* MRA */
3a554c0f 2629 iwmmxt_load_reg(cpu_V0, acc);
ecc7b3aa 2630 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
664b7e3b 2631 tcg_gen_extrh_i64_i32(cpu_R[rdhi], cpu_V0);
3a554c0f 2632 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
d00584b7 2633 } else { /* MAR */
3a554c0f
FN
2634 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2635 iwmmxt_store_reg(cpu_V0, acc);
18c9b560
AZ
2636 }
2637 return 0;
2638 }
2639
2640 return 1;
2641}
2642
9ee6e8bb
PB
2643#define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2644#define VFP_SREG(insn, bigbit, smallbit) \
2645 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2646#define VFP_DREG(reg, insn, bigbit, smallbit) do { \
d614a513 2647 if (arm_dc_feature(s, ARM_FEATURE_VFP3)) { \
9ee6e8bb
PB
2648 reg = (((insn) >> (bigbit)) & 0x0f) \
2649 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2650 } else { \
2651 if (insn & (1 << (smallbit))) \
2652 return 1; \
2653 reg = ((insn) >> (bigbit)) & 0x0f; \
2654 }} while (0)
2655
2656#define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2657#define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2658#define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2659#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2660#define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2661#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2662
39d5492a 2663static void gen_neon_dup_low16(TCGv_i32 var)
ad69471c 2664{
39d5492a 2665 TCGv_i32 tmp = tcg_temp_new_i32();
86831435 2666 tcg_gen_ext16u_i32(var, var);
ad69471c
PB
2667 tcg_gen_shli_i32(tmp, var, 16);
2668 tcg_gen_or_i32(var, var, tmp);
7d1b0095 2669 tcg_temp_free_i32(tmp);
ad69471c
PB
2670}
2671
39d5492a 2672static void gen_neon_dup_high16(TCGv_i32 var)
ad69471c 2673{
39d5492a 2674 TCGv_i32 tmp = tcg_temp_new_i32();
ad69471c
PB
2675 tcg_gen_andi_i32(var, var, 0xffff0000);
2676 tcg_gen_shri_i32(tmp, var, 16);
2677 tcg_gen_or_i32(var, var, tmp);
7d1b0095 2678 tcg_temp_free_i32(tmp);
ad69471c
PB
2679}
2680
06db8196
PM
2681/*
2682 * Disassemble a VFP instruction. Returns nonzero if an error occurred
2683 * (ie. an undefined instruction).
2684 */
7dcc1f89 2685static int disas_vfp_insn(DisasContext *s, uint32_t insn)
b7bcbe95 2686{
d614a513 2687 if (!arm_dc_feature(s, ARM_FEATURE_VFP)) {
40f137e1 2688 return 1;
d614a513 2689 }
40f137e1 2690
78e138bc
PM
2691 /*
2692 * If the decodetree decoder handles this insn it will always
2693 * emit code to either execute the insn or generate an appropriate
2694 * exception; so we don't need to ever return non-zero to tell
2695 * the calling code to emit an UNDEF exception.
2696 */
2697 if (extract32(insn, 28, 4) == 0xf) {
2698 if (disas_vfp_uncond(s, insn)) {
2699 return 0;
2700 }
2701 } else {
2702 if (disas_vfp(s, insn)) {
2703 return 0;
2704 }
2705 }
3111bfc2
PM
2706 /* If the decodetree decoder didn't handle this insn, it must be UNDEF */
2707 return 1;
b7bcbe95
FB
2708}
2709
90aa39a1 2710static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
c53be334 2711{
90aa39a1 2712#ifndef CONFIG_USER_ONLY
dcba3a8d 2713 return (s->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
a0415916 2714 ((s->base.pc_next - 1) & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
90aa39a1
SF
2715#else
2716 return true;
2717#endif
2718}
6e256c93 2719
8a6b28c7
EC
2720static void gen_goto_ptr(void)
2721{
7f11636d 2722 tcg_gen_lookup_and_goto_ptr();
8a6b28c7
EC
2723}
2724
4cae8f56
AB
2725/* This will end the TB but doesn't guarantee we'll return to
2726 * cpu_loop_exec. Any live exit_requests will be processed as we
2727 * enter the next TB.
2728 */
8a6b28c7 2729static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
90aa39a1
SF
2730{
2731 if (use_goto_tb(s, dest)) {
57fec1fe 2732 tcg_gen_goto_tb(n);
eaed129d 2733 gen_set_pc_im(s, dest);
07ea28b4 2734 tcg_gen_exit_tb(s->base.tb, n);
6e256c93 2735 } else {
eaed129d 2736 gen_set_pc_im(s, dest);
8a6b28c7 2737 gen_goto_ptr();
6e256c93 2738 }
dcba3a8d 2739 s->base.is_jmp = DISAS_NORETURN;
c53be334
FB
2740}
2741
8aaca4c0
FB
2742static inline void gen_jmp (DisasContext *s, uint32_t dest)
2743{
b636649f 2744 if (unlikely(is_singlestepping(s))) {
8aaca4c0 2745 /* An indirect jump so that we still trigger the debug exception. */
5899f386 2746 if (s->thumb)
d9ba4830
PB
2747 dest |= 1;
2748 gen_bx_im(s, dest);
8aaca4c0 2749 } else {
6e256c93 2750 gen_goto_tb(s, 0, dest);
8aaca4c0
FB
2751 }
2752}
2753
39d5492a 2754static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
b5ff1b31 2755{
ee097184 2756 if (x)
d9ba4830 2757 tcg_gen_sari_i32(t0, t0, 16);
b5ff1b31 2758 else
d9ba4830 2759 gen_sxth(t0);
ee097184 2760 if (y)
d9ba4830 2761 tcg_gen_sari_i32(t1, t1, 16);
b5ff1b31 2762 else
d9ba4830
PB
2763 gen_sxth(t1);
2764 tcg_gen_mul_i32(t0, t0, t1);
b5ff1b31
FB
2765}
2766
2767/* Return the mask of PSR bits set by a MSR instruction. */
7dcc1f89
PM
2768static uint32_t msr_mask(DisasContext *s, int flags, int spsr)
2769{
b5ff1b31
FB
2770 uint32_t mask;
2771
2772 mask = 0;
2773 if (flags & (1 << 0))
2774 mask |= 0xff;
2775 if (flags & (1 << 1))
2776 mask |= 0xff00;
2777 if (flags & (1 << 2))
2778 mask |= 0xff0000;
2779 if (flags & (1 << 3))
2780 mask |= 0xff000000;
9ee6e8bb 2781
2ae23e75 2782 /* Mask out undefined bits. */
9ee6e8bb 2783 mask &= ~CPSR_RESERVED;
d614a513 2784 if (!arm_dc_feature(s, ARM_FEATURE_V4T)) {
be5e7a76 2785 mask &= ~CPSR_T;
d614a513
PM
2786 }
2787 if (!arm_dc_feature(s, ARM_FEATURE_V5)) {
be5e7a76 2788 mask &= ~CPSR_Q; /* V5TE in reality*/
d614a513
PM
2789 }
2790 if (!arm_dc_feature(s, ARM_FEATURE_V6)) {
e160c51c 2791 mask &= ~(CPSR_E | CPSR_GE);
d614a513
PM
2792 }
2793 if (!arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
e160c51c 2794 mask &= ~CPSR_IT;
d614a513 2795 }
4051e12c
PM
2796 /* Mask out execution state and reserved bits. */
2797 if (!spsr) {
2798 mask &= ~(CPSR_EXEC | CPSR_RESERVED);
2799 }
b5ff1b31
FB
2800 /* Mask out privileged bits. */
2801 if (IS_USER(s))
9ee6e8bb 2802 mask &= CPSR_USER;
b5ff1b31
FB
2803 return mask;
2804}
2805
2fbac54b 2806/* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
39d5492a 2807static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
b5ff1b31 2808{
39d5492a 2809 TCGv_i32 tmp;
b5ff1b31
FB
2810 if (spsr) {
2811 /* ??? This is also undefined in system mode. */
2812 if (IS_USER(s))
2813 return 1;
d9ba4830
PB
2814
2815 tmp = load_cpu_field(spsr);
2816 tcg_gen_andi_i32(tmp, tmp, ~mask);
2fbac54b
FN
2817 tcg_gen_andi_i32(t0, t0, mask);
2818 tcg_gen_or_i32(tmp, tmp, t0);
d9ba4830 2819 store_cpu_field(tmp, spsr);
b5ff1b31 2820 } else {
2fbac54b 2821 gen_set_cpsr(t0, mask);
b5ff1b31 2822 }
7d1b0095 2823 tcg_temp_free_i32(t0);
b5ff1b31
FB
2824 gen_lookup_tb(s);
2825 return 0;
2826}
2827
2fbac54b
FN
2828/* Returns nonzero if access to the PSR is not permitted. */
2829static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
2830{
39d5492a 2831 TCGv_i32 tmp;
7d1b0095 2832 tmp = tcg_temp_new_i32();
2fbac54b
FN
2833 tcg_gen_movi_i32(tmp, val);
2834 return gen_set_psr(s, mask, spsr, tmp);
2835}
2836
8bfd0550
PM
2837static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
2838 int *tgtmode, int *regno)
2839{
2840 /* Decode the r and sysm fields of MSR/MRS banked accesses into
2841 * the target mode and register number, and identify the various
2842 * unpredictable cases.
2843 * MSR (banked) and MRS (banked) are CONSTRAINED UNPREDICTABLE if:
2844 * + executed in user mode
2845 * + using R15 as the src/dest register
2846 * + accessing an unimplemented register
2847 * + accessing a register that's inaccessible at current PL/security state*
2848 * + accessing a register that you could access with a different insn
2849 * We choose to UNDEF in all these cases.
2850 * Since we don't know which of the various AArch32 modes we are in
2851 * we have to defer some checks to runtime.
2852 * Accesses to Monitor mode registers from Secure EL1 (which implies
2853 * that EL3 is AArch64) must trap to EL3.
2854 *
2855 * If the access checks fail this function will emit code to take
2856 * an exception and return false. Otherwise it will return true,
2857 * and set *tgtmode and *regno appropriately.
2858 */
2859 int exc_target = default_exception_el(s);
2860
2861 /* These instructions are present only in ARMv8, or in ARMv7 with the
2862 * Virtualization Extensions.
2863 */
2864 if (!arm_dc_feature(s, ARM_FEATURE_V8) &&
2865 !arm_dc_feature(s, ARM_FEATURE_EL2)) {
2866 goto undef;
2867 }
2868
2869 if (IS_USER(s) || rn == 15) {
2870 goto undef;
2871 }
2872
2873 /* The table in the v8 ARM ARM section F5.2.3 describes the encoding
2874 * of registers into (r, sysm).
2875 */
2876 if (r) {
2877 /* SPSRs for other modes */
2878 switch (sysm) {
2879 case 0xe: /* SPSR_fiq */
2880 *tgtmode = ARM_CPU_MODE_FIQ;
2881 break;
2882 case 0x10: /* SPSR_irq */
2883 *tgtmode = ARM_CPU_MODE_IRQ;
2884 break;
2885 case 0x12: /* SPSR_svc */
2886 *tgtmode = ARM_CPU_MODE_SVC;
2887 break;
2888 case 0x14: /* SPSR_abt */
2889 *tgtmode = ARM_CPU_MODE_ABT;
2890 break;
2891 case 0x16: /* SPSR_und */
2892 *tgtmode = ARM_CPU_MODE_UND;
2893 break;
2894 case 0x1c: /* SPSR_mon */
2895 *tgtmode = ARM_CPU_MODE_MON;
2896 break;
2897 case 0x1e: /* SPSR_hyp */
2898 *tgtmode = ARM_CPU_MODE_HYP;
2899 break;
2900 default: /* unallocated */
2901 goto undef;
2902 }
2903 /* We arbitrarily assign SPSR a register number of 16. */
2904 *regno = 16;
2905 } else {
2906 /* general purpose registers for other modes */
2907 switch (sysm) {
2908 case 0x0 ... 0x6: /* 0b00xxx : r8_usr ... r14_usr */
2909 *tgtmode = ARM_CPU_MODE_USR;
2910 *regno = sysm + 8;
2911 break;
2912 case 0x8 ... 0xe: /* 0b01xxx : r8_fiq ... r14_fiq */
2913 *tgtmode = ARM_CPU_MODE_FIQ;
2914 *regno = sysm;
2915 break;
2916 case 0x10 ... 0x11: /* 0b1000x : r14_irq, r13_irq */
2917 *tgtmode = ARM_CPU_MODE_IRQ;
2918 *regno = sysm & 1 ? 13 : 14;
2919 break;
2920 case 0x12 ... 0x13: /* 0b1001x : r14_svc, r13_svc */
2921 *tgtmode = ARM_CPU_MODE_SVC;
2922 *regno = sysm & 1 ? 13 : 14;
2923 break;
2924 case 0x14 ... 0x15: /* 0b1010x : r14_abt, r13_abt */
2925 *tgtmode = ARM_CPU_MODE_ABT;
2926 *regno = sysm & 1 ? 13 : 14;
2927 break;
2928 case 0x16 ... 0x17: /* 0b1011x : r14_und, r13_und */
2929 *tgtmode = ARM_CPU_MODE_UND;
2930 *regno = sysm & 1 ? 13 : 14;
2931 break;
2932 case 0x1c ... 0x1d: /* 0b1110x : r14_mon, r13_mon */
2933 *tgtmode = ARM_CPU_MODE_MON;
2934 *regno = sysm & 1 ? 13 : 14;
2935 break;
2936 case 0x1e ... 0x1f: /* 0b1111x : elr_hyp, r13_hyp */
2937 *tgtmode = ARM_CPU_MODE_HYP;
2938 /* Arbitrarily pick 17 for ELR_Hyp (which is not a banked LR!) */
2939 *regno = sysm & 1 ? 13 : 17;
2940 break;
2941 default: /* unallocated */
2942 goto undef;
2943 }
2944 }
2945
2946 /* Catch the 'accessing inaccessible register' cases we can detect
2947 * at translate time.
2948 */
2949 switch (*tgtmode) {
2950 case ARM_CPU_MODE_MON:
2951 if (!arm_dc_feature(s, ARM_FEATURE_EL3) || s->ns) {
2952 goto undef;
2953 }
2954 if (s->current_el == 1) {
2955 /* If we're in Secure EL1 (which implies that EL3 is AArch64)
2956 * then accesses to Mon registers trap to EL3
2957 */
2958 exc_target = 3;
2959 goto undef;
2960 }
2961 break;
2962 case ARM_CPU_MODE_HYP:
aec4dd09
PM
2963 /*
2964 * SPSR_hyp and r13_hyp can only be accessed from Monitor mode
2965 * (and so we can forbid accesses from EL2 or below). elr_hyp
2966 * can be accessed also from Hyp mode, so forbid accesses from
2967 * EL0 or EL1.
8bfd0550 2968 */
aec4dd09
PM
2969 if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el < 2 ||
2970 (s->current_el < 3 && *regno != 17)) {
8bfd0550
PM
2971 goto undef;
2972 }
2973 break;
2974 default:
2975 break;
2976 }
2977
2978 return true;
2979
2980undef:
2981 /* If we get here then some access check did not pass */
a767fac8
RH
2982 gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
2983 syn_uncategorized(), exc_target);
8bfd0550
PM
2984 return false;
2985}
2986
2987static void gen_msr_banked(DisasContext *s, int r, int sysm, int rn)
2988{
2989 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
2990 int tgtmode = 0, regno = 0;
2991
2992 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
2993 return;
2994 }
2995
2996 /* Sync state because msr_banked() can raise exceptions */
2997 gen_set_condexec(s);
43722a6d 2998 gen_set_pc_im(s, s->pc_curr);
8bfd0550
PM
2999 tcg_reg = load_reg(s, rn);
3000 tcg_tgtmode = tcg_const_i32(tgtmode);
3001 tcg_regno = tcg_const_i32(regno);
3002 gen_helper_msr_banked(cpu_env, tcg_reg, tcg_tgtmode, tcg_regno);
3003 tcg_temp_free_i32(tcg_tgtmode);
3004 tcg_temp_free_i32(tcg_regno);
3005 tcg_temp_free_i32(tcg_reg);
dcba3a8d 3006 s->base.is_jmp = DISAS_UPDATE;
8bfd0550
PM
3007}
3008
3009static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn)
3010{
3011 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
3012 int tgtmode = 0, regno = 0;
3013
3014 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
3015 return;
3016 }
3017
3018 /* Sync state because mrs_banked() can raise exceptions */
3019 gen_set_condexec(s);
43722a6d 3020 gen_set_pc_im(s, s->pc_curr);
8bfd0550
PM
3021 tcg_reg = tcg_temp_new_i32();
3022 tcg_tgtmode = tcg_const_i32(tgtmode);
3023 tcg_regno = tcg_const_i32(regno);
3024 gen_helper_mrs_banked(tcg_reg, cpu_env, tcg_tgtmode, tcg_regno);
3025 tcg_temp_free_i32(tcg_tgtmode);
3026 tcg_temp_free_i32(tcg_regno);
3027 store_reg(s, rn, tcg_reg);
dcba3a8d 3028 s->base.is_jmp = DISAS_UPDATE;
8bfd0550
PM
3029}
3030
fb0e8e79
PM
3031/* Store value to PC as for an exception return (ie don't
3032 * mask bits). The subsequent call to gen_helper_cpsr_write_eret()
3033 * will do the masking based on the new value of the Thumb bit.
3034 */
3035static void store_pc_exc_ret(DisasContext *s, TCGv_i32 pc)
b5ff1b31 3036{
fb0e8e79
PM
3037 tcg_gen_mov_i32(cpu_R[15], pc);
3038 tcg_temp_free_i32(pc);
b5ff1b31
FB
3039}
3040
b0109805 3041/* Generate a v6 exception return. Marks both values as dead. */
39d5492a 3042static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
2c0262af 3043{
fb0e8e79
PM
3044 store_pc_exc_ret(s, pc);
3045 /* The cpsr_write_eret helper will mask the low bits of PC
3046 * appropriately depending on the new Thumb bit, so it must
3047 * be called after storing the new PC.
3048 */
e69ad9df
AL
3049 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
3050 gen_io_start();
3051 }
235ea1f5 3052 gen_helper_cpsr_write_eret(cpu_env, cpsr);
7d1b0095 3053 tcg_temp_free_i32(cpsr);
b29fd33d 3054 /* Must exit loop to check un-masked IRQs */
dcba3a8d 3055 s->base.is_jmp = DISAS_EXIT;
9ee6e8bb 3056}
3b46e624 3057
fb0e8e79
PM
3058/* Generate an old-style exception return. Marks pc as dead. */
3059static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
3060{
3061 gen_rfe(s, pc, load_cpu_field(spsr));
3062}
3063
c22edfeb
AB
3064/*
3065 * For WFI we will halt the vCPU until an IRQ. For WFE and YIELD we
3066 * only call the helper when running single threaded TCG code to ensure
3067 * the next round-robin scheduled vCPU gets a crack. In MTTCG mode we
3068 * just skip this instruction. Currently the SEV/SEVL instructions
3069 * which are *one* of many ways to wake the CPU from WFE are not
3070 * implemented so we can't sleep like WFI does.
3071 */
9ee6e8bb
PB
3072static void gen_nop_hint(DisasContext *s, int val)
3073{
3074 switch (val) {
2399d4e7
EC
3075 /* When running in MTTCG we don't generate jumps to the yield and
3076 * WFE helpers as it won't affect the scheduling of other vCPUs.
3077 * If we wanted to more completely model WFE/SEV so we don't busy
3078 * spin unnecessarily we would need to do something more involved.
3079 */
c87e5a61 3080 case 1: /* yield */
2399d4e7 3081 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
a0415916 3082 gen_set_pc_im(s, s->base.pc_next);
dcba3a8d 3083 s->base.is_jmp = DISAS_YIELD;
c22edfeb 3084 }
c87e5a61 3085 break;
9ee6e8bb 3086 case 3: /* wfi */
a0415916 3087 gen_set_pc_im(s, s->base.pc_next);
dcba3a8d 3088 s->base.is_jmp = DISAS_WFI;
9ee6e8bb
PB
3089 break;
3090 case 2: /* wfe */
2399d4e7 3091 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
a0415916 3092 gen_set_pc_im(s, s->base.pc_next);
dcba3a8d 3093 s->base.is_jmp = DISAS_WFE;
c22edfeb 3094 }
72c1d3af 3095 break;
9ee6e8bb 3096 case 4: /* sev */
12b10571
MR
3097 case 5: /* sevl */
3098 /* TODO: Implement SEV, SEVL and WFE. May help SMP performance. */
9ee6e8bb
PB
3099 default: /* nop */
3100 break;
3101 }
3102}
99c475ab 3103
ad69471c 3104#define CPU_V001 cpu_V0, cpu_V0, cpu_V1
9ee6e8bb 3105
39d5492a 3106static inline void gen_neon_add(int size, TCGv_i32 t0, TCGv_i32 t1)
9ee6e8bb
PB
3107{
3108 switch (size) {
dd8fbd78
FN
3109 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
3110 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
3111 case 2: tcg_gen_add_i32(t0, t0, t1); break;
62698be3 3112 default: abort();
9ee6e8bb 3113 }
9ee6e8bb
PB
3114}
3115
39d5492a 3116static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
ad69471c
PB
3117{
3118 switch (size) {
dd8fbd78
FN
3119 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
3120 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
3121 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
ad69471c
PB
3122 default: return;
3123 }
3124}
3125
3126/* 32-bit pairwise ops end up the same as the elementwise versions. */
9ecd3c5c
RH
3127#define gen_helper_neon_pmax_s32 tcg_gen_smax_i32
3128#define gen_helper_neon_pmax_u32 tcg_gen_umax_i32
3129#define gen_helper_neon_pmin_s32 tcg_gen_smin_i32
3130#define gen_helper_neon_pmin_u32 tcg_gen_umin_i32
ad69471c 3131
ad69471c
PB
3132#define GEN_NEON_INTEGER_OP_ENV(name) do { \
3133 switch ((size << 1) | u) { \
3134 case 0: \
dd8fbd78 3135 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
3136 break; \
3137 case 1: \
dd8fbd78 3138 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
3139 break; \
3140 case 2: \
dd8fbd78 3141 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
3142 break; \
3143 case 3: \
dd8fbd78 3144 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
3145 break; \
3146 case 4: \
dd8fbd78 3147 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
3148 break; \
3149 case 5: \
dd8fbd78 3150 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
ad69471c
PB
3151 break; \
3152 default: return 1; \
3153 }} while (0)
9ee6e8bb
PB
3154
3155#define GEN_NEON_INTEGER_OP(name) do { \
3156 switch ((size << 1) | u) { \
ad69471c 3157 case 0: \
dd8fbd78 3158 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
ad69471c
PB
3159 break; \
3160 case 1: \
dd8fbd78 3161 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
ad69471c
PB
3162 break; \
3163 case 2: \
dd8fbd78 3164 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
ad69471c
PB
3165 break; \
3166 case 3: \
dd8fbd78 3167 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
ad69471c
PB
3168 break; \
3169 case 4: \
dd8fbd78 3170 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
ad69471c
PB
3171 break; \
3172 case 5: \
dd8fbd78 3173 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
ad69471c 3174 break; \
9ee6e8bb
PB
3175 default: return 1; \
3176 }} while (0)
3177
39d5492a 3178static TCGv_i32 neon_load_scratch(int scratch)
9ee6e8bb 3179{
39d5492a 3180 TCGv_i32 tmp = tcg_temp_new_i32();
dd8fbd78
FN
3181 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3182 return tmp;
9ee6e8bb
PB
3183}
3184
39d5492a 3185static void neon_store_scratch(int scratch, TCGv_i32 var)
9ee6e8bb 3186{
dd8fbd78 3187 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
7d1b0095 3188 tcg_temp_free_i32(var);
9ee6e8bb
PB
3189}
3190
39d5492a 3191static inline TCGv_i32 neon_get_scalar(int size, int reg)
9ee6e8bb 3192{
39d5492a 3193 TCGv_i32 tmp;
9ee6e8bb 3194 if (size == 1) {
0fad6efc
PM
3195 tmp = neon_load_reg(reg & 7, reg >> 4);
3196 if (reg & 8) {
dd8fbd78 3197 gen_neon_dup_high16(tmp);
0fad6efc
PM
3198 } else {
3199 gen_neon_dup_low16(tmp);
dd8fbd78 3200 }
0fad6efc
PM
3201 } else {
3202 tmp = neon_load_reg(reg & 15, reg >> 4);
9ee6e8bb 3203 }
dd8fbd78 3204 return tmp;
9ee6e8bb
PB
3205}
3206
02acedf9 3207static int gen_neon_unzip(int rd, int rm, int size, int q)
19457615 3208{
b13708bb
RH
3209 TCGv_ptr pd, pm;
3210
600b828c 3211 if (!q && size == 2) {
02acedf9
PM
3212 return 1;
3213 }
b13708bb
RH
3214 pd = vfp_reg_ptr(true, rd);
3215 pm = vfp_reg_ptr(true, rm);
02acedf9
PM
3216 if (q) {
3217 switch (size) {
3218 case 0:
b13708bb 3219 gen_helper_neon_qunzip8(pd, pm);
02acedf9
PM
3220 break;
3221 case 1:
b13708bb 3222 gen_helper_neon_qunzip16(pd, pm);
02acedf9
PM
3223 break;
3224 case 2:
b13708bb 3225 gen_helper_neon_qunzip32(pd, pm);
02acedf9
PM
3226 break;
3227 default:
3228 abort();
3229 }
3230 } else {
3231 switch (size) {
3232 case 0:
b13708bb 3233 gen_helper_neon_unzip8(pd, pm);
02acedf9
PM
3234 break;
3235 case 1:
b13708bb 3236 gen_helper_neon_unzip16(pd, pm);
02acedf9
PM
3237 break;
3238 default:
3239 abort();
3240 }
3241 }
b13708bb
RH
3242 tcg_temp_free_ptr(pd);
3243 tcg_temp_free_ptr(pm);
02acedf9 3244 return 0;
19457615
FN
3245}
3246
d68a6f3a 3247static int gen_neon_zip(int rd, int rm, int size, int q)
19457615 3248{
b13708bb
RH
3249 TCGv_ptr pd, pm;
3250
600b828c 3251 if (!q && size == 2) {
d68a6f3a
PM
3252 return 1;
3253 }
b13708bb
RH
3254 pd = vfp_reg_ptr(true, rd);
3255 pm = vfp_reg_ptr(true, rm);
d68a6f3a
PM
3256 if (q) {
3257 switch (size) {
3258 case 0:
b13708bb 3259 gen_helper_neon_qzip8(pd, pm);
d68a6f3a
PM
3260 break;
3261 case 1:
b13708bb 3262 gen_helper_neon_qzip16(pd, pm);
d68a6f3a
PM
3263 break;
3264 case 2:
b13708bb 3265 gen_helper_neon_qzip32(pd, pm);
d68a6f3a
PM
3266 break;
3267 default:
3268 abort();
3269 }
3270 } else {
3271 switch (size) {
3272 case 0:
b13708bb 3273 gen_helper_neon_zip8(pd, pm);
d68a6f3a
PM
3274 break;
3275 case 1:
b13708bb 3276 gen_helper_neon_zip16(pd, pm);
d68a6f3a
PM
3277 break;
3278 default:
3279 abort();
3280 }
3281 }
b13708bb
RH
3282 tcg_temp_free_ptr(pd);
3283 tcg_temp_free_ptr(pm);
d68a6f3a 3284 return 0;
19457615
FN
3285}
3286
39d5492a 3287static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
19457615 3288{
39d5492a 3289 TCGv_i32 rd, tmp;
19457615 3290
7d1b0095
PM
3291 rd = tcg_temp_new_i32();
3292 tmp = tcg_temp_new_i32();
19457615
FN
3293
3294 tcg_gen_shli_i32(rd, t0, 8);
3295 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3296 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3297 tcg_gen_or_i32(rd, rd, tmp);
3298
3299 tcg_gen_shri_i32(t1, t1, 8);
3300 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3301 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3302 tcg_gen_or_i32(t1, t1, tmp);
3303 tcg_gen_mov_i32(t0, rd);
3304
7d1b0095
PM
3305 tcg_temp_free_i32(tmp);
3306 tcg_temp_free_i32(rd);
19457615
FN
3307}
3308
39d5492a 3309static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
19457615 3310{
39d5492a 3311 TCGv_i32 rd, tmp;
19457615 3312
7d1b0095
PM
3313 rd = tcg_temp_new_i32();
3314 tmp = tcg_temp_new_i32();
19457615
FN
3315
3316 tcg_gen_shli_i32(rd, t0, 16);
3317 tcg_gen_andi_i32(tmp, t1, 0xffff);
3318 tcg_gen_or_i32(rd, rd, tmp);
3319 tcg_gen_shri_i32(t1, t1, 16);
3320 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3321 tcg_gen_or_i32(t1, t1, tmp);
3322 tcg_gen_mov_i32(t0, rd);
3323
7d1b0095
PM
3324 tcg_temp_free_i32(tmp);
3325 tcg_temp_free_i32(rd);
19457615
FN
3326}
3327
3328
9ee6e8bb
PB
3329static struct {
3330 int nregs;
3331 int interleave;
3332 int spacing;
308e5636 3333} const neon_ls_element_type[11] = {
ac55d007
RH
3334 {1, 4, 1},
3335 {1, 4, 2},
9ee6e8bb 3336 {4, 1, 1},
ac55d007
RH
3337 {2, 2, 2},
3338 {1, 3, 1},
3339 {1, 3, 2},
9ee6e8bb
PB
3340 {3, 1, 1},
3341 {1, 1, 1},
ac55d007
RH
3342 {1, 2, 1},
3343 {1, 2, 2},
9ee6e8bb
PB
3344 {2, 1, 1}
3345};
3346
3347/* Translate a NEON load/store element instruction. Return nonzero if the
3348 instruction is invalid. */
7dcc1f89 3349static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
9ee6e8bb
PB
3350{
3351 int rd, rn, rm;
3352 int op;
3353 int nregs;
3354 int interleave;
84496233 3355 int spacing;
9ee6e8bb
PB
3356 int stride;
3357 int size;
3358 int reg;
9ee6e8bb 3359 int load;
9ee6e8bb 3360 int n;
7377c2c9 3361 int vec_size;
ac55d007 3362 int mmu_idx;
14776ab5 3363 MemOp endian;
39d5492a
PM
3364 TCGv_i32 addr;
3365 TCGv_i32 tmp;
3366 TCGv_i32 tmp2;
84496233 3367 TCGv_i64 tmp64;
9ee6e8bb 3368
2c7ffc41
PM
3369 /* FIXME: this access check should not take precedence over UNDEF
3370 * for invalid encodings; we will generate incorrect syndrome information
3371 * for attempts to execute invalid vfp/neon encodings with FP disabled.
3372 */
9dbbc748 3373 if (s->fp_excp_el) {
a767fac8 3374 gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
4be42f40 3375 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
2c7ffc41
PM
3376 return 0;
3377 }
3378
5df8bac1 3379 if (!s->vfp_enabled)
9ee6e8bb
PB
3380 return 1;
3381 VFP_DREG_D(rd, insn);
3382 rn = (insn >> 16) & 0xf;
3383 rm = insn & 0xf;
3384 load = (insn & (1 << 21)) != 0;
ac55d007
RH
3385 endian = s->be_data;
3386 mmu_idx = get_mem_index(s);
9ee6e8bb
PB
3387 if ((insn & (1 << 23)) == 0) {
3388 /* Load store all elements. */
3389 op = (insn >> 8) & 0xf;
3390 size = (insn >> 6) & 3;
84496233 3391 if (op > 10)
9ee6e8bb 3392 return 1;
f2dd89d0
PM
3393 /* Catch UNDEF cases for bad values of align field */
3394 switch (op & 0xc) {
3395 case 4:
3396 if (((insn >> 5) & 1) == 1) {
3397 return 1;
3398 }
3399 break;
3400 case 8:
3401 if (((insn >> 4) & 3) == 3) {
3402 return 1;
3403 }
3404 break;
3405 default:
3406 break;
3407 }
9ee6e8bb
PB
3408 nregs = neon_ls_element_type[op].nregs;
3409 interleave = neon_ls_element_type[op].interleave;
84496233 3410 spacing = neon_ls_element_type[op].spacing;
ac55d007 3411 if (size == 3 && (interleave | spacing) != 1) {
84496233 3412 return 1;
ac55d007 3413 }
e23f12b3
RH
3414 /* For our purposes, bytes are always little-endian. */
3415 if (size == 0) {
3416 endian = MO_LE;
3417 }
3418 /* Consecutive little-endian elements from a single register
3419 * can be promoted to a larger little-endian operation.
3420 */
3421 if (interleave == 1 && endian == MO_LE) {
3422 size = 3;
3423 }
ac55d007 3424 tmp64 = tcg_temp_new_i64();
e318a60b 3425 addr = tcg_temp_new_i32();
ac55d007 3426 tmp2 = tcg_const_i32(1 << size);
dcc65026 3427 load_reg_var(s, addr, rn);
9ee6e8bb 3428 for (reg = 0; reg < nregs; reg++) {
ac55d007
RH
3429 for (n = 0; n < 8 >> size; n++) {
3430 int xs;
3431 for (xs = 0; xs < interleave; xs++) {
3432 int tt = rd + reg + spacing * xs;
3433
3434 if (load) {
3435 gen_aa32_ld_i64(s, tmp64, addr, mmu_idx, endian | size);
3436 neon_store_element64(tt, n, size, tmp64);
3437 } else {
3438 neon_load_element64(tmp64, tt, n, size);
3439 gen_aa32_st_i64(s, tmp64, addr, mmu_idx, endian | size);
9ee6e8bb 3440 }
ac55d007 3441 tcg_gen_add_i32(addr, addr, tmp2);
9ee6e8bb
PB
3442 }
3443 }
9ee6e8bb 3444 }
e318a60b 3445 tcg_temp_free_i32(addr);
ac55d007
RH
3446 tcg_temp_free_i32(tmp2);
3447 tcg_temp_free_i64(tmp64);
3448 stride = nregs * interleave * 8;
9ee6e8bb
PB
3449 } else {
3450 size = (insn >> 10) & 3;
3451 if (size == 3) {
3452 /* Load single element to all lanes. */
8e18cde3
PM
3453 int a = (insn >> 4) & 1;
3454 if (!load) {
9ee6e8bb 3455 return 1;
8e18cde3 3456 }
9ee6e8bb
PB
3457 size = (insn >> 6) & 3;
3458 nregs = ((insn >> 8) & 3) + 1;
8e18cde3
PM
3459
3460 if (size == 3) {
3461 if (nregs != 4 || a == 0) {
9ee6e8bb 3462 return 1;
99c475ab 3463 }
8e18cde3
PM
3464 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
3465 size = 2;
3466 }
3467 if (nregs == 1 && a == 1 && size == 0) {
3468 return 1;
3469 }
3470 if (nregs == 3 && a == 1) {
3471 return 1;
3472 }
e318a60b 3473 addr = tcg_temp_new_i32();
8e18cde3 3474 load_reg_var(s, addr, rn);
7377c2c9
RH
3475
3476 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write.
3477 * VLD2/3/4 to all lanes: bit 5 indicates register stride.
3478 */
3479 stride = (insn & (1 << 5)) ? 2 : 1;
3480 vec_size = nregs == 1 ? stride * 8 : 8;
3481
3482 tmp = tcg_temp_new_i32();
3483 for (reg = 0; reg < nregs; reg++) {
3484 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
3485 s->be_data | size);
3486 if ((rd & 1) && vec_size == 16) {
3487 /* We cannot write 16 bytes at once because the
3488 * destination is unaligned.
3489 */
3490 tcg_gen_gvec_dup_i32(size, neon_reg_offset(rd, 0),
3491 8, 8, tmp);
3492 tcg_gen_gvec_mov(0, neon_reg_offset(rd + 1, 0),
3493 neon_reg_offset(rd, 0), 8, 8);
3494 } else {
3495 tcg_gen_gvec_dup_i32(size, neon_reg_offset(rd, 0),
3496 vec_size, vec_size, tmp);
8e18cde3 3497 }
7377c2c9
RH
3498 tcg_gen_addi_i32(addr, addr, 1 << size);
3499 rd += stride;
9ee6e8bb 3500 }
7377c2c9 3501 tcg_temp_free_i32(tmp);
e318a60b 3502 tcg_temp_free_i32(addr);
9ee6e8bb
PB
3503 stride = (1 << size) * nregs;
3504 } else {
3505 /* Single element. */
93262b16 3506 int idx = (insn >> 4) & 0xf;
2d6ac920 3507 int reg_idx;
9ee6e8bb
PB
3508 switch (size) {
3509 case 0:
2d6ac920 3510 reg_idx = (insn >> 5) & 7;
9ee6e8bb
PB
3511 stride = 1;
3512 break;
3513 case 1:
2d6ac920 3514 reg_idx = (insn >> 6) & 3;
9ee6e8bb
PB
3515 stride = (insn & (1 << 5)) ? 2 : 1;
3516 break;
3517 case 2:
2d6ac920 3518 reg_idx = (insn >> 7) & 1;
9ee6e8bb
PB
3519 stride = (insn & (1 << 6)) ? 2 : 1;
3520 break;
3521 default:
3522 abort();
3523 }
3524 nregs = ((insn >> 8) & 3) + 1;
93262b16
PM
3525 /* Catch the UNDEF cases. This is unavoidably a bit messy. */
3526 switch (nregs) {
3527 case 1:
3528 if (((idx & (1 << size)) != 0) ||
3529 (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
3530 return 1;
3531 }
3532 break;
3533 case 3:
3534 if ((idx & 1) != 0) {
3535 return 1;
3536 }
3537 /* fall through */
3538 case 2:
3539 if (size == 2 && (idx & 2) != 0) {
3540 return 1;
3541 }
3542 break;
3543 case 4:
3544 if ((size == 2) && ((idx & 3) == 3)) {
3545 return 1;
3546 }
3547 break;
3548 default:
3549 abort();
3550 }
3551 if ((rd + stride * (nregs - 1)) > 31) {
3552 /* Attempts to write off the end of the register file
3553 * are UNPREDICTABLE; we choose to UNDEF because otherwise
3554 * the neon_load_reg() would write off the end of the array.
3555 */
3556 return 1;
3557 }
2d6ac920 3558 tmp = tcg_temp_new_i32();
e318a60b 3559 addr = tcg_temp_new_i32();
dcc65026 3560 load_reg_var(s, addr, rn);
9ee6e8bb
PB
3561 for (reg = 0; reg < nregs; reg++) {
3562 if (load) {
2d6ac920
RH
3563 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
3564 s->be_data | size);
3565 neon_store_element(rd, reg_idx, size, tmp);
9ee6e8bb 3566 } else { /* Store */
2d6ac920
RH
3567 neon_load_element(tmp, rd, reg_idx, size);
3568 gen_aa32_st_i32(s, tmp, addr, get_mem_index(s),
3569 s->be_data | size);
99c475ab 3570 }
9ee6e8bb 3571 rd += stride;
1b2b1e54 3572 tcg_gen_addi_i32(addr, addr, 1 << size);
99c475ab 3573 }
e318a60b 3574 tcg_temp_free_i32(addr);
2d6ac920 3575 tcg_temp_free_i32(tmp);
9ee6e8bb 3576 stride = nregs * (1 << size);
99c475ab 3577 }
9ee6e8bb
PB
3578 }
3579 if (rm != 15) {
39d5492a 3580 TCGv_i32 base;
b26eefb6
PB
3581
3582 base = load_reg(s, rn);
9ee6e8bb 3583 if (rm == 13) {
b26eefb6 3584 tcg_gen_addi_i32(base, base, stride);
9ee6e8bb 3585 } else {
39d5492a 3586 TCGv_i32 index;
b26eefb6
PB
3587 index = load_reg(s, rm);
3588 tcg_gen_add_i32(base, base, index);
7d1b0095 3589 tcg_temp_free_i32(index);
9ee6e8bb 3590 }
b26eefb6 3591 store_reg(s, rn, base);
9ee6e8bb
PB
3592 }
3593 return 0;
3594}
3b46e624 3595
39d5492a 3596static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src)
ad69471c
PB
3597{
3598 switch (size) {
3599 case 0: gen_helper_neon_narrow_u8(dest, src); break;
3600 case 1: gen_helper_neon_narrow_u16(dest, src); break;
ecc7b3aa 3601 case 2: tcg_gen_extrl_i64_i32(dest, src); break;
ad69471c
PB
3602 default: abort();
3603 }
3604}
3605
39d5492a 3606static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
ad69471c
PB
3607{
3608 switch (size) {
02da0b2d
PM
3609 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
3610 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
3611 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
ad69471c
PB
3612 default: abort();
3613 }
3614}
3615
39d5492a 3616static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src)
ad69471c
PB
3617{
3618 switch (size) {
02da0b2d
PM
3619 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
3620 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
3621 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
ad69471c
PB
3622 default: abort();
3623 }
3624}
3625
39d5492a 3626static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
af1bbf30
JR
3627{
3628 switch (size) {
02da0b2d
PM
3629 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
3630 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
3631 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
af1bbf30
JR
3632 default: abort();
3633 }
3634}
3635
39d5492a 3636static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift,
ad69471c
PB
3637 int q, int u)
3638{
3639 if (q) {
3640 if (u) {
3641 switch (size) {
3642 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3643 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3644 default: abort();
3645 }
3646 } else {
3647 switch (size) {
3648 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
3649 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
3650 default: abort();
3651 }
3652 }
3653 } else {
3654 if (u) {
3655 switch (size) {
b408a9b0
CL
3656 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
3657 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
ad69471c
PB
3658 default: abort();
3659 }
3660 } else {
3661 switch (size) {
3662 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
3663 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
3664 default: abort();
3665 }
3666 }
3667 }
3668}
3669
39d5492a 3670static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
ad69471c
PB
3671{
3672 if (u) {
3673 switch (size) {
3674 case 0: gen_helper_neon_widen_u8(dest, src); break;
3675 case 1: gen_helper_neon_widen_u16(dest, src); break;
3676 case 2: tcg_gen_extu_i32_i64(dest, src); break;
3677 default: abort();
3678 }
3679 } else {
3680 switch (size) {
3681 case 0: gen_helper_neon_widen_s8(dest, src); break;
3682 case 1: gen_helper_neon_widen_s16(dest, src); break;
3683 case 2: tcg_gen_ext_i32_i64(dest, src); break;
3684 default: abort();
3685 }
3686 }
7d1b0095 3687 tcg_temp_free_i32(src);
ad69471c
PB
3688}
3689
3690static inline void gen_neon_addl(int size)
3691{
3692 switch (size) {
3693 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
3694 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
3695 case 2: tcg_gen_add_i64(CPU_V001); break;
3696 default: abort();
3697 }
3698}
3699
3700static inline void gen_neon_subl(int size)
3701{
3702 switch (size) {
3703 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
3704 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
3705 case 2: tcg_gen_sub_i64(CPU_V001); break;
3706 default: abort();
3707 }
3708}
3709
a7812ae4 3710static inline void gen_neon_negl(TCGv_i64 var, int size)
ad69471c
PB
3711{
3712 switch (size) {
3713 case 0: gen_helper_neon_negl_u16(var, var); break;
3714 case 1: gen_helper_neon_negl_u32(var, var); break;
ee6fa559
PM
3715 case 2:
3716 tcg_gen_neg_i64(var, var);
3717 break;
ad69471c
PB
3718 default: abort();
3719 }
3720}
3721
a7812ae4 3722static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
ad69471c
PB
3723{
3724 switch (size) {
02da0b2d
PM
3725 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
3726 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
ad69471c
PB
3727 default: abort();
3728 }
3729}
3730
39d5492a
PM
3731static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b,
3732 int size, int u)
ad69471c 3733{
a7812ae4 3734 TCGv_i64 tmp;
ad69471c
PB
3735
3736 switch ((size << 1) | u) {
3737 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
3738 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
3739 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
3740 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
3741 case 4:
3742 tmp = gen_muls_i64_i32(a, b);
3743 tcg_gen_mov_i64(dest, tmp);
7d2aabe2 3744 tcg_temp_free_i64(tmp);
ad69471c
PB
3745 break;
3746 case 5:
3747 tmp = gen_mulu_i64_i32(a, b);
3748 tcg_gen_mov_i64(dest, tmp);
7d2aabe2 3749 tcg_temp_free_i64(tmp);
ad69471c
PB
3750 break;
3751 default: abort();
3752 }
c6067f04
CL
3753
3754 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
3755 Don't forget to clean them now. */
3756 if (size < 2) {
7d1b0095
PM
3757 tcg_temp_free_i32(a);
3758 tcg_temp_free_i32(b);
c6067f04 3759 }
ad69471c
PB
3760}
3761
39d5492a
PM
3762static void gen_neon_narrow_op(int op, int u, int size,
3763 TCGv_i32 dest, TCGv_i64 src)
c33171c7
PM
3764{
3765 if (op) {
3766 if (u) {
3767 gen_neon_unarrow_sats(size, dest, src);
3768 } else {
3769 gen_neon_narrow(size, dest, src);
3770 }
3771 } else {
3772 if (u) {
3773 gen_neon_narrow_satu(size, dest, src);
3774 } else {
3775 gen_neon_narrow_sats(size, dest, src);
3776 }
3777 }
3778}
3779
62698be3
PM
3780/* Symbolic constants for op fields for Neon 3-register same-length.
3781 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
3782 * table A7-9.
3783 */
3784#define NEON_3R_VHADD 0
3785#define NEON_3R_VQADD 1
3786#define NEON_3R_VRHADD 2
3787#define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
3788#define NEON_3R_VHSUB 4
3789#define NEON_3R_VQSUB 5
3790#define NEON_3R_VCGT 6
3791#define NEON_3R_VCGE 7
3792#define NEON_3R_VSHL 8
3793#define NEON_3R_VQSHL 9
3794#define NEON_3R_VRSHL 10
3795#define NEON_3R_VQRSHL 11
3796#define NEON_3R_VMAX 12
3797#define NEON_3R_VMIN 13
3798#define NEON_3R_VABD 14
3799#define NEON_3R_VABA 15
3800#define NEON_3R_VADD_VSUB 16
3801#define NEON_3R_VTST_VCEQ 17
4a7832b0 3802#define NEON_3R_VML 18 /* VMLA, VMLS */
62698be3
PM
3803#define NEON_3R_VMUL 19
3804#define NEON_3R_VPMAX 20
3805#define NEON_3R_VPMIN 21
3806#define NEON_3R_VQDMULH_VQRDMULH 22
36a71934 3807#define NEON_3R_VPADD_VQRDMLAH 23
f1ecb913 3808#define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */
36a71934 3809#define NEON_3R_VFM_VQRDMLSH 25 /* VFMA, VFMS, VQRDMLSH */
62698be3
PM
3810#define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
3811#define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
3812#define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
3813#define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
3814#define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
505935fc 3815#define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */
62698be3
PM
3816
3817static const uint8_t neon_3r_sizes[] = {
3818 [NEON_3R_VHADD] = 0x7,
3819 [NEON_3R_VQADD] = 0xf,
3820 [NEON_3R_VRHADD] = 0x7,
3821 [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
3822 [NEON_3R_VHSUB] = 0x7,
3823 [NEON_3R_VQSUB] = 0xf,
3824 [NEON_3R_VCGT] = 0x7,
3825 [NEON_3R_VCGE] = 0x7,
3826 [NEON_3R_VSHL] = 0xf,
3827 [NEON_3R_VQSHL] = 0xf,
3828 [NEON_3R_VRSHL] = 0xf,
3829 [NEON_3R_VQRSHL] = 0xf,
3830 [NEON_3R_VMAX] = 0x7,
3831 [NEON_3R_VMIN] = 0x7,
3832 [NEON_3R_VABD] = 0x7,
3833 [NEON_3R_VABA] = 0x7,
3834 [NEON_3R_VADD_VSUB] = 0xf,
3835 [NEON_3R_VTST_VCEQ] = 0x7,
3836 [NEON_3R_VML] = 0x7,
3837 [NEON_3R_VMUL] = 0x7,
3838 [NEON_3R_VPMAX] = 0x7,
3839 [NEON_3R_VPMIN] = 0x7,
3840 [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
36a71934 3841 [NEON_3R_VPADD_VQRDMLAH] = 0x7,
f1ecb913 3842 [NEON_3R_SHA] = 0xf, /* size field encodes op type */
36a71934 3843 [NEON_3R_VFM_VQRDMLSH] = 0x7, /* For VFM, size bit 1 encodes op */
62698be3
PM
3844 [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
3845 [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
3846 [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
3847 [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
3848 [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
505935fc 3849 [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */
62698be3
PM
3850};
3851
600b828c
PM
3852/* Symbolic constants for op fields for Neon 2-register miscellaneous.
3853 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
3854 * table A7-13.
3855 */
3856#define NEON_2RM_VREV64 0
3857#define NEON_2RM_VREV32 1
3858#define NEON_2RM_VREV16 2
3859#define NEON_2RM_VPADDL 4
3860#define NEON_2RM_VPADDL_U 5
9d935509
AB
3861#define NEON_2RM_AESE 6 /* Includes AESD */
3862#define NEON_2RM_AESMC 7 /* Includes AESIMC */
600b828c
PM
3863#define NEON_2RM_VCLS 8
3864#define NEON_2RM_VCLZ 9
3865#define NEON_2RM_VCNT 10
3866#define NEON_2RM_VMVN 11
3867#define NEON_2RM_VPADAL 12
3868#define NEON_2RM_VPADAL_U 13
3869#define NEON_2RM_VQABS 14
3870#define NEON_2RM_VQNEG 15
3871#define NEON_2RM_VCGT0 16
3872#define NEON_2RM_VCGE0 17
3873#define NEON_2RM_VCEQ0 18
3874#define NEON_2RM_VCLE0 19
3875#define NEON_2RM_VCLT0 20
f1ecb913 3876#define NEON_2RM_SHA1H 21
600b828c
PM
3877#define NEON_2RM_VABS 22
3878#define NEON_2RM_VNEG 23
3879#define NEON_2RM_VCGT0_F 24
3880#define NEON_2RM_VCGE0_F 25
3881#define NEON_2RM_VCEQ0_F 26
3882#define NEON_2RM_VCLE0_F 27
3883#define NEON_2RM_VCLT0_F 28
3884#define NEON_2RM_VABS_F 30
3885#define NEON_2RM_VNEG_F 31
3886#define NEON_2RM_VSWP 32
3887#define NEON_2RM_VTRN 33
3888#define NEON_2RM_VUZP 34
3889#define NEON_2RM_VZIP 35
3890#define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
3891#define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
3892#define NEON_2RM_VSHLL 38
f1ecb913 3893#define NEON_2RM_SHA1SU1 39 /* Includes SHA256SU0 */
34f7b0a2 3894#define NEON_2RM_VRINTN 40
2ce70625 3895#define NEON_2RM_VRINTX 41
34f7b0a2
WN
3896#define NEON_2RM_VRINTA 42
3897#define NEON_2RM_VRINTZ 43
600b828c 3898#define NEON_2RM_VCVT_F16_F32 44
34f7b0a2 3899#define NEON_2RM_VRINTM 45
600b828c 3900#define NEON_2RM_VCVT_F32_F16 46
34f7b0a2 3901#define NEON_2RM_VRINTP 47
901ad525
WN
3902#define NEON_2RM_VCVTAU 48
3903#define NEON_2RM_VCVTAS 49
3904#define NEON_2RM_VCVTNU 50
3905#define NEON_2RM_VCVTNS 51
3906#define NEON_2RM_VCVTPU 52
3907#define NEON_2RM_VCVTPS 53
3908#define NEON_2RM_VCVTMU 54
3909#define NEON_2RM_VCVTMS 55
600b828c
PM
3910#define NEON_2RM_VRECPE 56
3911#define NEON_2RM_VRSQRTE 57
3912#define NEON_2RM_VRECPE_F 58
3913#define NEON_2RM_VRSQRTE_F 59
3914#define NEON_2RM_VCVT_FS 60
3915#define NEON_2RM_VCVT_FU 61
3916#define NEON_2RM_VCVT_SF 62
3917#define NEON_2RM_VCVT_UF 63
3918
fe8fcf3d
PM
3919static bool neon_2rm_is_v8_op(int op)
3920{
3921 /* Return true if this neon 2reg-misc op is ARMv8 and up */
3922 switch (op) {
3923 case NEON_2RM_VRINTN:
3924 case NEON_2RM_VRINTA:
3925 case NEON_2RM_VRINTM:
3926 case NEON_2RM_VRINTP:
3927 case NEON_2RM_VRINTZ:
3928 case NEON_2RM_VRINTX:
3929 case NEON_2RM_VCVTAU:
3930 case NEON_2RM_VCVTAS:
3931 case NEON_2RM_VCVTNU:
3932 case NEON_2RM_VCVTNS:
3933 case NEON_2RM_VCVTPU:
3934 case NEON_2RM_VCVTPS:
3935 case NEON_2RM_VCVTMU:
3936 case NEON_2RM_VCVTMS:
3937 return true;
3938 default:
3939 return false;
3940 }
3941}
3942
600b828c
PM
3943/* Each entry in this array has bit n set if the insn allows
3944 * size value n (otherwise it will UNDEF). Since unallocated
3945 * op values will have no bits set they always UNDEF.
3946 */
3947static const uint8_t neon_2rm_sizes[] = {
3948 [NEON_2RM_VREV64] = 0x7,
3949 [NEON_2RM_VREV32] = 0x3,
3950 [NEON_2RM_VREV16] = 0x1,
3951 [NEON_2RM_VPADDL] = 0x7,
3952 [NEON_2RM_VPADDL_U] = 0x7,
9d935509
AB
3953 [NEON_2RM_AESE] = 0x1,
3954 [NEON_2RM_AESMC] = 0x1,
600b828c
PM
3955 [NEON_2RM_VCLS] = 0x7,
3956 [NEON_2RM_VCLZ] = 0x7,
3957 [NEON_2RM_VCNT] = 0x1,
3958 [NEON_2RM_VMVN] = 0x1,
3959 [NEON_2RM_VPADAL] = 0x7,
3960 [NEON_2RM_VPADAL_U] = 0x7,
3961 [NEON_2RM_VQABS] = 0x7,
3962 [NEON_2RM_VQNEG] = 0x7,
3963 [NEON_2RM_VCGT0] = 0x7,
3964 [NEON_2RM_VCGE0] = 0x7,
3965 [NEON_2RM_VCEQ0] = 0x7,
3966 [NEON_2RM_VCLE0] = 0x7,
3967 [NEON_2RM_VCLT0] = 0x7,
f1ecb913 3968 [NEON_2RM_SHA1H] = 0x4,
600b828c
PM
3969 [NEON_2RM_VABS] = 0x7,
3970 [NEON_2RM_VNEG] = 0x7,
3971 [NEON_2RM_VCGT0_F] = 0x4,
3972 [NEON_2RM_VCGE0_F] = 0x4,
3973 [NEON_2RM_VCEQ0_F] = 0x4,
3974 [NEON_2RM_VCLE0_F] = 0x4,
3975 [NEON_2RM_VCLT0_F] = 0x4,
3976 [NEON_2RM_VABS_F] = 0x4,
3977 [NEON_2RM_VNEG_F] = 0x4,
3978 [NEON_2RM_VSWP] = 0x1,
3979 [NEON_2RM_VTRN] = 0x7,
3980 [NEON_2RM_VUZP] = 0x7,
3981 [NEON_2RM_VZIP] = 0x7,
3982 [NEON_2RM_VMOVN] = 0x7,
3983 [NEON_2RM_VQMOVN] = 0x7,
3984 [NEON_2RM_VSHLL] = 0x7,
f1ecb913 3985 [NEON_2RM_SHA1SU1] = 0x4,
34f7b0a2 3986 [NEON_2RM_VRINTN] = 0x4,
2ce70625 3987 [NEON_2RM_VRINTX] = 0x4,
34f7b0a2
WN
3988 [NEON_2RM_VRINTA] = 0x4,
3989 [NEON_2RM_VRINTZ] = 0x4,
600b828c 3990 [NEON_2RM_VCVT_F16_F32] = 0x2,
34f7b0a2 3991 [NEON_2RM_VRINTM] = 0x4,
600b828c 3992 [NEON_2RM_VCVT_F32_F16] = 0x2,
34f7b0a2 3993 [NEON_2RM_VRINTP] = 0x4,
901ad525
WN
3994 [NEON_2RM_VCVTAU] = 0x4,
3995 [NEON_2RM_VCVTAS] = 0x4,
3996 [NEON_2RM_VCVTNU] = 0x4,
3997 [NEON_2RM_VCVTNS] = 0x4,
3998 [NEON_2RM_VCVTPU] = 0x4,
3999 [NEON_2RM_VCVTPS] = 0x4,
4000 [NEON_2RM_VCVTMU] = 0x4,
4001 [NEON_2RM_VCVTMS] = 0x4,
600b828c
PM
4002 [NEON_2RM_VRECPE] = 0x4,
4003 [NEON_2RM_VRSQRTE] = 0x4,
4004 [NEON_2RM_VRECPE_F] = 0x4,
4005 [NEON_2RM_VRSQRTE_F] = 0x4,
4006 [NEON_2RM_VCVT_FS] = 0x4,
4007 [NEON_2RM_VCVT_FU] = 0x4,
4008 [NEON_2RM_VCVT_SF] = 0x4,
4009 [NEON_2RM_VCVT_UF] = 0x4,
4010};
4011
36a71934
RH
4012
4013/* Expand v8.1 simd helper. */
4014static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
4015 int q, int rd, int rn, int rm)
4016{
962fcbf2 4017 if (dc_isar_feature(aa32_rdm, s)) {
36a71934
RH
4018 int opr_sz = (1 + q) * 8;
4019 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
4020 vfp_reg_offset(1, rn),
4021 vfp_reg_offset(1, rm), cpu_env,
4022 opr_sz, opr_sz, 0, fn);
4023 return 0;
4024 }
4025 return 1;
4026}
4027
41f6c113
RH
4028static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4029{
4030 tcg_gen_vec_sar8i_i64(a, a, shift);
4031 tcg_gen_vec_add8_i64(d, d, a);
4032}
4033
4034static void gen_ssra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4035{
4036 tcg_gen_vec_sar16i_i64(a, a, shift);
4037 tcg_gen_vec_add16_i64(d, d, a);
4038}
4039
4040static void gen_ssra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
4041{
4042 tcg_gen_sari_i32(a, a, shift);
4043 tcg_gen_add_i32(d, d, a);
4044}
4045
4046static void gen_ssra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4047{
4048 tcg_gen_sari_i64(a, a, shift);
4049 tcg_gen_add_i64(d, d, a);
4050}
4051
4052static void gen_ssra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
4053{
4054 tcg_gen_sari_vec(vece, a, a, sh);
4055 tcg_gen_add_vec(vece, d, d, a);
4056}
4057
53229a77
RH
4058static const TCGOpcode vecop_list_ssra[] = {
4059 INDEX_op_sari_vec, INDEX_op_add_vec, 0
4060};
4061
41f6c113
RH
4062const GVecGen2i ssra_op[4] = {
4063 { .fni8 = gen_ssra8_i64,
4064 .fniv = gen_ssra_vec,
4065 .load_dest = true,
53229a77 4066 .opt_opc = vecop_list_ssra,
41f6c113
RH
4067 .vece = MO_8 },
4068 { .fni8 = gen_ssra16_i64,
4069 .fniv = gen_ssra_vec,
4070 .load_dest = true,
53229a77 4071 .opt_opc = vecop_list_ssra,
41f6c113
RH
4072 .vece = MO_16 },
4073 { .fni4 = gen_ssra32_i32,
4074 .fniv = gen_ssra_vec,
4075 .load_dest = true,
53229a77 4076 .opt_opc = vecop_list_ssra,
41f6c113
RH
4077 .vece = MO_32 },
4078 { .fni8 = gen_ssra64_i64,
4079 .fniv = gen_ssra_vec,
4080 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
53229a77 4081 .opt_opc = vecop_list_ssra,
41f6c113 4082 .load_dest = true,
41f6c113
RH
4083 .vece = MO_64 },
4084};
4085
4086static void gen_usra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4087{
4088 tcg_gen_vec_shr8i_i64(a, a, shift);
4089 tcg_gen_vec_add8_i64(d, d, a);
4090}
4091
4092static void gen_usra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4093{
4094 tcg_gen_vec_shr16i_i64(a, a, shift);
4095 tcg_gen_vec_add16_i64(d, d, a);
4096}
4097
4098static void gen_usra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
4099{
4100 tcg_gen_shri_i32(a, a, shift);
4101 tcg_gen_add_i32(d, d, a);
4102}
4103
4104static void gen_usra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4105{
4106 tcg_gen_shri_i64(a, a, shift);
4107 tcg_gen_add_i64(d, d, a);
4108}
4109
4110static void gen_usra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
4111{
4112 tcg_gen_shri_vec(vece, a, a, sh);
4113 tcg_gen_add_vec(vece, d, d, a);
4114}
4115
53229a77
RH
4116static const TCGOpcode vecop_list_usra[] = {
4117 INDEX_op_shri_vec, INDEX_op_add_vec, 0
4118};
4119
41f6c113
RH
4120const GVecGen2i usra_op[4] = {
4121 { .fni8 = gen_usra8_i64,
4122 .fniv = gen_usra_vec,
4123 .load_dest = true,
53229a77 4124 .opt_opc = vecop_list_usra,
41f6c113
RH
4125 .vece = MO_8, },
4126 { .fni8 = gen_usra16_i64,
4127 .fniv = gen_usra_vec,
4128 .load_dest = true,
53229a77 4129 .opt_opc = vecop_list_usra,
41f6c113
RH
4130 .vece = MO_16, },
4131 { .fni4 = gen_usra32_i32,
4132 .fniv = gen_usra_vec,
4133 .load_dest = true,
53229a77 4134 .opt_opc = vecop_list_usra,
41f6c113
RH
4135 .vece = MO_32, },
4136 { .fni8 = gen_usra64_i64,
4137 .fniv = gen_usra_vec,
4138 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4139 .load_dest = true,
53229a77 4140 .opt_opc = vecop_list_usra,
41f6c113
RH
4141 .vece = MO_64, },
4142};
eabcd6fa 4143
f3cd8218
RH
4144static void gen_shr8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4145{
4146 uint64_t mask = dup_const(MO_8, 0xff >> shift);
4147 TCGv_i64 t = tcg_temp_new_i64();
4148
4149 tcg_gen_shri_i64(t, a, shift);
4150 tcg_gen_andi_i64(t, t, mask);
4151 tcg_gen_andi_i64(d, d, ~mask);
4152 tcg_gen_or_i64(d, d, t);
4153 tcg_temp_free_i64(t);
4154}
4155
4156static void gen_shr16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4157{
4158 uint64_t mask = dup_const(MO_16, 0xffff >> shift);
4159 TCGv_i64 t = tcg_temp_new_i64();
4160
4161 tcg_gen_shri_i64(t, a, shift);
4162 tcg_gen_andi_i64(t, t, mask);
4163 tcg_gen_andi_i64(d, d, ~mask);
4164 tcg_gen_or_i64(d, d, t);
4165 tcg_temp_free_i64(t);
4166}
4167
4168static void gen_shr32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
4169{
4170 tcg_gen_shri_i32(a, a, shift);
4171 tcg_gen_deposit_i32(d, d, a, 0, 32 - shift);
4172}
4173
4174static void gen_shr64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4175{
4176 tcg_gen_shri_i64(a, a, shift);
4177 tcg_gen_deposit_i64(d, d, a, 0, 64 - shift);
4178}
4179
4180static void gen_shr_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
4181{
4182 if (sh == 0) {
4183 tcg_gen_mov_vec(d, a);
4184 } else {
4185 TCGv_vec t = tcg_temp_new_vec_matching(d);
4186 TCGv_vec m = tcg_temp_new_vec_matching(d);
4187
4188 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK((8 << vece) - sh, sh));
4189 tcg_gen_shri_vec(vece, t, a, sh);
4190 tcg_gen_and_vec(vece, d, d, m);
4191 tcg_gen_or_vec(vece, d, d, t);
4192
4193 tcg_temp_free_vec(t);
4194 tcg_temp_free_vec(m);
4195 }
4196}
4197
53229a77
RH
4198static const TCGOpcode vecop_list_sri[] = { INDEX_op_shri_vec, 0 };
4199
f3cd8218
RH
4200const GVecGen2i sri_op[4] = {
4201 { .fni8 = gen_shr8_ins_i64,
4202 .fniv = gen_shr_ins_vec,
4203 .load_dest = true,
53229a77 4204 .opt_opc = vecop_list_sri,
f3cd8218
RH
4205 .vece = MO_8 },
4206 { .fni8 = gen_shr16_ins_i64,
4207 .fniv = gen_shr_ins_vec,
4208 .load_dest = true,
53229a77 4209 .opt_opc = vecop_list_sri,
f3cd8218
RH
4210 .vece = MO_16 },
4211 { .fni4 = gen_shr32_ins_i32,
4212 .fniv = gen_shr_ins_vec,
4213 .load_dest = true,
53229a77 4214 .opt_opc = vecop_list_sri,
f3cd8218
RH
4215 .vece = MO_32 },
4216 { .fni8 = gen_shr64_ins_i64,
4217 .fniv = gen_shr_ins_vec,
4218 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4219 .load_dest = true,
53229a77 4220 .opt_opc = vecop_list_sri,
f3cd8218
RH
4221 .vece = MO_64 },
4222};
4223
4224static void gen_shl8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4225{
4226 uint64_t mask = dup_const(MO_8, 0xff << shift);
4227 TCGv_i64 t = tcg_temp_new_i64();
4228
4229 tcg_gen_shli_i64(t, a, shift);
4230 tcg_gen_andi_i64(t, t, mask);
4231 tcg_gen_andi_i64(d, d, ~mask);
4232 tcg_gen_or_i64(d, d, t);
4233 tcg_temp_free_i64(t);
4234}
4235
4236static void gen_shl16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4237{
4238 uint64_t mask = dup_const(MO_16, 0xffff << shift);
4239 TCGv_i64 t = tcg_temp_new_i64();
4240
4241 tcg_gen_shli_i64(t, a, shift);
4242 tcg_gen_andi_i64(t, t, mask);
4243 tcg_gen_andi_i64(d, d, ~mask);
4244 tcg_gen_or_i64(d, d, t);
4245 tcg_temp_free_i64(t);
4246}
4247
4248static void gen_shl32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
4249{
4250 tcg_gen_deposit_i32(d, d, a, shift, 32 - shift);
4251}
4252
4253static void gen_shl64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4254{
4255 tcg_gen_deposit_i64(d, d, a, shift, 64 - shift);
4256}
4257
4258static void gen_shl_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
4259{
4260 if (sh == 0) {
4261 tcg_gen_mov_vec(d, a);
4262 } else {
4263 TCGv_vec t = tcg_temp_new_vec_matching(d);
4264 TCGv_vec m = tcg_temp_new_vec_matching(d);
4265
4266 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK(0, sh));
4267 tcg_gen_shli_vec(vece, t, a, sh);
4268 tcg_gen_and_vec(vece, d, d, m);
4269 tcg_gen_or_vec(vece, d, d, t);
4270
4271 tcg_temp_free_vec(t);
4272 tcg_temp_free_vec(m);
4273 }
4274}
4275
53229a77
RH
4276static const TCGOpcode vecop_list_sli[] = { INDEX_op_shli_vec, 0 };
4277
f3cd8218
RH
4278const GVecGen2i sli_op[4] = {
4279 { .fni8 = gen_shl8_ins_i64,
4280 .fniv = gen_shl_ins_vec,
4281 .load_dest = true,
53229a77 4282 .opt_opc = vecop_list_sli,
f3cd8218
RH
4283 .vece = MO_8 },
4284 { .fni8 = gen_shl16_ins_i64,
4285 .fniv = gen_shl_ins_vec,
4286 .load_dest = true,
53229a77 4287 .opt_opc = vecop_list_sli,
f3cd8218
RH
4288 .vece = MO_16 },
4289 { .fni4 = gen_shl32_ins_i32,
4290 .fniv = gen_shl_ins_vec,
4291 .load_dest = true,
53229a77 4292 .opt_opc = vecop_list_sli,
f3cd8218
RH
4293 .vece = MO_32 },
4294 { .fni8 = gen_shl64_ins_i64,
4295 .fniv = gen_shl_ins_vec,
4296 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4297 .load_dest = true,
53229a77 4298 .opt_opc = vecop_list_sli,
f3cd8218
RH
4299 .vece = MO_64 },
4300};
4301
4a7832b0
RH
4302static void gen_mla8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4303{
4304 gen_helper_neon_mul_u8(a, a, b);
4305 gen_helper_neon_add_u8(d, d, a);
4306}
4307
4308static void gen_mls8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4309{
4310 gen_helper_neon_mul_u8(a, a, b);
4311 gen_helper_neon_sub_u8(d, d, a);
4312}
4313
4314static void gen_mla16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4315{
4316 gen_helper_neon_mul_u16(a, a, b);
4317 gen_helper_neon_add_u16(d, d, a);
4318}
4319
4320static void gen_mls16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4321{
4322 gen_helper_neon_mul_u16(a, a, b);
4323 gen_helper_neon_sub_u16(d, d, a);
4324}
4325
4326static void gen_mla32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4327{
4328 tcg_gen_mul_i32(a, a, b);
4329 tcg_gen_add_i32(d, d, a);
4330}
4331
4332static void gen_mls32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4333{
4334 tcg_gen_mul_i32(a, a, b);
4335 tcg_gen_sub_i32(d, d, a);
4336}
4337
4338static void gen_mla64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4339{
4340 tcg_gen_mul_i64(a, a, b);
4341 tcg_gen_add_i64(d, d, a);
4342}
4343
4344static void gen_mls64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4345{
4346 tcg_gen_mul_i64(a, a, b);
4347 tcg_gen_sub_i64(d, d, a);
4348}
4349
4350static void gen_mla_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4351{
4352 tcg_gen_mul_vec(vece, a, a, b);
4353 tcg_gen_add_vec(vece, d, d, a);
4354}
4355
4356static void gen_mls_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4357{
4358 tcg_gen_mul_vec(vece, a, a, b);
4359 tcg_gen_sub_vec(vece, d, d, a);
4360}
4361
4362/* Note that while NEON does not support VMLA and VMLS as 64-bit ops,
4363 * these tables are shared with AArch64 which does support them.
4364 */
53229a77
RH
4365
4366static const TCGOpcode vecop_list_mla[] = {
4367 INDEX_op_mul_vec, INDEX_op_add_vec, 0
4368};
4369
4370static const TCGOpcode vecop_list_mls[] = {
4371 INDEX_op_mul_vec, INDEX_op_sub_vec, 0
4372};
4373
4a7832b0
RH
4374const GVecGen3 mla_op[4] = {
4375 { .fni4 = gen_mla8_i32,
4376 .fniv = gen_mla_vec,
4a7832b0 4377 .load_dest = true,
53229a77 4378 .opt_opc = vecop_list_mla,
4a7832b0
RH
4379 .vece = MO_8 },
4380 { .fni4 = gen_mla16_i32,
4381 .fniv = gen_mla_vec,
4a7832b0 4382 .load_dest = true,
53229a77 4383 .opt_opc = vecop_list_mla,
4a7832b0
RH
4384 .vece = MO_16 },
4385 { .fni4 = gen_mla32_i32,
4386 .fniv = gen_mla_vec,
4a7832b0 4387 .load_dest = true,
53229a77 4388 .opt_opc = vecop_list_mla,
4a7832b0
RH
4389 .vece = MO_32 },
4390 { .fni8 = gen_mla64_i64,
4391 .fniv = gen_mla_vec,
4a7832b0
RH
4392 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4393 .load_dest = true,
53229a77 4394 .opt_opc = vecop_list_mla,
4a7832b0
RH
4395 .vece = MO_64 },
4396};
4397
4398const GVecGen3 mls_op[4] = {
4399 { .fni4 = gen_mls8_i32,
4400 .fniv = gen_mls_vec,
4a7832b0 4401 .load_dest = true,
53229a77 4402 .opt_opc = vecop_list_mls,
4a7832b0
RH
4403 .vece = MO_8 },
4404 { .fni4 = gen_mls16_i32,
4405 .fniv = gen_mls_vec,
4a7832b0 4406 .load_dest = true,
53229a77 4407 .opt_opc = vecop_list_mls,
4a7832b0
RH
4408 .vece = MO_16 },
4409 { .fni4 = gen_mls32_i32,
4410 .fniv = gen_mls_vec,
4a7832b0 4411 .load_dest = true,
53229a77 4412 .opt_opc = vecop_list_mls,
4a7832b0
RH
4413 .vece = MO_32 },
4414 { .fni8 = gen_mls64_i64,
4415 .fniv = gen_mls_vec,
4a7832b0
RH
4416 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4417 .load_dest = true,
53229a77 4418 .opt_opc = vecop_list_mls,
4a7832b0
RH
4419 .vece = MO_64 },
4420};
4421
ea580fa3
RH
4422/* CMTST : test is "if (X & Y != 0)". */
4423static void gen_cmtst_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4424{
4425 tcg_gen_and_i32(d, a, b);
4426 tcg_gen_setcondi_i32(TCG_COND_NE, d, d, 0);
4427 tcg_gen_neg_i32(d, d);
4428}
4429
4430void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4431{
4432 tcg_gen_and_i64(d, a, b);
4433 tcg_gen_setcondi_i64(TCG_COND_NE, d, d, 0);
4434 tcg_gen_neg_i64(d, d);
4435}
4436
4437static void gen_cmtst_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4438{
4439 tcg_gen_and_vec(vece, d, a, b);
4440 tcg_gen_dupi_vec(vece, a, 0);
4441 tcg_gen_cmp_vec(TCG_COND_NE, vece, d, d, a);
4442}
4443
53229a77
RH
4444static const TCGOpcode vecop_list_cmtst[] = { INDEX_op_cmp_vec, 0 };
4445
ea580fa3
RH
4446const GVecGen3 cmtst_op[4] = {
4447 { .fni4 = gen_helper_neon_tst_u8,
4448 .fniv = gen_cmtst_vec,
53229a77 4449 .opt_opc = vecop_list_cmtst,
ea580fa3
RH
4450 .vece = MO_8 },
4451 { .fni4 = gen_helper_neon_tst_u16,
4452 .fniv = gen_cmtst_vec,
53229a77 4453 .opt_opc = vecop_list_cmtst,
ea580fa3
RH
4454 .vece = MO_16 },
4455 { .fni4 = gen_cmtst_i32,
4456 .fniv = gen_cmtst_vec,
53229a77 4457 .opt_opc = vecop_list_cmtst,
ea580fa3
RH
4458 .vece = MO_32 },
4459 { .fni8 = gen_cmtst_i64,
4460 .fniv = gen_cmtst_vec,
4461 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
53229a77 4462 .opt_opc = vecop_list_cmtst,
ea580fa3
RH
4463 .vece = MO_64 },
4464};
4465
89e68b57
RH
4466static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4467 TCGv_vec a, TCGv_vec b)
4468{
4469 TCGv_vec x = tcg_temp_new_vec_matching(t);
4470 tcg_gen_add_vec(vece, x, a, b);
4471 tcg_gen_usadd_vec(vece, t, a, b);
4472 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4473 tcg_gen_or_vec(vece, sat, sat, x);
4474 tcg_temp_free_vec(x);
4475}
4476
53229a77
RH
4477static const TCGOpcode vecop_list_uqadd[] = {
4478 INDEX_op_usadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
4479};
4480
89e68b57
RH
4481const GVecGen4 uqadd_op[4] = {
4482 { .fniv = gen_uqadd_vec,
4483 .fno = gen_helper_gvec_uqadd_b,
89e68b57 4484 .write_aofs = true,
53229a77 4485 .opt_opc = vecop_list_uqadd,
89e68b57
RH
4486 .vece = MO_8 },
4487 { .fniv = gen_uqadd_vec,
4488 .fno = gen_helper_gvec_uqadd_h,
89e68b57 4489 .write_aofs = true,
53229a77 4490 .opt_opc = vecop_list_uqadd,
89e68b57
RH
4491 .vece = MO_16 },
4492 { .fniv = gen_uqadd_vec,
4493 .fno = gen_helper_gvec_uqadd_s,
89e68b57 4494 .write_aofs = true,
53229a77 4495 .opt_opc = vecop_list_uqadd,
89e68b57
RH
4496 .vece = MO_32 },
4497 { .fniv = gen_uqadd_vec,
4498 .fno = gen_helper_gvec_uqadd_d,
89e68b57 4499 .write_aofs = true,
53229a77 4500 .opt_opc = vecop_list_uqadd,
89e68b57
RH
4501 .vece = MO_64 },
4502};
4503
4504static void gen_sqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4505 TCGv_vec a, TCGv_vec b)
4506{
4507 TCGv_vec x = tcg_temp_new_vec_matching(t);
4508 tcg_gen_add_vec(vece, x, a, b);
4509 tcg_gen_ssadd_vec(vece, t, a, b);
4510 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4511 tcg_gen_or_vec(vece, sat, sat, x);
4512 tcg_temp_free_vec(x);
4513}
4514
53229a77
RH
4515static const TCGOpcode vecop_list_sqadd[] = {
4516 INDEX_op_ssadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
4517};
4518
89e68b57
RH
4519const GVecGen4 sqadd_op[4] = {
4520 { .fniv = gen_sqadd_vec,
4521 .fno = gen_helper_gvec_sqadd_b,
53229a77 4522 .opt_opc = vecop_list_sqadd,
89e68b57
RH
4523 .write_aofs = true,
4524 .vece = MO_8 },
4525 { .fniv = gen_sqadd_vec,
4526 .fno = gen_helper_gvec_sqadd_h,
53229a77 4527 .opt_opc = vecop_list_sqadd,
89e68b57
RH
4528 .write_aofs = true,
4529 .vece = MO_16 },
4530 { .fniv = gen_sqadd_vec,
4531 .fno = gen_helper_gvec_sqadd_s,
53229a77 4532 .opt_opc = vecop_list_sqadd,
89e68b57
RH
4533 .write_aofs = true,
4534 .vece = MO_32 },
4535 { .fniv = gen_sqadd_vec,
4536 .fno = gen_helper_gvec_sqadd_d,
53229a77 4537 .opt_opc = vecop_list_sqadd,
89e68b57
RH
4538 .write_aofs = true,
4539 .vece = MO_64 },
4540};
4541
4542static void gen_uqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4543 TCGv_vec a, TCGv_vec b)
4544{
4545 TCGv_vec x = tcg_temp_new_vec_matching(t);
4546 tcg_gen_sub_vec(vece, x, a, b);
4547 tcg_gen_ussub_vec(vece, t, a, b);
4548 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4549 tcg_gen_or_vec(vece, sat, sat, x);
4550 tcg_temp_free_vec(x);
4551}
4552
53229a77
RH
4553static const TCGOpcode vecop_list_uqsub[] = {
4554 INDEX_op_ussub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
4555};
4556
89e68b57
RH
4557const GVecGen4 uqsub_op[4] = {
4558 { .fniv = gen_uqsub_vec,
4559 .fno = gen_helper_gvec_uqsub_b,
53229a77 4560 .opt_opc = vecop_list_uqsub,
89e68b57
RH
4561 .write_aofs = true,
4562 .vece = MO_8 },
4563 { .fniv = gen_uqsub_vec,
4564 .fno = gen_helper_gvec_uqsub_h,
53229a77 4565 .opt_opc = vecop_list_uqsub,
89e68b57
RH
4566 .write_aofs = true,
4567 .vece = MO_16 },
4568 { .fniv = gen_uqsub_vec,
4569 .fno = gen_helper_gvec_uqsub_s,
53229a77 4570 .opt_opc = vecop_list_uqsub,
89e68b57
RH
4571 .write_aofs = true,
4572 .vece = MO_32 },
4573 { .fniv = gen_uqsub_vec,
4574 .fno = gen_helper_gvec_uqsub_d,
53229a77 4575 .opt_opc = vecop_list_uqsub,
89e68b57
RH
4576 .write_aofs = true,
4577 .vece = MO_64 },
4578};
4579
4580static void gen_sqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4581 TCGv_vec a, TCGv_vec b)
4582{
4583 TCGv_vec x = tcg_temp_new_vec_matching(t);
4584 tcg_gen_sub_vec(vece, x, a, b);
4585 tcg_gen_sssub_vec(vece, t, a, b);
4586 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4587 tcg_gen_or_vec(vece, sat, sat, x);
4588 tcg_temp_free_vec(x);
4589}
4590
53229a77
RH
4591static const TCGOpcode vecop_list_sqsub[] = {
4592 INDEX_op_sssub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
4593};
4594
89e68b57
RH
4595const GVecGen4 sqsub_op[4] = {
4596 { .fniv = gen_sqsub_vec,
4597 .fno = gen_helper_gvec_sqsub_b,
53229a77 4598 .opt_opc = vecop_list_sqsub,
89e68b57
RH
4599 .write_aofs = true,
4600 .vece = MO_8 },
4601 { .fniv = gen_sqsub_vec,
4602 .fno = gen_helper_gvec_sqsub_h,
53229a77 4603 .opt_opc = vecop_list_sqsub,
89e68b57
RH
4604 .write_aofs = true,
4605 .vece = MO_16 },
4606 { .fniv = gen_sqsub_vec,
4607 .fno = gen_helper_gvec_sqsub_s,
53229a77 4608 .opt_opc = vecop_list_sqsub,
89e68b57
RH
4609 .write_aofs = true,
4610 .vece = MO_32 },
4611 { .fniv = gen_sqsub_vec,
4612 .fno = gen_helper_gvec_sqsub_d,
53229a77 4613 .opt_opc = vecop_list_sqsub,
89e68b57
RH
4614 .write_aofs = true,
4615 .vece = MO_64 },
4616};
4617
9ee6e8bb
PB
4618/* Translate a NEON data processing instruction. Return nonzero if the
4619 instruction is invalid.
ad69471c
PB
4620 We process data in a mixture of 32-bit and 64-bit chunks.
4621 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
2c0262af 4622
7dcc1f89 4623static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
9ee6e8bb
PB
4624{
4625 int op;
4626 int q;
eabcd6fa 4627 int rd, rn, rm, rd_ofs, rn_ofs, rm_ofs;
9ee6e8bb
PB
4628 int size;
4629 int shift;
4630 int pass;
4631 int count;
4632 int pairwise;
4633 int u;
eabcd6fa 4634 int vec_size;
f3cd8218 4635 uint32_t imm;
39d5492a 4636 TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
1a66ac61 4637 TCGv_ptr ptr1, ptr2, ptr3;
a7812ae4 4638 TCGv_i64 tmp64;
9ee6e8bb 4639
2c7ffc41
PM
4640 /* FIXME: this access check should not take precedence over UNDEF
4641 * for invalid encodings; we will generate incorrect syndrome information
4642 * for attempts to execute invalid vfp/neon encodings with FP disabled.
4643 */
9dbbc748 4644 if (s->fp_excp_el) {
a767fac8 4645 gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
4be42f40 4646 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
2c7ffc41
PM
4647 return 0;
4648 }
4649
5df8bac1 4650 if (!s->vfp_enabled)
9ee6e8bb
PB
4651 return 1;
4652 q = (insn & (1 << 6)) != 0;
4653 u = (insn >> 24) & 1;
4654 VFP_DREG_D(rd, insn);
4655 VFP_DREG_N(rn, insn);
4656 VFP_DREG_M(rm, insn);
4657 size = (insn >> 20) & 3;
eabcd6fa
RH
4658 vec_size = q ? 16 : 8;
4659 rd_ofs = neon_reg_offset(rd, 0);
4660 rn_ofs = neon_reg_offset(rn, 0);
4661 rm_ofs = neon_reg_offset(rm, 0);
4662
9ee6e8bb
PB
4663 if ((insn & (1 << 23)) == 0) {
4664 /* Three register same length. */
4665 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
62698be3
PM
4666 /* Catch invalid op and bad size combinations: UNDEF */
4667 if ((neon_3r_sizes[op] & (1 << size)) == 0) {
4668 return 1;
4669 }
25f84f79
PM
4670 /* All insns of this form UNDEF for either this condition or the
4671 * superset of cases "Q==1"; we catch the latter later.
4672 */
4673 if (q && ((rd | rn | rm) & 1)) {
4674 return 1;
4675 }
36a71934
RH
4676 switch (op) {
4677 case NEON_3R_SHA:
4678 /* The SHA-1/SHA-256 3-register instructions require special
4679 * treatment here, as their size field is overloaded as an
4680 * op type selector, and they all consume their input in a
4681 * single pass.
4682 */
f1ecb913
AB
4683 if (!q) {
4684 return 1;
4685 }
4686 if (!u) { /* SHA-1 */
962fcbf2 4687 if (!dc_isar_feature(aa32_sha1, s)) {
f1ecb913
AB
4688 return 1;
4689 }
1a66ac61
RH
4690 ptr1 = vfp_reg_ptr(true, rd);
4691 ptr2 = vfp_reg_ptr(true, rn);
4692 ptr3 = vfp_reg_ptr(true, rm);
f1ecb913 4693 tmp4 = tcg_const_i32(size);
1a66ac61 4694 gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp4);
f1ecb913
AB
4695 tcg_temp_free_i32(tmp4);
4696 } else { /* SHA-256 */
962fcbf2 4697 if (!dc_isar_feature(aa32_sha2, s) || size == 3) {
f1ecb913
AB
4698 return 1;
4699 }
1a66ac61
RH
4700 ptr1 = vfp_reg_ptr(true, rd);
4701 ptr2 = vfp_reg_ptr(true, rn);
4702 ptr3 = vfp_reg_ptr(true, rm);
f1ecb913
AB
4703 switch (size) {
4704 case 0:
1a66ac61 4705 gen_helper_crypto_sha256h(ptr1, ptr2, ptr3);
f1ecb913
AB
4706 break;
4707 case 1:
1a66ac61 4708 gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3);
f1ecb913
AB
4709 break;
4710 case 2:
1a66ac61 4711 gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3);
f1ecb913
AB
4712 break;
4713 }
4714 }
1a66ac61
RH
4715 tcg_temp_free_ptr(ptr1);
4716 tcg_temp_free_ptr(ptr2);
4717 tcg_temp_free_ptr(ptr3);
f1ecb913 4718 return 0;
36a71934
RH
4719
4720 case NEON_3R_VPADD_VQRDMLAH:
4721 if (!u) {
4722 break; /* VPADD */
4723 }
4724 /* VQRDMLAH */
4725 switch (size) {
4726 case 1:
4727 return do_v81_helper(s, gen_helper_gvec_qrdmlah_s16,
4728 q, rd, rn, rm);
4729 case 2:
4730 return do_v81_helper(s, gen_helper_gvec_qrdmlah_s32,
4731 q, rd, rn, rm);
4732 }
4733 return 1;
4734
4735 case NEON_3R_VFM_VQRDMLSH:
4736 if (!u) {
4737 /* VFM, VFMS */
4738 if (size == 1) {
4739 return 1;
4740 }
4741 break;
4742 }
4743 /* VQRDMLSH */
4744 switch (size) {
4745 case 1:
4746 return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s16,
4747 q, rd, rn, rm);
4748 case 2:
4749 return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s32,
4750 q, rd, rn, rm);
4751 }
4752 return 1;
eabcd6fa
RH
4753
4754 case NEON_3R_LOGIC: /* Logic ops. */
4755 switch ((u << 2) | size) {
4756 case 0: /* VAND */
4757 tcg_gen_gvec_and(0, rd_ofs, rn_ofs, rm_ofs,
4758 vec_size, vec_size);
4759 break;
4760 case 1: /* VBIC */
4761 tcg_gen_gvec_andc(0, rd_ofs, rn_ofs, rm_ofs,
4762 vec_size, vec_size);
4763 break;
2900847f
RH
4764 case 2: /* VORR */
4765 tcg_gen_gvec_or(0, rd_ofs, rn_ofs, rm_ofs,
4766 vec_size, vec_size);
eabcd6fa
RH
4767 break;
4768 case 3: /* VORN */
4769 tcg_gen_gvec_orc(0, rd_ofs, rn_ofs, rm_ofs,
4770 vec_size, vec_size);
4771 break;
4772 case 4: /* VEOR */
4773 tcg_gen_gvec_xor(0, rd_ofs, rn_ofs, rm_ofs,
4774 vec_size, vec_size);
4775 break;
4776 case 5: /* VBSL */
3a7a2b4e
RH
4777 tcg_gen_gvec_bitsel(MO_8, rd_ofs, rd_ofs, rn_ofs, rm_ofs,
4778 vec_size, vec_size);
eabcd6fa
RH
4779 break;
4780 case 6: /* VBIT */
3a7a2b4e
RH
4781 tcg_gen_gvec_bitsel(MO_8, rd_ofs, rm_ofs, rn_ofs, rd_ofs,
4782 vec_size, vec_size);
eabcd6fa
RH
4783 break;
4784 case 7: /* VBIF */
3a7a2b4e
RH
4785 tcg_gen_gvec_bitsel(MO_8, rd_ofs, rm_ofs, rd_ofs, rn_ofs,
4786 vec_size, vec_size);
eabcd6fa
RH
4787 break;
4788 }
4789 return 0;
e4717ae0
RH
4790
4791 case NEON_3R_VADD_VSUB:
4792 if (u) {
4793 tcg_gen_gvec_sub(size, rd_ofs, rn_ofs, rm_ofs,
4794 vec_size, vec_size);
4795 } else {
4796 tcg_gen_gvec_add(size, rd_ofs, rn_ofs, rm_ofs,
4797 vec_size, vec_size);
4798 }
4799 return 0;
82083184 4800
89e68b57
RH
4801 case NEON_3R_VQADD:
4802 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4803 rn_ofs, rm_ofs, vec_size, vec_size,
4804 (u ? uqadd_op : sqadd_op) + size);
2f143d3a 4805 return 0;
89e68b57
RH
4806
4807 case NEON_3R_VQSUB:
4808 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4809 rn_ofs, rm_ofs, vec_size, vec_size,
4810 (u ? uqsub_op : sqsub_op) + size);
2f143d3a 4811 return 0;
89e68b57 4812
82083184
RH
4813 case NEON_3R_VMUL: /* VMUL */
4814 if (u) {
4815 /* Polynomial case allows only P8 and is handled below. */
4816 if (size != 0) {
4817 return 1;
4818 }
4819 } else {
4820 tcg_gen_gvec_mul(size, rd_ofs, rn_ofs, rm_ofs,
4821 vec_size, vec_size);
4822 return 0;
4823 }
4824 break;
4a7832b0
RH
4825
4826 case NEON_3R_VML: /* VMLA, VMLS */
4827 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size,
4828 u ? &mls_op[size] : &mla_op[size]);
4829 return 0;
ea580fa3
RH
4830
4831 case NEON_3R_VTST_VCEQ:
4832 if (u) { /* VCEQ */
4833 tcg_gen_gvec_cmp(TCG_COND_EQ, size, rd_ofs, rn_ofs, rm_ofs,
4834 vec_size, vec_size);
4835 } else { /* VTST */
4836 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
4837 vec_size, vec_size, &cmtst_op[size]);
4838 }
4839 return 0;
4840
4841 case NEON_3R_VCGT:
4842 tcg_gen_gvec_cmp(u ? TCG_COND_GTU : TCG_COND_GT, size,
4843 rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
4844 return 0;
4845
4846 case NEON_3R_VCGE:
4847 tcg_gen_gvec_cmp(u ? TCG_COND_GEU : TCG_COND_GE, size,
4848 rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
4849 return 0;
6f278221
RH
4850
4851 case NEON_3R_VMAX:
4852 if (u) {
4853 tcg_gen_gvec_umax(size, rd_ofs, rn_ofs, rm_ofs,
4854 vec_size, vec_size);
4855 } else {
4856 tcg_gen_gvec_smax(size, rd_ofs, rn_ofs, rm_ofs,
4857 vec_size, vec_size);
4858 }
4859 return 0;
4860 case NEON_3R_VMIN:
4861 if (u) {
4862 tcg_gen_gvec_umin(size, rd_ofs, rn_ofs, rm_ofs,
4863 vec_size, vec_size);
4864 } else {
4865 tcg_gen_gvec_smin(size, rd_ofs, rn_ofs, rm_ofs,
4866 vec_size, vec_size);
4867 }
4868 return 0;
f1ecb913 4869 }
4a7832b0 4870
eabcd6fa 4871 if (size == 3) {
62698be3 4872 /* 64-bit element instructions. */
9ee6e8bb 4873 for (pass = 0; pass < (q ? 2 : 1); pass++) {
ad69471c
PB
4874 neon_load_reg64(cpu_V0, rn + pass);
4875 neon_load_reg64(cpu_V1, rm + pass);
9ee6e8bb 4876 switch (op) {
62698be3 4877 case NEON_3R_VSHL:
ad69471c
PB
4878 if (u) {
4879 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4880 } else {
4881 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4882 }
4883 break;
62698be3 4884 case NEON_3R_VQSHL:
ad69471c 4885 if (u) {
02da0b2d
PM
4886 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4887 cpu_V1, cpu_V0);
ad69471c 4888 } else {
02da0b2d
PM
4889 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
4890 cpu_V1, cpu_V0);
ad69471c
PB
4891 }
4892 break;
62698be3 4893 case NEON_3R_VRSHL:
ad69471c
PB
4894 if (u) {
4895 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
1e8d4eec 4896 } else {
ad69471c
PB
4897 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4898 }
4899 break;
62698be3 4900 case NEON_3R_VQRSHL:
ad69471c 4901 if (u) {
02da0b2d
PM
4902 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4903 cpu_V1, cpu_V0);
ad69471c 4904 } else {
02da0b2d
PM
4905 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4906 cpu_V1, cpu_V0);
1e8d4eec 4907 }
9ee6e8bb 4908 break;
9ee6e8bb
PB
4909 default:
4910 abort();
2c0262af 4911 }
ad69471c 4912 neon_store_reg64(cpu_V0, rd + pass);
2c0262af 4913 }
9ee6e8bb 4914 return 0;
2c0262af 4915 }
25f84f79 4916 pairwise = 0;
9ee6e8bb 4917 switch (op) {
62698be3
PM
4918 case NEON_3R_VSHL:
4919 case NEON_3R_VQSHL:
4920 case NEON_3R_VRSHL:
4921 case NEON_3R_VQRSHL:
9ee6e8bb 4922 {
ad69471c
PB
4923 int rtmp;
4924 /* Shift instruction operands are reversed. */
4925 rtmp = rn;
9ee6e8bb 4926 rn = rm;
ad69471c 4927 rm = rtmp;
9ee6e8bb 4928 }
2c0262af 4929 break;
36a71934 4930 case NEON_3R_VPADD_VQRDMLAH:
62698be3
PM
4931 case NEON_3R_VPMAX:
4932 case NEON_3R_VPMIN:
9ee6e8bb 4933 pairwise = 1;
2c0262af 4934 break;
25f84f79
PM
4935 case NEON_3R_FLOAT_ARITH:
4936 pairwise = (u && size < 2); /* if VPADD (float) */
4937 break;
4938 case NEON_3R_FLOAT_MINMAX:
4939 pairwise = u; /* if VPMIN/VPMAX (float) */
4940 break;
4941 case NEON_3R_FLOAT_CMP:
4942 if (!u && size) {
4943 /* no encoding for U=0 C=1x */
4944 return 1;
4945 }
4946 break;
4947 case NEON_3R_FLOAT_ACMP:
4948 if (!u) {
4949 return 1;
4950 }
4951 break;
505935fc
WN
4952 case NEON_3R_FLOAT_MISC:
4953 /* VMAXNM/VMINNM in ARMv8 */
d614a513 4954 if (u && !arm_dc_feature(s, ARM_FEATURE_V8)) {
25f84f79
PM
4955 return 1;
4956 }
2c0262af 4957 break;
36a71934
RH
4958 case NEON_3R_VFM_VQRDMLSH:
4959 if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
da97f52c
PM
4960 return 1;
4961 }
4962 break;
9ee6e8bb 4963 default:
2c0262af 4964 break;
9ee6e8bb 4965 }
dd8fbd78 4966
25f84f79
PM
4967 if (pairwise && q) {
4968 /* All the pairwise insns UNDEF if Q is set */
4969 return 1;
4970 }
4971
9ee6e8bb
PB
4972 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4973
4974 if (pairwise) {
4975 /* Pairwise. */
a5a14945
JR
4976 if (pass < 1) {
4977 tmp = neon_load_reg(rn, 0);
4978 tmp2 = neon_load_reg(rn, 1);
9ee6e8bb 4979 } else {
a5a14945
JR
4980 tmp = neon_load_reg(rm, 0);
4981 tmp2 = neon_load_reg(rm, 1);
9ee6e8bb
PB
4982 }
4983 } else {
4984 /* Elementwise. */
dd8fbd78
FN
4985 tmp = neon_load_reg(rn, pass);
4986 tmp2 = neon_load_reg(rm, pass);
9ee6e8bb
PB
4987 }
4988 switch (op) {
62698be3 4989 case NEON_3R_VHADD:
9ee6e8bb
PB
4990 GEN_NEON_INTEGER_OP(hadd);
4991 break;
62698be3 4992 case NEON_3R_VRHADD:
9ee6e8bb 4993 GEN_NEON_INTEGER_OP(rhadd);
2c0262af 4994 break;
62698be3 4995 case NEON_3R_VHSUB:
9ee6e8bb
PB
4996 GEN_NEON_INTEGER_OP(hsub);
4997 break;
62698be3 4998 case NEON_3R_VSHL:
ad69471c 4999 GEN_NEON_INTEGER_OP(shl);
2c0262af 5000 break;
62698be3 5001 case NEON_3R_VQSHL:
02da0b2d 5002 GEN_NEON_INTEGER_OP_ENV(qshl);
2c0262af 5003 break;
62698be3 5004 case NEON_3R_VRSHL:
ad69471c 5005 GEN_NEON_INTEGER_OP(rshl);
2c0262af 5006 break;
62698be3 5007 case NEON_3R_VQRSHL:
02da0b2d 5008 GEN_NEON_INTEGER_OP_ENV(qrshl);
9ee6e8bb 5009 break;
62698be3 5010 case NEON_3R_VABD:
9ee6e8bb
PB
5011 GEN_NEON_INTEGER_OP(abd);
5012 break;
62698be3 5013 case NEON_3R_VABA:
9ee6e8bb 5014 GEN_NEON_INTEGER_OP(abd);
7d1b0095 5015 tcg_temp_free_i32(tmp2);
dd8fbd78
FN
5016 tmp2 = neon_load_reg(rd, pass);
5017 gen_neon_add(size, tmp, tmp2);
9ee6e8bb 5018 break;
62698be3 5019 case NEON_3R_VMUL:
82083184
RH
5020 /* VMUL.P8; other cases already eliminated. */
5021 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
9ee6e8bb 5022 break;
62698be3 5023 case NEON_3R_VPMAX:
9ee6e8bb
PB
5024 GEN_NEON_INTEGER_OP(pmax);
5025 break;
62698be3 5026 case NEON_3R_VPMIN:
9ee6e8bb
PB
5027 GEN_NEON_INTEGER_OP(pmin);
5028 break;
62698be3 5029 case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
9ee6e8bb
PB
5030 if (!u) { /* VQDMULH */
5031 switch (size) {
02da0b2d
PM
5032 case 1:
5033 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5034 break;
5035 case 2:
5036 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5037 break;
62698be3 5038 default: abort();
9ee6e8bb 5039 }
62698be3 5040 } else { /* VQRDMULH */
9ee6e8bb 5041 switch (size) {
02da0b2d
PM
5042 case 1:
5043 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5044 break;
5045 case 2:
5046 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5047 break;
62698be3 5048 default: abort();
9ee6e8bb
PB
5049 }
5050 }
5051 break;
36a71934 5052 case NEON_3R_VPADD_VQRDMLAH:
9ee6e8bb 5053 switch (size) {
dd8fbd78
FN
5054 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
5055 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
5056 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
62698be3 5057 default: abort();
9ee6e8bb
PB
5058 }
5059 break;
62698be3 5060 case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
aa47cfdd
PM
5061 {
5062 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
9ee6e8bb
PB
5063 switch ((u << 2) | size) {
5064 case 0: /* VADD */
aa47cfdd
PM
5065 case 4: /* VPADD */
5066 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
9ee6e8bb
PB
5067 break;
5068 case 2: /* VSUB */
aa47cfdd 5069 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
9ee6e8bb
PB
5070 break;
5071 case 6: /* VABD */
aa47cfdd 5072 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
9ee6e8bb
PB
5073 break;
5074 default:
62698be3 5075 abort();
9ee6e8bb 5076 }
aa47cfdd 5077 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 5078 break;
aa47cfdd 5079 }
62698be3 5080 case NEON_3R_FLOAT_MULTIPLY:
aa47cfdd
PM
5081 {
5082 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5083 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
9ee6e8bb 5084 if (!u) {
7d1b0095 5085 tcg_temp_free_i32(tmp2);
dd8fbd78 5086 tmp2 = neon_load_reg(rd, pass);
9ee6e8bb 5087 if (size == 0) {
aa47cfdd 5088 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
9ee6e8bb 5089 } else {
aa47cfdd 5090 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
9ee6e8bb
PB
5091 }
5092 }
aa47cfdd 5093 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 5094 break;
aa47cfdd 5095 }
62698be3 5096 case NEON_3R_FLOAT_CMP:
aa47cfdd
PM
5097 {
5098 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
9ee6e8bb 5099 if (!u) {
aa47cfdd 5100 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
b5ff1b31 5101 } else {
aa47cfdd
PM
5102 if (size == 0) {
5103 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
5104 } else {
5105 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
5106 }
b5ff1b31 5107 }
aa47cfdd 5108 tcg_temp_free_ptr(fpstatus);
2c0262af 5109 break;
aa47cfdd 5110 }
62698be3 5111 case NEON_3R_FLOAT_ACMP:
aa47cfdd
PM
5112 {
5113 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5114 if (size == 0) {
5115 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
5116 } else {
5117 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
5118 }
5119 tcg_temp_free_ptr(fpstatus);
2c0262af 5120 break;
aa47cfdd 5121 }
62698be3 5122 case NEON_3R_FLOAT_MINMAX:
aa47cfdd
PM
5123 {
5124 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5125 if (size == 0) {
f71a2ae5 5126 gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus);
aa47cfdd 5127 } else {
f71a2ae5 5128 gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus);
aa47cfdd
PM
5129 }
5130 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 5131 break;
aa47cfdd 5132 }
505935fc
WN
5133 case NEON_3R_FLOAT_MISC:
5134 if (u) {
5135 /* VMAXNM/VMINNM */
5136 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5137 if (size == 0) {
f71a2ae5 5138 gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus);
505935fc 5139 } else {
f71a2ae5 5140 gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus);
505935fc
WN
5141 }
5142 tcg_temp_free_ptr(fpstatus);
5143 } else {
5144 if (size == 0) {
5145 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
5146 } else {
5147 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
5148 }
5149 }
2c0262af 5150 break;
36a71934 5151 case NEON_3R_VFM_VQRDMLSH:
da97f52c
PM
5152 {
5153 /* VFMA, VFMS: fused multiply-add */
5154 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5155 TCGv_i32 tmp3 = neon_load_reg(rd, pass);
5156 if (size) {
5157 /* VFMS */
5158 gen_helper_vfp_negs(tmp, tmp);
5159 }
5160 gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus);
5161 tcg_temp_free_i32(tmp3);
5162 tcg_temp_free_ptr(fpstatus);
5163 break;
5164 }
9ee6e8bb
PB
5165 default:
5166 abort();
2c0262af 5167 }
7d1b0095 5168 tcg_temp_free_i32(tmp2);
dd8fbd78 5169
9ee6e8bb
PB
5170 /* Save the result. For elementwise operations we can put it
5171 straight into the destination register. For pairwise operations
5172 we have to be careful to avoid clobbering the source operands. */
5173 if (pairwise && rd == rm) {
dd8fbd78 5174 neon_store_scratch(pass, tmp);
9ee6e8bb 5175 } else {
dd8fbd78 5176 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
5177 }
5178
5179 } /* for pass */
5180 if (pairwise && rd == rm) {
5181 for (pass = 0; pass < (q ? 4 : 2); pass++) {
dd8fbd78
FN
5182 tmp = neon_load_scratch(pass);
5183 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
5184 }
5185 }
ad69471c 5186 /* End of 3 register same size operations. */
9ee6e8bb
PB
5187 } else if (insn & (1 << 4)) {
5188 if ((insn & 0x00380080) != 0) {
5189 /* Two registers and shift. */
5190 op = (insn >> 8) & 0xf;
5191 if (insn & (1 << 7)) {
cc13115b
PM
5192 /* 64-bit shift. */
5193 if (op > 7) {
5194 return 1;
5195 }
9ee6e8bb
PB
5196 size = 3;
5197 } else {
5198 size = 2;
5199 while ((insn & (1 << (size + 19))) == 0)
5200 size--;
5201 }
5202 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
9ee6e8bb
PB
5203 if (op < 8) {
5204 /* Shift by immediate:
5205 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
cc13115b
PM
5206 if (q && ((rd | rm) & 1)) {
5207 return 1;
5208 }
5209 if (!u && (op == 4 || op == 6)) {
5210 return 1;
5211 }
9ee6e8bb
PB
5212 /* Right shifts are encoded as N - shift, where N is the
5213 element size in bits. */
1dc8425e 5214 if (op <= 4) {
9ee6e8bb 5215 shift = shift - (1 << (size + 3));
1dc8425e
RH
5216 }
5217
5218 switch (op) {
5219 case 0: /* VSHR */
5220 /* Right shift comes here negative. */
5221 shift = -shift;
5222 /* Shifts larger than the element size are architecturally
5223 * valid. Unsigned results in all zeros; signed results
5224 * in all sign bits.
5225 */
5226 if (!u) {
5227 tcg_gen_gvec_sari(size, rd_ofs, rm_ofs,
5228 MIN(shift, (8 << size) - 1),
5229 vec_size, vec_size);
5230 } else if (shift >= 8 << size) {
5231 tcg_gen_gvec_dup8i(rd_ofs, vec_size, vec_size, 0);
5232 } else {
5233 tcg_gen_gvec_shri(size, rd_ofs, rm_ofs, shift,
5234 vec_size, vec_size);
5235 }
5236 return 0;
5237
41f6c113
RH
5238 case 1: /* VSRA */
5239 /* Right shift comes here negative. */
5240 shift = -shift;
5241 /* Shifts larger than the element size are architecturally
5242 * valid. Unsigned results in all zeros; signed results
5243 * in all sign bits.
5244 */
5245 if (!u) {
5246 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
5247 MIN(shift, (8 << size) - 1),
5248 &ssra_op[size]);
5249 } else if (shift >= 8 << size) {
5250 /* rd += 0 */
5251 } else {
5252 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
5253 shift, &usra_op[size]);
5254 }
5255 return 0;
5256
f3cd8218
RH
5257 case 4: /* VSRI */
5258 if (!u) {
5259 return 1;
5260 }
5261 /* Right shift comes here negative. */
5262 shift = -shift;
5263 /* Shift out of range leaves destination unchanged. */
5264 if (shift < 8 << size) {
5265 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
5266 shift, &sri_op[size]);
5267 }
5268 return 0;
5269
1dc8425e 5270 case 5: /* VSHL, VSLI */
f3cd8218
RH
5271 if (u) { /* VSLI */
5272 /* Shift out of range leaves destination unchanged. */
5273 if (shift < 8 << size) {
5274 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size,
5275 vec_size, shift, &sli_op[size]);
5276 }
5277 } else { /* VSHL */
1dc8425e
RH
5278 /* Shifts larger than the element size are
5279 * architecturally valid and results in zero.
5280 */
5281 if (shift >= 8 << size) {
5282 tcg_gen_gvec_dup8i(rd_ofs, vec_size, vec_size, 0);
5283 } else {
5284 tcg_gen_gvec_shli(size, rd_ofs, rm_ofs, shift,
5285 vec_size, vec_size);
5286 }
1dc8425e 5287 }
f3cd8218 5288 return 0;
1dc8425e
RH
5289 }
5290
9ee6e8bb
PB
5291 if (size == 3) {
5292 count = q + 1;
5293 } else {
5294 count = q ? 4: 2;
5295 }
1dc8425e
RH
5296
5297 /* To avoid excessive duplication of ops we implement shift
5298 * by immediate using the variable shift operations.
5299 */
5300 imm = dup_const(size, shift);
9ee6e8bb
PB
5301
5302 for (pass = 0; pass < count; pass++) {
ad69471c
PB
5303 if (size == 3) {
5304 neon_load_reg64(cpu_V0, rm + pass);
5305 tcg_gen_movi_i64(cpu_V1, imm);
5306 switch (op) {
ad69471c
PB
5307 case 2: /* VRSHR */
5308 case 3: /* VRSRA */
5309 if (u)
5310 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
9ee6e8bb 5311 else
ad69471c 5312 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
9ee6e8bb 5313 break;
0322b26e 5314 case 6: /* VQSHLU */
02da0b2d
PM
5315 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
5316 cpu_V0, cpu_V1);
ad69471c 5317 break;
0322b26e
PM
5318 case 7: /* VQSHL */
5319 if (u) {
02da0b2d 5320 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
0322b26e
PM
5321 cpu_V0, cpu_V1);
5322 } else {
02da0b2d 5323 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
0322b26e
PM
5324 cpu_V0, cpu_V1);
5325 }
9ee6e8bb 5326 break;
1dc8425e
RH
5327 default:
5328 g_assert_not_reached();
9ee6e8bb 5329 }
41f6c113 5330 if (op == 3) {
ad69471c 5331 /* Accumulate. */
5371cb81 5332 neon_load_reg64(cpu_V1, rd + pass);
ad69471c 5333 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
ad69471c
PB
5334 }
5335 neon_store_reg64(cpu_V0, rd + pass);
5336 } else { /* size < 3 */
5337 /* Operands in T0 and T1. */
dd8fbd78 5338 tmp = neon_load_reg(rm, pass);
7d1b0095 5339 tmp2 = tcg_temp_new_i32();
dd8fbd78 5340 tcg_gen_movi_i32(tmp2, imm);
ad69471c 5341 switch (op) {
ad69471c
PB
5342 case 2: /* VRSHR */
5343 case 3: /* VRSRA */
5344 GEN_NEON_INTEGER_OP(rshl);
5345 break;
0322b26e 5346 case 6: /* VQSHLU */
ad69471c 5347 switch (size) {
0322b26e 5348 case 0:
02da0b2d
PM
5349 gen_helper_neon_qshlu_s8(tmp, cpu_env,
5350 tmp, tmp2);
0322b26e
PM
5351 break;
5352 case 1:
02da0b2d
PM
5353 gen_helper_neon_qshlu_s16(tmp, cpu_env,
5354 tmp, tmp2);
0322b26e
PM
5355 break;
5356 case 2:
02da0b2d
PM
5357 gen_helper_neon_qshlu_s32(tmp, cpu_env,
5358 tmp, tmp2);
0322b26e
PM
5359 break;
5360 default:
cc13115b 5361 abort();
ad69471c
PB
5362 }
5363 break;
0322b26e 5364 case 7: /* VQSHL */
02da0b2d 5365 GEN_NEON_INTEGER_OP_ENV(qshl);
0322b26e 5366 break;
1dc8425e
RH
5367 default:
5368 g_assert_not_reached();
ad69471c 5369 }
7d1b0095 5370 tcg_temp_free_i32(tmp2);
ad69471c 5371
41f6c113 5372 if (op == 3) {
ad69471c 5373 /* Accumulate. */
dd8fbd78 5374 tmp2 = neon_load_reg(rd, pass);
5371cb81 5375 gen_neon_add(size, tmp, tmp2);
7d1b0095 5376 tcg_temp_free_i32(tmp2);
ad69471c 5377 }
dd8fbd78 5378 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
5379 }
5380 } /* for pass */
5381 } else if (op < 10) {
ad69471c 5382 /* Shift by immediate and narrow:
9ee6e8bb 5383 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
0b36f4cd 5384 int input_unsigned = (op == 8) ? !u : u;
cc13115b
PM
5385 if (rm & 1) {
5386 return 1;
5387 }
9ee6e8bb
PB
5388 shift = shift - (1 << (size + 3));
5389 size++;
92cdfaeb 5390 if (size == 3) {
a7812ae4 5391 tmp64 = tcg_const_i64(shift);
92cdfaeb
PM
5392 neon_load_reg64(cpu_V0, rm);
5393 neon_load_reg64(cpu_V1, rm + 1);
5394 for (pass = 0; pass < 2; pass++) {
5395 TCGv_i64 in;
5396 if (pass == 0) {
5397 in = cpu_V0;
5398 } else {
5399 in = cpu_V1;
5400 }
ad69471c 5401 if (q) {
0b36f4cd 5402 if (input_unsigned) {
92cdfaeb 5403 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
0b36f4cd 5404 } else {
92cdfaeb 5405 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
0b36f4cd 5406 }
ad69471c 5407 } else {
0b36f4cd 5408 if (input_unsigned) {
92cdfaeb 5409 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
0b36f4cd 5410 } else {
92cdfaeb 5411 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
0b36f4cd 5412 }
ad69471c 5413 }
7d1b0095 5414 tmp = tcg_temp_new_i32();
92cdfaeb
PM
5415 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5416 neon_store_reg(rd, pass, tmp);
5417 } /* for pass */
5418 tcg_temp_free_i64(tmp64);
5419 } else {
5420 if (size == 1) {
5421 imm = (uint16_t)shift;
5422 imm |= imm << 16;
2c0262af 5423 } else {
92cdfaeb
PM
5424 /* size == 2 */
5425 imm = (uint32_t)shift;
5426 }
5427 tmp2 = tcg_const_i32(imm);
5428 tmp4 = neon_load_reg(rm + 1, 0);
5429 tmp5 = neon_load_reg(rm + 1, 1);
5430 for (pass = 0; pass < 2; pass++) {
5431 if (pass == 0) {
5432 tmp = neon_load_reg(rm, 0);
5433 } else {
5434 tmp = tmp4;
5435 }
0b36f4cd
CL
5436 gen_neon_shift_narrow(size, tmp, tmp2, q,
5437 input_unsigned);
92cdfaeb
PM
5438 if (pass == 0) {
5439 tmp3 = neon_load_reg(rm, 1);
5440 } else {
5441 tmp3 = tmp5;
5442 }
0b36f4cd
CL
5443 gen_neon_shift_narrow(size, tmp3, tmp2, q,
5444 input_unsigned);
36aa55dc 5445 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
7d1b0095
PM
5446 tcg_temp_free_i32(tmp);
5447 tcg_temp_free_i32(tmp3);
5448 tmp = tcg_temp_new_i32();
92cdfaeb
PM
5449 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5450 neon_store_reg(rd, pass, tmp);
5451 } /* for pass */
c6067f04 5452 tcg_temp_free_i32(tmp2);
b75263d6 5453 }
9ee6e8bb 5454 } else if (op == 10) {
cc13115b
PM
5455 /* VSHLL, VMOVL */
5456 if (q || (rd & 1)) {
9ee6e8bb 5457 return 1;
cc13115b 5458 }
ad69471c
PB
5459 tmp = neon_load_reg(rm, 0);
5460 tmp2 = neon_load_reg(rm, 1);
9ee6e8bb 5461 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
5462 if (pass == 1)
5463 tmp = tmp2;
5464
5465 gen_neon_widen(cpu_V0, tmp, size, u);
9ee6e8bb 5466
9ee6e8bb
PB
5467 if (shift != 0) {
5468 /* The shift is less than the width of the source
ad69471c
PB
5469 type, so we can just shift the whole register. */
5470 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
acdf01ef
CL
5471 /* Widen the result of shift: we need to clear
5472 * the potential overflow bits resulting from
5473 * left bits of the narrow input appearing as
5474 * right bits of left the neighbour narrow
5475 * input. */
ad69471c
PB
5476 if (size < 2 || !u) {
5477 uint64_t imm64;
5478 if (size == 0) {
5479 imm = (0xffu >> (8 - shift));
5480 imm |= imm << 16;
acdf01ef 5481 } else if (size == 1) {
ad69471c 5482 imm = 0xffff >> (16 - shift);
acdf01ef
CL
5483 } else {
5484 /* size == 2 */
5485 imm = 0xffffffff >> (32 - shift);
5486 }
5487 if (size < 2) {
5488 imm64 = imm | (((uint64_t)imm) << 32);
5489 } else {
5490 imm64 = imm;
9ee6e8bb 5491 }
acdf01ef 5492 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
9ee6e8bb
PB
5493 }
5494 }
ad69471c 5495 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb 5496 }
f73534a5 5497 } else if (op >= 14) {
9ee6e8bb 5498 /* VCVT fixed-point. */
c253dd78
PM
5499 TCGv_ptr fpst;
5500 TCGv_i32 shiftv;
5501 VFPGenFixPointFn *fn;
5502
cc13115b
PM
5503 if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
5504 return 1;
5505 }
c253dd78
PM
5506
5507 if (!(op & 1)) {
5508 if (u) {
5509 fn = gen_helper_vfp_ultos;
5510 } else {
5511 fn = gen_helper_vfp_sltos;
5512 }
5513 } else {
5514 if (u) {
5515 fn = gen_helper_vfp_touls_round_to_zero;
5516 } else {
5517 fn = gen_helper_vfp_tosls_round_to_zero;
5518 }
5519 }
5520
f73534a5
PM
5521 /* We have already masked out the must-be-1 top bit of imm6,
5522 * hence this 32-shift where the ARM ARM has 64-imm6.
5523 */
5524 shift = 32 - shift;
c253dd78
PM
5525 fpst = get_fpstatus_ptr(1);
5526 shiftv = tcg_const_i32(shift);
9ee6e8bb 5527 for (pass = 0; pass < (q ? 4 : 2); pass++) {
c253dd78
PM
5528 TCGv_i32 tmpf = neon_load_reg(rm, pass);
5529 fn(tmpf, tmpf, shiftv, fpst);
5530 neon_store_reg(rd, pass, tmpf);
2c0262af 5531 }
c253dd78
PM
5532 tcg_temp_free_ptr(fpst);
5533 tcg_temp_free_i32(shiftv);
2c0262af 5534 } else {
9ee6e8bb
PB
5535 return 1;
5536 }
5537 } else { /* (insn & 0x00380080) == 0 */
246fa4ac
RH
5538 int invert, reg_ofs, vec_size;
5539
7d80fee5
PM
5540 if (q && (rd & 1)) {
5541 return 1;
5542 }
9ee6e8bb
PB
5543
5544 op = (insn >> 8) & 0xf;
5545 /* One register and immediate. */
5546 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
5547 invert = (insn & (1 << 5)) != 0;
7d80fee5
PM
5548 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
5549 * We choose to not special-case this and will behave as if a
5550 * valid constant encoding of 0 had been given.
5551 */
9ee6e8bb
PB
5552 switch (op) {
5553 case 0: case 1:
5554 /* no-op */
5555 break;
5556 case 2: case 3:
5557 imm <<= 8;
5558 break;
5559 case 4: case 5:
5560 imm <<= 16;
5561 break;
5562 case 6: case 7:
5563 imm <<= 24;
5564 break;
5565 case 8: case 9:
5566 imm |= imm << 16;
5567 break;
5568 case 10: case 11:
5569 imm = (imm << 8) | (imm << 24);
5570 break;
5571 case 12:
8e31209e 5572 imm = (imm << 8) | 0xff;
9ee6e8bb
PB
5573 break;
5574 case 13:
5575 imm = (imm << 16) | 0xffff;
5576 break;
5577 case 14:
5578 imm |= (imm << 8) | (imm << 16) | (imm << 24);
246fa4ac 5579 if (invert) {
9ee6e8bb 5580 imm = ~imm;
246fa4ac 5581 }
9ee6e8bb
PB
5582 break;
5583 case 15:
7d80fee5
PM
5584 if (invert) {
5585 return 1;
5586 }
9ee6e8bb
PB
5587 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
5588 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
5589 break;
5590 }
246fa4ac 5591 if (invert) {
9ee6e8bb 5592 imm = ~imm;
246fa4ac 5593 }
9ee6e8bb 5594
246fa4ac
RH
5595 reg_ofs = neon_reg_offset(rd, 0);
5596 vec_size = q ? 16 : 8;
5597
5598 if (op & 1 && op < 12) {
5599 if (invert) {
5600 /* The immediate value has already been inverted,
5601 * so BIC becomes AND.
5602 */
5603 tcg_gen_gvec_andi(MO_32, reg_ofs, reg_ofs, imm,
5604 vec_size, vec_size);
9ee6e8bb 5605 } else {
246fa4ac
RH
5606 tcg_gen_gvec_ori(MO_32, reg_ofs, reg_ofs, imm,
5607 vec_size, vec_size);
5608 }
5609 } else {
5610 /* VMOV, VMVN. */
5611 if (op == 14 && invert) {
5612 TCGv_i64 t64 = tcg_temp_new_i64();
5613
5614 for (pass = 0; pass <= q; ++pass) {
5615 uint64_t val = 0;
a5a14945 5616 int n;
246fa4ac
RH
5617
5618 for (n = 0; n < 8; n++) {
5619 if (imm & (1 << (n + pass * 8))) {
5620 val |= 0xffull << (n * 8);
5621 }
9ee6e8bb 5622 }
246fa4ac
RH
5623 tcg_gen_movi_i64(t64, val);
5624 neon_store_reg64(t64, rd + pass);
9ee6e8bb 5625 }
246fa4ac
RH
5626 tcg_temp_free_i64(t64);
5627 } else {
5628 tcg_gen_gvec_dup32i(reg_ofs, vec_size, vec_size, imm);
9ee6e8bb
PB
5629 }
5630 }
5631 }
e4b3861d 5632 } else { /* (insn & 0x00800010 == 0x00800000) */
9ee6e8bb
PB
5633 if (size != 3) {
5634 op = (insn >> 8) & 0xf;
5635 if ((insn & (1 << 6)) == 0) {
5636 /* Three registers of different lengths. */
5637 int src1_wide;
5638 int src2_wide;
5639 int prewiden;
526d0096
PM
5640 /* undefreq: bit 0 : UNDEF if size == 0
5641 * bit 1 : UNDEF if size == 1
5642 * bit 2 : UNDEF if size == 2
5643 * bit 3 : UNDEF if U == 1
5644 * Note that [2:0] set implies 'always UNDEF'
695272dc
PM
5645 */
5646 int undefreq;
5647 /* prewiden, src1_wide, src2_wide, undefreq */
5648 static const int neon_3reg_wide[16][4] = {
5649 {1, 0, 0, 0}, /* VADDL */
5650 {1, 1, 0, 0}, /* VADDW */
5651 {1, 0, 0, 0}, /* VSUBL */
5652 {1, 1, 0, 0}, /* VSUBW */
5653 {0, 1, 1, 0}, /* VADDHN */
5654 {0, 0, 0, 0}, /* VABAL */
5655 {0, 1, 1, 0}, /* VSUBHN */
5656 {0, 0, 0, 0}, /* VABDL */
5657 {0, 0, 0, 0}, /* VMLAL */
526d0096 5658 {0, 0, 0, 9}, /* VQDMLAL */
695272dc 5659 {0, 0, 0, 0}, /* VMLSL */
526d0096 5660 {0, 0, 0, 9}, /* VQDMLSL */
695272dc 5661 {0, 0, 0, 0}, /* Integer VMULL */
526d0096 5662 {0, 0, 0, 1}, /* VQDMULL */
4e624eda 5663 {0, 0, 0, 0xa}, /* Polynomial VMULL */
526d0096 5664 {0, 0, 0, 7}, /* Reserved: always UNDEF */
9ee6e8bb
PB
5665 };
5666
5667 prewiden = neon_3reg_wide[op][0];
5668 src1_wide = neon_3reg_wide[op][1];
5669 src2_wide = neon_3reg_wide[op][2];
695272dc 5670 undefreq = neon_3reg_wide[op][3];
9ee6e8bb 5671
526d0096
PM
5672 if ((undefreq & (1 << size)) ||
5673 ((undefreq & 8) && u)) {
695272dc
PM
5674 return 1;
5675 }
5676 if ((src1_wide && (rn & 1)) ||
5677 (src2_wide && (rm & 1)) ||
5678 (!src2_wide && (rd & 1))) {
ad69471c 5679 return 1;
695272dc 5680 }
ad69471c 5681
4e624eda
PM
5682 /* Handle VMULL.P64 (Polynomial 64x64 to 128 bit multiply)
5683 * outside the loop below as it only performs a single pass.
5684 */
5685 if (op == 14 && size == 2) {
5686 TCGv_i64 tcg_rn, tcg_rm, tcg_rd;
5687
962fcbf2 5688 if (!dc_isar_feature(aa32_pmull, s)) {
4e624eda
PM
5689 return 1;
5690 }
5691 tcg_rn = tcg_temp_new_i64();
5692 tcg_rm = tcg_temp_new_i64();
5693 tcg_rd = tcg_temp_new_i64();
5694 neon_load_reg64(tcg_rn, rn);
5695 neon_load_reg64(tcg_rm, rm);
5696 gen_helper_neon_pmull_64_lo(tcg_rd, tcg_rn, tcg_rm);
5697 neon_store_reg64(tcg_rd, rd);
5698 gen_helper_neon_pmull_64_hi(tcg_rd, tcg_rn, tcg_rm);
5699 neon_store_reg64(tcg_rd, rd + 1);
5700 tcg_temp_free_i64(tcg_rn);
5701 tcg_temp_free_i64(tcg_rm);
5702 tcg_temp_free_i64(tcg_rd);
5703 return 0;
5704 }
5705
9ee6e8bb
PB
5706 /* Avoid overlapping operands. Wide source operands are
5707 always aligned so will never overlap with wide
5708 destinations in problematic ways. */
8f8e3aa4 5709 if (rd == rm && !src2_wide) {
dd8fbd78
FN
5710 tmp = neon_load_reg(rm, 1);
5711 neon_store_scratch(2, tmp);
8f8e3aa4 5712 } else if (rd == rn && !src1_wide) {
dd8fbd78
FN
5713 tmp = neon_load_reg(rn, 1);
5714 neon_store_scratch(2, tmp);
9ee6e8bb 5715 }
f764718d 5716 tmp3 = NULL;
9ee6e8bb 5717 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
5718 if (src1_wide) {
5719 neon_load_reg64(cpu_V0, rn + pass);
f764718d 5720 tmp = NULL;
9ee6e8bb 5721 } else {
ad69471c 5722 if (pass == 1 && rd == rn) {
dd8fbd78 5723 tmp = neon_load_scratch(2);
9ee6e8bb 5724 } else {
ad69471c
PB
5725 tmp = neon_load_reg(rn, pass);
5726 }
5727 if (prewiden) {
5728 gen_neon_widen(cpu_V0, tmp, size, u);
9ee6e8bb
PB
5729 }
5730 }
ad69471c
PB
5731 if (src2_wide) {
5732 neon_load_reg64(cpu_V1, rm + pass);
f764718d 5733 tmp2 = NULL;
9ee6e8bb 5734 } else {
ad69471c 5735 if (pass == 1 && rd == rm) {
dd8fbd78 5736 tmp2 = neon_load_scratch(2);
9ee6e8bb 5737 } else {
ad69471c
PB
5738 tmp2 = neon_load_reg(rm, pass);
5739 }
5740 if (prewiden) {
5741 gen_neon_widen(cpu_V1, tmp2, size, u);
9ee6e8bb 5742 }
9ee6e8bb
PB
5743 }
5744 switch (op) {
5745 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
ad69471c 5746 gen_neon_addl(size);
9ee6e8bb 5747 break;
79b0e534 5748 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
ad69471c 5749 gen_neon_subl(size);
9ee6e8bb
PB
5750 break;
5751 case 5: case 7: /* VABAL, VABDL */
5752 switch ((size << 1) | u) {
ad69471c
PB
5753 case 0:
5754 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
5755 break;
5756 case 1:
5757 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
5758 break;
5759 case 2:
5760 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
5761 break;
5762 case 3:
5763 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
5764 break;
5765 case 4:
5766 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
5767 break;
5768 case 5:
5769 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
5770 break;
9ee6e8bb
PB
5771 default: abort();
5772 }
7d1b0095
PM
5773 tcg_temp_free_i32(tmp2);
5774 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
5775 break;
5776 case 8: case 9: case 10: case 11: case 12: case 13:
5777 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
ad69471c 5778 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
9ee6e8bb
PB
5779 break;
5780 case 14: /* Polynomial VMULL */
e5ca24cb 5781 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
7d1b0095
PM
5782 tcg_temp_free_i32(tmp2);
5783 tcg_temp_free_i32(tmp);
e5ca24cb 5784 break;
695272dc
PM
5785 default: /* 15 is RESERVED: caught earlier */
5786 abort();
9ee6e8bb 5787 }
ebcd88ce
PM
5788 if (op == 13) {
5789 /* VQDMULL */
5790 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5791 neon_store_reg64(cpu_V0, rd + pass);
5792 } else if (op == 5 || (op >= 8 && op <= 11)) {
9ee6e8bb 5793 /* Accumulate. */
ebcd88ce 5794 neon_load_reg64(cpu_V1, rd + pass);
9ee6e8bb 5795 switch (op) {
4dc064e6
PM
5796 case 10: /* VMLSL */
5797 gen_neon_negl(cpu_V0, size);
5798 /* Fall through */
5799 case 5: case 8: /* VABAL, VMLAL */
ad69471c 5800 gen_neon_addl(size);
9ee6e8bb
PB
5801 break;
5802 case 9: case 11: /* VQDMLAL, VQDMLSL */
ad69471c 5803 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4dc064e6
PM
5804 if (op == 11) {
5805 gen_neon_negl(cpu_V0, size);
5806 }
ad69471c
PB
5807 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5808 break;
9ee6e8bb
PB
5809 default:
5810 abort();
5811 }
ad69471c 5812 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
5813 } else if (op == 4 || op == 6) {
5814 /* Narrowing operation. */
7d1b0095 5815 tmp = tcg_temp_new_i32();
79b0e534 5816 if (!u) {
9ee6e8bb 5817 switch (size) {
ad69471c
PB
5818 case 0:
5819 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
5820 break;
5821 case 1:
5822 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
5823 break;
5824 case 2:
664b7e3b 5825 tcg_gen_extrh_i64_i32(tmp, cpu_V0);
ad69471c 5826 break;
9ee6e8bb
PB
5827 default: abort();
5828 }
5829 } else {
5830 switch (size) {
ad69471c
PB
5831 case 0:
5832 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
5833 break;
5834 case 1:
5835 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
5836 break;
5837 case 2:
5838 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
664b7e3b 5839 tcg_gen_extrh_i64_i32(tmp, cpu_V0);
ad69471c 5840 break;
9ee6e8bb
PB
5841 default: abort();
5842 }
5843 }
ad69471c
PB
5844 if (pass == 0) {
5845 tmp3 = tmp;
5846 } else {
5847 neon_store_reg(rd, 0, tmp3);
5848 neon_store_reg(rd, 1, tmp);
5849 }
9ee6e8bb
PB
5850 } else {
5851 /* Write back the result. */
ad69471c 5852 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
5853 }
5854 }
5855 } else {
3e3326df
PM
5856 /* Two registers and a scalar. NB that for ops of this form
5857 * the ARM ARM labels bit 24 as Q, but it is in our variable
5858 * 'u', not 'q'.
5859 */
5860 if (size == 0) {
5861 return 1;
5862 }
9ee6e8bb 5863 switch (op) {
9ee6e8bb 5864 case 1: /* Float VMLA scalar */
9ee6e8bb 5865 case 5: /* Floating point VMLS scalar */
9ee6e8bb 5866 case 9: /* Floating point VMUL scalar */
3e3326df
PM
5867 if (size == 1) {
5868 return 1;
5869 }
5870 /* fall through */
5871 case 0: /* Integer VMLA scalar */
5872 case 4: /* Integer VMLS scalar */
5873 case 8: /* Integer VMUL scalar */
9ee6e8bb
PB
5874 case 12: /* VQDMULH scalar */
5875 case 13: /* VQRDMULH scalar */
3e3326df
PM
5876 if (u && ((rd | rn) & 1)) {
5877 return 1;
5878 }
dd8fbd78
FN
5879 tmp = neon_get_scalar(size, rm);
5880 neon_store_scratch(0, tmp);
9ee6e8bb 5881 for (pass = 0; pass < (u ? 4 : 2); pass++) {
dd8fbd78
FN
5882 tmp = neon_load_scratch(0);
5883 tmp2 = neon_load_reg(rn, pass);
9ee6e8bb
PB
5884 if (op == 12) {
5885 if (size == 1) {
02da0b2d 5886 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 5887 } else {
02da0b2d 5888 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
9ee6e8bb
PB
5889 }
5890 } else if (op == 13) {
5891 if (size == 1) {
02da0b2d 5892 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
9ee6e8bb 5893 } else {
02da0b2d 5894 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
9ee6e8bb
PB
5895 }
5896 } else if (op & 1) {
aa47cfdd
PM
5897 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5898 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
5899 tcg_temp_free_ptr(fpstatus);
9ee6e8bb
PB
5900 } else {
5901 switch (size) {
dd8fbd78
FN
5902 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5903 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5904 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
3e3326df 5905 default: abort();
9ee6e8bb
PB
5906 }
5907 }
7d1b0095 5908 tcg_temp_free_i32(tmp2);
9ee6e8bb
PB
5909 if (op < 8) {
5910 /* Accumulate. */
dd8fbd78 5911 tmp2 = neon_load_reg(rd, pass);
9ee6e8bb
PB
5912 switch (op) {
5913 case 0:
dd8fbd78 5914 gen_neon_add(size, tmp, tmp2);
9ee6e8bb
PB
5915 break;
5916 case 1:
aa47cfdd
PM
5917 {
5918 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5919 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5920 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 5921 break;
aa47cfdd 5922 }
9ee6e8bb 5923 case 4:
dd8fbd78 5924 gen_neon_rsb(size, tmp, tmp2);
9ee6e8bb
PB
5925 break;
5926 case 5:
aa47cfdd
PM
5927 {
5928 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5929 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
5930 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 5931 break;
aa47cfdd 5932 }
9ee6e8bb
PB
5933 default:
5934 abort();
5935 }
7d1b0095 5936 tcg_temp_free_i32(tmp2);
9ee6e8bb 5937 }
dd8fbd78 5938 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
5939 }
5940 break;
9ee6e8bb 5941 case 3: /* VQDMLAL scalar */
9ee6e8bb 5942 case 7: /* VQDMLSL scalar */
9ee6e8bb 5943 case 11: /* VQDMULL scalar */
3e3326df 5944 if (u == 1) {
ad69471c 5945 return 1;
3e3326df
PM
5946 }
5947 /* fall through */
5948 case 2: /* VMLAL sclar */
5949 case 6: /* VMLSL scalar */
5950 case 10: /* VMULL scalar */
5951 if (rd & 1) {
5952 return 1;
5953 }
dd8fbd78 5954 tmp2 = neon_get_scalar(size, rm);
c6067f04
CL
5955 /* We need a copy of tmp2 because gen_neon_mull
5956 * deletes it during pass 0. */
7d1b0095 5957 tmp4 = tcg_temp_new_i32();
c6067f04 5958 tcg_gen_mov_i32(tmp4, tmp2);
dd8fbd78 5959 tmp3 = neon_load_reg(rn, 1);
ad69471c 5960
9ee6e8bb 5961 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
5962 if (pass == 0) {
5963 tmp = neon_load_reg(rn, 0);
9ee6e8bb 5964 } else {
dd8fbd78 5965 tmp = tmp3;
c6067f04 5966 tmp2 = tmp4;
9ee6e8bb 5967 }
ad69471c 5968 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
ad69471c
PB
5969 if (op != 11) {
5970 neon_load_reg64(cpu_V1, rd + pass);
9ee6e8bb 5971 }
9ee6e8bb 5972 switch (op) {
4dc064e6
PM
5973 case 6:
5974 gen_neon_negl(cpu_V0, size);
5975 /* Fall through */
5976 case 2:
ad69471c 5977 gen_neon_addl(size);
9ee6e8bb
PB
5978 break;
5979 case 3: case 7:
ad69471c 5980 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4dc064e6
PM
5981 if (op == 7) {
5982 gen_neon_negl(cpu_V0, size);
5983 }
ad69471c 5984 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
9ee6e8bb
PB
5985 break;
5986 case 10:
5987 /* no-op */
5988 break;
5989 case 11:
ad69471c 5990 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
9ee6e8bb
PB
5991 break;
5992 default:
5993 abort();
5994 }
ad69471c 5995 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb 5996 }
61adacc8
RH
5997 break;
5998 case 14: /* VQRDMLAH scalar */
5999 case 15: /* VQRDMLSH scalar */
6000 {
6001 NeonGenThreeOpEnvFn *fn;
dd8fbd78 6002
962fcbf2 6003 if (!dc_isar_feature(aa32_rdm, s)) {
61adacc8
RH
6004 return 1;
6005 }
6006 if (u && ((rd | rn) & 1)) {
6007 return 1;
6008 }
6009 if (op == 14) {
6010 if (size == 1) {
6011 fn = gen_helper_neon_qrdmlah_s16;
6012 } else {
6013 fn = gen_helper_neon_qrdmlah_s32;
6014 }
6015 } else {
6016 if (size == 1) {
6017 fn = gen_helper_neon_qrdmlsh_s16;
6018 } else {
6019 fn = gen_helper_neon_qrdmlsh_s32;
6020 }
6021 }
dd8fbd78 6022
61adacc8
RH
6023 tmp2 = neon_get_scalar(size, rm);
6024 for (pass = 0; pass < (u ? 4 : 2); pass++) {
6025 tmp = neon_load_reg(rn, pass);
6026 tmp3 = neon_load_reg(rd, pass);
6027 fn(tmp, cpu_env, tmp, tmp2, tmp3);
6028 tcg_temp_free_i32(tmp3);
6029 neon_store_reg(rd, pass, tmp);
6030 }
6031 tcg_temp_free_i32(tmp2);
6032 }
9ee6e8bb 6033 break;
61adacc8
RH
6034 default:
6035 g_assert_not_reached();
9ee6e8bb
PB
6036 }
6037 }
6038 } else { /* size == 3 */
6039 if (!u) {
6040 /* Extract. */
9ee6e8bb 6041 imm = (insn >> 8) & 0xf;
ad69471c
PB
6042
6043 if (imm > 7 && !q)
6044 return 1;
6045
52579ea1
PM
6046 if (q && ((rd | rn | rm) & 1)) {
6047 return 1;
6048 }
6049
ad69471c
PB
6050 if (imm == 0) {
6051 neon_load_reg64(cpu_V0, rn);
6052 if (q) {
6053 neon_load_reg64(cpu_V1, rn + 1);
9ee6e8bb 6054 }
ad69471c
PB
6055 } else if (imm == 8) {
6056 neon_load_reg64(cpu_V0, rn + 1);
6057 if (q) {
6058 neon_load_reg64(cpu_V1, rm);
9ee6e8bb 6059 }
ad69471c 6060 } else if (q) {
a7812ae4 6061 tmp64 = tcg_temp_new_i64();
ad69471c
PB
6062 if (imm < 8) {
6063 neon_load_reg64(cpu_V0, rn);
a7812ae4 6064 neon_load_reg64(tmp64, rn + 1);
ad69471c
PB
6065 } else {
6066 neon_load_reg64(cpu_V0, rn + 1);
a7812ae4 6067 neon_load_reg64(tmp64, rm);
ad69471c
PB
6068 }
6069 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
a7812ae4 6070 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
ad69471c
PB
6071 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6072 if (imm < 8) {
6073 neon_load_reg64(cpu_V1, rm);
9ee6e8bb 6074 } else {
ad69471c
PB
6075 neon_load_reg64(cpu_V1, rm + 1);
6076 imm -= 8;
9ee6e8bb 6077 }
ad69471c 6078 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
a7812ae4
PB
6079 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
6080 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
b75263d6 6081 tcg_temp_free_i64(tmp64);
ad69471c 6082 } else {
a7812ae4 6083 /* BUGFIX */
ad69471c 6084 neon_load_reg64(cpu_V0, rn);
a7812ae4 6085 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
ad69471c 6086 neon_load_reg64(cpu_V1, rm);
a7812ae4 6087 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
ad69471c
PB
6088 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6089 }
6090 neon_store_reg64(cpu_V0, rd);
6091 if (q) {
6092 neon_store_reg64(cpu_V1, rd + 1);
9ee6e8bb
PB
6093 }
6094 } else if ((insn & (1 << 11)) == 0) {
6095 /* Two register misc. */
6096 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
6097 size = (insn >> 18) & 3;
600b828c
PM
6098 /* UNDEF for unknown op values and bad op-size combinations */
6099 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
6100 return 1;
6101 }
fe8fcf3d
PM
6102 if (neon_2rm_is_v8_op(op) &&
6103 !arm_dc_feature(s, ARM_FEATURE_V8)) {
6104 return 1;
6105 }
fc2a9b37
PM
6106 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
6107 q && ((rm | rd) & 1)) {
6108 return 1;
6109 }
9ee6e8bb 6110 switch (op) {
600b828c 6111 case NEON_2RM_VREV64:
9ee6e8bb 6112 for (pass = 0; pass < (q ? 2 : 1); pass++) {
dd8fbd78
FN
6113 tmp = neon_load_reg(rm, pass * 2);
6114 tmp2 = neon_load_reg(rm, pass * 2 + 1);
9ee6e8bb 6115 switch (size) {
dd8fbd78
FN
6116 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6117 case 1: gen_swap_half(tmp); break;
9ee6e8bb
PB
6118 case 2: /* no-op */ break;
6119 default: abort();
6120 }
dd8fbd78 6121 neon_store_reg(rd, pass * 2 + 1, tmp);
9ee6e8bb 6122 if (size == 2) {
dd8fbd78 6123 neon_store_reg(rd, pass * 2, tmp2);
9ee6e8bb 6124 } else {
9ee6e8bb 6125 switch (size) {
dd8fbd78
FN
6126 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
6127 case 1: gen_swap_half(tmp2); break;
9ee6e8bb
PB
6128 default: abort();
6129 }
dd8fbd78 6130 neon_store_reg(rd, pass * 2, tmp2);
9ee6e8bb
PB
6131 }
6132 }
6133 break;
600b828c
PM
6134 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
6135 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
ad69471c
PB
6136 for (pass = 0; pass < q + 1; pass++) {
6137 tmp = neon_load_reg(rm, pass * 2);
6138 gen_neon_widen(cpu_V0, tmp, size, op & 1);
6139 tmp = neon_load_reg(rm, pass * 2 + 1);
6140 gen_neon_widen(cpu_V1, tmp, size, op & 1);
6141 switch (size) {
6142 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
6143 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
6144 case 2: tcg_gen_add_i64(CPU_V001); break;
6145 default: abort();
6146 }
600b828c 6147 if (op >= NEON_2RM_VPADAL) {
9ee6e8bb 6148 /* Accumulate. */
ad69471c
PB
6149 neon_load_reg64(cpu_V1, rd + pass);
6150 gen_neon_addl(size);
9ee6e8bb 6151 }
ad69471c 6152 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
6153 }
6154 break;
600b828c 6155 case NEON_2RM_VTRN:
9ee6e8bb 6156 if (size == 2) {
a5a14945 6157 int n;
9ee6e8bb 6158 for (n = 0; n < (q ? 4 : 2); n += 2) {
dd8fbd78
FN
6159 tmp = neon_load_reg(rm, n);
6160 tmp2 = neon_load_reg(rd, n + 1);
6161 neon_store_reg(rm, n, tmp2);
6162 neon_store_reg(rd, n + 1, tmp);
9ee6e8bb
PB
6163 }
6164 } else {
6165 goto elementwise;
6166 }
6167 break;
600b828c 6168 case NEON_2RM_VUZP:
02acedf9 6169 if (gen_neon_unzip(rd, rm, size, q)) {
9ee6e8bb 6170 return 1;
9ee6e8bb
PB
6171 }
6172 break;
600b828c 6173 case NEON_2RM_VZIP:
d68a6f3a 6174 if (gen_neon_zip(rd, rm, size, q)) {
9ee6e8bb 6175 return 1;
9ee6e8bb
PB
6176 }
6177 break;
600b828c
PM
6178 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
6179 /* also VQMOVUN; op field and mnemonics don't line up */
fc2a9b37
PM
6180 if (rm & 1) {
6181 return 1;
6182 }
f764718d 6183 tmp2 = NULL;
9ee6e8bb 6184 for (pass = 0; pass < 2; pass++) {
ad69471c 6185 neon_load_reg64(cpu_V0, rm + pass);
7d1b0095 6186 tmp = tcg_temp_new_i32();
600b828c
PM
6187 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
6188 tmp, cpu_V0);
ad69471c
PB
6189 if (pass == 0) {
6190 tmp2 = tmp;
6191 } else {
6192 neon_store_reg(rd, 0, tmp2);
6193 neon_store_reg(rd, 1, tmp);
9ee6e8bb 6194 }
9ee6e8bb
PB
6195 }
6196 break;
600b828c 6197 case NEON_2RM_VSHLL:
fc2a9b37 6198 if (q || (rd & 1)) {
9ee6e8bb 6199 return 1;
600b828c 6200 }
ad69471c
PB
6201 tmp = neon_load_reg(rm, 0);
6202 tmp2 = neon_load_reg(rm, 1);
9ee6e8bb 6203 for (pass = 0; pass < 2; pass++) {
ad69471c
PB
6204 if (pass == 1)
6205 tmp = tmp2;
6206 gen_neon_widen(cpu_V0, tmp, size, 1);
30d11a2a 6207 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
ad69471c 6208 neon_store_reg64(cpu_V0, rd + pass);
9ee6e8bb
PB
6209 }
6210 break;
600b828c 6211 case NEON_2RM_VCVT_F16_F32:
486624fc
AB
6212 {
6213 TCGv_ptr fpst;
6214 TCGv_i32 ahp;
6215
602f6e42 6216 if (!dc_isar_feature(aa32_fp16_spconv, s) ||
fc2a9b37
PM
6217 q || (rm & 1)) {
6218 return 1;
6219 }
486624fc
AB
6220 fpst = get_fpstatus_ptr(true);
6221 ahp = get_ahp_flag();
58f2682e
PM
6222 tmp = neon_load_reg(rm, 0);
6223 gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp);
6224 tmp2 = neon_load_reg(rm, 1);
6225 gen_helper_vfp_fcvt_f32_to_f16(tmp2, tmp2, fpst, ahp);
60011498
PB
6226 tcg_gen_shli_i32(tmp2, tmp2, 16);
6227 tcg_gen_or_i32(tmp2, tmp2, tmp);
58f2682e
PM
6228 tcg_temp_free_i32(tmp);
6229 tmp = neon_load_reg(rm, 2);
6230 gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp);
6231 tmp3 = neon_load_reg(rm, 3);
60011498 6232 neon_store_reg(rd, 0, tmp2);
58f2682e
PM
6233 gen_helper_vfp_fcvt_f32_to_f16(tmp3, tmp3, fpst, ahp);
6234 tcg_gen_shli_i32(tmp3, tmp3, 16);
6235 tcg_gen_or_i32(tmp3, tmp3, tmp);
6236 neon_store_reg(rd, 1, tmp3);
7d1b0095 6237 tcg_temp_free_i32(tmp);
486624fc
AB
6238 tcg_temp_free_i32(ahp);
6239 tcg_temp_free_ptr(fpst);
60011498 6240 break;
486624fc 6241 }
600b828c 6242 case NEON_2RM_VCVT_F32_F16:
486624fc
AB
6243 {
6244 TCGv_ptr fpst;
6245 TCGv_i32 ahp;
602f6e42 6246 if (!dc_isar_feature(aa32_fp16_spconv, s) ||
fc2a9b37
PM
6247 q || (rd & 1)) {
6248 return 1;
6249 }
486624fc
AB
6250 fpst = get_fpstatus_ptr(true);
6251 ahp = get_ahp_flag();
7d1b0095 6252 tmp3 = tcg_temp_new_i32();
60011498
PB
6253 tmp = neon_load_reg(rm, 0);
6254 tmp2 = neon_load_reg(rm, 1);
6255 tcg_gen_ext16u_i32(tmp3, tmp);
b66f6b99
PM
6256 gen_helper_vfp_fcvt_f16_to_f32(tmp3, tmp3, fpst, ahp);
6257 neon_store_reg(rd, 0, tmp3);
6258 tcg_gen_shri_i32(tmp, tmp, 16);
6259 gen_helper_vfp_fcvt_f16_to_f32(tmp, tmp, fpst, ahp);
6260 neon_store_reg(rd, 1, tmp);
6261 tmp3 = tcg_temp_new_i32();
60011498 6262 tcg_gen_ext16u_i32(tmp3, tmp2);
b66f6b99
PM
6263 gen_helper_vfp_fcvt_f16_to_f32(tmp3, tmp3, fpst, ahp);
6264 neon_store_reg(rd, 2, tmp3);
6265 tcg_gen_shri_i32(tmp2, tmp2, 16);
6266 gen_helper_vfp_fcvt_f16_to_f32(tmp2, tmp2, fpst, ahp);
6267 neon_store_reg(rd, 3, tmp2);
486624fc
AB
6268 tcg_temp_free_i32(ahp);
6269 tcg_temp_free_ptr(fpst);
60011498 6270 break;
486624fc 6271 }
9d935509 6272 case NEON_2RM_AESE: case NEON_2RM_AESMC:
962fcbf2 6273 if (!dc_isar_feature(aa32_aes, s) || ((rm | rd) & 1)) {
9d935509
AB
6274 return 1;
6275 }
1a66ac61
RH
6276 ptr1 = vfp_reg_ptr(true, rd);
6277 ptr2 = vfp_reg_ptr(true, rm);
9d935509
AB
6278
6279 /* Bit 6 is the lowest opcode bit; it distinguishes between
6280 * encryption (AESE/AESMC) and decryption (AESD/AESIMC)
6281 */
6282 tmp3 = tcg_const_i32(extract32(insn, 6, 1));
6283
6284 if (op == NEON_2RM_AESE) {
1a66ac61 6285 gen_helper_crypto_aese(ptr1, ptr2, tmp3);
9d935509 6286 } else {
1a66ac61 6287 gen_helper_crypto_aesmc(ptr1, ptr2, tmp3);
9d935509 6288 }
1a66ac61
RH
6289 tcg_temp_free_ptr(ptr1);
6290 tcg_temp_free_ptr(ptr2);
9d935509
AB
6291 tcg_temp_free_i32(tmp3);
6292 break;
f1ecb913 6293 case NEON_2RM_SHA1H:
962fcbf2 6294 if (!dc_isar_feature(aa32_sha1, s) || ((rm | rd) & 1)) {
f1ecb913
AB
6295 return 1;
6296 }
1a66ac61
RH
6297 ptr1 = vfp_reg_ptr(true, rd);
6298 ptr2 = vfp_reg_ptr(true, rm);
f1ecb913 6299
1a66ac61 6300 gen_helper_crypto_sha1h(ptr1, ptr2);
f1ecb913 6301
1a66ac61
RH
6302 tcg_temp_free_ptr(ptr1);
6303 tcg_temp_free_ptr(ptr2);
f1ecb913
AB
6304 break;
6305 case NEON_2RM_SHA1SU1:
6306 if ((rm | rd) & 1) {
6307 return 1;
6308 }
6309 /* bit 6 (q): set -> SHA256SU0, cleared -> SHA1SU1 */
6310 if (q) {
962fcbf2 6311 if (!dc_isar_feature(aa32_sha2, s)) {
f1ecb913
AB
6312 return 1;
6313 }
962fcbf2 6314 } else if (!dc_isar_feature(aa32_sha1, s)) {
f1ecb913
AB
6315 return 1;
6316 }
1a66ac61
RH
6317 ptr1 = vfp_reg_ptr(true, rd);
6318 ptr2 = vfp_reg_ptr(true, rm);
f1ecb913 6319 if (q) {
1a66ac61 6320 gen_helper_crypto_sha256su0(ptr1, ptr2);
f1ecb913 6321 } else {
1a66ac61 6322 gen_helper_crypto_sha1su1(ptr1, ptr2);
f1ecb913 6323 }
1a66ac61
RH
6324 tcg_temp_free_ptr(ptr1);
6325 tcg_temp_free_ptr(ptr2);
f1ecb913 6326 break;
4bf940be
RH
6327
6328 case NEON_2RM_VMVN:
6329 tcg_gen_gvec_not(0, rd_ofs, rm_ofs, vec_size, vec_size);
6330 break;
6331 case NEON_2RM_VNEG:
6332 tcg_gen_gvec_neg(size, rd_ofs, rm_ofs, vec_size, vec_size);
6333 break;
4e027a71
RH
6334 case NEON_2RM_VABS:
6335 tcg_gen_gvec_abs(size, rd_ofs, rm_ofs, vec_size, vec_size);
6336 break;
4bf940be 6337
9ee6e8bb
PB
6338 default:
6339 elementwise:
6340 for (pass = 0; pass < (q ? 4 : 2); pass++) {
60737ed5 6341 tmp = neon_load_reg(rm, pass);
9ee6e8bb 6342 switch (op) {
600b828c 6343 case NEON_2RM_VREV32:
9ee6e8bb 6344 switch (size) {
dd8fbd78
FN
6345 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6346 case 1: gen_swap_half(tmp); break;
600b828c 6347 default: abort();
9ee6e8bb
PB
6348 }
6349 break;
600b828c 6350 case NEON_2RM_VREV16:
46497f6a 6351 gen_rev16(tmp, tmp);
9ee6e8bb 6352 break;
600b828c 6353 case NEON_2RM_VCLS:
9ee6e8bb 6354 switch (size) {
dd8fbd78
FN
6355 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
6356 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
6357 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
600b828c 6358 default: abort();
9ee6e8bb
PB
6359 }
6360 break;
600b828c 6361 case NEON_2RM_VCLZ:
9ee6e8bb 6362 switch (size) {
dd8fbd78
FN
6363 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
6364 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
7539a012 6365 case 2: tcg_gen_clzi_i32(tmp, tmp, 32); break;
600b828c 6366 default: abort();
9ee6e8bb
PB
6367 }
6368 break;
600b828c 6369 case NEON_2RM_VCNT:
dd8fbd78 6370 gen_helper_neon_cnt_u8(tmp, tmp);
9ee6e8bb 6371 break;
600b828c 6372 case NEON_2RM_VQABS:
9ee6e8bb 6373 switch (size) {
02da0b2d
PM
6374 case 0:
6375 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
6376 break;
6377 case 1:
6378 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
6379 break;
6380 case 2:
6381 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
6382 break;
600b828c 6383 default: abort();
9ee6e8bb
PB
6384 }
6385 break;
600b828c 6386 case NEON_2RM_VQNEG:
9ee6e8bb 6387 switch (size) {
02da0b2d
PM
6388 case 0:
6389 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
6390 break;
6391 case 1:
6392 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
6393 break;
6394 case 2:
6395 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
6396 break;
600b828c 6397 default: abort();
9ee6e8bb
PB
6398 }
6399 break;
600b828c 6400 case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
dd8fbd78 6401 tmp2 = tcg_const_i32(0);
9ee6e8bb 6402 switch(size) {
dd8fbd78
FN
6403 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
6404 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
6405 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
600b828c 6406 default: abort();
9ee6e8bb 6407 }
39d5492a 6408 tcg_temp_free_i32(tmp2);
600b828c 6409 if (op == NEON_2RM_VCLE0) {
dd8fbd78 6410 tcg_gen_not_i32(tmp, tmp);
600b828c 6411 }
9ee6e8bb 6412 break;
600b828c 6413 case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
dd8fbd78 6414 tmp2 = tcg_const_i32(0);
9ee6e8bb 6415 switch(size) {
dd8fbd78
FN
6416 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
6417 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
6418 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
600b828c 6419 default: abort();
9ee6e8bb 6420 }
39d5492a 6421 tcg_temp_free_i32(tmp2);
600b828c 6422 if (op == NEON_2RM_VCLT0) {
dd8fbd78 6423 tcg_gen_not_i32(tmp, tmp);
600b828c 6424 }
9ee6e8bb 6425 break;
600b828c 6426 case NEON_2RM_VCEQ0:
dd8fbd78 6427 tmp2 = tcg_const_i32(0);
9ee6e8bb 6428 switch(size) {
dd8fbd78
FN
6429 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
6430 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
6431 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
600b828c 6432 default: abort();
9ee6e8bb 6433 }
39d5492a 6434 tcg_temp_free_i32(tmp2);
9ee6e8bb 6435 break;
600b828c 6436 case NEON_2RM_VCGT0_F:
aa47cfdd
PM
6437 {
6438 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
dd8fbd78 6439 tmp2 = tcg_const_i32(0);
aa47cfdd 6440 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
39d5492a 6441 tcg_temp_free_i32(tmp2);
aa47cfdd 6442 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6443 break;
aa47cfdd 6444 }
600b828c 6445 case NEON_2RM_VCGE0_F:
aa47cfdd
PM
6446 {
6447 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
dd8fbd78 6448 tmp2 = tcg_const_i32(0);
aa47cfdd 6449 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
39d5492a 6450 tcg_temp_free_i32(tmp2);
aa47cfdd 6451 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6452 break;
aa47cfdd 6453 }
600b828c 6454 case NEON_2RM_VCEQ0_F:
aa47cfdd
PM
6455 {
6456 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
dd8fbd78 6457 tmp2 = tcg_const_i32(0);
aa47cfdd 6458 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
39d5492a 6459 tcg_temp_free_i32(tmp2);
aa47cfdd 6460 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6461 break;
aa47cfdd 6462 }
600b828c 6463 case NEON_2RM_VCLE0_F:
aa47cfdd
PM
6464 {
6465 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
0e326109 6466 tmp2 = tcg_const_i32(0);
aa47cfdd 6467 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
39d5492a 6468 tcg_temp_free_i32(tmp2);
aa47cfdd 6469 tcg_temp_free_ptr(fpstatus);
0e326109 6470 break;
aa47cfdd 6471 }
600b828c 6472 case NEON_2RM_VCLT0_F:
aa47cfdd
PM
6473 {
6474 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
0e326109 6475 tmp2 = tcg_const_i32(0);
aa47cfdd 6476 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
39d5492a 6477 tcg_temp_free_i32(tmp2);
aa47cfdd 6478 tcg_temp_free_ptr(fpstatus);
0e326109 6479 break;
aa47cfdd 6480 }
600b828c 6481 case NEON_2RM_VABS_F:
fd8a68cd 6482 gen_helper_vfp_abss(tmp, tmp);
9ee6e8bb 6483 break;
600b828c 6484 case NEON_2RM_VNEG_F:
cedcc96f 6485 gen_helper_vfp_negs(tmp, tmp);
9ee6e8bb 6486 break;
600b828c 6487 case NEON_2RM_VSWP:
dd8fbd78
FN
6488 tmp2 = neon_load_reg(rd, pass);
6489 neon_store_reg(rm, pass, tmp2);
9ee6e8bb 6490 break;
600b828c 6491 case NEON_2RM_VTRN:
dd8fbd78 6492 tmp2 = neon_load_reg(rd, pass);
9ee6e8bb 6493 switch (size) {
dd8fbd78
FN
6494 case 0: gen_neon_trn_u8(tmp, tmp2); break;
6495 case 1: gen_neon_trn_u16(tmp, tmp2); break;
600b828c 6496 default: abort();
9ee6e8bb 6497 }
dd8fbd78 6498 neon_store_reg(rm, pass, tmp2);
9ee6e8bb 6499 break;
34f7b0a2
WN
6500 case NEON_2RM_VRINTN:
6501 case NEON_2RM_VRINTA:
6502 case NEON_2RM_VRINTM:
6503 case NEON_2RM_VRINTP:
6504 case NEON_2RM_VRINTZ:
6505 {
6506 TCGv_i32 tcg_rmode;
6507 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6508 int rmode;
6509
6510 if (op == NEON_2RM_VRINTZ) {
6511 rmode = FPROUNDING_ZERO;
6512 } else {
6513 rmode = fp_decode_rm[((op & 0x6) >> 1) ^ 1];
6514 }
6515
6516 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
6517 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6518 cpu_env);
3b52ad1f 6519 gen_helper_rints(tmp, tmp, fpstatus);
34f7b0a2
WN
6520 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6521 cpu_env);
6522 tcg_temp_free_ptr(fpstatus);
6523 tcg_temp_free_i32(tcg_rmode);
6524 break;
6525 }
2ce70625
WN
6526 case NEON_2RM_VRINTX:
6527 {
6528 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
3b52ad1f 6529 gen_helper_rints_exact(tmp, tmp, fpstatus);
2ce70625
WN
6530 tcg_temp_free_ptr(fpstatus);
6531 break;
6532 }
901ad525
WN
6533 case NEON_2RM_VCVTAU:
6534 case NEON_2RM_VCVTAS:
6535 case NEON_2RM_VCVTNU:
6536 case NEON_2RM_VCVTNS:
6537 case NEON_2RM_VCVTPU:
6538 case NEON_2RM_VCVTPS:
6539 case NEON_2RM_VCVTMU:
6540 case NEON_2RM_VCVTMS:
6541 {
6542 bool is_signed = !extract32(insn, 7, 1);
6543 TCGv_ptr fpst = get_fpstatus_ptr(1);
6544 TCGv_i32 tcg_rmode, tcg_shift;
6545 int rmode = fp_decode_rm[extract32(insn, 8, 2)];
6546
6547 tcg_shift = tcg_const_i32(0);
6548 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
6549 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6550 cpu_env);
6551
6552 if (is_signed) {
30bf0a01 6553 gen_helper_vfp_tosls(tmp, tmp,
901ad525
WN
6554 tcg_shift, fpst);
6555 } else {
30bf0a01 6556 gen_helper_vfp_touls(tmp, tmp,
901ad525
WN
6557 tcg_shift, fpst);
6558 }
6559
6560 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6561 cpu_env);
6562 tcg_temp_free_i32(tcg_rmode);
6563 tcg_temp_free_i32(tcg_shift);
6564 tcg_temp_free_ptr(fpst);
6565 break;
6566 }
600b828c 6567 case NEON_2RM_VRECPE:
b6d4443a
AB
6568 {
6569 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6570 gen_helper_recpe_u32(tmp, tmp, fpstatus);
6571 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6572 break;
b6d4443a 6573 }
600b828c 6574 case NEON_2RM_VRSQRTE:
c2fb418e
AB
6575 {
6576 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6577 gen_helper_rsqrte_u32(tmp, tmp, fpstatus);
6578 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6579 break;
c2fb418e 6580 }
600b828c 6581 case NEON_2RM_VRECPE_F:
b6d4443a
AB
6582 {
6583 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
9a011fec 6584 gen_helper_recpe_f32(tmp, tmp, fpstatus);
b6d4443a 6585 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6586 break;
b6d4443a 6587 }
600b828c 6588 case NEON_2RM_VRSQRTE_F:
c2fb418e
AB
6589 {
6590 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
9a011fec 6591 gen_helper_rsqrte_f32(tmp, tmp, fpstatus);
c2fb418e 6592 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6593 break;
c2fb418e 6594 }
600b828c 6595 case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
60737ed5
PM
6596 {
6597 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6598 gen_helper_vfp_sitos(tmp, tmp, fpstatus);
6599 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6600 break;
60737ed5 6601 }
600b828c 6602 case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
60737ed5
PM
6603 {
6604 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6605 gen_helper_vfp_uitos(tmp, tmp, fpstatus);
6606 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6607 break;
60737ed5 6608 }
600b828c 6609 case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
60737ed5
PM
6610 {
6611 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6612 gen_helper_vfp_tosizs(tmp, tmp, fpstatus);
6613 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6614 break;
60737ed5 6615 }
600b828c 6616 case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
60737ed5
PM
6617 {
6618 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6619 gen_helper_vfp_touizs(tmp, tmp, fpstatus);
6620 tcg_temp_free_ptr(fpstatus);
9ee6e8bb 6621 break;
60737ed5 6622 }
9ee6e8bb 6623 default:
600b828c
PM
6624 /* Reserved op values were caught by the
6625 * neon_2rm_sizes[] check earlier.
6626 */
6627 abort();
9ee6e8bb 6628 }
60737ed5 6629 neon_store_reg(rd, pass, tmp);
9ee6e8bb
PB
6630 }
6631 break;
6632 }
6633 } else if ((insn & (1 << 10)) == 0) {
6634 /* VTBL, VTBX. */
56907d77
PM
6635 int n = ((insn >> 8) & 3) + 1;
6636 if ((rn + n) > 32) {
6637 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
6638 * helper function running off the end of the register file.
6639 */
6640 return 1;
6641 }
6642 n <<= 3;
9ee6e8bb 6643 if (insn & (1 << 6)) {
8f8e3aa4 6644 tmp = neon_load_reg(rd, 0);
9ee6e8bb 6645 } else {
7d1b0095 6646 tmp = tcg_temp_new_i32();
8f8e3aa4 6647 tcg_gen_movi_i32(tmp, 0);
9ee6e8bb 6648 }
8f8e3aa4 6649 tmp2 = neon_load_reg(rm, 0);
e7c06c4e 6650 ptr1 = vfp_reg_ptr(true, rn);
b75263d6 6651 tmp5 = tcg_const_i32(n);
e7c06c4e 6652 gen_helper_neon_tbl(tmp2, tmp2, tmp, ptr1, tmp5);
7d1b0095 6653 tcg_temp_free_i32(tmp);
9ee6e8bb 6654 if (insn & (1 << 6)) {
8f8e3aa4 6655 tmp = neon_load_reg(rd, 1);
9ee6e8bb 6656 } else {
7d1b0095 6657 tmp = tcg_temp_new_i32();
8f8e3aa4 6658 tcg_gen_movi_i32(tmp, 0);
9ee6e8bb 6659 }
8f8e3aa4 6660 tmp3 = neon_load_reg(rm, 1);
e7c06c4e 6661 gen_helper_neon_tbl(tmp3, tmp3, tmp, ptr1, tmp5);
25aeb69b 6662 tcg_temp_free_i32(tmp5);
e7c06c4e 6663 tcg_temp_free_ptr(ptr1);
8f8e3aa4 6664 neon_store_reg(rd, 0, tmp2);
3018f259 6665 neon_store_reg(rd, 1, tmp3);
7d1b0095 6666 tcg_temp_free_i32(tmp);
9ee6e8bb
PB
6667 } else if ((insn & 0x380) == 0) {
6668 /* VDUP */
32f91fb7 6669 int element;
14776ab5 6670 MemOp size;
32f91fb7 6671
133da6aa
JR
6672 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
6673 return 1;
6674 }
9ee6e8bb 6675 if (insn & (1 << 16)) {
32f91fb7
RH
6676 size = MO_8;
6677 element = (insn >> 17) & 7;
9ee6e8bb 6678 } else if (insn & (1 << 17)) {
32f91fb7
RH
6679 size = MO_16;
6680 element = (insn >> 18) & 3;
6681 } else {
6682 size = MO_32;
6683 element = (insn >> 19) & 1;
9ee6e8bb 6684 }
32f91fb7
RH
6685 tcg_gen_gvec_dup_mem(size, neon_reg_offset(rd, 0),
6686 neon_element_offset(rm, element, size),
6687 q ? 16 : 8, q ? 16 : 8);
9ee6e8bb
PB
6688 } else {
6689 return 1;
6690 }
6691 }
6692 }
6693 return 0;
6694}
6695
8b7209fa
RH
6696/* Advanced SIMD three registers of the same length extension.
6697 * 31 25 23 22 20 16 12 11 10 9 8 3 0
6698 * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
6699 * | 1 1 1 1 1 1 0 | op1 | D | op2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
6700 * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
6701 */
6702static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
6703{
26c470a7
RH
6704 gen_helper_gvec_3 *fn_gvec = NULL;
6705 gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
6706 int rd, rn, rm, opr_sz;
6707 int data = 0;
87732318
RH
6708 int off_rn, off_rm;
6709 bool is_long = false, q = extract32(insn, 6, 1);
6710 bool ptr_is_env = false;
8b7209fa
RH
6711
6712 if ((insn & 0xfe200f10) == 0xfc200800) {
6713 /* VCMLA -- 1111 110R R.1S .... .... 1000 ...0 .... */
26c470a7
RH
6714 int size = extract32(insn, 20, 1);
6715 data = extract32(insn, 23, 2); /* rot */
962fcbf2 6716 if (!dc_isar_feature(aa32_vcma, s)
5763190f 6717 || (!size && !dc_isar_feature(aa32_fp16_arith, s))) {
8b7209fa
RH
6718 return 1;
6719 }
6720 fn_gvec_ptr = size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
6721 } else if ((insn & 0xfea00f10) == 0xfc800800) {
6722 /* VCADD -- 1111 110R 1.0S .... .... 1000 ...0 .... */
26c470a7
RH
6723 int size = extract32(insn, 20, 1);
6724 data = extract32(insn, 24, 1); /* rot */
962fcbf2 6725 if (!dc_isar_feature(aa32_vcma, s)
5763190f 6726 || (!size && !dc_isar_feature(aa32_fp16_arith, s))) {
8b7209fa
RH
6727 return 1;
6728 }
6729 fn_gvec_ptr = size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
26c470a7
RH
6730 } else if ((insn & 0xfeb00f00) == 0xfc200d00) {
6731 /* V[US]DOT -- 1111 1100 0.10 .... .... 1101 .Q.U .... */
6732 bool u = extract32(insn, 4, 1);
962fcbf2 6733 if (!dc_isar_feature(aa32_dp, s)) {
26c470a7
RH
6734 return 1;
6735 }
6736 fn_gvec = u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b;
87732318
RH
6737 } else if ((insn & 0xff300f10) == 0xfc200810) {
6738 /* VFM[AS]L -- 1111 1100 S.10 .... .... 1000 .Q.1 .... */
6739 int is_s = extract32(insn, 23, 1);
6740 if (!dc_isar_feature(aa32_fhm, s)) {
6741 return 1;
6742 }
6743 is_long = true;
6744 data = is_s; /* is_2 == 0 */
6745 fn_gvec_ptr = gen_helper_gvec_fmlal_a32;
6746 ptr_is_env = true;
8b7209fa
RH
6747 } else {
6748 return 1;
6749 }
6750
87732318
RH
6751 VFP_DREG_D(rd, insn);
6752 if (rd & q) {
6753 return 1;
6754 }
6755 if (q || !is_long) {
6756 VFP_DREG_N(rn, insn);
6757 VFP_DREG_M(rm, insn);
6758 if ((rn | rm) & q & !is_long) {
6759 return 1;
6760 }
6761 off_rn = vfp_reg_offset(1, rn);
6762 off_rm = vfp_reg_offset(1, rm);
6763 } else {
6764 rn = VFP_SREG_N(insn);
6765 rm = VFP_SREG_M(insn);
6766 off_rn = vfp_reg_offset(0, rn);
6767 off_rm = vfp_reg_offset(0, rm);
6768 }
6769
8b7209fa 6770 if (s->fp_excp_el) {
a767fac8 6771 gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
4be42f40 6772 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
8b7209fa
RH
6773 return 0;
6774 }
6775 if (!s->vfp_enabled) {
6776 return 1;
6777 }
6778
6779 opr_sz = (1 + q) * 8;
26c470a7 6780 if (fn_gvec_ptr) {
87732318
RH
6781 TCGv_ptr ptr;
6782 if (ptr_is_env) {
6783 ptr = cpu_env;
6784 } else {
6785 ptr = get_fpstatus_ptr(1);
6786 }
6787 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
26c470a7 6788 opr_sz, opr_sz, data, fn_gvec_ptr);
87732318
RH
6789 if (!ptr_is_env) {
6790 tcg_temp_free_ptr(ptr);
6791 }
26c470a7 6792 } else {
87732318 6793 tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
26c470a7
RH
6794 opr_sz, opr_sz, data, fn_gvec);
6795 }
8b7209fa
RH
6796 return 0;
6797}
6798
638808ff
RH
6799/* Advanced SIMD two registers and a scalar extension.
6800 * 31 24 23 22 20 16 12 11 10 9 8 3 0
6801 * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
6802 * | 1 1 1 1 1 1 1 0 | o1 | D | o2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
6803 * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
6804 *
6805 */
6806
6807static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
6808{
26c470a7
RH
6809 gen_helper_gvec_3 *fn_gvec = NULL;
6810 gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
2cc99919 6811 int rd, rn, rm, opr_sz, data;
87732318
RH
6812 int off_rn, off_rm;
6813 bool is_long = false, q = extract32(insn, 6, 1);
6814 bool ptr_is_env = false;
638808ff
RH
6815
6816 if ((insn & 0xff000f10) == 0xfe000800) {
6817 /* VCMLA (indexed) -- 1111 1110 S.RR .... .... 1000 ...0 .... */
2cc99919
RH
6818 int rot = extract32(insn, 20, 2);
6819 int size = extract32(insn, 23, 1);
6820 int index;
6821
962fcbf2 6822 if (!dc_isar_feature(aa32_vcma, s)) {
638808ff
RH
6823 return 1;
6824 }
2cc99919 6825 if (size == 0) {
5763190f 6826 if (!dc_isar_feature(aa32_fp16_arith, s)) {
2cc99919
RH
6827 return 1;
6828 }
6829 /* For fp16, rm is just Vm, and index is M. */
6830 rm = extract32(insn, 0, 4);
6831 index = extract32(insn, 5, 1);
6832 } else {
6833 /* For fp32, rm is the usual M:Vm, and index is 0. */
6834 VFP_DREG_M(rm, insn);
6835 index = 0;
6836 }
6837 data = (index << 2) | rot;
6838 fn_gvec_ptr = (size ? gen_helper_gvec_fcmlas_idx
6839 : gen_helper_gvec_fcmlah_idx);
26c470a7
RH
6840 } else if ((insn & 0xffb00f00) == 0xfe200d00) {
6841 /* V[US]DOT -- 1111 1110 0.10 .... .... 1101 .Q.U .... */
6842 int u = extract32(insn, 4, 1);
87732318 6843
962fcbf2 6844 if (!dc_isar_feature(aa32_dp, s)) {
26c470a7
RH
6845 return 1;
6846 }
6847 fn_gvec = u ? gen_helper_gvec_udot_idx_b : gen_helper_gvec_sdot_idx_b;
6848 /* rm is just Vm, and index is M. */
6849 data = extract32(insn, 5, 1); /* index */
6850 rm = extract32(insn, 0, 4);
87732318
RH
6851 } else if ((insn & 0xffa00f10) == 0xfe000810) {
6852 /* VFM[AS]L -- 1111 1110 0.0S .... .... 1000 .Q.1 .... */
6853 int is_s = extract32(insn, 20, 1);
6854 int vm20 = extract32(insn, 0, 3);
6855 int vm3 = extract32(insn, 3, 1);
6856 int m = extract32(insn, 5, 1);
6857 int index;
6858
6859 if (!dc_isar_feature(aa32_fhm, s)) {
6860 return 1;
6861 }
6862 if (q) {
6863 rm = vm20;
6864 index = m * 2 + vm3;
6865 } else {
6866 rm = vm20 * 2 + m;
6867 index = vm3;
6868 }
6869 is_long = true;
6870 data = (index << 2) | is_s; /* is_2 == 0 */
6871 fn_gvec_ptr = gen_helper_gvec_fmlal_idx_a32;
6872 ptr_is_env = true;
638808ff
RH
6873 } else {
6874 return 1;
6875 }
6876
87732318
RH
6877 VFP_DREG_D(rd, insn);
6878 if (rd & q) {
6879 return 1;
6880 }
6881 if (q || !is_long) {
6882 VFP_DREG_N(rn, insn);
6883 if (rn & q & !is_long) {
6884 return 1;
6885 }
6886 off_rn = vfp_reg_offset(1, rn);
6887 off_rm = vfp_reg_offset(1, rm);
6888 } else {
6889 rn = VFP_SREG_N(insn);
6890 off_rn = vfp_reg_offset(0, rn);
6891 off_rm = vfp_reg_offset(0, rm);
6892 }
638808ff 6893 if (s->fp_excp_el) {
a767fac8 6894 gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
4be42f40 6895 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
638808ff
RH
6896 return 0;
6897 }
6898 if (!s->vfp_enabled) {
6899 return 1;
6900 }
6901
6902 opr_sz = (1 + q) * 8;
26c470a7 6903 if (fn_gvec_ptr) {
87732318
RH
6904 TCGv_ptr ptr;
6905 if (ptr_is_env) {
6906 ptr = cpu_env;
6907 } else {
6908 ptr = get_fpstatus_ptr(1);
6909 }
6910 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
26c470a7 6911 opr_sz, opr_sz, data, fn_gvec_ptr);
87732318
RH
6912 if (!ptr_is_env) {
6913 tcg_temp_free_ptr(ptr);
6914 }
26c470a7 6915 } else {
87732318 6916 tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
26c470a7
RH
6917 opr_sz, opr_sz, data, fn_gvec);
6918 }
638808ff
RH
6919 return 0;
6920}
6921
7dcc1f89 6922static int disas_coproc_insn(DisasContext *s, uint32_t insn)
9ee6e8bb 6923{
4b6a83fb
PM
6924 int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
6925 const ARMCPRegInfo *ri;
9ee6e8bb
PB
6926
6927 cpnum = (insn >> 8) & 0xf;
c0f4af17
PM
6928
6929 /* First check for coprocessor space used for XScale/iwMMXt insns */
d614a513 6930 if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cpnum < 2)) {
c0f4af17
PM
6931 if (extract32(s->c15_cpar, cpnum, 1) == 0) {
6932 return 1;
6933 }
d614a513 6934 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
7dcc1f89 6935 return disas_iwmmxt_insn(s, insn);
d614a513 6936 } else if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
7dcc1f89 6937 return disas_dsp_insn(s, insn);
c0f4af17
PM
6938 }
6939 return 1;
4b6a83fb
PM
6940 }
6941
6942 /* Otherwise treat as a generic register access */
6943 is64 = (insn & (1 << 25)) == 0;
6944 if (!is64 && ((insn & (1 << 4)) == 0)) {
6945 /* cdp */
6946 return 1;
6947 }
6948
6949 crm = insn & 0xf;
6950 if (is64) {
6951 crn = 0;
6952 opc1 = (insn >> 4) & 0xf;
6953 opc2 = 0;
6954 rt2 = (insn >> 16) & 0xf;
6955 } else {
6956 crn = (insn >> 16) & 0xf;
6957 opc1 = (insn >> 21) & 7;
6958 opc2 = (insn >> 5) & 7;
6959 rt2 = 0;
6960 }
6961 isread = (insn >> 20) & 1;
6962 rt = (insn >> 12) & 0xf;
6963
60322b39 6964 ri = get_arm_cp_reginfo(s->cp_regs,
51a79b03 6965 ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
4b6a83fb
PM
6966 if (ri) {
6967 /* Check access permissions */
dcbff19b 6968 if (!cp_access_ok(s->current_el, ri, isread)) {
4b6a83fb
PM
6969 return 1;
6970 }
6971
c0f4af17 6972 if (ri->accessfn ||
d614a513 6973 (arm_dc_feature(s, ARM_FEATURE_XSCALE) && cpnum < 14)) {
f59df3f2
PM
6974 /* Emit code to perform further access permissions checks at
6975 * runtime; this may result in an exception.
c0f4af17
PM
6976 * Note that on XScale all cp0..c13 registers do an access check
6977 * call in order to handle c15_cpar.
f59df3f2
PM
6978 */
6979 TCGv_ptr tmpptr;
3f208fd7 6980 TCGv_i32 tcg_syn, tcg_isread;
8bcbf37c
PM
6981 uint32_t syndrome;
6982
6983 /* Note that since we are an implementation which takes an
6984 * exception on a trapped conditional instruction only if the
6985 * instruction passes its condition code check, we can take
6986 * advantage of the clause in the ARM ARM that allows us to set
6987 * the COND field in the instruction to 0xE in all cases.
6988 * We could fish the actual condition out of the insn (ARM)
6989 * or the condexec bits (Thumb) but it isn't necessary.
6990 */
6991 switch (cpnum) {
6992 case 14:
6993 if (is64) {
6994 syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
4df32259 6995 isread, false);
8bcbf37c
PM
6996 } else {
6997 syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
4df32259 6998 rt, isread, false);
8bcbf37c
PM
6999 }
7000 break;
7001 case 15:
7002 if (is64) {
7003 syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
4df32259 7004 isread, false);
8bcbf37c
PM
7005 } else {
7006 syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
4df32259 7007 rt, isread, false);
8bcbf37c
PM
7008 }
7009 break;
7010 default:
7011 /* ARMv8 defines that only coprocessors 14 and 15 exist,
7012 * so this can only happen if this is an ARMv7 or earlier CPU,
7013 * in which case the syndrome information won't actually be
7014 * guest visible.
7015 */
d614a513 7016 assert(!arm_dc_feature(s, ARM_FEATURE_V8));
8bcbf37c
PM
7017 syndrome = syn_uncategorized();
7018 break;
7019 }
7020
43bfa4a1 7021 gen_set_condexec(s);
43722a6d 7022 gen_set_pc_im(s, s->pc_curr);
f59df3f2 7023 tmpptr = tcg_const_ptr(ri);
8bcbf37c 7024 tcg_syn = tcg_const_i32(syndrome);
3f208fd7
PM
7025 tcg_isread = tcg_const_i32(isread);
7026 gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn,
7027 tcg_isread);
f59df3f2 7028 tcg_temp_free_ptr(tmpptr);
8bcbf37c 7029 tcg_temp_free_i32(tcg_syn);
3f208fd7 7030 tcg_temp_free_i32(tcg_isread);
37ff584c
PM
7031 } else if (ri->type & ARM_CP_RAISES_EXC) {
7032 /*
7033 * The readfn or writefn might raise an exception;
7034 * synchronize the CPU state in case it does.
7035 */
7036 gen_set_condexec(s);
7037 gen_set_pc_im(s, s->pc_curr);
f59df3f2
PM
7038 }
7039
4b6a83fb
PM
7040 /* Handle special cases first */
7041 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
7042 case ARM_CP_NOP:
7043 return 0;
7044 case ARM_CP_WFI:
7045 if (isread) {
7046 return 1;
7047 }
a0415916 7048 gen_set_pc_im(s, s->base.pc_next);
dcba3a8d 7049 s->base.is_jmp = DISAS_WFI;
2bee5105 7050 return 0;
4b6a83fb
PM
7051 default:
7052 break;
7053 }
7054
c5a49c63 7055 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
2452731c
PM
7056 gen_io_start();
7057 }
7058
4b6a83fb
PM
7059 if (isread) {
7060 /* Read */
7061 if (is64) {
7062 TCGv_i64 tmp64;
7063 TCGv_i32 tmp;
7064 if (ri->type & ARM_CP_CONST) {
7065 tmp64 = tcg_const_i64(ri->resetvalue);
7066 } else if (ri->readfn) {
7067 TCGv_ptr tmpptr;
4b6a83fb
PM
7068 tmp64 = tcg_temp_new_i64();
7069 tmpptr = tcg_const_ptr(ri);
7070 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
7071 tcg_temp_free_ptr(tmpptr);
7072 } else {
7073 tmp64 = tcg_temp_new_i64();
7074 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
7075 }
7076 tmp = tcg_temp_new_i32();
ecc7b3aa 7077 tcg_gen_extrl_i64_i32(tmp, tmp64);
4b6a83fb 7078 store_reg(s, rt, tmp);
ed336850 7079 tmp = tcg_temp_new_i32();
664b7e3b 7080 tcg_gen_extrh_i64_i32(tmp, tmp64);
ed336850 7081 tcg_temp_free_i64(tmp64);
4b6a83fb
PM
7082 store_reg(s, rt2, tmp);
7083 } else {
39d5492a 7084 TCGv_i32 tmp;
4b6a83fb
PM
7085 if (ri->type & ARM_CP_CONST) {
7086 tmp = tcg_const_i32(ri->resetvalue);
7087 } else if (ri->readfn) {
7088 TCGv_ptr tmpptr;
4b6a83fb
PM
7089 tmp = tcg_temp_new_i32();
7090 tmpptr = tcg_const_ptr(ri);
7091 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
7092 tcg_temp_free_ptr(tmpptr);
7093 } else {
7094 tmp = load_cpu_offset(ri->fieldoffset);
7095 }
7096 if (rt == 15) {
7097 /* Destination register of r15 for 32 bit loads sets
7098 * the condition codes from the high 4 bits of the value
7099 */
7100 gen_set_nzcv(tmp);
7101 tcg_temp_free_i32(tmp);
7102 } else {
7103 store_reg(s, rt, tmp);
7104 }
7105 }
7106 } else {
7107 /* Write */
7108 if (ri->type & ARM_CP_CONST) {
7109 /* If not forbidden by access permissions, treat as WI */
7110 return 0;
7111 }
7112
7113 if (is64) {
39d5492a 7114 TCGv_i32 tmplo, tmphi;
4b6a83fb
PM
7115 TCGv_i64 tmp64 = tcg_temp_new_i64();
7116 tmplo = load_reg(s, rt);
7117 tmphi = load_reg(s, rt2);
7118 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
7119 tcg_temp_free_i32(tmplo);
7120 tcg_temp_free_i32(tmphi);
7121 if (ri->writefn) {
7122 TCGv_ptr tmpptr = tcg_const_ptr(ri);
4b6a83fb
PM
7123 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
7124 tcg_temp_free_ptr(tmpptr);
7125 } else {
7126 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
7127 }
7128 tcg_temp_free_i64(tmp64);
7129 } else {
7130 if (ri->writefn) {
39d5492a 7131 TCGv_i32 tmp;
4b6a83fb 7132 TCGv_ptr tmpptr;
4b6a83fb
PM
7133 tmp = load_reg(s, rt);
7134 tmpptr = tcg_const_ptr(ri);
7135 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
7136 tcg_temp_free_ptr(tmpptr);
7137 tcg_temp_free_i32(tmp);
7138 } else {
39d5492a 7139 TCGv_i32 tmp = load_reg(s, rt);
4b6a83fb
PM
7140 store_cpu_offset(tmp, ri->fieldoffset);
7141 }
7142 }
2452731c
PM
7143 }
7144
c5a49c63 7145 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
2452731c 7146 /* I/O operations must end the TB here (whether read or write) */
2452731c
PM
7147 gen_lookup_tb(s);
7148 } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
4b6a83fb
PM
7149 /* We default to ending the TB on a coprocessor register write,
7150 * but allow this to be suppressed by the register definition
7151 * (usually only necessary to work around guest bugs).
7152 */
2452731c 7153 gen_lookup_tb(s);
4b6a83fb 7154 }
2452731c 7155
4b6a83fb
PM
7156 return 0;
7157 }
7158
626187d8
PM
7159 /* Unknown register; this might be a guest error or a QEMU
7160 * unimplemented feature.
7161 */
7162 if (is64) {
7163 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
51a79b03
PM
7164 "64 bit system register cp:%d opc1: %d crm:%d "
7165 "(%s)\n",
7166 isread ? "read" : "write", cpnum, opc1, crm,
7167 s->ns ? "non-secure" : "secure");
626187d8
PM
7168 } else {
7169 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
51a79b03
PM
7170 "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d "
7171 "(%s)\n",
7172 isread ? "read" : "write", cpnum, opc1, crn, crm, opc2,
7173 s->ns ? "non-secure" : "secure");
626187d8
PM
7174 }
7175
4a9a539f 7176 return 1;
9ee6e8bb
PB
7177}
7178
5e3f878a
PB
7179
7180/* Store a 64-bit value to a register pair. Clobbers val. */
a7812ae4 7181static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5e3f878a 7182{
39d5492a 7183 TCGv_i32 tmp;
7d1b0095 7184 tmp = tcg_temp_new_i32();
ecc7b3aa 7185 tcg_gen_extrl_i64_i32(tmp, val);
5e3f878a 7186 store_reg(s, rlow, tmp);
7d1b0095 7187 tmp = tcg_temp_new_i32();
664b7e3b 7188 tcg_gen_extrh_i64_i32(tmp, val);
5e3f878a
PB
7189 store_reg(s, rhigh, tmp);
7190}
7191
5e3f878a 7192/* load and add a 64-bit value from a register pair. */
a7812ae4 7193static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5e3f878a 7194{
a7812ae4 7195 TCGv_i64 tmp;
39d5492a
PM
7196 TCGv_i32 tmpl;
7197 TCGv_i32 tmph;
5e3f878a
PB
7198
7199 /* Load 64-bit value rd:rn. */
36aa55dc
PB
7200 tmpl = load_reg(s, rlow);
7201 tmph = load_reg(s, rhigh);
a7812ae4 7202 tmp = tcg_temp_new_i64();
36aa55dc 7203 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
7d1b0095
PM
7204 tcg_temp_free_i32(tmpl);
7205 tcg_temp_free_i32(tmph);
5e3f878a 7206 tcg_gen_add_i64(val, val, tmp);
b75263d6 7207 tcg_temp_free_i64(tmp);
5e3f878a
PB
7208}
7209
c9f10124 7210/* Set N and Z flags from hi|lo. */
39d5492a 7211static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
5e3f878a 7212{
c9f10124
RH
7213 tcg_gen_mov_i32(cpu_NF, hi);
7214 tcg_gen_or_i32(cpu_ZF, lo, hi);
5e3f878a
PB
7215}
7216
426f5abc
PB
7217/* Load/Store exclusive instructions are implemented by remembering
7218 the value/address loaded, and seeing if these are the same
354161b3 7219 when the store is performed. This should be sufficient to implement
426f5abc 7220 the architecturally mandated semantics, and avoids having to monitor
354161b3
EC
7221 regular stores. The compare vs the remembered value is done during
7222 the cmpxchg operation, but we must compare the addresses manually. */
426f5abc 7223static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
39d5492a 7224 TCGv_i32 addr, int size)
426f5abc 7225{
94ee24e7 7226 TCGv_i32 tmp = tcg_temp_new_i32();
14776ab5 7227 MemOp opc = size | MO_ALIGN | s->be_data;
426f5abc 7228
50225ad0
PM
7229 s->is_ldex = true;
7230
426f5abc 7231 if (size == 3) {
39d5492a 7232 TCGv_i32 tmp2 = tcg_temp_new_i32();
354161b3 7233 TCGv_i64 t64 = tcg_temp_new_i64();
03d05e2d 7234
3448d47b
PM
7235 /* For AArch32, architecturally the 32-bit word at the lowest
7236 * address is always Rt and the one at addr+4 is Rt2, even if
7237 * the CPU is big-endian. That means we don't want to do a
7238 * gen_aa32_ld_i64(), which invokes gen_aa32_frob64() as if
7239 * for an architecturally 64-bit access, but instead do a
7240 * 64-bit access using MO_BE if appropriate and then split
7241 * the two halves.
7242 * This only makes a difference for BE32 user-mode, where
7243 * frob64() must not flip the two halves of the 64-bit data
7244 * but this code must treat BE32 user-mode like BE32 system.
7245 */
7246 TCGv taddr = gen_aa32_addr(s, addr, opc);
7247
7248 tcg_gen_qemu_ld_i64(t64, taddr, get_mem_index(s), opc);
7249 tcg_temp_free(taddr);
354161b3 7250 tcg_gen_mov_i64(cpu_exclusive_val, t64);
3448d47b
PM
7251 if (s->be_data == MO_BE) {
7252 tcg_gen_extr_i64_i32(tmp2, tmp, t64);
7253 } else {
7254 tcg_gen_extr_i64_i32(tmp, tmp2, t64);
7255 }
354161b3
EC
7256 tcg_temp_free_i64(t64);
7257
7258 store_reg(s, rt2, tmp2);
03d05e2d 7259 } else {
354161b3 7260 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), opc);
03d05e2d 7261 tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
426f5abc 7262 }
03d05e2d
PM
7263
7264 store_reg(s, rt, tmp);
7265 tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
426f5abc
PB
7266}
7267
7268static void gen_clrex(DisasContext *s)
7269{
03d05e2d 7270 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
426f5abc
PB
7271}
7272
426f5abc 7273static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
39d5492a 7274 TCGv_i32 addr, int size)
426f5abc 7275{
354161b3
EC
7276 TCGv_i32 t0, t1, t2;
7277 TCGv_i64 extaddr;
7278 TCGv taddr;
42a268c2
RH
7279 TCGLabel *done_label;
7280 TCGLabel *fail_label;
14776ab5 7281 MemOp opc = size | MO_ALIGN | s->be_data;
426f5abc
PB
7282
7283 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
7284 [addr] = {Rt};
7285 {Rd} = 0;
7286 } else {
7287 {Rd} = 1;
7288 } */
7289 fail_label = gen_new_label();
7290 done_label = gen_new_label();
03d05e2d
PM
7291 extaddr = tcg_temp_new_i64();
7292 tcg_gen_extu_i32_i64(extaddr, addr);
7293 tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
7294 tcg_temp_free_i64(extaddr);
7295
354161b3
EC
7296 taddr = gen_aa32_addr(s, addr, opc);
7297 t0 = tcg_temp_new_i32();
7298 t1 = load_reg(s, rt);
426f5abc 7299 if (size == 3) {
354161b3
EC
7300 TCGv_i64 o64 = tcg_temp_new_i64();
7301 TCGv_i64 n64 = tcg_temp_new_i64();
03d05e2d 7302
354161b3 7303 t2 = load_reg(s, rt2);
3448d47b
PM
7304 /* For AArch32, architecturally the 32-bit word at the lowest
7305 * address is always Rt and the one at addr+4 is Rt2, even if
7306 * the CPU is big-endian. Since we're going to treat this as a
7307 * single 64-bit BE store, we need to put the two halves in the
7308 * opposite order for BE to LE, so that they end up in the right
7309 * places.
7310 * We don't want gen_aa32_frob64() because that does the wrong
7311 * thing for BE32 usermode.
7312 */
7313 if (s->be_data == MO_BE) {
7314 tcg_gen_concat_i32_i64(n64, t2, t1);
7315 } else {
7316 tcg_gen_concat_i32_i64(n64, t1, t2);
7317 }
354161b3 7318 tcg_temp_free_i32(t2);
03d05e2d 7319
354161b3
EC
7320 tcg_gen_atomic_cmpxchg_i64(o64, taddr, cpu_exclusive_val, n64,
7321 get_mem_index(s), opc);
7322 tcg_temp_free_i64(n64);
7323
354161b3
EC
7324 tcg_gen_setcond_i64(TCG_COND_NE, o64, o64, cpu_exclusive_val);
7325 tcg_gen_extrl_i64_i32(t0, o64);
7326
7327 tcg_temp_free_i64(o64);
7328 } else {
7329 t2 = tcg_temp_new_i32();
7330 tcg_gen_extrl_i64_i32(t2, cpu_exclusive_val);
7331 tcg_gen_atomic_cmpxchg_i32(t0, taddr, t2, t1, get_mem_index(s), opc);
7332 tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t2);
7333 tcg_temp_free_i32(t2);
426f5abc 7334 }
354161b3
EC
7335 tcg_temp_free_i32(t1);
7336 tcg_temp_free(taddr);
7337 tcg_gen_mov_i32(cpu_R[rd], t0);
7338 tcg_temp_free_i32(t0);
426f5abc 7339 tcg_gen_br(done_label);
354161b3 7340
426f5abc
PB
7341 gen_set_label(fail_label);
7342 tcg_gen_movi_i32(cpu_R[rd], 1);
7343 gen_set_label(done_label);
03d05e2d 7344 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
426f5abc 7345}
426f5abc 7346
81465888
PM
7347/* gen_srs:
7348 * @env: CPUARMState
7349 * @s: DisasContext
7350 * @mode: mode field from insn (which stack to store to)
7351 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
7352 * @writeback: true if writeback bit set
7353 *
7354 * Generate code for the SRS (Store Return State) insn.
7355 */
7356static void gen_srs(DisasContext *s,
7357 uint32_t mode, uint32_t amode, bool writeback)
7358{
7359 int32_t offset;
cbc0326b
PM
7360 TCGv_i32 addr, tmp;
7361 bool undef = false;
7362
7363 /* SRS is:
7364 * - trapped to EL3 if EL3 is AArch64 and we are at Secure EL1
ba63cf47 7365 * and specified mode is monitor mode
cbc0326b
PM
7366 * - UNDEFINED in Hyp mode
7367 * - UNPREDICTABLE in User or System mode
7368 * - UNPREDICTABLE if the specified mode is:
7369 * -- not implemented
7370 * -- not a valid mode number
7371 * -- a mode that's at a higher exception level
7372 * -- Monitor, if we are Non-secure
f01377f5 7373 * For the UNPREDICTABLE cases we choose to UNDEF.
cbc0326b 7374 */
ba63cf47 7375 if (s->current_el == 1 && !s->ns && mode == ARM_CPU_MODE_MON) {
a767fac8 7376 gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(), 3);
cbc0326b
PM
7377 return;
7378 }
7379
7380 if (s->current_el == 0 || s->current_el == 2) {
7381 undef = true;
7382 }
7383
7384 switch (mode) {
7385 case ARM_CPU_MODE_USR:
7386 case ARM_CPU_MODE_FIQ:
7387 case ARM_CPU_MODE_IRQ:
7388 case ARM_CPU_MODE_SVC:
7389 case ARM_CPU_MODE_ABT:
7390 case ARM_CPU_MODE_UND:
7391 case ARM_CPU_MODE_SYS:
7392 break;
7393 case ARM_CPU_MODE_HYP:
7394 if (s->current_el == 1 || !arm_dc_feature(s, ARM_FEATURE_EL2)) {
7395 undef = true;
7396 }
7397 break;
7398 case ARM_CPU_MODE_MON:
7399 /* No need to check specifically for "are we non-secure" because
7400 * we've already made EL0 UNDEF and handled the trap for S-EL1;
7401 * so if this isn't EL3 then we must be non-secure.
7402 */
7403 if (s->current_el != 3) {
7404 undef = true;
7405 }
7406 break;
7407 default:
7408 undef = true;
7409 }
7410
7411 if (undef) {
1ce21ba1 7412 unallocated_encoding(s);
cbc0326b
PM
7413 return;
7414 }
7415
7416 addr = tcg_temp_new_i32();
7417 tmp = tcg_const_i32(mode);
f01377f5
PM
7418 /* get_r13_banked() will raise an exception if called from System mode */
7419 gen_set_condexec(s);
43722a6d 7420 gen_set_pc_im(s, s->pc_curr);
81465888
PM
7421 gen_helper_get_r13_banked(addr, cpu_env, tmp);
7422 tcg_temp_free_i32(tmp);
7423 switch (amode) {
7424 case 0: /* DA */
7425 offset = -4;
7426 break;
7427 case 1: /* IA */
7428 offset = 0;
7429 break;
7430 case 2: /* DB */
7431 offset = -8;
7432 break;
7433 case 3: /* IB */
7434 offset = 4;
7435 break;
7436 default:
7437 abort();
7438 }
7439 tcg_gen_addi_i32(addr, addr, offset);
7440 tmp = load_reg(s, 14);
12dcc321 7441 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 7442 tcg_temp_free_i32(tmp);
81465888
PM
7443 tmp = load_cpu_field(spsr);
7444 tcg_gen_addi_i32(addr, addr, 4);
12dcc321 7445 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
5a839c0d 7446 tcg_temp_free_i32(tmp);
81465888
PM
7447 if (writeback) {
7448 switch (amode) {
7449 case 0:
7450 offset = -8;
7451 break;
7452 case 1:
7453 offset = 4;
7454 break;
7455 case 2:
7456 offset = -4;
7457 break;
7458 case 3:
7459 offset = 0;
7460 break;
7461 default:
7462 abort();
7463 }
7464 tcg_gen_addi_i32(addr, addr, offset);
7465 tmp = tcg_const_i32(mode);
7466 gen_helper_set_r13_banked(cpu_env, tmp, addr);
7467 tcg_temp_free_i32(tmp);
7468 }
7469 tcg_temp_free_i32(addr);
dcba3a8d 7470 s->base.is_jmp = DISAS_UPDATE;
81465888
PM
7471}
7472
c2d9644e
RK
7473/* Generate a label used for skipping this instruction */
7474static void arm_gen_condlabel(DisasContext *s)
7475{
7476 if (!s->condjmp) {
7477 s->condlabel = gen_new_label();
7478 s->condjmp = 1;
7479 }
7480}
7481
7482/* Skip this instruction if the ARM condition is false */
7483static void arm_skip_unless(DisasContext *s, uint32_t cond)
7484{
7485 arm_gen_condlabel(s);
7486 arm_gen_test_cc(cond ^ 1, s->condlabel);
7487}
7488
581c6ebd
RH
7489
7490/*
7491 * Constant expanders for the decoders.
7492 */
7493
145952e8
RH
7494static int negate(DisasContext *s, int x)
7495{
7496 return -x;
7497}
7498
581c6ebd
RH
7499static int times_2(DisasContext *s, int x)
7500{
7501 return x * 2;
7502}
7503
5e291fe1
RH
7504static int times_4(DisasContext *s, int x)
7505{
7506 return x * 4;
7507}
7508
581c6ebd
RH
7509/* Return only the rotation part of T32ExpandImm. */
7510static int t32_expandimm_rot(DisasContext *s, int x)
7511{
7512 return x & 0xc00 ? extract32(x, 7, 5) : 0;
7513}
7514
7515/* Return the unrotated immediate from T32ExpandImm. */
7516static int t32_expandimm_imm(DisasContext *s, int x)
7517{
7518 int imm = extract32(x, 0, 8);
7519
7520 switch (extract32(x, 8, 4)) {
7521 case 0: /* XY */
7522 /* Nothing to do. */
7523 break;
7524 case 1: /* 00XY00XY */
7525 imm *= 0x00010001;
7526 break;
7527 case 2: /* XY00XY00 */
7528 imm *= 0x01000100;
7529 break;
7530 case 3: /* XYXYXYXY */
7531 imm *= 0x01010101;
7532 break;
7533 default:
7534 /* Rotated constant. */
7535 imm |= 0x80;
7536 break;
7537 }
7538 return imm;
7539}
7540
360144f3
RH
7541static int t32_branch24(DisasContext *s, int x)
7542{
7543 /* Convert J1:J2 at x[22:21] to I2:I1, which involves I=J^~S. */
7544 x ^= !(x < 0) * (3 << 21);
7545 /* Append the final zero. */
7546 return x << 1;
7547}
7548
080c4ead
RH
7549static int t16_setflags(DisasContext *s)
7550{
7551 return s->condexec_mask == 0;
7552}
7553
51409b9e
RH
7554/*
7555 * Include the generated decoders.
7556 */
7557
7558#include "decode-a32.inc.c"
7559#include "decode-a32-uncond.inc.c"
7560#include "decode-t32.inc.c"
f97b454e 7561#include "decode-t16.inc.c"
51409b9e 7562
25ae32c5
RH
7563/* Helpers to swap operands for reverse-subtract. */
7564static void gen_rsb(TCGv_i32 dst, TCGv_i32 a, TCGv_i32 b)
7565{
7566 tcg_gen_sub_i32(dst, b, a);
7567}
7568
7569static void gen_rsb_CC(TCGv_i32 dst, TCGv_i32 a, TCGv_i32 b)
7570{
7571 gen_sub_CC(dst, b, a);
7572}
7573
7574static void gen_rsc(TCGv_i32 dest, TCGv_i32 a, TCGv_i32 b)
7575{
7576 gen_sub_carry(dest, b, a);
7577}
7578
7579static void gen_rsc_CC(TCGv_i32 dest, TCGv_i32 a, TCGv_i32 b)
7580{
7581 gen_sbc_CC(dest, b, a);
7582}
7583
7584/*
7585 * Helpers for the data processing routines.
7586 *
7587 * After the computation store the results back.
7588 * This may be suppressed altogether (STREG_NONE), require a runtime
7589 * check against the stack limits (STREG_SP_CHECK), or generate an
7590 * exception return. Oh, or store into a register.
7591 *
7592 * Always return true, indicating success for a trans_* function.
7593 */
7594typedef enum {
7595 STREG_NONE,
7596 STREG_NORMAL,
7597 STREG_SP_CHECK,
7598 STREG_EXC_RET,
7599} StoreRegKind;
7600
7601static bool store_reg_kind(DisasContext *s, int rd,
7602 TCGv_i32 val, StoreRegKind kind)
7603{
7604 switch (kind) {
7605 case STREG_NONE:
7606 tcg_temp_free_i32(val);
7607 return true;
7608 case STREG_NORMAL:
7609 /* See ALUWritePC: Interworking only from a32 mode. */
7610 if (s->thumb) {
7611 store_reg(s, rd, val);
7612 } else {
7613 store_reg_bx(s, rd, val);
7614 }
7615 return true;
7616 case STREG_SP_CHECK:
7617 store_sp_checked(s, val);
7618 return true;
7619 case STREG_EXC_RET:
7620 gen_exception_return(s, val);
7621 return true;
7622 }
7623 g_assert_not_reached();
7624}
7625
7626/*
7627 * Data Processing (register)
7628 *
7629 * Operate, with set flags, one register source,
7630 * one immediate shifted register source, and a destination.
7631 */
7632static bool op_s_rrr_shi(DisasContext *s, arg_s_rrr_shi *a,
7633 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32),
7634 int logic_cc, StoreRegKind kind)
7635{
7636 TCGv_i32 tmp1, tmp2;
7637
7638 tmp2 = load_reg(s, a->rm);
7639 gen_arm_shift_im(tmp2, a->shty, a->shim, logic_cc);
7640 tmp1 = load_reg(s, a->rn);
7641
7642 gen(tmp1, tmp1, tmp2);
7643 tcg_temp_free_i32(tmp2);
7644
7645 if (logic_cc) {
7646 gen_logic_CC(tmp1);
7647 }
7648 return store_reg_kind(s, a->rd, tmp1, kind);
7649}
7650
7651static bool op_s_rxr_shi(DisasContext *s, arg_s_rrr_shi *a,
7652 void (*gen)(TCGv_i32, TCGv_i32),
7653 int logic_cc, StoreRegKind kind)
7654{
7655 TCGv_i32 tmp;
7656
7657 tmp = load_reg(s, a->rm);
7658 gen_arm_shift_im(tmp, a->shty, a->shim, logic_cc);
7659
7660 gen(tmp, tmp);
7661 if (logic_cc) {
7662 gen_logic_CC(tmp);
7663 }
7664 return store_reg_kind(s, a->rd, tmp, kind);
7665}
7666
5be2c123
RH
7667/*
7668 * Data-processing (register-shifted register)
7669 *
7670 * Operate, with set flags, one register source,
7671 * one register shifted register source, and a destination.
7672 */
7673static bool op_s_rrr_shr(DisasContext *s, arg_s_rrr_shr *a,
7674 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32),
7675 int logic_cc, StoreRegKind kind)
7676{
7677 TCGv_i32 tmp1, tmp2;
7678
7679 tmp1 = load_reg(s, a->rs);
7680 tmp2 = load_reg(s, a->rm);
7681 gen_arm_shift_reg(tmp2, a->shty, tmp1, logic_cc);
7682 tmp1 = load_reg(s, a->rn);
7683
7684 gen(tmp1, tmp1, tmp2);
7685 tcg_temp_free_i32(tmp2);
7686
7687 if (logic_cc) {
7688 gen_logic_CC(tmp1);
7689 }
7690 return store_reg_kind(s, a->rd, tmp1, kind);
7691}
7692
7693static bool op_s_rxr_shr(DisasContext *s, arg_s_rrr_shr *a,
7694 void (*gen)(TCGv_i32, TCGv_i32),
7695 int logic_cc, StoreRegKind kind)
7696{
7697 TCGv_i32 tmp1, tmp2;
7698
7699 tmp1 = load_reg(s, a->rs);
7700 tmp2 = load_reg(s, a->rm);
7701 gen_arm_shift_reg(tmp2, a->shty, tmp1, logic_cc);
7702
7703 gen(tmp2, tmp2);
7704 if (logic_cc) {
7705 gen_logic_CC(tmp2);
7706 }
7707 return store_reg_kind(s, a->rd, tmp2, kind);
7708}
7709
581c6ebd
RH
7710/*
7711 * Data-processing (immediate)
7712 *
7713 * Operate, with set flags, one register source,
7714 * one rotated immediate, and a destination.
7715 *
7716 * Note that logic_cc && a->rot setting CF based on the msb of the
7717 * immediate is the reason why we must pass in the unrotated form
7718 * of the immediate.
7719 */
7720static bool op_s_rri_rot(DisasContext *s, arg_s_rri_rot *a,
7721 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32),
7722 int logic_cc, StoreRegKind kind)
7723{
7724 TCGv_i32 tmp1, tmp2;
7725 uint32_t imm;
7726
7727 imm = ror32(a->imm, a->rot);
7728 if (logic_cc && a->rot) {
7729 tcg_gen_movi_i32(cpu_CF, imm >> 31);
7730 }
7731 tmp2 = tcg_const_i32(imm);
7732 tmp1 = load_reg(s, a->rn);
7733
7734 gen(tmp1, tmp1, tmp2);
7735 tcg_temp_free_i32(tmp2);
7736
7737 if (logic_cc) {
7738 gen_logic_CC(tmp1);
7739 }
7740 return store_reg_kind(s, a->rd, tmp1, kind);
7741}
7742
7743static bool op_s_rxi_rot(DisasContext *s, arg_s_rri_rot *a,
7744 void (*gen)(TCGv_i32, TCGv_i32),
7745 int logic_cc, StoreRegKind kind)
7746{
7747 TCGv_i32 tmp;
7748 uint32_t imm;
7749
7750 imm = ror32(a->imm, a->rot);
7751 if (logic_cc && a->rot) {
7752 tcg_gen_movi_i32(cpu_CF, imm >> 31);
7753 }
7754 tmp = tcg_const_i32(imm);
7755
7756 gen(tmp, tmp);
7757 if (logic_cc) {
7758 gen_logic_CC(tmp);
7759 }
7760 return store_reg_kind(s, a->rd, tmp, kind);
7761}
7762
25ae32c5
RH
7763#define DO_ANY3(NAME, OP, L, K) \
7764 static bool trans_##NAME##_rrri(DisasContext *s, arg_s_rrr_shi *a) \
5be2c123
RH
7765 { StoreRegKind k = (K); return op_s_rrr_shi(s, a, OP, L, k); } \
7766 static bool trans_##NAME##_rrrr(DisasContext *s, arg_s_rrr_shr *a) \
581c6ebd
RH
7767 { StoreRegKind k = (K); return op_s_rrr_shr(s, a, OP, L, k); } \
7768 static bool trans_##NAME##_rri(DisasContext *s, arg_s_rri_rot *a) \
7769 { StoreRegKind k = (K); return op_s_rri_rot(s, a, OP, L, k); }
25ae32c5
RH
7770
7771#define DO_ANY2(NAME, OP, L, K) \
7772 static bool trans_##NAME##_rxri(DisasContext *s, arg_s_rrr_shi *a) \
5be2c123
RH
7773 { StoreRegKind k = (K); return op_s_rxr_shi(s, a, OP, L, k); } \
7774 static bool trans_##NAME##_rxrr(DisasContext *s, arg_s_rrr_shr *a) \
581c6ebd
RH
7775 { StoreRegKind k = (K); return op_s_rxr_shr(s, a, OP, L, k); } \
7776 static bool trans_##NAME##_rxi(DisasContext *s, arg_s_rri_rot *a) \
7777 { StoreRegKind k = (K); return op_s_rxi_rot(s, a, OP, L, k); }
25ae32c5
RH
7778
7779#define DO_CMP2(NAME, OP, L) \
7780 static bool trans_##NAME##_xrri(DisasContext *s, arg_s_rrr_shi *a) \
5be2c123
RH
7781 { return op_s_rrr_shi(s, a, OP, L, STREG_NONE); } \
7782 static bool trans_##NAME##_xrrr(DisasContext *s, arg_s_rrr_shr *a) \
581c6ebd
RH
7783 { return op_s_rrr_shr(s, a, OP, L, STREG_NONE); } \
7784 static bool trans_##NAME##_xri(DisasContext *s, arg_s_rri_rot *a) \
7785 { return op_s_rri_rot(s, a, OP, L, STREG_NONE); }
25ae32c5
RH
7786
7787DO_ANY3(AND, tcg_gen_and_i32, a->s, STREG_NORMAL)
7788DO_ANY3(EOR, tcg_gen_xor_i32, a->s, STREG_NORMAL)
7789DO_ANY3(ORR, tcg_gen_or_i32, a->s, STREG_NORMAL)
7790DO_ANY3(BIC, tcg_gen_andc_i32, a->s, STREG_NORMAL)
7791
7792DO_ANY3(RSB, a->s ? gen_rsb_CC : gen_rsb, false, STREG_NORMAL)
7793DO_ANY3(ADC, a->s ? gen_adc_CC : gen_add_carry, false, STREG_NORMAL)
7794DO_ANY3(SBC, a->s ? gen_sbc_CC : gen_sub_carry, false, STREG_NORMAL)
7795DO_ANY3(RSC, a->s ? gen_rsc_CC : gen_rsc, false, STREG_NORMAL)
7796
7797DO_CMP2(TST, tcg_gen_and_i32, true)
7798DO_CMP2(TEQ, tcg_gen_xor_i32, true)
7799DO_CMP2(CMN, gen_add_CC, false)
7800DO_CMP2(CMP, gen_sub_CC, false)
7801
7802DO_ANY3(ADD, a->s ? gen_add_CC : tcg_gen_add_i32, false,
7803 a->rd == 13 && a->rn == 13 ? STREG_SP_CHECK : STREG_NORMAL)
7804
7805/*
7806 * Note for the computation of StoreRegKind we return out of the
7807 * middle of the functions that are expanded by DO_ANY3, and that
7808 * we modify a->s via that parameter before it is used by OP.
7809 */
7810DO_ANY3(SUB, a->s ? gen_sub_CC : tcg_gen_sub_i32, false,
7811 ({
7812 StoreRegKind ret = STREG_NORMAL;
7813 if (a->rd == 15 && a->s) {
7814 /*
7815 * See ALUExceptionReturn:
7816 * In User mode, UNPREDICTABLE; we choose UNDEF.
7817 * In Hyp mode, UNDEFINED.
7818 */
7819 if (IS_USER(s) || s->current_el == 2) {
7820 unallocated_encoding(s);
7821 return true;
7822 }
7823 /* There is no writeback of nzcv to PSTATE. */
7824 a->s = 0;
7825 ret = STREG_EXC_RET;
7826 } else if (a->rd == 13 && a->rn == 13) {
7827 ret = STREG_SP_CHECK;
7828 }
7829 ret;
7830 }))
7831
7832DO_ANY2(MOV, tcg_gen_mov_i32, a->s,
7833 ({
7834 StoreRegKind ret = STREG_NORMAL;
7835 if (a->rd == 15 && a->s) {
7836 /*
7837 * See ALUExceptionReturn:
7838 * In User mode, UNPREDICTABLE; we choose UNDEF.
7839 * In Hyp mode, UNDEFINED.
7840 */
7841 if (IS_USER(s) || s->current_el == 2) {
7842 unallocated_encoding(s);
7843 return true;
7844 }
7845 /* There is no writeback of nzcv to PSTATE. */
7846 a->s = 0;
7847 ret = STREG_EXC_RET;
7848 } else if (a->rd == 13) {
7849 ret = STREG_SP_CHECK;
7850 }
7851 ret;
7852 }))
7853
7854DO_ANY2(MVN, tcg_gen_not_i32, a->s, STREG_NORMAL)
7855
7856/*
7857 * ORN is only available with T32, so there is no register-shifted-register
7858 * form of the insn. Using the DO_ANY3 macro would create an unused function.
7859 */
7860static bool trans_ORN_rrri(DisasContext *s, arg_s_rrr_shi *a)
7861{
7862 return op_s_rrr_shi(s, a, tcg_gen_orc_i32, a->s, STREG_NORMAL);
7863}
7864
581c6ebd
RH
7865static bool trans_ORN_rri(DisasContext *s, arg_s_rri_rot *a)
7866{
7867 return op_s_rri_rot(s, a, tcg_gen_orc_i32, a->s, STREG_NORMAL);
7868}
7869
25ae32c5
RH
7870#undef DO_ANY3
7871#undef DO_ANY2
7872#undef DO_CMP2
7873
145952e8
RH
7874static bool trans_ADR(DisasContext *s, arg_ri *a)
7875{
7876 store_reg_bx(s, a->rd, add_reg_for_lit(s, 15, a->imm));
7877 return true;
7878}
7879
8f445127
RH
7880static bool trans_MOVW(DisasContext *s, arg_MOVW *a)
7881{
7882 TCGv_i32 tmp;
7883
7884 if (!ENABLE_ARCH_6T2) {
7885 return false;
7886 }
7887
7888 tmp = tcg_const_i32(a->imm);
7889 store_reg(s, a->rd, tmp);
7890 return true;
7891}
7892
7893static bool trans_MOVT(DisasContext *s, arg_MOVW *a)
7894{
7895 TCGv_i32 tmp;
7896
7897 if (!ENABLE_ARCH_6T2) {
7898 return false;
7899 }
7900
7901 tmp = load_reg(s, a->rd);
7902 tcg_gen_ext16u_i32(tmp, tmp);
7903 tcg_gen_ori_i32(tmp, tmp, a->imm << 16);
7904 store_reg(s, a->rd, tmp);
7905 return true;
7906}
7907
bd92fe35
RH
7908/*
7909 * Multiply and multiply accumulate
7910 */
7911
7912static bool op_mla(DisasContext *s, arg_s_rrrr *a, bool add)
7913{
7914 TCGv_i32 t1, t2;
7915
7916 t1 = load_reg(s, a->rn);
7917 t2 = load_reg(s, a->rm);
7918 tcg_gen_mul_i32(t1, t1, t2);
7919 tcg_temp_free_i32(t2);
7920 if (add) {
7921 t2 = load_reg(s, a->ra);
7922 tcg_gen_add_i32(t1, t1, t2);
7923 tcg_temp_free_i32(t2);
7924 }
7925 if (a->s) {
7926 gen_logic_CC(t1);
7927 }
7928 store_reg(s, a->rd, t1);
7929 return true;
7930}
7931
7932static bool trans_MUL(DisasContext *s, arg_MUL *a)
7933{
7934 return op_mla(s, a, false);
7935}
7936
7937static bool trans_MLA(DisasContext *s, arg_MLA *a)
7938{
7939 return op_mla(s, a, true);
7940}
7941
7942static bool trans_MLS(DisasContext *s, arg_MLS *a)
7943{
7944 TCGv_i32 t1, t2;
7945
7946 if (!ENABLE_ARCH_6T2) {
7947 return false;
7948 }
7949 t1 = load_reg(s, a->rn);
7950 t2 = load_reg(s, a->rm);
7951 tcg_gen_mul_i32(t1, t1, t2);
7952 tcg_temp_free_i32(t2);
7953 t2 = load_reg(s, a->ra);
7954 tcg_gen_sub_i32(t1, t2, t1);
7955 tcg_temp_free_i32(t2);
7956 store_reg(s, a->rd, t1);
7957 return true;
7958}
7959
7960static bool op_mlal(DisasContext *s, arg_s_rrrr *a, bool uns, bool add)
7961{
7962 TCGv_i32 t0, t1, t2, t3;
7963
7964 t0 = load_reg(s, a->rm);
7965 t1 = load_reg(s, a->rn);
7966 if (uns) {
7967 tcg_gen_mulu2_i32(t0, t1, t0, t1);
7968 } else {
7969 tcg_gen_muls2_i32(t0, t1, t0, t1);
7970 }
7971 if (add) {
7972 t2 = load_reg(s, a->ra);
7973 t3 = load_reg(s, a->rd);
7974 tcg_gen_add2_i32(t0, t1, t0, t1, t2, t3);
7975 tcg_temp_free_i32(t2);
7976 tcg_temp_free_i32(t3);
7977 }
7978 if (a->s) {
7979 gen_logicq_cc(t0, t1);
7980 }
7981 store_reg(s, a->ra, t0);
7982 store_reg(s, a->rd, t1);
7983 return true;
7984}
7985
7986static bool trans_UMULL(DisasContext *s, arg_UMULL *a)
7987{
7988 return op_mlal(s, a, true, false);
7989}
7990
7991static bool trans_SMULL(DisasContext *s, arg_SMULL *a)
7992{
7993 return op_mlal(s, a, false, false);
7994}
7995
7996static bool trans_UMLAL(DisasContext *s, arg_UMLAL *a)
7997{
7998 return op_mlal(s, a, true, true);
7999}
8000
8001static bool trans_SMLAL(DisasContext *s, arg_SMLAL *a)
8002{
8003 return op_mlal(s, a, false, true);
8004}
8005
8006static bool trans_UMAAL(DisasContext *s, arg_UMAAL *a)
8007{
2409d564 8008 TCGv_i32 t0, t1, t2, zero;
bd92fe35
RH
8009
8010 if (s->thumb
8011 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
8012 : !ENABLE_ARCH_6) {
8013 return false;
8014 }
8015
8016 t0 = load_reg(s, a->rm);
8017 t1 = load_reg(s, a->rn);
2409d564
RH
8018 tcg_gen_mulu2_i32(t0, t1, t0, t1);
8019 zero = tcg_const_i32(0);
8020 t2 = load_reg(s, a->ra);
8021 tcg_gen_add2_i32(t0, t1, t0, t1, t2, zero);
8022 tcg_temp_free_i32(t2);
8023 t2 = load_reg(s, a->rd);
8024 tcg_gen_add2_i32(t0, t1, t0, t1, t2, zero);
8025 tcg_temp_free_i32(t2);
8026 tcg_temp_free_i32(zero);
8027 store_reg(s, a->ra, t0);
8028 store_reg(s, a->rd, t1);
bd92fe35
RH
8029 return true;
8030}
8031
6d0730a8
RH
8032/*
8033 * Saturating addition and subtraction
8034 */
8035
8036static bool op_qaddsub(DisasContext *s, arg_rrr *a, bool add, bool doub)
8037{
8038 TCGv_i32 t0, t1;
8039
8040 if (s->thumb
8041 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
8042 : !ENABLE_ARCH_5TE) {
8043 return false;
8044 }
8045
8046 t0 = load_reg(s, a->rm);
8047 t1 = load_reg(s, a->rn);
8048 if (doub) {
8049 gen_helper_add_saturate(t1, cpu_env, t1, t1);
8050 }
8051 if (add) {
8052 gen_helper_add_saturate(t0, cpu_env, t0, t1);
8053 } else {
8054 gen_helper_sub_saturate(t0, cpu_env, t0, t1);
8055 }
8056 tcg_temp_free_i32(t1);
8057 store_reg(s, a->rd, t0);
8058 return true;
8059}
8060
8061#define DO_QADDSUB(NAME, ADD, DOUB) \
8062static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
8063{ \
8064 return op_qaddsub(s, a, ADD, DOUB); \
8065}
8066
8067DO_QADDSUB(QADD, true, false)
8068DO_QADDSUB(QSUB, false, false)
8069DO_QADDSUB(QDADD, true, true)
8070DO_QADDSUB(QDSUB, false, true)
8071
8072#undef DO_QADDSUB
8073
26c6923d
RH
8074/*
8075 * Halfword multiply and multiply accumulate
8076 */
8077
8078static bool op_smlaxxx(DisasContext *s, arg_rrrr *a,
8079 int add_long, bool nt, bool mt)
8080{
ea96b374 8081 TCGv_i32 t0, t1, tl, th;
26c6923d
RH
8082
8083 if (s->thumb
8084 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
8085 : !ENABLE_ARCH_5TE) {
8086 return false;
8087 }
8088
8089 t0 = load_reg(s, a->rn);
8090 t1 = load_reg(s, a->rm);
8091 gen_mulxy(t0, t1, nt, mt);
8092 tcg_temp_free_i32(t1);
8093
8094 switch (add_long) {
8095 case 0:
8096 store_reg(s, a->rd, t0);
8097 break;
8098 case 1:
8099 t1 = load_reg(s, a->ra);
8100 gen_helper_add_setq(t0, cpu_env, t0, t1);
8101 tcg_temp_free_i32(t1);
8102 store_reg(s, a->rd, t0);
8103 break;
8104 case 2:
ea96b374
RH
8105 tl = load_reg(s, a->ra);
8106 th = load_reg(s, a->rd);
8107 t1 = tcg_const_i32(0);
8108 tcg_gen_add2_i32(tl, th, tl, th, t0, t1);
26c6923d 8109 tcg_temp_free_i32(t0);
ea96b374
RH
8110 tcg_temp_free_i32(t1);
8111 store_reg(s, a->ra, tl);
8112 store_reg(s, a->rd, th);
26c6923d
RH
8113 break;
8114 default:
8115 g_assert_not_reached();
8116 }
8117 return true;
8118}
8119
8120#define DO_SMLAX(NAME, add, nt, mt) \
8121static bool trans_##NAME(DisasContext *s, arg_rrrr *a) \
8122{ \
8123 return op_smlaxxx(s, a, add, nt, mt); \
8124}
8125
8126DO_SMLAX(SMULBB, 0, 0, 0)
8127DO_SMLAX(SMULBT, 0, 0, 1)
8128DO_SMLAX(SMULTB, 0, 1, 0)
8129DO_SMLAX(SMULTT, 0, 1, 1)
8130
8131DO_SMLAX(SMLABB, 1, 0, 0)
8132DO_SMLAX(SMLABT, 1, 0, 1)
8133DO_SMLAX(SMLATB, 1, 1, 0)
8134DO_SMLAX(SMLATT, 1, 1, 1)
8135
8136DO_SMLAX(SMLALBB, 2, 0, 0)
8137DO_SMLAX(SMLALBT, 2, 0, 1)
8138DO_SMLAX(SMLALTB, 2, 1, 0)
8139DO_SMLAX(SMLALTT, 2, 1, 1)
8140
8141#undef DO_SMLAX
8142
8143static bool op_smlawx(DisasContext *s, arg_rrrr *a, bool add, bool mt)
8144{
8145 TCGv_i32 t0, t1;
26c6923d
RH
8146
8147 if (!ENABLE_ARCH_5TE) {
8148 return false;
8149 }
8150
8151 t0 = load_reg(s, a->rn);
8152 t1 = load_reg(s, a->rm);
485b607d
RH
8153 /*
8154 * Since the nominal result is product<47:16>, shift the 16-bit
8155 * input up by 16 bits, so that the result is at product<63:32>.
8156 */
26c6923d 8157 if (mt) {
485b607d 8158 tcg_gen_andi_i32(t1, t1, 0xffff0000);
26c6923d 8159 } else {
485b607d 8160 tcg_gen_shli_i32(t1, t1, 16);
26c6923d 8161 }
485b607d
RH
8162 tcg_gen_muls2_i32(t0, t1, t0, t1);
8163 tcg_temp_free_i32(t0);
26c6923d
RH
8164 if (add) {
8165 t0 = load_reg(s, a->ra);
8166 gen_helper_add_setq(t1, cpu_env, t1, t0);
8167 tcg_temp_free_i32(t0);
8168 }
8169 store_reg(s, a->rd, t1);
8170 return true;
8171}
8172
8173#define DO_SMLAWX(NAME, add, mt) \
8174static bool trans_##NAME(DisasContext *s, arg_rrrr *a) \
8175{ \
8176 return op_smlawx(s, a, add, mt); \
8177}
8178
8179DO_SMLAWX(SMULWB, 0, 0)
8180DO_SMLAWX(SMULWT, 0, 1)
8181DO_SMLAWX(SMLAWB, 1, 0)
8182DO_SMLAWX(SMLAWT, 1, 1)
8183
8184#undef DO_SMLAWX
8185
63130596
RH
8186/*
8187 * MSR (immediate) and hints
8188 */
8189
8190static bool trans_YIELD(DisasContext *s, arg_YIELD *a)
8191{
8192 gen_nop_hint(s, 1);
8193 return true;
8194}
8195
8196static bool trans_WFE(DisasContext *s, arg_WFE *a)
8197{
8198 gen_nop_hint(s, 2);
8199 return true;
8200}
8201
8202static bool trans_WFI(DisasContext *s, arg_WFI *a)
8203{
8204 gen_nop_hint(s, 3);
8205 return true;
8206}
8207
8208static bool trans_NOP(DisasContext *s, arg_NOP *a)
8209{
8210 return true;
8211}
8212
8213static bool trans_MSR_imm(DisasContext *s, arg_MSR_imm *a)
8214{
8215 uint32_t val = ror32(a->imm, a->rot * 2);
8216 uint32_t mask = msr_mask(s, a->mask, a->r);
8217
8218 if (gen_set_psr_im(s, mask, a->r, val)) {
8219 unallocated_encoding(s);
8220 }
8221 return true;
8222}
8223
6c35d53f
RH
8224/*
8225 * Cyclic Redundancy Check
8226 */
8227
8228static bool op_crc32(DisasContext *s, arg_rrr *a, bool c, MemOp sz)
8229{
8230 TCGv_i32 t1, t2, t3;
8231
8232 if (!dc_isar_feature(aa32_crc32, s)) {
8233 return false;
8234 }
8235
8236 t1 = load_reg(s, a->rn);
8237 t2 = load_reg(s, a->rm);
8238 switch (sz) {
8239 case MO_8:
8240 gen_uxtb(t2);
8241 break;
8242 case MO_16:
8243 gen_uxth(t2);
8244 break;
8245 case MO_32:
8246 break;
8247 default:
8248 g_assert_not_reached();
8249 }
8250 t3 = tcg_const_i32(1 << sz);
8251 if (c) {
8252 gen_helper_crc32c(t1, t1, t2, t3);
8253 } else {
8254 gen_helper_crc32(t1, t1, t2, t3);
8255 }
8256 tcg_temp_free_i32(t2);
8257 tcg_temp_free_i32(t3);
8258 store_reg(s, a->rd, t1);
8259 return true;
8260}
8261
8262#define DO_CRC32(NAME, c, sz) \
8263static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
8264 { return op_crc32(s, a, c, sz); }
8265
8266DO_CRC32(CRC32B, false, MO_8)
8267DO_CRC32(CRC32H, false, MO_16)
8268DO_CRC32(CRC32W, false, MO_32)
8269DO_CRC32(CRC32CB, true, MO_8)
8270DO_CRC32(CRC32CH, true, MO_16)
8271DO_CRC32(CRC32CW, true, MO_32)
8272
8273#undef DO_CRC32
8274
d0b26644
RH
8275/*
8276 * Miscellaneous instructions
8277 */
8278
8279static bool trans_MRS_bank(DisasContext *s, arg_MRS_bank *a)
8280{
8281 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8282 return false;
8283 }
8284 gen_mrs_banked(s, a->r, a->sysm, a->rd);
8285 return true;
8286}
8287
8288static bool trans_MSR_bank(DisasContext *s, arg_MSR_bank *a)
8289{
8290 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8291 return false;
8292 }
8293 gen_msr_banked(s, a->r, a->sysm, a->rn);
8294 return true;
8295}
8296
8297static bool trans_MRS_reg(DisasContext *s, arg_MRS_reg *a)
8298{
8299 TCGv_i32 tmp;
8300
8301 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8302 return false;
8303 }
8304 if (a->r) {
8305 if (IS_USER(s)) {
8306 unallocated_encoding(s);
8307 return true;
8308 }
8309 tmp = load_cpu_field(spsr);
8310 } else {
8311 tmp = tcg_temp_new_i32();
8312 gen_helper_cpsr_read(tmp, cpu_env);
8313 }
8314 store_reg(s, a->rd, tmp);
8315 return true;
8316}
8317
8318static bool trans_MSR_reg(DisasContext *s, arg_MSR_reg *a)
8319{
8320 TCGv_i32 tmp;
8321 uint32_t mask = msr_mask(s, a->mask, a->r);
8322
8323 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8324 return false;
8325 }
8326 tmp = load_reg(s, a->rn);
8327 if (gen_set_psr(s, mask, a->r, tmp)) {
8328 unallocated_encoding(s);
8329 }
8330 return true;
8331}
8332
8333static bool trans_MRS_v7m(DisasContext *s, arg_MRS_v7m *a)
8334{
8335 TCGv_i32 tmp;
8336
8337 if (!arm_dc_feature(s, ARM_FEATURE_M)) {
8338 return false;
8339 }
8340 tmp = tcg_const_i32(a->sysm);
8341 gen_helper_v7m_mrs(tmp, cpu_env, tmp);
8342 store_reg(s, a->rd, tmp);
8343 return true;
8344}
8345
8346static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m *a)
8347{
8348 TCGv_i32 addr, reg;
8349
8350 if (!arm_dc_feature(s, ARM_FEATURE_M)) {
8351 return false;
8352 }
8353 addr = tcg_const_i32((a->mask << 10) | a->sysm);
8354 reg = load_reg(s, a->rn);
8355 gen_helper_v7m_msr(cpu_env, addr, reg);
8356 tcg_temp_free_i32(addr);
8357 tcg_temp_free_i32(reg);
8358 gen_lookup_tb(s);
8359 return true;
8360}
8361
4ed95abd
RH
8362static bool trans_BX(DisasContext *s, arg_BX *a)
8363{
8364 if (!ENABLE_ARCH_4T) {
8365 return false;
8366 }
a0ef0774 8367 gen_bx_excret(s, load_reg(s, a->rm));
4ed95abd
RH
8368 return true;
8369}
8370
8371static bool trans_BXJ(DisasContext *s, arg_BXJ *a)
8372{
8373 if (!ENABLE_ARCH_5J || arm_dc_feature(s, ARM_FEATURE_M)) {
8374 return false;
8375 }
8376 /* Trivial implementation equivalent to bx. */
8377 gen_bx(s, load_reg(s, a->rm));
8378 return true;
8379}
8380
8381static bool trans_BLX_r(DisasContext *s, arg_BLX_r *a)
8382{
8383 TCGv_i32 tmp;
8384
8385 if (!ENABLE_ARCH_5) {
8386 return false;
8387 }
8388 tmp = load_reg(s, a->rm);
8389 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
8390 gen_bx(s, tmp);
8391 return true;
8392}
8393
a0ef0774
RH
8394/*
8395 * BXNS/BLXNS: only exist for v8M with the security extensions,
8396 * and always UNDEF if NonSecure. We don't implement these in
8397 * the user-only mode either (in theory you can use them from
8398 * Secure User mode but they are too tied in to system emulation).
8399 */
8400static bool trans_BXNS(DisasContext *s, arg_BXNS *a)
8401{
8402 if (!s->v8m_secure || IS_USER_ONLY) {
8403 unallocated_encoding(s);
8404 } else {
8405 gen_bxns(s, a->rm);
8406 }
8407 return true;
8408}
8409
8410static bool trans_BLXNS(DisasContext *s, arg_BLXNS *a)
8411{
8412 if (!s->v8m_secure || IS_USER_ONLY) {
8413 unallocated_encoding(s);
8414 } else {
8415 gen_blxns(s, a->rm);
8416 }
8417 return true;
8418}
8419
4c97f5b2
RH
8420static bool trans_CLZ(DisasContext *s, arg_CLZ *a)
8421{
8422 TCGv_i32 tmp;
8423
8424 if (!ENABLE_ARCH_5) {
8425 return false;
8426 }
8427 tmp = load_reg(s, a->rm);
8428 tcg_gen_clzi_i32(tmp, tmp, 32);
8429 store_reg(s, a->rd, tmp);
8430 return true;
8431}
8432
ef11bc3c
RH
8433static bool trans_ERET(DisasContext *s, arg_ERET *a)
8434{
8435 TCGv_i32 tmp;
8436
8437 if (!arm_dc_feature(s, ARM_FEATURE_V7VE)) {
8438 return false;
8439 }
8440 if (IS_USER(s)) {
8441 unallocated_encoding(s);
8442 return true;
8443 }
8444 if (s->current_el == 2) {
8445 /* ERET from Hyp uses ELR_Hyp, not LR */
8446 tmp = load_cpu_field(elr_el[2]);
8447 } else {
8448 tmp = load_reg(s, 14);
8449 }
8450 gen_exception_return(s, tmp);
8451 return true;
8452}
8453
2cde9ea5
RH
8454static bool trans_HLT(DisasContext *s, arg_HLT *a)
8455{
8456 gen_hlt(s, a->imm);
8457 return true;
8458}
8459
8460static bool trans_BKPT(DisasContext *s, arg_BKPT *a)
8461{
8462 if (!ENABLE_ARCH_5) {
8463 return false;
8464 }
8465 gen_exception_bkpt_insn(s, syn_aa32_bkpt(a->imm, false));
8466 return true;
8467}
8468
8469static bool trans_HVC(DisasContext *s, arg_HVC *a)
8470{
8471 if (!ENABLE_ARCH_7 || arm_dc_feature(s, ARM_FEATURE_M)) {
8472 return false;
8473 }
8474 if (IS_USER(s)) {
8475 unallocated_encoding(s);
8476 } else {
8477 gen_hvc(s, a->imm);
8478 }
8479 return true;
8480}
8481
8482static bool trans_SMC(DisasContext *s, arg_SMC *a)
8483{
8484 if (!ENABLE_ARCH_6K || arm_dc_feature(s, ARM_FEATURE_M)) {
8485 return false;
8486 }
8487 if (IS_USER(s)) {
8488 unallocated_encoding(s);
8489 } else {
8490 gen_smc(s);
8491 }
8492 return true;
8493}
8494
35d240ac
RH
8495static bool trans_SG(DisasContext *s, arg_SG *a)
8496{
8497 if (!arm_dc_feature(s, ARM_FEATURE_M) ||
8498 !arm_dc_feature(s, ARM_FEATURE_V8)) {
8499 return false;
8500 }
8501 /*
8502 * SG (v8M only)
8503 * The bulk of the behaviour for this instruction is implemented
8504 * in v7m_handle_execute_nsc(), which deals with the insn when
8505 * it is executed by a CPU in non-secure state from memory
8506 * which is Secure & NonSecure-Callable.
8507 * Here we only need to handle the remaining cases:
8508 * * in NS memory (including the "security extension not
8509 * implemented" case) : NOP
8510 * * in S memory but CPU already secure (clear IT bits)
8511 * We know that the attribute for the memory this insn is
8512 * in must match the current CPU state, because otherwise
8513 * get_phys_addr_pmsav8 would have generated an exception.
8514 */
8515 if (s->v8m_secure) {
8516 /* Like the IT insn, we don't need to generate any code */
8517 s->condexec_cond = 0;
8518 s->condexec_mask = 0;
8519 }
8520 return true;
8521}
8522
d449f174
RH
8523static bool trans_TT(DisasContext *s, arg_TT *a)
8524{
8525 TCGv_i32 addr, tmp;
8526
8527 if (!arm_dc_feature(s, ARM_FEATURE_M) ||
8528 !arm_dc_feature(s, ARM_FEATURE_V8)) {
8529 return false;
8530 }
8531 if (a->rd == 13 || a->rd == 15 || a->rn == 15) {
8532 /* We UNDEF for these UNPREDICTABLE cases */
8533 unallocated_encoding(s);
8534 return true;
8535 }
8536 if (a->A && !s->v8m_secure) {
8537 /* This case is UNDEFINED. */
8538 unallocated_encoding(s);
8539 return true;
8540 }
8541
8542 addr = load_reg(s, a->rn);
8543 tmp = tcg_const_i32((a->A << 1) | a->T);
8544 gen_helper_v7m_tt(tmp, cpu_env, addr, tmp);
8545 tcg_temp_free_i32(addr);
8546 store_reg(s, a->rd, tmp);
8547 return true;
8548}
8549
5e291fe1
RH
8550/*
8551 * Load/store register index
8552 */
8553
8554static ISSInfo make_issinfo(DisasContext *s, int rd, bool p, bool w)
8555{
8556 ISSInfo ret;
8557
8558 /* ISS not valid if writeback */
8559 if (p && !w) {
8560 ret = rd;
8561 } else {
8562 ret = ISSInvalid;
8563 }
8564 return ret;
8565}
8566
8567static TCGv_i32 op_addr_rr_pre(DisasContext *s, arg_ldst_rr *a)
8568{
8569 TCGv_i32 addr = load_reg(s, a->rn);
8570
8571 if (s->v8m_stackcheck && a->rn == 13 && a->w) {
8572 gen_helper_v8m_stackcheck(cpu_env, addr);
8573 }
8574
8575 if (a->p) {
8576 TCGv_i32 ofs = load_reg(s, a->rm);
8577 gen_arm_shift_im(ofs, a->shtype, a->shimm, 0);
8578 if (a->u) {
8579 tcg_gen_add_i32(addr, addr, ofs);
8580 } else {
8581 tcg_gen_sub_i32(addr, addr, ofs);
8582 }
8583 tcg_temp_free_i32(ofs);
8584 }
8585 return addr;
8586}
8587
8588static void op_addr_rr_post(DisasContext *s, arg_ldst_rr *a,
8589 TCGv_i32 addr, int address_offset)
8590{
8591 if (!a->p) {
8592 TCGv_i32 ofs = load_reg(s, a->rm);
8593 gen_arm_shift_im(ofs, a->shtype, a->shimm, 0);
8594 if (a->u) {
8595 tcg_gen_add_i32(addr, addr, ofs);
8596 } else {
8597 tcg_gen_sub_i32(addr, addr, ofs);
8598 }
8599 tcg_temp_free_i32(ofs);
8600 } else if (!a->w) {
8601 tcg_temp_free_i32(addr);
8602 return;
8603 }
8604 tcg_gen_addi_i32(addr, addr, address_offset);
8605 store_reg(s, a->rn, addr);
8606}
8607
8608static bool op_load_rr(DisasContext *s, arg_ldst_rr *a,
8609 MemOp mop, int mem_idx)
8610{
8611 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w);
8612 TCGv_i32 addr, tmp;
8613
8614 addr = op_addr_rr_pre(s, a);
8615
8616 tmp = tcg_temp_new_i32();
8617 gen_aa32_ld_i32(s, tmp, addr, mem_idx, mop | s->be_data);
8618 disas_set_da_iss(s, mop, issinfo);
8619
8620 /*
8621 * Perform base writeback before the loaded value to
8622 * ensure correct behavior with overlapping index registers.
8623 */
8624 op_addr_rr_post(s, a, addr, 0);
8625 store_reg_from_load(s, a->rt, tmp);
8626 return true;
8627}
8628
8629static bool op_store_rr(DisasContext *s, arg_ldst_rr *a,
8630 MemOp mop, int mem_idx)
8631{
8632 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w) | ISSIsWrite;
8633 TCGv_i32 addr, tmp;
8634
8635 addr = op_addr_rr_pre(s, a);
8636
8637 tmp = load_reg(s, a->rt);
8638 gen_aa32_st_i32(s, tmp, addr, mem_idx, mop | s->be_data);
8639 disas_set_da_iss(s, mop, issinfo);
8640 tcg_temp_free_i32(tmp);
8641
8642 op_addr_rr_post(s, a, addr, 0);
8643 return true;
8644}
8645
8646static bool trans_LDRD_rr(DisasContext *s, arg_ldst_rr *a)
8647{
8648 int mem_idx = get_mem_index(s);
8649 TCGv_i32 addr, tmp;
8650
8651 if (!ENABLE_ARCH_5TE) {
8652 return false;
8653 }
8654 if (a->rt & 1) {
8655 unallocated_encoding(s);
8656 return true;
8657 }
8658 addr = op_addr_rr_pre(s, a);
8659
8660 tmp = tcg_temp_new_i32();
8661 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
8662 store_reg(s, a->rt, tmp);
8663
8664 tcg_gen_addi_i32(addr, addr, 4);
8665
8666 tmp = tcg_temp_new_i32();
8667 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
8668 store_reg(s, a->rt + 1, tmp);
8669
8670 /* LDRD w/ base writeback is undefined if the registers overlap. */
8671 op_addr_rr_post(s, a, addr, -4);
8672 return true;
8673}
8674
8675static bool trans_STRD_rr(DisasContext *s, arg_ldst_rr *a)
8676{
8677 int mem_idx = get_mem_index(s);
8678 TCGv_i32 addr, tmp;
8679
8680 if (!ENABLE_ARCH_5TE) {
8681 return false;
8682 }
8683 if (a->rt & 1) {
8684 unallocated_encoding(s);
8685 return true;
8686 }
8687 addr = op_addr_rr_pre(s, a);
8688
8689 tmp = load_reg(s, a->rt);
8690 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
8691 tcg_temp_free_i32(tmp);
8692
8693 tcg_gen_addi_i32(addr, addr, 4);
8694
8695 tmp = load_reg(s, a->rt + 1);
8696 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
8697 tcg_temp_free_i32(tmp);
8698
8699 op_addr_rr_post(s, a, addr, -4);
8700 return true;
8701}
8702
8703/*
8704 * Load/store immediate index
8705 */
8706
8707static TCGv_i32 op_addr_ri_pre(DisasContext *s, arg_ldst_ri *a)
8708{
8709 int ofs = a->imm;
8710
8711 if (!a->u) {
8712 ofs = -ofs;
8713 }
8714
8715 if (s->v8m_stackcheck && a->rn == 13 && a->w) {
8716 /*
8717 * Stackcheck. Here we know 'addr' is the current SP;
8718 * U is set if we're moving SP up, else down. It is
8719 * UNKNOWN whether the limit check triggers when SP starts
8720 * below the limit and ends up above it; we chose to do so.
8721 */
8722 if (!a->u) {
8723 TCGv_i32 newsp = tcg_temp_new_i32();
8724 tcg_gen_addi_i32(newsp, cpu_R[13], ofs);
8725 gen_helper_v8m_stackcheck(cpu_env, newsp);
8726 tcg_temp_free_i32(newsp);
8727 } else {
8728 gen_helper_v8m_stackcheck(cpu_env, cpu_R[13]);
8729 }
8730 }
8731
8732 return add_reg_for_lit(s, a->rn, a->p ? ofs : 0);
8733}
8734
8735static void op_addr_ri_post(DisasContext *s, arg_ldst_ri *a,
8736 TCGv_i32 addr, int address_offset)
8737{
8738 if (!a->p) {
8739 if (a->u) {
8740 address_offset += a->imm;
8741 } else {
8742 address_offset -= a->imm;
8743 }
8744 } else if (!a->w) {
8745 tcg_temp_free_i32(addr);
8746 return;
8747 }
8748 tcg_gen_addi_i32(addr, addr, address_offset);
8749 store_reg(s, a->rn, addr);
8750}
8751
8752static bool op_load_ri(DisasContext *s, arg_ldst_ri *a,
8753 MemOp mop, int mem_idx)
8754{
8755 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w);
8756 TCGv_i32 addr, tmp;
8757
8758 addr = op_addr_ri_pre(s, a);
8759
8760 tmp = tcg_temp_new_i32();
8761 gen_aa32_ld_i32(s, tmp, addr, mem_idx, mop | s->be_data);
8762 disas_set_da_iss(s, mop, issinfo);
8763
8764 /*
8765 * Perform base writeback before the loaded value to
8766 * ensure correct behavior with overlapping index registers.
8767 */
8768 op_addr_ri_post(s, a, addr, 0);
8769 store_reg_from_load(s, a->rt, tmp);
8770 return true;
8771}
8772
8773static bool op_store_ri(DisasContext *s, arg_ldst_ri *a,
8774 MemOp mop, int mem_idx)
8775{
8776 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w) | ISSIsWrite;
8777 TCGv_i32 addr, tmp;
8778
8779 addr = op_addr_ri_pre(s, a);
8780
8781 tmp = load_reg(s, a->rt);
8782 gen_aa32_st_i32(s, tmp, addr, mem_idx, mop | s->be_data);
8783 disas_set_da_iss(s, mop, issinfo);
8784 tcg_temp_free_i32(tmp);
8785
8786 op_addr_ri_post(s, a, addr, 0);
8787 return true;
8788}
8789
8790static bool op_ldrd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
8791{
8792 int mem_idx = get_mem_index(s);
8793 TCGv_i32 addr, tmp;
8794
8795 addr = op_addr_ri_pre(s, a);
8796
8797 tmp = tcg_temp_new_i32();
8798 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
8799 store_reg(s, a->rt, tmp);
8800
8801 tcg_gen_addi_i32(addr, addr, 4);
8802
8803 tmp = tcg_temp_new_i32();
8804 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
8805 store_reg(s, rt2, tmp);
8806
8807 /* LDRD w/ base writeback is undefined if the registers overlap. */
8808 op_addr_ri_post(s, a, addr, -4);
8809 return true;
8810}
8811
8812static bool trans_LDRD_ri_a32(DisasContext *s, arg_ldst_ri *a)
8813{
8814 if (!ENABLE_ARCH_5TE || (a->rt & 1)) {
8815 return false;
8816 }
8817 return op_ldrd_ri(s, a, a->rt + 1);
8818}
8819
8820static bool trans_LDRD_ri_t32(DisasContext *s, arg_ldst_ri2 *a)
8821{
8822 arg_ldst_ri b = {
8823 .u = a->u, .w = a->w, .p = a->p,
8824 .rn = a->rn, .rt = a->rt, .imm = a->imm
8825 };
8826 return op_ldrd_ri(s, &b, a->rt2);
8827}
8828
8829static bool op_strd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
8830{
8831 int mem_idx = get_mem_index(s);
8832 TCGv_i32 addr, tmp;
8833
8834 addr = op_addr_ri_pre(s, a);
8835
8836 tmp = load_reg(s, a->rt);
8837 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
8838 tcg_temp_free_i32(tmp);
8839
8840 tcg_gen_addi_i32(addr, addr, 4);
8841
8842 tmp = load_reg(s, rt2);
8843 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
8844 tcg_temp_free_i32(tmp);
8845
8846 op_addr_ri_post(s, a, addr, -4);
8847 return true;
8848}
8849
8850static bool trans_STRD_ri_a32(DisasContext *s, arg_ldst_ri *a)
8851{
8852 if (!ENABLE_ARCH_5TE || (a->rt & 1)) {
8853 return false;
8854 }
8855 return op_strd_ri(s, a, a->rt + 1);
8856}
8857
8858static bool trans_STRD_ri_t32(DisasContext *s, arg_ldst_ri2 *a)
8859{
8860 arg_ldst_ri b = {
8861 .u = a->u, .w = a->w, .p = a->p,
8862 .rn = a->rn, .rt = a->rt, .imm = a->imm
8863 };
8864 return op_strd_ri(s, &b, a->rt2);
8865}
8866
8867#define DO_LDST(NAME, WHICH, MEMOP) \
8868static bool trans_##NAME##_ri(DisasContext *s, arg_ldst_ri *a) \
8869{ \
8870 return op_##WHICH##_ri(s, a, MEMOP, get_mem_index(s)); \
8871} \
8872static bool trans_##NAME##T_ri(DisasContext *s, arg_ldst_ri *a) \
8873{ \
8874 return op_##WHICH##_ri(s, a, MEMOP, get_a32_user_mem_index(s)); \
8875} \
8876static bool trans_##NAME##_rr(DisasContext *s, arg_ldst_rr *a) \
8877{ \
8878 return op_##WHICH##_rr(s, a, MEMOP, get_mem_index(s)); \
8879} \
8880static bool trans_##NAME##T_rr(DisasContext *s, arg_ldst_rr *a) \
8881{ \
8882 return op_##WHICH##_rr(s, a, MEMOP, get_a32_user_mem_index(s)); \
8883}
8884
8885DO_LDST(LDR, load, MO_UL)
8886DO_LDST(LDRB, load, MO_UB)
8887DO_LDST(LDRH, load, MO_UW)
8888DO_LDST(LDRSB, load, MO_SB)
8889DO_LDST(LDRSH, load, MO_SW)
8890
8891DO_LDST(STR, store, MO_UL)
8892DO_LDST(STRB, store, MO_UB)
8893DO_LDST(STRH, store, MO_UW)
8894
8895#undef DO_LDST
8896
1efdd407
RH
8897/*
8898 * Synchronization primitives
8899 */
8900
8901static bool op_swp(DisasContext *s, arg_SWP *a, MemOp opc)
8902{
8903 TCGv_i32 addr, tmp;
8904 TCGv taddr;
8905
8906 opc |= s->be_data;
8907 addr = load_reg(s, a->rn);
8908 taddr = gen_aa32_addr(s, addr, opc);
8909 tcg_temp_free_i32(addr);
8910
8911 tmp = load_reg(s, a->rt2);
8912 tcg_gen_atomic_xchg_i32(tmp, taddr, tmp, get_mem_index(s), opc);
8913 tcg_temp_free(taddr);
8914
8915 store_reg(s, a->rt, tmp);
8916 return true;
8917}
8918
8919static bool trans_SWP(DisasContext *s, arg_SWP *a)
8920{
8921 return op_swp(s, a, MO_UL | MO_ALIGN);
8922}
8923
8924static bool trans_SWPB(DisasContext *s, arg_SWP *a)
8925{
8926 return op_swp(s, a, MO_UB);
8927}
8928
8929/*
8930 * Load/Store Exclusive and Load-Acquire/Store-Release
8931 */
8932
8933static bool op_strex(DisasContext *s, arg_STREX *a, MemOp mop, bool rel)
8934{
8935 TCGv_i32 addr;
8936
af288228
RH
8937 /* We UNDEF for these UNPREDICTABLE cases. */
8938 if (a->rd == 15 || a->rn == 15 || a->rt == 15
8939 || a->rd == a->rn || a->rd == a->rt
8940 || (s->thumb && (a->rd == 13 || a->rt == 13))
8941 || (mop == MO_64
8942 && (a->rt2 == 15
8943 || a->rd == a->rt2 || a->rt == a->rt2
8944 || (s->thumb && a->rt2 == 13)))) {
8945 unallocated_encoding(s);
8946 return true;
8947 }
8948
1efdd407
RH
8949 if (rel) {
8950 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
8951 }
8952
8953 addr = tcg_temp_local_new_i32();
8954 load_reg_var(s, addr, a->rn);
8955 tcg_gen_addi_i32(addr, addr, a->imm);
8956
8957 gen_store_exclusive(s, a->rd, a->rt, a->rt2, addr, mop);
8958 tcg_temp_free_i32(addr);
8959 return true;
8960}
8961
8962static bool trans_STREX(DisasContext *s, arg_STREX *a)
8963{
8964 if (!ENABLE_ARCH_6) {
8965 return false;
8966 }
8967 return op_strex(s, a, MO_32, false);
8968}
8969
8970static bool trans_STREXD_a32(DisasContext *s, arg_STREX *a)
8971{
8972 if (!ENABLE_ARCH_6K) {
8973 return false;
8974 }
af288228 8975 /* We UNDEF for these UNPREDICTABLE cases. */
1efdd407
RH
8976 if (a->rt & 1) {
8977 unallocated_encoding(s);
8978 return true;
8979 }
8980 a->rt2 = a->rt + 1;
8981 return op_strex(s, a, MO_64, false);
8982}
8983
8984static bool trans_STREXD_t32(DisasContext *s, arg_STREX *a)
8985{
8986 return op_strex(s, a, MO_64, false);
8987}
8988
8989static bool trans_STREXB(DisasContext *s, arg_STREX *a)
8990{
8991 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
8992 return false;
8993 }
8994 return op_strex(s, a, MO_8, false);
8995}
8996
8997static bool trans_STREXH(DisasContext *s, arg_STREX *a)
8998{
8999 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
9000 return false;
9001 }
9002 return op_strex(s, a, MO_16, false);
9003}
9004
9005static bool trans_STLEX(DisasContext *s, arg_STREX *a)
9006{
9007 if (!ENABLE_ARCH_8) {
9008 return false;
9009 }
9010 return op_strex(s, a, MO_32, true);
9011}
9012
9013static bool trans_STLEXD_a32(DisasContext *s, arg_STREX *a)
9014{
9015 if (!ENABLE_ARCH_8) {
9016 return false;
9017 }
af288228 9018 /* We UNDEF for these UNPREDICTABLE cases. */
1efdd407
RH
9019 if (a->rt & 1) {
9020 unallocated_encoding(s);
9021 return true;
9022 }
9023 a->rt2 = a->rt + 1;
9024 return op_strex(s, a, MO_64, true);
9025}
9026
9027static bool trans_STLEXD_t32(DisasContext *s, arg_STREX *a)
9028{
9029 if (!ENABLE_ARCH_8) {
9030 return false;
9031 }
9032 return op_strex(s, a, MO_64, true);
9033}
9034
9035static bool trans_STLEXB(DisasContext *s, arg_STREX *a)
9036{
9037 if (!ENABLE_ARCH_8) {
9038 return false;
9039 }
9040 return op_strex(s, a, MO_8, true);
9041}
9042
9043static bool trans_STLEXH(DisasContext *s, arg_STREX *a)
9044{
9045 if (!ENABLE_ARCH_8) {
9046 return false;
9047 }
9048 return op_strex(s, a, MO_16, true);
9049}
9050
9051static bool op_stl(DisasContext *s, arg_STL *a, MemOp mop)
9052{
9053 TCGv_i32 addr, tmp;
9054
9055 if (!ENABLE_ARCH_8) {
9056 return false;
9057 }
af288228
RH
9058 /* We UNDEF for these UNPREDICTABLE cases. */
9059 if (a->rn == 15 || a->rt == 15) {
9060 unallocated_encoding(s);
9061 return true;
9062 }
1efdd407 9063
af288228 9064 addr = load_reg(s, a->rn);
1efdd407
RH
9065 tmp = load_reg(s, a->rt);
9066 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
9067 gen_aa32_st_i32(s, tmp, addr, get_mem_index(s), mop | s->be_data);
9068 disas_set_da_iss(s, mop, a->rt | ISSIsAcqRel | ISSIsWrite);
9069
9070 tcg_temp_free_i32(tmp);
9071 tcg_temp_free_i32(addr);
9072 return true;
9073}
9074
9075static bool trans_STL(DisasContext *s, arg_STL *a)
9076{
9077 return op_stl(s, a, MO_UL);
9078}
9079
9080static bool trans_STLB(DisasContext *s, arg_STL *a)
9081{
9082 return op_stl(s, a, MO_UB);
9083}
9084
9085static bool trans_STLH(DisasContext *s, arg_STL *a)
9086{
9087 return op_stl(s, a, MO_UW);
9088}
9089
9090static bool op_ldrex(DisasContext *s, arg_LDREX *a, MemOp mop, bool acq)
9091{
9092 TCGv_i32 addr;
9093
af288228
RH
9094 /* We UNDEF for these UNPREDICTABLE cases. */
9095 if (a->rn == 15 || a->rt == 15
9096 || (s->thumb && a->rt == 13)
9097 || (mop == MO_64
9098 && (a->rt2 == 15 || a->rt == a->rt2
9099 || (s->thumb && a->rt2 == 13)))) {
9100 unallocated_encoding(s);
9101 return true;
9102 }
9103
1efdd407
RH
9104 addr = tcg_temp_local_new_i32();
9105 load_reg_var(s, addr, a->rn);
9106 tcg_gen_addi_i32(addr, addr, a->imm);
9107
9108 gen_load_exclusive(s, a->rt, a->rt2, addr, mop);
9109 tcg_temp_free_i32(addr);
9110
9111 if (acq) {
9112 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
9113 }
9114 return true;
9115}
9116
9117static bool trans_LDREX(DisasContext *s, arg_LDREX *a)
9118{
9119 if (!ENABLE_ARCH_6) {
9120 return false;
9121 }
9122 return op_ldrex(s, a, MO_32, false);
9123}
9124
9125static bool trans_LDREXD_a32(DisasContext *s, arg_LDREX *a)
9126{
9127 if (!ENABLE_ARCH_6K) {
9128 return false;
9129 }
af288228 9130 /* We UNDEF for these UNPREDICTABLE cases. */
1efdd407
RH
9131 if (a->rt & 1) {
9132 unallocated_encoding(s);
9133 return true;
9134 }
9135 a->rt2 = a->rt + 1;
9136 return op_ldrex(s, a, MO_64, false);
9137}
9138
9139static bool trans_LDREXD_t32(DisasContext *s, arg_LDREX *a)
9140{
9141 return op_ldrex(s, a, MO_64, false);
9142}
9143
9144static bool trans_LDREXB(DisasContext *s, arg_LDREX *a)
9145{
9146 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
9147 return false;
9148 }
9149 return op_ldrex(s, a, MO_8, false);
9150}
9151
9152static bool trans_LDREXH(DisasContext *s, arg_LDREX *a)
9153{
9154 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
9155 return false;
9156 }
9157 return op_ldrex(s, a, MO_16, false);
9158}
9159
9160static bool trans_LDAEX(DisasContext *s, arg_LDREX *a)
9161{
9162 if (!ENABLE_ARCH_8) {
9163 return false;
9164 }
9165 return op_ldrex(s, a, MO_32, true);
9166}
9167
9168static bool trans_LDAEXD_a32(DisasContext *s, arg_LDREX *a)
9169{
9170 if (!ENABLE_ARCH_8) {
9171 return false;
9172 }
af288228 9173 /* We UNDEF for these UNPREDICTABLE cases. */
1efdd407
RH
9174 if (a->rt & 1) {
9175 unallocated_encoding(s);
9176 return true;
9177 }
9178 a->rt2 = a->rt + 1;
9179 return op_ldrex(s, a, MO_64, true);
9180}
9181
9182static bool trans_LDAEXD_t32(DisasContext *s, arg_LDREX *a)
9183{
9184 if (!ENABLE_ARCH_8) {
9185 return false;
9186 }
9187 return op_ldrex(s, a, MO_64, true);
9188}
9189
9190static bool trans_LDAEXB(DisasContext *s, arg_LDREX *a)
9191{
9192 if (!ENABLE_ARCH_8) {
9193 return false;
9194 }
9195 return op_ldrex(s, a, MO_8, true);
9196}
9197
9198static bool trans_LDAEXH(DisasContext *s, arg_LDREX *a)
9199{
9200 if (!ENABLE_ARCH_8) {
9201 return false;
9202 }
9203 return op_ldrex(s, a, MO_16, true);
9204}
9205
9206static bool op_lda(DisasContext *s, arg_LDA *a, MemOp mop)
9207{
9208 TCGv_i32 addr, tmp;
9209
9210 if (!ENABLE_ARCH_8) {
9211 return false;
9212 }
af288228
RH
9213 /* We UNDEF for these UNPREDICTABLE cases. */
9214 if (a->rn == 15 || a->rt == 15) {
9215 unallocated_encoding(s);
9216 return true;
9217 }
1efdd407 9218
af288228 9219 addr = load_reg(s, a->rn);
1efdd407
RH
9220 tmp = tcg_temp_new_i32();
9221 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), mop | s->be_data);
9222 disas_set_da_iss(s, mop, a->rt | ISSIsAcqRel);
9223 tcg_temp_free_i32(addr);
9224
9225 store_reg(s, a->rt, tmp);
9226 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
9227 return true;
9228}
9229
9230static bool trans_LDA(DisasContext *s, arg_LDA *a)
9231{
9232 return op_lda(s, a, MO_UL);
9233}
9234
9235static bool trans_LDAB(DisasContext *s, arg_LDA *a)
9236{
9237 return op_lda(s, a, MO_UB);
9238}
9239
9240static bool trans_LDAH(DisasContext *s, arg_LDA *a)
9241{
9242 return op_lda(s, a, MO_UW);
9243}
9244
86d21e4b
RH
9245/*
9246 * Media instructions
9247 */
9248
9249static bool trans_USADA8(DisasContext *s, arg_USADA8 *a)
9250{
9251 TCGv_i32 t1, t2;
9252
9253 if (!ENABLE_ARCH_6) {
9254 return false;
9255 }
9256
9257 t1 = load_reg(s, a->rn);
9258 t2 = load_reg(s, a->rm);
9259 gen_helper_usad8(t1, t1, t2);
9260 tcg_temp_free_i32(t2);
9261 if (a->ra != 15) {
9262 t2 = load_reg(s, a->ra);
9263 tcg_gen_add_i32(t1, t1, t2);
9264 tcg_temp_free_i32(t2);
9265 }
9266 store_reg(s, a->rd, t1);
9267 return true;
9268}
9269
9270static bool op_bfx(DisasContext *s, arg_UBFX *a, bool u)
9271{
9272 TCGv_i32 tmp;
9273 int width = a->widthm1 + 1;
9274 int shift = a->lsb;
9275
9276 if (!ENABLE_ARCH_6T2) {
9277 return false;
9278 }
9279 if (shift + width > 32) {
9280 /* UNPREDICTABLE; we choose to UNDEF */
9281 unallocated_encoding(s);
9282 return true;
9283 }
9284
9285 tmp = load_reg(s, a->rn);
9286 if (u) {
9287 tcg_gen_extract_i32(tmp, tmp, shift, width);
9288 } else {
9289 tcg_gen_sextract_i32(tmp, tmp, shift, width);
9290 }
9291 store_reg(s, a->rd, tmp);
9292 return true;
9293}
9294
9295static bool trans_SBFX(DisasContext *s, arg_SBFX *a)
9296{
9297 return op_bfx(s, a, false);
9298}
9299
9300static bool trans_UBFX(DisasContext *s, arg_UBFX *a)
9301{
9302 return op_bfx(s, a, true);
9303}
9304
9305static bool trans_BFCI(DisasContext *s, arg_BFCI *a)
9306{
9307 TCGv_i32 tmp;
9308 int msb = a->msb, lsb = a->lsb;
9309 int width;
9310
9311 if (!ENABLE_ARCH_6T2) {
9312 return false;
9313 }
9314 if (msb < lsb) {
9315 /* UNPREDICTABLE; we choose to UNDEF */
9316 unallocated_encoding(s);
9317 return true;
9318 }
9319
9320 width = msb + 1 - lsb;
9321 if (a->rn == 15) {
9322 /* BFC */
9323 tmp = tcg_const_i32(0);
9324 } else {
9325 /* BFI */
9326 tmp = load_reg(s, a->rn);
9327 }
9328 if (width != 32) {
9329 TCGv_i32 tmp2 = load_reg(s, a->rd);
9330 tcg_gen_deposit_i32(tmp, tmp2, tmp, lsb, width);
9331 tcg_temp_free_i32(tmp2);
9332 }
9333 store_reg(s, a->rd, tmp);
9334 return true;
9335}
9336
9337static bool trans_UDF(DisasContext *s, arg_UDF *a)
9338{
9339 unallocated_encoding(s);
9340 return true;
9341}
9342
adf1a566
RH
9343/*
9344 * Parallel addition and subtraction
9345 */
9346
9347static bool op_par_addsub(DisasContext *s, arg_rrr *a,
9348 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32))
9349{
9350 TCGv_i32 t0, t1;
9351
9352 if (s->thumb
9353 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
9354 : !ENABLE_ARCH_6) {
9355 return false;
9356 }
9357
9358 t0 = load_reg(s, a->rn);
9359 t1 = load_reg(s, a->rm);
9360
9361 gen(t0, t0, t1);
9362
9363 tcg_temp_free_i32(t1);
9364 store_reg(s, a->rd, t0);
9365 return true;
9366}
9367
9368static bool op_par_addsub_ge(DisasContext *s, arg_rrr *a,
9369 void (*gen)(TCGv_i32, TCGv_i32,
9370 TCGv_i32, TCGv_ptr))
9371{
9372 TCGv_i32 t0, t1;
9373 TCGv_ptr ge;
9374
9375 if (s->thumb
9376 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
9377 : !ENABLE_ARCH_6) {
9378 return false;
9379 }
9380
9381 t0 = load_reg(s, a->rn);
9382 t1 = load_reg(s, a->rm);
9383
9384 ge = tcg_temp_new_ptr();
9385 tcg_gen_addi_ptr(ge, cpu_env, offsetof(CPUARMState, GE));
9386 gen(t0, t0, t1, ge);
9387
9388 tcg_temp_free_ptr(ge);
9389 tcg_temp_free_i32(t1);
9390 store_reg(s, a->rd, t0);
9391 return true;
9392}
9393
9394#define DO_PAR_ADDSUB(NAME, helper) \
9395static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
9396{ \
9397 return op_par_addsub(s, a, helper); \
9398}
9399
9400#define DO_PAR_ADDSUB_GE(NAME, helper) \
9401static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
9402{ \
9403 return op_par_addsub_ge(s, a, helper); \
9404}
9405
9406DO_PAR_ADDSUB_GE(SADD16, gen_helper_sadd16)
9407DO_PAR_ADDSUB_GE(SASX, gen_helper_saddsubx)
9408DO_PAR_ADDSUB_GE(SSAX, gen_helper_ssubaddx)
9409DO_PAR_ADDSUB_GE(SSUB16, gen_helper_ssub16)
9410DO_PAR_ADDSUB_GE(SADD8, gen_helper_sadd8)
9411DO_PAR_ADDSUB_GE(SSUB8, gen_helper_ssub8)
9412
9413DO_PAR_ADDSUB_GE(UADD16, gen_helper_uadd16)
9414DO_PAR_ADDSUB_GE(UASX, gen_helper_uaddsubx)
9415DO_PAR_ADDSUB_GE(USAX, gen_helper_usubaddx)
9416DO_PAR_ADDSUB_GE(USUB16, gen_helper_usub16)
9417DO_PAR_ADDSUB_GE(UADD8, gen_helper_uadd8)
9418DO_PAR_ADDSUB_GE(USUB8, gen_helper_usub8)
9419
9420DO_PAR_ADDSUB(QADD16, gen_helper_qadd16)
9421DO_PAR_ADDSUB(QASX, gen_helper_qaddsubx)
9422DO_PAR_ADDSUB(QSAX, gen_helper_qsubaddx)
9423DO_PAR_ADDSUB(QSUB16, gen_helper_qsub16)
9424DO_PAR_ADDSUB(QADD8, gen_helper_qadd8)
9425DO_PAR_ADDSUB(QSUB8, gen_helper_qsub8)
9426
9427DO_PAR_ADDSUB(UQADD16, gen_helper_uqadd16)
9428DO_PAR_ADDSUB(UQASX, gen_helper_uqaddsubx)
9429DO_PAR_ADDSUB(UQSAX, gen_helper_uqsubaddx)
9430DO_PAR_ADDSUB(UQSUB16, gen_helper_uqsub16)
9431DO_PAR_ADDSUB(UQADD8, gen_helper_uqadd8)
9432DO_PAR_ADDSUB(UQSUB8, gen_helper_uqsub8)
9433
9434DO_PAR_ADDSUB(SHADD16, gen_helper_shadd16)
9435DO_PAR_ADDSUB(SHASX, gen_helper_shaddsubx)
9436DO_PAR_ADDSUB(SHSAX, gen_helper_shsubaddx)
9437DO_PAR_ADDSUB(SHSUB16, gen_helper_shsub16)
9438DO_PAR_ADDSUB(SHADD8, gen_helper_shadd8)
9439DO_PAR_ADDSUB(SHSUB8, gen_helper_shsub8)
9440
9441DO_PAR_ADDSUB(UHADD16, gen_helper_uhadd16)
9442DO_PAR_ADDSUB(UHASX, gen_helper_uhaddsubx)
9443DO_PAR_ADDSUB(UHSAX, gen_helper_uhsubaddx)
9444DO_PAR_ADDSUB(UHSUB16, gen_helper_uhsub16)
9445DO_PAR_ADDSUB(UHADD8, gen_helper_uhadd8)
9446DO_PAR_ADDSUB(UHSUB8, gen_helper_uhsub8)
9447
9448#undef DO_PAR_ADDSUB
9449#undef DO_PAR_ADDSUB_GE
9450
46497f6a
RH
9451/*
9452 * Packing, unpacking, saturation, and reversal
9453 */
9454
9455static bool trans_PKH(DisasContext *s, arg_PKH *a)
9456{
9457 TCGv_i32 tn, tm;
9458 int shift = a->imm;
9459
9460 if (s->thumb
9461 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
9462 : !ENABLE_ARCH_6) {
9463 return false;
9464 }
9465
9466 tn = load_reg(s, a->rn);
9467 tm = load_reg(s, a->rm);
9468 if (a->tb) {
9469 /* PKHTB */
9470 if (shift == 0) {
9471 shift = 31;
9472 }
9473 tcg_gen_sari_i32(tm, tm, shift);
9474 tcg_gen_deposit_i32(tn, tn, tm, 0, 16);
9475 } else {
9476 /* PKHBT */
9477 tcg_gen_shli_i32(tm, tm, shift);
9478 tcg_gen_deposit_i32(tn, tm, tn, 0, 16);
9479 }
9480 tcg_temp_free_i32(tm);
9481 store_reg(s, a->rd, tn);
9482 return true;
9483}
9484
9485static bool op_sat(DisasContext *s, arg_sat *a,
9486 void (*gen)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32))
9487{
9488 TCGv_i32 tmp, satimm;
9489 int shift = a->imm;
9490
9491 if (!ENABLE_ARCH_6) {
9492 return false;
9493 }
9494
9495 tmp = load_reg(s, a->rn);
9496 if (a->sh) {
9497 tcg_gen_sari_i32(tmp, tmp, shift ? shift : 31);
9498 } else {
9499 tcg_gen_shli_i32(tmp, tmp, shift);
9500 }
9501
9502 satimm = tcg_const_i32(a->satimm);
9503 gen(tmp, cpu_env, tmp, satimm);
9504 tcg_temp_free_i32(satimm);
9505
9506 store_reg(s, a->rd, tmp);
9507 return true;
9508}
9509
9510static bool trans_SSAT(DisasContext *s, arg_sat *a)
9511{
9512 return op_sat(s, a, gen_helper_ssat);
9513}
9514
9515static bool trans_USAT(DisasContext *s, arg_sat *a)
9516{
9517 return op_sat(s, a, gen_helper_usat);
9518}
9519
9520static bool trans_SSAT16(DisasContext *s, arg_sat *a)
9521{
9522 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9523 return false;
9524 }
9525 return op_sat(s, a, gen_helper_ssat16);
9526}
9527
9528static bool trans_USAT16(DisasContext *s, arg_sat *a)
9529{
9530 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9531 return false;
9532 }
9533 return op_sat(s, a, gen_helper_usat16);
9534}
9535
9536static bool op_xta(DisasContext *s, arg_rrr_rot *a,
9537 void (*gen_extract)(TCGv_i32, TCGv_i32),
9538 void (*gen_add)(TCGv_i32, TCGv_i32, TCGv_i32))
9539{
9540 TCGv_i32 tmp;
9541
9542 if (!ENABLE_ARCH_6) {
9543 return false;
9544 }
9545
9546 tmp = load_reg(s, a->rm);
9547 /*
9548 * TODO: In many cases we could do a shift instead of a rotate.
9549 * Combined with a simple extend, that becomes an extract.
9550 */
9551 tcg_gen_rotri_i32(tmp, tmp, a->rot * 8);
9552 gen_extract(tmp, tmp);
9553
9554 if (a->rn != 15) {
9555 TCGv_i32 tmp2 = load_reg(s, a->rn);
9556 gen_add(tmp, tmp, tmp2);
9557 tcg_temp_free_i32(tmp2);
9558 }
9559 store_reg(s, a->rd, tmp);
9560 return true;
9561}
9562
9563static bool trans_SXTAB(DisasContext *s, arg_rrr_rot *a)
9564{
9565 return op_xta(s, a, tcg_gen_ext8s_i32, tcg_gen_add_i32);
9566}
9567
9568static bool trans_SXTAH(DisasContext *s, arg_rrr_rot *a)
9569{
9570 return op_xta(s, a, tcg_gen_ext16s_i32, tcg_gen_add_i32);
9571}
9572
9573static bool trans_SXTAB16(DisasContext *s, arg_rrr_rot *a)
9574{
9575 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9576 return false;
9577 }
9578 return op_xta(s, a, gen_helper_sxtb16, gen_add16);
9579}
9580
9581static bool trans_UXTAB(DisasContext *s, arg_rrr_rot *a)
9582{
9583 return op_xta(s, a, tcg_gen_ext8u_i32, tcg_gen_add_i32);
9584}
9585
9586static bool trans_UXTAH(DisasContext *s, arg_rrr_rot *a)
9587{
9588 return op_xta(s, a, tcg_gen_ext16u_i32, tcg_gen_add_i32);
9589}
9590
9591static bool trans_UXTAB16(DisasContext *s, arg_rrr_rot *a)
9592{
9593 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9594 return false;
9595 }
9596 return op_xta(s, a, gen_helper_uxtb16, gen_add16);
9597}
9598
9599static bool trans_SEL(DisasContext *s, arg_rrr *a)
9600{
9601 TCGv_i32 t1, t2, t3;
9602
9603 if (s->thumb
9604 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
9605 : !ENABLE_ARCH_6) {
9606 return false;
9607 }
9608
9609 t1 = load_reg(s, a->rn);
9610 t2 = load_reg(s, a->rm);
9611 t3 = tcg_temp_new_i32();
9612 tcg_gen_ld_i32(t3, cpu_env, offsetof(CPUARMState, GE));
9613 gen_helper_sel_flags(t1, t3, t1, t2);
9614 tcg_temp_free_i32(t3);
9615 tcg_temp_free_i32(t2);
9616 store_reg(s, a->rd, t1);
9617 return true;
9618}
9619
9620static bool op_rr(DisasContext *s, arg_rr *a,
9621 void (*gen)(TCGv_i32, TCGv_i32))
9622{
9623 TCGv_i32 tmp;
9624
9625 tmp = load_reg(s, a->rm);
9626 gen(tmp, tmp);
9627 store_reg(s, a->rd, tmp);
9628 return true;
9629}
9630
9631static bool trans_REV(DisasContext *s, arg_rr *a)
9632{
9633 if (!ENABLE_ARCH_6) {
9634 return false;
9635 }
9636 return op_rr(s, a, tcg_gen_bswap32_i32);
9637}
9638
9639static bool trans_REV16(DisasContext *s, arg_rr *a)
9640{
9641 if (!ENABLE_ARCH_6) {
9642 return false;
9643 }
9644 return op_rr(s, a, gen_rev16);
9645}
9646
9647static bool trans_REVSH(DisasContext *s, arg_rr *a)
9648{
9649 if (!ENABLE_ARCH_6) {
9650 return false;
9651 }
9652 return op_rr(s, a, gen_revsh);
9653}
9654
9655static bool trans_RBIT(DisasContext *s, arg_rr *a)
9656{
9657 if (!ENABLE_ARCH_6T2) {
9658 return false;
9659 }
9660 return op_rr(s, a, gen_helper_rbit);
9661}
9662
2c7c4e09
RH
9663/*
9664 * Signed multiply, signed and unsigned divide
9665 */
9666
9667static bool op_smlad(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
9668{
9669 TCGv_i32 t1, t2;
9670
9671 if (!ENABLE_ARCH_6) {
9672 return false;
9673 }
9674
9675 t1 = load_reg(s, a->rn);
9676 t2 = load_reg(s, a->rm);
9677 if (m_swap) {
9678 gen_swap_half(t2);
9679 }
9680 gen_smul_dual(t1, t2);
9681
9682 if (sub) {
9683 /* This subtraction cannot overflow. */
9684 tcg_gen_sub_i32(t1, t1, t2);
9685 } else {
9686 /*
9687 * This addition cannot overflow 32 bits; however it may
9688 * overflow considered as a signed operation, in which case
9689 * we must set the Q flag.
9690 */
9691 gen_helper_add_setq(t1, cpu_env, t1, t2);
9692 }
9693 tcg_temp_free_i32(t2);
9694
9695 if (a->ra != 15) {
9696 t2 = load_reg(s, a->ra);
9697 gen_helper_add_setq(t1, cpu_env, t1, t2);
9698 tcg_temp_free_i32(t2);
9699 }
9700 store_reg(s, a->rd, t1);
9701 return true;
9702}
9703
9704static bool trans_SMLAD(DisasContext *s, arg_rrrr *a)
9705{
9706 return op_smlad(s, a, false, false);
9707}
9708
9709static bool trans_SMLADX(DisasContext *s, arg_rrrr *a)
9710{
9711 return op_smlad(s, a, true, false);
9712}
9713
9714static bool trans_SMLSD(DisasContext *s, arg_rrrr *a)
9715{
9716 return op_smlad(s, a, false, true);
9717}
9718
9719static bool trans_SMLSDX(DisasContext *s, arg_rrrr *a)
9720{
9721 return op_smlad(s, a, true, true);
9722}
9723
9724static bool op_smlald(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
9725{
9726 TCGv_i32 t1, t2;
9727 TCGv_i64 l1, l2;
9728
9729 if (!ENABLE_ARCH_6) {
9730 return false;
9731 }
9732
9733 t1 = load_reg(s, a->rn);
9734 t2 = load_reg(s, a->rm);
9735 if (m_swap) {
9736 gen_swap_half(t2);
9737 }
9738 gen_smul_dual(t1, t2);
9739
9740 l1 = tcg_temp_new_i64();
9741 l2 = tcg_temp_new_i64();
9742 tcg_gen_ext_i32_i64(l1, t1);
9743 tcg_gen_ext_i32_i64(l2, t2);
9744 tcg_temp_free_i32(t1);
9745 tcg_temp_free_i32(t2);
9746
9747 if (sub) {
9748 tcg_gen_sub_i64(l1, l1, l2);
9749 } else {
9750 tcg_gen_add_i64(l1, l1, l2);
9751 }
9752 tcg_temp_free_i64(l2);
9753
9754 gen_addq(s, l1, a->ra, a->rd);
9755 gen_storeq_reg(s, a->ra, a->rd, l1);
9756 tcg_temp_free_i64(l1);
9757 return true;
9758}
9759
9760static bool trans_SMLALD(DisasContext *s, arg_rrrr *a)
9761{
9762 return op_smlald(s, a, false, false);
9763}
9764
9765static bool trans_SMLALDX(DisasContext *s, arg_rrrr *a)
9766{
9767 return op_smlald(s, a, true, false);
9768}
9769
9770static bool trans_SMLSLD(DisasContext *s, arg_rrrr *a)
9771{
9772 return op_smlald(s, a, false, true);
9773}
9774
9775static bool trans_SMLSLDX(DisasContext *s, arg_rrrr *a)
9776{
9777 return op_smlald(s, a, true, true);
9778}
9779
9780static bool op_smmla(DisasContext *s, arg_rrrr *a, bool round, bool sub)
9781{
9782 TCGv_i32 t1, t2;
9783
9784 if (s->thumb
9785 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
9786 : !ENABLE_ARCH_6) {
9787 return false;
9788 }
9789
9790 t1 = load_reg(s, a->rn);
9791 t2 = load_reg(s, a->rm);
9792 tcg_gen_muls2_i32(t2, t1, t1, t2);
9793
9794 if (a->ra != 15) {
9795 TCGv_i32 t3 = load_reg(s, a->ra);
9796 if (sub) {
9797 /*
9798 * For SMMLS, we need a 64-bit subtract. Borrow caused by
9799 * a non-zero multiplicand lowpart, and the correct result
9800 * lowpart for rounding.
9801 */
9802 TCGv_i32 zero = tcg_const_i32(0);
9803 tcg_gen_sub2_i32(t2, t1, zero, t3, t2, t1);
9804 tcg_temp_free_i32(zero);
9805 } else {
9806 tcg_gen_add_i32(t1, t1, t3);
9807 }
9808 tcg_temp_free_i32(t3);
9809 }
9810 if (round) {
9811 /*
9812 * Adding 0x80000000 to the 64-bit quantity means that we have
9813 * carry in to the high word when the low word has the msb set.
9814 */
9815 tcg_gen_shri_i32(t2, t2, 31);
9816 tcg_gen_add_i32(t1, t1, t2);
9817 }
9818 tcg_temp_free_i32(t2);
9819 store_reg(s, a->rd, t1);
9820 return true;
9821}
9822
9823static bool trans_SMMLA(DisasContext *s, arg_rrrr *a)
9824{
9825 return op_smmla(s, a, false, false);
9826}
9827
9828static bool trans_SMMLAR(DisasContext *s, arg_rrrr *a)
9829{
9830 return op_smmla(s, a, true, false);
9831}
9832
9833static bool trans_SMMLS(DisasContext *s, arg_rrrr *a)
9834{
9835 return op_smmla(s, a, false, true);
9836}
9837
9838static bool trans_SMMLSR(DisasContext *s, arg_rrrr *a)
9839{
9840 return op_smmla(s, a, true, true);
9841}
9842
9843static bool op_div(DisasContext *s, arg_rrr *a, bool u)
9844{
9845 TCGv_i32 t1, t2;
9846
9847 if (s->thumb
9848 ? !dc_isar_feature(thumb_div, s)
9849 : !dc_isar_feature(arm_div, s)) {
9850 return false;
9851 }
9852
9853 t1 = load_reg(s, a->rn);
9854 t2 = load_reg(s, a->rm);
9855 if (u) {
9856 gen_helper_udiv(t1, t1, t2);
9857 } else {
9858 gen_helper_sdiv(t1, t1, t2);
9859 }
9860 tcg_temp_free_i32(t2);
9861 store_reg(s, a->rd, t1);
9862 return true;
9863}
9864
9865static bool trans_SDIV(DisasContext *s, arg_rrr *a)
9866{
9867 return op_div(s, a, false);
9868}
9869
9870static bool trans_UDIV(DisasContext *s, arg_rrr *a)
9871{
9872 return op_div(s, a, true);
9873}
9874
c5c426d4
RH
9875/*
9876 * Block data transfer
9877 */
9878
9879static TCGv_i32 op_addr_block_pre(DisasContext *s, arg_ldst_block *a, int n)
9880{
9881 TCGv_i32 addr = load_reg(s, a->rn);
9882
9883 if (a->b) {
9884 if (a->i) {
9885 /* pre increment */
9886 tcg_gen_addi_i32(addr, addr, 4);
9887 } else {
9888 /* pre decrement */
9889 tcg_gen_addi_i32(addr, addr, -(n * 4));
9890 }
9891 } else if (!a->i && n != 1) {
9892 /* post decrement */
9893 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
9894 }
9895
9896 if (s->v8m_stackcheck && a->rn == 13 && a->w) {
9897 /*
9898 * If the writeback is incrementing SP rather than
9899 * decrementing it, and the initial SP is below the
9900 * stack limit but the final written-back SP would
9901 * be above, then then we must not perform any memory
9902 * accesses, but it is IMPDEF whether we generate
9903 * an exception. We choose to do so in this case.
9904 * At this point 'addr' is the lowest address, so
9905 * either the original SP (if incrementing) or our
9906 * final SP (if decrementing), so that's what we check.
9907 */
9908 gen_helper_v8m_stackcheck(cpu_env, addr);
9909 }
9910
9911 return addr;
9912}
9913
9914static void op_addr_block_post(DisasContext *s, arg_ldst_block *a,
9915 TCGv_i32 addr, int n)
9916{
9917 if (a->w) {
9918 /* write back */
9919 if (!a->b) {
9920 if (a->i) {
9921 /* post increment */
9922 tcg_gen_addi_i32(addr, addr, 4);
9923 } else {
9924 /* post decrement */
9925 tcg_gen_addi_i32(addr, addr, -(n * 4));
9926 }
9927 } else if (!a->i && n != 1) {
9928 /* pre decrement */
9929 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
9930 }
9931 store_reg(s, a->rn, addr);
9932 } else {
9933 tcg_temp_free_i32(addr);
9934 }
9935}
9936
4b222545 9937static bool op_stm(DisasContext *s, arg_ldst_block *a, int min_n)
c5c426d4
RH
9938{
9939 int i, j, n, list, mem_idx;
9940 bool user = a->u;
9941 TCGv_i32 addr, tmp, tmp2;
9942
9943 if (user) {
9944 /* STM (user) */
9945 if (IS_USER(s)) {
9946 /* Only usable in supervisor mode. */
9947 unallocated_encoding(s);
9948 return true;
9949 }
9950 }
9951
9952 list = a->list;
9953 n = ctpop16(list);
b0e382b8 9954 if (n < min_n || a->rn == 15) {
4b222545
RH
9955 unallocated_encoding(s);
9956 return true;
9957 }
c5c426d4
RH
9958
9959 addr = op_addr_block_pre(s, a, n);
9960 mem_idx = get_mem_index(s);
9961
9962 for (i = j = 0; i < 16; i++) {
9963 if (!(list & (1 << i))) {
9964 continue;
9965 }
9966
9967 if (user && i != 15) {
9968 tmp = tcg_temp_new_i32();
9969 tmp2 = tcg_const_i32(i);
9970 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
9971 tcg_temp_free_i32(tmp2);
9972 } else {
9973 tmp = load_reg(s, i);
9974 }
9975 gen_aa32_st32(s, tmp, addr, mem_idx);
9976 tcg_temp_free_i32(tmp);
9977
9978 /* No need to add after the last transfer. */
9979 if (++j != n) {
9980 tcg_gen_addi_i32(addr, addr, 4);
9981 }
9982 }
9983
9984 op_addr_block_post(s, a, addr, n);
9985 return true;
9986}
9987
9988static bool trans_STM(DisasContext *s, arg_ldst_block *a)
9989{
4b222545
RH
9990 /* BitCount(list) < 1 is UNPREDICTABLE */
9991 return op_stm(s, a, 1);
c5c426d4
RH
9992}
9993
9994static bool trans_STM_t32(DisasContext *s, arg_ldst_block *a)
9995{
9996 /* Writeback register in register list is UNPREDICTABLE for T32. */
9997 if (a->w && (a->list & (1 << a->rn))) {
9998 unallocated_encoding(s);
9999 return true;
10000 }
4b222545
RH
10001 /* BitCount(list) < 2 is UNPREDICTABLE */
10002 return op_stm(s, a, 2);
c5c426d4
RH
10003}
10004
4b222545 10005static bool do_ldm(DisasContext *s, arg_ldst_block *a, int min_n)
c5c426d4
RH
10006{
10007 int i, j, n, list, mem_idx;
10008 bool loaded_base;
10009 bool user = a->u;
10010 bool exc_return = false;
10011 TCGv_i32 addr, tmp, tmp2, loaded_var;
10012
10013 if (user) {
10014 /* LDM (user), LDM (exception return) */
10015 if (IS_USER(s)) {
10016 /* Only usable in supervisor mode. */
10017 unallocated_encoding(s);
10018 return true;
10019 }
10020 if (extract32(a->list, 15, 1)) {
10021 exc_return = true;
10022 user = false;
10023 } else {
10024 /* LDM (user) does not allow writeback. */
10025 if (a->w) {
10026 unallocated_encoding(s);
10027 return true;
10028 }
10029 }
10030 }
10031
10032 list = a->list;
10033 n = ctpop16(list);
b0e382b8 10034 if (n < min_n || a->rn == 15) {
4b222545
RH
10035 unallocated_encoding(s);
10036 return true;
10037 }
c5c426d4
RH
10038
10039 addr = op_addr_block_pre(s, a, n);
10040 mem_idx = get_mem_index(s);
10041 loaded_base = false;
10042 loaded_var = NULL;
10043
10044 for (i = j = 0; i < 16; i++) {
10045 if (!(list & (1 << i))) {
10046 continue;
10047 }
10048
10049 tmp = tcg_temp_new_i32();
10050 gen_aa32_ld32u(s, tmp, addr, mem_idx);
10051 if (user) {
10052 tmp2 = tcg_const_i32(i);
10053 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
10054 tcg_temp_free_i32(tmp2);
10055 tcg_temp_free_i32(tmp);
10056 } else if (i == a->rn) {
10057 loaded_var = tmp;
10058 loaded_base = true;
10059 } else if (i == 15 && exc_return) {
10060 store_pc_exc_ret(s, tmp);
10061 } else {
10062 store_reg_from_load(s, i, tmp);
10063 }
10064
10065 /* No need to add after the last transfer. */
10066 if (++j != n) {
10067 tcg_gen_addi_i32(addr, addr, 4);
10068 }
10069 }
10070
10071 op_addr_block_post(s, a, addr, n);
10072
10073 if (loaded_base) {
b0e382b8 10074 /* Note that we reject base == pc above. */
c5c426d4
RH
10075 store_reg(s, a->rn, loaded_var);
10076 }
10077
10078 if (exc_return) {
10079 /* Restore CPSR from SPSR. */
10080 tmp = load_cpu_field(spsr);
10081 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
10082 gen_io_start();
10083 }
10084 gen_helper_cpsr_write_eret(cpu_env, tmp);
10085 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
10086 gen_io_end();
10087 }
10088 tcg_temp_free_i32(tmp);
10089 /* Must exit loop to check un-masked IRQs */
10090 s->base.is_jmp = DISAS_EXIT;
10091 }
10092 return true;
10093}
10094
10095static bool trans_LDM_a32(DisasContext *s, arg_ldst_block *a)
10096{
3949f467
RH
10097 /*
10098 * Writeback register in register list is UNPREDICTABLE
10099 * for ArchVersion() >= 7. Prior to v7, A32 would write
10100 * an UNKNOWN value to the base register.
10101 */
10102 if (ENABLE_ARCH_7 && a->w && (a->list & (1 << a->rn))) {
10103 unallocated_encoding(s);
10104 return true;
10105 }
4b222545
RH
10106 /* BitCount(list) < 1 is UNPREDICTABLE */
10107 return do_ldm(s, a, 1);
c5c426d4
RH
10108}
10109
10110static bool trans_LDM_t32(DisasContext *s, arg_ldst_block *a)
10111{
10112 /* Writeback register in register list is UNPREDICTABLE for T32. */
10113 if (a->w && (a->list & (1 << a->rn))) {
10114 unallocated_encoding(s);
10115 return true;
10116 }
4b222545
RH
10117 /* BitCount(list) < 2 is UNPREDICTABLE */
10118 return do_ldm(s, a, 2);
c5c426d4
RH
10119}
10120
6e8514ba
RH
10121static bool trans_LDM_t16(DisasContext *s, arg_ldst_block *a)
10122{
10123 /* Writeback is conditional on the base register not being loaded. */
10124 a->w = !(a->list & (1 << a->rn));
10125 /* BitCount(list) < 1 is UNPREDICTABLE */
10126 return do_ldm(s, a, 1);
10127}
10128
360144f3
RH
10129/*
10130 * Branch, branch with link
10131 */
10132
10133static bool trans_B(DisasContext *s, arg_i *a)
10134{
10135 gen_jmp(s, read_pc(s) + a->imm);
10136 return true;
10137}
10138
10139static bool trans_B_cond_thumb(DisasContext *s, arg_ci *a)
10140{
10141 /* This has cond from encoding, required to be outside IT block. */
10142 if (a->cond >= 0xe) {
10143 return false;
10144 }
10145 if (s->condexec_mask) {
10146 unallocated_encoding(s);
10147 return true;
10148 }
10149 arm_skip_unless(s, a->cond);
10150 gen_jmp(s, read_pc(s) + a->imm);
10151 return true;
10152}
10153
10154static bool trans_BL(DisasContext *s, arg_i *a)
10155{
10156 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
10157 gen_jmp(s, read_pc(s) + a->imm);
10158 return true;
10159}
10160
10161static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
10162{
10163 /* For A32, ARCH(5) is checked near the start of the uncond block. */
10164 if (s->thumb && (a->imm & 2)) {
10165 return false;
10166 }
10167 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
10168 gen_bx_im(s, (read_pc(s) & ~3) + a->imm + !s->thumb);
10169 return true;
10170}
10171
808092bb
RH
10172static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
10173{
10174 TCGv_i32 addr, tmp;
10175
10176 tmp = load_reg(s, a->rm);
10177 if (half) {
10178 tcg_gen_add_i32(tmp, tmp, tmp);
10179 }
10180 addr = load_reg(s, a->rn);
10181 tcg_gen_add_i32(addr, addr, tmp);
10182
10183 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
10184 half ? MO_UW | s->be_data : MO_UB);
10185 tcg_temp_free_i32(addr);
10186
10187 tcg_gen_add_i32(tmp, tmp, tmp);
10188 tcg_gen_addi_i32(tmp, tmp, read_pc(s));
10189 store_reg(s, 15, tmp);
10190 return true;
10191}
10192
10193static bool trans_TBB(DisasContext *s, arg_tbranch *a)
10194{
10195 return op_tbranch(s, a, false);
10196}
10197
10198static bool trans_TBH(DisasContext *s, arg_tbranch *a)
10199{
10200 return op_tbranch(s, a, true);
10201}
10202
542f5188
RH
10203/*
10204 * Supervisor call
10205 */
10206
10207static bool trans_SVC(DisasContext *s, arg_SVC *a)
10208{
10209 gen_set_pc_im(s, s->base.pc_next);
10210 s->svc_imm = a->imm;
10211 s->base.is_jmp = DISAS_SWI;
10212 return true;
10213}
10214
885782a7
RH
10215/*
10216 * Unconditional system instructions
10217 */
10218
10219static bool trans_RFE(DisasContext *s, arg_RFE *a)
10220{
10221 static const int8_t pre_offset[4] = {
10222 /* DA */ -4, /* IA */ 0, /* DB */ -8, /* IB */ 4
10223 };
10224 static const int8_t post_offset[4] = {
10225 /* DA */ -8, /* IA */ 4, /* DB */ -4, /* IB */ 0
10226 };
10227 TCGv_i32 addr, t1, t2;
10228
10229 if (!ENABLE_ARCH_6 || arm_dc_feature(s, ARM_FEATURE_M)) {
10230 return false;
10231 }
10232 if (IS_USER(s)) {
10233 unallocated_encoding(s);
10234 return true;
10235 }
10236
10237 addr = load_reg(s, a->rn);
10238 tcg_gen_addi_i32(addr, addr, pre_offset[a->pu]);
10239
10240 /* Load PC into tmp and CPSR into tmp2. */
10241 t1 = tcg_temp_new_i32();
10242 gen_aa32_ld32u(s, t1, addr, get_mem_index(s));
10243 tcg_gen_addi_i32(addr, addr, 4);
10244 t2 = tcg_temp_new_i32();
10245 gen_aa32_ld32u(s, t2, addr, get_mem_index(s));
10246
10247 if (a->w) {
10248 /* Base writeback. */
10249 tcg_gen_addi_i32(addr, addr, post_offset[a->pu]);
10250 store_reg(s, a->rn, addr);
10251 } else {
10252 tcg_temp_free_i32(addr);
10253 }
10254 gen_rfe(s, t1, t2);
10255 return true;
10256}
10257
10258static bool trans_SRS(DisasContext *s, arg_SRS *a)
10259{
10260 if (!ENABLE_ARCH_6 || arm_dc_feature(s, ARM_FEATURE_M)) {
10261 return false;
10262 }
10263 gen_srs(s, a->mode, a->pu, a->w);
10264 return true;
10265}
10266
52f83b9c
RH
10267static bool trans_CPS(DisasContext *s, arg_CPS *a)
10268{
10269 uint32_t mask, val;
10270
10271 if (arm_dc_feature(s, ARM_FEATURE_M)) {
10272 return false;
10273 }
10274 if (IS_USER(s)) {
10275 /* Implemented as NOP in user mode. */
10276 return true;
10277 }
10278 /* TODO: There are quite a lot of UNPREDICTABLE argument combinations. */
10279
10280 mask = val = 0;
10281 if (a->imod & 2) {
10282 if (a->A) {
10283 mask |= CPSR_A;
10284 }
10285 if (a->I) {
10286 mask |= CPSR_I;
10287 }
10288 if (a->F) {
10289 mask |= CPSR_F;
10290 }
10291 if (a->imod & 1) {
10292 val |= mask;
10293 }
10294 }
10295 if (a->M) {
10296 mask |= CPSR_M;
10297 val |= a->mode;
10298 }
10299 if (mask) {
10300 gen_set_psr_im(s, mask, 0, val);
10301 }
10302 return true;
10303}
10304
519b8471
RH
10305/*
10306 * Clear-Exclusive, Barriers
10307 */
10308
10309static bool trans_CLREX(DisasContext *s, arg_CLREX *a)
10310{
10311 if (s->thumb
10312 ? !ENABLE_ARCH_7 && !arm_dc_feature(s, ARM_FEATURE_M)
10313 : !ENABLE_ARCH_6K) {
10314 return false;
10315 }
10316 gen_clrex(s);
10317 return true;
10318}
10319
10320static bool trans_DSB(DisasContext *s, arg_DSB *a)
10321{
10322 if (!ENABLE_ARCH_7 && !arm_dc_feature(s, ARM_FEATURE_M)) {
10323 return false;
10324 }
10325 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
10326 return true;
10327}
10328
10329static bool trans_DMB(DisasContext *s, arg_DMB *a)
10330{
10331 return trans_DSB(s, NULL);
10332}
10333
10334static bool trans_ISB(DisasContext *s, arg_ISB *a)
10335{
10336 if (!ENABLE_ARCH_7 && !arm_dc_feature(s, ARM_FEATURE_M)) {
10337 return false;
10338 }
10339 /*
10340 * We need to break the TB after this insn to execute
10341 * self-modifying code correctly and also to take
10342 * any pending interrupts immediately.
10343 */
10344 gen_goto_tb(s, 0, s->base.pc_next);
10345 return true;
10346}
10347
10348static bool trans_SB(DisasContext *s, arg_SB *a)
10349{
10350 if (!dc_isar_feature(aa32_sb, s)) {
10351 return false;
10352 }
10353 /*
10354 * TODO: There is no speculation barrier opcode
10355 * for TCG; MB and end the TB instead.
10356 */
10357 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
10358 gen_goto_tb(s, 0, s->base.pc_next);
10359 return true;
10360}
10361
48c04a5d
RH
10362static bool trans_SETEND(DisasContext *s, arg_SETEND *a)
10363{
10364 if (!ENABLE_ARCH_6) {
10365 return false;
10366 }
10367 if (a->E != (s->be_data == MO_BE)) {
10368 gen_helper_setend(cpu_env);
10369 s->base.is_jmp = DISAS_UPDATE;
10370 }
10371 return true;
10372}
10373
beb595f6
RH
10374/*
10375 * Preload instructions
10376 * All are nops, contingent on the appropriate arch level.
10377 */
10378
10379static bool trans_PLD(DisasContext *s, arg_PLD *a)
10380{
10381 return ENABLE_ARCH_5TE;
10382}
10383
10384static bool trans_PLDW(DisasContext *s, arg_PLD *a)
10385{
10386 return arm_dc_feature(s, ARM_FEATURE_V7MP);
10387}
10388
10389static bool trans_PLI(DisasContext *s, arg_PLD *a)
10390{
10391 return ENABLE_ARCH_7;
10392}
10393
51409b9e
RH
10394/*
10395 * Legacy decoder.
10396 */
10397
f4df2210 10398static void disas_arm_insn(DisasContext *s, unsigned int insn)
9ee6e8bb 10399{
590057d9 10400 unsigned int cond = insn >> 28;
9ee6e8bb 10401
e13886e3
PM
10402 /* M variants do not implement ARM mode; this must raise the INVSTATE
10403 * UsageFault exception.
10404 */
b53d8923 10405 if (arm_dc_feature(s, ARM_FEATURE_M)) {
a767fac8 10406 gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
e13886e3
PM
10407 default_exception_el(s));
10408 return;
b53d8923 10409 }
51409b9e
RH
10410
10411 if (cond == 0xf) {
be5e7a76
DES
10412 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
10413 * choose to UNDEF. In ARMv5 and above the space is used
10414 * for miscellaneous unconditional instructions.
10415 */
10416 ARCH(5);
10417
9ee6e8bb 10418 /* Unconditional instructions. */
51409b9e
RH
10419 if (disas_a32_uncond(s, insn)) {
10420 return;
10421 }
10422 /* fall back to legacy decoder */
10423
9ee6e8bb
PB
10424 if (((insn >> 25) & 7) == 1) {
10425 /* NEON Data processing. */
d614a513 10426 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
9ee6e8bb 10427 goto illegal_op;
d614a513 10428 }
9ee6e8bb 10429
7dcc1f89 10430 if (disas_neon_data_insn(s, insn)) {
9ee6e8bb 10431 goto illegal_op;
7dcc1f89 10432 }
9ee6e8bb
PB
10433 return;
10434 }
10435 if ((insn & 0x0f100000) == 0x04000000) {
10436 /* NEON load/store. */
d614a513 10437 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
9ee6e8bb 10438 goto illegal_op;
d614a513 10439 }
9ee6e8bb 10440
7dcc1f89 10441 if (disas_neon_ls_insn(s, insn)) {
9ee6e8bb 10442 goto illegal_op;
7dcc1f89 10443 }
9ee6e8bb
PB
10444 return;
10445 }
6a57f3eb
WN
10446 if ((insn & 0x0f000e10) == 0x0e000a00) {
10447 /* VFP. */
7dcc1f89 10448 if (disas_vfp_insn(s, insn)) {
6a57f3eb
WN
10449 goto illegal_op;
10450 }
10451 return;
10452 }
48c04a5d 10453 if ((insn & 0x0e000f00) == 0x0c000100) {
d614a513 10454 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
9ee6e8bb 10455 /* iWMMXt register transfer. */
c0f4af17 10456 if (extract32(s->c15_cpar, 1, 1)) {
7dcc1f89 10457 if (!disas_iwmmxt_insn(s, insn)) {
9ee6e8bb 10458 return;
c0f4af17
PM
10459 }
10460 }
9ee6e8bb 10461 }
8b7209fa
RH
10462 } else if ((insn & 0x0e000a00) == 0x0c000800
10463 && arm_dc_feature(s, ARM_FEATURE_V8)) {
10464 if (disas_neon_insn_3same_ext(s, insn)) {
10465 goto illegal_op;
10466 }
10467 return;
638808ff
RH
10468 } else if ((insn & 0x0f000a00) == 0x0e000800
10469 && arm_dc_feature(s, ARM_FEATURE_V8)) {
10470 if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
10471 goto illegal_op;
10472 }
10473 return;
9ee6e8bb
PB
10474 }
10475 goto illegal_op;
10476 }
10477 if (cond != 0xe) {
10478 /* if not always execute, we generate a conditional jump to
10479 next instruction */
c2d9644e 10480 arm_skip_unless(s, cond);
9ee6e8bb 10481 }
51409b9e
RH
10482
10483 if (disas_a32(s, insn)) {
10484 return;
10485 }
10486 /* fall back to legacy decoder */
10487
590057d9
RH
10488 switch ((insn >> 24) & 0xf) {
10489 case 0xc:
10490 case 0xd:
10491 case 0xe:
10492 if (((insn >> 8) & 0xe) == 10) {
10493 /* VFP. */
10494 if (disas_vfp_insn(s, insn)) {
9ee6e8bb 10495 goto illegal_op;
6a57f3eb 10496 }
590057d9
RH
10497 } else if (disas_coproc_insn(s, insn)) {
10498 /* Coprocessor. */
10499 goto illegal_op;
9ee6e8bb 10500 }
590057d9
RH
10501 break;
10502 default:
10503 illegal_op:
10504 unallocated_encoding(s);
10505 break;
9ee6e8bb
PB
10506 }
10507}
10508
331b1ca6 10509static bool thumb_insn_is_16bit(DisasContext *s, uint32_t pc, uint32_t insn)
296e5a0a 10510{
331b1ca6
RH
10511 /*
10512 * Return true if this is a 16 bit instruction. We must be precise
10513 * about this (matching the decode).
296e5a0a
PM
10514 */
10515 if ((insn >> 11) < 0x1d) {
10516 /* Definitely a 16-bit instruction */
10517 return true;
10518 }
10519
10520 /* Top five bits 0b11101 / 0b11110 / 0b11111 : this is the
10521 * first half of a 32-bit Thumb insn. Thumb-1 cores might
10522 * end up actually treating this as two 16-bit insns, though,
10523 * if it's half of a bl/blx pair that might span a page boundary.
10524 */
14120108
JS
10525 if (arm_dc_feature(s, ARM_FEATURE_THUMB2) ||
10526 arm_dc_feature(s, ARM_FEATURE_M)) {
296e5a0a
PM
10527 /* Thumb2 cores (including all M profile ones) always treat
10528 * 32-bit insns as 32-bit.
10529 */
10530 return false;
10531 }
10532
331b1ca6 10533 if ((insn >> 11) == 0x1e && pc - s->page_start < TARGET_PAGE_SIZE - 3) {
296e5a0a
PM
10534 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix, and the suffix
10535 * is not on the next page; we merge this into a 32-bit
10536 * insn.
10537 */
10538 return false;
10539 }
10540 /* 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF);
10541 * 0b1111_1xxx_xxxx_xxxx : BL suffix;
10542 * 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix on the end of a page
10543 * -- handle as single 16 bit insn
10544 */
10545 return true;
10546}
10547
2eea841c
PM
10548/* Translate a 32-bit thumb instruction. */
10549static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
9ee6e8bb 10550{
14120108
JS
10551 /*
10552 * ARMv6-M supports a limited subset of Thumb2 instructions.
10553 * Other Thumb1 architectures allow only 32-bit
10554 * combined BL/BLX prefix and suffix.
296e5a0a 10555 */
14120108
JS
10556 if (arm_dc_feature(s, ARM_FEATURE_M) &&
10557 !arm_dc_feature(s, ARM_FEATURE_V7)) {
10558 int i;
10559 bool found = false;
8297cb13
JS
10560 static const uint32_t armv6m_insn[] = {0xf3808000 /* msr */,
10561 0xf3b08040 /* dsb */,
10562 0xf3b08050 /* dmb */,
10563 0xf3b08060 /* isb */,
10564 0xf3e08000 /* mrs */,
10565 0xf000d000 /* bl */};
10566 static const uint32_t armv6m_mask[] = {0xffe0d000,
10567 0xfff0d0f0,
10568 0xfff0d0f0,
10569 0xfff0d0f0,
10570 0xffe0d000,
10571 0xf800d000};
14120108
JS
10572
10573 for (i = 0; i < ARRAY_SIZE(armv6m_insn); i++) {
10574 if ((insn & armv6m_mask[i]) == armv6m_insn[i]) {
10575 found = true;
10576 break;
10577 }
10578 }
10579 if (!found) {
10580 goto illegal_op;
10581 }
10582 } else if ((insn & 0xf800e800) != 0xf000e800) {
9ee6e8bb
PB
10583 ARCH(6T2);
10584 }
10585
51409b9e
RH
10586 if (disas_t32(s, insn)) {
10587 return;
10588 }
10589 /* fall back to legacy decoder */
10590
9ee6e8bb
PB
10591 switch ((insn >> 25) & 0xf) {
10592 case 0: case 1: case 2: case 3:
10593 /* 16-bit instructions. Should never happen. */
10594 abort();
9ee6e8bb
PB
10595 case 6: case 7: case 14: case 15:
10596 /* Coprocessor. */
7517748e 10597 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8859ba3c
PM
10598 /* 0b111x_11xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx */
10599 if (extract32(insn, 24, 2) == 3) {
10600 goto illegal_op; /* op0 = 0b11 : unallocated */
10601 }
10602
10603 /*
10604 * Decode VLLDM and VLSTM first: these are nonstandard because:
10605 * * if there is no FPU then these insns must NOP in
10606 * Secure state and UNDEF in Nonsecure state
10607 * * if there is an FPU then these insns do not have
10608 * the usual behaviour that disas_vfp_insn() provides of
10609 * being controlled by CPACR/NSACR enable bits or the
10610 * lazy-stacking logic.
7517748e 10611 */
b1e5336a
PM
10612 if (arm_dc_feature(s, ARM_FEATURE_V8) &&
10613 (insn & 0xffa00f00) == 0xec200a00) {
10614 /* 0b1110_1100_0x1x_xxxx_xxxx_1010_xxxx_xxxx
10615 * - VLLDM, VLSTM
10616 * We choose to UNDEF if the RAZ bits are non-zero.
10617 */
10618 if (!s->v8m_secure || (insn & 0x0040f0ff)) {
10619 goto illegal_op;
10620 }
019076b0
PM
10621
10622 if (arm_dc_feature(s, ARM_FEATURE_VFP)) {
f843e771 10623 uint32_t rn = (insn >> 16) & 0xf;
019076b0
PM
10624 TCGv_i32 fptr = load_reg(s, rn);
10625
10626 if (extract32(insn, 20, 1)) {
956fe143 10627 gen_helper_v7m_vlldm(cpu_env, fptr);
019076b0
PM
10628 } else {
10629 gen_helper_v7m_vlstm(cpu_env, fptr);
10630 }
10631 tcg_temp_free_i32(fptr);
10632
10633 /* End the TB, because we have updated FP control bits */
10634 s->base.is_jmp = DISAS_UPDATE;
10635 }
b1e5336a
PM
10636 break;
10637 }
8859ba3c
PM
10638 if (arm_dc_feature(s, ARM_FEATURE_VFP) &&
10639 ((insn >> 8) & 0xe) == 10) {
10640 /* FP, and the CPU supports it */
10641 if (disas_vfp_insn(s, insn)) {
10642 goto illegal_op;
10643 }
10644 break;
10645 }
10646
b1e5336a 10647 /* All other insns: NOCP */
a767fac8 10648 gen_exception_insn(s, s->pc_curr, EXCP_NOCP, syn_uncategorized(),
7517748e
PM
10649 default_exception_el(s));
10650 break;
10651 }
0052087e
RH
10652 if ((insn & 0xfe000a00) == 0xfc000800
10653 && arm_dc_feature(s, ARM_FEATURE_V8)) {
10654 /* The Thumb2 and ARM encodings are identical. */
10655 if (disas_neon_insn_3same_ext(s, insn)) {
10656 goto illegal_op;
10657 }
10658 } else if ((insn & 0xff000a00) == 0xfe000800
10659 && arm_dc_feature(s, ARM_FEATURE_V8)) {
10660 /* The Thumb2 and ARM encodings are identical. */
10661 if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
10662 goto illegal_op;
10663 }
10664 } else if (((insn >> 24) & 3) == 3) {
9ee6e8bb 10665 /* Translate into the equivalent ARM encoding. */
f06053e3 10666 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
7dcc1f89 10667 if (disas_neon_data_insn(s, insn)) {
9ee6e8bb 10668 goto illegal_op;
7dcc1f89 10669 }
6a57f3eb 10670 } else if (((insn >> 8) & 0xe) == 10) {
7dcc1f89 10671 if (disas_vfp_insn(s, insn)) {
6a57f3eb
WN
10672 goto illegal_op;
10673 }
9ee6e8bb
PB
10674 } else {
10675 if (insn & (1 << 28))
10676 goto illegal_op;
7dcc1f89 10677 if (disas_coproc_insn(s, insn)) {
9ee6e8bb 10678 goto illegal_op;
7dcc1f89 10679 }
9ee6e8bb
PB
10680 }
10681 break;
5e291fe1 10682 case 12:
9ee6e8bb 10683 if ((insn & 0x01100000) == 0x01000000) {
7dcc1f89 10684 if (disas_neon_ls_insn(s, insn)) {
c1713132 10685 goto illegal_op;
7dcc1f89 10686 }
9ee6e8bb
PB
10687 break;
10688 }
5e291fe1 10689 goto illegal_op;
9ee6e8bb 10690 default:
f843e771
RH
10691 illegal_op:
10692 unallocated_encoding(s);
2c0262af
FB
10693 }
10694}
10695
296e5a0a 10696static void disas_thumb_insn(DisasContext *s, uint32_t insn)
99c475ab 10697{
296e5a0a 10698 uint32_t val, op, rm, rn, rd, shift, cond;
99c475ab
FB
10699 int32_t offset;
10700 int i;
39d5492a
PM
10701 TCGv_i32 tmp;
10702 TCGv_i32 tmp2;
10703 TCGv_i32 addr;
99c475ab 10704
f97b454e
RH
10705 if (disas_t16(s, insn)) {
10706 return;
10707 }
10708 /* fall back to legacy decoder */
10709
99c475ab
FB
10710 switch (insn >> 12) {
10711 case 0: case 1:
396e467c 10712
99c475ab
FB
10713 rd = insn & 7;
10714 op = (insn >> 11) & 3;
10715 if (op == 3) {
a2d12f0f
PM
10716 /*
10717 * 0b0001_1xxx_xxxx_xxxx
10718 * - Add, subtract (three low registers)
10719 * - Add, subtract (two low registers and immediate)
c4d3095b 10720 * In decodetree.
a2d12f0f 10721 */
c4d3095b 10722 goto illegal_op;
99c475ab
FB
10723 } else {
10724 /* shift immediate */
10725 rm = (insn >> 3) & 7;
10726 shift = (insn >> 6) & 0x1f;
9a119ff6
PB
10727 tmp = load_reg(s, rm);
10728 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
10729 if (!s->condexec_mask)
10730 gen_logic_CC(tmp);
10731 store_reg(s, rd, tmp);
99c475ab
FB
10732 }
10733 break;
6c6d237a
RH
10734 case 2: case 3: /* add, sub, cmp, mov (reg, imm), in decodetree */
10735 goto illegal_op;
99c475ab
FB
10736 case 4:
10737 if (insn & (1 << 11)) {
10738 rd = (insn >> 8) & 7;
5899f386 10739 /* load pc-relative. Bit 1 of PC is ignored. */
16e0d823 10740 addr = add_reg_for_lit(s, 15, (insn & 0xff) * 4);
c40c8556 10741 tmp = tcg_temp_new_i32();
9bb6558a
PM
10742 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s),
10743 rd | ISSIs16Bit);
7d1b0095 10744 tcg_temp_free_i32(addr);
b0109805 10745 store_reg(s, rd, tmp);
99c475ab
FB
10746 break;
10747 }
99c475ab 10748
a2d12f0f 10749 /*
90aa0421
RH
10750 * - Data-processing (two low registers), in decodetree
10751 * - data processing extended, branch and exchange, in decodetree
a2d12f0f 10752 */
080c4ead 10753 goto illegal_op;
99c475ab 10754
07afd747
RH
10755 case 5: /* load/store register offset, in decodetree */
10756 case 6: /* load/store word immediate offset, in decodetree */
10757 case 7: /* load/store byte immediate offset, in decodetree */
10758 case 8: /* load/store halfword immediate offset, in decodetree */
10759 case 9: /* load/store from stack, in decodetree */
1cb13234 10760 case 10: /* add PC/SP (immediate), in decodetree */
6e8514ba 10761 case 12: /* load/store multiple, in decodetree */
d1d22917 10762 goto illegal_op;
99c475ab 10763
99c475ab
FB
10764 case 11:
10765 /* misc */
10766 op = (insn >> 8) & 0xf;
10767 switch (op) {
10768 case 0:
55203189
PM
10769 /*
10770 * 0b1011_0000_xxxx_xxxx
10771 * - ADD (SP plus immediate)
10772 * - SUB (SP minus immediate)
10773 */
b26eefb6 10774 tmp = load_reg(s, 13);
99c475ab
FB
10775 val = (insn & 0x7f) * 4;
10776 if (insn & (1 << 7))
6a0d8a1d 10777 val = -(int32_t)val;
b26eefb6 10778 tcg_gen_addi_i32(tmp, tmp, val);
55203189 10779 store_sp_checked(s, tmp);
99c475ab
FB
10780 break;
10781
9ee6e8bb
PB
10782 case 2: /* sign/zero extend. */
10783 ARCH(6);
10784 rd = insn & 7;
10785 rm = (insn >> 3) & 7;
b0109805 10786 tmp = load_reg(s, rm);
9ee6e8bb 10787 switch ((insn >> 6) & 3) {
b0109805
PB
10788 case 0: gen_sxth(tmp); break;
10789 case 1: gen_sxtb(tmp); break;
10790 case 2: gen_uxth(tmp); break;
10791 case 3: gen_uxtb(tmp); break;
9ee6e8bb 10792 }
b0109805 10793 store_reg(s, rd, tmp);
9ee6e8bb 10794 break;
99c475ab 10795 case 4: case 5: case 0xc: case 0xd:
aa369e5c
PM
10796 /*
10797 * 0b1011_x10x_xxxx_xxxx
10798 * - push/pop
10799 */
b0109805 10800 addr = load_reg(s, 13);
5899f386
FB
10801 if (insn & (1 << 8))
10802 offset = 4;
99c475ab 10803 else
5899f386
FB
10804 offset = 0;
10805 for (i = 0; i < 8; i++) {
10806 if (insn & (1 << i))
10807 offset += 4;
10808 }
10809 if ((insn & (1 << 11)) == 0) {
b0109805 10810 tcg_gen_addi_i32(addr, addr, -offset);
5899f386 10811 }
aa369e5c
PM
10812
10813 if (s->v8m_stackcheck) {
10814 /*
10815 * Here 'addr' is the lower of "old SP" and "new SP";
10816 * if this is a pop that starts below the limit and ends
10817 * above it, it is UNKNOWN whether the limit check triggers;
10818 * we choose to trigger.
10819 */
10820 gen_helper_v8m_stackcheck(cpu_env, addr);
10821 }
10822
99c475ab
FB
10823 for (i = 0; i < 8; i++) {
10824 if (insn & (1 << i)) {
10825 if (insn & (1 << 11)) {
10826 /* pop */
c40c8556 10827 tmp = tcg_temp_new_i32();
12dcc321 10828 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
b0109805 10829 store_reg(s, i, tmp);
99c475ab
FB
10830 } else {
10831 /* push */
b0109805 10832 tmp = load_reg(s, i);
12dcc321 10833 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
c40c8556 10834 tcg_temp_free_i32(tmp);
99c475ab 10835 }
5899f386 10836 /* advance to the next address. */
b0109805 10837 tcg_gen_addi_i32(addr, addr, 4);
99c475ab
FB
10838 }
10839 }
f764718d 10840 tmp = NULL;
99c475ab
FB
10841 if (insn & (1 << 8)) {
10842 if (insn & (1 << 11)) {
10843 /* pop pc */
c40c8556 10844 tmp = tcg_temp_new_i32();
12dcc321 10845 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
99c475ab
FB
10846 /* don't set the pc until the rest of the instruction
10847 has completed */
10848 } else {
10849 /* push lr */
b0109805 10850 tmp = load_reg(s, 14);
12dcc321 10851 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
c40c8556 10852 tcg_temp_free_i32(tmp);
99c475ab 10853 }
b0109805 10854 tcg_gen_addi_i32(addr, addr, 4);
99c475ab 10855 }
5899f386 10856 if ((insn & (1 << 11)) == 0) {
b0109805 10857 tcg_gen_addi_i32(addr, addr, -offset);
5899f386 10858 }
99c475ab 10859 /* write back the new stack pointer */
b0109805 10860 store_reg(s, 13, addr);
99c475ab 10861 /* set the new PC value */
be5e7a76 10862 if ((insn & 0x0900) == 0x0900) {
7dcc1f89 10863 store_reg_from_load(s, 15, tmp);
be5e7a76 10864 }
99c475ab
FB
10865 break;
10866
9ee6e8bb
PB
10867 case 1: case 3: case 9: case 11: /* czb */
10868 rm = insn & 7;
d9ba4830 10869 tmp = load_reg(s, rm);
c2d9644e 10870 arm_gen_condlabel(s);
9ee6e8bb 10871 if (insn & (1 << 11))
cb63669a 10872 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
9ee6e8bb 10873 else
cb63669a 10874 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
7d1b0095 10875 tcg_temp_free_i32(tmp);
9ee6e8bb 10876 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
fdbcf632 10877 gen_jmp(s, read_pc(s) + offset);
9ee6e8bb
PB
10878 break;
10879
10880 case 15: /* IT, nop-hint. */
10881 if ((insn & 0xf) == 0) {
10882 gen_nop_hint(s, (insn >> 4) & 0xf);
10883 break;
10884 }
5529de1e
PM
10885 /*
10886 * IT (If-Then)
10887 *
10888 * Combinations of firstcond and mask which set up an 0b1111
10889 * condition are UNPREDICTABLE; we take the CONSTRAINED
10890 * UNPREDICTABLE choice to treat 0b1111 the same as 0b1110,
10891 * i.e. both meaning "execute always".
10892 */
9ee6e8bb
PB
10893 s->condexec_cond = (insn >> 4) & 0xe;
10894 s->condexec_mask = insn & 0x1f;
10895 /* No actual code generated for this insn, just setup state. */
10896 break;
10897
06c949e6 10898 case 0xe: /* bkpt */
d4a2dc67
PM
10899 {
10900 int imm8 = extract32(insn, 0, 8);
be5e7a76 10901 ARCH(5);
06bcbda3 10902 gen_exception_bkpt_insn(s, syn_aa32_bkpt(imm8, true));
06c949e6 10903 break;
d4a2dc67 10904 }
06c949e6 10905
19a6e31c
PM
10906 case 0xa: /* rev, and hlt */
10907 {
10908 int op1 = extract32(insn, 6, 2);
10909
10910 if (op1 == 2) {
10911 /* HLT */
10912 int imm6 = extract32(insn, 0, 6);
10913
10914 gen_hlt(s, imm6);
10915 break;
10916 }
10917
10918 /* Otherwise this is rev */
9ee6e8bb
PB
10919 ARCH(6);
10920 rn = (insn >> 3) & 0x7;
10921 rd = insn & 0x7;
b0109805 10922 tmp = load_reg(s, rn);
19a6e31c 10923 switch (op1) {
66896cb8 10924 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
46497f6a
RH
10925 case 1: gen_rev16(tmp, tmp); break;
10926 case 3: gen_revsh(tmp, tmp); break;
19a6e31c
PM
10927 default:
10928 g_assert_not_reached();
9ee6e8bb 10929 }
b0109805 10930 store_reg(s, rd, tmp);
9ee6e8bb 10931 break;
19a6e31c 10932 }
9ee6e8bb 10933
d9e028c1
PM
10934 case 6:
10935 switch ((insn >> 5) & 7) {
10936 case 2:
10937 /* setend */
10938 ARCH(6);
9886ecdf
PB
10939 if (((insn >> 3) & 1) != !!(s->be_data == MO_BE)) {
10940 gen_helper_setend(cpu_env);
dcba3a8d 10941 s->base.is_jmp = DISAS_UPDATE;
d9e028c1 10942 }
9ee6e8bb 10943 break;
d9e028c1
PM
10944 case 3:
10945 /* cps */
10946 ARCH(6);
10947 if (IS_USER(s)) {
10948 break;
8984bd2e 10949 }
b53d8923 10950 if (arm_dc_feature(s, ARM_FEATURE_M)) {
d9e028c1
PM
10951 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
10952 /* FAULTMASK */
10953 if (insn & 1) {
10954 addr = tcg_const_i32(19);
10955 gen_helper_v7m_msr(cpu_env, addr, tmp);
10956 tcg_temp_free_i32(addr);
10957 }
10958 /* PRIMASK */
10959 if (insn & 2) {
10960 addr = tcg_const_i32(16);
10961 gen_helper_v7m_msr(cpu_env, addr, tmp);
10962 tcg_temp_free_i32(addr);
10963 }
10964 tcg_temp_free_i32(tmp);
10965 gen_lookup_tb(s);
10966 } else {
10967 if (insn & (1 << 4)) {
10968 shift = CPSR_A | CPSR_I | CPSR_F;
10969 } else {
10970 shift = 0;
10971 }
10972 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
8984bd2e 10973 }
d9e028c1
PM
10974 break;
10975 default:
10976 goto undef;
9ee6e8bb
PB
10977 }
10978 break;
10979
99c475ab
FB
10980 default:
10981 goto undef;
10982 }
10983 break;
10984
99c475ab
FB
10985 case 13:
10986 /* conditional branch or swi */
10987 cond = (insn >> 8) & 0xf;
10988 if (cond == 0xe)
10989 goto undef;
10990
10991 if (cond == 0xf) {
10992 /* swi */
a0415916 10993 gen_set_pc_im(s, s->base.pc_next);
d4a2dc67 10994 s->svc_imm = extract32(insn, 0, 8);
dcba3a8d 10995 s->base.is_jmp = DISAS_SWI;
99c475ab
FB
10996 break;
10997 }
10998 /* generate a conditional jump to next instruction */
c2d9644e 10999 arm_skip_unless(s, cond);
99c475ab
FB
11000
11001 /* jump to the offset */
fdbcf632 11002 val = read_pc(s);
99c475ab 11003 offset = ((int32_t)insn << 24) >> 24;
5899f386 11004 val += offset << 1;
8aaca4c0 11005 gen_jmp(s, val);
99c475ab
FB
11006 break;
11007
11008 case 14:
358bf29e 11009 if (insn & (1 << 11)) {
296e5a0a
PM
11010 /* thumb_insn_is_16bit() ensures we can't get here for
11011 * a Thumb2 CPU, so this must be a thumb1 split BL/BLX:
11012 * 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF)
11013 */
11014 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
11015 ARCH(5);
11016 offset = ((insn & 0x7ff) << 1);
11017 tmp = load_reg(s, 14);
11018 tcg_gen_addi_i32(tmp, tmp, offset);
11019 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
11020
11021 tmp2 = tcg_temp_new_i32();
a0415916 11022 tcg_gen_movi_i32(tmp2, s->base.pc_next | 1);
296e5a0a
PM
11023 store_reg(s, 14, tmp2);
11024 gen_bx(s, tmp);
358bf29e
PB
11025 break;
11026 }
9ee6e8bb 11027 /* unconditional branch */
fdbcf632 11028 val = read_pc(s);
99c475ab 11029 offset = ((int32_t)insn << 21) >> 21;
fdbcf632 11030 val += offset << 1;
8aaca4c0 11031 gen_jmp(s, val);
99c475ab
FB
11032 break;
11033
11034 case 15:
296e5a0a
PM
11035 /* thumb_insn_is_16bit() ensures we can't get here for
11036 * a Thumb2 CPU, so this must be a thumb1 split BL/BLX.
11037 */
11038 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
11039
11040 if (insn & (1 << 11)) {
11041 /* 0b1111_1xxx_xxxx_xxxx : BL suffix */
11042 offset = ((insn & 0x7ff) << 1) | 1;
11043 tmp = load_reg(s, 14);
11044 tcg_gen_addi_i32(tmp, tmp, offset);
11045
11046 tmp2 = tcg_temp_new_i32();
a0415916 11047 tcg_gen_movi_i32(tmp2, s->base.pc_next | 1);
296e5a0a
PM
11048 store_reg(s, 14, tmp2);
11049 gen_bx(s, tmp);
11050 } else {
11051 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix */
11052 uint32_t uoffset = ((int32_t)insn << 21) >> 9;
11053
fdbcf632 11054 tcg_gen_movi_i32(cpu_R[14], read_pc(s) + uoffset);
296e5a0a 11055 }
9ee6e8bb 11056 break;
99c475ab
FB
11057 }
11058 return;
9ee6e8bb 11059illegal_op:
99c475ab 11060undef:
1ce21ba1 11061 unallocated_encoding(s);
99c475ab
FB
11062}
11063
541ebcd4
PM
11064static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
11065{
a0415916 11066 /* Return true if the insn at dc->base.pc_next might cross a page boundary.
541ebcd4 11067 * (False positives are OK, false negatives are not.)
5b8d7289 11068 * We know this is a Thumb insn, and our caller ensures we are
a0415916 11069 * only called if dc->base.pc_next is less than 4 bytes from the page
5b8d7289
PM
11070 * boundary, so we cross the page if the first 16 bits indicate
11071 * that this is a 32 bit insn.
541ebcd4 11072 */
a0415916 11073 uint16_t insn = arm_lduw_code(env, s->base.pc_next, s->sctlr_b);
541ebcd4 11074
a0415916 11075 return !thumb_insn_is_16bit(s, s->base.pc_next, insn);
541ebcd4
PM
11076}
11077
b542683d 11078static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
2c0262af 11079{
1d8a5535 11080 DisasContext *dc = container_of(dcbase, DisasContext, base);
9c489ea6 11081 CPUARMState *env = cs->env_ptr;
2fc0cc0e 11082 ARMCPU *cpu = env_archcpu(env);
aad821ac
RH
11083 uint32_t tb_flags = dc->base.tb->flags;
11084 uint32_t condexec, core_mmu_idx;
3b46e624 11085
962fcbf2 11086 dc->isar = &cpu->isar;
e50e6a20 11087 dc->condjmp = 0;
3926cc84 11088
40f860cd 11089 dc->aarch64 = 0;
cef9ee70
SS
11090 /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
11091 * there is no secure EL1, so we route exceptions to EL3.
11092 */
11093 dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
11094 !arm_el_is_aa64(env, 3);
aad821ac
RH
11095 dc->thumb = FIELD_EX32(tb_flags, TBFLAG_A32, THUMB);
11096 dc->sctlr_b = FIELD_EX32(tb_flags, TBFLAG_A32, SCTLR_B);
11097 dc->be_data = FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
11098 condexec = FIELD_EX32(tb_flags, TBFLAG_A32, CONDEXEC);
11099 dc->condexec_mask = (condexec & 0xf) << 1;
11100 dc->condexec_cond = condexec >> 4;
11101 core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX);
11102 dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
c1e37810 11103 dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
3926cc84 11104#if !defined(CONFIG_USER_ONLY)
c1e37810 11105 dc->user = (dc->current_el == 0);
3926cc84 11106#endif
aad821ac
RH
11107 dc->ns = FIELD_EX32(tb_flags, TBFLAG_A32, NS);
11108 dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL);
11109 dc->vfp_enabled = FIELD_EX32(tb_flags, TBFLAG_A32, VFPEN);
11110 dc->vec_len = FIELD_EX32(tb_flags, TBFLAG_A32, VECLEN);
ea7ac69d
PM
11111 if (arm_feature(env, ARM_FEATURE_XSCALE)) {
11112 dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
11113 dc->vec_stride = 0;
11114 } else {
11115 dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
11116 dc->c15_cpar = 0;
11117 }
aad821ac 11118 dc->v7m_handler_mode = FIELD_EX32(tb_flags, TBFLAG_A32, HANDLER);
fb602cb7
PM
11119 dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
11120 regime_is_secure(env, dc->mmu_idx);
aad821ac 11121 dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_A32, STACKCHECK);
6d60c67a 11122 dc->v8m_fpccr_s_wrong = FIELD_EX32(tb_flags, TBFLAG_A32, FPCCR_S_WRONG);
6000531e
PM
11123 dc->v7m_new_fp_ctxt_needed =
11124 FIELD_EX32(tb_flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED);
e33cf0f8 11125 dc->v7m_lspact = FIELD_EX32(tb_flags, TBFLAG_A32, LSPACT);
60322b39 11126 dc->cp_regs = cpu->cp_regs;
a984e42c 11127 dc->features = env->features;
40f860cd 11128
50225ad0
PM
11129 /* Single step state. The code-generation logic here is:
11130 * SS_ACTIVE == 0:
11131 * generate code with no special handling for single-stepping (except
11132 * that anything that can make us go to SS_ACTIVE == 1 must end the TB;
11133 * this happens anyway because those changes are all system register or
11134 * PSTATE writes).
11135 * SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
11136 * emit code for one insn
11137 * emit code to clear PSTATE.SS
11138 * emit code to generate software step exception for completed step
11139 * end TB (as usual for having generated an exception)
11140 * SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
11141 * emit code to generate a software step exception
11142 * end the TB
11143 */
aad821ac
RH
11144 dc->ss_active = FIELD_EX32(tb_flags, TBFLAG_ANY, SS_ACTIVE);
11145 dc->pstate_ss = FIELD_EX32(tb_flags, TBFLAG_ANY, PSTATE_SS);
50225ad0 11146 dc->is_ldex = false;
8bd587c1
PM
11147 if (!arm_feature(env, ARM_FEATURE_M)) {
11148 dc->debug_target_el = FIELD_EX32(tb_flags, TBFLAG_ANY, DEBUG_TARGET_EL);
11149 }
50225ad0 11150
bfe7ad5b 11151 dc->page_start = dc->base.pc_first & TARGET_PAGE_MASK;
1d8a5535 11152
f7708456
RH
11153 /* If architectural single step active, limit to 1. */
11154 if (is_singlestepping(dc)) {
b542683d 11155 dc->base.max_insns = 1;
f7708456
RH
11156 }
11157
d0264d86
RH
11158 /* ARM is a fixed-length ISA. Bound the number of insns to execute
11159 to those left on the page. */
11160 if (!dc->thumb) {
bfe7ad5b 11161 int bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
b542683d 11162 dc->base.max_insns = MIN(dc->base.max_insns, bound);
d0264d86
RH
11163 }
11164
d9eea52c
PM
11165 cpu_V0 = tcg_temp_new_i64();
11166 cpu_V1 = tcg_temp_new_i64();
e677137d 11167 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
a7812ae4 11168 cpu_M0 = tcg_temp_new_i64();
1d8a5535
LV
11169}
11170
b1476854
LV
11171static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
11172{
11173 DisasContext *dc = container_of(dcbase, DisasContext, base);
11174
11175 /* A note on handling of the condexec (IT) bits:
11176 *
11177 * We want to avoid the overhead of having to write the updated condexec
11178 * bits back to the CPUARMState for every instruction in an IT block. So:
11179 * (1) if the condexec bits are not already zero then we write
11180 * zero back into the CPUARMState now. This avoids complications trying
11181 * to do it at the end of the block. (For example if we don't do this
11182 * it's hard to identify whether we can safely skip writing condexec
11183 * at the end of the TB, which we definitely want to do for the case
11184 * where a TB doesn't do anything with the IT state at all.)
11185 * (2) if we are going to leave the TB then we call gen_set_condexec()
11186 * which will write the correct value into CPUARMState if zero is wrong.
11187 * This is done both for leaving the TB at the end, and for leaving
11188 * it because of an exception we know will happen, which is done in
11189 * gen_exception_insn(). The latter is necessary because we need to
11190 * leave the TB with the PC/IT state just prior to execution of the
11191 * instruction which caused the exception.
11192 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
11193 * then the CPUARMState will be wrong and we need to reset it.
11194 * This is handled in the same way as restoration of the
11195 * PC in these situations; we save the value of the condexec bits
11196 * for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
11197 * then uses this to restore them after an exception.
11198 *
11199 * Note that there are no instructions which can read the condexec
11200 * bits, and none which can write non-static values to them, so
11201 * we don't need to care about whether CPUARMState is correct in the
11202 * middle of a TB.
11203 */
11204
11205 /* Reset the conditional execution bits immediately. This avoids
11206 complications trying to do it at the end of the block. */
11207 if (dc->condexec_mask || dc->condexec_cond) {
11208 TCGv_i32 tmp = tcg_temp_new_i32();
11209 tcg_gen_movi_i32(tmp, 0);
11210 store_cpu_field(tmp, condexec_bits);
11211 }
11212}
11213
f62bd897
LV
11214static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
11215{
11216 DisasContext *dc = container_of(dcbase, DisasContext, base);
11217
a0415916 11218 tcg_gen_insn_start(dc->base.pc_next,
f62bd897
LV
11219 (dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
11220 0);
15fa08f8 11221 dc->insn_start = tcg_last_op();
f62bd897
LV
11222}
11223
a68956ad
LV
11224static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
11225 const CPUBreakpoint *bp)
11226{
11227 DisasContext *dc = container_of(dcbase, DisasContext, base);
11228
11229 if (bp->flags & BP_CPU) {
11230 gen_set_condexec(dc);
a0415916 11231 gen_set_pc_im(dc, dc->base.pc_next);
a68956ad
LV
11232 gen_helper_check_breakpoints(cpu_env);
11233 /* End the TB early; it's likely not going to be executed */
11234 dc->base.is_jmp = DISAS_TOO_MANY;
11235 } else {
aee828e7 11236 gen_exception_internal_insn(dc, dc->base.pc_next, EXCP_DEBUG);
a68956ad
LV
11237 /* The address covered by the breakpoint must be
11238 included in [tb->pc, tb->pc + tb->size) in order
11239 to for it to be properly cleared -- thus we
11240 increment the PC here so that the logic setting
11241 tb->size below does the right thing. */
11242 /* TODO: Advance PC by correct instruction length to
11243 * avoid disassembler error messages */
a0415916 11244 dc->base.pc_next += 2;
a68956ad
LV
11245 dc->base.is_jmp = DISAS_NORETURN;
11246 }
11247
11248 return true;
11249}
11250
722ef0a5 11251static bool arm_pre_translate_insn(DisasContext *dc)
13189a90 11252{
13189a90
LV
11253#ifdef CONFIG_USER_ONLY
11254 /* Intercept jump to the magic kernel page. */
a0415916 11255 if (dc->base.pc_next >= 0xffff0000) {
13189a90
LV
11256 /* We always get here via a jump, so know we are not in a
11257 conditional execution block. */
11258 gen_exception_internal(EXCP_KERNEL_TRAP);
11259 dc->base.is_jmp = DISAS_NORETURN;
722ef0a5 11260 return true;
13189a90
LV
11261 }
11262#endif
11263
11264 if (dc->ss_active && !dc->pstate_ss) {
11265 /* Singlestep state is Active-pending.
11266 * If we're in this state at the start of a TB then either
11267 * a) we just took an exception to an EL which is being debugged
11268 * and this is the first insn in the exception handler
11269 * b) debug exceptions were masked and we just unmasked them
11270 * without changing EL (eg by clearing PSTATE.D)
11271 * In either case we're going to take a swstep exception in the
11272 * "did not step an insn" case, and so the syndrome ISV and EX
11273 * bits should be zero.
11274 */
11275 assert(dc->base.num_insns == 1);
c1d5f50f 11276 gen_swstep_exception(dc, 0, 0);
13189a90 11277 dc->base.is_jmp = DISAS_NORETURN;
722ef0a5 11278 return true;
13189a90
LV
11279 }
11280
722ef0a5
RH
11281 return false;
11282}
13189a90 11283
d0264d86 11284static void arm_post_translate_insn(DisasContext *dc)
722ef0a5 11285{
13189a90
LV
11286 if (dc->condjmp && !dc->base.is_jmp) {
11287 gen_set_label(dc->condlabel);
11288 dc->condjmp = 0;
11289 }
23169224 11290 translator_loop_temp_check(&dc->base);
13189a90
LV
11291}
11292
722ef0a5
RH
11293static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
11294{
11295 DisasContext *dc = container_of(dcbase, DisasContext, base);
11296 CPUARMState *env = cpu->env_ptr;
11297 unsigned int insn;
11298
11299 if (arm_pre_translate_insn(dc)) {
11300 return;
11301 }
11302
a0415916
RH
11303 dc->pc_curr = dc->base.pc_next;
11304 insn = arm_ldl_code(env, dc->base.pc_next, dc->sctlr_b);
58803318 11305 dc->insn = insn;
a0415916 11306 dc->base.pc_next += 4;
722ef0a5
RH
11307 disas_arm_insn(dc, insn);
11308
d0264d86
RH
11309 arm_post_translate_insn(dc);
11310
11311 /* ARM is a fixed-length ISA. We performed the cross-page check
11312 in init_disas_context by adjusting max_insns. */
722ef0a5
RH
11313}
11314
dcf14dfb
PM
11315static bool thumb_insn_is_unconditional(DisasContext *s, uint32_t insn)
11316{
11317 /* Return true if this Thumb insn is always unconditional,
11318 * even inside an IT block. This is true of only a very few
11319 * instructions: BKPT, HLT, and SG.
11320 *
11321 * A larger class of instructions are UNPREDICTABLE if used
11322 * inside an IT block; we do not need to detect those here, because
11323 * what we do by default (perform the cc check and update the IT
11324 * bits state machine) is a permitted CONSTRAINED UNPREDICTABLE
11325 * choice for those situations.
11326 *
11327 * insn is either a 16-bit or a 32-bit instruction; the two are
11328 * distinguishable because for the 16-bit case the top 16 bits
11329 * are zeroes, and that isn't a valid 32-bit encoding.
11330 */
11331 if ((insn & 0xffffff00) == 0xbe00) {
11332 /* BKPT */
11333 return true;
11334 }
11335
11336 if ((insn & 0xffffffc0) == 0xba80 && arm_dc_feature(s, ARM_FEATURE_V8) &&
11337 !arm_dc_feature(s, ARM_FEATURE_M)) {
11338 /* HLT: v8A only. This is unconditional even when it is going to
11339 * UNDEF; see the v8A ARM ARM DDI0487B.a H3.3.
11340 * For v7 cores this was a plain old undefined encoding and so
11341 * honours its cc check. (We might be using the encoding as
11342 * a semihosting trap, but we don't change the cc check behaviour
11343 * on that account, because a debugger connected to a real v7A
11344 * core and emulating semihosting traps by catching the UNDEF
11345 * exception would also only see cases where the cc check passed.
11346 * No guest code should be trying to do a HLT semihosting trap
11347 * in an IT block anyway.
11348 */
11349 return true;
11350 }
11351
11352 if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_V8) &&
11353 arm_dc_feature(s, ARM_FEATURE_M)) {
11354 /* SG: v8M only */
11355 return true;
11356 }
11357
11358 return false;
11359}
11360
722ef0a5
RH
11361static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
11362{
11363 DisasContext *dc = container_of(dcbase, DisasContext, base);
11364 CPUARMState *env = cpu->env_ptr;
296e5a0a
PM
11365 uint32_t insn;
11366 bool is_16bit;
722ef0a5
RH
11367
11368 if (arm_pre_translate_insn(dc)) {
11369 return;
11370 }
11371
a0415916
RH
11372 dc->pc_curr = dc->base.pc_next;
11373 insn = arm_lduw_code(env, dc->base.pc_next, dc->sctlr_b);
11374 is_16bit = thumb_insn_is_16bit(dc, dc->base.pc_next, insn);
11375 dc->base.pc_next += 2;
296e5a0a 11376 if (!is_16bit) {
a0415916 11377 uint32_t insn2 = arm_lduw_code(env, dc->base.pc_next, dc->sctlr_b);
296e5a0a
PM
11378
11379 insn = insn << 16 | insn2;
a0415916 11380 dc->base.pc_next += 2;
296e5a0a 11381 }
58803318 11382 dc->insn = insn;
296e5a0a 11383
dcf14dfb 11384 if (dc->condexec_mask && !thumb_insn_is_unconditional(dc, insn)) {
296e5a0a
PM
11385 uint32_t cond = dc->condexec_cond;
11386
5529de1e
PM
11387 /*
11388 * Conditionally skip the insn. Note that both 0xe and 0xf mean
11389 * "always"; 0xf is not "never".
11390 */
11391 if (cond < 0x0e) {
c2d9644e 11392 arm_skip_unless(dc, cond);
296e5a0a
PM
11393 }
11394 }
11395
11396 if (is_16bit) {
11397 disas_thumb_insn(dc, insn);
11398 } else {
2eea841c 11399 disas_thumb2_insn(dc, insn);
296e5a0a 11400 }
722ef0a5
RH
11401
11402 /* Advance the Thumb condexec condition. */
11403 if (dc->condexec_mask) {
11404 dc->condexec_cond = ((dc->condexec_cond & 0xe) |
11405 ((dc->condexec_mask >> 4) & 1));
11406 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
11407 if (dc->condexec_mask == 0) {
11408 dc->condexec_cond = 0;
11409 }
11410 }
11411
d0264d86
RH
11412 arm_post_translate_insn(dc);
11413
11414 /* Thumb is a variable-length ISA. Stop translation when the next insn
11415 * will touch a new page. This ensures that prefetch aborts occur at
11416 * the right place.
11417 *
11418 * We want to stop the TB if the next insn starts in a new page,
11419 * or if it spans between this page and the next. This means that
11420 * if we're looking at the last halfword in the page we need to
11421 * see if it's a 16-bit Thumb insn (which will fit in this TB)
11422 * or a 32-bit Thumb insn (which won't).
11423 * This is to avoid generating a silly TB with a single 16-bit insn
11424 * in it at the end of this page (which would execute correctly
11425 * but isn't very efficient).
11426 */
11427 if (dc->base.is_jmp == DISAS_NEXT
a0415916
RH
11428 && (dc->base.pc_next - dc->page_start >= TARGET_PAGE_SIZE
11429 || (dc->base.pc_next - dc->page_start >= TARGET_PAGE_SIZE - 3
d0264d86
RH
11430 && insn_crosses_page(env, dc)))) {
11431 dc->base.is_jmp = DISAS_TOO_MANY;
11432 }
722ef0a5
RH
11433}
11434
70d3c035 11435static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
1d8a5535 11436{
70d3c035 11437 DisasContext *dc = container_of(dcbase, DisasContext, base);
2e70f6ef 11438
c5a49c63 11439 if (tb_cflags(dc->base.tb) & CF_LAST_IO && dc->condjmp) {
70d3c035
LV
11440 /* FIXME: This can theoretically happen with self-modifying code. */
11441 cpu_abort(cpu, "IO on conditional branch instruction");
2e70f6ef 11442 }
9ee6e8bb 11443
b5ff1b31 11444 /* At this stage dc->condjmp will only be set when the skipped
9ee6e8bb
PB
11445 instruction was a conditional branch or trap, and the PC has
11446 already been written. */
f021b2c4 11447 gen_set_condexec(dc);
dcba3a8d 11448 if (dc->base.is_jmp == DISAS_BX_EXCRET) {
3bb8a96f
PM
11449 /* Exception return branches need some special case code at the
11450 * end of the TB, which is complex enough that it has to
11451 * handle the single-step vs not and the condition-failed
11452 * insn codepath itself.
11453 */
11454 gen_bx_excret_final_code(dc);
11455 } else if (unlikely(is_singlestepping(dc))) {
7999a5c8 11456 /* Unconditional and "condition passed" instruction codepath. */
dcba3a8d 11457 switch (dc->base.is_jmp) {
7999a5c8 11458 case DISAS_SWI:
50225ad0 11459 gen_ss_advance(dc);
73710361
GB
11460 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
11461 default_exception_el(dc));
7999a5c8
SF
11462 break;
11463 case DISAS_HVC:
37e6456e 11464 gen_ss_advance(dc);
73710361 11465 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
7999a5c8
SF
11466 break;
11467 case DISAS_SMC:
37e6456e 11468 gen_ss_advance(dc);
73710361 11469 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
7999a5c8
SF
11470 break;
11471 case DISAS_NEXT:
a68956ad 11472 case DISAS_TOO_MANY:
7999a5c8 11473 case DISAS_UPDATE:
a0415916 11474 gen_set_pc_im(dc, dc->base.pc_next);
7999a5c8
SF
11475 /* fall through */
11476 default:
5425415e
PM
11477 /* FIXME: Single stepping a WFI insn will not halt the CPU. */
11478 gen_singlestep_exception(dc);
a0c231e6
RH
11479 break;
11480 case DISAS_NORETURN:
11481 break;
7999a5c8 11482 }
8aaca4c0 11483 } else {
9ee6e8bb
PB
11484 /* While branches must always occur at the end of an IT block,
11485 there are a few other things that can cause us to terminate
65626741 11486 the TB in the middle of an IT block:
9ee6e8bb
PB
11487 - Exception generating instructions (bkpt, swi, undefined).
11488 - Page boundaries.
11489 - Hardware watchpoints.
11490 Hardware breakpoints have already been handled and skip this code.
11491 */
dcba3a8d 11492 switch(dc->base.is_jmp) {
8aaca4c0 11493 case DISAS_NEXT:
a68956ad 11494 case DISAS_TOO_MANY:
a0415916 11495 gen_goto_tb(dc, 1, dc->base.pc_next);
8aaca4c0 11496 break;
577bf808 11497 case DISAS_JUMP:
8a6b28c7
EC
11498 gen_goto_ptr();
11499 break;
e8d52302 11500 case DISAS_UPDATE:
a0415916 11501 gen_set_pc_im(dc, dc->base.pc_next);
e8d52302 11502 /* fall through */
577bf808 11503 default:
8aaca4c0 11504 /* indicate that the hash table must be used to find the next TB */
07ea28b4 11505 tcg_gen_exit_tb(NULL, 0);
8aaca4c0 11506 break;
a0c231e6 11507 case DISAS_NORETURN:
8aaca4c0
FB
11508 /* nothing more to generate */
11509 break;
9ee6e8bb 11510 case DISAS_WFI:
58803318
SS
11511 {
11512 TCGv_i32 tmp = tcg_const_i32((dc->thumb &&
11513 !(dc->insn & (1U << 31))) ? 2 : 4);
11514
11515 gen_helper_wfi(cpu_env, tmp);
11516 tcg_temp_free_i32(tmp);
84549b6d
PM
11517 /* The helper doesn't necessarily throw an exception, but we
11518 * must go back to the main loop to check for interrupts anyway.
11519 */
07ea28b4 11520 tcg_gen_exit_tb(NULL, 0);
9ee6e8bb 11521 break;
58803318 11522 }
72c1d3af
PM
11523 case DISAS_WFE:
11524 gen_helper_wfe(cpu_env);
11525 break;
c87e5a61
PM
11526 case DISAS_YIELD:
11527 gen_helper_yield(cpu_env);
11528 break;
9ee6e8bb 11529 case DISAS_SWI:
73710361
GB
11530 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
11531 default_exception_el(dc));
9ee6e8bb 11532 break;
37e6456e 11533 case DISAS_HVC:
73710361 11534 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
37e6456e
PM
11535 break;
11536 case DISAS_SMC:
73710361 11537 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
37e6456e 11538 break;
8aaca4c0 11539 }
f021b2c4
PM
11540 }
11541
11542 if (dc->condjmp) {
11543 /* "Condition failed" instruction codepath for the branch/trap insn */
11544 gen_set_label(dc->condlabel);
11545 gen_set_condexec(dc);
b636649f 11546 if (unlikely(is_singlestepping(dc))) {
a0415916 11547 gen_set_pc_im(dc, dc->base.pc_next);
f021b2c4
PM
11548 gen_singlestep_exception(dc);
11549 } else {
a0415916 11550 gen_goto_tb(dc, 1, dc->base.pc_next);
e50e6a20 11551 }
2c0262af 11552 }
70d3c035
LV
11553}
11554
4013f7fc
LV
11555static void arm_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
11556{
11557 DisasContext *dc = container_of(dcbase, DisasContext, base);
11558
11559 qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
1d48474d 11560 log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
4013f7fc
LV
11561}
11562
23169224
LV
11563static const TranslatorOps arm_translator_ops = {
11564 .init_disas_context = arm_tr_init_disas_context,
11565 .tb_start = arm_tr_tb_start,
11566 .insn_start = arm_tr_insn_start,
11567 .breakpoint_check = arm_tr_breakpoint_check,
11568 .translate_insn = arm_tr_translate_insn,
11569 .tb_stop = arm_tr_tb_stop,
11570 .disas_log = arm_tr_disas_log,
11571};
11572
722ef0a5
RH
11573static const TranslatorOps thumb_translator_ops = {
11574 .init_disas_context = arm_tr_init_disas_context,
11575 .tb_start = arm_tr_tb_start,
11576 .insn_start = arm_tr_insn_start,
11577 .breakpoint_check = arm_tr_breakpoint_check,
11578 .translate_insn = thumb_tr_translate_insn,
11579 .tb_stop = arm_tr_tb_stop,
11580 .disas_log = arm_tr_disas_log,
11581};
11582
70d3c035 11583/* generate intermediate code for basic block 'tb'. */
8b86d6d2 11584void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
70d3c035 11585{
23169224
LV
11586 DisasContext dc;
11587 const TranslatorOps *ops = &arm_translator_ops;
70d3c035 11588
aad821ac 11589 if (FIELD_EX32(tb->flags, TBFLAG_A32, THUMB)) {
722ef0a5
RH
11590 ops = &thumb_translator_ops;
11591 }
23169224 11592#ifdef TARGET_AARCH64
aad821ac 11593 if (FIELD_EX32(tb->flags, TBFLAG_ANY, AARCH64_STATE)) {
23169224 11594 ops = &aarch64_translator_ops;
2c0262af
FB
11595 }
11596#endif
23169224 11597
8b86d6d2 11598 translator_loop(ops, &dc.base, cpu, tb, max_insns);
2c0262af
FB
11599}
11600
bad729e2
RH
11601void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
11602 target_ulong *data)
d2856f1a 11603{
3926cc84 11604 if (is_a64(env)) {
bad729e2 11605 env->pc = data[0];
40f860cd 11606 env->condexec_bits = 0;
aaa1f954 11607 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
3926cc84 11608 } else {
bad729e2
RH
11609 env->regs[15] = data[0];
11610 env->condexec_bits = data[1];
aaa1f954 11611 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
3926cc84 11612 }
d2856f1a 11613}