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