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