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