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