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