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