target/arm: Convert Neon 3-reg-same logic ops to decodetree
[qemu/ar7.git] / target / arm / translate.c
blob9affa92cbe7f0482db41e98e625544b9cdab64a5
1 /*
2 * ARM translation
4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2005-2007 CodeSourcery
6 * Copyright (c) 2007 OpenedHand, Ltd.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
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.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include "qemu/osdep.h"
23 #include "cpu.h"
24 #include "internals.h"
25 #include "disas/disas.h"
26 #include "exec/exec-all.h"
27 #include "tcg/tcg-op.h"
28 #include "tcg/tcg-op-gvec.h"
29 #include "qemu/log.h"
30 #include "qemu/bitops.h"
31 #include "arm_ldst.h"
32 #include "hw/semihosting/semihost.h"
34 #include "exec/helper-proto.h"
35 #include "exec/helper-gen.h"
37 #include "trace-tcg.h"
38 #include "exec/log.h"
41 #define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T)
42 #define ENABLE_ARCH_5 arm_dc_feature(s, ARM_FEATURE_V5)
43 /* currently all emulated v5 cores are also v5TE, so don't bother */
44 #define ENABLE_ARCH_5TE arm_dc_feature(s, ARM_FEATURE_V5)
45 #define ENABLE_ARCH_5J dc_isar_feature(aa32_jazelle, s)
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)
52 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
54 #include "translate.h"
56 #if defined(CONFIG_USER_ONLY)
57 #define IS_USER(s) 1
58 #else
59 #define IS_USER(s) (s->user)
60 #endif
62 /* We reuse the same 64-bit temporaries for efficiency. */
63 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
64 static TCGv_i32 cpu_R[16];
65 TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
66 TCGv_i64 cpu_exclusive_addr;
67 TCGv_i64 cpu_exclusive_val;
69 #include "exec/gen-icount.h"
71 static const char * const regnames[] =
72 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
73 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
75 /* Function prototypes for gen_ functions calling Neon helpers. */
76 typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32,
77 TCGv_i32, TCGv_i32);
78 /* Function prototypes for gen_ functions for fix point conversions */
79 typedef void VFPGenFixPointFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
81 /* initialize TCG globals. */
82 void arm_translate_init(void)
84 int i;
86 for (i = 0; i < 16; i++) {
87 cpu_R[i] = tcg_global_mem_new_i32(cpu_env,
88 offsetof(CPUARMState, regs[i]),
89 regnames[i]);
91 cpu_CF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, CF), "CF");
92 cpu_NF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, NF), "NF");
93 cpu_VF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, VF), "VF");
94 cpu_ZF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, ZF), "ZF");
96 cpu_exclusive_addr = tcg_global_mem_new_i64(cpu_env,
97 offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
98 cpu_exclusive_val = tcg_global_mem_new_i64(cpu_env,
99 offsetof(CPUARMState, exclusive_val), "exclusive_val");
101 a64_translate_init();
104 /* Flags for the disas_set_da_iss info argument:
105 * lower bits hold the Rt register number, higher bits are flags.
107 typedef enum ISSInfo {
108 ISSNone = 0,
109 ISSRegMask = 0x1f,
110 ISSInvalid = (1 << 5),
111 ISSIsAcqRel = (1 << 6),
112 ISSIsWrite = (1 << 7),
113 ISSIs16Bit = (1 << 8),
114 } ISSInfo;
116 /* Save the syndrome information for a Data Abort */
117 static void disas_set_da_iss(DisasContext *s, MemOp memop, ISSInfo issinfo)
119 uint32_t syn;
120 int sas = memop & MO_SIZE;
121 bool sse = memop & MO_SIGN;
122 bool is_acqrel = issinfo & ISSIsAcqRel;
123 bool is_write = issinfo & ISSIsWrite;
124 bool is_16bit = issinfo & ISSIs16Bit;
125 int srt = issinfo & ISSRegMask;
127 if (issinfo & ISSInvalid) {
128 /* Some callsites want to conditionally provide ISS info,
129 * eg "only if this was not a writeback"
131 return;
134 if (srt == 15) {
135 /* For AArch32, insns where the src/dest is R15 never generate
136 * ISS information. Catching that here saves checking at all
137 * the call sites.
139 return;
142 syn = syn_data_abort_with_iss(0, sas, sse, srt, 0, is_acqrel,
143 0, 0, 0, is_write, 0, is_16bit);
144 disas_set_insn_syndrome(s, syn);
147 static inline int get_a32_user_mem_index(DisasContext *s)
149 /* Return the core mmu_idx to use for A32/T32 "unprivileged load/store"
150 * insns:
151 * if PL2, UNPREDICTABLE (we choose to implement as if PL0)
152 * otherwise, access as if at PL0.
154 switch (s->mmu_idx) {
155 case ARMMMUIdx_E2: /* this one is UNPREDICTABLE */
156 case ARMMMUIdx_E10_0:
157 case ARMMMUIdx_E10_1:
158 case ARMMMUIdx_E10_1_PAN:
159 return arm_to_core_mmu_idx(ARMMMUIdx_E10_0);
160 case ARMMMUIdx_SE3:
161 case ARMMMUIdx_SE10_0:
162 case ARMMMUIdx_SE10_1:
163 case ARMMMUIdx_SE10_1_PAN:
164 return arm_to_core_mmu_idx(ARMMMUIdx_SE10_0);
165 case ARMMMUIdx_MUser:
166 case ARMMMUIdx_MPriv:
167 return arm_to_core_mmu_idx(ARMMMUIdx_MUser);
168 case ARMMMUIdx_MUserNegPri:
169 case ARMMMUIdx_MPrivNegPri:
170 return arm_to_core_mmu_idx(ARMMMUIdx_MUserNegPri);
171 case ARMMMUIdx_MSUser:
172 case ARMMMUIdx_MSPriv:
173 return arm_to_core_mmu_idx(ARMMMUIdx_MSUser);
174 case ARMMMUIdx_MSUserNegPri:
175 case ARMMMUIdx_MSPrivNegPri:
176 return arm_to_core_mmu_idx(ARMMMUIdx_MSUserNegPri);
177 default:
178 g_assert_not_reached();
182 static inline TCGv_i32 load_cpu_offset(int offset)
184 TCGv_i32 tmp = tcg_temp_new_i32();
185 tcg_gen_ld_i32(tmp, cpu_env, offset);
186 return tmp;
189 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
191 static inline void store_cpu_offset(TCGv_i32 var, int offset)
193 tcg_gen_st_i32(var, cpu_env, offset);
194 tcg_temp_free_i32(var);
197 #define store_cpu_field(var, name) \
198 store_cpu_offset(var, offsetof(CPUARMState, name))
200 /* The architectural value of PC. */
201 static uint32_t read_pc(DisasContext *s)
203 return s->pc_curr + (s->thumb ? 4 : 8);
206 /* Set a variable to the value of a CPU register. */
207 static void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
209 if (reg == 15) {
210 tcg_gen_movi_i32(var, read_pc(s));
211 } else {
212 tcg_gen_mov_i32(var, cpu_R[reg]);
216 /* Create a new temporary and set it to the value of a CPU register. */
217 static inline TCGv_i32 load_reg(DisasContext *s, int reg)
219 TCGv_i32 tmp = tcg_temp_new_i32();
220 load_reg_var(s, tmp, reg);
221 return tmp;
225 * Create a new temp, REG + OFS, except PC is ALIGN(PC, 4).
226 * This is used for load/store for which use of PC implies (literal),
227 * or ADD that implies ADR.
229 static TCGv_i32 add_reg_for_lit(DisasContext *s, int reg, int ofs)
231 TCGv_i32 tmp = tcg_temp_new_i32();
233 if (reg == 15) {
234 tcg_gen_movi_i32(tmp, (read_pc(s) & ~3) + ofs);
235 } else {
236 tcg_gen_addi_i32(tmp, cpu_R[reg], ofs);
238 return tmp;
241 /* Set a CPU register. The source must be a temporary and will be
242 marked as dead. */
243 static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
245 if (reg == 15) {
246 /* In Thumb mode, we must ignore bit 0.
247 * In ARM mode, for ARMv4 and ARMv5, it is UNPREDICTABLE if bits [1:0]
248 * are not 0b00, but for ARMv6 and above, we must ignore bits [1:0].
249 * We choose to ignore [1:0] in ARM mode for all architecture versions.
251 tcg_gen_andi_i32(var, var, s->thumb ? ~1 : ~3);
252 s->base.is_jmp = DISAS_JUMP;
254 tcg_gen_mov_i32(cpu_R[reg], var);
255 tcg_temp_free_i32(var);
259 * Variant of store_reg which applies v8M stack-limit checks before updating
260 * SP. If the check fails this will result in an exception being taken.
261 * We disable the stack checks for CONFIG_USER_ONLY because we have
262 * no idea what the stack limits should be in that case.
263 * If stack checking is not being done this just acts like store_reg().
265 static void store_sp_checked(DisasContext *s, TCGv_i32 var)
267 #ifndef CONFIG_USER_ONLY
268 if (s->v8m_stackcheck) {
269 gen_helper_v8m_stackcheck(cpu_env, var);
271 #endif
272 store_reg(s, 13, var);
275 /* Value extensions. */
276 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
277 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
278 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
279 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
281 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
282 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
285 static inline void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
287 TCGv_i32 tmp_mask = tcg_const_i32(mask);
288 gen_helper_cpsr_write(cpu_env, var, tmp_mask);
289 tcg_temp_free_i32(tmp_mask);
291 /* Set NZCV flags from the high 4 bits of var. */
292 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
294 static void gen_exception_internal(int excp)
296 TCGv_i32 tcg_excp = tcg_const_i32(excp);
298 assert(excp_is_internal(excp));
299 gen_helper_exception_internal(cpu_env, tcg_excp);
300 tcg_temp_free_i32(tcg_excp);
303 static void gen_step_complete_exception(DisasContext *s)
305 /* We just completed step of an insn. Move from Active-not-pending
306 * to Active-pending, and then also take the swstep exception.
307 * This corresponds to making the (IMPDEF) choice to prioritize
308 * swstep exceptions over asynchronous exceptions taken to an exception
309 * level where debug is disabled. This choice has the advantage that
310 * we do not need to maintain internal state corresponding to the
311 * ISV/EX syndrome bits between completion of the step and generation
312 * of the exception, and our syndrome information is always correct.
314 gen_ss_advance(s);
315 gen_swstep_exception(s, 1, s->is_ldex);
316 s->base.is_jmp = DISAS_NORETURN;
319 static void gen_singlestep_exception(DisasContext *s)
321 /* Generate the right kind of exception for singlestep, which is
322 * either the architectural singlestep or EXCP_DEBUG for QEMU's
323 * gdb singlestepping.
325 if (s->ss_active) {
326 gen_step_complete_exception(s);
327 } else {
328 gen_exception_internal(EXCP_DEBUG);
332 static inline bool is_singlestepping(DisasContext *s)
334 /* Return true if we are singlestepping either because of
335 * architectural singlestep or QEMU gdbstub singlestep. This does
336 * not include the command line '-singlestep' mode which is rather
337 * misnamed as it only means "one instruction per TB" and doesn't
338 * affect the code we generate.
340 return s->base.singlestep_enabled || s->ss_active;
343 static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
345 TCGv_i32 tmp1 = tcg_temp_new_i32();
346 TCGv_i32 tmp2 = tcg_temp_new_i32();
347 tcg_gen_ext16s_i32(tmp1, a);
348 tcg_gen_ext16s_i32(tmp2, b);
349 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
350 tcg_temp_free_i32(tmp2);
351 tcg_gen_sari_i32(a, a, 16);
352 tcg_gen_sari_i32(b, b, 16);
353 tcg_gen_mul_i32(b, b, a);
354 tcg_gen_mov_i32(a, tmp1);
355 tcg_temp_free_i32(tmp1);
358 /* Byteswap each halfword. */
359 static void gen_rev16(TCGv_i32 dest, TCGv_i32 var)
361 TCGv_i32 tmp = tcg_temp_new_i32();
362 TCGv_i32 mask = tcg_const_i32(0x00ff00ff);
363 tcg_gen_shri_i32(tmp, var, 8);
364 tcg_gen_and_i32(tmp, tmp, mask);
365 tcg_gen_and_i32(var, var, mask);
366 tcg_gen_shli_i32(var, var, 8);
367 tcg_gen_or_i32(dest, var, tmp);
368 tcg_temp_free_i32(mask);
369 tcg_temp_free_i32(tmp);
372 /* Byteswap low halfword and sign extend. */
373 static void gen_revsh(TCGv_i32 dest, TCGv_i32 var)
375 tcg_gen_ext16u_i32(var, var);
376 tcg_gen_bswap16_i32(var, var);
377 tcg_gen_ext16s_i32(dest, var);
380 /* 32x32->64 multiply. Marks inputs as dead. */
381 static TCGv_i64 gen_mulu_i64_i32(TCGv_i32 a, TCGv_i32 b)
383 TCGv_i32 lo = tcg_temp_new_i32();
384 TCGv_i32 hi = tcg_temp_new_i32();
385 TCGv_i64 ret;
387 tcg_gen_mulu2_i32(lo, hi, a, b);
388 tcg_temp_free_i32(a);
389 tcg_temp_free_i32(b);
391 ret = tcg_temp_new_i64();
392 tcg_gen_concat_i32_i64(ret, lo, hi);
393 tcg_temp_free_i32(lo);
394 tcg_temp_free_i32(hi);
396 return ret;
399 static TCGv_i64 gen_muls_i64_i32(TCGv_i32 a, TCGv_i32 b)
401 TCGv_i32 lo = tcg_temp_new_i32();
402 TCGv_i32 hi = tcg_temp_new_i32();
403 TCGv_i64 ret;
405 tcg_gen_muls2_i32(lo, hi, a, b);
406 tcg_temp_free_i32(a);
407 tcg_temp_free_i32(b);
409 ret = tcg_temp_new_i64();
410 tcg_gen_concat_i32_i64(ret, lo, hi);
411 tcg_temp_free_i32(lo);
412 tcg_temp_free_i32(hi);
414 return ret;
417 /* Swap low and high halfwords. */
418 static void gen_swap_half(TCGv_i32 var)
420 tcg_gen_rotri_i32(var, var, 16);
423 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
424 tmp = (t0 ^ t1) & 0x8000;
425 t0 &= ~0x8000;
426 t1 &= ~0x8000;
427 t0 = (t0 + t1) ^ tmp;
430 static void gen_add16(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
432 TCGv_i32 tmp = tcg_temp_new_i32();
433 tcg_gen_xor_i32(tmp, t0, t1);
434 tcg_gen_andi_i32(tmp, tmp, 0x8000);
435 tcg_gen_andi_i32(t0, t0, ~0x8000);
436 tcg_gen_andi_i32(t1, t1, ~0x8000);
437 tcg_gen_add_i32(t0, t0, t1);
438 tcg_gen_xor_i32(dest, t0, tmp);
439 tcg_temp_free_i32(tmp);
442 /* Set N and Z flags from var. */
443 static inline void gen_logic_CC(TCGv_i32 var)
445 tcg_gen_mov_i32(cpu_NF, var);
446 tcg_gen_mov_i32(cpu_ZF, var);
449 /* dest = T0 + T1 + CF. */
450 static void gen_add_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
452 tcg_gen_add_i32(dest, t0, t1);
453 tcg_gen_add_i32(dest, dest, cpu_CF);
456 /* dest = T0 - T1 + CF - 1. */
457 static void gen_sub_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
459 tcg_gen_sub_i32(dest, t0, t1);
460 tcg_gen_add_i32(dest, dest, cpu_CF);
461 tcg_gen_subi_i32(dest, dest, 1);
464 /* dest = T0 + T1. Compute C, N, V and Z flags */
465 static void gen_add_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
467 TCGv_i32 tmp = tcg_temp_new_i32();
468 tcg_gen_movi_i32(tmp, 0);
469 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, t1, tmp);
470 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
471 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
472 tcg_gen_xor_i32(tmp, t0, t1);
473 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
474 tcg_temp_free_i32(tmp);
475 tcg_gen_mov_i32(dest, cpu_NF);
478 /* dest = T0 + T1 + CF. Compute C, N, V and Z flags */
479 static void gen_adc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
481 TCGv_i32 tmp = tcg_temp_new_i32();
482 if (TCG_TARGET_HAS_add2_i32) {
483 tcg_gen_movi_i32(tmp, 0);
484 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp);
485 tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1, tmp);
486 } else {
487 TCGv_i64 q0 = tcg_temp_new_i64();
488 TCGv_i64 q1 = tcg_temp_new_i64();
489 tcg_gen_extu_i32_i64(q0, t0);
490 tcg_gen_extu_i32_i64(q1, t1);
491 tcg_gen_add_i64(q0, q0, q1);
492 tcg_gen_extu_i32_i64(q1, cpu_CF);
493 tcg_gen_add_i64(q0, q0, q1);
494 tcg_gen_extr_i64_i32(cpu_NF, cpu_CF, q0);
495 tcg_temp_free_i64(q0);
496 tcg_temp_free_i64(q1);
498 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
499 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
500 tcg_gen_xor_i32(tmp, t0, t1);
501 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
502 tcg_temp_free_i32(tmp);
503 tcg_gen_mov_i32(dest, cpu_NF);
506 /* dest = T0 - T1. Compute C, N, V and Z flags */
507 static void gen_sub_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
509 TCGv_i32 tmp;
510 tcg_gen_sub_i32(cpu_NF, t0, t1);
511 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
512 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0, t1);
513 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
514 tmp = tcg_temp_new_i32();
515 tcg_gen_xor_i32(tmp, t0, t1);
516 tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
517 tcg_temp_free_i32(tmp);
518 tcg_gen_mov_i32(dest, cpu_NF);
521 /* dest = T0 + ~T1 + CF. Compute C, N, V and Z flags */
522 static void gen_sbc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
524 TCGv_i32 tmp = tcg_temp_new_i32();
525 tcg_gen_not_i32(tmp, t1);
526 gen_adc_CC(dest, t0, tmp);
527 tcg_temp_free_i32(tmp);
530 #define GEN_SHIFT(name) \
531 static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \
533 TCGv_i32 tmp1, tmp2, tmp3; \
534 tmp1 = tcg_temp_new_i32(); \
535 tcg_gen_andi_i32(tmp1, t1, 0xff); \
536 tmp2 = tcg_const_i32(0); \
537 tmp3 = tcg_const_i32(0x1f); \
538 tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
539 tcg_temp_free_i32(tmp3); \
540 tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
541 tcg_gen_##name##_i32(dest, tmp2, tmp1); \
542 tcg_temp_free_i32(tmp2); \
543 tcg_temp_free_i32(tmp1); \
545 GEN_SHIFT(shl)
546 GEN_SHIFT(shr)
547 #undef GEN_SHIFT
549 static void gen_sar(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
551 TCGv_i32 tmp1, tmp2;
552 tmp1 = tcg_temp_new_i32();
553 tcg_gen_andi_i32(tmp1, t1, 0xff);
554 tmp2 = tcg_const_i32(0x1f);
555 tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1);
556 tcg_temp_free_i32(tmp2);
557 tcg_gen_sar_i32(dest, t0, tmp1);
558 tcg_temp_free_i32(tmp1);
561 static void shifter_out_im(TCGv_i32 var, int shift)
563 tcg_gen_extract_i32(cpu_CF, var, shift, 1);
566 /* Shift by immediate. Includes special handling for shift == 0. */
567 static inline void gen_arm_shift_im(TCGv_i32 var, int shiftop,
568 int shift, int flags)
570 switch (shiftop) {
571 case 0: /* LSL */
572 if (shift != 0) {
573 if (flags)
574 shifter_out_im(var, 32 - shift);
575 tcg_gen_shli_i32(var, var, shift);
577 break;
578 case 1: /* LSR */
579 if (shift == 0) {
580 if (flags) {
581 tcg_gen_shri_i32(cpu_CF, var, 31);
583 tcg_gen_movi_i32(var, 0);
584 } else {
585 if (flags)
586 shifter_out_im(var, shift - 1);
587 tcg_gen_shri_i32(var, var, shift);
589 break;
590 case 2: /* ASR */
591 if (shift == 0)
592 shift = 32;
593 if (flags)
594 shifter_out_im(var, shift - 1);
595 if (shift == 32)
596 shift = 31;
597 tcg_gen_sari_i32(var, var, shift);
598 break;
599 case 3: /* ROR/RRX */
600 if (shift != 0) {
601 if (flags)
602 shifter_out_im(var, shift - 1);
603 tcg_gen_rotri_i32(var, var, shift); break;
604 } else {
605 TCGv_i32 tmp = tcg_temp_new_i32();
606 tcg_gen_shli_i32(tmp, cpu_CF, 31);
607 if (flags)
608 shifter_out_im(var, 0);
609 tcg_gen_shri_i32(var, var, 1);
610 tcg_gen_or_i32(var, var, tmp);
611 tcg_temp_free_i32(tmp);
616 static inline void gen_arm_shift_reg(TCGv_i32 var, int shiftop,
617 TCGv_i32 shift, int flags)
619 if (flags) {
620 switch (shiftop) {
621 case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break;
622 case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break;
623 case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break;
624 case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break;
626 } else {
627 switch (shiftop) {
628 case 0:
629 gen_shl(var, var, shift);
630 break;
631 case 1:
632 gen_shr(var, var, shift);
633 break;
634 case 2:
635 gen_sar(var, var, shift);
636 break;
637 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
638 tcg_gen_rotr_i32(var, var, shift); break;
641 tcg_temp_free_i32(shift);
645 * Generate a conditional based on ARM condition code cc.
646 * This is common between ARM and Aarch64 targets.
648 void arm_test_cc(DisasCompare *cmp, int cc)
650 TCGv_i32 value;
651 TCGCond cond;
652 bool global = true;
654 switch (cc) {
655 case 0: /* eq: Z */
656 case 1: /* ne: !Z */
657 cond = TCG_COND_EQ;
658 value = cpu_ZF;
659 break;
661 case 2: /* cs: C */
662 case 3: /* cc: !C */
663 cond = TCG_COND_NE;
664 value = cpu_CF;
665 break;
667 case 4: /* mi: N */
668 case 5: /* pl: !N */
669 cond = TCG_COND_LT;
670 value = cpu_NF;
671 break;
673 case 6: /* vs: V */
674 case 7: /* vc: !V */
675 cond = TCG_COND_LT;
676 value = cpu_VF;
677 break;
679 case 8: /* hi: C && !Z */
680 case 9: /* ls: !C || Z -> !(C && !Z) */
681 cond = TCG_COND_NE;
682 value = tcg_temp_new_i32();
683 global = false;
684 /* CF is 1 for C, so -CF is an all-bits-set mask for C;
685 ZF is non-zero for !Z; so AND the two subexpressions. */
686 tcg_gen_neg_i32(value, cpu_CF);
687 tcg_gen_and_i32(value, value, cpu_ZF);
688 break;
690 case 10: /* ge: N == V -> N ^ V == 0 */
691 case 11: /* lt: N != V -> N ^ V != 0 */
692 /* Since we're only interested in the sign bit, == 0 is >= 0. */
693 cond = TCG_COND_GE;
694 value = tcg_temp_new_i32();
695 global = false;
696 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
697 break;
699 case 12: /* gt: !Z && N == V */
700 case 13: /* le: Z || N != V */
701 cond = TCG_COND_NE;
702 value = tcg_temp_new_i32();
703 global = false;
704 /* (N == V) is equal to the sign bit of ~(NF ^ VF). Propagate
705 * the sign bit then AND with ZF to yield the result. */
706 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
707 tcg_gen_sari_i32(value, value, 31);
708 tcg_gen_andc_i32(value, cpu_ZF, value);
709 break;
711 case 14: /* always */
712 case 15: /* always */
713 /* Use the ALWAYS condition, which will fold early.
714 * It doesn't matter what we use for the value. */
715 cond = TCG_COND_ALWAYS;
716 value = cpu_ZF;
717 goto no_invert;
719 default:
720 fprintf(stderr, "Bad condition code 0x%x\n", cc);
721 abort();
724 if (cc & 1) {
725 cond = tcg_invert_cond(cond);
728 no_invert:
729 cmp->cond = cond;
730 cmp->value = value;
731 cmp->value_global = global;
734 void arm_free_cc(DisasCompare *cmp)
736 if (!cmp->value_global) {
737 tcg_temp_free_i32(cmp->value);
741 void arm_jump_cc(DisasCompare *cmp, TCGLabel *label)
743 tcg_gen_brcondi_i32(cmp->cond, cmp->value, 0, label);
746 void arm_gen_test_cc(int cc, TCGLabel *label)
748 DisasCompare cmp;
749 arm_test_cc(&cmp, cc);
750 arm_jump_cc(&cmp, label);
751 arm_free_cc(&cmp);
754 static inline void gen_set_condexec(DisasContext *s)
756 if (s->condexec_mask) {
757 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
758 TCGv_i32 tmp = tcg_temp_new_i32();
759 tcg_gen_movi_i32(tmp, val);
760 store_cpu_field(tmp, condexec_bits);
764 static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
766 tcg_gen_movi_i32(cpu_R[15], val);
769 /* Set PC and Thumb state from var. var is marked as dead. */
770 static inline void gen_bx(DisasContext *s, TCGv_i32 var)
772 s->base.is_jmp = DISAS_JUMP;
773 tcg_gen_andi_i32(cpu_R[15], var, ~1);
774 tcg_gen_andi_i32(var, var, 1);
775 store_cpu_field(var, thumb);
779 * Set PC and Thumb state from var. var is marked as dead.
780 * For M-profile CPUs, include logic to detect exception-return
781 * branches and handle them. This is needed for Thumb POP/LDM to PC, LDR to PC,
782 * and BX reg, and no others, and happens only for code in Handler mode.
783 * The Security Extension also requires us to check for the FNC_RETURN
784 * which signals a function return from non-secure state; this can happen
785 * in both Handler and Thread mode.
786 * To avoid having to do multiple comparisons in inline generated code,
787 * we make the check we do here loose, so it will match for EXC_RETURN
788 * in Thread mode. For system emulation do_v7m_exception_exit() checks
789 * for these spurious cases and returns without doing anything (giving
790 * the same behaviour as for a branch to a non-magic address).
792 * In linux-user mode it is unclear what the right behaviour for an
793 * attempted FNC_RETURN should be, because in real hardware this will go
794 * directly to Secure code (ie not the Linux kernel) which will then treat
795 * the error in any way it chooses. For QEMU we opt to make the FNC_RETURN
796 * attempt behave the way it would on a CPU without the security extension,
797 * which is to say "like a normal branch". That means we can simply treat
798 * all branches as normal with no magic address behaviour.
800 static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var)
802 /* Generate the same code here as for a simple bx, but flag via
803 * s->base.is_jmp that we need to do the rest of the work later.
805 gen_bx(s, var);
806 #ifndef CONFIG_USER_ONLY
807 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY) ||
808 (s->v7m_handler_mode && arm_dc_feature(s, ARM_FEATURE_M))) {
809 s->base.is_jmp = DISAS_BX_EXCRET;
811 #endif
814 static inline void gen_bx_excret_final_code(DisasContext *s)
816 /* Generate the code to finish possible exception return and end the TB */
817 TCGLabel *excret_label = gen_new_label();
818 uint32_t min_magic;
820 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY)) {
821 /* Covers FNC_RETURN and EXC_RETURN magic */
822 min_magic = FNC_RETURN_MIN_MAGIC;
823 } else {
824 /* EXC_RETURN magic only */
825 min_magic = EXC_RETURN_MIN_MAGIC;
828 /* Is the new PC value in the magic range indicating exception return? */
829 tcg_gen_brcondi_i32(TCG_COND_GEU, cpu_R[15], min_magic, excret_label);
830 /* No: end the TB as we would for a DISAS_JMP */
831 if (is_singlestepping(s)) {
832 gen_singlestep_exception(s);
833 } else {
834 tcg_gen_exit_tb(NULL, 0);
836 gen_set_label(excret_label);
837 /* Yes: this is an exception return.
838 * At this point in runtime env->regs[15] and env->thumb will hold
839 * the exception-return magic number, which do_v7m_exception_exit()
840 * will read. Nothing else will be able to see those values because
841 * the cpu-exec main loop guarantees that we will always go straight
842 * from raising the exception to the exception-handling code.
844 * gen_ss_advance(s) does nothing on M profile currently but
845 * calling it is conceptually the right thing as we have executed
846 * this instruction (compare SWI, HVC, SMC handling).
848 gen_ss_advance(s);
849 gen_exception_internal(EXCP_EXCEPTION_EXIT);
852 static inline void gen_bxns(DisasContext *s, int rm)
854 TCGv_i32 var = load_reg(s, rm);
856 /* The bxns helper may raise an EXCEPTION_EXIT exception, so in theory
857 * we need to sync state before calling it, but:
858 * - we don't need to do gen_set_pc_im() because the bxns helper will
859 * always set the PC itself
860 * - we don't need to do gen_set_condexec() because BXNS is UNPREDICTABLE
861 * unless it's outside an IT block or the last insn in an IT block,
862 * so we know that condexec == 0 (already set at the top of the TB)
863 * is correct in the non-UNPREDICTABLE cases, and we can choose
864 * "zeroes the IT bits" as our UNPREDICTABLE behaviour otherwise.
866 gen_helper_v7m_bxns(cpu_env, var);
867 tcg_temp_free_i32(var);
868 s->base.is_jmp = DISAS_EXIT;
871 static inline void gen_blxns(DisasContext *s, int rm)
873 TCGv_i32 var = load_reg(s, rm);
875 /* We don't need to sync condexec state, for the same reason as bxns.
876 * We do however need to set the PC, because the blxns helper reads it.
877 * The blxns helper may throw an exception.
879 gen_set_pc_im(s, s->base.pc_next);
880 gen_helper_v7m_blxns(cpu_env, var);
881 tcg_temp_free_i32(var);
882 s->base.is_jmp = DISAS_EXIT;
885 /* Variant of store_reg which uses branch&exchange logic when storing
886 to r15 in ARM architecture v7 and above. The source must be a temporary
887 and will be marked as dead. */
888 static inline void store_reg_bx(DisasContext *s, int reg, TCGv_i32 var)
890 if (reg == 15 && ENABLE_ARCH_7) {
891 gen_bx(s, var);
892 } else {
893 store_reg(s, reg, var);
897 /* Variant of store_reg which uses branch&exchange logic when storing
898 * to r15 in ARM architecture v5T and above. This is used for storing
899 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
900 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
901 static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
903 if (reg == 15 && ENABLE_ARCH_5) {
904 gen_bx_excret(s, var);
905 } else {
906 store_reg(s, reg, var);
910 #ifdef CONFIG_USER_ONLY
911 #define IS_USER_ONLY 1
912 #else
913 #define IS_USER_ONLY 0
914 #endif
916 /* Abstractions of "generate code to do a guest load/store for
917 * AArch32", where a vaddr is always 32 bits (and is zero
918 * extended if we're a 64 bit core) and data is also
919 * 32 bits unless specifically doing a 64 bit access.
920 * These functions work like tcg_gen_qemu_{ld,st}* except
921 * that the address argument is TCGv_i32 rather than TCGv.
924 static inline TCGv gen_aa32_addr(DisasContext *s, TCGv_i32 a32, MemOp op)
926 TCGv addr = tcg_temp_new();
927 tcg_gen_extu_i32_tl(addr, a32);
929 /* Not needed for user-mode BE32, where we use MO_BE instead. */
930 if (!IS_USER_ONLY && s->sctlr_b && (op & MO_SIZE) < MO_32) {
931 tcg_gen_xori_tl(addr, addr, 4 - (1 << (op & MO_SIZE)));
933 return addr;
936 static void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
937 int index, MemOp opc)
939 TCGv addr;
941 if (arm_dc_feature(s, ARM_FEATURE_M) &&
942 !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
943 opc |= MO_ALIGN;
946 addr = gen_aa32_addr(s, a32, opc);
947 tcg_gen_qemu_ld_i32(val, addr, index, opc);
948 tcg_temp_free(addr);
951 static void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
952 int index, MemOp opc)
954 TCGv addr;
956 if (arm_dc_feature(s, ARM_FEATURE_M) &&
957 !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
958 opc |= MO_ALIGN;
961 addr = gen_aa32_addr(s, a32, opc);
962 tcg_gen_qemu_st_i32(val, addr, index, opc);
963 tcg_temp_free(addr);
966 #define DO_GEN_LD(SUFF, OPC) \
967 static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
968 TCGv_i32 a32, int index) \
970 gen_aa32_ld_i32(s, val, a32, index, OPC | s->be_data); \
973 #define DO_GEN_ST(SUFF, OPC) \
974 static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
975 TCGv_i32 a32, int index) \
977 gen_aa32_st_i32(s, val, a32, index, OPC | s->be_data); \
980 static inline void gen_aa32_frob64(DisasContext *s, TCGv_i64 val)
982 /* Not needed for user-mode BE32, where we use MO_BE instead. */
983 if (!IS_USER_ONLY && s->sctlr_b) {
984 tcg_gen_rotri_i64(val, val, 32);
988 static void gen_aa32_ld_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
989 int index, MemOp opc)
991 TCGv addr = gen_aa32_addr(s, a32, opc);
992 tcg_gen_qemu_ld_i64(val, addr, index, opc);
993 gen_aa32_frob64(s, val);
994 tcg_temp_free(addr);
997 static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
998 TCGv_i32 a32, int index)
1000 gen_aa32_ld_i64(s, val, a32, index, MO_Q | s->be_data);
1003 static void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
1004 int index, MemOp opc)
1006 TCGv addr = gen_aa32_addr(s, a32, opc);
1008 /* Not needed for user-mode BE32, where we use MO_BE instead. */
1009 if (!IS_USER_ONLY && s->sctlr_b) {
1010 TCGv_i64 tmp = tcg_temp_new_i64();
1011 tcg_gen_rotri_i64(tmp, val, 32);
1012 tcg_gen_qemu_st_i64(tmp, addr, index, opc);
1013 tcg_temp_free_i64(tmp);
1014 } else {
1015 tcg_gen_qemu_st_i64(val, addr, index, opc);
1017 tcg_temp_free(addr);
1020 static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
1021 TCGv_i32 a32, int index)
1023 gen_aa32_st_i64(s, val, a32, index, MO_Q | s->be_data);
1026 DO_GEN_LD(8u, MO_UB)
1027 DO_GEN_LD(16u, MO_UW)
1028 DO_GEN_LD(32u, MO_UL)
1029 DO_GEN_ST(8, MO_UB)
1030 DO_GEN_ST(16, MO_UW)
1031 DO_GEN_ST(32, MO_UL)
1033 static inline void gen_hvc(DisasContext *s, int imm16)
1035 /* The pre HVC helper handles cases when HVC gets trapped
1036 * as an undefined insn by runtime configuration (ie before
1037 * the insn really executes).
1039 gen_set_pc_im(s, s->pc_curr);
1040 gen_helper_pre_hvc(cpu_env);
1041 /* Otherwise we will treat this as a real exception which
1042 * happens after execution of the insn. (The distinction matters
1043 * for the PC value reported to the exception handler and also
1044 * for single stepping.)
1046 s->svc_imm = imm16;
1047 gen_set_pc_im(s, s->base.pc_next);
1048 s->base.is_jmp = DISAS_HVC;
1051 static inline void gen_smc(DisasContext *s)
1053 /* As with HVC, we may take an exception either before or after
1054 * the insn executes.
1056 TCGv_i32 tmp;
1058 gen_set_pc_im(s, s->pc_curr);
1059 tmp = tcg_const_i32(syn_aa32_smc());
1060 gen_helper_pre_smc(cpu_env, tmp);
1061 tcg_temp_free_i32(tmp);
1062 gen_set_pc_im(s, s->base.pc_next);
1063 s->base.is_jmp = DISAS_SMC;
1066 static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp)
1068 gen_set_condexec(s);
1069 gen_set_pc_im(s, pc);
1070 gen_exception_internal(excp);
1071 s->base.is_jmp = DISAS_NORETURN;
1074 static void gen_exception_insn(DisasContext *s, uint32_t pc, int excp,
1075 int syn, uint32_t target_el)
1077 gen_set_condexec(s);
1078 gen_set_pc_im(s, pc);
1079 gen_exception(excp, syn, target_el);
1080 s->base.is_jmp = DISAS_NORETURN;
1083 static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
1085 TCGv_i32 tcg_syn;
1087 gen_set_condexec(s);
1088 gen_set_pc_im(s, s->pc_curr);
1089 tcg_syn = tcg_const_i32(syn);
1090 gen_helper_exception_bkpt_insn(cpu_env, tcg_syn);
1091 tcg_temp_free_i32(tcg_syn);
1092 s->base.is_jmp = DISAS_NORETURN;
1095 static void unallocated_encoding(DisasContext *s)
1097 /* Unallocated and reserved encodings are uncategorized */
1098 gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(),
1099 default_exception_el(s));
1102 /* Force a TB lookup after an instruction that changes the CPU state. */
1103 static inline void gen_lookup_tb(DisasContext *s)
1105 tcg_gen_movi_i32(cpu_R[15], s->base.pc_next);
1106 s->base.is_jmp = DISAS_EXIT;
1109 static inline void gen_hlt(DisasContext *s, int imm)
1111 /* HLT. This has two purposes.
1112 * Architecturally, it is an external halting debug instruction.
1113 * Since QEMU doesn't implement external debug, we treat this as
1114 * it is required for halting debug disabled: it will UNDEF.
1115 * Secondly, "HLT 0x3C" is a T32 semihosting trap instruction,
1116 * and "HLT 0xF000" is an A32 semihosting syscall. These traps
1117 * must trigger semihosting even for ARMv7 and earlier, where
1118 * HLT was an undefined encoding.
1119 * In system mode, we don't allow userspace access to
1120 * semihosting, to provide some semblance of security
1121 * (and for consistency with our 32-bit semihosting).
1123 if (semihosting_enabled() &&
1124 #ifndef CONFIG_USER_ONLY
1125 s->current_el != 0 &&
1126 #endif
1127 (imm == (s->thumb ? 0x3c : 0xf000))) {
1128 gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
1129 return;
1132 unallocated_encoding(s);
1135 static TCGv_ptr get_fpstatus_ptr(int neon)
1137 TCGv_ptr statusptr = tcg_temp_new_ptr();
1138 int offset;
1139 if (neon) {
1140 offset = offsetof(CPUARMState, vfp.standard_fp_status);
1141 } else {
1142 offset = offsetof(CPUARMState, vfp.fp_status);
1144 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
1145 return statusptr;
1148 static inline long vfp_reg_offset(bool dp, unsigned reg)
1150 if (dp) {
1151 return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]);
1152 } else {
1153 long ofs = offsetof(CPUARMState, vfp.zregs[reg >> 2].d[(reg >> 1) & 1]);
1154 if (reg & 1) {
1155 ofs += offsetof(CPU_DoubleU, l.upper);
1156 } else {
1157 ofs += offsetof(CPU_DoubleU, l.lower);
1159 return ofs;
1163 /* Return the offset of a 32-bit piece of a NEON register.
1164 zero is the least significant end of the register. */
1165 static inline long
1166 neon_reg_offset (int reg, int n)
1168 int sreg;
1169 sreg = reg * 2 + n;
1170 return vfp_reg_offset(0, sreg);
1173 /* Return the offset of a 2**SIZE piece of a NEON register, at index ELE,
1174 * where 0 is the least significant end of the register.
1176 static inline long
1177 neon_element_offset(int reg, int element, MemOp size)
1179 int element_size = 1 << size;
1180 int ofs = element * element_size;
1181 #ifdef HOST_WORDS_BIGENDIAN
1182 /* Calculate the offset assuming fully little-endian,
1183 * then XOR to account for the order of the 8-byte units.
1185 if (element_size < 8) {
1186 ofs ^= 8 - element_size;
1188 #endif
1189 return neon_reg_offset(reg, 0) + ofs;
1192 static TCGv_i32 neon_load_reg(int reg, int pass)
1194 TCGv_i32 tmp = tcg_temp_new_i32();
1195 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1196 return tmp;
1199 static void neon_load_element(TCGv_i32 var, int reg, int ele, MemOp mop)
1201 long offset = neon_element_offset(reg, ele, mop & MO_SIZE);
1203 switch (mop) {
1204 case MO_UB:
1205 tcg_gen_ld8u_i32(var, cpu_env, offset);
1206 break;
1207 case MO_UW:
1208 tcg_gen_ld16u_i32(var, cpu_env, offset);
1209 break;
1210 case MO_UL:
1211 tcg_gen_ld_i32(var, cpu_env, offset);
1212 break;
1213 default:
1214 g_assert_not_reached();
1218 static void neon_load_element64(TCGv_i64 var, int reg, int ele, MemOp mop)
1220 long offset = neon_element_offset(reg, ele, mop & MO_SIZE);
1222 switch (mop) {
1223 case MO_UB:
1224 tcg_gen_ld8u_i64(var, cpu_env, offset);
1225 break;
1226 case MO_UW:
1227 tcg_gen_ld16u_i64(var, cpu_env, offset);
1228 break;
1229 case MO_UL:
1230 tcg_gen_ld32u_i64(var, cpu_env, offset);
1231 break;
1232 case MO_Q:
1233 tcg_gen_ld_i64(var, cpu_env, offset);
1234 break;
1235 default:
1236 g_assert_not_reached();
1240 static void neon_store_reg(int reg, int pass, TCGv_i32 var)
1242 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1243 tcg_temp_free_i32(var);
1246 static void neon_store_element(int reg, int ele, MemOp size, TCGv_i32 var)
1248 long offset = neon_element_offset(reg, ele, size);
1250 switch (size) {
1251 case MO_8:
1252 tcg_gen_st8_i32(var, cpu_env, offset);
1253 break;
1254 case MO_16:
1255 tcg_gen_st16_i32(var, cpu_env, offset);
1256 break;
1257 case MO_32:
1258 tcg_gen_st_i32(var, cpu_env, offset);
1259 break;
1260 default:
1261 g_assert_not_reached();
1265 static void neon_store_element64(int reg, int ele, MemOp size, TCGv_i64 var)
1267 long offset = neon_element_offset(reg, ele, size);
1269 switch (size) {
1270 case MO_8:
1271 tcg_gen_st8_i64(var, cpu_env, offset);
1272 break;
1273 case MO_16:
1274 tcg_gen_st16_i64(var, cpu_env, offset);
1275 break;
1276 case MO_32:
1277 tcg_gen_st32_i64(var, cpu_env, offset);
1278 break;
1279 case MO_64:
1280 tcg_gen_st_i64(var, cpu_env, offset);
1281 break;
1282 default:
1283 g_assert_not_reached();
1287 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1289 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1292 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1294 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1297 static inline void neon_load_reg32(TCGv_i32 var, int reg)
1299 tcg_gen_ld_i32(var, cpu_env, vfp_reg_offset(false, reg));
1302 static inline void neon_store_reg32(TCGv_i32 var, int reg)
1304 tcg_gen_st_i32(var, cpu_env, vfp_reg_offset(false, reg));
1307 static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
1309 TCGv_ptr ret = tcg_temp_new_ptr();
1310 tcg_gen_addi_ptr(ret, cpu_env, vfp_reg_offset(dp, reg));
1311 return ret;
1314 #define ARM_CP_RW_BIT (1 << 20)
1316 /* Include the VFP and Neon decoders */
1317 #include "translate-vfp.inc.c"
1318 #include "translate-neon.inc.c"
1320 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1322 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1325 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1327 tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1330 static inline TCGv_i32 iwmmxt_load_creg(int reg)
1332 TCGv_i32 var = tcg_temp_new_i32();
1333 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1334 return var;
1337 static inline void iwmmxt_store_creg(int reg, TCGv_i32 var)
1339 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1340 tcg_temp_free_i32(var);
1343 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1345 iwmmxt_store_reg(cpu_M0, rn);
1348 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1350 iwmmxt_load_reg(cpu_M0, rn);
1353 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1355 iwmmxt_load_reg(cpu_V1, rn);
1356 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1359 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1361 iwmmxt_load_reg(cpu_V1, rn);
1362 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1365 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1367 iwmmxt_load_reg(cpu_V1, rn);
1368 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1371 #define IWMMXT_OP(name) \
1372 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1374 iwmmxt_load_reg(cpu_V1, rn); \
1375 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1378 #define IWMMXT_OP_ENV(name) \
1379 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1381 iwmmxt_load_reg(cpu_V1, rn); \
1382 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1385 #define IWMMXT_OP_ENV_SIZE(name) \
1386 IWMMXT_OP_ENV(name##b) \
1387 IWMMXT_OP_ENV(name##w) \
1388 IWMMXT_OP_ENV(name##l)
1390 #define IWMMXT_OP_ENV1(name) \
1391 static inline void gen_op_iwmmxt_##name##_M0(void) \
1393 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1396 IWMMXT_OP(maddsq)
1397 IWMMXT_OP(madduq)
1398 IWMMXT_OP(sadb)
1399 IWMMXT_OP(sadw)
1400 IWMMXT_OP(mulslw)
1401 IWMMXT_OP(mulshw)
1402 IWMMXT_OP(mululw)
1403 IWMMXT_OP(muluhw)
1404 IWMMXT_OP(macsw)
1405 IWMMXT_OP(macuw)
1407 IWMMXT_OP_ENV_SIZE(unpackl)
1408 IWMMXT_OP_ENV_SIZE(unpackh)
1410 IWMMXT_OP_ENV1(unpacklub)
1411 IWMMXT_OP_ENV1(unpackluw)
1412 IWMMXT_OP_ENV1(unpacklul)
1413 IWMMXT_OP_ENV1(unpackhub)
1414 IWMMXT_OP_ENV1(unpackhuw)
1415 IWMMXT_OP_ENV1(unpackhul)
1416 IWMMXT_OP_ENV1(unpacklsb)
1417 IWMMXT_OP_ENV1(unpacklsw)
1418 IWMMXT_OP_ENV1(unpacklsl)
1419 IWMMXT_OP_ENV1(unpackhsb)
1420 IWMMXT_OP_ENV1(unpackhsw)
1421 IWMMXT_OP_ENV1(unpackhsl)
1423 IWMMXT_OP_ENV_SIZE(cmpeq)
1424 IWMMXT_OP_ENV_SIZE(cmpgtu)
1425 IWMMXT_OP_ENV_SIZE(cmpgts)
1427 IWMMXT_OP_ENV_SIZE(mins)
1428 IWMMXT_OP_ENV_SIZE(minu)
1429 IWMMXT_OP_ENV_SIZE(maxs)
1430 IWMMXT_OP_ENV_SIZE(maxu)
1432 IWMMXT_OP_ENV_SIZE(subn)
1433 IWMMXT_OP_ENV_SIZE(addn)
1434 IWMMXT_OP_ENV_SIZE(subu)
1435 IWMMXT_OP_ENV_SIZE(addu)
1436 IWMMXT_OP_ENV_SIZE(subs)
1437 IWMMXT_OP_ENV_SIZE(adds)
1439 IWMMXT_OP_ENV(avgb0)
1440 IWMMXT_OP_ENV(avgb1)
1441 IWMMXT_OP_ENV(avgw0)
1442 IWMMXT_OP_ENV(avgw1)
1444 IWMMXT_OP_ENV(packuw)
1445 IWMMXT_OP_ENV(packul)
1446 IWMMXT_OP_ENV(packuq)
1447 IWMMXT_OP_ENV(packsw)
1448 IWMMXT_OP_ENV(packsl)
1449 IWMMXT_OP_ENV(packsq)
1451 static void gen_op_iwmmxt_set_mup(void)
1453 TCGv_i32 tmp;
1454 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1455 tcg_gen_ori_i32(tmp, tmp, 2);
1456 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1459 static void gen_op_iwmmxt_set_cup(void)
1461 TCGv_i32 tmp;
1462 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1463 tcg_gen_ori_i32(tmp, tmp, 1);
1464 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1467 static void gen_op_iwmmxt_setpsr_nz(void)
1469 TCGv_i32 tmp = tcg_temp_new_i32();
1470 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1471 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1474 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1476 iwmmxt_load_reg(cpu_V1, rn);
1477 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1478 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1481 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn,
1482 TCGv_i32 dest)
1484 int rd;
1485 uint32_t offset;
1486 TCGv_i32 tmp;
1488 rd = (insn >> 16) & 0xf;
1489 tmp = load_reg(s, rd);
1491 offset = (insn & 0xff) << ((insn >> 7) & 2);
1492 if (insn & (1 << 24)) {
1493 /* Pre indexed */
1494 if (insn & (1 << 23))
1495 tcg_gen_addi_i32(tmp, tmp, offset);
1496 else
1497 tcg_gen_addi_i32(tmp, tmp, -offset);
1498 tcg_gen_mov_i32(dest, tmp);
1499 if (insn & (1 << 21))
1500 store_reg(s, rd, tmp);
1501 else
1502 tcg_temp_free_i32(tmp);
1503 } else if (insn & (1 << 21)) {
1504 /* Post indexed */
1505 tcg_gen_mov_i32(dest, tmp);
1506 if (insn & (1 << 23))
1507 tcg_gen_addi_i32(tmp, tmp, offset);
1508 else
1509 tcg_gen_addi_i32(tmp, tmp, -offset);
1510 store_reg(s, rd, tmp);
1511 } else if (!(insn & (1 << 23)))
1512 return 1;
1513 return 0;
1516 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest)
1518 int rd = (insn >> 0) & 0xf;
1519 TCGv_i32 tmp;
1521 if (insn & (1 << 8)) {
1522 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1523 return 1;
1524 } else {
1525 tmp = iwmmxt_load_creg(rd);
1527 } else {
1528 tmp = tcg_temp_new_i32();
1529 iwmmxt_load_reg(cpu_V0, rd);
1530 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
1532 tcg_gen_andi_i32(tmp, tmp, mask);
1533 tcg_gen_mov_i32(dest, tmp);
1534 tcg_temp_free_i32(tmp);
1535 return 0;
1538 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
1539 (ie. an undefined instruction). */
1540 static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
1542 int rd, wrd;
1543 int rdhi, rdlo, rd0, rd1, i;
1544 TCGv_i32 addr;
1545 TCGv_i32 tmp, tmp2, tmp3;
1547 if ((insn & 0x0e000e00) == 0x0c000000) {
1548 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1549 wrd = insn & 0xf;
1550 rdlo = (insn >> 12) & 0xf;
1551 rdhi = (insn >> 16) & 0xf;
1552 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1553 iwmmxt_load_reg(cpu_V0, wrd);
1554 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
1555 tcg_gen_extrh_i64_i32(cpu_R[rdhi], cpu_V0);
1556 } else { /* TMCRR */
1557 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1558 iwmmxt_store_reg(cpu_V0, wrd);
1559 gen_op_iwmmxt_set_mup();
1561 return 0;
1564 wrd = (insn >> 12) & 0xf;
1565 addr = tcg_temp_new_i32();
1566 if (gen_iwmmxt_address(s, insn, addr)) {
1567 tcg_temp_free_i32(addr);
1568 return 1;
1570 if (insn & ARM_CP_RW_BIT) {
1571 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1572 tmp = tcg_temp_new_i32();
1573 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
1574 iwmmxt_store_creg(wrd, tmp);
1575 } else {
1576 i = 1;
1577 if (insn & (1 << 8)) {
1578 if (insn & (1 << 22)) { /* WLDRD */
1579 gen_aa32_ld64(s, cpu_M0, addr, get_mem_index(s));
1580 i = 0;
1581 } else { /* WLDRW wRd */
1582 tmp = tcg_temp_new_i32();
1583 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
1585 } else {
1586 tmp = tcg_temp_new_i32();
1587 if (insn & (1 << 22)) { /* WLDRH */
1588 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
1589 } else { /* WLDRB */
1590 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
1593 if (i) {
1594 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1595 tcg_temp_free_i32(tmp);
1597 gen_op_iwmmxt_movq_wRn_M0(wrd);
1599 } else {
1600 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1601 tmp = iwmmxt_load_creg(wrd);
1602 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
1603 } else {
1604 gen_op_iwmmxt_movq_M0_wRn(wrd);
1605 tmp = tcg_temp_new_i32();
1606 if (insn & (1 << 8)) {
1607 if (insn & (1 << 22)) { /* WSTRD */
1608 gen_aa32_st64(s, cpu_M0, addr, get_mem_index(s));
1609 } else { /* WSTRW wRd */
1610 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1611 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
1613 } else {
1614 if (insn & (1 << 22)) { /* WSTRH */
1615 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1616 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
1617 } else { /* WSTRB */
1618 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1619 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
1623 tcg_temp_free_i32(tmp);
1625 tcg_temp_free_i32(addr);
1626 return 0;
1629 if ((insn & 0x0f000000) != 0x0e000000)
1630 return 1;
1632 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1633 case 0x000: /* WOR */
1634 wrd = (insn >> 12) & 0xf;
1635 rd0 = (insn >> 0) & 0xf;
1636 rd1 = (insn >> 16) & 0xf;
1637 gen_op_iwmmxt_movq_M0_wRn(rd0);
1638 gen_op_iwmmxt_orq_M0_wRn(rd1);
1639 gen_op_iwmmxt_setpsr_nz();
1640 gen_op_iwmmxt_movq_wRn_M0(wrd);
1641 gen_op_iwmmxt_set_mup();
1642 gen_op_iwmmxt_set_cup();
1643 break;
1644 case 0x011: /* TMCR */
1645 if (insn & 0xf)
1646 return 1;
1647 rd = (insn >> 12) & 0xf;
1648 wrd = (insn >> 16) & 0xf;
1649 switch (wrd) {
1650 case ARM_IWMMXT_wCID:
1651 case ARM_IWMMXT_wCASF:
1652 break;
1653 case ARM_IWMMXT_wCon:
1654 gen_op_iwmmxt_set_cup();
1655 /* Fall through. */
1656 case ARM_IWMMXT_wCSSF:
1657 tmp = iwmmxt_load_creg(wrd);
1658 tmp2 = load_reg(s, rd);
1659 tcg_gen_andc_i32(tmp, tmp, tmp2);
1660 tcg_temp_free_i32(tmp2);
1661 iwmmxt_store_creg(wrd, tmp);
1662 break;
1663 case ARM_IWMMXT_wCGR0:
1664 case ARM_IWMMXT_wCGR1:
1665 case ARM_IWMMXT_wCGR2:
1666 case ARM_IWMMXT_wCGR3:
1667 gen_op_iwmmxt_set_cup();
1668 tmp = load_reg(s, rd);
1669 iwmmxt_store_creg(wrd, tmp);
1670 break;
1671 default:
1672 return 1;
1674 break;
1675 case 0x100: /* WXOR */
1676 wrd = (insn >> 12) & 0xf;
1677 rd0 = (insn >> 0) & 0xf;
1678 rd1 = (insn >> 16) & 0xf;
1679 gen_op_iwmmxt_movq_M0_wRn(rd0);
1680 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1681 gen_op_iwmmxt_setpsr_nz();
1682 gen_op_iwmmxt_movq_wRn_M0(wrd);
1683 gen_op_iwmmxt_set_mup();
1684 gen_op_iwmmxt_set_cup();
1685 break;
1686 case 0x111: /* TMRC */
1687 if (insn & 0xf)
1688 return 1;
1689 rd = (insn >> 12) & 0xf;
1690 wrd = (insn >> 16) & 0xf;
1691 tmp = iwmmxt_load_creg(wrd);
1692 store_reg(s, rd, tmp);
1693 break;
1694 case 0x300: /* WANDN */
1695 wrd = (insn >> 12) & 0xf;
1696 rd0 = (insn >> 0) & 0xf;
1697 rd1 = (insn >> 16) & 0xf;
1698 gen_op_iwmmxt_movq_M0_wRn(rd0);
1699 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1700 gen_op_iwmmxt_andq_M0_wRn(rd1);
1701 gen_op_iwmmxt_setpsr_nz();
1702 gen_op_iwmmxt_movq_wRn_M0(wrd);
1703 gen_op_iwmmxt_set_mup();
1704 gen_op_iwmmxt_set_cup();
1705 break;
1706 case 0x200: /* WAND */
1707 wrd = (insn >> 12) & 0xf;
1708 rd0 = (insn >> 0) & 0xf;
1709 rd1 = (insn >> 16) & 0xf;
1710 gen_op_iwmmxt_movq_M0_wRn(rd0);
1711 gen_op_iwmmxt_andq_M0_wRn(rd1);
1712 gen_op_iwmmxt_setpsr_nz();
1713 gen_op_iwmmxt_movq_wRn_M0(wrd);
1714 gen_op_iwmmxt_set_mup();
1715 gen_op_iwmmxt_set_cup();
1716 break;
1717 case 0x810: case 0xa10: /* WMADD */
1718 wrd = (insn >> 12) & 0xf;
1719 rd0 = (insn >> 0) & 0xf;
1720 rd1 = (insn >> 16) & 0xf;
1721 gen_op_iwmmxt_movq_M0_wRn(rd0);
1722 if (insn & (1 << 21))
1723 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1724 else
1725 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1726 gen_op_iwmmxt_movq_wRn_M0(wrd);
1727 gen_op_iwmmxt_set_mup();
1728 break;
1729 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1730 wrd = (insn >> 12) & 0xf;
1731 rd0 = (insn >> 16) & 0xf;
1732 rd1 = (insn >> 0) & 0xf;
1733 gen_op_iwmmxt_movq_M0_wRn(rd0);
1734 switch ((insn >> 22) & 3) {
1735 case 0:
1736 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1737 break;
1738 case 1:
1739 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1740 break;
1741 case 2:
1742 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1743 break;
1744 case 3:
1745 return 1;
1747 gen_op_iwmmxt_movq_wRn_M0(wrd);
1748 gen_op_iwmmxt_set_mup();
1749 gen_op_iwmmxt_set_cup();
1750 break;
1751 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1752 wrd = (insn >> 12) & 0xf;
1753 rd0 = (insn >> 16) & 0xf;
1754 rd1 = (insn >> 0) & 0xf;
1755 gen_op_iwmmxt_movq_M0_wRn(rd0);
1756 switch ((insn >> 22) & 3) {
1757 case 0:
1758 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1759 break;
1760 case 1:
1761 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1762 break;
1763 case 2:
1764 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1765 break;
1766 case 3:
1767 return 1;
1769 gen_op_iwmmxt_movq_wRn_M0(wrd);
1770 gen_op_iwmmxt_set_mup();
1771 gen_op_iwmmxt_set_cup();
1772 break;
1773 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1774 wrd = (insn >> 12) & 0xf;
1775 rd0 = (insn >> 16) & 0xf;
1776 rd1 = (insn >> 0) & 0xf;
1777 gen_op_iwmmxt_movq_M0_wRn(rd0);
1778 if (insn & (1 << 22))
1779 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1780 else
1781 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1782 if (!(insn & (1 << 20)))
1783 gen_op_iwmmxt_addl_M0_wRn(wrd);
1784 gen_op_iwmmxt_movq_wRn_M0(wrd);
1785 gen_op_iwmmxt_set_mup();
1786 break;
1787 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1788 wrd = (insn >> 12) & 0xf;
1789 rd0 = (insn >> 16) & 0xf;
1790 rd1 = (insn >> 0) & 0xf;
1791 gen_op_iwmmxt_movq_M0_wRn(rd0);
1792 if (insn & (1 << 21)) {
1793 if (insn & (1 << 20))
1794 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1795 else
1796 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1797 } else {
1798 if (insn & (1 << 20))
1799 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1800 else
1801 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1803 gen_op_iwmmxt_movq_wRn_M0(wrd);
1804 gen_op_iwmmxt_set_mup();
1805 break;
1806 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1807 wrd = (insn >> 12) & 0xf;
1808 rd0 = (insn >> 16) & 0xf;
1809 rd1 = (insn >> 0) & 0xf;
1810 gen_op_iwmmxt_movq_M0_wRn(rd0);
1811 if (insn & (1 << 21))
1812 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1813 else
1814 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1815 if (!(insn & (1 << 20))) {
1816 iwmmxt_load_reg(cpu_V1, wrd);
1817 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1819 gen_op_iwmmxt_movq_wRn_M0(wrd);
1820 gen_op_iwmmxt_set_mup();
1821 break;
1822 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1823 wrd = (insn >> 12) & 0xf;
1824 rd0 = (insn >> 16) & 0xf;
1825 rd1 = (insn >> 0) & 0xf;
1826 gen_op_iwmmxt_movq_M0_wRn(rd0);
1827 switch ((insn >> 22) & 3) {
1828 case 0:
1829 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1830 break;
1831 case 1:
1832 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1833 break;
1834 case 2:
1835 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1836 break;
1837 case 3:
1838 return 1;
1840 gen_op_iwmmxt_movq_wRn_M0(wrd);
1841 gen_op_iwmmxt_set_mup();
1842 gen_op_iwmmxt_set_cup();
1843 break;
1844 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1845 wrd = (insn >> 12) & 0xf;
1846 rd0 = (insn >> 16) & 0xf;
1847 rd1 = (insn >> 0) & 0xf;
1848 gen_op_iwmmxt_movq_M0_wRn(rd0);
1849 if (insn & (1 << 22)) {
1850 if (insn & (1 << 20))
1851 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1852 else
1853 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1854 } else {
1855 if (insn & (1 << 20))
1856 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1857 else
1858 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1860 gen_op_iwmmxt_movq_wRn_M0(wrd);
1861 gen_op_iwmmxt_set_mup();
1862 gen_op_iwmmxt_set_cup();
1863 break;
1864 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1865 wrd = (insn >> 12) & 0xf;
1866 rd0 = (insn >> 16) & 0xf;
1867 rd1 = (insn >> 0) & 0xf;
1868 gen_op_iwmmxt_movq_M0_wRn(rd0);
1869 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1870 tcg_gen_andi_i32(tmp, tmp, 7);
1871 iwmmxt_load_reg(cpu_V1, rd1);
1872 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
1873 tcg_temp_free_i32(tmp);
1874 gen_op_iwmmxt_movq_wRn_M0(wrd);
1875 gen_op_iwmmxt_set_mup();
1876 break;
1877 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1878 if (((insn >> 6) & 3) == 3)
1879 return 1;
1880 rd = (insn >> 12) & 0xf;
1881 wrd = (insn >> 16) & 0xf;
1882 tmp = load_reg(s, rd);
1883 gen_op_iwmmxt_movq_M0_wRn(wrd);
1884 switch ((insn >> 6) & 3) {
1885 case 0:
1886 tmp2 = tcg_const_i32(0xff);
1887 tmp3 = tcg_const_i32((insn & 7) << 3);
1888 break;
1889 case 1:
1890 tmp2 = tcg_const_i32(0xffff);
1891 tmp3 = tcg_const_i32((insn & 3) << 4);
1892 break;
1893 case 2:
1894 tmp2 = tcg_const_i32(0xffffffff);
1895 tmp3 = tcg_const_i32((insn & 1) << 5);
1896 break;
1897 default:
1898 tmp2 = NULL;
1899 tmp3 = NULL;
1901 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
1902 tcg_temp_free_i32(tmp3);
1903 tcg_temp_free_i32(tmp2);
1904 tcg_temp_free_i32(tmp);
1905 gen_op_iwmmxt_movq_wRn_M0(wrd);
1906 gen_op_iwmmxt_set_mup();
1907 break;
1908 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1909 rd = (insn >> 12) & 0xf;
1910 wrd = (insn >> 16) & 0xf;
1911 if (rd == 15 || ((insn >> 22) & 3) == 3)
1912 return 1;
1913 gen_op_iwmmxt_movq_M0_wRn(wrd);
1914 tmp = tcg_temp_new_i32();
1915 switch ((insn >> 22) & 3) {
1916 case 0:
1917 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
1918 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1919 if (insn & 8) {
1920 tcg_gen_ext8s_i32(tmp, tmp);
1921 } else {
1922 tcg_gen_andi_i32(tmp, tmp, 0xff);
1924 break;
1925 case 1:
1926 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
1927 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1928 if (insn & 8) {
1929 tcg_gen_ext16s_i32(tmp, tmp);
1930 } else {
1931 tcg_gen_andi_i32(tmp, tmp, 0xffff);
1933 break;
1934 case 2:
1935 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
1936 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1937 break;
1939 store_reg(s, rd, tmp);
1940 break;
1941 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1942 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1943 return 1;
1944 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1945 switch ((insn >> 22) & 3) {
1946 case 0:
1947 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
1948 break;
1949 case 1:
1950 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
1951 break;
1952 case 2:
1953 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
1954 break;
1956 tcg_gen_shli_i32(tmp, tmp, 28);
1957 gen_set_nzcv(tmp);
1958 tcg_temp_free_i32(tmp);
1959 break;
1960 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1961 if (((insn >> 6) & 3) == 3)
1962 return 1;
1963 rd = (insn >> 12) & 0xf;
1964 wrd = (insn >> 16) & 0xf;
1965 tmp = load_reg(s, rd);
1966 switch ((insn >> 6) & 3) {
1967 case 0:
1968 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
1969 break;
1970 case 1:
1971 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
1972 break;
1973 case 2:
1974 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
1975 break;
1977 tcg_temp_free_i32(tmp);
1978 gen_op_iwmmxt_movq_wRn_M0(wrd);
1979 gen_op_iwmmxt_set_mup();
1980 break;
1981 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1982 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1983 return 1;
1984 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1985 tmp2 = tcg_temp_new_i32();
1986 tcg_gen_mov_i32(tmp2, tmp);
1987 switch ((insn >> 22) & 3) {
1988 case 0:
1989 for (i = 0; i < 7; i ++) {
1990 tcg_gen_shli_i32(tmp2, tmp2, 4);
1991 tcg_gen_and_i32(tmp, tmp, tmp2);
1993 break;
1994 case 1:
1995 for (i = 0; i < 3; i ++) {
1996 tcg_gen_shli_i32(tmp2, tmp2, 8);
1997 tcg_gen_and_i32(tmp, tmp, tmp2);
1999 break;
2000 case 2:
2001 tcg_gen_shli_i32(tmp2, tmp2, 16);
2002 tcg_gen_and_i32(tmp, tmp, tmp2);
2003 break;
2005 gen_set_nzcv(tmp);
2006 tcg_temp_free_i32(tmp2);
2007 tcg_temp_free_i32(tmp);
2008 break;
2009 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
2010 wrd = (insn >> 12) & 0xf;
2011 rd0 = (insn >> 16) & 0xf;
2012 gen_op_iwmmxt_movq_M0_wRn(rd0);
2013 switch ((insn >> 22) & 3) {
2014 case 0:
2015 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
2016 break;
2017 case 1:
2018 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
2019 break;
2020 case 2:
2021 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
2022 break;
2023 case 3:
2024 return 1;
2026 gen_op_iwmmxt_movq_wRn_M0(wrd);
2027 gen_op_iwmmxt_set_mup();
2028 break;
2029 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
2030 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
2031 return 1;
2032 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
2033 tmp2 = tcg_temp_new_i32();
2034 tcg_gen_mov_i32(tmp2, tmp);
2035 switch ((insn >> 22) & 3) {
2036 case 0:
2037 for (i = 0; i < 7; i ++) {
2038 tcg_gen_shli_i32(tmp2, tmp2, 4);
2039 tcg_gen_or_i32(tmp, tmp, tmp2);
2041 break;
2042 case 1:
2043 for (i = 0; i < 3; i ++) {
2044 tcg_gen_shli_i32(tmp2, tmp2, 8);
2045 tcg_gen_or_i32(tmp, tmp, tmp2);
2047 break;
2048 case 2:
2049 tcg_gen_shli_i32(tmp2, tmp2, 16);
2050 tcg_gen_or_i32(tmp, tmp, tmp2);
2051 break;
2053 gen_set_nzcv(tmp);
2054 tcg_temp_free_i32(tmp2);
2055 tcg_temp_free_i32(tmp);
2056 break;
2057 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
2058 rd = (insn >> 12) & 0xf;
2059 rd0 = (insn >> 16) & 0xf;
2060 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
2061 return 1;
2062 gen_op_iwmmxt_movq_M0_wRn(rd0);
2063 tmp = tcg_temp_new_i32();
2064 switch ((insn >> 22) & 3) {
2065 case 0:
2066 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
2067 break;
2068 case 1:
2069 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
2070 break;
2071 case 2:
2072 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
2073 break;
2075 store_reg(s, rd, tmp);
2076 break;
2077 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
2078 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2079 wrd = (insn >> 12) & 0xf;
2080 rd0 = (insn >> 16) & 0xf;
2081 rd1 = (insn >> 0) & 0xf;
2082 gen_op_iwmmxt_movq_M0_wRn(rd0);
2083 switch ((insn >> 22) & 3) {
2084 case 0:
2085 if (insn & (1 << 21))
2086 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2087 else
2088 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2089 break;
2090 case 1:
2091 if (insn & (1 << 21))
2092 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2093 else
2094 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2095 break;
2096 case 2:
2097 if (insn & (1 << 21))
2098 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2099 else
2100 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2101 break;
2102 case 3:
2103 return 1;
2105 gen_op_iwmmxt_movq_wRn_M0(wrd);
2106 gen_op_iwmmxt_set_mup();
2107 gen_op_iwmmxt_set_cup();
2108 break;
2109 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2110 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2111 wrd = (insn >> 12) & 0xf;
2112 rd0 = (insn >> 16) & 0xf;
2113 gen_op_iwmmxt_movq_M0_wRn(rd0);
2114 switch ((insn >> 22) & 3) {
2115 case 0:
2116 if (insn & (1 << 21))
2117 gen_op_iwmmxt_unpacklsb_M0();
2118 else
2119 gen_op_iwmmxt_unpacklub_M0();
2120 break;
2121 case 1:
2122 if (insn & (1 << 21))
2123 gen_op_iwmmxt_unpacklsw_M0();
2124 else
2125 gen_op_iwmmxt_unpackluw_M0();
2126 break;
2127 case 2:
2128 if (insn & (1 << 21))
2129 gen_op_iwmmxt_unpacklsl_M0();
2130 else
2131 gen_op_iwmmxt_unpacklul_M0();
2132 break;
2133 case 3:
2134 return 1;
2136 gen_op_iwmmxt_movq_wRn_M0(wrd);
2137 gen_op_iwmmxt_set_mup();
2138 gen_op_iwmmxt_set_cup();
2139 break;
2140 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2141 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2142 wrd = (insn >> 12) & 0xf;
2143 rd0 = (insn >> 16) & 0xf;
2144 gen_op_iwmmxt_movq_M0_wRn(rd0);
2145 switch ((insn >> 22) & 3) {
2146 case 0:
2147 if (insn & (1 << 21))
2148 gen_op_iwmmxt_unpackhsb_M0();
2149 else
2150 gen_op_iwmmxt_unpackhub_M0();
2151 break;
2152 case 1:
2153 if (insn & (1 << 21))
2154 gen_op_iwmmxt_unpackhsw_M0();
2155 else
2156 gen_op_iwmmxt_unpackhuw_M0();
2157 break;
2158 case 2:
2159 if (insn & (1 << 21))
2160 gen_op_iwmmxt_unpackhsl_M0();
2161 else
2162 gen_op_iwmmxt_unpackhul_M0();
2163 break;
2164 case 3:
2165 return 1;
2167 gen_op_iwmmxt_movq_wRn_M0(wrd);
2168 gen_op_iwmmxt_set_mup();
2169 gen_op_iwmmxt_set_cup();
2170 break;
2171 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2172 case 0x214: case 0x614: case 0xa14: case 0xe14:
2173 if (((insn >> 22) & 3) == 0)
2174 return 1;
2175 wrd = (insn >> 12) & 0xf;
2176 rd0 = (insn >> 16) & 0xf;
2177 gen_op_iwmmxt_movq_M0_wRn(rd0);
2178 tmp = tcg_temp_new_i32();
2179 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2180 tcg_temp_free_i32(tmp);
2181 return 1;
2183 switch ((insn >> 22) & 3) {
2184 case 1:
2185 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
2186 break;
2187 case 2:
2188 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
2189 break;
2190 case 3:
2191 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
2192 break;
2194 tcg_temp_free_i32(tmp);
2195 gen_op_iwmmxt_movq_wRn_M0(wrd);
2196 gen_op_iwmmxt_set_mup();
2197 gen_op_iwmmxt_set_cup();
2198 break;
2199 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2200 case 0x014: case 0x414: case 0x814: case 0xc14:
2201 if (((insn >> 22) & 3) == 0)
2202 return 1;
2203 wrd = (insn >> 12) & 0xf;
2204 rd0 = (insn >> 16) & 0xf;
2205 gen_op_iwmmxt_movq_M0_wRn(rd0);
2206 tmp = tcg_temp_new_i32();
2207 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2208 tcg_temp_free_i32(tmp);
2209 return 1;
2211 switch ((insn >> 22) & 3) {
2212 case 1:
2213 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2214 break;
2215 case 2:
2216 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2217 break;
2218 case 3:
2219 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2220 break;
2222 tcg_temp_free_i32(tmp);
2223 gen_op_iwmmxt_movq_wRn_M0(wrd);
2224 gen_op_iwmmxt_set_mup();
2225 gen_op_iwmmxt_set_cup();
2226 break;
2227 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2228 case 0x114: case 0x514: case 0x914: case 0xd14:
2229 if (((insn >> 22) & 3) == 0)
2230 return 1;
2231 wrd = (insn >> 12) & 0xf;
2232 rd0 = (insn >> 16) & 0xf;
2233 gen_op_iwmmxt_movq_M0_wRn(rd0);
2234 tmp = tcg_temp_new_i32();
2235 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2236 tcg_temp_free_i32(tmp);
2237 return 1;
2239 switch ((insn >> 22) & 3) {
2240 case 1:
2241 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2242 break;
2243 case 2:
2244 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2245 break;
2246 case 3:
2247 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2248 break;
2250 tcg_temp_free_i32(tmp);
2251 gen_op_iwmmxt_movq_wRn_M0(wrd);
2252 gen_op_iwmmxt_set_mup();
2253 gen_op_iwmmxt_set_cup();
2254 break;
2255 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2256 case 0x314: case 0x714: case 0xb14: case 0xf14:
2257 if (((insn >> 22) & 3) == 0)
2258 return 1;
2259 wrd = (insn >> 12) & 0xf;
2260 rd0 = (insn >> 16) & 0xf;
2261 gen_op_iwmmxt_movq_M0_wRn(rd0);
2262 tmp = tcg_temp_new_i32();
2263 switch ((insn >> 22) & 3) {
2264 case 1:
2265 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2266 tcg_temp_free_i32(tmp);
2267 return 1;
2269 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2270 break;
2271 case 2:
2272 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2273 tcg_temp_free_i32(tmp);
2274 return 1;
2276 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2277 break;
2278 case 3:
2279 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2280 tcg_temp_free_i32(tmp);
2281 return 1;
2283 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2284 break;
2286 tcg_temp_free_i32(tmp);
2287 gen_op_iwmmxt_movq_wRn_M0(wrd);
2288 gen_op_iwmmxt_set_mup();
2289 gen_op_iwmmxt_set_cup();
2290 break;
2291 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2292 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2293 wrd = (insn >> 12) & 0xf;
2294 rd0 = (insn >> 16) & 0xf;
2295 rd1 = (insn >> 0) & 0xf;
2296 gen_op_iwmmxt_movq_M0_wRn(rd0);
2297 switch ((insn >> 22) & 3) {
2298 case 0:
2299 if (insn & (1 << 21))
2300 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2301 else
2302 gen_op_iwmmxt_minub_M0_wRn(rd1);
2303 break;
2304 case 1:
2305 if (insn & (1 << 21))
2306 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2307 else
2308 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2309 break;
2310 case 2:
2311 if (insn & (1 << 21))
2312 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2313 else
2314 gen_op_iwmmxt_minul_M0_wRn(rd1);
2315 break;
2316 case 3:
2317 return 1;
2319 gen_op_iwmmxt_movq_wRn_M0(wrd);
2320 gen_op_iwmmxt_set_mup();
2321 break;
2322 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2323 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2324 wrd = (insn >> 12) & 0xf;
2325 rd0 = (insn >> 16) & 0xf;
2326 rd1 = (insn >> 0) & 0xf;
2327 gen_op_iwmmxt_movq_M0_wRn(rd0);
2328 switch ((insn >> 22) & 3) {
2329 case 0:
2330 if (insn & (1 << 21))
2331 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2332 else
2333 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2334 break;
2335 case 1:
2336 if (insn & (1 << 21))
2337 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2338 else
2339 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2340 break;
2341 case 2:
2342 if (insn & (1 << 21))
2343 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2344 else
2345 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2346 break;
2347 case 3:
2348 return 1;
2350 gen_op_iwmmxt_movq_wRn_M0(wrd);
2351 gen_op_iwmmxt_set_mup();
2352 break;
2353 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2354 case 0x402: case 0x502: case 0x602: case 0x702:
2355 wrd = (insn >> 12) & 0xf;
2356 rd0 = (insn >> 16) & 0xf;
2357 rd1 = (insn >> 0) & 0xf;
2358 gen_op_iwmmxt_movq_M0_wRn(rd0);
2359 tmp = tcg_const_i32((insn >> 20) & 3);
2360 iwmmxt_load_reg(cpu_V1, rd1);
2361 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2362 tcg_temp_free_i32(tmp);
2363 gen_op_iwmmxt_movq_wRn_M0(wrd);
2364 gen_op_iwmmxt_set_mup();
2365 break;
2366 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2367 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2368 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2369 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2370 wrd = (insn >> 12) & 0xf;
2371 rd0 = (insn >> 16) & 0xf;
2372 rd1 = (insn >> 0) & 0xf;
2373 gen_op_iwmmxt_movq_M0_wRn(rd0);
2374 switch ((insn >> 20) & 0xf) {
2375 case 0x0:
2376 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2377 break;
2378 case 0x1:
2379 gen_op_iwmmxt_subub_M0_wRn(rd1);
2380 break;
2381 case 0x3:
2382 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2383 break;
2384 case 0x4:
2385 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2386 break;
2387 case 0x5:
2388 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2389 break;
2390 case 0x7:
2391 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2392 break;
2393 case 0x8:
2394 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2395 break;
2396 case 0x9:
2397 gen_op_iwmmxt_subul_M0_wRn(rd1);
2398 break;
2399 case 0xb:
2400 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2401 break;
2402 default:
2403 return 1;
2405 gen_op_iwmmxt_movq_wRn_M0(wrd);
2406 gen_op_iwmmxt_set_mup();
2407 gen_op_iwmmxt_set_cup();
2408 break;
2409 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2410 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2411 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2412 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2413 wrd = (insn >> 12) & 0xf;
2414 rd0 = (insn >> 16) & 0xf;
2415 gen_op_iwmmxt_movq_M0_wRn(rd0);
2416 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2417 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2418 tcg_temp_free_i32(tmp);
2419 gen_op_iwmmxt_movq_wRn_M0(wrd);
2420 gen_op_iwmmxt_set_mup();
2421 gen_op_iwmmxt_set_cup();
2422 break;
2423 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2424 case 0x418: case 0x518: case 0x618: case 0x718:
2425 case 0x818: case 0x918: case 0xa18: case 0xb18:
2426 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2427 wrd = (insn >> 12) & 0xf;
2428 rd0 = (insn >> 16) & 0xf;
2429 rd1 = (insn >> 0) & 0xf;
2430 gen_op_iwmmxt_movq_M0_wRn(rd0);
2431 switch ((insn >> 20) & 0xf) {
2432 case 0x0:
2433 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2434 break;
2435 case 0x1:
2436 gen_op_iwmmxt_addub_M0_wRn(rd1);
2437 break;
2438 case 0x3:
2439 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2440 break;
2441 case 0x4:
2442 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2443 break;
2444 case 0x5:
2445 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2446 break;
2447 case 0x7:
2448 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2449 break;
2450 case 0x8:
2451 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2452 break;
2453 case 0x9:
2454 gen_op_iwmmxt_addul_M0_wRn(rd1);
2455 break;
2456 case 0xb:
2457 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2458 break;
2459 default:
2460 return 1;
2462 gen_op_iwmmxt_movq_wRn_M0(wrd);
2463 gen_op_iwmmxt_set_mup();
2464 gen_op_iwmmxt_set_cup();
2465 break;
2466 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2467 case 0x408: case 0x508: case 0x608: case 0x708:
2468 case 0x808: case 0x908: case 0xa08: case 0xb08:
2469 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2470 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2471 return 1;
2472 wrd = (insn >> 12) & 0xf;
2473 rd0 = (insn >> 16) & 0xf;
2474 rd1 = (insn >> 0) & 0xf;
2475 gen_op_iwmmxt_movq_M0_wRn(rd0);
2476 switch ((insn >> 22) & 3) {
2477 case 1:
2478 if (insn & (1 << 21))
2479 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2480 else
2481 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2482 break;
2483 case 2:
2484 if (insn & (1 << 21))
2485 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2486 else
2487 gen_op_iwmmxt_packul_M0_wRn(rd1);
2488 break;
2489 case 3:
2490 if (insn & (1 << 21))
2491 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2492 else
2493 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2494 break;
2496 gen_op_iwmmxt_movq_wRn_M0(wrd);
2497 gen_op_iwmmxt_set_mup();
2498 gen_op_iwmmxt_set_cup();
2499 break;
2500 case 0x201: case 0x203: case 0x205: case 0x207:
2501 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2502 case 0x211: case 0x213: case 0x215: case 0x217:
2503 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2504 wrd = (insn >> 5) & 0xf;
2505 rd0 = (insn >> 12) & 0xf;
2506 rd1 = (insn >> 0) & 0xf;
2507 if (rd0 == 0xf || rd1 == 0xf)
2508 return 1;
2509 gen_op_iwmmxt_movq_M0_wRn(wrd);
2510 tmp = load_reg(s, rd0);
2511 tmp2 = load_reg(s, rd1);
2512 switch ((insn >> 16) & 0xf) {
2513 case 0x0: /* TMIA */
2514 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2515 break;
2516 case 0x8: /* TMIAPH */
2517 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2518 break;
2519 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2520 if (insn & (1 << 16))
2521 tcg_gen_shri_i32(tmp, tmp, 16);
2522 if (insn & (1 << 17))
2523 tcg_gen_shri_i32(tmp2, tmp2, 16);
2524 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2525 break;
2526 default:
2527 tcg_temp_free_i32(tmp2);
2528 tcg_temp_free_i32(tmp);
2529 return 1;
2531 tcg_temp_free_i32(tmp2);
2532 tcg_temp_free_i32(tmp);
2533 gen_op_iwmmxt_movq_wRn_M0(wrd);
2534 gen_op_iwmmxt_set_mup();
2535 break;
2536 default:
2537 return 1;
2540 return 0;
2543 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
2544 (ie. an undefined instruction). */
2545 static int disas_dsp_insn(DisasContext *s, uint32_t insn)
2547 int acc, rd0, rd1, rdhi, rdlo;
2548 TCGv_i32 tmp, tmp2;
2550 if ((insn & 0x0ff00f10) == 0x0e200010) {
2551 /* Multiply with Internal Accumulate Format */
2552 rd0 = (insn >> 12) & 0xf;
2553 rd1 = insn & 0xf;
2554 acc = (insn >> 5) & 7;
2556 if (acc != 0)
2557 return 1;
2559 tmp = load_reg(s, rd0);
2560 tmp2 = load_reg(s, rd1);
2561 switch ((insn >> 16) & 0xf) {
2562 case 0x0: /* MIA */
2563 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2564 break;
2565 case 0x8: /* MIAPH */
2566 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2567 break;
2568 case 0xc: /* MIABB */
2569 case 0xd: /* MIABT */
2570 case 0xe: /* MIATB */
2571 case 0xf: /* MIATT */
2572 if (insn & (1 << 16))
2573 tcg_gen_shri_i32(tmp, tmp, 16);
2574 if (insn & (1 << 17))
2575 tcg_gen_shri_i32(tmp2, tmp2, 16);
2576 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2577 break;
2578 default:
2579 return 1;
2581 tcg_temp_free_i32(tmp2);
2582 tcg_temp_free_i32(tmp);
2584 gen_op_iwmmxt_movq_wRn_M0(acc);
2585 return 0;
2588 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2589 /* Internal Accumulator Access Format */
2590 rdhi = (insn >> 16) & 0xf;
2591 rdlo = (insn >> 12) & 0xf;
2592 acc = insn & 7;
2594 if (acc != 0)
2595 return 1;
2597 if (insn & ARM_CP_RW_BIT) { /* MRA */
2598 iwmmxt_load_reg(cpu_V0, acc);
2599 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
2600 tcg_gen_extrh_i64_i32(cpu_R[rdhi], cpu_V0);
2601 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2602 } else { /* MAR */
2603 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2604 iwmmxt_store_reg(cpu_V0, acc);
2606 return 0;
2609 return 1;
2612 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2613 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2614 if (dc_isar_feature(aa32_simd_r32, s)) { \
2615 reg = (((insn) >> (bigbit)) & 0x0f) \
2616 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2617 } else { \
2618 if (insn & (1 << (smallbit))) \
2619 return 1; \
2620 reg = ((insn) >> (bigbit)) & 0x0f; \
2621 }} while (0)
2623 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2624 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2625 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2627 static void gen_neon_dup_low16(TCGv_i32 var)
2629 TCGv_i32 tmp = tcg_temp_new_i32();
2630 tcg_gen_ext16u_i32(var, var);
2631 tcg_gen_shli_i32(tmp, var, 16);
2632 tcg_gen_or_i32(var, var, tmp);
2633 tcg_temp_free_i32(tmp);
2636 static void gen_neon_dup_high16(TCGv_i32 var)
2638 TCGv_i32 tmp = tcg_temp_new_i32();
2639 tcg_gen_andi_i32(var, var, 0xffff0000);
2640 tcg_gen_shri_i32(tmp, var, 16);
2641 tcg_gen_or_i32(var, var, tmp);
2642 tcg_temp_free_i32(tmp);
2645 static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
2647 #ifndef CONFIG_USER_ONLY
2648 return (s->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
2649 ((s->base.pc_next - 1) & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
2650 #else
2651 return true;
2652 #endif
2655 static void gen_goto_ptr(void)
2657 tcg_gen_lookup_and_goto_ptr();
2660 /* This will end the TB but doesn't guarantee we'll return to
2661 * cpu_loop_exec. Any live exit_requests will be processed as we
2662 * enter the next TB.
2664 static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
2666 if (use_goto_tb(s, dest)) {
2667 tcg_gen_goto_tb(n);
2668 gen_set_pc_im(s, dest);
2669 tcg_gen_exit_tb(s->base.tb, n);
2670 } else {
2671 gen_set_pc_im(s, dest);
2672 gen_goto_ptr();
2674 s->base.is_jmp = DISAS_NORETURN;
2677 static inline void gen_jmp (DisasContext *s, uint32_t dest)
2679 if (unlikely(is_singlestepping(s))) {
2680 /* An indirect jump so that we still trigger the debug exception. */
2681 gen_set_pc_im(s, dest);
2682 s->base.is_jmp = DISAS_JUMP;
2683 } else {
2684 gen_goto_tb(s, 0, dest);
2688 static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
2690 if (x)
2691 tcg_gen_sari_i32(t0, t0, 16);
2692 else
2693 gen_sxth(t0);
2694 if (y)
2695 tcg_gen_sari_i32(t1, t1, 16);
2696 else
2697 gen_sxth(t1);
2698 tcg_gen_mul_i32(t0, t0, t1);
2701 /* Return the mask of PSR bits set by a MSR instruction. */
2702 static uint32_t msr_mask(DisasContext *s, int flags, int spsr)
2704 uint32_t mask = 0;
2706 if (flags & (1 << 0)) {
2707 mask |= 0xff;
2709 if (flags & (1 << 1)) {
2710 mask |= 0xff00;
2712 if (flags & (1 << 2)) {
2713 mask |= 0xff0000;
2715 if (flags & (1 << 3)) {
2716 mask |= 0xff000000;
2719 /* Mask out undefined and reserved bits. */
2720 mask &= aarch32_cpsr_valid_mask(s->features, s->isar);
2722 /* Mask out execution state. */
2723 if (!spsr) {
2724 mask &= ~CPSR_EXEC;
2727 /* Mask out privileged bits. */
2728 if (IS_USER(s)) {
2729 mask &= CPSR_USER;
2731 return mask;
2734 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
2735 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
2737 TCGv_i32 tmp;
2738 if (spsr) {
2739 /* ??? This is also undefined in system mode. */
2740 if (IS_USER(s))
2741 return 1;
2743 tmp = load_cpu_field(spsr);
2744 tcg_gen_andi_i32(tmp, tmp, ~mask);
2745 tcg_gen_andi_i32(t0, t0, mask);
2746 tcg_gen_or_i32(tmp, tmp, t0);
2747 store_cpu_field(tmp, spsr);
2748 } else {
2749 gen_set_cpsr(t0, mask);
2751 tcg_temp_free_i32(t0);
2752 gen_lookup_tb(s);
2753 return 0;
2756 /* Returns nonzero if access to the PSR is not permitted. */
2757 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
2759 TCGv_i32 tmp;
2760 tmp = tcg_temp_new_i32();
2761 tcg_gen_movi_i32(tmp, val);
2762 return gen_set_psr(s, mask, spsr, tmp);
2765 static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
2766 int *tgtmode, int *regno)
2768 /* Decode the r and sysm fields of MSR/MRS banked accesses into
2769 * the target mode and register number, and identify the various
2770 * unpredictable cases.
2771 * MSR (banked) and MRS (banked) are CONSTRAINED UNPREDICTABLE if:
2772 * + executed in user mode
2773 * + using R15 as the src/dest register
2774 * + accessing an unimplemented register
2775 * + accessing a register that's inaccessible at current PL/security state*
2776 * + accessing a register that you could access with a different insn
2777 * We choose to UNDEF in all these cases.
2778 * Since we don't know which of the various AArch32 modes we are in
2779 * we have to defer some checks to runtime.
2780 * Accesses to Monitor mode registers from Secure EL1 (which implies
2781 * that EL3 is AArch64) must trap to EL3.
2783 * If the access checks fail this function will emit code to take
2784 * an exception and return false. Otherwise it will return true,
2785 * and set *tgtmode and *regno appropriately.
2787 int exc_target = default_exception_el(s);
2789 /* These instructions are present only in ARMv8, or in ARMv7 with the
2790 * Virtualization Extensions.
2792 if (!arm_dc_feature(s, ARM_FEATURE_V8) &&
2793 !arm_dc_feature(s, ARM_FEATURE_EL2)) {
2794 goto undef;
2797 if (IS_USER(s) || rn == 15) {
2798 goto undef;
2801 /* The table in the v8 ARM ARM section F5.2.3 describes the encoding
2802 * of registers into (r, sysm).
2804 if (r) {
2805 /* SPSRs for other modes */
2806 switch (sysm) {
2807 case 0xe: /* SPSR_fiq */
2808 *tgtmode = ARM_CPU_MODE_FIQ;
2809 break;
2810 case 0x10: /* SPSR_irq */
2811 *tgtmode = ARM_CPU_MODE_IRQ;
2812 break;
2813 case 0x12: /* SPSR_svc */
2814 *tgtmode = ARM_CPU_MODE_SVC;
2815 break;
2816 case 0x14: /* SPSR_abt */
2817 *tgtmode = ARM_CPU_MODE_ABT;
2818 break;
2819 case 0x16: /* SPSR_und */
2820 *tgtmode = ARM_CPU_MODE_UND;
2821 break;
2822 case 0x1c: /* SPSR_mon */
2823 *tgtmode = ARM_CPU_MODE_MON;
2824 break;
2825 case 0x1e: /* SPSR_hyp */
2826 *tgtmode = ARM_CPU_MODE_HYP;
2827 break;
2828 default: /* unallocated */
2829 goto undef;
2831 /* We arbitrarily assign SPSR a register number of 16. */
2832 *regno = 16;
2833 } else {
2834 /* general purpose registers for other modes */
2835 switch (sysm) {
2836 case 0x0 ... 0x6: /* 0b00xxx : r8_usr ... r14_usr */
2837 *tgtmode = ARM_CPU_MODE_USR;
2838 *regno = sysm + 8;
2839 break;
2840 case 0x8 ... 0xe: /* 0b01xxx : r8_fiq ... r14_fiq */
2841 *tgtmode = ARM_CPU_MODE_FIQ;
2842 *regno = sysm;
2843 break;
2844 case 0x10 ... 0x11: /* 0b1000x : r14_irq, r13_irq */
2845 *tgtmode = ARM_CPU_MODE_IRQ;
2846 *regno = sysm & 1 ? 13 : 14;
2847 break;
2848 case 0x12 ... 0x13: /* 0b1001x : r14_svc, r13_svc */
2849 *tgtmode = ARM_CPU_MODE_SVC;
2850 *regno = sysm & 1 ? 13 : 14;
2851 break;
2852 case 0x14 ... 0x15: /* 0b1010x : r14_abt, r13_abt */
2853 *tgtmode = ARM_CPU_MODE_ABT;
2854 *regno = sysm & 1 ? 13 : 14;
2855 break;
2856 case 0x16 ... 0x17: /* 0b1011x : r14_und, r13_und */
2857 *tgtmode = ARM_CPU_MODE_UND;
2858 *regno = sysm & 1 ? 13 : 14;
2859 break;
2860 case 0x1c ... 0x1d: /* 0b1110x : r14_mon, r13_mon */
2861 *tgtmode = ARM_CPU_MODE_MON;
2862 *regno = sysm & 1 ? 13 : 14;
2863 break;
2864 case 0x1e ... 0x1f: /* 0b1111x : elr_hyp, r13_hyp */
2865 *tgtmode = ARM_CPU_MODE_HYP;
2866 /* Arbitrarily pick 17 for ELR_Hyp (which is not a banked LR!) */
2867 *regno = sysm & 1 ? 13 : 17;
2868 break;
2869 default: /* unallocated */
2870 goto undef;
2874 /* Catch the 'accessing inaccessible register' cases we can detect
2875 * at translate time.
2877 switch (*tgtmode) {
2878 case ARM_CPU_MODE_MON:
2879 if (!arm_dc_feature(s, ARM_FEATURE_EL3) || s->ns) {
2880 goto undef;
2882 if (s->current_el == 1) {
2883 /* If we're in Secure EL1 (which implies that EL3 is AArch64)
2884 * then accesses to Mon registers trap to EL3
2886 exc_target = 3;
2887 goto undef;
2889 break;
2890 case ARM_CPU_MODE_HYP:
2892 * SPSR_hyp and r13_hyp can only be accessed from Monitor mode
2893 * (and so we can forbid accesses from EL2 or below). elr_hyp
2894 * can be accessed also from Hyp mode, so forbid accesses from
2895 * EL0 or EL1.
2897 if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el < 2 ||
2898 (s->current_el < 3 && *regno != 17)) {
2899 goto undef;
2901 break;
2902 default:
2903 break;
2906 return true;
2908 undef:
2909 /* If we get here then some access check did not pass */
2910 gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
2911 syn_uncategorized(), exc_target);
2912 return false;
2915 static void gen_msr_banked(DisasContext *s, int r, int sysm, int rn)
2917 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
2918 int tgtmode = 0, regno = 0;
2920 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
2921 return;
2924 /* Sync state because msr_banked() can raise exceptions */
2925 gen_set_condexec(s);
2926 gen_set_pc_im(s, s->pc_curr);
2927 tcg_reg = load_reg(s, rn);
2928 tcg_tgtmode = tcg_const_i32(tgtmode);
2929 tcg_regno = tcg_const_i32(regno);
2930 gen_helper_msr_banked(cpu_env, tcg_reg, tcg_tgtmode, tcg_regno);
2931 tcg_temp_free_i32(tcg_tgtmode);
2932 tcg_temp_free_i32(tcg_regno);
2933 tcg_temp_free_i32(tcg_reg);
2934 s->base.is_jmp = DISAS_UPDATE;
2937 static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn)
2939 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
2940 int tgtmode = 0, regno = 0;
2942 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
2943 return;
2946 /* Sync state because mrs_banked() can raise exceptions */
2947 gen_set_condexec(s);
2948 gen_set_pc_im(s, s->pc_curr);
2949 tcg_reg = tcg_temp_new_i32();
2950 tcg_tgtmode = tcg_const_i32(tgtmode);
2951 tcg_regno = tcg_const_i32(regno);
2952 gen_helper_mrs_banked(tcg_reg, cpu_env, tcg_tgtmode, tcg_regno);
2953 tcg_temp_free_i32(tcg_tgtmode);
2954 tcg_temp_free_i32(tcg_regno);
2955 store_reg(s, rn, tcg_reg);
2956 s->base.is_jmp = DISAS_UPDATE;
2959 /* Store value to PC as for an exception return (ie don't
2960 * mask bits). The subsequent call to gen_helper_cpsr_write_eret()
2961 * will do the masking based on the new value of the Thumb bit.
2963 static void store_pc_exc_ret(DisasContext *s, TCGv_i32 pc)
2965 tcg_gen_mov_i32(cpu_R[15], pc);
2966 tcg_temp_free_i32(pc);
2969 /* Generate a v6 exception return. Marks both values as dead. */
2970 static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
2972 store_pc_exc_ret(s, pc);
2973 /* The cpsr_write_eret helper will mask the low bits of PC
2974 * appropriately depending on the new Thumb bit, so it must
2975 * be called after storing the new PC.
2977 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
2978 gen_io_start();
2980 gen_helper_cpsr_write_eret(cpu_env, cpsr);
2981 tcg_temp_free_i32(cpsr);
2982 /* Must exit loop to check un-masked IRQs */
2983 s->base.is_jmp = DISAS_EXIT;
2986 /* Generate an old-style exception return. Marks pc as dead. */
2987 static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
2989 gen_rfe(s, pc, load_cpu_field(spsr));
2992 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
2994 static inline void gen_neon_add(int size, TCGv_i32 t0, TCGv_i32 t1)
2996 switch (size) {
2997 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
2998 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
2999 case 2: tcg_gen_add_i32(t0, t0, t1); break;
3000 default: abort();
3004 static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
3006 switch (size) {
3007 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
3008 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
3009 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
3010 default: return;
3014 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3015 #define gen_helper_neon_pmax_s32 tcg_gen_smax_i32
3016 #define gen_helper_neon_pmax_u32 tcg_gen_umax_i32
3017 #define gen_helper_neon_pmin_s32 tcg_gen_smin_i32
3018 #define gen_helper_neon_pmin_u32 tcg_gen_umin_i32
3020 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3021 switch ((size << 1) | u) { \
3022 case 0: \
3023 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3024 break; \
3025 case 1: \
3026 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3027 break; \
3028 case 2: \
3029 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3030 break; \
3031 case 3: \
3032 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3033 break; \
3034 case 4: \
3035 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3036 break; \
3037 case 5: \
3038 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3039 break; \
3040 default: return 1; \
3041 }} while (0)
3043 #define GEN_NEON_INTEGER_OP(name) do { \
3044 switch ((size << 1) | u) { \
3045 case 0: \
3046 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3047 break; \
3048 case 1: \
3049 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3050 break; \
3051 case 2: \
3052 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3053 break; \
3054 case 3: \
3055 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3056 break; \
3057 case 4: \
3058 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3059 break; \
3060 case 5: \
3061 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3062 break; \
3063 default: return 1; \
3064 }} while (0)
3066 static TCGv_i32 neon_load_scratch(int scratch)
3068 TCGv_i32 tmp = tcg_temp_new_i32();
3069 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3070 return tmp;
3073 static void neon_store_scratch(int scratch, TCGv_i32 var)
3075 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3076 tcg_temp_free_i32(var);
3079 static inline TCGv_i32 neon_get_scalar(int size, int reg)
3081 TCGv_i32 tmp;
3082 if (size == 1) {
3083 tmp = neon_load_reg(reg & 7, reg >> 4);
3084 if (reg & 8) {
3085 gen_neon_dup_high16(tmp);
3086 } else {
3087 gen_neon_dup_low16(tmp);
3089 } else {
3090 tmp = neon_load_reg(reg & 15, reg >> 4);
3092 return tmp;
3095 static int gen_neon_unzip(int rd, int rm, int size, int q)
3097 TCGv_ptr pd, pm;
3099 if (!q && size == 2) {
3100 return 1;
3102 pd = vfp_reg_ptr(true, rd);
3103 pm = vfp_reg_ptr(true, rm);
3104 if (q) {
3105 switch (size) {
3106 case 0:
3107 gen_helper_neon_qunzip8(pd, pm);
3108 break;
3109 case 1:
3110 gen_helper_neon_qunzip16(pd, pm);
3111 break;
3112 case 2:
3113 gen_helper_neon_qunzip32(pd, pm);
3114 break;
3115 default:
3116 abort();
3118 } else {
3119 switch (size) {
3120 case 0:
3121 gen_helper_neon_unzip8(pd, pm);
3122 break;
3123 case 1:
3124 gen_helper_neon_unzip16(pd, pm);
3125 break;
3126 default:
3127 abort();
3130 tcg_temp_free_ptr(pd);
3131 tcg_temp_free_ptr(pm);
3132 return 0;
3135 static int gen_neon_zip(int rd, int rm, int size, int q)
3137 TCGv_ptr pd, pm;
3139 if (!q && size == 2) {
3140 return 1;
3142 pd = vfp_reg_ptr(true, rd);
3143 pm = vfp_reg_ptr(true, rm);
3144 if (q) {
3145 switch (size) {
3146 case 0:
3147 gen_helper_neon_qzip8(pd, pm);
3148 break;
3149 case 1:
3150 gen_helper_neon_qzip16(pd, pm);
3151 break;
3152 case 2:
3153 gen_helper_neon_qzip32(pd, pm);
3154 break;
3155 default:
3156 abort();
3158 } else {
3159 switch (size) {
3160 case 0:
3161 gen_helper_neon_zip8(pd, pm);
3162 break;
3163 case 1:
3164 gen_helper_neon_zip16(pd, pm);
3165 break;
3166 default:
3167 abort();
3170 tcg_temp_free_ptr(pd);
3171 tcg_temp_free_ptr(pm);
3172 return 0;
3175 static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
3177 TCGv_i32 rd, tmp;
3179 rd = tcg_temp_new_i32();
3180 tmp = tcg_temp_new_i32();
3182 tcg_gen_shli_i32(rd, t0, 8);
3183 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3184 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3185 tcg_gen_or_i32(rd, rd, tmp);
3187 tcg_gen_shri_i32(t1, t1, 8);
3188 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3189 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3190 tcg_gen_or_i32(t1, t1, tmp);
3191 tcg_gen_mov_i32(t0, rd);
3193 tcg_temp_free_i32(tmp);
3194 tcg_temp_free_i32(rd);
3197 static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
3199 TCGv_i32 rd, tmp;
3201 rd = tcg_temp_new_i32();
3202 tmp = tcg_temp_new_i32();
3204 tcg_gen_shli_i32(rd, t0, 16);
3205 tcg_gen_andi_i32(tmp, t1, 0xffff);
3206 tcg_gen_or_i32(rd, rd, tmp);
3207 tcg_gen_shri_i32(t1, t1, 16);
3208 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3209 tcg_gen_or_i32(t1, t1, tmp);
3210 tcg_gen_mov_i32(t0, rd);
3212 tcg_temp_free_i32(tmp);
3213 tcg_temp_free_i32(rd);
3216 static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src)
3218 switch (size) {
3219 case 0: gen_helper_neon_narrow_u8(dest, src); break;
3220 case 1: gen_helper_neon_narrow_u16(dest, src); break;
3221 case 2: tcg_gen_extrl_i64_i32(dest, src); break;
3222 default: abort();
3226 static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
3228 switch (size) {
3229 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
3230 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
3231 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
3232 default: abort();
3236 static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src)
3238 switch (size) {
3239 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
3240 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
3241 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
3242 default: abort();
3246 static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
3248 switch (size) {
3249 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
3250 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
3251 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
3252 default: abort();
3256 static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift,
3257 int q, int u)
3259 if (q) {
3260 if (u) {
3261 switch (size) {
3262 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3263 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3264 default: abort();
3266 } else {
3267 switch (size) {
3268 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
3269 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
3270 default: abort();
3273 } else {
3274 if (u) {
3275 switch (size) {
3276 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
3277 case 2: gen_ushl_i32(var, var, shift); break;
3278 default: abort();
3280 } else {
3281 switch (size) {
3282 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
3283 case 2: gen_sshl_i32(var, var, shift); break;
3284 default: abort();
3290 static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
3292 if (u) {
3293 switch (size) {
3294 case 0: gen_helper_neon_widen_u8(dest, src); break;
3295 case 1: gen_helper_neon_widen_u16(dest, src); break;
3296 case 2: tcg_gen_extu_i32_i64(dest, src); break;
3297 default: abort();
3299 } else {
3300 switch (size) {
3301 case 0: gen_helper_neon_widen_s8(dest, src); break;
3302 case 1: gen_helper_neon_widen_s16(dest, src); break;
3303 case 2: tcg_gen_ext_i32_i64(dest, src); break;
3304 default: abort();
3307 tcg_temp_free_i32(src);
3310 static inline void gen_neon_addl(int size)
3312 switch (size) {
3313 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
3314 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
3315 case 2: tcg_gen_add_i64(CPU_V001); break;
3316 default: abort();
3320 static inline void gen_neon_subl(int size)
3322 switch (size) {
3323 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
3324 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
3325 case 2: tcg_gen_sub_i64(CPU_V001); break;
3326 default: abort();
3330 static inline void gen_neon_negl(TCGv_i64 var, int size)
3332 switch (size) {
3333 case 0: gen_helper_neon_negl_u16(var, var); break;
3334 case 1: gen_helper_neon_negl_u32(var, var); break;
3335 case 2:
3336 tcg_gen_neg_i64(var, var);
3337 break;
3338 default: abort();
3342 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
3344 switch (size) {
3345 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
3346 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
3347 default: abort();
3351 static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b,
3352 int size, int u)
3354 TCGv_i64 tmp;
3356 switch ((size << 1) | u) {
3357 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
3358 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
3359 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
3360 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
3361 case 4:
3362 tmp = gen_muls_i64_i32(a, b);
3363 tcg_gen_mov_i64(dest, tmp);
3364 tcg_temp_free_i64(tmp);
3365 break;
3366 case 5:
3367 tmp = gen_mulu_i64_i32(a, b);
3368 tcg_gen_mov_i64(dest, tmp);
3369 tcg_temp_free_i64(tmp);
3370 break;
3371 default: abort();
3374 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
3375 Don't forget to clean them now. */
3376 if (size < 2) {
3377 tcg_temp_free_i32(a);
3378 tcg_temp_free_i32(b);
3382 static void gen_neon_narrow_op(int op, int u, int size,
3383 TCGv_i32 dest, TCGv_i64 src)
3385 if (op) {
3386 if (u) {
3387 gen_neon_unarrow_sats(size, dest, src);
3388 } else {
3389 gen_neon_narrow(size, dest, src);
3391 } else {
3392 if (u) {
3393 gen_neon_narrow_satu(size, dest, src);
3394 } else {
3395 gen_neon_narrow_sats(size, dest, src);
3400 /* Symbolic constants for op fields for Neon 3-register same-length.
3401 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
3402 * table A7-9.
3404 #define NEON_3R_VHADD 0
3405 #define NEON_3R_VQADD 1
3406 #define NEON_3R_VRHADD 2
3407 #define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
3408 #define NEON_3R_VHSUB 4
3409 #define NEON_3R_VQSUB 5
3410 #define NEON_3R_VCGT 6
3411 #define NEON_3R_VCGE 7
3412 #define NEON_3R_VSHL 8
3413 #define NEON_3R_VQSHL 9
3414 #define NEON_3R_VRSHL 10
3415 #define NEON_3R_VQRSHL 11
3416 #define NEON_3R_VMAX 12
3417 #define NEON_3R_VMIN 13
3418 #define NEON_3R_VABD 14
3419 #define NEON_3R_VABA 15
3420 #define NEON_3R_VADD_VSUB 16
3421 #define NEON_3R_VTST_VCEQ 17
3422 #define NEON_3R_VML 18 /* VMLA, VMLS */
3423 #define NEON_3R_VMUL 19
3424 #define NEON_3R_VPMAX 20
3425 #define NEON_3R_VPMIN 21
3426 #define NEON_3R_VQDMULH_VQRDMULH 22
3427 #define NEON_3R_VPADD_VQRDMLAH 23
3428 #define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */
3429 #define NEON_3R_VFM_VQRDMLSH 25 /* VFMA, VFMS, VQRDMLSH */
3430 #define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
3431 #define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
3432 #define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
3433 #define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
3434 #define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
3435 #define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */
3437 static const uint8_t neon_3r_sizes[] = {
3438 [NEON_3R_VHADD] = 0x7,
3439 [NEON_3R_VQADD] = 0xf,
3440 [NEON_3R_VRHADD] = 0x7,
3441 [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
3442 [NEON_3R_VHSUB] = 0x7,
3443 [NEON_3R_VQSUB] = 0xf,
3444 [NEON_3R_VCGT] = 0x7,
3445 [NEON_3R_VCGE] = 0x7,
3446 [NEON_3R_VSHL] = 0xf,
3447 [NEON_3R_VQSHL] = 0xf,
3448 [NEON_3R_VRSHL] = 0xf,
3449 [NEON_3R_VQRSHL] = 0xf,
3450 [NEON_3R_VMAX] = 0x7,
3451 [NEON_3R_VMIN] = 0x7,
3452 [NEON_3R_VABD] = 0x7,
3453 [NEON_3R_VABA] = 0x7,
3454 [NEON_3R_VADD_VSUB] = 0xf,
3455 [NEON_3R_VTST_VCEQ] = 0x7,
3456 [NEON_3R_VML] = 0x7,
3457 [NEON_3R_VMUL] = 0x7,
3458 [NEON_3R_VPMAX] = 0x7,
3459 [NEON_3R_VPMIN] = 0x7,
3460 [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
3461 [NEON_3R_VPADD_VQRDMLAH] = 0x7,
3462 [NEON_3R_SHA] = 0xf, /* size field encodes op type */
3463 [NEON_3R_VFM_VQRDMLSH] = 0x7, /* For VFM, size bit 1 encodes op */
3464 [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
3465 [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
3466 [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
3467 [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
3468 [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
3469 [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */
3472 /* Symbolic constants for op fields for Neon 2-register miscellaneous.
3473 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
3474 * table A7-13.
3476 #define NEON_2RM_VREV64 0
3477 #define NEON_2RM_VREV32 1
3478 #define NEON_2RM_VREV16 2
3479 #define NEON_2RM_VPADDL 4
3480 #define NEON_2RM_VPADDL_U 5
3481 #define NEON_2RM_AESE 6 /* Includes AESD */
3482 #define NEON_2RM_AESMC 7 /* Includes AESIMC */
3483 #define NEON_2RM_VCLS 8
3484 #define NEON_2RM_VCLZ 9
3485 #define NEON_2RM_VCNT 10
3486 #define NEON_2RM_VMVN 11
3487 #define NEON_2RM_VPADAL 12
3488 #define NEON_2RM_VPADAL_U 13
3489 #define NEON_2RM_VQABS 14
3490 #define NEON_2RM_VQNEG 15
3491 #define NEON_2RM_VCGT0 16
3492 #define NEON_2RM_VCGE0 17
3493 #define NEON_2RM_VCEQ0 18
3494 #define NEON_2RM_VCLE0 19
3495 #define NEON_2RM_VCLT0 20
3496 #define NEON_2RM_SHA1H 21
3497 #define NEON_2RM_VABS 22
3498 #define NEON_2RM_VNEG 23
3499 #define NEON_2RM_VCGT0_F 24
3500 #define NEON_2RM_VCGE0_F 25
3501 #define NEON_2RM_VCEQ0_F 26
3502 #define NEON_2RM_VCLE0_F 27
3503 #define NEON_2RM_VCLT0_F 28
3504 #define NEON_2RM_VABS_F 30
3505 #define NEON_2RM_VNEG_F 31
3506 #define NEON_2RM_VSWP 32
3507 #define NEON_2RM_VTRN 33
3508 #define NEON_2RM_VUZP 34
3509 #define NEON_2RM_VZIP 35
3510 #define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
3511 #define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
3512 #define NEON_2RM_VSHLL 38
3513 #define NEON_2RM_SHA1SU1 39 /* Includes SHA256SU0 */
3514 #define NEON_2RM_VRINTN 40
3515 #define NEON_2RM_VRINTX 41
3516 #define NEON_2RM_VRINTA 42
3517 #define NEON_2RM_VRINTZ 43
3518 #define NEON_2RM_VCVT_F16_F32 44
3519 #define NEON_2RM_VRINTM 45
3520 #define NEON_2RM_VCVT_F32_F16 46
3521 #define NEON_2RM_VRINTP 47
3522 #define NEON_2RM_VCVTAU 48
3523 #define NEON_2RM_VCVTAS 49
3524 #define NEON_2RM_VCVTNU 50
3525 #define NEON_2RM_VCVTNS 51
3526 #define NEON_2RM_VCVTPU 52
3527 #define NEON_2RM_VCVTPS 53
3528 #define NEON_2RM_VCVTMU 54
3529 #define NEON_2RM_VCVTMS 55
3530 #define NEON_2RM_VRECPE 56
3531 #define NEON_2RM_VRSQRTE 57
3532 #define NEON_2RM_VRECPE_F 58
3533 #define NEON_2RM_VRSQRTE_F 59
3534 #define NEON_2RM_VCVT_FS 60
3535 #define NEON_2RM_VCVT_FU 61
3536 #define NEON_2RM_VCVT_SF 62
3537 #define NEON_2RM_VCVT_UF 63
3539 static bool neon_2rm_is_v8_op(int op)
3541 /* Return true if this neon 2reg-misc op is ARMv8 and up */
3542 switch (op) {
3543 case NEON_2RM_VRINTN:
3544 case NEON_2RM_VRINTA:
3545 case NEON_2RM_VRINTM:
3546 case NEON_2RM_VRINTP:
3547 case NEON_2RM_VRINTZ:
3548 case NEON_2RM_VRINTX:
3549 case NEON_2RM_VCVTAU:
3550 case NEON_2RM_VCVTAS:
3551 case NEON_2RM_VCVTNU:
3552 case NEON_2RM_VCVTNS:
3553 case NEON_2RM_VCVTPU:
3554 case NEON_2RM_VCVTPS:
3555 case NEON_2RM_VCVTMU:
3556 case NEON_2RM_VCVTMS:
3557 return true;
3558 default:
3559 return false;
3563 /* Each entry in this array has bit n set if the insn allows
3564 * size value n (otherwise it will UNDEF). Since unallocated
3565 * op values will have no bits set they always UNDEF.
3567 static const uint8_t neon_2rm_sizes[] = {
3568 [NEON_2RM_VREV64] = 0x7,
3569 [NEON_2RM_VREV32] = 0x3,
3570 [NEON_2RM_VREV16] = 0x1,
3571 [NEON_2RM_VPADDL] = 0x7,
3572 [NEON_2RM_VPADDL_U] = 0x7,
3573 [NEON_2RM_AESE] = 0x1,
3574 [NEON_2RM_AESMC] = 0x1,
3575 [NEON_2RM_VCLS] = 0x7,
3576 [NEON_2RM_VCLZ] = 0x7,
3577 [NEON_2RM_VCNT] = 0x1,
3578 [NEON_2RM_VMVN] = 0x1,
3579 [NEON_2RM_VPADAL] = 0x7,
3580 [NEON_2RM_VPADAL_U] = 0x7,
3581 [NEON_2RM_VQABS] = 0x7,
3582 [NEON_2RM_VQNEG] = 0x7,
3583 [NEON_2RM_VCGT0] = 0x7,
3584 [NEON_2RM_VCGE0] = 0x7,
3585 [NEON_2RM_VCEQ0] = 0x7,
3586 [NEON_2RM_VCLE0] = 0x7,
3587 [NEON_2RM_VCLT0] = 0x7,
3588 [NEON_2RM_SHA1H] = 0x4,
3589 [NEON_2RM_VABS] = 0x7,
3590 [NEON_2RM_VNEG] = 0x7,
3591 [NEON_2RM_VCGT0_F] = 0x4,
3592 [NEON_2RM_VCGE0_F] = 0x4,
3593 [NEON_2RM_VCEQ0_F] = 0x4,
3594 [NEON_2RM_VCLE0_F] = 0x4,
3595 [NEON_2RM_VCLT0_F] = 0x4,
3596 [NEON_2RM_VABS_F] = 0x4,
3597 [NEON_2RM_VNEG_F] = 0x4,
3598 [NEON_2RM_VSWP] = 0x1,
3599 [NEON_2RM_VTRN] = 0x7,
3600 [NEON_2RM_VUZP] = 0x7,
3601 [NEON_2RM_VZIP] = 0x7,
3602 [NEON_2RM_VMOVN] = 0x7,
3603 [NEON_2RM_VQMOVN] = 0x7,
3604 [NEON_2RM_VSHLL] = 0x7,
3605 [NEON_2RM_SHA1SU1] = 0x4,
3606 [NEON_2RM_VRINTN] = 0x4,
3607 [NEON_2RM_VRINTX] = 0x4,
3608 [NEON_2RM_VRINTA] = 0x4,
3609 [NEON_2RM_VRINTZ] = 0x4,
3610 [NEON_2RM_VCVT_F16_F32] = 0x2,
3611 [NEON_2RM_VRINTM] = 0x4,
3612 [NEON_2RM_VCVT_F32_F16] = 0x2,
3613 [NEON_2RM_VRINTP] = 0x4,
3614 [NEON_2RM_VCVTAU] = 0x4,
3615 [NEON_2RM_VCVTAS] = 0x4,
3616 [NEON_2RM_VCVTNU] = 0x4,
3617 [NEON_2RM_VCVTNS] = 0x4,
3618 [NEON_2RM_VCVTPU] = 0x4,
3619 [NEON_2RM_VCVTPS] = 0x4,
3620 [NEON_2RM_VCVTMU] = 0x4,
3621 [NEON_2RM_VCVTMS] = 0x4,
3622 [NEON_2RM_VRECPE] = 0x4,
3623 [NEON_2RM_VRSQRTE] = 0x4,
3624 [NEON_2RM_VRECPE_F] = 0x4,
3625 [NEON_2RM_VRSQRTE_F] = 0x4,
3626 [NEON_2RM_VCVT_FS] = 0x4,
3627 [NEON_2RM_VCVT_FU] = 0x4,
3628 [NEON_2RM_VCVT_SF] = 0x4,
3629 [NEON_2RM_VCVT_UF] = 0x4,
3633 /* Expand v8.1 simd helper. */
3634 static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
3635 int q, int rd, int rn, int rm)
3637 if (dc_isar_feature(aa32_rdm, s)) {
3638 int opr_sz = (1 + q) * 8;
3639 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
3640 vfp_reg_offset(1, rn),
3641 vfp_reg_offset(1, rm), cpu_env,
3642 opr_sz, opr_sz, 0, fn);
3643 return 0;
3645 return 1;
3648 static void gen_ceq0_i32(TCGv_i32 d, TCGv_i32 a)
3650 tcg_gen_setcondi_i32(TCG_COND_EQ, d, a, 0);
3651 tcg_gen_neg_i32(d, d);
3654 static void gen_ceq0_i64(TCGv_i64 d, TCGv_i64 a)
3656 tcg_gen_setcondi_i64(TCG_COND_EQ, d, a, 0);
3657 tcg_gen_neg_i64(d, d);
3660 static void gen_ceq0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
3662 TCGv_vec zero = tcg_const_zeros_vec_matching(d);
3663 tcg_gen_cmp_vec(TCG_COND_EQ, vece, d, a, zero);
3664 tcg_temp_free_vec(zero);
3667 static const TCGOpcode vecop_list_cmp[] = {
3668 INDEX_op_cmp_vec, 0
3671 const GVecGen2 ceq0_op[4] = {
3672 { .fno = gen_helper_gvec_ceq0_b,
3673 .fniv = gen_ceq0_vec,
3674 .opt_opc = vecop_list_cmp,
3675 .vece = MO_8 },
3676 { .fno = gen_helper_gvec_ceq0_h,
3677 .fniv = gen_ceq0_vec,
3678 .opt_opc = vecop_list_cmp,
3679 .vece = MO_16 },
3680 { .fni4 = gen_ceq0_i32,
3681 .fniv = gen_ceq0_vec,
3682 .opt_opc = vecop_list_cmp,
3683 .vece = MO_32 },
3684 { .fni8 = gen_ceq0_i64,
3685 .fniv = gen_ceq0_vec,
3686 .opt_opc = vecop_list_cmp,
3687 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3688 .vece = MO_64 },
3691 static void gen_cle0_i32(TCGv_i32 d, TCGv_i32 a)
3693 tcg_gen_setcondi_i32(TCG_COND_LE, d, a, 0);
3694 tcg_gen_neg_i32(d, d);
3697 static void gen_cle0_i64(TCGv_i64 d, TCGv_i64 a)
3699 tcg_gen_setcondi_i64(TCG_COND_LE, d, a, 0);
3700 tcg_gen_neg_i64(d, d);
3703 static void gen_cle0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
3705 TCGv_vec zero = tcg_const_zeros_vec_matching(d);
3706 tcg_gen_cmp_vec(TCG_COND_LE, vece, d, a, zero);
3707 tcg_temp_free_vec(zero);
3710 const GVecGen2 cle0_op[4] = {
3711 { .fno = gen_helper_gvec_cle0_b,
3712 .fniv = gen_cle0_vec,
3713 .opt_opc = vecop_list_cmp,
3714 .vece = MO_8 },
3715 { .fno = gen_helper_gvec_cle0_h,
3716 .fniv = gen_cle0_vec,
3717 .opt_opc = vecop_list_cmp,
3718 .vece = MO_16 },
3719 { .fni4 = gen_cle0_i32,
3720 .fniv = gen_cle0_vec,
3721 .opt_opc = vecop_list_cmp,
3722 .vece = MO_32 },
3723 { .fni8 = gen_cle0_i64,
3724 .fniv = gen_cle0_vec,
3725 .opt_opc = vecop_list_cmp,
3726 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3727 .vece = MO_64 },
3730 static void gen_cge0_i32(TCGv_i32 d, TCGv_i32 a)
3732 tcg_gen_setcondi_i32(TCG_COND_GE, d, a, 0);
3733 tcg_gen_neg_i32(d, d);
3736 static void gen_cge0_i64(TCGv_i64 d, TCGv_i64 a)
3738 tcg_gen_setcondi_i64(TCG_COND_GE, d, a, 0);
3739 tcg_gen_neg_i64(d, d);
3742 static void gen_cge0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
3744 TCGv_vec zero = tcg_const_zeros_vec_matching(d);
3745 tcg_gen_cmp_vec(TCG_COND_GE, vece, d, a, zero);
3746 tcg_temp_free_vec(zero);
3749 const GVecGen2 cge0_op[4] = {
3750 { .fno = gen_helper_gvec_cge0_b,
3751 .fniv = gen_cge0_vec,
3752 .opt_opc = vecop_list_cmp,
3753 .vece = MO_8 },
3754 { .fno = gen_helper_gvec_cge0_h,
3755 .fniv = gen_cge0_vec,
3756 .opt_opc = vecop_list_cmp,
3757 .vece = MO_16 },
3758 { .fni4 = gen_cge0_i32,
3759 .fniv = gen_cge0_vec,
3760 .opt_opc = vecop_list_cmp,
3761 .vece = MO_32 },
3762 { .fni8 = gen_cge0_i64,
3763 .fniv = gen_cge0_vec,
3764 .opt_opc = vecop_list_cmp,
3765 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3766 .vece = MO_64 },
3769 static void gen_clt0_i32(TCGv_i32 d, TCGv_i32 a)
3771 tcg_gen_setcondi_i32(TCG_COND_LT, d, a, 0);
3772 tcg_gen_neg_i32(d, d);
3775 static void gen_clt0_i64(TCGv_i64 d, TCGv_i64 a)
3777 tcg_gen_setcondi_i64(TCG_COND_LT, d, a, 0);
3778 tcg_gen_neg_i64(d, d);
3781 static void gen_clt0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
3783 TCGv_vec zero = tcg_const_zeros_vec_matching(d);
3784 tcg_gen_cmp_vec(TCG_COND_LT, vece, d, a, zero);
3785 tcg_temp_free_vec(zero);
3788 const GVecGen2 clt0_op[4] = {
3789 { .fno = gen_helper_gvec_clt0_b,
3790 .fniv = gen_clt0_vec,
3791 .opt_opc = vecop_list_cmp,
3792 .vece = MO_8 },
3793 { .fno = gen_helper_gvec_clt0_h,
3794 .fniv = gen_clt0_vec,
3795 .opt_opc = vecop_list_cmp,
3796 .vece = MO_16 },
3797 { .fni4 = gen_clt0_i32,
3798 .fniv = gen_clt0_vec,
3799 .opt_opc = vecop_list_cmp,
3800 .vece = MO_32 },
3801 { .fni8 = gen_clt0_i64,
3802 .fniv = gen_clt0_vec,
3803 .opt_opc = vecop_list_cmp,
3804 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3805 .vece = MO_64 },
3808 static void gen_cgt0_i32(TCGv_i32 d, TCGv_i32 a)
3810 tcg_gen_setcondi_i32(TCG_COND_GT, d, a, 0);
3811 tcg_gen_neg_i32(d, d);
3814 static void gen_cgt0_i64(TCGv_i64 d, TCGv_i64 a)
3816 tcg_gen_setcondi_i64(TCG_COND_GT, d, a, 0);
3817 tcg_gen_neg_i64(d, d);
3820 static void gen_cgt0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
3822 TCGv_vec zero = tcg_const_zeros_vec_matching(d);
3823 tcg_gen_cmp_vec(TCG_COND_GT, vece, d, a, zero);
3824 tcg_temp_free_vec(zero);
3827 const GVecGen2 cgt0_op[4] = {
3828 { .fno = gen_helper_gvec_cgt0_b,
3829 .fniv = gen_cgt0_vec,
3830 .opt_opc = vecop_list_cmp,
3831 .vece = MO_8 },
3832 { .fno = gen_helper_gvec_cgt0_h,
3833 .fniv = gen_cgt0_vec,
3834 .opt_opc = vecop_list_cmp,
3835 .vece = MO_16 },
3836 { .fni4 = gen_cgt0_i32,
3837 .fniv = gen_cgt0_vec,
3838 .opt_opc = vecop_list_cmp,
3839 .vece = MO_32 },
3840 { .fni8 = gen_cgt0_i64,
3841 .fniv = gen_cgt0_vec,
3842 .opt_opc = vecop_list_cmp,
3843 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3844 .vece = MO_64 },
3847 static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3849 tcg_gen_vec_sar8i_i64(a, a, shift);
3850 tcg_gen_vec_add8_i64(d, d, a);
3853 static void gen_ssra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3855 tcg_gen_vec_sar16i_i64(a, a, shift);
3856 tcg_gen_vec_add16_i64(d, d, a);
3859 static void gen_ssra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
3861 tcg_gen_sari_i32(a, a, shift);
3862 tcg_gen_add_i32(d, d, a);
3865 static void gen_ssra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3867 tcg_gen_sari_i64(a, a, shift);
3868 tcg_gen_add_i64(d, d, a);
3871 static void gen_ssra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3873 tcg_gen_sari_vec(vece, a, a, sh);
3874 tcg_gen_add_vec(vece, d, d, a);
3877 static const TCGOpcode vecop_list_ssra[] = {
3878 INDEX_op_sari_vec, INDEX_op_add_vec, 0
3881 const GVecGen2i ssra_op[4] = {
3882 { .fni8 = gen_ssra8_i64,
3883 .fniv = gen_ssra_vec,
3884 .load_dest = true,
3885 .opt_opc = vecop_list_ssra,
3886 .vece = MO_8 },
3887 { .fni8 = gen_ssra16_i64,
3888 .fniv = gen_ssra_vec,
3889 .load_dest = true,
3890 .opt_opc = vecop_list_ssra,
3891 .vece = MO_16 },
3892 { .fni4 = gen_ssra32_i32,
3893 .fniv = gen_ssra_vec,
3894 .load_dest = true,
3895 .opt_opc = vecop_list_ssra,
3896 .vece = MO_32 },
3897 { .fni8 = gen_ssra64_i64,
3898 .fniv = gen_ssra_vec,
3899 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3900 .opt_opc = vecop_list_ssra,
3901 .load_dest = true,
3902 .vece = MO_64 },
3905 static void gen_usra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3907 tcg_gen_vec_shr8i_i64(a, a, shift);
3908 tcg_gen_vec_add8_i64(d, d, a);
3911 static void gen_usra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3913 tcg_gen_vec_shr16i_i64(a, a, shift);
3914 tcg_gen_vec_add16_i64(d, d, a);
3917 static void gen_usra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
3919 tcg_gen_shri_i32(a, a, shift);
3920 tcg_gen_add_i32(d, d, a);
3923 static void gen_usra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3925 tcg_gen_shri_i64(a, a, shift);
3926 tcg_gen_add_i64(d, d, a);
3929 static void gen_usra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3931 tcg_gen_shri_vec(vece, a, a, sh);
3932 tcg_gen_add_vec(vece, d, d, a);
3935 static const TCGOpcode vecop_list_usra[] = {
3936 INDEX_op_shri_vec, INDEX_op_add_vec, 0
3939 const GVecGen2i usra_op[4] = {
3940 { .fni8 = gen_usra8_i64,
3941 .fniv = gen_usra_vec,
3942 .load_dest = true,
3943 .opt_opc = vecop_list_usra,
3944 .vece = MO_8, },
3945 { .fni8 = gen_usra16_i64,
3946 .fniv = gen_usra_vec,
3947 .load_dest = true,
3948 .opt_opc = vecop_list_usra,
3949 .vece = MO_16, },
3950 { .fni4 = gen_usra32_i32,
3951 .fniv = gen_usra_vec,
3952 .load_dest = true,
3953 .opt_opc = vecop_list_usra,
3954 .vece = MO_32, },
3955 { .fni8 = gen_usra64_i64,
3956 .fniv = gen_usra_vec,
3957 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3958 .load_dest = true,
3959 .opt_opc = vecop_list_usra,
3960 .vece = MO_64, },
3963 static void gen_shr8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3965 uint64_t mask = dup_const(MO_8, 0xff >> shift);
3966 TCGv_i64 t = tcg_temp_new_i64();
3968 tcg_gen_shri_i64(t, a, shift);
3969 tcg_gen_andi_i64(t, t, mask);
3970 tcg_gen_andi_i64(d, d, ~mask);
3971 tcg_gen_or_i64(d, d, t);
3972 tcg_temp_free_i64(t);
3975 static void gen_shr16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3977 uint64_t mask = dup_const(MO_16, 0xffff >> shift);
3978 TCGv_i64 t = tcg_temp_new_i64();
3980 tcg_gen_shri_i64(t, a, shift);
3981 tcg_gen_andi_i64(t, t, mask);
3982 tcg_gen_andi_i64(d, d, ~mask);
3983 tcg_gen_or_i64(d, d, t);
3984 tcg_temp_free_i64(t);
3987 static void gen_shr32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
3989 tcg_gen_shri_i32(a, a, shift);
3990 tcg_gen_deposit_i32(d, d, a, 0, 32 - shift);
3993 static void gen_shr64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3995 tcg_gen_shri_i64(a, a, shift);
3996 tcg_gen_deposit_i64(d, d, a, 0, 64 - shift);
3999 static void gen_shr_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
4001 if (sh == 0) {
4002 tcg_gen_mov_vec(d, a);
4003 } else {
4004 TCGv_vec t = tcg_temp_new_vec_matching(d);
4005 TCGv_vec m = tcg_temp_new_vec_matching(d);
4007 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK((8 << vece) - sh, sh));
4008 tcg_gen_shri_vec(vece, t, a, sh);
4009 tcg_gen_and_vec(vece, d, d, m);
4010 tcg_gen_or_vec(vece, d, d, t);
4012 tcg_temp_free_vec(t);
4013 tcg_temp_free_vec(m);
4017 static const TCGOpcode vecop_list_sri[] = { INDEX_op_shri_vec, 0 };
4019 const GVecGen2i sri_op[4] = {
4020 { .fni8 = gen_shr8_ins_i64,
4021 .fniv = gen_shr_ins_vec,
4022 .load_dest = true,
4023 .opt_opc = vecop_list_sri,
4024 .vece = MO_8 },
4025 { .fni8 = gen_shr16_ins_i64,
4026 .fniv = gen_shr_ins_vec,
4027 .load_dest = true,
4028 .opt_opc = vecop_list_sri,
4029 .vece = MO_16 },
4030 { .fni4 = gen_shr32_ins_i32,
4031 .fniv = gen_shr_ins_vec,
4032 .load_dest = true,
4033 .opt_opc = vecop_list_sri,
4034 .vece = MO_32 },
4035 { .fni8 = gen_shr64_ins_i64,
4036 .fniv = gen_shr_ins_vec,
4037 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4038 .load_dest = true,
4039 .opt_opc = vecop_list_sri,
4040 .vece = MO_64 },
4043 static void gen_shl8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4045 uint64_t mask = dup_const(MO_8, 0xff << shift);
4046 TCGv_i64 t = tcg_temp_new_i64();
4048 tcg_gen_shli_i64(t, a, shift);
4049 tcg_gen_andi_i64(t, t, mask);
4050 tcg_gen_andi_i64(d, d, ~mask);
4051 tcg_gen_or_i64(d, d, t);
4052 tcg_temp_free_i64(t);
4055 static void gen_shl16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4057 uint64_t mask = dup_const(MO_16, 0xffff << shift);
4058 TCGv_i64 t = tcg_temp_new_i64();
4060 tcg_gen_shli_i64(t, a, shift);
4061 tcg_gen_andi_i64(t, t, mask);
4062 tcg_gen_andi_i64(d, d, ~mask);
4063 tcg_gen_or_i64(d, d, t);
4064 tcg_temp_free_i64(t);
4067 static void gen_shl32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
4069 tcg_gen_deposit_i32(d, d, a, shift, 32 - shift);
4072 static void gen_shl64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4074 tcg_gen_deposit_i64(d, d, a, shift, 64 - shift);
4077 static void gen_shl_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
4079 if (sh == 0) {
4080 tcg_gen_mov_vec(d, a);
4081 } else {
4082 TCGv_vec t = tcg_temp_new_vec_matching(d);
4083 TCGv_vec m = tcg_temp_new_vec_matching(d);
4085 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK(0, sh));
4086 tcg_gen_shli_vec(vece, t, a, sh);
4087 tcg_gen_and_vec(vece, d, d, m);
4088 tcg_gen_or_vec(vece, d, d, t);
4090 tcg_temp_free_vec(t);
4091 tcg_temp_free_vec(m);
4095 static const TCGOpcode vecop_list_sli[] = { INDEX_op_shli_vec, 0 };
4097 const GVecGen2i sli_op[4] = {
4098 { .fni8 = gen_shl8_ins_i64,
4099 .fniv = gen_shl_ins_vec,
4100 .load_dest = true,
4101 .opt_opc = vecop_list_sli,
4102 .vece = MO_8 },
4103 { .fni8 = gen_shl16_ins_i64,
4104 .fniv = gen_shl_ins_vec,
4105 .load_dest = true,
4106 .opt_opc = vecop_list_sli,
4107 .vece = MO_16 },
4108 { .fni4 = gen_shl32_ins_i32,
4109 .fniv = gen_shl_ins_vec,
4110 .load_dest = true,
4111 .opt_opc = vecop_list_sli,
4112 .vece = MO_32 },
4113 { .fni8 = gen_shl64_ins_i64,
4114 .fniv = gen_shl_ins_vec,
4115 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4116 .load_dest = true,
4117 .opt_opc = vecop_list_sli,
4118 .vece = MO_64 },
4121 static void gen_mla8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4123 gen_helper_neon_mul_u8(a, a, b);
4124 gen_helper_neon_add_u8(d, d, a);
4127 static void gen_mls8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4129 gen_helper_neon_mul_u8(a, a, b);
4130 gen_helper_neon_sub_u8(d, d, a);
4133 static void gen_mla16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4135 gen_helper_neon_mul_u16(a, a, b);
4136 gen_helper_neon_add_u16(d, d, a);
4139 static void gen_mls16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4141 gen_helper_neon_mul_u16(a, a, b);
4142 gen_helper_neon_sub_u16(d, d, a);
4145 static void gen_mla32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4147 tcg_gen_mul_i32(a, a, b);
4148 tcg_gen_add_i32(d, d, a);
4151 static void gen_mls32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4153 tcg_gen_mul_i32(a, a, b);
4154 tcg_gen_sub_i32(d, d, a);
4157 static void gen_mla64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4159 tcg_gen_mul_i64(a, a, b);
4160 tcg_gen_add_i64(d, d, a);
4163 static void gen_mls64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4165 tcg_gen_mul_i64(a, a, b);
4166 tcg_gen_sub_i64(d, d, a);
4169 static void gen_mla_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4171 tcg_gen_mul_vec(vece, a, a, b);
4172 tcg_gen_add_vec(vece, d, d, a);
4175 static void gen_mls_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4177 tcg_gen_mul_vec(vece, a, a, b);
4178 tcg_gen_sub_vec(vece, d, d, a);
4181 /* Note that while NEON does not support VMLA and VMLS as 64-bit ops,
4182 * these tables are shared with AArch64 which does support them.
4185 static const TCGOpcode vecop_list_mla[] = {
4186 INDEX_op_mul_vec, INDEX_op_add_vec, 0
4189 static const TCGOpcode vecop_list_mls[] = {
4190 INDEX_op_mul_vec, INDEX_op_sub_vec, 0
4193 const GVecGen3 mla_op[4] = {
4194 { .fni4 = gen_mla8_i32,
4195 .fniv = gen_mla_vec,
4196 .load_dest = true,
4197 .opt_opc = vecop_list_mla,
4198 .vece = MO_8 },
4199 { .fni4 = gen_mla16_i32,
4200 .fniv = gen_mla_vec,
4201 .load_dest = true,
4202 .opt_opc = vecop_list_mla,
4203 .vece = MO_16 },
4204 { .fni4 = gen_mla32_i32,
4205 .fniv = gen_mla_vec,
4206 .load_dest = true,
4207 .opt_opc = vecop_list_mla,
4208 .vece = MO_32 },
4209 { .fni8 = gen_mla64_i64,
4210 .fniv = gen_mla_vec,
4211 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4212 .load_dest = true,
4213 .opt_opc = vecop_list_mla,
4214 .vece = MO_64 },
4217 const GVecGen3 mls_op[4] = {
4218 { .fni4 = gen_mls8_i32,
4219 .fniv = gen_mls_vec,
4220 .load_dest = true,
4221 .opt_opc = vecop_list_mls,
4222 .vece = MO_8 },
4223 { .fni4 = gen_mls16_i32,
4224 .fniv = gen_mls_vec,
4225 .load_dest = true,
4226 .opt_opc = vecop_list_mls,
4227 .vece = MO_16 },
4228 { .fni4 = gen_mls32_i32,
4229 .fniv = gen_mls_vec,
4230 .load_dest = true,
4231 .opt_opc = vecop_list_mls,
4232 .vece = MO_32 },
4233 { .fni8 = gen_mls64_i64,
4234 .fniv = gen_mls_vec,
4235 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4236 .load_dest = true,
4237 .opt_opc = vecop_list_mls,
4238 .vece = MO_64 },
4241 /* CMTST : test is "if (X & Y != 0)". */
4242 static void gen_cmtst_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4244 tcg_gen_and_i32(d, a, b);
4245 tcg_gen_setcondi_i32(TCG_COND_NE, d, d, 0);
4246 tcg_gen_neg_i32(d, d);
4249 void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4251 tcg_gen_and_i64(d, a, b);
4252 tcg_gen_setcondi_i64(TCG_COND_NE, d, d, 0);
4253 tcg_gen_neg_i64(d, d);
4256 static void gen_cmtst_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4258 tcg_gen_and_vec(vece, d, a, b);
4259 tcg_gen_dupi_vec(vece, a, 0);
4260 tcg_gen_cmp_vec(TCG_COND_NE, vece, d, d, a);
4263 static const TCGOpcode vecop_list_cmtst[] = { INDEX_op_cmp_vec, 0 };
4265 const GVecGen3 cmtst_op[4] = {
4266 { .fni4 = gen_helper_neon_tst_u8,
4267 .fniv = gen_cmtst_vec,
4268 .opt_opc = vecop_list_cmtst,
4269 .vece = MO_8 },
4270 { .fni4 = gen_helper_neon_tst_u16,
4271 .fniv = gen_cmtst_vec,
4272 .opt_opc = vecop_list_cmtst,
4273 .vece = MO_16 },
4274 { .fni4 = gen_cmtst_i32,
4275 .fniv = gen_cmtst_vec,
4276 .opt_opc = vecop_list_cmtst,
4277 .vece = MO_32 },
4278 { .fni8 = gen_cmtst_i64,
4279 .fniv = gen_cmtst_vec,
4280 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4281 .opt_opc = vecop_list_cmtst,
4282 .vece = MO_64 },
4285 void gen_ushl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift)
4287 TCGv_i32 lval = tcg_temp_new_i32();
4288 TCGv_i32 rval = tcg_temp_new_i32();
4289 TCGv_i32 lsh = tcg_temp_new_i32();
4290 TCGv_i32 rsh = tcg_temp_new_i32();
4291 TCGv_i32 zero = tcg_const_i32(0);
4292 TCGv_i32 max = tcg_const_i32(32);
4295 * Rely on the TCG guarantee that out of range shifts produce
4296 * unspecified results, not undefined behaviour (i.e. no trap).
4297 * Discard out-of-range results after the fact.
4299 tcg_gen_ext8s_i32(lsh, shift);
4300 tcg_gen_neg_i32(rsh, lsh);
4301 tcg_gen_shl_i32(lval, src, lsh);
4302 tcg_gen_shr_i32(rval, src, rsh);
4303 tcg_gen_movcond_i32(TCG_COND_LTU, dst, lsh, max, lval, zero);
4304 tcg_gen_movcond_i32(TCG_COND_LTU, dst, rsh, max, rval, dst);
4306 tcg_temp_free_i32(lval);
4307 tcg_temp_free_i32(rval);
4308 tcg_temp_free_i32(lsh);
4309 tcg_temp_free_i32(rsh);
4310 tcg_temp_free_i32(zero);
4311 tcg_temp_free_i32(max);
4314 void gen_ushl_i64(TCGv_i64 dst, TCGv_i64 src, TCGv_i64 shift)
4316 TCGv_i64 lval = tcg_temp_new_i64();
4317 TCGv_i64 rval = tcg_temp_new_i64();
4318 TCGv_i64 lsh = tcg_temp_new_i64();
4319 TCGv_i64 rsh = tcg_temp_new_i64();
4320 TCGv_i64 zero = tcg_const_i64(0);
4321 TCGv_i64 max = tcg_const_i64(64);
4324 * Rely on the TCG guarantee that out of range shifts produce
4325 * unspecified results, not undefined behaviour (i.e. no trap).
4326 * Discard out-of-range results after the fact.
4328 tcg_gen_ext8s_i64(lsh, shift);
4329 tcg_gen_neg_i64(rsh, lsh);
4330 tcg_gen_shl_i64(lval, src, lsh);
4331 tcg_gen_shr_i64(rval, src, rsh);
4332 tcg_gen_movcond_i64(TCG_COND_LTU, dst, lsh, max, lval, zero);
4333 tcg_gen_movcond_i64(TCG_COND_LTU, dst, rsh, max, rval, dst);
4335 tcg_temp_free_i64(lval);
4336 tcg_temp_free_i64(rval);
4337 tcg_temp_free_i64(lsh);
4338 tcg_temp_free_i64(rsh);
4339 tcg_temp_free_i64(zero);
4340 tcg_temp_free_i64(max);
4343 static void gen_ushl_vec(unsigned vece, TCGv_vec dst,
4344 TCGv_vec src, TCGv_vec shift)
4346 TCGv_vec lval = tcg_temp_new_vec_matching(dst);
4347 TCGv_vec rval = tcg_temp_new_vec_matching(dst);
4348 TCGv_vec lsh = tcg_temp_new_vec_matching(dst);
4349 TCGv_vec rsh = tcg_temp_new_vec_matching(dst);
4350 TCGv_vec msk, max;
4352 tcg_gen_neg_vec(vece, rsh, shift);
4353 if (vece == MO_8) {
4354 tcg_gen_mov_vec(lsh, shift);
4355 } else {
4356 msk = tcg_temp_new_vec_matching(dst);
4357 tcg_gen_dupi_vec(vece, msk, 0xff);
4358 tcg_gen_and_vec(vece, lsh, shift, msk);
4359 tcg_gen_and_vec(vece, rsh, rsh, msk);
4360 tcg_temp_free_vec(msk);
4364 * Rely on the TCG guarantee that out of range shifts produce
4365 * unspecified results, not undefined behaviour (i.e. no trap).
4366 * Discard out-of-range results after the fact.
4368 tcg_gen_shlv_vec(vece, lval, src, lsh);
4369 tcg_gen_shrv_vec(vece, rval, src, rsh);
4371 max = tcg_temp_new_vec_matching(dst);
4372 tcg_gen_dupi_vec(vece, max, 8 << vece);
4375 * The choice of LT (signed) and GEU (unsigned) are biased toward
4376 * the instructions of the x86_64 host. For MO_8, the whole byte
4377 * is significant so we must use an unsigned compare; otherwise we
4378 * have already masked to a byte and so a signed compare works.
4379 * Other tcg hosts have a full set of comparisons and do not care.
4381 if (vece == MO_8) {
4382 tcg_gen_cmp_vec(TCG_COND_GEU, vece, lsh, lsh, max);
4383 tcg_gen_cmp_vec(TCG_COND_GEU, vece, rsh, rsh, max);
4384 tcg_gen_andc_vec(vece, lval, lval, lsh);
4385 tcg_gen_andc_vec(vece, rval, rval, rsh);
4386 } else {
4387 tcg_gen_cmp_vec(TCG_COND_LT, vece, lsh, lsh, max);
4388 tcg_gen_cmp_vec(TCG_COND_LT, vece, rsh, rsh, max);
4389 tcg_gen_and_vec(vece, lval, lval, lsh);
4390 tcg_gen_and_vec(vece, rval, rval, rsh);
4392 tcg_gen_or_vec(vece, dst, lval, rval);
4394 tcg_temp_free_vec(max);
4395 tcg_temp_free_vec(lval);
4396 tcg_temp_free_vec(rval);
4397 tcg_temp_free_vec(lsh);
4398 tcg_temp_free_vec(rsh);
4401 static const TCGOpcode ushl_list[] = {
4402 INDEX_op_neg_vec, INDEX_op_shlv_vec,
4403 INDEX_op_shrv_vec, INDEX_op_cmp_vec, 0
4406 const GVecGen3 ushl_op[4] = {
4407 { .fniv = gen_ushl_vec,
4408 .fno = gen_helper_gvec_ushl_b,
4409 .opt_opc = ushl_list,
4410 .vece = MO_8 },
4411 { .fniv = gen_ushl_vec,
4412 .fno = gen_helper_gvec_ushl_h,
4413 .opt_opc = ushl_list,
4414 .vece = MO_16 },
4415 { .fni4 = gen_ushl_i32,
4416 .fniv = gen_ushl_vec,
4417 .opt_opc = ushl_list,
4418 .vece = MO_32 },
4419 { .fni8 = gen_ushl_i64,
4420 .fniv = gen_ushl_vec,
4421 .opt_opc = ushl_list,
4422 .vece = MO_64 },
4425 void gen_sshl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift)
4427 TCGv_i32 lval = tcg_temp_new_i32();
4428 TCGv_i32 rval = tcg_temp_new_i32();
4429 TCGv_i32 lsh = tcg_temp_new_i32();
4430 TCGv_i32 rsh = tcg_temp_new_i32();
4431 TCGv_i32 zero = tcg_const_i32(0);
4432 TCGv_i32 max = tcg_const_i32(31);
4435 * Rely on the TCG guarantee that out of range shifts produce
4436 * unspecified results, not undefined behaviour (i.e. no trap).
4437 * Discard out-of-range results after the fact.
4439 tcg_gen_ext8s_i32(lsh, shift);
4440 tcg_gen_neg_i32(rsh, lsh);
4441 tcg_gen_shl_i32(lval, src, lsh);
4442 tcg_gen_umin_i32(rsh, rsh, max);
4443 tcg_gen_sar_i32(rval, src, rsh);
4444 tcg_gen_movcond_i32(TCG_COND_LEU, lval, lsh, max, lval, zero);
4445 tcg_gen_movcond_i32(TCG_COND_LT, dst, lsh, zero, rval, lval);
4447 tcg_temp_free_i32(lval);
4448 tcg_temp_free_i32(rval);
4449 tcg_temp_free_i32(lsh);
4450 tcg_temp_free_i32(rsh);
4451 tcg_temp_free_i32(zero);
4452 tcg_temp_free_i32(max);
4455 void gen_sshl_i64(TCGv_i64 dst, TCGv_i64 src, TCGv_i64 shift)
4457 TCGv_i64 lval = tcg_temp_new_i64();
4458 TCGv_i64 rval = tcg_temp_new_i64();
4459 TCGv_i64 lsh = tcg_temp_new_i64();
4460 TCGv_i64 rsh = tcg_temp_new_i64();
4461 TCGv_i64 zero = tcg_const_i64(0);
4462 TCGv_i64 max = tcg_const_i64(63);
4465 * Rely on the TCG guarantee that out of range shifts produce
4466 * unspecified results, not undefined behaviour (i.e. no trap).
4467 * Discard out-of-range results after the fact.
4469 tcg_gen_ext8s_i64(lsh, shift);
4470 tcg_gen_neg_i64(rsh, lsh);
4471 tcg_gen_shl_i64(lval, src, lsh);
4472 tcg_gen_umin_i64(rsh, rsh, max);
4473 tcg_gen_sar_i64(rval, src, rsh);
4474 tcg_gen_movcond_i64(TCG_COND_LEU, lval, lsh, max, lval, zero);
4475 tcg_gen_movcond_i64(TCG_COND_LT, dst, lsh, zero, rval, lval);
4477 tcg_temp_free_i64(lval);
4478 tcg_temp_free_i64(rval);
4479 tcg_temp_free_i64(lsh);
4480 tcg_temp_free_i64(rsh);
4481 tcg_temp_free_i64(zero);
4482 tcg_temp_free_i64(max);
4485 static void gen_sshl_vec(unsigned vece, TCGv_vec dst,
4486 TCGv_vec src, TCGv_vec shift)
4488 TCGv_vec lval = tcg_temp_new_vec_matching(dst);
4489 TCGv_vec rval = tcg_temp_new_vec_matching(dst);
4490 TCGv_vec lsh = tcg_temp_new_vec_matching(dst);
4491 TCGv_vec rsh = tcg_temp_new_vec_matching(dst);
4492 TCGv_vec tmp = tcg_temp_new_vec_matching(dst);
4495 * Rely on the TCG guarantee that out of range shifts produce
4496 * unspecified results, not undefined behaviour (i.e. no trap).
4497 * Discard out-of-range results after the fact.
4499 tcg_gen_neg_vec(vece, rsh, shift);
4500 if (vece == MO_8) {
4501 tcg_gen_mov_vec(lsh, shift);
4502 } else {
4503 tcg_gen_dupi_vec(vece, tmp, 0xff);
4504 tcg_gen_and_vec(vece, lsh, shift, tmp);
4505 tcg_gen_and_vec(vece, rsh, rsh, tmp);
4508 /* Bound rsh so out of bound right shift gets -1. */
4509 tcg_gen_dupi_vec(vece, tmp, (8 << vece) - 1);
4510 tcg_gen_umin_vec(vece, rsh, rsh, tmp);
4511 tcg_gen_cmp_vec(TCG_COND_GT, vece, tmp, lsh, tmp);
4513 tcg_gen_shlv_vec(vece, lval, src, lsh);
4514 tcg_gen_sarv_vec(vece, rval, src, rsh);
4516 /* Select in-bound left shift. */
4517 tcg_gen_andc_vec(vece, lval, lval, tmp);
4519 /* Select between left and right shift. */
4520 if (vece == MO_8) {
4521 tcg_gen_dupi_vec(vece, tmp, 0);
4522 tcg_gen_cmpsel_vec(TCG_COND_LT, vece, dst, lsh, tmp, rval, lval);
4523 } else {
4524 tcg_gen_dupi_vec(vece, tmp, 0x80);
4525 tcg_gen_cmpsel_vec(TCG_COND_LT, vece, dst, lsh, tmp, lval, rval);
4528 tcg_temp_free_vec(lval);
4529 tcg_temp_free_vec(rval);
4530 tcg_temp_free_vec(lsh);
4531 tcg_temp_free_vec(rsh);
4532 tcg_temp_free_vec(tmp);
4535 static const TCGOpcode sshl_list[] = {
4536 INDEX_op_neg_vec, INDEX_op_umin_vec, INDEX_op_shlv_vec,
4537 INDEX_op_sarv_vec, INDEX_op_cmp_vec, INDEX_op_cmpsel_vec, 0
4540 const GVecGen3 sshl_op[4] = {
4541 { .fniv = gen_sshl_vec,
4542 .fno = gen_helper_gvec_sshl_b,
4543 .opt_opc = sshl_list,
4544 .vece = MO_8 },
4545 { .fniv = gen_sshl_vec,
4546 .fno = gen_helper_gvec_sshl_h,
4547 .opt_opc = sshl_list,
4548 .vece = MO_16 },
4549 { .fni4 = gen_sshl_i32,
4550 .fniv = gen_sshl_vec,
4551 .opt_opc = sshl_list,
4552 .vece = MO_32 },
4553 { .fni8 = gen_sshl_i64,
4554 .fniv = gen_sshl_vec,
4555 .opt_opc = sshl_list,
4556 .vece = MO_64 },
4559 static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4560 TCGv_vec a, TCGv_vec b)
4562 TCGv_vec x = tcg_temp_new_vec_matching(t);
4563 tcg_gen_add_vec(vece, x, a, b);
4564 tcg_gen_usadd_vec(vece, t, a, b);
4565 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4566 tcg_gen_or_vec(vece, sat, sat, x);
4567 tcg_temp_free_vec(x);
4570 static const TCGOpcode vecop_list_uqadd[] = {
4571 INDEX_op_usadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
4574 const GVecGen4 uqadd_op[4] = {
4575 { .fniv = gen_uqadd_vec,
4576 .fno = gen_helper_gvec_uqadd_b,
4577 .write_aofs = true,
4578 .opt_opc = vecop_list_uqadd,
4579 .vece = MO_8 },
4580 { .fniv = gen_uqadd_vec,
4581 .fno = gen_helper_gvec_uqadd_h,
4582 .write_aofs = true,
4583 .opt_opc = vecop_list_uqadd,
4584 .vece = MO_16 },
4585 { .fniv = gen_uqadd_vec,
4586 .fno = gen_helper_gvec_uqadd_s,
4587 .write_aofs = true,
4588 .opt_opc = vecop_list_uqadd,
4589 .vece = MO_32 },
4590 { .fniv = gen_uqadd_vec,
4591 .fno = gen_helper_gvec_uqadd_d,
4592 .write_aofs = true,
4593 .opt_opc = vecop_list_uqadd,
4594 .vece = MO_64 },
4597 static void gen_sqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4598 TCGv_vec a, TCGv_vec b)
4600 TCGv_vec x = tcg_temp_new_vec_matching(t);
4601 tcg_gen_add_vec(vece, x, a, b);
4602 tcg_gen_ssadd_vec(vece, t, a, b);
4603 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4604 tcg_gen_or_vec(vece, sat, sat, x);
4605 tcg_temp_free_vec(x);
4608 static const TCGOpcode vecop_list_sqadd[] = {
4609 INDEX_op_ssadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
4612 const GVecGen4 sqadd_op[4] = {
4613 { .fniv = gen_sqadd_vec,
4614 .fno = gen_helper_gvec_sqadd_b,
4615 .opt_opc = vecop_list_sqadd,
4616 .write_aofs = true,
4617 .vece = MO_8 },
4618 { .fniv = gen_sqadd_vec,
4619 .fno = gen_helper_gvec_sqadd_h,
4620 .opt_opc = vecop_list_sqadd,
4621 .write_aofs = true,
4622 .vece = MO_16 },
4623 { .fniv = gen_sqadd_vec,
4624 .fno = gen_helper_gvec_sqadd_s,
4625 .opt_opc = vecop_list_sqadd,
4626 .write_aofs = true,
4627 .vece = MO_32 },
4628 { .fniv = gen_sqadd_vec,
4629 .fno = gen_helper_gvec_sqadd_d,
4630 .opt_opc = vecop_list_sqadd,
4631 .write_aofs = true,
4632 .vece = MO_64 },
4635 static void gen_uqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4636 TCGv_vec a, TCGv_vec b)
4638 TCGv_vec x = tcg_temp_new_vec_matching(t);
4639 tcg_gen_sub_vec(vece, x, a, b);
4640 tcg_gen_ussub_vec(vece, t, a, b);
4641 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4642 tcg_gen_or_vec(vece, sat, sat, x);
4643 tcg_temp_free_vec(x);
4646 static const TCGOpcode vecop_list_uqsub[] = {
4647 INDEX_op_ussub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
4650 const GVecGen4 uqsub_op[4] = {
4651 { .fniv = gen_uqsub_vec,
4652 .fno = gen_helper_gvec_uqsub_b,
4653 .opt_opc = vecop_list_uqsub,
4654 .write_aofs = true,
4655 .vece = MO_8 },
4656 { .fniv = gen_uqsub_vec,
4657 .fno = gen_helper_gvec_uqsub_h,
4658 .opt_opc = vecop_list_uqsub,
4659 .write_aofs = true,
4660 .vece = MO_16 },
4661 { .fniv = gen_uqsub_vec,
4662 .fno = gen_helper_gvec_uqsub_s,
4663 .opt_opc = vecop_list_uqsub,
4664 .write_aofs = true,
4665 .vece = MO_32 },
4666 { .fniv = gen_uqsub_vec,
4667 .fno = gen_helper_gvec_uqsub_d,
4668 .opt_opc = vecop_list_uqsub,
4669 .write_aofs = true,
4670 .vece = MO_64 },
4673 static void gen_sqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4674 TCGv_vec a, TCGv_vec b)
4676 TCGv_vec x = tcg_temp_new_vec_matching(t);
4677 tcg_gen_sub_vec(vece, x, a, b);
4678 tcg_gen_sssub_vec(vece, t, a, b);
4679 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4680 tcg_gen_or_vec(vece, sat, sat, x);
4681 tcg_temp_free_vec(x);
4684 static const TCGOpcode vecop_list_sqsub[] = {
4685 INDEX_op_sssub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
4688 const GVecGen4 sqsub_op[4] = {
4689 { .fniv = gen_sqsub_vec,
4690 .fno = gen_helper_gvec_sqsub_b,
4691 .opt_opc = vecop_list_sqsub,
4692 .write_aofs = true,
4693 .vece = MO_8 },
4694 { .fniv = gen_sqsub_vec,
4695 .fno = gen_helper_gvec_sqsub_h,
4696 .opt_opc = vecop_list_sqsub,
4697 .write_aofs = true,
4698 .vece = MO_16 },
4699 { .fniv = gen_sqsub_vec,
4700 .fno = gen_helper_gvec_sqsub_s,
4701 .opt_opc = vecop_list_sqsub,
4702 .write_aofs = true,
4703 .vece = MO_32 },
4704 { .fniv = gen_sqsub_vec,
4705 .fno = gen_helper_gvec_sqsub_d,
4706 .opt_opc = vecop_list_sqsub,
4707 .write_aofs = true,
4708 .vece = MO_64 },
4711 /* Translate a NEON data processing instruction. Return nonzero if the
4712 instruction is invalid.
4713 We process data in a mixture of 32-bit and 64-bit chunks.
4714 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4716 static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
4718 int op;
4719 int q;
4720 int rd, rn, rm, rd_ofs, rn_ofs, rm_ofs;
4721 int size;
4722 int shift;
4723 int pass;
4724 int count;
4725 int pairwise;
4726 int u;
4727 int vec_size;
4728 uint32_t imm;
4729 TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
4730 TCGv_ptr ptr1, ptr2, ptr3;
4731 TCGv_i64 tmp64;
4733 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
4734 return 1;
4737 /* FIXME: this access check should not take precedence over UNDEF
4738 * for invalid encodings; we will generate incorrect syndrome information
4739 * for attempts to execute invalid vfp/neon encodings with FP disabled.
4741 if (s->fp_excp_el) {
4742 gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
4743 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
4744 return 0;
4747 if (!s->vfp_enabled)
4748 return 1;
4749 q = (insn & (1 << 6)) != 0;
4750 u = (insn >> 24) & 1;
4751 VFP_DREG_D(rd, insn);
4752 VFP_DREG_N(rn, insn);
4753 VFP_DREG_M(rm, insn);
4754 size = (insn >> 20) & 3;
4755 vec_size = q ? 16 : 8;
4756 rd_ofs = neon_reg_offset(rd, 0);
4757 rn_ofs = neon_reg_offset(rn, 0);
4758 rm_ofs = neon_reg_offset(rm, 0);
4760 if ((insn & (1 << 23)) == 0) {
4761 /* Three register same length. */
4762 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4763 /* Catch invalid op and bad size combinations: UNDEF */
4764 if ((neon_3r_sizes[op] & (1 << size)) == 0) {
4765 return 1;
4767 /* All insns of this form UNDEF for either this condition or the
4768 * superset of cases "Q==1"; we catch the latter later.
4770 if (q && ((rd | rn | rm) & 1)) {
4771 return 1;
4773 switch (op) {
4774 case NEON_3R_SHA:
4775 /* The SHA-1/SHA-256 3-register instructions require special
4776 * treatment here, as their size field is overloaded as an
4777 * op type selector, and they all consume their input in a
4778 * single pass.
4780 if (!q) {
4781 return 1;
4783 if (!u) { /* SHA-1 */
4784 if (!dc_isar_feature(aa32_sha1, s)) {
4785 return 1;
4787 ptr1 = vfp_reg_ptr(true, rd);
4788 ptr2 = vfp_reg_ptr(true, rn);
4789 ptr3 = vfp_reg_ptr(true, rm);
4790 tmp4 = tcg_const_i32(size);
4791 gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp4);
4792 tcg_temp_free_i32(tmp4);
4793 } else { /* SHA-256 */
4794 if (!dc_isar_feature(aa32_sha2, s) || size == 3) {
4795 return 1;
4797 ptr1 = vfp_reg_ptr(true, rd);
4798 ptr2 = vfp_reg_ptr(true, rn);
4799 ptr3 = vfp_reg_ptr(true, rm);
4800 switch (size) {
4801 case 0:
4802 gen_helper_crypto_sha256h(ptr1, ptr2, ptr3);
4803 break;
4804 case 1:
4805 gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3);
4806 break;
4807 case 2:
4808 gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3);
4809 break;
4812 tcg_temp_free_ptr(ptr1);
4813 tcg_temp_free_ptr(ptr2);
4814 tcg_temp_free_ptr(ptr3);
4815 return 0;
4817 case NEON_3R_VPADD_VQRDMLAH:
4818 if (!u) {
4819 break; /* VPADD */
4821 /* VQRDMLAH */
4822 switch (size) {
4823 case 1:
4824 return do_v81_helper(s, gen_helper_gvec_qrdmlah_s16,
4825 q, rd, rn, rm);
4826 case 2:
4827 return do_v81_helper(s, gen_helper_gvec_qrdmlah_s32,
4828 q, rd, rn, rm);
4830 return 1;
4832 case NEON_3R_VFM_VQRDMLSH:
4833 if (!u) {
4834 /* VFM, VFMS */
4835 if (size == 1) {
4836 return 1;
4838 break;
4840 /* VQRDMLSH */
4841 switch (size) {
4842 case 1:
4843 return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s16,
4844 q, rd, rn, rm);
4845 case 2:
4846 return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s32,
4847 q, rd, rn, rm);
4849 return 1;
4851 case NEON_3R_VQADD:
4852 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4853 rn_ofs, rm_ofs, vec_size, vec_size,
4854 (u ? uqadd_op : sqadd_op) + size);
4855 return 0;
4857 case NEON_3R_VQSUB:
4858 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4859 rn_ofs, rm_ofs, vec_size, vec_size,
4860 (u ? uqsub_op : sqsub_op) + size);
4861 return 0;
4863 case NEON_3R_VMUL: /* VMUL */
4864 if (u) {
4865 /* Polynomial case allows only P8. */
4866 if (size != 0) {
4867 return 1;
4869 tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size,
4870 0, gen_helper_gvec_pmul_b);
4871 } else {
4872 tcg_gen_gvec_mul(size, rd_ofs, rn_ofs, rm_ofs,
4873 vec_size, vec_size);
4875 return 0;
4877 case NEON_3R_VML: /* VMLA, VMLS */
4878 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size,
4879 u ? &mls_op[size] : &mla_op[size]);
4880 return 0;
4882 case NEON_3R_VTST_VCEQ:
4883 if (u) { /* VCEQ */
4884 tcg_gen_gvec_cmp(TCG_COND_EQ, size, rd_ofs, rn_ofs, rm_ofs,
4885 vec_size, vec_size);
4886 } else { /* VTST */
4887 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
4888 vec_size, vec_size, &cmtst_op[size]);
4890 return 0;
4892 case NEON_3R_VCGT:
4893 tcg_gen_gvec_cmp(u ? TCG_COND_GTU : TCG_COND_GT, size,
4894 rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
4895 return 0;
4897 case NEON_3R_VCGE:
4898 tcg_gen_gvec_cmp(u ? TCG_COND_GEU : TCG_COND_GE, size,
4899 rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
4900 return 0;
4902 case NEON_3R_VMAX:
4903 if (u) {
4904 tcg_gen_gvec_umax(size, rd_ofs, rn_ofs, rm_ofs,
4905 vec_size, vec_size);
4906 } else {
4907 tcg_gen_gvec_smax(size, rd_ofs, rn_ofs, rm_ofs,
4908 vec_size, vec_size);
4910 return 0;
4911 case NEON_3R_VMIN:
4912 if (u) {
4913 tcg_gen_gvec_umin(size, rd_ofs, rn_ofs, rm_ofs,
4914 vec_size, vec_size);
4915 } else {
4916 tcg_gen_gvec_smin(size, rd_ofs, rn_ofs, rm_ofs,
4917 vec_size, vec_size);
4919 return 0;
4921 case NEON_3R_VSHL:
4922 /* Note the operation is vshl vd,vm,vn */
4923 tcg_gen_gvec_3(rd_ofs, rm_ofs, rn_ofs, vec_size, vec_size,
4924 u ? &ushl_op[size] : &sshl_op[size]);
4925 return 0;
4927 case NEON_3R_VADD_VSUB:
4928 case NEON_3R_LOGIC:
4929 /* Already handled by decodetree */
4930 return 1;
4933 if (size == 3) {
4934 /* 64-bit element instructions. */
4935 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4936 neon_load_reg64(cpu_V0, rn + pass);
4937 neon_load_reg64(cpu_V1, rm + pass);
4938 switch (op) {
4939 case NEON_3R_VQSHL:
4940 if (u) {
4941 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4942 cpu_V1, cpu_V0);
4943 } else {
4944 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
4945 cpu_V1, cpu_V0);
4947 break;
4948 case NEON_3R_VRSHL:
4949 if (u) {
4950 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4951 } else {
4952 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4954 break;
4955 case NEON_3R_VQRSHL:
4956 if (u) {
4957 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4958 cpu_V1, cpu_V0);
4959 } else {
4960 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4961 cpu_V1, cpu_V0);
4963 break;
4964 default:
4965 abort();
4967 neon_store_reg64(cpu_V0, rd + pass);
4969 return 0;
4971 pairwise = 0;
4972 switch (op) {
4973 case NEON_3R_VQSHL:
4974 case NEON_3R_VRSHL:
4975 case NEON_3R_VQRSHL:
4977 int rtmp;
4978 /* Shift instruction operands are reversed. */
4979 rtmp = rn;
4980 rn = rm;
4981 rm = rtmp;
4983 break;
4984 case NEON_3R_VPADD_VQRDMLAH:
4985 case NEON_3R_VPMAX:
4986 case NEON_3R_VPMIN:
4987 pairwise = 1;
4988 break;
4989 case NEON_3R_FLOAT_ARITH:
4990 pairwise = (u && size < 2); /* if VPADD (float) */
4991 break;
4992 case NEON_3R_FLOAT_MINMAX:
4993 pairwise = u; /* if VPMIN/VPMAX (float) */
4994 break;
4995 case NEON_3R_FLOAT_CMP:
4996 if (!u && size) {
4997 /* no encoding for U=0 C=1x */
4998 return 1;
5000 break;
5001 case NEON_3R_FLOAT_ACMP:
5002 if (!u) {
5003 return 1;
5005 break;
5006 case NEON_3R_FLOAT_MISC:
5007 /* VMAXNM/VMINNM in ARMv8 */
5008 if (u && !arm_dc_feature(s, ARM_FEATURE_V8)) {
5009 return 1;
5011 break;
5012 case NEON_3R_VFM_VQRDMLSH:
5013 if (!dc_isar_feature(aa32_simdfmac, s)) {
5014 return 1;
5016 break;
5017 default:
5018 break;
5021 if (pairwise && q) {
5022 /* All the pairwise insns UNDEF if Q is set */
5023 return 1;
5026 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5028 if (pairwise) {
5029 /* Pairwise. */
5030 if (pass < 1) {
5031 tmp = neon_load_reg(rn, 0);
5032 tmp2 = neon_load_reg(rn, 1);
5033 } else {
5034 tmp = neon_load_reg(rm, 0);
5035 tmp2 = neon_load_reg(rm, 1);
5037 } else {
5038 /* Elementwise. */
5039 tmp = neon_load_reg(rn, pass);
5040 tmp2 = neon_load_reg(rm, pass);
5042 switch (op) {
5043 case NEON_3R_VHADD:
5044 GEN_NEON_INTEGER_OP(hadd);
5045 break;
5046 case NEON_3R_VRHADD:
5047 GEN_NEON_INTEGER_OP(rhadd);
5048 break;
5049 case NEON_3R_VHSUB:
5050 GEN_NEON_INTEGER_OP(hsub);
5051 break;
5052 case NEON_3R_VQSHL:
5053 GEN_NEON_INTEGER_OP_ENV(qshl);
5054 break;
5055 case NEON_3R_VRSHL:
5056 GEN_NEON_INTEGER_OP(rshl);
5057 break;
5058 case NEON_3R_VQRSHL:
5059 GEN_NEON_INTEGER_OP_ENV(qrshl);
5060 break;
5061 case NEON_3R_VABD:
5062 GEN_NEON_INTEGER_OP(abd);
5063 break;
5064 case NEON_3R_VABA:
5065 GEN_NEON_INTEGER_OP(abd);
5066 tcg_temp_free_i32(tmp2);
5067 tmp2 = neon_load_reg(rd, pass);
5068 gen_neon_add(size, tmp, tmp2);
5069 break;
5070 case NEON_3R_VPMAX:
5071 GEN_NEON_INTEGER_OP(pmax);
5072 break;
5073 case NEON_3R_VPMIN:
5074 GEN_NEON_INTEGER_OP(pmin);
5075 break;
5076 case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
5077 if (!u) { /* VQDMULH */
5078 switch (size) {
5079 case 1:
5080 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5081 break;
5082 case 2:
5083 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5084 break;
5085 default: abort();
5087 } else { /* VQRDMULH */
5088 switch (size) {
5089 case 1:
5090 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5091 break;
5092 case 2:
5093 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5094 break;
5095 default: abort();
5098 break;
5099 case NEON_3R_VPADD_VQRDMLAH:
5100 switch (size) {
5101 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
5102 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
5103 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
5104 default: abort();
5106 break;
5107 case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
5109 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5110 switch ((u << 2) | size) {
5111 case 0: /* VADD */
5112 case 4: /* VPADD */
5113 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5114 break;
5115 case 2: /* VSUB */
5116 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
5117 break;
5118 case 6: /* VABD */
5119 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
5120 break;
5121 default:
5122 abort();
5124 tcg_temp_free_ptr(fpstatus);
5125 break;
5127 case NEON_3R_FLOAT_MULTIPLY:
5129 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5130 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
5131 if (!u) {
5132 tcg_temp_free_i32(tmp2);
5133 tmp2 = neon_load_reg(rd, pass);
5134 if (size == 0) {
5135 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5136 } else {
5137 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
5140 tcg_temp_free_ptr(fpstatus);
5141 break;
5143 case NEON_3R_FLOAT_CMP:
5145 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5146 if (!u) {
5147 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
5148 } else {
5149 if (size == 0) {
5150 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
5151 } else {
5152 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
5155 tcg_temp_free_ptr(fpstatus);
5156 break;
5158 case NEON_3R_FLOAT_ACMP:
5160 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5161 if (size == 0) {
5162 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
5163 } else {
5164 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
5166 tcg_temp_free_ptr(fpstatus);
5167 break;
5169 case NEON_3R_FLOAT_MINMAX:
5171 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5172 if (size == 0) {
5173 gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus);
5174 } else {
5175 gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus);
5177 tcg_temp_free_ptr(fpstatus);
5178 break;
5180 case NEON_3R_FLOAT_MISC:
5181 if (u) {
5182 /* VMAXNM/VMINNM */
5183 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5184 if (size == 0) {
5185 gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus);
5186 } else {
5187 gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus);
5189 tcg_temp_free_ptr(fpstatus);
5190 } else {
5191 if (size == 0) {
5192 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
5193 } else {
5194 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
5197 break;
5198 case NEON_3R_VFM_VQRDMLSH:
5200 /* VFMA, VFMS: fused multiply-add */
5201 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5202 TCGv_i32 tmp3 = neon_load_reg(rd, pass);
5203 if (size) {
5204 /* VFMS */
5205 gen_helper_vfp_negs(tmp, tmp);
5207 gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus);
5208 tcg_temp_free_i32(tmp3);
5209 tcg_temp_free_ptr(fpstatus);
5210 break;
5212 default:
5213 abort();
5215 tcg_temp_free_i32(tmp2);
5217 /* Save the result. For elementwise operations we can put it
5218 straight into the destination register. For pairwise operations
5219 we have to be careful to avoid clobbering the source operands. */
5220 if (pairwise && rd == rm) {
5221 neon_store_scratch(pass, tmp);
5222 } else {
5223 neon_store_reg(rd, pass, tmp);
5226 } /* for pass */
5227 if (pairwise && rd == rm) {
5228 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5229 tmp = neon_load_scratch(pass);
5230 neon_store_reg(rd, pass, tmp);
5233 /* End of 3 register same size operations. */
5234 } else if (insn & (1 << 4)) {
5235 if ((insn & 0x00380080) != 0) {
5236 /* Two registers and shift. */
5237 op = (insn >> 8) & 0xf;
5238 if (insn & (1 << 7)) {
5239 /* 64-bit shift. */
5240 if (op > 7) {
5241 return 1;
5243 size = 3;
5244 } else {
5245 size = 2;
5246 while ((insn & (1 << (size + 19))) == 0)
5247 size--;
5249 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
5250 if (op < 8) {
5251 /* Shift by immediate:
5252 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
5253 if (q && ((rd | rm) & 1)) {
5254 return 1;
5256 if (!u && (op == 4 || op == 6)) {
5257 return 1;
5259 /* Right shifts are encoded as N - shift, where N is the
5260 element size in bits. */
5261 if (op <= 4) {
5262 shift = shift - (1 << (size + 3));
5265 switch (op) {
5266 case 0: /* VSHR */
5267 /* Right shift comes here negative. */
5268 shift = -shift;
5269 /* Shifts larger than the element size are architecturally
5270 * valid. Unsigned results in all zeros; signed results
5271 * in all sign bits.
5273 if (!u) {
5274 tcg_gen_gvec_sari(size, rd_ofs, rm_ofs,
5275 MIN(shift, (8 << size) - 1),
5276 vec_size, vec_size);
5277 } else if (shift >= 8 << size) {
5278 tcg_gen_gvec_dup8i(rd_ofs, vec_size, vec_size, 0);
5279 } else {
5280 tcg_gen_gvec_shri(size, rd_ofs, rm_ofs, shift,
5281 vec_size, vec_size);
5283 return 0;
5285 case 1: /* VSRA */
5286 /* Right shift comes here negative. */
5287 shift = -shift;
5288 /* Shifts larger than the element size are architecturally
5289 * valid. Unsigned results in all zeros; signed results
5290 * in all sign bits.
5292 if (!u) {
5293 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
5294 MIN(shift, (8 << size) - 1),
5295 &ssra_op[size]);
5296 } else if (shift >= 8 << size) {
5297 /* rd += 0 */
5298 } else {
5299 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
5300 shift, &usra_op[size]);
5302 return 0;
5304 case 4: /* VSRI */
5305 if (!u) {
5306 return 1;
5308 /* Right shift comes here negative. */
5309 shift = -shift;
5310 /* Shift out of range leaves destination unchanged. */
5311 if (shift < 8 << size) {
5312 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
5313 shift, &sri_op[size]);
5315 return 0;
5317 case 5: /* VSHL, VSLI */
5318 if (u) { /* VSLI */
5319 /* Shift out of range leaves destination unchanged. */
5320 if (shift < 8 << size) {
5321 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size,
5322 vec_size, shift, &sli_op[size]);
5324 } else { /* VSHL */
5325 /* Shifts larger than the element size are
5326 * architecturally valid and results in zero.
5328 if (shift >= 8 << size) {
5329 tcg_gen_gvec_dup8i(rd_ofs, vec_size, vec_size, 0);
5330 } else {
5331 tcg_gen_gvec_shli(size, rd_ofs, rm_ofs, shift,
5332 vec_size, vec_size);
5335 return 0;
5338 if (size == 3) {
5339 count = q + 1;
5340 } else {
5341 count = q ? 4: 2;
5344 /* To avoid excessive duplication of ops we implement shift
5345 * by immediate using the variable shift operations.
5347 imm = dup_const(size, shift);
5349 for (pass = 0; pass < count; pass++) {
5350 if (size == 3) {
5351 neon_load_reg64(cpu_V0, rm + pass);
5352 tcg_gen_movi_i64(cpu_V1, imm);
5353 switch (op) {
5354 case 2: /* VRSHR */
5355 case 3: /* VRSRA */
5356 if (u)
5357 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
5358 else
5359 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
5360 break;
5361 case 6: /* VQSHLU */
5362 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
5363 cpu_V0, cpu_V1);
5364 break;
5365 case 7: /* VQSHL */
5366 if (u) {
5367 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
5368 cpu_V0, cpu_V1);
5369 } else {
5370 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
5371 cpu_V0, cpu_V1);
5373 break;
5374 default:
5375 g_assert_not_reached();
5377 if (op == 3) {
5378 /* Accumulate. */
5379 neon_load_reg64(cpu_V1, rd + pass);
5380 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
5382 neon_store_reg64(cpu_V0, rd + pass);
5383 } else { /* size < 3 */
5384 /* Operands in T0 and T1. */
5385 tmp = neon_load_reg(rm, pass);
5386 tmp2 = tcg_temp_new_i32();
5387 tcg_gen_movi_i32(tmp2, imm);
5388 switch (op) {
5389 case 2: /* VRSHR */
5390 case 3: /* VRSRA */
5391 GEN_NEON_INTEGER_OP(rshl);
5392 break;
5393 case 6: /* VQSHLU */
5394 switch (size) {
5395 case 0:
5396 gen_helper_neon_qshlu_s8(tmp, cpu_env,
5397 tmp, tmp2);
5398 break;
5399 case 1:
5400 gen_helper_neon_qshlu_s16(tmp, cpu_env,
5401 tmp, tmp2);
5402 break;
5403 case 2:
5404 gen_helper_neon_qshlu_s32(tmp, cpu_env,
5405 tmp, tmp2);
5406 break;
5407 default:
5408 abort();
5410 break;
5411 case 7: /* VQSHL */
5412 GEN_NEON_INTEGER_OP_ENV(qshl);
5413 break;
5414 default:
5415 g_assert_not_reached();
5417 tcg_temp_free_i32(tmp2);
5419 if (op == 3) {
5420 /* Accumulate. */
5421 tmp2 = neon_load_reg(rd, pass);
5422 gen_neon_add(size, tmp, tmp2);
5423 tcg_temp_free_i32(tmp2);
5425 neon_store_reg(rd, pass, tmp);
5427 } /* for pass */
5428 } else if (op < 10) {
5429 /* Shift by immediate and narrow:
5430 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
5431 int input_unsigned = (op == 8) ? !u : u;
5432 if (rm & 1) {
5433 return 1;
5435 shift = shift - (1 << (size + 3));
5436 size++;
5437 if (size == 3) {
5438 tmp64 = tcg_const_i64(shift);
5439 neon_load_reg64(cpu_V0, rm);
5440 neon_load_reg64(cpu_V1, rm + 1);
5441 for (pass = 0; pass < 2; pass++) {
5442 TCGv_i64 in;
5443 if (pass == 0) {
5444 in = cpu_V0;
5445 } else {
5446 in = cpu_V1;
5448 if (q) {
5449 if (input_unsigned) {
5450 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
5451 } else {
5452 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
5454 } else {
5455 if (input_unsigned) {
5456 gen_ushl_i64(cpu_V0, in, tmp64);
5457 } else {
5458 gen_sshl_i64(cpu_V0, in, tmp64);
5461 tmp = tcg_temp_new_i32();
5462 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5463 neon_store_reg(rd, pass, tmp);
5464 } /* for pass */
5465 tcg_temp_free_i64(tmp64);
5466 } else {
5467 if (size == 1) {
5468 imm = (uint16_t)shift;
5469 imm |= imm << 16;
5470 } else {
5471 /* size == 2 */
5472 imm = (uint32_t)shift;
5474 tmp2 = tcg_const_i32(imm);
5475 tmp4 = neon_load_reg(rm + 1, 0);
5476 tmp5 = neon_load_reg(rm + 1, 1);
5477 for (pass = 0; pass < 2; pass++) {
5478 if (pass == 0) {
5479 tmp = neon_load_reg(rm, 0);
5480 } else {
5481 tmp = tmp4;
5483 gen_neon_shift_narrow(size, tmp, tmp2, q,
5484 input_unsigned);
5485 if (pass == 0) {
5486 tmp3 = neon_load_reg(rm, 1);
5487 } else {
5488 tmp3 = tmp5;
5490 gen_neon_shift_narrow(size, tmp3, tmp2, q,
5491 input_unsigned);
5492 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
5493 tcg_temp_free_i32(tmp);
5494 tcg_temp_free_i32(tmp3);
5495 tmp = tcg_temp_new_i32();
5496 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5497 neon_store_reg(rd, pass, tmp);
5498 } /* for pass */
5499 tcg_temp_free_i32(tmp2);
5501 } else if (op == 10) {
5502 /* VSHLL, VMOVL */
5503 if (q || (rd & 1)) {
5504 return 1;
5506 tmp = neon_load_reg(rm, 0);
5507 tmp2 = neon_load_reg(rm, 1);
5508 for (pass = 0; pass < 2; pass++) {
5509 if (pass == 1)
5510 tmp = tmp2;
5512 gen_neon_widen(cpu_V0, tmp, size, u);
5514 if (shift != 0) {
5515 /* The shift is less than the width of the source
5516 type, so we can just shift the whole register. */
5517 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
5518 /* Widen the result of shift: we need to clear
5519 * the potential overflow bits resulting from
5520 * left bits of the narrow input appearing as
5521 * right bits of left the neighbour narrow
5522 * input. */
5523 if (size < 2 || !u) {
5524 uint64_t imm64;
5525 if (size == 0) {
5526 imm = (0xffu >> (8 - shift));
5527 imm |= imm << 16;
5528 } else if (size == 1) {
5529 imm = 0xffff >> (16 - shift);
5530 } else {
5531 /* size == 2 */
5532 imm = 0xffffffff >> (32 - shift);
5534 if (size < 2) {
5535 imm64 = imm | (((uint64_t)imm) << 32);
5536 } else {
5537 imm64 = imm;
5539 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
5542 neon_store_reg64(cpu_V0, rd + pass);
5544 } else if (op >= 14) {
5545 /* VCVT fixed-point. */
5546 TCGv_ptr fpst;
5547 TCGv_i32 shiftv;
5548 VFPGenFixPointFn *fn;
5550 if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
5551 return 1;
5554 if (!(op & 1)) {
5555 if (u) {
5556 fn = gen_helper_vfp_ultos;
5557 } else {
5558 fn = gen_helper_vfp_sltos;
5560 } else {
5561 if (u) {
5562 fn = gen_helper_vfp_touls_round_to_zero;
5563 } else {
5564 fn = gen_helper_vfp_tosls_round_to_zero;
5568 /* We have already masked out the must-be-1 top bit of imm6,
5569 * hence this 32-shift where the ARM ARM has 64-imm6.
5571 shift = 32 - shift;
5572 fpst = get_fpstatus_ptr(1);
5573 shiftv = tcg_const_i32(shift);
5574 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5575 TCGv_i32 tmpf = neon_load_reg(rm, pass);
5576 fn(tmpf, tmpf, shiftv, fpst);
5577 neon_store_reg(rd, pass, tmpf);
5579 tcg_temp_free_ptr(fpst);
5580 tcg_temp_free_i32(shiftv);
5581 } else {
5582 return 1;
5584 } else { /* (insn & 0x00380080) == 0 */
5585 int invert, reg_ofs, vec_size;
5587 if (q && (rd & 1)) {
5588 return 1;
5591 op = (insn >> 8) & 0xf;
5592 /* One register and immediate. */
5593 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
5594 invert = (insn & (1 << 5)) != 0;
5595 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
5596 * We choose to not special-case this and will behave as if a
5597 * valid constant encoding of 0 had been given.
5599 switch (op) {
5600 case 0: case 1:
5601 /* no-op */
5602 break;
5603 case 2: case 3:
5604 imm <<= 8;
5605 break;
5606 case 4: case 5:
5607 imm <<= 16;
5608 break;
5609 case 6: case 7:
5610 imm <<= 24;
5611 break;
5612 case 8: case 9:
5613 imm |= imm << 16;
5614 break;
5615 case 10: case 11:
5616 imm = (imm << 8) | (imm << 24);
5617 break;
5618 case 12:
5619 imm = (imm << 8) | 0xff;
5620 break;
5621 case 13:
5622 imm = (imm << 16) | 0xffff;
5623 break;
5624 case 14:
5625 imm |= (imm << 8) | (imm << 16) | (imm << 24);
5626 if (invert) {
5627 imm = ~imm;
5629 break;
5630 case 15:
5631 if (invert) {
5632 return 1;
5634 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
5635 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
5636 break;
5638 if (invert) {
5639 imm = ~imm;
5642 reg_ofs = neon_reg_offset(rd, 0);
5643 vec_size = q ? 16 : 8;
5645 if (op & 1 && op < 12) {
5646 if (invert) {
5647 /* The immediate value has already been inverted,
5648 * so BIC becomes AND.
5650 tcg_gen_gvec_andi(MO_32, reg_ofs, reg_ofs, imm,
5651 vec_size, vec_size);
5652 } else {
5653 tcg_gen_gvec_ori(MO_32, reg_ofs, reg_ofs, imm,
5654 vec_size, vec_size);
5656 } else {
5657 /* VMOV, VMVN. */
5658 if (op == 14 && invert) {
5659 TCGv_i64 t64 = tcg_temp_new_i64();
5661 for (pass = 0; pass <= q; ++pass) {
5662 uint64_t val = 0;
5663 int n;
5665 for (n = 0; n < 8; n++) {
5666 if (imm & (1 << (n + pass * 8))) {
5667 val |= 0xffull << (n * 8);
5670 tcg_gen_movi_i64(t64, val);
5671 neon_store_reg64(t64, rd + pass);
5673 tcg_temp_free_i64(t64);
5674 } else {
5675 tcg_gen_gvec_dup32i(reg_ofs, vec_size, vec_size, imm);
5679 } else { /* (insn & 0x00800010 == 0x00800000) */
5680 if (size != 3) {
5681 op = (insn >> 8) & 0xf;
5682 if ((insn & (1 << 6)) == 0) {
5683 /* Three registers of different lengths. */
5684 int src1_wide;
5685 int src2_wide;
5686 int prewiden;
5687 /* undefreq: bit 0 : UNDEF if size == 0
5688 * bit 1 : UNDEF if size == 1
5689 * bit 2 : UNDEF if size == 2
5690 * bit 3 : UNDEF if U == 1
5691 * Note that [2:0] set implies 'always UNDEF'
5693 int undefreq;
5694 /* prewiden, src1_wide, src2_wide, undefreq */
5695 static const int neon_3reg_wide[16][4] = {
5696 {1, 0, 0, 0}, /* VADDL */
5697 {1, 1, 0, 0}, /* VADDW */
5698 {1, 0, 0, 0}, /* VSUBL */
5699 {1, 1, 0, 0}, /* VSUBW */
5700 {0, 1, 1, 0}, /* VADDHN */
5701 {0, 0, 0, 0}, /* VABAL */
5702 {0, 1, 1, 0}, /* VSUBHN */
5703 {0, 0, 0, 0}, /* VABDL */
5704 {0, 0, 0, 0}, /* VMLAL */
5705 {0, 0, 0, 9}, /* VQDMLAL */
5706 {0, 0, 0, 0}, /* VMLSL */
5707 {0, 0, 0, 9}, /* VQDMLSL */
5708 {0, 0, 0, 0}, /* Integer VMULL */
5709 {0, 0, 0, 9}, /* VQDMULL */
5710 {0, 0, 0, 0xa}, /* Polynomial VMULL */
5711 {0, 0, 0, 7}, /* Reserved: always UNDEF */
5714 prewiden = neon_3reg_wide[op][0];
5715 src1_wide = neon_3reg_wide[op][1];
5716 src2_wide = neon_3reg_wide[op][2];
5717 undefreq = neon_3reg_wide[op][3];
5719 if ((undefreq & (1 << size)) ||
5720 ((undefreq & 8) && u)) {
5721 return 1;
5723 if ((src1_wide && (rn & 1)) ||
5724 (src2_wide && (rm & 1)) ||
5725 (!src2_wide && (rd & 1))) {
5726 return 1;
5729 /* Handle polynomial VMULL in a single pass. */
5730 if (op == 14) {
5731 if (size == 0) {
5732 /* VMULL.P8 */
5733 tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, 16, 16,
5734 0, gen_helper_neon_pmull_h);
5735 } else {
5736 /* VMULL.P64 */
5737 if (!dc_isar_feature(aa32_pmull, s)) {
5738 return 1;
5740 tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, 16, 16,
5741 0, gen_helper_gvec_pmull_q);
5743 return 0;
5746 /* Avoid overlapping operands. Wide source operands are
5747 always aligned so will never overlap with wide
5748 destinations in problematic ways. */
5749 if (rd == rm && !src2_wide) {
5750 tmp = neon_load_reg(rm, 1);
5751 neon_store_scratch(2, tmp);
5752 } else if (rd == rn && !src1_wide) {
5753 tmp = neon_load_reg(rn, 1);
5754 neon_store_scratch(2, tmp);
5756 tmp3 = NULL;
5757 for (pass = 0; pass < 2; pass++) {
5758 if (src1_wide) {
5759 neon_load_reg64(cpu_V0, rn + pass);
5760 tmp = NULL;
5761 } else {
5762 if (pass == 1 && rd == rn) {
5763 tmp = neon_load_scratch(2);
5764 } else {
5765 tmp = neon_load_reg(rn, pass);
5767 if (prewiden) {
5768 gen_neon_widen(cpu_V0, tmp, size, u);
5771 if (src2_wide) {
5772 neon_load_reg64(cpu_V1, rm + pass);
5773 tmp2 = NULL;
5774 } else {
5775 if (pass == 1 && rd == rm) {
5776 tmp2 = neon_load_scratch(2);
5777 } else {
5778 tmp2 = neon_load_reg(rm, pass);
5780 if (prewiden) {
5781 gen_neon_widen(cpu_V1, tmp2, size, u);
5784 switch (op) {
5785 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5786 gen_neon_addl(size);
5787 break;
5788 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
5789 gen_neon_subl(size);
5790 break;
5791 case 5: case 7: /* VABAL, VABDL */
5792 switch ((size << 1) | u) {
5793 case 0:
5794 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
5795 break;
5796 case 1:
5797 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
5798 break;
5799 case 2:
5800 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
5801 break;
5802 case 3:
5803 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
5804 break;
5805 case 4:
5806 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
5807 break;
5808 case 5:
5809 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
5810 break;
5811 default: abort();
5813 tcg_temp_free_i32(tmp2);
5814 tcg_temp_free_i32(tmp);
5815 break;
5816 case 8: case 9: case 10: case 11: case 12: case 13:
5817 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5818 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5819 break;
5820 default: /* 15 is RESERVED: caught earlier */
5821 abort();
5823 if (op == 13) {
5824 /* VQDMULL */
5825 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5826 neon_store_reg64(cpu_V0, rd + pass);
5827 } else if (op == 5 || (op >= 8 && op <= 11)) {
5828 /* Accumulate. */
5829 neon_load_reg64(cpu_V1, rd + pass);
5830 switch (op) {
5831 case 10: /* VMLSL */
5832 gen_neon_negl(cpu_V0, size);
5833 /* Fall through */
5834 case 5: case 8: /* VABAL, VMLAL */
5835 gen_neon_addl(size);
5836 break;
5837 case 9: case 11: /* VQDMLAL, VQDMLSL */
5838 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5839 if (op == 11) {
5840 gen_neon_negl(cpu_V0, size);
5842 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5843 break;
5844 default:
5845 abort();
5847 neon_store_reg64(cpu_V0, rd + pass);
5848 } else if (op == 4 || op == 6) {
5849 /* Narrowing operation. */
5850 tmp = tcg_temp_new_i32();
5851 if (!u) {
5852 switch (size) {
5853 case 0:
5854 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
5855 break;
5856 case 1:
5857 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
5858 break;
5859 case 2:
5860 tcg_gen_extrh_i64_i32(tmp, cpu_V0);
5861 break;
5862 default: abort();
5864 } else {
5865 switch (size) {
5866 case 0:
5867 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
5868 break;
5869 case 1:
5870 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
5871 break;
5872 case 2:
5873 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
5874 tcg_gen_extrh_i64_i32(tmp, cpu_V0);
5875 break;
5876 default: abort();
5879 if (pass == 0) {
5880 tmp3 = tmp;
5881 } else {
5882 neon_store_reg(rd, 0, tmp3);
5883 neon_store_reg(rd, 1, tmp);
5885 } else {
5886 /* Write back the result. */
5887 neon_store_reg64(cpu_V0, rd + pass);
5890 } else {
5891 /* Two registers and a scalar. NB that for ops of this form
5892 * the ARM ARM labels bit 24 as Q, but it is in our variable
5893 * 'u', not 'q'.
5895 if (size == 0) {
5896 return 1;
5898 switch (op) {
5899 case 1: /* Float VMLA scalar */
5900 case 5: /* Floating point VMLS scalar */
5901 case 9: /* Floating point VMUL scalar */
5902 if (size == 1) {
5903 return 1;
5905 /* fall through */
5906 case 0: /* Integer VMLA scalar */
5907 case 4: /* Integer VMLS scalar */
5908 case 8: /* Integer VMUL scalar */
5909 case 12: /* VQDMULH scalar */
5910 case 13: /* VQRDMULH scalar */
5911 if (u && ((rd | rn) & 1)) {
5912 return 1;
5914 tmp = neon_get_scalar(size, rm);
5915 neon_store_scratch(0, tmp);
5916 for (pass = 0; pass < (u ? 4 : 2); pass++) {
5917 tmp = neon_load_scratch(0);
5918 tmp2 = neon_load_reg(rn, pass);
5919 if (op == 12) {
5920 if (size == 1) {
5921 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5922 } else {
5923 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5925 } else if (op == 13) {
5926 if (size == 1) {
5927 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5928 } else {
5929 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5931 } else if (op & 1) {
5932 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5933 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
5934 tcg_temp_free_ptr(fpstatus);
5935 } else {
5936 switch (size) {
5937 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5938 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5939 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5940 default: abort();
5943 tcg_temp_free_i32(tmp2);
5944 if (op < 8) {
5945 /* Accumulate. */
5946 tmp2 = neon_load_reg(rd, pass);
5947 switch (op) {
5948 case 0:
5949 gen_neon_add(size, tmp, tmp2);
5950 break;
5951 case 1:
5953 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5954 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5955 tcg_temp_free_ptr(fpstatus);
5956 break;
5958 case 4:
5959 gen_neon_rsb(size, tmp, tmp2);
5960 break;
5961 case 5:
5963 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5964 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
5965 tcg_temp_free_ptr(fpstatus);
5966 break;
5968 default:
5969 abort();
5971 tcg_temp_free_i32(tmp2);
5973 neon_store_reg(rd, pass, tmp);
5975 break;
5976 case 3: /* VQDMLAL scalar */
5977 case 7: /* VQDMLSL scalar */
5978 case 11: /* VQDMULL scalar */
5979 if (u == 1) {
5980 return 1;
5982 /* fall through */
5983 case 2: /* VMLAL sclar */
5984 case 6: /* VMLSL scalar */
5985 case 10: /* VMULL scalar */
5986 if (rd & 1) {
5987 return 1;
5989 tmp2 = neon_get_scalar(size, rm);
5990 /* We need a copy of tmp2 because gen_neon_mull
5991 * deletes it during pass 0. */
5992 tmp4 = tcg_temp_new_i32();
5993 tcg_gen_mov_i32(tmp4, tmp2);
5994 tmp3 = neon_load_reg(rn, 1);
5996 for (pass = 0; pass < 2; pass++) {
5997 if (pass == 0) {
5998 tmp = neon_load_reg(rn, 0);
5999 } else {
6000 tmp = tmp3;
6001 tmp2 = tmp4;
6003 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
6004 if (op != 11) {
6005 neon_load_reg64(cpu_V1, rd + pass);
6007 switch (op) {
6008 case 6:
6009 gen_neon_negl(cpu_V0, size);
6010 /* Fall through */
6011 case 2:
6012 gen_neon_addl(size);
6013 break;
6014 case 3: case 7:
6015 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6016 if (op == 7) {
6017 gen_neon_negl(cpu_V0, size);
6019 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
6020 break;
6021 case 10:
6022 /* no-op */
6023 break;
6024 case 11:
6025 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6026 break;
6027 default:
6028 abort();
6030 neon_store_reg64(cpu_V0, rd + pass);
6032 break;
6033 case 14: /* VQRDMLAH scalar */
6034 case 15: /* VQRDMLSH scalar */
6036 NeonGenThreeOpEnvFn *fn;
6038 if (!dc_isar_feature(aa32_rdm, s)) {
6039 return 1;
6041 if (u && ((rd | rn) & 1)) {
6042 return 1;
6044 if (op == 14) {
6045 if (size == 1) {
6046 fn = gen_helper_neon_qrdmlah_s16;
6047 } else {
6048 fn = gen_helper_neon_qrdmlah_s32;
6050 } else {
6051 if (size == 1) {
6052 fn = gen_helper_neon_qrdmlsh_s16;
6053 } else {
6054 fn = gen_helper_neon_qrdmlsh_s32;
6058 tmp2 = neon_get_scalar(size, rm);
6059 for (pass = 0; pass < (u ? 4 : 2); pass++) {
6060 tmp = neon_load_reg(rn, pass);
6061 tmp3 = neon_load_reg(rd, pass);
6062 fn(tmp, cpu_env, tmp, tmp2, tmp3);
6063 tcg_temp_free_i32(tmp3);
6064 neon_store_reg(rd, pass, tmp);
6066 tcg_temp_free_i32(tmp2);
6068 break;
6069 default:
6070 g_assert_not_reached();
6073 } else { /* size == 3 */
6074 if (!u) {
6075 /* Extract. */
6076 imm = (insn >> 8) & 0xf;
6078 if (imm > 7 && !q)
6079 return 1;
6081 if (q && ((rd | rn | rm) & 1)) {
6082 return 1;
6085 if (imm == 0) {
6086 neon_load_reg64(cpu_V0, rn);
6087 if (q) {
6088 neon_load_reg64(cpu_V1, rn + 1);
6090 } else if (imm == 8) {
6091 neon_load_reg64(cpu_V0, rn + 1);
6092 if (q) {
6093 neon_load_reg64(cpu_V1, rm);
6095 } else if (q) {
6096 tmp64 = tcg_temp_new_i64();
6097 if (imm < 8) {
6098 neon_load_reg64(cpu_V0, rn);
6099 neon_load_reg64(tmp64, rn + 1);
6100 } else {
6101 neon_load_reg64(cpu_V0, rn + 1);
6102 neon_load_reg64(tmp64, rm);
6104 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
6105 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
6106 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6107 if (imm < 8) {
6108 neon_load_reg64(cpu_V1, rm);
6109 } else {
6110 neon_load_reg64(cpu_V1, rm + 1);
6111 imm -= 8;
6113 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
6114 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
6115 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
6116 tcg_temp_free_i64(tmp64);
6117 } else {
6118 /* BUGFIX */
6119 neon_load_reg64(cpu_V0, rn);
6120 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
6121 neon_load_reg64(cpu_V1, rm);
6122 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
6123 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6125 neon_store_reg64(cpu_V0, rd);
6126 if (q) {
6127 neon_store_reg64(cpu_V1, rd + 1);
6129 } else if ((insn & (1 << 11)) == 0) {
6130 /* Two register misc. */
6131 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
6132 size = (insn >> 18) & 3;
6133 /* UNDEF for unknown op values and bad op-size combinations */
6134 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
6135 return 1;
6137 if (neon_2rm_is_v8_op(op) &&
6138 !arm_dc_feature(s, ARM_FEATURE_V8)) {
6139 return 1;
6141 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
6142 q && ((rm | rd) & 1)) {
6143 return 1;
6145 switch (op) {
6146 case NEON_2RM_VREV64:
6147 for (pass = 0; pass < (q ? 2 : 1); pass++) {
6148 tmp = neon_load_reg(rm, pass * 2);
6149 tmp2 = neon_load_reg(rm, pass * 2 + 1);
6150 switch (size) {
6151 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6152 case 1: gen_swap_half(tmp); break;
6153 case 2: /* no-op */ break;
6154 default: abort();
6156 neon_store_reg(rd, pass * 2 + 1, tmp);
6157 if (size == 2) {
6158 neon_store_reg(rd, pass * 2, tmp2);
6159 } else {
6160 switch (size) {
6161 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
6162 case 1: gen_swap_half(tmp2); break;
6163 default: abort();
6165 neon_store_reg(rd, pass * 2, tmp2);
6168 break;
6169 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
6170 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
6171 for (pass = 0; pass < q + 1; pass++) {
6172 tmp = neon_load_reg(rm, pass * 2);
6173 gen_neon_widen(cpu_V0, tmp, size, op & 1);
6174 tmp = neon_load_reg(rm, pass * 2 + 1);
6175 gen_neon_widen(cpu_V1, tmp, size, op & 1);
6176 switch (size) {
6177 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
6178 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
6179 case 2: tcg_gen_add_i64(CPU_V001); break;
6180 default: abort();
6182 if (op >= NEON_2RM_VPADAL) {
6183 /* Accumulate. */
6184 neon_load_reg64(cpu_V1, rd + pass);
6185 gen_neon_addl(size);
6187 neon_store_reg64(cpu_V0, rd + pass);
6189 break;
6190 case NEON_2RM_VTRN:
6191 if (size == 2) {
6192 int n;
6193 for (n = 0; n < (q ? 4 : 2); n += 2) {
6194 tmp = neon_load_reg(rm, n);
6195 tmp2 = neon_load_reg(rd, n + 1);
6196 neon_store_reg(rm, n, tmp2);
6197 neon_store_reg(rd, n + 1, tmp);
6199 } else {
6200 goto elementwise;
6202 break;
6203 case NEON_2RM_VUZP:
6204 if (gen_neon_unzip(rd, rm, size, q)) {
6205 return 1;
6207 break;
6208 case NEON_2RM_VZIP:
6209 if (gen_neon_zip(rd, rm, size, q)) {
6210 return 1;
6212 break;
6213 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
6214 /* also VQMOVUN; op field and mnemonics don't line up */
6215 if (rm & 1) {
6216 return 1;
6218 tmp2 = NULL;
6219 for (pass = 0; pass < 2; pass++) {
6220 neon_load_reg64(cpu_V0, rm + pass);
6221 tmp = tcg_temp_new_i32();
6222 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
6223 tmp, cpu_V0);
6224 if (pass == 0) {
6225 tmp2 = tmp;
6226 } else {
6227 neon_store_reg(rd, 0, tmp2);
6228 neon_store_reg(rd, 1, tmp);
6231 break;
6232 case NEON_2RM_VSHLL:
6233 if (q || (rd & 1)) {
6234 return 1;
6236 tmp = neon_load_reg(rm, 0);
6237 tmp2 = neon_load_reg(rm, 1);
6238 for (pass = 0; pass < 2; pass++) {
6239 if (pass == 1)
6240 tmp = tmp2;
6241 gen_neon_widen(cpu_V0, tmp, size, 1);
6242 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
6243 neon_store_reg64(cpu_V0, rd + pass);
6245 break;
6246 case NEON_2RM_VCVT_F16_F32:
6248 TCGv_ptr fpst;
6249 TCGv_i32 ahp;
6251 if (!dc_isar_feature(aa32_fp16_spconv, s) ||
6252 q || (rm & 1)) {
6253 return 1;
6255 fpst = get_fpstatus_ptr(true);
6256 ahp = get_ahp_flag();
6257 tmp = neon_load_reg(rm, 0);
6258 gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp);
6259 tmp2 = neon_load_reg(rm, 1);
6260 gen_helper_vfp_fcvt_f32_to_f16(tmp2, tmp2, fpst, ahp);
6261 tcg_gen_shli_i32(tmp2, tmp2, 16);
6262 tcg_gen_or_i32(tmp2, tmp2, tmp);
6263 tcg_temp_free_i32(tmp);
6264 tmp = neon_load_reg(rm, 2);
6265 gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp);
6266 tmp3 = neon_load_reg(rm, 3);
6267 neon_store_reg(rd, 0, tmp2);
6268 gen_helper_vfp_fcvt_f32_to_f16(tmp3, tmp3, fpst, ahp);
6269 tcg_gen_shli_i32(tmp3, tmp3, 16);
6270 tcg_gen_or_i32(tmp3, tmp3, tmp);
6271 neon_store_reg(rd, 1, tmp3);
6272 tcg_temp_free_i32(tmp);
6273 tcg_temp_free_i32(ahp);
6274 tcg_temp_free_ptr(fpst);
6275 break;
6277 case NEON_2RM_VCVT_F32_F16:
6279 TCGv_ptr fpst;
6280 TCGv_i32 ahp;
6281 if (!dc_isar_feature(aa32_fp16_spconv, s) ||
6282 q || (rd & 1)) {
6283 return 1;
6285 fpst = get_fpstatus_ptr(true);
6286 ahp = get_ahp_flag();
6287 tmp3 = tcg_temp_new_i32();
6288 tmp = neon_load_reg(rm, 0);
6289 tmp2 = neon_load_reg(rm, 1);
6290 tcg_gen_ext16u_i32(tmp3, tmp);
6291 gen_helper_vfp_fcvt_f16_to_f32(tmp3, tmp3, fpst, ahp);
6292 neon_store_reg(rd, 0, tmp3);
6293 tcg_gen_shri_i32(tmp, tmp, 16);
6294 gen_helper_vfp_fcvt_f16_to_f32(tmp, tmp, fpst, ahp);
6295 neon_store_reg(rd, 1, tmp);
6296 tmp3 = tcg_temp_new_i32();
6297 tcg_gen_ext16u_i32(tmp3, tmp2);
6298 gen_helper_vfp_fcvt_f16_to_f32(tmp3, tmp3, fpst, ahp);
6299 neon_store_reg(rd, 2, tmp3);
6300 tcg_gen_shri_i32(tmp2, tmp2, 16);
6301 gen_helper_vfp_fcvt_f16_to_f32(tmp2, tmp2, fpst, ahp);
6302 neon_store_reg(rd, 3, tmp2);
6303 tcg_temp_free_i32(ahp);
6304 tcg_temp_free_ptr(fpst);
6305 break;
6307 case NEON_2RM_AESE: case NEON_2RM_AESMC:
6308 if (!dc_isar_feature(aa32_aes, s) || ((rm | rd) & 1)) {
6309 return 1;
6311 ptr1 = vfp_reg_ptr(true, rd);
6312 ptr2 = vfp_reg_ptr(true, rm);
6314 /* Bit 6 is the lowest opcode bit; it distinguishes between
6315 * encryption (AESE/AESMC) and decryption (AESD/AESIMC)
6317 tmp3 = tcg_const_i32(extract32(insn, 6, 1));
6319 if (op == NEON_2RM_AESE) {
6320 gen_helper_crypto_aese(ptr1, ptr2, tmp3);
6321 } else {
6322 gen_helper_crypto_aesmc(ptr1, ptr2, tmp3);
6324 tcg_temp_free_ptr(ptr1);
6325 tcg_temp_free_ptr(ptr2);
6326 tcg_temp_free_i32(tmp3);
6327 break;
6328 case NEON_2RM_SHA1H:
6329 if (!dc_isar_feature(aa32_sha1, s) || ((rm | rd) & 1)) {
6330 return 1;
6332 ptr1 = vfp_reg_ptr(true, rd);
6333 ptr2 = vfp_reg_ptr(true, rm);
6335 gen_helper_crypto_sha1h(ptr1, ptr2);
6337 tcg_temp_free_ptr(ptr1);
6338 tcg_temp_free_ptr(ptr2);
6339 break;
6340 case NEON_2RM_SHA1SU1:
6341 if ((rm | rd) & 1) {
6342 return 1;
6344 /* bit 6 (q): set -> SHA256SU0, cleared -> SHA1SU1 */
6345 if (q) {
6346 if (!dc_isar_feature(aa32_sha2, s)) {
6347 return 1;
6349 } else if (!dc_isar_feature(aa32_sha1, s)) {
6350 return 1;
6352 ptr1 = vfp_reg_ptr(true, rd);
6353 ptr2 = vfp_reg_ptr(true, rm);
6354 if (q) {
6355 gen_helper_crypto_sha256su0(ptr1, ptr2);
6356 } else {
6357 gen_helper_crypto_sha1su1(ptr1, ptr2);
6359 tcg_temp_free_ptr(ptr1);
6360 tcg_temp_free_ptr(ptr2);
6361 break;
6363 case NEON_2RM_VMVN:
6364 tcg_gen_gvec_not(0, rd_ofs, rm_ofs, vec_size, vec_size);
6365 break;
6366 case NEON_2RM_VNEG:
6367 tcg_gen_gvec_neg(size, rd_ofs, rm_ofs, vec_size, vec_size);
6368 break;
6369 case NEON_2RM_VABS:
6370 tcg_gen_gvec_abs(size, rd_ofs, rm_ofs, vec_size, vec_size);
6371 break;
6373 case NEON_2RM_VCEQ0:
6374 tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
6375 vec_size, &ceq0_op[size]);
6376 break;
6377 case NEON_2RM_VCGT0:
6378 tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
6379 vec_size, &cgt0_op[size]);
6380 break;
6381 case NEON_2RM_VCLE0:
6382 tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
6383 vec_size, &cle0_op[size]);
6384 break;
6385 case NEON_2RM_VCGE0:
6386 tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
6387 vec_size, &cge0_op[size]);
6388 break;
6389 case NEON_2RM_VCLT0:
6390 tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
6391 vec_size, &clt0_op[size]);
6392 break;
6394 default:
6395 elementwise:
6396 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6397 tmp = neon_load_reg(rm, pass);
6398 switch (op) {
6399 case NEON_2RM_VREV32:
6400 switch (size) {
6401 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6402 case 1: gen_swap_half(tmp); break;
6403 default: abort();
6405 break;
6406 case NEON_2RM_VREV16:
6407 gen_rev16(tmp, tmp);
6408 break;
6409 case NEON_2RM_VCLS:
6410 switch (size) {
6411 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
6412 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
6413 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
6414 default: abort();
6416 break;
6417 case NEON_2RM_VCLZ:
6418 switch (size) {
6419 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
6420 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
6421 case 2: tcg_gen_clzi_i32(tmp, tmp, 32); break;
6422 default: abort();
6424 break;
6425 case NEON_2RM_VCNT:
6426 gen_helper_neon_cnt_u8(tmp, tmp);
6427 break;
6428 case NEON_2RM_VQABS:
6429 switch (size) {
6430 case 0:
6431 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
6432 break;
6433 case 1:
6434 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
6435 break;
6436 case 2:
6437 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
6438 break;
6439 default: abort();
6441 break;
6442 case NEON_2RM_VQNEG:
6443 switch (size) {
6444 case 0:
6445 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
6446 break;
6447 case 1:
6448 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
6449 break;
6450 case 2:
6451 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
6452 break;
6453 default: abort();
6455 break;
6456 case NEON_2RM_VCGT0_F:
6458 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6459 tmp2 = tcg_const_i32(0);
6460 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
6461 tcg_temp_free_i32(tmp2);
6462 tcg_temp_free_ptr(fpstatus);
6463 break;
6465 case NEON_2RM_VCGE0_F:
6467 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6468 tmp2 = tcg_const_i32(0);
6469 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
6470 tcg_temp_free_i32(tmp2);
6471 tcg_temp_free_ptr(fpstatus);
6472 break;
6474 case NEON_2RM_VCEQ0_F:
6476 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6477 tmp2 = tcg_const_i32(0);
6478 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
6479 tcg_temp_free_i32(tmp2);
6480 tcg_temp_free_ptr(fpstatus);
6481 break;
6483 case NEON_2RM_VCLE0_F:
6485 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6486 tmp2 = tcg_const_i32(0);
6487 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
6488 tcg_temp_free_i32(tmp2);
6489 tcg_temp_free_ptr(fpstatus);
6490 break;
6492 case NEON_2RM_VCLT0_F:
6494 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6495 tmp2 = tcg_const_i32(0);
6496 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
6497 tcg_temp_free_i32(tmp2);
6498 tcg_temp_free_ptr(fpstatus);
6499 break;
6501 case NEON_2RM_VABS_F:
6502 gen_helper_vfp_abss(tmp, tmp);
6503 break;
6504 case NEON_2RM_VNEG_F:
6505 gen_helper_vfp_negs(tmp, tmp);
6506 break;
6507 case NEON_2RM_VSWP:
6508 tmp2 = neon_load_reg(rd, pass);
6509 neon_store_reg(rm, pass, tmp2);
6510 break;
6511 case NEON_2RM_VTRN:
6512 tmp2 = neon_load_reg(rd, pass);
6513 switch (size) {
6514 case 0: gen_neon_trn_u8(tmp, tmp2); break;
6515 case 1: gen_neon_trn_u16(tmp, tmp2); break;
6516 default: abort();
6518 neon_store_reg(rm, pass, tmp2);
6519 break;
6520 case NEON_2RM_VRINTN:
6521 case NEON_2RM_VRINTA:
6522 case NEON_2RM_VRINTM:
6523 case NEON_2RM_VRINTP:
6524 case NEON_2RM_VRINTZ:
6526 TCGv_i32 tcg_rmode;
6527 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6528 int rmode;
6530 if (op == NEON_2RM_VRINTZ) {
6531 rmode = FPROUNDING_ZERO;
6532 } else {
6533 rmode = fp_decode_rm[((op & 0x6) >> 1) ^ 1];
6536 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
6537 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6538 cpu_env);
6539 gen_helper_rints(tmp, tmp, fpstatus);
6540 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6541 cpu_env);
6542 tcg_temp_free_ptr(fpstatus);
6543 tcg_temp_free_i32(tcg_rmode);
6544 break;
6546 case NEON_2RM_VRINTX:
6548 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6549 gen_helper_rints_exact(tmp, tmp, fpstatus);
6550 tcg_temp_free_ptr(fpstatus);
6551 break;
6553 case NEON_2RM_VCVTAU:
6554 case NEON_2RM_VCVTAS:
6555 case NEON_2RM_VCVTNU:
6556 case NEON_2RM_VCVTNS:
6557 case NEON_2RM_VCVTPU:
6558 case NEON_2RM_VCVTPS:
6559 case NEON_2RM_VCVTMU:
6560 case NEON_2RM_VCVTMS:
6562 bool is_signed = !extract32(insn, 7, 1);
6563 TCGv_ptr fpst = get_fpstatus_ptr(1);
6564 TCGv_i32 tcg_rmode, tcg_shift;
6565 int rmode = fp_decode_rm[extract32(insn, 8, 2)];
6567 tcg_shift = tcg_const_i32(0);
6568 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
6569 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6570 cpu_env);
6572 if (is_signed) {
6573 gen_helper_vfp_tosls(tmp, tmp,
6574 tcg_shift, fpst);
6575 } else {
6576 gen_helper_vfp_touls(tmp, tmp,
6577 tcg_shift, fpst);
6580 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6581 cpu_env);
6582 tcg_temp_free_i32(tcg_rmode);
6583 tcg_temp_free_i32(tcg_shift);
6584 tcg_temp_free_ptr(fpst);
6585 break;
6587 case NEON_2RM_VRECPE:
6589 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6590 gen_helper_recpe_u32(tmp, tmp, fpstatus);
6591 tcg_temp_free_ptr(fpstatus);
6592 break;
6594 case NEON_2RM_VRSQRTE:
6596 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6597 gen_helper_rsqrte_u32(tmp, tmp, fpstatus);
6598 tcg_temp_free_ptr(fpstatus);
6599 break;
6601 case NEON_2RM_VRECPE_F:
6603 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6604 gen_helper_recpe_f32(tmp, tmp, fpstatus);
6605 tcg_temp_free_ptr(fpstatus);
6606 break;
6608 case NEON_2RM_VRSQRTE_F:
6610 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6611 gen_helper_rsqrte_f32(tmp, tmp, fpstatus);
6612 tcg_temp_free_ptr(fpstatus);
6613 break;
6615 case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
6617 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6618 gen_helper_vfp_sitos(tmp, tmp, fpstatus);
6619 tcg_temp_free_ptr(fpstatus);
6620 break;
6622 case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
6624 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6625 gen_helper_vfp_uitos(tmp, tmp, fpstatus);
6626 tcg_temp_free_ptr(fpstatus);
6627 break;
6629 case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
6631 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6632 gen_helper_vfp_tosizs(tmp, tmp, fpstatus);
6633 tcg_temp_free_ptr(fpstatus);
6634 break;
6636 case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
6638 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6639 gen_helper_vfp_touizs(tmp, tmp, fpstatus);
6640 tcg_temp_free_ptr(fpstatus);
6641 break;
6643 default:
6644 /* Reserved op values were caught by the
6645 * neon_2rm_sizes[] check earlier.
6647 abort();
6649 neon_store_reg(rd, pass, tmp);
6651 break;
6653 } else if ((insn & (1 << 10)) == 0) {
6654 /* VTBL, VTBX. */
6655 int n = ((insn >> 8) & 3) + 1;
6656 if ((rn + n) > 32) {
6657 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
6658 * helper function running off the end of the register file.
6660 return 1;
6662 n <<= 3;
6663 if (insn & (1 << 6)) {
6664 tmp = neon_load_reg(rd, 0);
6665 } else {
6666 tmp = tcg_temp_new_i32();
6667 tcg_gen_movi_i32(tmp, 0);
6669 tmp2 = neon_load_reg(rm, 0);
6670 ptr1 = vfp_reg_ptr(true, rn);
6671 tmp5 = tcg_const_i32(n);
6672 gen_helper_neon_tbl(tmp2, tmp2, tmp, ptr1, tmp5);
6673 tcg_temp_free_i32(tmp);
6674 if (insn & (1 << 6)) {
6675 tmp = neon_load_reg(rd, 1);
6676 } else {
6677 tmp = tcg_temp_new_i32();
6678 tcg_gen_movi_i32(tmp, 0);
6680 tmp3 = neon_load_reg(rm, 1);
6681 gen_helper_neon_tbl(tmp3, tmp3, tmp, ptr1, tmp5);
6682 tcg_temp_free_i32(tmp5);
6683 tcg_temp_free_ptr(ptr1);
6684 neon_store_reg(rd, 0, tmp2);
6685 neon_store_reg(rd, 1, tmp3);
6686 tcg_temp_free_i32(tmp);
6687 } else if ((insn & 0x380) == 0) {
6688 /* VDUP */
6689 int element;
6690 MemOp size;
6692 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
6693 return 1;
6695 if (insn & (1 << 16)) {
6696 size = MO_8;
6697 element = (insn >> 17) & 7;
6698 } else if (insn & (1 << 17)) {
6699 size = MO_16;
6700 element = (insn >> 18) & 3;
6701 } else {
6702 size = MO_32;
6703 element = (insn >> 19) & 1;
6705 tcg_gen_gvec_dup_mem(size, neon_reg_offset(rd, 0),
6706 neon_element_offset(rm, element, size),
6707 q ? 16 : 8, q ? 16 : 8);
6708 } else {
6709 return 1;
6713 return 0;
6716 static int disas_coproc_insn(DisasContext *s, uint32_t insn)
6718 int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
6719 const ARMCPRegInfo *ri;
6721 cpnum = (insn >> 8) & 0xf;
6723 /* First check for coprocessor space used for XScale/iwMMXt insns */
6724 if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cpnum < 2)) {
6725 if (extract32(s->c15_cpar, cpnum, 1) == 0) {
6726 return 1;
6728 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
6729 return disas_iwmmxt_insn(s, insn);
6730 } else if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
6731 return disas_dsp_insn(s, insn);
6733 return 1;
6736 /* Otherwise treat as a generic register access */
6737 is64 = (insn & (1 << 25)) == 0;
6738 if (!is64 && ((insn & (1 << 4)) == 0)) {
6739 /* cdp */
6740 return 1;
6743 crm = insn & 0xf;
6744 if (is64) {
6745 crn = 0;
6746 opc1 = (insn >> 4) & 0xf;
6747 opc2 = 0;
6748 rt2 = (insn >> 16) & 0xf;
6749 } else {
6750 crn = (insn >> 16) & 0xf;
6751 opc1 = (insn >> 21) & 7;
6752 opc2 = (insn >> 5) & 7;
6753 rt2 = 0;
6755 isread = (insn >> 20) & 1;
6756 rt = (insn >> 12) & 0xf;
6758 ri = get_arm_cp_reginfo(s->cp_regs,
6759 ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
6760 if (ri) {
6761 bool need_exit_tb;
6763 /* Check access permissions */
6764 if (!cp_access_ok(s->current_el, ri, isread)) {
6765 return 1;
6768 if (s->hstr_active || ri->accessfn ||
6769 (arm_dc_feature(s, ARM_FEATURE_XSCALE) && cpnum < 14)) {
6770 /* Emit code to perform further access permissions checks at
6771 * runtime; this may result in an exception.
6772 * Note that on XScale all cp0..c13 registers do an access check
6773 * call in order to handle c15_cpar.
6775 TCGv_ptr tmpptr;
6776 TCGv_i32 tcg_syn, tcg_isread;
6777 uint32_t syndrome;
6779 /* Note that since we are an implementation which takes an
6780 * exception on a trapped conditional instruction only if the
6781 * instruction passes its condition code check, we can take
6782 * advantage of the clause in the ARM ARM that allows us to set
6783 * the COND field in the instruction to 0xE in all cases.
6784 * We could fish the actual condition out of the insn (ARM)
6785 * or the condexec bits (Thumb) but it isn't necessary.
6787 switch (cpnum) {
6788 case 14:
6789 if (is64) {
6790 syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
6791 isread, false);
6792 } else {
6793 syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
6794 rt, isread, false);
6796 break;
6797 case 15:
6798 if (is64) {
6799 syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
6800 isread, false);
6801 } else {
6802 syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
6803 rt, isread, false);
6805 break;
6806 default:
6807 /* ARMv8 defines that only coprocessors 14 and 15 exist,
6808 * so this can only happen if this is an ARMv7 or earlier CPU,
6809 * in which case the syndrome information won't actually be
6810 * guest visible.
6812 assert(!arm_dc_feature(s, ARM_FEATURE_V8));
6813 syndrome = syn_uncategorized();
6814 break;
6817 gen_set_condexec(s);
6818 gen_set_pc_im(s, s->pc_curr);
6819 tmpptr = tcg_const_ptr(ri);
6820 tcg_syn = tcg_const_i32(syndrome);
6821 tcg_isread = tcg_const_i32(isread);
6822 gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn,
6823 tcg_isread);
6824 tcg_temp_free_ptr(tmpptr);
6825 tcg_temp_free_i32(tcg_syn);
6826 tcg_temp_free_i32(tcg_isread);
6827 } else if (ri->type & ARM_CP_RAISES_EXC) {
6829 * The readfn or writefn might raise an exception;
6830 * synchronize the CPU state in case it does.
6832 gen_set_condexec(s);
6833 gen_set_pc_im(s, s->pc_curr);
6836 /* Handle special cases first */
6837 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
6838 case ARM_CP_NOP:
6839 return 0;
6840 case ARM_CP_WFI:
6841 if (isread) {
6842 return 1;
6844 gen_set_pc_im(s, s->base.pc_next);
6845 s->base.is_jmp = DISAS_WFI;
6846 return 0;
6847 default:
6848 break;
6851 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
6852 gen_io_start();
6855 if (isread) {
6856 /* Read */
6857 if (is64) {
6858 TCGv_i64 tmp64;
6859 TCGv_i32 tmp;
6860 if (ri->type & ARM_CP_CONST) {
6861 tmp64 = tcg_const_i64(ri->resetvalue);
6862 } else if (ri->readfn) {
6863 TCGv_ptr tmpptr;
6864 tmp64 = tcg_temp_new_i64();
6865 tmpptr = tcg_const_ptr(ri);
6866 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
6867 tcg_temp_free_ptr(tmpptr);
6868 } else {
6869 tmp64 = tcg_temp_new_i64();
6870 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
6872 tmp = tcg_temp_new_i32();
6873 tcg_gen_extrl_i64_i32(tmp, tmp64);
6874 store_reg(s, rt, tmp);
6875 tmp = tcg_temp_new_i32();
6876 tcg_gen_extrh_i64_i32(tmp, tmp64);
6877 tcg_temp_free_i64(tmp64);
6878 store_reg(s, rt2, tmp);
6879 } else {
6880 TCGv_i32 tmp;
6881 if (ri->type & ARM_CP_CONST) {
6882 tmp = tcg_const_i32(ri->resetvalue);
6883 } else if (ri->readfn) {
6884 TCGv_ptr tmpptr;
6885 tmp = tcg_temp_new_i32();
6886 tmpptr = tcg_const_ptr(ri);
6887 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
6888 tcg_temp_free_ptr(tmpptr);
6889 } else {
6890 tmp = load_cpu_offset(ri->fieldoffset);
6892 if (rt == 15) {
6893 /* Destination register of r15 for 32 bit loads sets
6894 * the condition codes from the high 4 bits of the value
6896 gen_set_nzcv(tmp);
6897 tcg_temp_free_i32(tmp);
6898 } else {
6899 store_reg(s, rt, tmp);
6902 } else {
6903 /* Write */
6904 if (ri->type & ARM_CP_CONST) {
6905 /* If not forbidden by access permissions, treat as WI */
6906 return 0;
6909 if (is64) {
6910 TCGv_i32 tmplo, tmphi;
6911 TCGv_i64 tmp64 = tcg_temp_new_i64();
6912 tmplo = load_reg(s, rt);
6913 tmphi = load_reg(s, rt2);
6914 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
6915 tcg_temp_free_i32(tmplo);
6916 tcg_temp_free_i32(tmphi);
6917 if (ri->writefn) {
6918 TCGv_ptr tmpptr = tcg_const_ptr(ri);
6919 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
6920 tcg_temp_free_ptr(tmpptr);
6921 } else {
6922 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
6924 tcg_temp_free_i64(tmp64);
6925 } else {
6926 if (ri->writefn) {
6927 TCGv_i32 tmp;
6928 TCGv_ptr tmpptr;
6929 tmp = load_reg(s, rt);
6930 tmpptr = tcg_const_ptr(ri);
6931 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
6932 tcg_temp_free_ptr(tmpptr);
6933 tcg_temp_free_i32(tmp);
6934 } else {
6935 TCGv_i32 tmp = load_reg(s, rt);
6936 store_cpu_offset(tmp, ri->fieldoffset);
6941 /* I/O operations must end the TB here (whether read or write) */
6942 need_exit_tb = ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) &&
6943 (ri->type & ARM_CP_IO));
6945 if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
6947 * A write to any coprocessor register that ends a TB
6948 * must rebuild the hflags for the next TB.
6950 TCGv_i32 tcg_el = tcg_const_i32(s->current_el);
6951 if (arm_dc_feature(s, ARM_FEATURE_M)) {
6952 gen_helper_rebuild_hflags_m32(cpu_env, tcg_el);
6953 } else {
6954 if (ri->type & ARM_CP_NEWEL) {
6955 gen_helper_rebuild_hflags_a32_newel(cpu_env);
6956 } else {
6957 gen_helper_rebuild_hflags_a32(cpu_env, tcg_el);
6960 tcg_temp_free_i32(tcg_el);
6962 * We default to ending the TB on a coprocessor register write,
6963 * but allow this to be suppressed by the register definition
6964 * (usually only necessary to work around guest bugs).
6966 need_exit_tb = true;
6968 if (need_exit_tb) {
6969 gen_lookup_tb(s);
6972 return 0;
6975 /* Unknown register; this might be a guest error or a QEMU
6976 * unimplemented feature.
6978 if (is64) {
6979 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
6980 "64 bit system register cp:%d opc1: %d crm:%d "
6981 "(%s)\n",
6982 isread ? "read" : "write", cpnum, opc1, crm,
6983 s->ns ? "non-secure" : "secure");
6984 } else {
6985 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
6986 "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d "
6987 "(%s)\n",
6988 isread ? "read" : "write", cpnum, opc1, crn, crm, opc2,
6989 s->ns ? "non-secure" : "secure");
6992 return 1;
6996 /* Store a 64-bit value to a register pair. Clobbers val. */
6997 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
6999 TCGv_i32 tmp;
7000 tmp = tcg_temp_new_i32();
7001 tcg_gen_extrl_i64_i32(tmp, val);
7002 store_reg(s, rlow, tmp);
7003 tmp = tcg_temp_new_i32();
7004 tcg_gen_extrh_i64_i32(tmp, val);
7005 store_reg(s, rhigh, tmp);
7008 /* load and add a 64-bit value from a register pair. */
7009 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
7011 TCGv_i64 tmp;
7012 TCGv_i32 tmpl;
7013 TCGv_i32 tmph;
7015 /* Load 64-bit value rd:rn. */
7016 tmpl = load_reg(s, rlow);
7017 tmph = load_reg(s, rhigh);
7018 tmp = tcg_temp_new_i64();
7019 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
7020 tcg_temp_free_i32(tmpl);
7021 tcg_temp_free_i32(tmph);
7022 tcg_gen_add_i64(val, val, tmp);
7023 tcg_temp_free_i64(tmp);
7026 /* Set N and Z flags from hi|lo. */
7027 static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
7029 tcg_gen_mov_i32(cpu_NF, hi);
7030 tcg_gen_or_i32(cpu_ZF, lo, hi);
7033 /* Load/Store exclusive instructions are implemented by remembering
7034 the value/address loaded, and seeing if these are the same
7035 when the store is performed. This should be sufficient to implement
7036 the architecturally mandated semantics, and avoids having to monitor
7037 regular stores. The compare vs the remembered value is done during
7038 the cmpxchg operation, but we must compare the addresses manually. */
7039 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
7040 TCGv_i32 addr, int size)
7042 TCGv_i32 tmp = tcg_temp_new_i32();
7043 MemOp opc = size | MO_ALIGN | s->be_data;
7045 s->is_ldex = true;
7047 if (size == 3) {
7048 TCGv_i32 tmp2 = tcg_temp_new_i32();
7049 TCGv_i64 t64 = tcg_temp_new_i64();
7051 /* For AArch32, architecturally the 32-bit word at the lowest
7052 * address is always Rt and the one at addr+4 is Rt2, even if
7053 * the CPU is big-endian. That means we don't want to do a
7054 * gen_aa32_ld_i64(), which invokes gen_aa32_frob64() as if
7055 * for an architecturally 64-bit access, but instead do a
7056 * 64-bit access using MO_BE if appropriate and then split
7057 * the two halves.
7058 * This only makes a difference for BE32 user-mode, where
7059 * frob64() must not flip the two halves of the 64-bit data
7060 * but this code must treat BE32 user-mode like BE32 system.
7062 TCGv taddr = gen_aa32_addr(s, addr, opc);
7064 tcg_gen_qemu_ld_i64(t64, taddr, get_mem_index(s), opc);
7065 tcg_temp_free(taddr);
7066 tcg_gen_mov_i64(cpu_exclusive_val, t64);
7067 if (s->be_data == MO_BE) {
7068 tcg_gen_extr_i64_i32(tmp2, tmp, t64);
7069 } else {
7070 tcg_gen_extr_i64_i32(tmp, tmp2, t64);
7072 tcg_temp_free_i64(t64);
7074 store_reg(s, rt2, tmp2);
7075 } else {
7076 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), opc);
7077 tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
7080 store_reg(s, rt, tmp);
7081 tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
7084 static void gen_clrex(DisasContext *s)
7086 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
7089 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
7090 TCGv_i32 addr, int size)
7092 TCGv_i32 t0, t1, t2;
7093 TCGv_i64 extaddr;
7094 TCGv taddr;
7095 TCGLabel *done_label;
7096 TCGLabel *fail_label;
7097 MemOp opc = size | MO_ALIGN | s->be_data;
7099 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
7100 [addr] = {Rt};
7101 {Rd} = 0;
7102 } else {
7103 {Rd} = 1;
7104 } */
7105 fail_label = gen_new_label();
7106 done_label = gen_new_label();
7107 extaddr = tcg_temp_new_i64();
7108 tcg_gen_extu_i32_i64(extaddr, addr);
7109 tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
7110 tcg_temp_free_i64(extaddr);
7112 taddr = gen_aa32_addr(s, addr, opc);
7113 t0 = tcg_temp_new_i32();
7114 t1 = load_reg(s, rt);
7115 if (size == 3) {
7116 TCGv_i64 o64 = tcg_temp_new_i64();
7117 TCGv_i64 n64 = tcg_temp_new_i64();
7119 t2 = load_reg(s, rt2);
7120 /* For AArch32, architecturally the 32-bit word at the lowest
7121 * address is always Rt and the one at addr+4 is Rt2, even if
7122 * the CPU is big-endian. Since we're going to treat this as a
7123 * single 64-bit BE store, we need to put the two halves in the
7124 * opposite order for BE to LE, so that they end up in the right
7125 * places.
7126 * We don't want gen_aa32_frob64() because that does the wrong
7127 * thing for BE32 usermode.
7129 if (s->be_data == MO_BE) {
7130 tcg_gen_concat_i32_i64(n64, t2, t1);
7131 } else {
7132 tcg_gen_concat_i32_i64(n64, t1, t2);
7134 tcg_temp_free_i32(t2);
7136 tcg_gen_atomic_cmpxchg_i64(o64, taddr, cpu_exclusive_val, n64,
7137 get_mem_index(s), opc);
7138 tcg_temp_free_i64(n64);
7140 tcg_gen_setcond_i64(TCG_COND_NE, o64, o64, cpu_exclusive_val);
7141 tcg_gen_extrl_i64_i32(t0, o64);
7143 tcg_temp_free_i64(o64);
7144 } else {
7145 t2 = tcg_temp_new_i32();
7146 tcg_gen_extrl_i64_i32(t2, cpu_exclusive_val);
7147 tcg_gen_atomic_cmpxchg_i32(t0, taddr, t2, t1, get_mem_index(s), opc);
7148 tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t2);
7149 tcg_temp_free_i32(t2);
7151 tcg_temp_free_i32(t1);
7152 tcg_temp_free(taddr);
7153 tcg_gen_mov_i32(cpu_R[rd], t0);
7154 tcg_temp_free_i32(t0);
7155 tcg_gen_br(done_label);
7157 gen_set_label(fail_label);
7158 tcg_gen_movi_i32(cpu_R[rd], 1);
7159 gen_set_label(done_label);
7160 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
7163 /* gen_srs:
7164 * @env: CPUARMState
7165 * @s: DisasContext
7166 * @mode: mode field from insn (which stack to store to)
7167 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
7168 * @writeback: true if writeback bit set
7170 * Generate code for the SRS (Store Return State) insn.
7172 static void gen_srs(DisasContext *s,
7173 uint32_t mode, uint32_t amode, bool writeback)
7175 int32_t offset;
7176 TCGv_i32 addr, tmp;
7177 bool undef = false;
7179 /* SRS is:
7180 * - trapped to EL3 if EL3 is AArch64 and we are at Secure EL1
7181 * and specified mode is monitor mode
7182 * - UNDEFINED in Hyp mode
7183 * - UNPREDICTABLE in User or System mode
7184 * - UNPREDICTABLE if the specified mode is:
7185 * -- not implemented
7186 * -- not a valid mode number
7187 * -- a mode that's at a higher exception level
7188 * -- Monitor, if we are Non-secure
7189 * For the UNPREDICTABLE cases we choose to UNDEF.
7191 if (s->current_el == 1 && !s->ns && mode == ARM_CPU_MODE_MON) {
7192 gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(), 3);
7193 return;
7196 if (s->current_el == 0 || s->current_el == 2) {
7197 undef = true;
7200 switch (mode) {
7201 case ARM_CPU_MODE_USR:
7202 case ARM_CPU_MODE_FIQ:
7203 case ARM_CPU_MODE_IRQ:
7204 case ARM_CPU_MODE_SVC:
7205 case ARM_CPU_MODE_ABT:
7206 case ARM_CPU_MODE_UND:
7207 case ARM_CPU_MODE_SYS:
7208 break;
7209 case ARM_CPU_MODE_HYP:
7210 if (s->current_el == 1 || !arm_dc_feature(s, ARM_FEATURE_EL2)) {
7211 undef = true;
7213 break;
7214 case ARM_CPU_MODE_MON:
7215 /* No need to check specifically for "are we non-secure" because
7216 * we've already made EL0 UNDEF and handled the trap for S-EL1;
7217 * so if this isn't EL3 then we must be non-secure.
7219 if (s->current_el != 3) {
7220 undef = true;
7222 break;
7223 default:
7224 undef = true;
7227 if (undef) {
7228 unallocated_encoding(s);
7229 return;
7232 addr = tcg_temp_new_i32();
7233 tmp = tcg_const_i32(mode);
7234 /* get_r13_banked() will raise an exception if called from System mode */
7235 gen_set_condexec(s);
7236 gen_set_pc_im(s, s->pc_curr);
7237 gen_helper_get_r13_banked(addr, cpu_env, tmp);
7238 tcg_temp_free_i32(tmp);
7239 switch (amode) {
7240 case 0: /* DA */
7241 offset = -4;
7242 break;
7243 case 1: /* IA */
7244 offset = 0;
7245 break;
7246 case 2: /* DB */
7247 offset = -8;
7248 break;
7249 case 3: /* IB */
7250 offset = 4;
7251 break;
7252 default:
7253 abort();
7255 tcg_gen_addi_i32(addr, addr, offset);
7256 tmp = load_reg(s, 14);
7257 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
7258 tcg_temp_free_i32(tmp);
7259 tmp = load_cpu_field(spsr);
7260 tcg_gen_addi_i32(addr, addr, 4);
7261 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
7262 tcg_temp_free_i32(tmp);
7263 if (writeback) {
7264 switch (amode) {
7265 case 0:
7266 offset = -8;
7267 break;
7268 case 1:
7269 offset = 4;
7270 break;
7271 case 2:
7272 offset = -4;
7273 break;
7274 case 3:
7275 offset = 0;
7276 break;
7277 default:
7278 abort();
7280 tcg_gen_addi_i32(addr, addr, offset);
7281 tmp = tcg_const_i32(mode);
7282 gen_helper_set_r13_banked(cpu_env, tmp, addr);
7283 tcg_temp_free_i32(tmp);
7285 tcg_temp_free_i32(addr);
7286 s->base.is_jmp = DISAS_UPDATE;
7289 /* Generate a label used for skipping this instruction */
7290 static void arm_gen_condlabel(DisasContext *s)
7292 if (!s->condjmp) {
7293 s->condlabel = gen_new_label();
7294 s->condjmp = 1;
7298 /* Skip this instruction if the ARM condition is false */
7299 static void arm_skip_unless(DisasContext *s, uint32_t cond)
7301 arm_gen_condlabel(s);
7302 arm_gen_test_cc(cond ^ 1, s->condlabel);
7307 * Constant expanders for the decoders.
7310 static int negate(DisasContext *s, int x)
7312 return -x;
7315 static int plus_2(DisasContext *s, int x)
7317 return x + 2;
7320 static int times_2(DisasContext *s, int x)
7322 return x * 2;
7325 static int times_4(DisasContext *s, int x)
7327 return x * 4;
7330 /* Return only the rotation part of T32ExpandImm. */
7331 static int t32_expandimm_rot(DisasContext *s, int x)
7333 return x & 0xc00 ? extract32(x, 7, 5) : 0;
7336 /* Return the unrotated immediate from T32ExpandImm. */
7337 static int t32_expandimm_imm(DisasContext *s, int x)
7339 int imm = extract32(x, 0, 8);
7341 switch (extract32(x, 8, 4)) {
7342 case 0: /* XY */
7343 /* Nothing to do. */
7344 break;
7345 case 1: /* 00XY00XY */
7346 imm *= 0x00010001;
7347 break;
7348 case 2: /* XY00XY00 */
7349 imm *= 0x01000100;
7350 break;
7351 case 3: /* XYXYXYXY */
7352 imm *= 0x01010101;
7353 break;
7354 default:
7355 /* Rotated constant. */
7356 imm |= 0x80;
7357 break;
7359 return imm;
7362 static int t32_branch24(DisasContext *s, int x)
7364 /* Convert J1:J2 at x[22:21] to I2:I1, which involves I=J^~S. */
7365 x ^= !(x < 0) * (3 << 21);
7366 /* Append the final zero. */
7367 return x << 1;
7370 static int t16_setflags(DisasContext *s)
7372 return s->condexec_mask == 0;
7375 static int t16_push_list(DisasContext *s, int x)
7377 return (x & 0xff) | (x & 0x100) << (14 - 8);
7380 static int t16_pop_list(DisasContext *s, int x)
7382 return (x & 0xff) | (x & 0x100) << (15 - 8);
7386 * Include the generated decoders.
7389 #include "decode-a32.inc.c"
7390 #include "decode-a32-uncond.inc.c"
7391 #include "decode-t32.inc.c"
7392 #include "decode-t16.inc.c"
7394 /* Helpers to swap operands for reverse-subtract. */
7395 static void gen_rsb(TCGv_i32 dst, TCGv_i32 a, TCGv_i32 b)
7397 tcg_gen_sub_i32(dst, b, a);
7400 static void gen_rsb_CC(TCGv_i32 dst, TCGv_i32 a, TCGv_i32 b)
7402 gen_sub_CC(dst, b, a);
7405 static void gen_rsc(TCGv_i32 dest, TCGv_i32 a, TCGv_i32 b)
7407 gen_sub_carry(dest, b, a);
7410 static void gen_rsc_CC(TCGv_i32 dest, TCGv_i32 a, TCGv_i32 b)
7412 gen_sbc_CC(dest, b, a);
7416 * Helpers for the data processing routines.
7418 * After the computation store the results back.
7419 * This may be suppressed altogether (STREG_NONE), require a runtime
7420 * check against the stack limits (STREG_SP_CHECK), or generate an
7421 * exception return. Oh, or store into a register.
7423 * Always return true, indicating success for a trans_* function.
7425 typedef enum {
7426 STREG_NONE,
7427 STREG_NORMAL,
7428 STREG_SP_CHECK,
7429 STREG_EXC_RET,
7430 } StoreRegKind;
7432 static bool store_reg_kind(DisasContext *s, int rd,
7433 TCGv_i32 val, StoreRegKind kind)
7435 switch (kind) {
7436 case STREG_NONE:
7437 tcg_temp_free_i32(val);
7438 return true;
7439 case STREG_NORMAL:
7440 /* See ALUWritePC: Interworking only from a32 mode. */
7441 if (s->thumb) {
7442 store_reg(s, rd, val);
7443 } else {
7444 store_reg_bx(s, rd, val);
7446 return true;
7447 case STREG_SP_CHECK:
7448 store_sp_checked(s, val);
7449 return true;
7450 case STREG_EXC_RET:
7451 gen_exception_return(s, val);
7452 return true;
7454 g_assert_not_reached();
7458 * Data Processing (register)
7460 * Operate, with set flags, one register source,
7461 * one immediate shifted register source, and a destination.
7463 static bool op_s_rrr_shi(DisasContext *s, arg_s_rrr_shi *a,
7464 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32),
7465 int logic_cc, StoreRegKind kind)
7467 TCGv_i32 tmp1, tmp2;
7469 tmp2 = load_reg(s, a->rm);
7470 gen_arm_shift_im(tmp2, a->shty, a->shim, logic_cc);
7471 tmp1 = load_reg(s, a->rn);
7473 gen(tmp1, tmp1, tmp2);
7474 tcg_temp_free_i32(tmp2);
7476 if (logic_cc) {
7477 gen_logic_CC(tmp1);
7479 return store_reg_kind(s, a->rd, tmp1, kind);
7482 static bool op_s_rxr_shi(DisasContext *s, arg_s_rrr_shi *a,
7483 void (*gen)(TCGv_i32, TCGv_i32),
7484 int logic_cc, StoreRegKind kind)
7486 TCGv_i32 tmp;
7488 tmp = load_reg(s, a->rm);
7489 gen_arm_shift_im(tmp, a->shty, a->shim, logic_cc);
7491 gen(tmp, tmp);
7492 if (logic_cc) {
7493 gen_logic_CC(tmp);
7495 return store_reg_kind(s, a->rd, tmp, kind);
7499 * Data-processing (register-shifted register)
7501 * Operate, with set flags, one register source,
7502 * one register shifted register source, and a destination.
7504 static bool op_s_rrr_shr(DisasContext *s, arg_s_rrr_shr *a,
7505 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32),
7506 int logic_cc, StoreRegKind kind)
7508 TCGv_i32 tmp1, tmp2;
7510 tmp1 = load_reg(s, a->rs);
7511 tmp2 = load_reg(s, a->rm);
7512 gen_arm_shift_reg(tmp2, a->shty, tmp1, logic_cc);
7513 tmp1 = load_reg(s, a->rn);
7515 gen(tmp1, tmp1, tmp2);
7516 tcg_temp_free_i32(tmp2);
7518 if (logic_cc) {
7519 gen_logic_CC(tmp1);
7521 return store_reg_kind(s, a->rd, tmp1, kind);
7524 static bool op_s_rxr_shr(DisasContext *s, arg_s_rrr_shr *a,
7525 void (*gen)(TCGv_i32, TCGv_i32),
7526 int logic_cc, StoreRegKind kind)
7528 TCGv_i32 tmp1, tmp2;
7530 tmp1 = load_reg(s, a->rs);
7531 tmp2 = load_reg(s, a->rm);
7532 gen_arm_shift_reg(tmp2, a->shty, tmp1, logic_cc);
7534 gen(tmp2, tmp2);
7535 if (logic_cc) {
7536 gen_logic_CC(tmp2);
7538 return store_reg_kind(s, a->rd, tmp2, kind);
7542 * Data-processing (immediate)
7544 * Operate, with set flags, one register source,
7545 * one rotated immediate, and a destination.
7547 * Note that logic_cc && a->rot setting CF based on the msb of the
7548 * immediate is the reason why we must pass in the unrotated form
7549 * of the immediate.
7551 static bool op_s_rri_rot(DisasContext *s, arg_s_rri_rot *a,
7552 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32),
7553 int logic_cc, StoreRegKind kind)
7555 TCGv_i32 tmp1, tmp2;
7556 uint32_t imm;
7558 imm = ror32(a->imm, a->rot);
7559 if (logic_cc && a->rot) {
7560 tcg_gen_movi_i32(cpu_CF, imm >> 31);
7562 tmp2 = tcg_const_i32(imm);
7563 tmp1 = load_reg(s, a->rn);
7565 gen(tmp1, tmp1, tmp2);
7566 tcg_temp_free_i32(tmp2);
7568 if (logic_cc) {
7569 gen_logic_CC(tmp1);
7571 return store_reg_kind(s, a->rd, tmp1, kind);
7574 static bool op_s_rxi_rot(DisasContext *s, arg_s_rri_rot *a,
7575 void (*gen)(TCGv_i32, TCGv_i32),
7576 int logic_cc, StoreRegKind kind)
7578 TCGv_i32 tmp;
7579 uint32_t imm;
7581 imm = ror32(a->imm, a->rot);
7582 if (logic_cc && a->rot) {
7583 tcg_gen_movi_i32(cpu_CF, imm >> 31);
7585 tmp = tcg_const_i32(imm);
7587 gen(tmp, tmp);
7588 if (logic_cc) {
7589 gen_logic_CC(tmp);
7591 return store_reg_kind(s, a->rd, tmp, kind);
7594 #define DO_ANY3(NAME, OP, L, K) \
7595 static bool trans_##NAME##_rrri(DisasContext *s, arg_s_rrr_shi *a) \
7596 { StoreRegKind k = (K); return op_s_rrr_shi(s, a, OP, L, k); } \
7597 static bool trans_##NAME##_rrrr(DisasContext *s, arg_s_rrr_shr *a) \
7598 { StoreRegKind k = (K); return op_s_rrr_shr(s, a, OP, L, k); } \
7599 static bool trans_##NAME##_rri(DisasContext *s, arg_s_rri_rot *a) \
7600 { StoreRegKind k = (K); return op_s_rri_rot(s, a, OP, L, k); }
7602 #define DO_ANY2(NAME, OP, L, K) \
7603 static bool trans_##NAME##_rxri(DisasContext *s, arg_s_rrr_shi *a) \
7604 { StoreRegKind k = (K); return op_s_rxr_shi(s, a, OP, L, k); } \
7605 static bool trans_##NAME##_rxrr(DisasContext *s, arg_s_rrr_shr *a) \
7606 { StoreRegKind k = (K); return op_s_rxr_shr(s, a, OP, L, k); } \
7607 static bool trans_##NAME##_rxi(DisasContext *s, arg_s_rri_rot *a) \
7608 { StoreRegKind k = (K); return op_s_rxi_rot(s, a, OP, L, k); }
7610 #define DO_CMP2(NAME, OP, L) \
7611 static bool trans_##NAME##_xrri(DisasContext *s, arg_s_rrr_shi *a) \
7612 { return op_s_rrr_shi(s, a, OP, L, STREG_NONE); } \
7613 static bool trans_##NAME##_xrrr(DisasContext *s, arg_s_rrr_shr *a) \
7614 { return op_s_rrr_shr(s, a, OP, L, STREG_NONE); } \
7615 static bool trans_##NAME##_xri(DisasContext *s, arg_s_rri_rot *a) \
7616 { return op_s_rri_rot(s, a, OP, L, STREG_NONE); }
7618 DO_ANY3(AND, tcg_gen_and_i32, a->s, STREG_NORMAL)
7619 DO_ANY3(EOR, tcg_gen_xor_i32, a->s, STREG_NORMAL)
7620 DO_ANY3(ORR, tcg_gen_or_i32, a->s, STREG_NORMAL)
7621 DO_ANY3(BIC, tcg_gen_andc_i32, a->s, STREG_NORMAL)
7623 DO_ANY3(RSB, a->s ? gen_rsb_CC : gen_rsb, false, STREG_NORMAL)
7624 DO_ANY3(ADC, a->s ? gen_adc_CC : gen_add_carry, false, STREG_NORMAL)
7625 DO_ANY3(SBC, a->s ? gen_sbc_CC : gen_sub_carry, false, STREG_NORMAL)
7626 DO_ANY3(RSC, a->s ? gen_rsc_CC : gen_rsc, false, STREG_NORMAL)
7628 DO_CMP2(TST, tcg_gen_and_i32, true)
7629 DO_CMP2(TEQ, tcg_gen_xor_i32, true)
7630 DO_CMP2(CMN, gen_add_CC, false)
7631 DO_CMP2(CMP, gen_sub_CC, false)
7633 DO_ANY3(ADD, a->s ? gen_add_CC : tcg_gen_add_i32, false,
7634 a->rd == 13 && a->rn == 13 ? STREG_SP_CHECK : STREG_NORMAL)
7637 * Note for the computation of StoreRegKind we return out of the
7638 * middle of the functions that are expanded by DO_ANY3, and that
7639 * we modify a->s via that parameter before it is used by OP.
7641 DO_ANY3(SUB, a->s ? gen_sub_CC : tcg_gen_sub_i32, false,
7643 StoreRegKind ret = STREG_NORMAL;
7644 if (a->rd == 15 && a->s) {
7646 * See ALUExceptionReturn:
7647 * In User mode, UNPREDICTABLE; we choose UNDEF.
7648 * In Hyp mode, UNDEFINED.
7650 if (IS_USER(s) || s->current_el == 2) {
7651 unallocated_encoding(s);
7652 return true;
7654 /* There is no writeback of nzcv to PSTATE. */
7655 a->s = 0;
7656 ret = STREG_EXC_RET;
7657 } else if (a->rd == 13 && a->rn == 13) {
7658 ret = STREG_SP_CHECK;
7660 ret;
7663 DO_ANY2(MOV, tcg_gen_mov_i32, a->s,
7665 StoreRegKind ret = STREG_NORMAL;
7666 if (a->rd == 15 && a->s) {
7668 * See ALUExceptionReturn:
7669 * In User mode, UNPREDICTABLE; we choose UNDEF.
7670 * In Hyp mode, UNDEFINED.
7672 if (IS_USER(s) || s->current_el == 2) {
7673 unallocated_encoding(s);
7674 return true;
7676 /* There is no writeback of nzcv to PSTATE. */
7677 a->s = 0;
7678 ret = STREG_EXC_RET;
7679 } else if (a->rd == 13) {
7680 ret = STREG_SP_CHECK;
7682 ret;
7685 DO_ANY2(MVN, tcg_gen_not_i32, a->s, STREG_NORMAL)
7688 * ORN is only available with T32, so there is no register-shifted-register
7689 * form of the insn. Using the DO_ANY3 macro would create an unused function.
7691 static bool trans_ORN_rrri(DisasContext *s, arg_s_rrr_shi *a)
7693 return op_s_rrr_shi(s, a, tcg_gen_orc_i32, a->s, STREG_NORMAL);
7696 static bool trans_ORN_rri(DisasContext *s, arg_s_rri_rot *a)
7698 return op_s_rri_rot(s, a, tcg_gen_orc_i32, a->s, STREG_NORMAL);
7701 #undef DO_ANY3
7702 #undef DO_ANY2
7703 #undef DO_CMP2
7705 static bool trans_ADR(DisasContext *s, arg_ri *a)
7707 store_reg_bx(s, a->rd, add_reg_for_lit(s, 15, a->imm));
7708 return true;
7711 static bool trans_MOVW(DisasContext *s, arg_MOVW *a)
7713 TCGv_i32 tmp;
7715 if (!ENABLE_ARCH_6T2) {
7716 return false;
7719 tmp = tcg_const_i32(a->imm);
7720 store_reg(s, a->rd, tmp);
7721 return true;
7724 static bool trans_MOVT(DisasContext *s, arg_MOVW *a)
7726 TCGv_i32 tmp;
7728 if (!ENABLE_ARCH_6T2) {
7729 return false;
7732 tmp = load_reg(s, a->rd);
7733 tcg_gen_ext16u_i32(tmp, tmp);
7734 tcg_gen_ori_i32(tmp, tmp, a->imm << 16);
7735 store_reg(s, a->rd, tmp);
7736 return true;
7740 * Multiply and multiply accumulate
7743 static bool op_mla(DisasContext *s, arg_s_rrrr *a, bool add)
7745 TCGv_i32 t1, t2;
7747 t1 = load_reg(s, a->rn);
7748 t2 = load_reg(s, a->rm);
7749 tcg_gen_mul_i32(t1, t1, t2);
7750 tcg_temp_free_i32(t2);
7751 if (add) {
7752 t2 = load_reg(s, a->ra);
7753 tcg_gen_add_i32(t1, t1, t2);
7754 tcg_temp_free_i32(t2);
7756 if (a->s) {
7757 gen_logic_CC(t1);
7759 store_reg(s, a->rd, t1);
7760 return true;
7763 static bool trans_MUL(DisasContext *s, arg_MUL *a)
7765 return op_mla(s, a, false);
7768 static bool trans_MLA(DisasContext *s, arg_MLA *a)
7770 return op_mla(s, a, true);
7773 static bool trans_MLS(DisasContext *s, arg_MLS *a)
7775 TCGv_i32 t1, t2;
7777 if (!ENABLE_ARCH_6T2) {
7778 return false;
7780 t1 = load_reg(s, a->rn);
7781 t2 = load_reg(s, a->rm);
7782 tcg_gen_mul_i32(t1, t1, t2);
7783 tcg_temp_free_i32(t2);
7784 t2 = load_reg(s, a->ra);
7785 tcg_gen_sub_i32(t1, t2, t1);
7786 tcg_temp_free_i32(t2);
7787 store_reg(s, a->rd, t1);
7788 return true;
7791 static bool op_mlal(DisasContext *s, arg_s_rrrr *a, bool uns, bool add)
7793 TCGv_i32 t0, t1, t2, t3;
7795 t0 = load_reg(s, a->rm);
7796 t1 = load_reg(s, a->rn);
7797 if (uns) {
7798 tcg_gen_mulu2_i32(t0, t1, t0, t1);
7799 } else {
7800 tcg_gen_muls2_i32(t0, t1, t0, t1);
7802 if (add) {
7803 t2 = load_reg(s, a->ra);
7804 t3 = load_reg(s, a->rd);
7805 tcg_gen_add2_i32(t0, t1, t0, t1, t2, t3);
7806 tcg_temp_free_i32(t2);
7807 tcg_temp_free_i32(t3);
7809 if (a->s) {
7810 gen_logicq_cc(t0, t1);
7812 store_reg(s, a->ra, t0);
7813 store_reg(s, a->rd, t1);
7814 return true;
7817 static bool trans_UMULL(DisasContext *s, arg_UMULL *a)
7819 return op_mlal(s, a, true, false);
7822 static bool trans_SMULL(DisasContext *s, arg_SMULL *a)
7824 return op_mlal(s, a, false, false);
7827 static bool trans_UMLAL(DisasContext *s, arg_UMLAL *a)
7829 return op_mlal(s, a, true, true);
7832 static bool trans_SMLAL(DisasContext *s, arg_SMLAL *a)
7834 return op_mlal(s, a, false, true);
7837 static bool trans_UMAAL(DisasContext *s, arg_UMAAL *a)
7839 TCGv_i32 t0, t1, t2, zero;
7841 if (s->thumb
7842 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7843 : !ENABLE_ARCH_6) {
7844 return false;
7847 t0 = load_reg(s, a->rm);
7848 t1 = load_reg(s, a->rn);
7849 tcg_gen_mulu2_i32(t0, t1, t0, t1);
7850 zero = tcg_const_i32(0);
7851 t2 = load_reg(s, a->ra);
7852 tcg_gen_add2_i32(t0, t1, t0, t1, t2, zero);
7853 tcg_temp_free_i32(t2);
7854 t2 = load_reg(s, a->rd);
7855 tcg_gen_add2_i32(t0, t1, t0, t1, t2, zero);
7856 tcg_temp_free_i32(t2);
7857 tcg_temp_free_i32(zero);
7858 store_reg(s, a->ra, t0);
7859 store_reg(s, a->rd, t1);
7860 return true;
7864 * Saturating addition and subtraction
7867 static bool op_qaddsub(DisasContext *s, arg_rrr *a, bool add, bool doub)
7869 TCGv_i32 t0, t1;
7871 if (s->thumb
7872 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7873 : !ENABLE_ARCH_5TE) {
7874 return false;
7877 t0 = load_reg(s, a->rm);
7878 t1 = load_reg(s, a->rn);
7879 if (doub) {
7880 gen_helper_add_saturate(t1, cpu_env, t1, t1);
7882 if (add) {
7883 gen_helper_add_saturate(t0, cpu_env, t0, t1);
7884 } else {
7885 gen_helper_sub_saturate(t0, cpu_env, t0, t1);
7887 tcg_temp_free_i32(t1);
7888 store_reg(s, a->rd, t0);
7889 return true;
7892 #define DO_QADDSUB(NAME, ADD, DOUB) \
7893 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
7895 return op_qaddsub(s, a, ADD, DOUB); \
7898 DO_QADDSUB(QADD, true, false)
7899 DO_QADDSUB(QSUB, false, false)
7900 DO_QADDSUB(QDADD, true, true)
7901 DO_QADDSUB(QDSUB, false, true)
7903 #undef DO_QADDSUB
7906 * Halfword multiply and multiply accumulate
7909 static bool op_smlaxxx(DisasContext *s, arg_rrrr *a,
7910 int add_long, bool nt, bool mt)
7912 TCGv_i32 t0, t1, tl, th;
7914 if (s->thumb
7915 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7916 : !ENABLE_ARCH_5TE) {
7917 return false;
7920 t0 = load_reg(s, a->rn);
7921 t1 = load_reg(s, a->rm);
7922 gen_mulxy(t0, t1, nt, mt);
7923 tcg_temp_free_i32(t1);
7925 switch (add_long) {
7926 case 0:
7927 store_reg(s, a->rd, t0);
7928 break;
7929 case 1:
7930 t1 = load_reg(s, a->ra);
7931 gen_helper_add_setq(t0, cpu_env, t0, t1);
7932 tcg_temp_free_i32(t1);
7933 store_reg(s, a->rd, t0);
7934 break;
7935 case 2:
7936 tl = load_reg(s, a->ra);
7937 th = load_reg(s, a->rd);
7938 /* Sign-extend the 32-bit product to 64 bits. */
7939 t1 = tcg_temp_new_i32();
7940 tcg_gen_sari_i32(t1, t0, 31);
7941 tcg_gen_add2_i32(tl, th, tl, th, t0, t1);
7942 tcg_temp_free_i32(t0);
7943 tcg_temp_free_i32(t1);
7944 store_reg(s, a->ra, tl);
7945 store_reg(s, a->rd, th);
7946 break;
7947 default:
7948 g_assert_not_reached();
7950 return true;
7953 #define DO_SMLAX(NAME, add, nt, mt) \
7954 static bool trans_##NAME(DisasContext *s, arg_rrrr *a) \
7956 return op_smlaxxx(s, a, add, nt, mt); \
7959 DO_SMLAX(SMULBB, 0, 0, 0)
7960 DO_SMLAX(SMULBT, 0, 0, 1)
7961 DO_SMLAX(SMULTB, 0, 1, 0)
7962 DO_SMLAX(SMULTT, 0, 1, 1)
7964 DO_SMLAX(SMLABB, 1, 0, 0)
7965 DO_SMLAX(SMLABT, 1, 0, 1)
7966 DO_SMLAX(SMLATB, 1, 1, 0)
7967 DO_SMLAX(SMLATT, 1, 1, 1)
7969 DO_SMLAX(SMLALBB, 2, 0, 0)
7970 DO_SMLAX(SMLALBT, 2, 0, 1)
7971 DO_SMLAX(SMLALTB, 2, 1, 0)
7972 DO_SMLAX(SMLALTT, 2, 1, 1)
7974 #undef DO_SMLAX
7976 static bool op_smlawx(DisasContext *s, arg_rrrr *a, bool add, bool mt)
7978 TCGv_i32 t0, t1;
7980 if (!ENABLE_ARCH_5TE) {
7981 return false;
7984 t0 = load_reg(s, a->rn);
7985 t1 = load_reg(s, a->rm);
7987 * Since the nominal result is product<47:16>, shift the 16-bit
7988 * input up by 16 bits, so that the result is at product<63:32>.
7990 if (mt) {
7991 tcg_gen_andi_i32(t1, t1, 0xffff0000);
7992 } else {
7993 tcg_gen_shli_i32(t1, t1, 16);
7995 tcg_gen_muls2_i32(t0, t1, t0, t1);
7996 tcg_temp_free_i32(t0);
7997 if (add) {
7998 t0 = load_reg(s, a->ra);
7999 gen_helper_add_setq(t1, cpu_env, t1, t0);
8000 tcg_temp_free_i32(t0);
8002 store_reg(s, a->rd, t1);
8003 return true;
8006 #define DO_SMLAWX(NAME, add, mt) \
8007 static bool trans_##NAME(DisasContext *s, arg_rrrr *a) \
8009 return op_smlawx(s, a, add, mt); \
8012 DO_SMLAWX(SMULWB, 0, 0)
8013 DO_SMLAWX(SMULWT, 0, 1)
8014 DO_SMLAWX(SMLAWB, 1, 0)
8015 DO_SMLAWX(SMLAWT, 1, 1)
8017 #undef DO_SMLAWX
8020 * MSR (immediate) and hints
8023 static bool trans_YIELD(DisasContext *s, arg_YIELD *a)
8026 * When running single-threaded TCG code, use the helper to ensure that
8027 * the next round-robin scheduled vCPU gets a crack. When running in
8028 * MTTCG we don't generate jumps to the helper as it won't affect the
8029 * scheduling of other vCPUs.
8031 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
8032 gen_set_pc_im(s, s->base.pc_next);
8033 s->base.is_jmp = DISAS_YIELD;
8035 return true;
8038 static bool trans_WFE(DisasContext *s, arg_WFE *a)
8041 * When running single-threaded TCG code, use the helper to ensure that
8042 * the next round-robin scheduled vCPU gets a crack. In MTTCG mode we
8043 * just skip this instruction. Currently the SEV/SEVL instructions,
8044 * which are *one* of many ways to wake the CPU from WFE, are not
8045 * implemented so we can't sleep like WFI does.
8047 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
8048 gen_set_pc_im(s, s->base.pc_next);
8049 s->base.is_jmp = DISAS_WFE;
8051 return true;
8054 static bool trans_WFI(DisasContext *s, arg_WFI *a)
8056 /* For WFI, halt the vCPU until an IRQ. */
8057 gen_set_pc_im(s, s->base.pc_next);
8058 s->base.is_jmp = DISAS_WFI;
8059 return true;
8062 static bool trans_NOP(DisasContext *s, arg_NOP *a)
8064 return true;
8067 static bool trans_MSR_imm(DisasContext *s, arg_MSR_imm *a)
8069 uint32_t val = ror32(a->imm, a->rot * 2);
8070 uint32_t mask = msr_mask(s, a->mask, a->r);
8072 if (gen_set_psr_im(s, mask, a->r, val)) {
8073 unallocated_encoding(s);
8075 return true;
8079 * Cyclic Redundancy Check
8082 static bool op_crc32(DisasContext *s, arg_rrr *a, bool c, MemOp sz)
8084 TCGv_i32 t1, t2, t3;
8086 if (!dc_isar_feature(aa32_crc32, s)) {
8087 return false;
8090 t1 = load_reg(s, a->rn);
8091 t2 = load_reg(s, a->rm);
8092 switch (sz) {
8093 case MO_8:
8094 gen_uxtb(t2);
8095 break;
8096 case MO_16:
8097 gen_uxth(t2);
8098 break;
8099 case MO_32:
8100 break;
8101 default:
8102 g_assert_not_reached();
8104 t3 = tcg_const_i32(1 << sz);
8105 if (c) {
8106 gen_helper_crc32c(t1, t1, t2, t3);
8107 } else {
8108 gen_helper_crc32(t1, t1, t2, t3);
8110 tcg_temp_free_i32(t2);
8111 tcg_temp_free_i32(t3);
8112 store_reg(s, a->rd, t1);
8113 return true;
8116 #define DO_CRC32(NAME, c, sz) \
8117 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
8118 { return op_crc32(s, a, c, sz); }
8120 DO_CRC32(CRC32B, false, MO_8)
8121 DO_CRC32(CRC32H, false, MO_16)
8122 DO_CRC32(CRC32W, false, MO_32)
8123 DO_CRC32(CRC32CB, true, MO_8)
8124 DO_CRC32(CRC32CH, true, MO_16)
8125 DO_CRC32(CRC32CW, true, MO_32)
8127 #undef DO_CRC32
8130 * Miscellaneous instructions
8133 static bool trans_MRS_bank(DisasContext *s, arg_MRS_bank *a)
8135 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8136 return false;
8138 gen_mrs_banked(s, a->r, a->sysm, a->rd);
8139 return true;
8142 static bool trans_MSR_bank(DisasContext *s, arg_MSR_bank *a)
8144 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8145 return false;
8147 gen_msr_banked(s, a->r, a->sysm, a->rn);
8148 return true;
8151 static bool trans_MRS_reg(DisasContext *s, arg_MRS_reg *a)
8153 TCGv_i32 tmp;
8155 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8156 return false;
8158 if (a->r) {
8159 if (IS_USER(s)) {
8160 unallocated_encoding(s);
8161 return true;
8163 tmp = load_cpu_field(spsr);
8164 } else {
8165 tmp = tcg_temp_new_i32();
8166 gen_helper_cpsr_read(tmp, cpu_env);
8168 store_reg(s, a->rd, tmp);
8169 return true;
8172 static bool trans_MSR_reg(DisasContext *s, arg_MSR_reg *a)
8174 TCGv_i32 tmp;
8175 uint32_t mask = msr_mask(s, a->mask, a->r);
8177 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8178 return false;
8180 tmp = load_reg(s, a->rn);
8181 if (gen_set_psr(s, mask, a->r, tmp)) {
8182 unallocated_encoding(s);
8184 return true;
8187 static bool trans_MRS_v7m(DisasContext *s, arg_MRS_v7m *a)
8189 TCGv_i32 tmp;
8191 if (!arm_dc_feature(s, ARM_FEATURE_M)) {
8192 return false;
8194 tmp = tcg_const_i32(a->sysm);
8195 gen_helper_v7m_mrs(tmp, cpu_env, tmp);
8196 store_reg(s, a->rd, tmp);
8197 return true;
8200 static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m *a)
8202 TCGv_i32 addr, reg;
8204 if (!arm_dc_feature(s, ARM_FEATURE_M)) {
8205 return false;
8207 addr = tcg_const_i32((a->mask << 10) | a->sysm);
8208 reg = load_reg(s, a->rn);
8209 gen_helper_v7m_msr(cpu_env, addr, reg);
8210 tcg_temp_free_i32(addr);
8211 tcg_temp_free_i32(reg);
8212 /* If we wrote to CONTROL, the EL might have changed */
8213 gen_helper_rebuild_hflags_m32_newel(cpu_env);
8214 gen_lookup_tb(s);
8215 return true;
8218 static bool trans_BX(DisasContext *s, arg_BX *a)
8220 if (!ENABLE_ARCH_4T) {
8221 return false;
8223 gen_bx_excret(s, load_reg(s, a->rm));
8224 return true;
8227 static bool trans_BXJ(DisasContext *s, arg_BXJ *a)
8229 if (!ENABLE_ARCH_5J || arm_dc_feature(s, ARM_FEATURE_M)) {
8230 return false;
8232 /* Trivial implementation equivalent to bx. */
8233 gen_bx(s, load_reg(s, a->rm));
8234 return true;
8237 static bool trans_BLX_r(DisasContext *s, arg_BLX_r *a)
8239 TCGv_i32 tmp;
8241 if (!ENABLE_ARCH_5) {
8242 return false;
8244 tmp = load_reg(s, a->rm);
8245 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
8246 gen_bx(s, tmp);
8247 return true;
8251 * BXNS/BLXNS: only exist for v8M with the security extensions,
8252 * and always UNDEF if NonSecure. We don't implement these in
8253 * the user-only mode either (in theory you can use them from
8254 * Secure User mode but they are too tied in to system emulation).
8256 static bool trans_BXNS(DisasContext *s, arg_BXNS *a)
8258 if (!s->v8m_secure || IS_USER_ONLY) {
8259 unallocated_encoding(s);
8260 } else {
8261 gen_bxns(s, a->rm);
8263 return true;
8266 static bool trans_BLXNS(DisasContext *s, arg_BLXNS *a)
8268 if (!s->v8m_secure || IS_USER_ONLY) {
8269 unallocated_encoding(s);
8270 } else {
8271 gen_blxns(s, a->rm);
8273 return true;
8276 static bool trans_CLZ(DisasContext *s, arg_CLZ *a)
8278 TCGv_i32 tmp;
8280 if (!ENABLE_ARCH_5) {
8281 return false;
8283 tmp = load_reg(s, a->rm);
8284 tcg_gen_clzi_i32(tmp, tmp, 32);
8285 store_reg(s, a->rd, tmp);
8286 return true;
8289 static bool trans_ERET(DisasContext *s, arg_ERET *a)
8291 TCGv_i32 tmp;
8293 if (!arm_dc_feature(s, ARM_FEATURE_V7VE)) {
8294 return false;
8296 if (IS_USER(s)) {
8297 unallocated_encoding(s);
8298 return true;
8300 if (s->current_el == 2) {
8301 /* ERET from Hyp uses ELR_Hyp, not LR */
8302 tmp = load_cpu_field(elr_el[2]);
8303 } else {
8304 tmp = load_reg(s, 14);
8306 gen_exception_return(s, tmp);
8307 return true;
8310 static bool trans_HLT(DisasContext *s, arg_HLT *a)
8312 gen_hlt(s, a->imm);
8313 return true;
8316 static bool trans_BKPT(DisasContext *s, arg_BKPT *a)
8318 if (!ENABLE_ARCH_5) {
8319 return false;
8321 if (arm_dc_feature(s, ARM_FEATURE_M) &&
8322 semihosting_enabled() &&
8323 #ifndef CONFIG_USER_ONLY
8324 !IS_USER(s) &&
8325 #endif
8326 (a->imm == 0xab)) {
8327 gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
8328 } else {
8329 gen_exception_bkpt_insn(s, syn_aa32_bkpt(a->imm, false));
8331 return true;
8334 static bool trans_HVC(DisasContext *s, arg_HVC *a)
8336 if (!ENABLE_ARCH_7 || arm_dc_feature(s, ARM_FEATURE_M)) {
8337 return false;
8339 if (IS_USER(s)) {
8340 unallocated_encoding(s);
8341 } else {
8342 gen_hvc(s, a->imm);
8344 return true;
8347 static bool trans_SMC(DisasContext *s, arg_SMC *a)
8349 if (!ENABLE_ARCH_6K || arm_dc_feature(s, ARM_FEATURE_M)) {
8350 return false;
8352 if (IS_USER(s)) {
8353 unallocated_encoding(s);
8354 } else {
8355 gen_smc(s);
8357 return true;
8360 static bool trans_SG(DisasContext *s, arg_SG *a)
8362 if (!arm_dc_feature(s, ARM_FEATURE_M) ||
8363 !arm_dc_feature(s, ARM_FEATURE_V8)) {
8364 return false;
8367 * SG (v8M only)
8368 * The bulk of the behaviour for this instruction is implemented
8369 * in v7m_handle_execute_nsc(), which deals with the insn when
8370 * it is executed by a CPU in non-secure state from memory
8371 * which is Secure & NonSecure-Callable.
8372 * Here we only need to handle the remaining cases:
8373 * * in NS memory (including the "security extension not
8374 * implemented" case) : NOP
8375 * * in S memory but CPU already secure (clear IT bits)
8376 * We know that the attribute for the memory this insn is
8377 * in must match the current CPU state, because otherwise
8378 * get_phys_addr_pmsav8 would have generated an exception.
8380 if (s->v8m_secure) {
8381 /* Like the IT insn, we don't need to generate any code */
8382 s->condexec_cond = 0;
8383 s->condexec_mask = 0;
8385 return true;
8388 static bool trans_TT(DisasContext *s, arg_TT *a)
8390 TCGv_i32 addr, tmp;
8392 if (!arm_dc_feature(s, ARM_FEATURE_M) ||
8393 !arm_dc_feature(s, ARM_FEATURE_V8)) {
8394 return false;
8396 if (a->rd == 13 || a->rd == 15 || a->rn == 15) {
8397 /* We UNDEF for these UNPREDICTABLE cases */
8398 unallocated_encoding(s);
8399 return true;
8401 if (a->A && !s->v8m_secure) {
8402 /* This case is UNDEFINED. */
8403 unallocated_encoding(s);
8404 return true;
8407 addr = load_reg(s, a->rn);
8408 tmp = tcg_const_i32((a->A << 1) | a->T);
8409 gen_helper_v7m_tt(tmp, cpu_env, addr, tmp);
8410 tcg_temp_free_i32(addr);
8411 store_reg(s, a->rd, tmp);
8412 return true;
8416 * Load/store register index
8419 static ISSInfo make_issinfo(DisasContext *s, int rd, bool p, bool w)
8421 ISSInfo ret;
8423 /* ISS not valid if writeback */
8424 if (p && !w) {
8425 ret = rd;
8426 if (s->base.pc_next - s->pc_curr == 2) {
8427 ret |= ISSIs16Bit;
8429 } else {
8430 ret = ISSInvalid;
8432 return ret;
8435 static TCGv_i32 op_addr_rr_pre(DisasContext *s, arg_ldst_rr *a)
8437 TCGv_i32 addr = load_reg(s, a->rn);
8439 if (s->v8m_stackcheck && a->rn == 13 && a->w) {
8440 gen_helper_v8m_stackcheck(cpu_env, addr);
8443 if (a->p) {
8444 TCGv_i32 ofs = load_reg(s, a->rm);
8445 gen_arm_shift_im(ofs, a->shtype, a->shimm, 0);
8446 if (a->u) {
8447 tcg_gen_add_i32(addr, addr, ofs);
8448 } else {
8449 tcg_gen_sub_i32(addr, addr, ofs);
8451 tcg_temp_free_i32(ofs);
8453 return addr;
8456 static void op_addr_rr_post(DisasContext *s, arg_ldst_rr *a,
8457 TCGv_i32 addr, int address_offset)
8459 if (!a->p) {
8460 TCGv_i32 ofs = load_reg(s, a->rm);
8461 gen_arm_shift_im(ofs, a->shtype, a->shimm, 0);
8462 if (a->u) {
8463 tcg_gen_add_i32(addr, addr, ofs);
8464 } else {
8465 tcg_gen_sub_i32(addr, addr, ofs);
8467 tcg_temp_free_i32(ofs);
8468 } else if (!a->w) {
8469 tcg_temp_free_i32(addr);
8470 return;
8472 tcg_gen_addi_i32(addr, addr, address_offset);
8473 store_reg(s, a->rn, addr);
8476 static bool op_load_rr(DisasContext *s, arg_ldst_rr *a,
8477 MemOp mop, int mem_idx)
8479 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w);
8480 TCGv_i32 addr, tmp;
8482 addr = op_addr_rr_pre(s, a);
8484 tmp = tcg_temp_new_i32();
8485 gen_aa32_ld_i32(s, tmp, addr, mem_idx, mop | s->be_data);
8486 disas_set_da_iss(s, mop, issinfo);
8489 * Perform base writeback before the loaded value to
8490 * ensure correct behavior with overlapping index registers.
8492 op_addr_rr_post(s, a, addr, 0);
8493 store_reg_from_load(s, a->rt, tmp);
8494 return true;
8497 static bool op_store_rr(DisasContext *s, arg_ldst_rr *a,
8498 MemOp mop, int mem_idx)
8500 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w) | ISSIsWrite;
8501 TCGv_i32 addr, tmp;
8503 addr = op_addr_rr_pre(s, a);
8505 tmp = load_reg(s, a->rt);
8506 gen_aa32_st_i32(s, tmp, addr, mem_idx, mop | s->be_data);
8507 disas_set_da_iss(s, mop, issinfo);
8508 tcg_temp_free_i32(tmp);
8510 op_addr_rr_post(s, a, addr, 0);
8511 return true;
8514 static bool trans_LDRD_rr(DisasContext *s, arg_ldst_rr *a)
8516 int mem_idx = get_mem_index(s);
8517 TCGv_i32 addr, tmp;
8519 if (!ENABLE_ARCH_5TE) {
8520 return false;
8522 if (a->rt & 1) {
8523 unallocated_encoding(s);
8524 return true;
8526 addr = op_addr_rr_pre(s, a);
8528 tmp = tcg_temp_new_i32();
8529 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
8530 store_reg(s, a->rt, tmp);
8532 tcg_gen_addi_i32(addr, addr, 4);
8534 tmp = tcg_temp_new_i32();
8535 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
8536 store_reg(s, a->rt + 1, tmp);
8538 /* LDRD w/ base writeback is undefined if the registers overlap. */
8539 op_addr_rr_post(s, a, addr, -4);
8540 return true;
8543 static bool trans_STRD_rr(DisasContext *s, arg_ldst_rr *a)
8545 int mem_idx = get_mem_index(s);
8546 TCGv_i32 addr, tmp;
8548 if (!ENABLE_ARCH_5TE) {
8549 return false;
8551 if (a->rt & 1) {
8552 unallocated_encoding(s);
8553 return true;
8555 addr = op_addr_rr_pre(s, a);
8557 tmp = load_reg(s, a->rt);
8558 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
8559 tcg_temp_free_i32(tmp);
8561 tcg_gen_addi_i32(addr, addr, 4);
8563 tmp = load_reg(s, a->rt + 1);
8564 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
8565 tcg_temp_free_i32(tmp);
8567 op_addr_rr_post(s, a, addr, -4);
8568 return true;
8572 * Load/store immediate index
8575 static TCGv_i32 op_addr_ri_pre(DisasContext *s, arg_ldst_ri *a)
8577 int ofs = a->imm;
8579 if (!a->u) {
8580 ofs = -ofs;
8583 if (s->v8m_stackcheck && a->rn == 13 && a->w) {
8585 * Stackcheck. Here we know 'addr' is the current SP;
8586 * U is set if we're moving SP up, else down. It is
8587 * UNKNOWN whether the limit check triggers when SP starts
8588 * below the limit and ends up above it; we chose to do so.
8590 if (!a->u) {
8591 TCGv_i32 newsp = tcg_temp_new_i32();
8592 tcg_gen_addi_i32(newsp, cpu_R[13], ofs);
8593 gen_helper_v8m_stackcheck(cpu_env, newsp);
8594 tcg_temp_free_i32(newsp);
8595 } else {
8596 gen_helper_v8m_stackcheck(cpu_env, cpu_R[13]);
8600 return add_reg_for_lit(s, a->rn, a->p ? ofs : 0);
8603 static void op_addr_ri_post(DisasContext *s, arg_ldst_ri *a,
8604 TCGv_i32 addr, int address_offset)
8606 if (!a->p) {
8607 if (a->u) {
8608 address_offset += a->imm;
8609 } else {
8610 address_offset -= a->imm;
8612 } else if (!a->w) {
8613 tcg_temp_free_i32(addr);
8614 return;
8616 tcg_gen_addi_i32(addr, addr, address_offset);
8617 store_reg(s, a->rn, addr);
8620 static bool op_load_ri(DisasContext *s, arg_ldst_ri *a,
8621 MemOp mop, int mem_idx)
8623 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w);
8624 TCGv_i32 addr, tmp;
8626 addr = op_addr_ri_pre(s, a);
8628 tmp = tcg_temp_new_i32();
8629 gen_aa32_ld_i32(s, tmp, addr, mem_idx, mop | s->be_data);
8630 disas_set_da_iss(s, mop, issinfo);
8633 * Perform base writeback before the loaded value to
8634 * ensure correct behavior with overlapping index registers.
8636 op_addr_ri_post(s, a, addr, 0);
8637 store_reg_from_load(s, a->rt, tmp);
8638 return true;
8641 static bool op_store_ri(DisasContext *s, arg_ldst_ri *a,
8642 MemOp mop, int mem_idx)
8644 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w) | ISSIsWrite;
8645 TCGv_i32 addr, tmp;
8647 addr = op_addr_ri_pre(s, a);
8649 tmp = load_reg(s, a->rt);
8650 gen_aa32_st_i32(s, tmp, addr, mem_idx, mop | s->be_data);
8651 disas_set_da_iss(s, mop, issinfo);
8652 tcg_temp_free_i32(tmp);
8654 op_addr_ri_post(s, a, addr, 0);
8655 return true;
8658 static bool op_ldrd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
8660 int mem_idx = get_mem_index(s);
8661 TCGv_i32 addr, tmp;
8663 addr = op_addr_ri_pre(s, a);
8665 tmp = tcg_temp_new_i32();
8666 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
8667 store_reg(s, a->rt, tmp);
8669 tcg_gen_addi_i32(addr, addr, 4);
8671 tmp = tcg_temp_new_i32();
8672 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
8673 store_reg(s, rt2, tmp);
8675 /* LDRD w/ base writeback is undefined if the registers overlap. */
8676 op_addr_ri_post(s, a, addr, -4);
8677 return true;
8680 static bool trans_LDRD_ri_a32(DisasContext *s, arg_ldst_ri *a)
8682 if (!ENABLE_ARCH_5TE || (a->rt & 1)) {
8683 return false;
8685 return op_ldrd_ri(s, a, a->rt + 1);
8688 static bool trans_LDRD_ri_t32(DisasContext *s, arg_ldst_ri2 *a)
8690 arg_ldst_ri b = {
8691 .u = a->u, .w = a->w, .p = a->p,
8692 .rn = a->rn, .rt = a->rt, .imm = a->imm
8694 return op_ldrd_ri(s, &b, a->rt2);
8697 static bool op_strd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
8699 int mem_idx = get_mem_index(s);
8700 TCGv_i32 addr, tmp;
8702 addr = op_addr_ri_pre(s, a);
8704 tmp = load_reg(s, a->rt);
8705 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
8706 tcg_temp_free_i32(tmp);
8708 tcg_gen_addi_i32(addr, addr, 4);
8710 tmp = load_reg(s, rt2);
8711 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
8712 tcg_temp_free_i32(tmp);
8714 op_addr_ri_post(s, a, addr, -4);
8715 return true;
8718 static bool trans_STRD_ri_a32(DisasContext *s, arg_ldst_ri *a)
8720 if (!ENABLE_ARCH_5TE || (a->rt & 1)) {
8721 return false;
8723 return op_strd_ri(s, a, a->rt + 1);
8726 static bool trans_STRD_ri_t32(DisasContext *s, arg_ldst_ri2 *a)
8728 arg_ldst_ri b = {
8729 .u = a->u, .w = a->w, .p = a->p,
8730 .rn = a->rn, .rt = a->rt, .imm = a->imm
8732 return op_strd_ri(s, &b, a->rt2);
8735 #define DO_LDST(NAME, WHICH, MEMOP) \
8736 static bool trans_##NAME##_ri(DisasContext *s, arg_ldst_ri *a) \
8738 return op_##WHICH##_ri(s, a, MEMOP, get_mem_index(s)); \
8740 static bool trans_##NAME##T_ri(DisasContext *s, arg_ldst_ri *a) \
8742 return op_##WHICH##_ri(s, a, MEMOP, get_a32_user_mem_index(s)); \
8744 static bool trans_##NAME##_rr(DisasContext *s, arg_ldst_rr *a) \
8746 return op_##WHICH##_rr(s, a, MEMOP, get_mem_index(s)); \
8748 static bool trans_##NAME##T_rr(DisasContext *s, arg_ldst_rr *a) \
8750 return op_##WHICH##_rr(s, a, MEMOP, get_a32_user_mem_index(s)); \
8753 DO_LDST(LDR, load, MO_UL)
8754 DO_LDST(LDRB, load, MO_UB)
8755 DO_LDST(LDRH, load, MO_UW)
8756 DO_LDST(LDRSB, load, MO_SB)
8757 DO_LDST(LDRSH, load, MO_SW)
8759 DO_LDST(STR, store, MO_UL)
8760 DO_LDST(STRB, store, MO_UB)
8761 DO_LDST(STRH, store, MO_UW)
8763 #undef DO_LDST
8766 * Synchronization primitives
8769 static bool op_swp(DisasContext *s, arg_SWP *a, MemOp opc)
8771 TCGv_i32 addr, tmp;
8772 TCGv taddr;
8774 opc |= s->be_data;
8775 addr = load_reg(s, a->rn);
8776 taddr = gen_aa32_addr(s, addr, opc);
8777 tcg_temp_free_i32(addr);
8779 tmp = load_reg(s, a->rt2);
8780 tcg_gen_atomic_xchg_i32(tmp, taddr, tmp, get_mem_index(s), opc);
8781 tcg_temp_free(taddr);
8783 store_reg(s, a->rt, tmp);
8784 return true;
8787 static bool trans_SWP(DisasContext *s, arg_SWP *a)
8789 return op_swp(s, a, MO_UL | MO_ALIGN);
8792 static bool trans_SWPB(DisasContext *s, arg_SWP *a)
8794 return op_swp(s, a, MO_UB);
8798 * Load/Store Exclusive and Load-Acquire/Store-Release
8801 static bool op_strex(DisasContext *s, arg_STREX *a, MemOp mop, bool rel)
8803 TCGv_i32 addr;
8804 /* Some cases stopped being UNPREDICTABLE in v8A (but not v8M) */
8805 bool v8a = ENABLE_ARCH_8 && !arm_dc_feature(s, ARM_FEATURE_M);
8807 /* We UNDEF for these UNPREDICTABLE cases. */
8808 if (a->rd == 15 || a->rn == 15 || a->rt == 15
8809 || a->rd == a->rn || a->rd == a->rt
8810 || (!v8a && s->thumb && (a->rd == 13 || a->rt == 13))
8811 || (mop == MO_64
8812 && (a->rt2 == 15
8813 || a->rd == a->rt2
8814 || (!v8a && s->thumb && a->rt2 == 13)))) {
8815 unallocated_encoding(s);
8816 return true;
8819 if (rel) {
8820 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
8823 addr = tcg_temp_local_new_i32();
8824 load_reg_var(s, addr, a->rn);
8825 tcg_gen_addi_i32(addr, addr, a->imm);
8827 gen_store_exclusive(s, a->rd, a->rt, a->rt2, addr, mop);
8828 tcg_temp_free_i32(addr);
8829 return true;
8832 static bool trans_STREX(DisasContext *s, arg_STREX *a)
8834 if (!ENABLE_ARCH_6) {
8835 return false;
8837 return op_strex(s, a, MO_32, false);
8840 static bool trans_STREXD_a32(DisasContext *s, arg_STREX *a)
8842 if (!ENABLE_ARCH_6K) {
8843 return false;
8845 /* We UNDEF for these UNPREDICTABLE cases. */
8846 if (a->rt & 1) {
8847 unallocated_encoding(s);
8848 return true;
8850 a->rt2 = a->rt + 1;
8851 return op_strex(s, a, MO_64, false);
8854 static bool trans_STREXD_t32(DisasContext *s, arg_STREX *a)
8856 return op_strex(s, a, MO_64, false);
8859 static bool trans_STREXB(DisasContext *s, arg_STREX *a)
8861 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
8862 return false;
8864 return op_strex(s, a, MO_8, false);
8867 static bool trans_STREXH(DisasContext *s, arg_STREX *a)
8869 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
8870 return false;
8872 return op_strex(s, a, MO_16, false);
8875 static bool trans_STLEX(DisasContext *s, arg_STREX *a)
8877 if (!ENABLE_ARCH_8) {
8878 return false;
8880 return op_strex(s, a, MO_32, true);
8883 static bool trans_STLEXD_a32(DisasContext *s, arg_STREX *a)
8885 if (!ENABLE_ARCH_8) {
8886 return false;
8888 /* We UNDEF for these UNPREDICTABLE cases. */
8889 if (a->rt & 1) {
8890 unallocated_encoding(s);
8891 return true;
8893 a->rt2 = a->rt + 1;
8894 return op_strex(s, a, MO_64, true);
8897 static bool trans_STLEXD_t32(DisasContext *s, arg_STREX *a)
8899 if (!ENABLE_ARCH_8) {
8900 return false;
8902 return op_strex(s, a, MO_64, true);
8905 static bool trans_STLEXB(DisasContext *s, arg_STREX *a)
8907 if (!ENABLE_ARCH_8) {
8908 return false;
8910 return op_strex(s, a, MO_8, true);
8913 static bool trans_STLEXH(DisasContext *s, arg_STREX *a)
8915 if (!ENABLE_ARCH_8) {
8916 return false;
8918 return op_strex(s, a, MO_16, true);
8921 static bool op_stl(DisasContext *s, arg_STL *a, MemOp mop)
8923 TCGv_i32 addr, tmp;
8925 if (!ENABLE_ARCH_8) {
8926 return false;
8928 /* We UNDEF for these UNPREDICTABLE cases. */
8929 if (a->rn == 15 || a->rt == 15) {
8930 unallocated_encoding(s);
8931 return true;
8934 addr = load_reg(s, a->rn);
8935 tmp = load_reg(s, a->rt);
8936 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
8937 gen_aa32_st_i32(s, tmp, addr, get_mem_index(s), mop | s->be_data);
8938 disas_set_da_iss(s, mop, a->rt | ISSIsAcqRel | ISSIsWrite);
8940 tcg_temp_free_i32(tmp);
8941 tcg_temp_free_i32(addr);
8942 return true;
8945 static bool trans_STL(DisasContext *s, arg_STL *a)
8947 return op_stl(s, a, MO_UL);
8950 static bool trans_STLB(DisasContext *s, arg_STL *a)
8952 return op_stl(s, a, MO_UB);
8955 static bool trans_STLH(DisasContext *s, arg_STL *a)
8957 return op_stl(s, a, MO_UW);
8960 static bool op_ldrex(DisasContext *s, arg_LDREX *a, MemOp mop, bool acq)
8962 TCGv_i32 addr;
8963 /* Some cases stopped being UNPREDICTABLE in v8A (but not v8M) */
8964 bool v8a = ENABLE_ARCH_8 && !arm_dc_feature(s, ARM_FEATURE_M);
8966 /* We UNDEF for these UNPREDICTABLE cases. */
8967 if (a->rn == 15 || a->rt == 15
8968 || (!v8a && s->thumb && a->rt == 13)
8969 || (mop == MO_64
8970 && (a->rt2 == 15 || a->rt == a->rt2
8971 || (!v8a && s->thumb && a->rt2 == 13)))) {
8972 unallocated_encoding(s);
8973 return true;
8976 addr = tcg_temp_local_new_i32();
8977 load_reg_var(s, addr, a->rn);
8978 tcg_gen_addi_i32(addr, addr, a->imm);
8980 gen_load_exclusive(s, a->rt, a->rt2, addr, mop);
8981 tcg_temp_free_i32(addr);
8983 if (acq) {
8984 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
8986 return true;
8989 static bool trans_LDREX(DisasContext *s, arg_LDREX *a)
8991 if (!ENABLE_ARCH_6) {
8992 return false;
8994 return op_ldrex(s, a, MO_32, false);
8997 static bool trans_LDREXD_a32(DisasContext *s, arg_LDREX *a)
8999 if (!ENABLE_ARCH_6K) {
9000 return false;
9002 /* We UNDEF for these UNPREDICTABLE cases. */
9003 if (a->rt & 1) {
9004 unallocated_encoding(s);
9005 return true;
9007 a->rt2 = a->rt + 1;
9008 return op_ldrex(s, a, MO_64, false);
9011 static bool trans_LDREXD_t32(DisasContext *s, arg_LDREX *a)
9013 return op_ldrex(s, a, MO_64, false);
9016 static bool trans_LDREXB(DisasContext *s, arg_LDREX *a)
9018 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
9019 return false;
9021 return op_ldrex(s, a, MO_8, false);
9024 static bool trans_LDREXH(DisasContext *s, arg_LDREX *a)
9026 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
9027 return false;
9029 return op_ldrex(s, a, MO_16, false);
9032 static bool trans_LDAEX(DisasContext *s, arg_LDREX *a)
9034 if (!ENABLE_ARCH_8) {
9035 return false;
9037 return op_ldrex(s, a, MO_32, true);
9040 static bool trans_LDAEXD_a32(DisasContext *s, arg_LDREX *a)
9042 if (!ENABLE_ARCH_8) {
9043 return false;
9045 /* We UNDEF for these UNPREDICTABLE cases. */
9046 if (a->rt & 1) {
9047 unallocated_encoding(s);
9048 return true;
9050 a->rt2 = a->rt + 1;
9051 return op_ldrex(s, a, MO_64, true);
9054 static bool trans_LDAEXD_t32(DisasContext *s, arg_LDREX *a)
9056 if (!ENABLE_ARCH_8) {
9057 return false;
9059 return op_ldrex(s, a, MO_64, true);
9062 static bool trans_LDAEXB(DisasContext *s, arg_LDREX *a)
9064 if (!ENABLE_ARCH_8) {
9065 return false;
9067 return op_ldrex(s, a, MO_8, true);
9070 static bool trans_LDAEXH(DisasContext *s, arg_LDREX *a)
9072 if (!ENABLE_ARCH_8) {
9073 return false;
9075 return op_ldrex(s, a, MO_16, true);
9078 static bool op_lda(DisasContext *s, arg_LDA *a, MemOp mop)
9080 TCGv_i32 addr, tmp;
9082 if (!ENABLE_ARCH_8) {
9083 return false;
9085 /* We UNDEF for these UNPREDICTABLE cases. */
9086 if (a->rn == 15 || a->rt == 15) {
9087 unallocated_encoding(s);
9088 return true;
9091 addr = load_reg(s, a->rn);
9092 tmp = tcg_temp_new_i32();
9093 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), mop | s->be_data);
9094 disas_set_da_iss(s, mop, a->rt | ISSIsAcqRel);
9095 tcg_temp_free_i32(addr);
9097 store_reg(s, a->rt, tmp);
9098 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
9099 return true;
9102 static bool trans_LDA(DisasContext *s, arg_LDA *a)
9104 return op_lda(s, a, MO_UL);
9107 static bool trans_LDAB(DisasContext *s, arg_LDA *a)
9109 return op_lda(s, a, MO_UB);
9112 static bool trans_LDAH(DisasContext *s, arg_LDA *a)
9114 return op_lda(s, a, MO_UW);
9118 * Media instructions
9121 static bool trans_USADA8(DisasContext *s, arg_USADA8 *a)
9123 TCGv_i32 t1, t2;
9125 if (!ENABLE_ARCH_6) {
9126 return false;
9129 t1 = load_reg(s, a->rn);
9130 t2 = load_reg(s, a->rm);
9131 gen_helper_usad8(t1, t1, t2);
9132 tcg_temp_free_i32(t2);
9133 if (a->ra != 15) {
9134 t2 = load_reg(s, a->ra);
9135 tcg_gen_add_i32(t1, t1, t2);
9136 tcg_temp_free_i32(t2);
9138 store_reg(s, a->rd, t1);
9139 return true;
9142 static bool op_bfx(DisasContext *s, arg_UBFX *a, bool u)
9144 TCGv_i32 tmp;
9145 int width = a->widthm1 + 1;
9146 int shift = a->lsb;
9148 if (!ENABLE_ARCH_6T2) {
9149 return false;
9151 if (shift + width > 32) {
9152 /* UNPREDICTABLE; we choose to UNDEF */
9153 unallocated_encoding(s);
9154 return true;
9157 tmp = load_reg(s, a->rn);
9158 if (u) {
9159 tcg_gen_extract_i32(tmp, tmp, shift, width);
9160 } else {
9161 tcg_gen_sextract_i32(tmp, tmp, shift, width);
9163 store_reg(s, a->rd, tmp);
9164 return true;
9167 static bool trans_SBFX(DisasContext *s, arg_SBFX *a)
9169 return op_bfx(s, a, false);
9172 static bool trans_UBFX(DisasContext *s, arg_UBFX *a)
9174 return op_bfx(s, a, true);
9177 static bool trans_BFCI(DisasContext *s, arg_BFCI *a)
9179 TCGv_i32 tmp;
9180 int msb = a->msb, lsb = a->lsb;
9181 int width;
9183 if (!ENABLE_ARCH_6T2) {
9184 return false;
9186 if (msb < lsb) {
9187 /* UNPREDICTABLE; we choose to UNDEF */
9188 unallocated_encoding(s);
9189 return true;
9192 width = msb + 1 - lsb;
9193 if (a->rn == 15) {
9194 /* BFC */
9195 tmp = tcg_const_i32(0);
9196 } else {
9197 /* BFI */
9198 tmp = load_reg(s, a->rn);
9200 if (width != 32) {
9201 TCGv_i32 tmp2 = load_reg(s, a->rd);
9202 tcg_gen_deposit_i32(tmp, tmp2, tmp, lsb, width);
9203 tcg_temp_free_i32(tmp2);
9205 store_reg(s, a->rd, tmp);
9206 return true;
9209 static bool trans_UDF(DisasContext *s, arg_UDF *a)
9211 unallocated_encoding(s);
9212 return true;
9216 * Parallel addition and subtraction
9219 static bool op_par_addsub(DisasContext *s, arg_rrr *a,
9220 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32))
9222 TCGv_i32 t0, t1;
9224 if (s->thumb
9225 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
9226 : !ENABLE_ARCH_6) {
9227 return false;
9230 t0 = load_reg(s, a->rn);
9231 t1 = load_reg(s, a->rm);
9233 gen(t0, t0, t1);
9235 tcg_temp_free_i32(t1);
9236 store_reg(s, a->rd, t0);
9237 return true;
9240 static bool op_par_addsub_ge(DisasContext *s, arg_rrr *a,
9241 void (*gen)(TCGv_i32, TCGv_i32,
9242 TCGv_i32, TCGv_ptr))
9244 TCGv_i32 t0, t1;
9245 TCGv_ptr ge;
9247 if (s->thumb
9248 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
9249 : !ENABLE_ARCH_6) {
9250 return false;
9253 t0 = load_reg(s, a->rn);
9254 t1 = load_reg(s, a->rm);
9256 ge = tcg_temp_new_ptr();
9257 tcg_gen_addi_ptr(ge, cpu_env, offsetof(CPUARMState, GE));
9258 gen(t0, t0, t1, ge);
9260 tcg_temp_free_ptr(ge);
9261 tcg_temp_free_i32(t1);
9262 store_reg(s, a->rd, t0);
9263 return true;
9266 #define DO_PAR_ADDSUB(NAME, helper) \
9267 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
9269 return op_par_addsub(s, a, helper); \
9272 #define DO_PAR_ADDSUB_GE(NAME, helper) \
9273 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
9275 return op_par_addsub_ge(s, a, helper); \
9278 DO_PAR_ADDSUB_GE(SADD16, gen_helper_sadd16)
9279 DO_PAR_ADDSUB_GE(SASX, gen_helper_saddsubx)
9280 DO_PAR_ADDSUB_GE(SSAX, gen_helper_ssubaddx)
9281 DO_PAR_ADDSUB_GE(SSUB16, gen_helper_ssub16)
9282 DO_PAR_ADDSUB_GE(SADD8, gen_helper_sadd8)
9283 DO_PAR_ADDSUB_GE(SSUB8, gen_helper_ssub8)
9285 DO_PAR_ADDSUB_GE(UADD16, gen_helper_uadd16)
9286 DO_PAR_ADDSUB_GE(UASX, gen_helper_uaddsubx)
9287 DO_PAR_ADDSUB_GE(USAX, gen_helper_usubaddx)
9288 DO_PAR_ADDSUB_GE(USUB16, gen_helper_usub16)
9289 DO_PAR_ADDSUB_GE(UADD8, gen_helper_uadd8)
9290 DO_PAR_ADDSUB_GE(USUB8, gen_helper_usub8)
9292 DO_PAR_ADDSUB(QADD16, gen_helper_qadd16)
9293 DO_PAR_ADDSUB(QASX, gen_helper_qaddsubx)
9294 DO_PAR_ADDSUB(QSAX, gen_helper_qsubaddx)
9295 DO_PAR_ADDSUB(QSUB16, gen_helper_qsub16)
9296 DO_PAR_ADDSUB(QADD8, gen_helper_qadd8)
9297 DO_PAR_ADDSUB(QSUB8, gen_helper_qsub8)
9299 DO_PAR_ADDSUB(UQADD16, gen_helper_uqadd16)
9300 DO_PAR_ADDSUB(UQASX, gen_helper_uqaddsubx)
9301 DO_PAR_ADDSUB(UQSAX, gen_helper_uqsubaddx)
9302 DO_PAR_ADDSUB(UQSUB16, gen_helper_uqsub16)
9303 DO_PAR_ADDSUB(UQADD8, gen_helper_uqadd8)
9304 DO_PAR_ADDSUB(UQSUB8, gen_helper_uqsub8)
9306 DO_PAR_ADDSUB(SHADD16, gen_helper_shadd16)
9307 DO_PAR_ADDSUB(SHASX, gen_helper_shaddsubx)
9308 DO_PAR_ADDSUB(SHSAX, gen_helper_shsubaddx)
9309 DO_PAR_ADDSUB(SHSUB16, gen_helper_shsub16)
9310 DO_PAR_ADDSUB(SHADD8, gen_helper_shadd8)
9311 DO_PAR_ADDSUB(SHSUB8, gen_helper_shsub8)
9313 DO_PAR_ADDSUB(UHADD16, gen_helper_uhadd16)
9314 DO_PAR_ADDSUB(UHASX, gen_helper_uhaddsubx)
9315 DO_PAR_ADDSUB(UHSAX, gen_helper_uhsubaddx)
9316 DO_PAR_ADDSUB(UHSUB16, gen_helper_uhsub16)
9317 DO_PAR_ADDSUB(UHADD8, gen_helper_uhadd8)
9318 DO_PAR_ADDSUB(UHSUB8, gen_helper_uhsub8)
9320 #undef DO_PAR_ADDSUB
9321 #undef DO_PAR_ADDSUB_GE
9324 * Packing, unpacking, saturation, and reversal
9327 static bool trans_PKH(DisasContext *s, arg_PKH *a)
9329 TCGv_i32 tn, tm;
9330 int shift = a->imm;
9332 if (s->thumb
9333 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
9334 : !ENABLE_ARCH_6) {
9335 return false;
9338 tn = load_reg(s, a->rn);
9339 tm = load_reg(s, a->rm);
9340 if (a->tb) {
9341 /* PKHTB */
9342 if (shift == 0) {
9343 shift = 31;
9345 tcg_gen_sari_i32(tm, tm, shift);
9346 tcg_gen_deposit_i32(tn, tn, tm, 0, 16);
9347 } else {
9348 /* PKHBT */
9349 tcg_gen_shli_i32(tm, tm, shift);
9350 tcg_gen_deposit_i32(tn, tm, tn, 0, 16);
9352 tcg_temp_free_i32(tm);
9353 store_reg(s, a->rd, tn);
9354 return true;
9357 static bool op_sat(DisasContext *s, arg_sat *a,
9358 void (*gen)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32))
9360 TCGv_i32 tmp, satimm;
9361 int shift = a->imm;
9363 if (!ENABLE_ARCH_6) {
9364 return false;
9367 tmp = load_reg(s, a->rn);
9368 if (a->sh) {
9369 tcg_gen_sari_i32(tmp, tmp, shift ? shift : 31);
9370 } else {
9371 tcg_gen_shli_i32(tmp, tmp, shift);
9374 satimm = tcg_const_i32(a->satimm);
9375 gen(tmp, cpu_env, tmp, satimm);
9376 tcg_temp_free_i32(satimm);
9378 store_reg(s, a->rd, tmp);
9379 return true;
9382 static bool trans_SSAT(DisasContext *s, arg_sat *a)
9384 return op_sat(s, a, gen_helper_ssat);
9387 static bool trans_USAT(DisasContext *s, arg_sat *a)
9389 return op_sat(s, a, gen_helper_usat);
9392 static bool trans_SSAT16(DisasContext *s, arg_sat *a)
9394 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9395 return false;
9397 return op_sat(s, a, gen_helper_ssat16);
9400 static bool trans_USAT16(DisasContext *s, arg_sat *a)
9402 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9403 return false;
9405 return op_sat(s, a, gen_helper_usat16);
9408 static bool op_xta(DisasContext *s, arg_rrr_rot *a,
9409 void (*gen_extract)(TCGv_i32, TCGv_i32),
9410 void (*gen_add)(TCGv_i32, TCGv_i32, TCGv_i32))
9412 TCGv_i32 tmp;
9414 if (!ENABLE_ARCH_6) {
9415 return false;
9418 tmp = load_reg(s, a->rm);
9420 * TODO: In many cases we could do a shift instead of a rotate.
9421 * Combined with a simple extend, that becomes an extract.
9423 tcg_gen_rotri_i32(tmp, tmp, a->rot * 8);
9424 gen_extract(tmp, tmp);
9426 if (a->rn != 15) {
9427 TCGv_i32 tmp2 = load_reg(s, a->rn);
9428 gen_add(tmp, tmp, tmp2);
9429 tcg_temp_free_i32(tmp2);
9431 store_reg(s, a->rd, tmp);
9432 return true;
9435 static bool trans_SXTAB(DisasContext *s, arg_rrr_rot *a)
9437 return op_xta(s, a, tcg_gen_ext8s_i32, tcg_gen_add_i32);
9440 static bool trans_SXTAH(DisasContext *s, arg_rrr_rot *a)
9442 return op_xta(s, a, tcg_gen_ext16s_i32, tcg_gen_add_i32);
9445 static bool trans_SXTAB16(DisasContext *s, arg_rrr_rot *a)
9447 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9448 return false;
9450 return op_xta(s, a, gen_helper_sxtb16, gen_add16);
9453 static bool trans_UXTAB(DisasContext *s, arg_rrr_rot *a)
9455 return op_xta(s, a, tcg_gen_ext8u_i32, tcg_gen_add_i32);
9458 static bool trans_UXTAH(DisasContext *s, arg_rrr_rot *a)
9460 return op_xta(s, a, tcg_gen_ext16u_i32, tcg_gen_add_i32);
9463 static bool trans_UXTAB16(DisasContext *s, arg_rrr_rot *a)
9465 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
9466 return false;
9468 return op_xta(s, a, gen_helper_uxtb16, gen_add16);
9471 static bool trans_SEL(DisasContext *s, arg_rrr *a)
9473 TCGv_i32 t1, t2, t3;
9475 if (s->thumb
9476 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
9477 : !ENABLE_ARCH_6) {
9478 return false;
9481 t1 = load_reg(s, a->rn);
9482 t2 = load_reg(s, a->rm);
9483 t3 = tcg_temp_new_i32();
9484 tcg_gen_ld_i32(t3, cpu_env, offsetof(CPUARMState, GE));
9485 gen_helper_sel_flags(t1, t3, t1, t2);
9486 tcg_temp_free_i32(t3);
9487 tcg_temp_free_i32(t2);
9488 store_reg(s, a->rd, t1);
9489 return true;
9492 static bool op_rr(DisasContext *s, arg_rr *a,
9493 void (*gen)(TCGv_i32, TCGv_i32))
9495 TCGv_i32 tmp;
9497 tmp = load_reg(s, a->rm);
9498 gen(tmp, tmp);
9499 store_reg(s, a->rd, tmp);
9500 return true;
9503 static bool trans_REV(DisasContext *s, arg_rr *a)
9505 if (!ENABLE_ARCH_6) {
9506 return false;
9508 return op_rr(s, a, tcg_gen_bswap32_i32);
9511 static bool trans_REV16(DisasContext *s, arg_rr *a)
9513 if (!ENABLE_ARCH_6) {
9514 return false;
9516 return op_rr(s, a, gen_rev16);
9519 static bool trans_REVSH(DisasContext *s, arg_rr *a)
9521 if (!ENABLE_ARCH_6) {
9522 return false;
9524 return op_rr(s, a, gen_revsh);
9527 static bool trans_RBIT(DisasContext *s, arg_rr *a)
9529 if (!ENABLE_ARCH_6T2) {
9530 return false;
9532 return op_rr(s, a, gen_helper_rbit);
9536 * Signed multiply, signed and unsigned divide
9539 static bool op_smlad(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
9541 TCGv_i32 t1, t2;
9543 if (!ENABLE_ARCH_6) {
9544 return false;
9547 t1 = load_reg(s, a->rn);
9548 t2 = load_reg(s, a->rm);
9549 if (m_swap) {
9550 gen_swap_half(t2);
9552 gen_smul_dual(t1, t2);
9554 if (sub) {
9555 /* This subtraction cannot overflow. */
9556 tcg_gen_sub_i32(t1, t1, t2);
9557 } else {
9559 * This addition cannot overflow 32 bits; however it may
9560 * overflow considered as a signed operation, in which case
9561 * we must set the Q flag.
9563 gen_helper_add_setq(t1, cpu_env, t1, t2);
9565 tcg_temp_free_i32(t2);
9567 if (a->ra != 15) {
9568 t2 = load_reg(s, a->ra);
9569 gen_helper_add_setq(t1, cpu_env, t1, t2);
9570 tcg_temp_free_i32(t2);
9572 store_reg(s, a->rd, t1);
9573 return true;
9576 static bool trans_SMLAD(DisasContext *s, arg_rrrr *a)
9578 return op_smlad(s, a, false, false);
9581 static bool trans_SMLADX(DisasContext *s, arg_rrrr *a)
9583 return op_smlad(s, a, true, false);
9586 static bool trans_SMLSD(DisasContext *s, arg_rrrr *a)
9588 return op_smlad(s, a, false, true);
9591 static bool trans_SMLSDX(DisasContext *s, arg_rrrr *a)
9593 return op_smlad(s, a, true, true);
9596 static bool op_smlald(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
9598 TCGv_i32 t1, t2;
9599 TCGv_i64 l1, l2;
9601 if (!ENABLE_ARCH_6) {
9602 return false;
9605 t1 = load_reg(s, a->rn);
9606 t2 = load_reg(s, a->rm);
9607 if (m_swap) {
9608 gen_swap_half(t2);
9610 gen_smul_dual(t1, t2);
9612 l1 = tcg_temp_new_i64();
9613 l2 = tcg_temp_new_i64();
9614 tcg_gen_ext_i32_i64(l1, t1);
9615 tcg_gen_ext_i32_i64(l2, t2);
9616 tcg_temp_free_i32(t1);
9617 tcg_temp_free_i32(t2);
9619 if (sub) {
9620 tcg_gen_sub_i64(l1, l1, l2);
9621 } else {
9622 tcg_gen_add_i64(l1, l1, l2);
9624 tcg_temp_free_i64(l2);
9626 gen_addq(s, l1, a->ra, a->rd);
9627 gen_storeq_reg(s, a->ra, a->rd, l1);
9628 tcg_temp_free_i64(l1);
9629 return true;
9632 static bool trans_SMLALD(DisasContext *s, arg_rrrr *a)
9634 return op_smlald(s, a, false, false);
9637 static bool trans_SMLALDX(DisasContext *s, arg_rrrr *a)
9639 return op_smlald(s, a, true, false);
9642 static bool trans_SMLSLD(DisasContext *s, arg_rrrr *a)
9644 return op_smlald(s, a, false, true);
9647 static bool trans_SMLSLDX(DisasContext *s, arg_rrrr *a)
9649 return op_smlald(s, a, true, true);
9652 static bool op_smmla(DisasContext *s, arg_rrrr *a, bool round, bool sub)
9654 TCGv_i32 t1, t2;
9656 if (s->thumb
9657 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
9658 : !ENABLE_ARCH_6) {
9659 return false;
9662 t1 = load_reg(s, a->rn);
9663 t2 = load_reg(s, a->rm);
9664 tcg_gen_muls2_i32(t2, t1, t1, t2);
9666 if (a->ra != 15) {
9667 TCGv_i32 t3 = load_reg(s, a->ra);
9668 if (sub) {
9670 * For SMMLS, we need a 64-bit subtract. Borrow caused by
9671 * a non-zero multiplicand lowpart, and the correct result
9672 * lowpart for rounding.
9674 TCGv_i32 zero = tcg_const_i32(0);
9675 tcg_gen_sub2_i32(t2, t1, zero, t3, t2, t1);
9676 tcg_temp_free_i32(zero);
9677 } else {
9678 tcg_gen_add_i32(t1, t1, t3);
9680 tcg_temp_free_i32(t3);
9682 if (round) {
9684 * Adding 0x80000000 to the 64-bit quantity means that we have
9685 * carry in to the high word when the low word has the msb set.
9687 tcg_gen_shri_i32(t2, t2, 31);
9688 tcg_gen_add_i32(t1, t1, t2);
9690 tcg_temp_free_i32(t2);
9691 store_reg(s, a->rd, t1);
9692 return true;
9695 static bool trans_SMMLA(DisasContext *s, arg_rrrr *a)
9697 return op_smmla(s, a, false, false);
9700 static bool trans_SMMLAR(DisasContext *s, arg_rrrr *a)
9702 return op_smmla(s, a, true, false);
9705 static bool trans_SMMLS(DisasContext *s, arg_rrrr *a)
9707 return op_smmla(s, a, false, true);
9710 static bool trans_SMMLSR(DisasContext *s, arg_rrrr *a)
9712 return op_smmla(s, a, true, true);
9715 static bool op_div(DisasContext *s, arg_rrr *a, bool u)
9717 TCGv_i32 t1, t2;
9719 if (s->thumb
9720 ? !dc_isar_feature(aa32_thumb_div, s)
9721 : !dc_isar_feature(aa32_arm_div, s)) {
9722 return false;
9725 t1 = load_reg(s, a->rn);
9726 t2 = load_reg(s, a->rm);
9727 if (u) {
9728 gen_helper_udiv(t1, t1, t2);
9729 } else {
9730 gen_helper_sdiv(t1, t1, t2);
9732 tcg_temp_free_i32(t2);
9733 store_reg(s, a->rd, t1);
9734 return true;
9737 static bool trans_SDIV(DisasContext *s, arg_rrr *a)
9739 return op_div(s, a, false);
9742 static bool trans_UDIV(DisasContext *s, arg_rrr *a)
9744 return op_div(s, a, true);
9748 * Block data transfer
9751 static TCGv_i32 op_addr_block_pre(DisasContext *s, arg_ldst_block *a, int n)
9753 TCGv_i32 addr = load_reg(s, a->rn);
9755 if (a->b) {
9756 if (a->i) {
9757 /* pre increment */
9758 tcg_gen_addi_i32(addr, addr, 4);
9759 } else {
9760 /* pre decrement */
9761 tcg_gen_addi_i32(addr, addr, -(n * 4));
9763 } else if (!a->i && n != 1) {
9764 /* post decrement */
9765 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
9768 if (s->v8m_stackcheck && a->rn == 13 && a->w) {
9770 * If the writeback is incrementing SP rather than
9771 * decrementing it, and the initial SP is below the
9772 * stack limit but the final written-back SP would
9773 * be above, then then we must not perform any memory
9774 * accesses, but it is IMPDEF whether we generate
9775 * an exception. We choose to do so in this case.
9776 * At this point 'addr' is the lowest address, so
9777 * either the original SP (if incrementing) or our
9778 * final SP (if decrementing), so that's what we check.
9780 gen_helper_v8m_stackcheck(cpu_env, addr);
9783 return addr;
9786 static void op_addr_block_post(DisasContext *s, arg_ldst_block *a,
9787 TCGv_i32 addr, int n)
9789 if (a->w) {
9790 /* write back */
9791 if (!a->b) {
9792 if (a->i) {
9793 /* post increment */
9794 tcg_gen_addi_i32(addr, addr, 4);
9795 } else {
9796 /* post decrement */
9797 tcg_gen_addi_i32(addr, addr, -(n * 4));
9799 } else if (!a->i && n != 1) {
9800 /* pre decrement */
9801 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
9803 store_reg(s, a->rn, addr);
9804 } else {
9805 tcg_temp_free_i32(addr);
9809 static bool op_stm(DisasContext *s, arg_ldst_block *a, int min_n)
9811 int i, j, n, list, mem_idx;
9812 bool user = a->u;
9813 TCGv_i32 addr, tmp, tmp2;
9815 if (user) {
9816 /* STM (user) */
9817 if (IS_USER(s)) {
9818 /* Only usable in supervisor mode. */
9819 unallocated_encoding(s);
9820 return true;
9824 list = a->list;
9825 n = ctpop16(list);
9826 if (n < min_n || a->rn == 15) {
9827 unallocated_encoding(s);
9828 return true;
9831 addr = op_addr_block_pre(s, a, n);
9832 mem_idx = get_mem_index(s);
9834 for (i = j = 0; i < 16; i++) {
9835 if (!(list & (1 << i))) {
9836 continue;
9839 if (user && i != 15) {
9840 tmp = tcg_temp_new_i32();
9841 tmp2 = tcg_const_i32(i);
9842 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
9843 tcg_temp_free_i32(tmp2);
9844 } else {
9845 tmp = load_reg(s, i);
9847 gen_aa32_st32(s, tmp, addr, mem_idx);
9848 tcg_temp_free_i32(tmp);
9850 /* No need to add after the last transfer. */
9851 if (++j != n) {
9852 tcg_gen_addi_i32(addr, addr, 4);
9856 op_addr_block_post(s, a, addr, n);
9857 return true;
9860 static bool trans_STM(DisasContext *s, arg_ldst_block *a)
9862 /* BitCount(list) < 1 is UNPREDICTABLE */
9863 return op_stm(s, a, 1);
9866 static bool trans_STM_t32(DisasContext *s, arg_ldst_block *a)
9868 /* Writeback register in register list is UNPREDICTABLE for T32. */
9869 if (a->w && (a->list & (1 << a->rn))) {
9870 unallocated_encoding(s);
9871 return true;
9873 /* BitCount(list) < 2 is UNPREDICTABLE */
9874 return op_stm(s, a, 2);
9877 static bool do_ldm(DisasContext *s, arg_ldst_block *a, int min_n)
9879 int i, j, n, list, mem_idx;
9880 bool loaded_base;
9881 bool user = a->u;
9882 bool exc_return = false;
9883 TCGv_i32 addr, tmp, tmp2, loaded_var;
9885 if (user) {
9886 /* LDM (user), LDM (exception return) */
9887 if (IS_USER(s)) {
9888 /* Only usable in supervisor mode. */
9889 unallocated_encoding(s);
9890 return true;
9892 if (extract32(a->list, 15, 1)) {
9893 exc_return = true;
9894 user = false;
9895 } else {
9896 /* LDM (user) does not allow writeback. */
9897 if (a->w) {
9898 unallocated_encoding(s);
9899 return true;
9904 list = a->list;
9905 n = ctpop16(list);
9906 if (n < min_n || a->rn == 15) {
9907 unallocated_encoding(s);
9908 return true;
9911 addr = op_addr_block_pre(s, a, n);
9912 mem_idx = get_mem_index(s);
9913 loaded_base = false;
9914 loaded_var = NULL;
9916 for (i = j = 0; i < 16; i++) {
9917 if (!(list & (1 << i))) {
9918 continue;
9921 tmp = tcg_temp_new_i32();
9922 gen_aa32_ld32u(s, tmp, addr, mem_idx);
9923 if (user) {
9924 tmp2 = tcg_const_i32(i);
9925 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
9926 tcg_temp_free_i32(tmp2);
9927 tcg_temp_free_i32(tmp);
9928 } else if (i == a->rn) {
9929 loaded_var = tmp;
9930 loaded_base = true;
9931 } else if (i == 15 && exc_return) {
9932 store_pc_exc_ret(s, tmp);
9933 } else {
9934 store_reg_from_load(s, i, tmp);
9937 /* No need to add after the last transfer. */
9938 if (++j != n) {
9939 tcg_gen_addi_i32(addr, addr, 4);
9943 op_addr_block_post(s, a, addr, n);
9945 if (loaded_base) {
9946 /* Note that we reject base == pc above. */
9947 store_reg(s, a->rn, loaded_var);
9950 if (exc_return) {
9951 /* Restore CPSR from SPSR. */
9952 tmp = load_cpu_field(spsr);
9953 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
9954 gen_io_start();
9956 gen_helper_cpsr_write_eret(cpu_env, tmp);
9957 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
9958 gen_io_end();
9960 tcg_temp_free_i32(tmp);
9961 /* Must exit loop to check un-masked IRQs */
9962 s->base.is_jmp = DISAS_EXIT;
9964 return true;
9967 static bool trans_LDM_a32(DisasContext *s, arg_ldst_block *a)
9970 * Writeback register in register list is UNPREDICTABLE
9971 * for ArchVersion() >= 7. Prior to v7, A32 would write
9972 * an UNKNOWN value to the base register.
9974 if (ENABLE_ARCH_7 && a->w && (a->list & (1 << a->rn))) {
9975 unallocated_encoding(s);
9976 return true;
9978 /* BitCount(list) < 1 is UNPREDICTABLE */
9979 return do_ldm(s, a, 1);
9982 static bool trans_LDM_t32(DisasContext *s, arg_ldst_block *a)
9984 /* Writeback register in register list is UNPREDICTABLE for T32. */
9985 if (a->w && (a->list & (1 << a->rn))) {
9986 unallocated_encoding(s);
9987 return true;
9989 /* BitCount(list) < 2 is UNPREDICTABLE */
9990 return do_ldm(s, a, 2);
9993 static bool trans_LDM_t16(DisasContext *s, arg_ldst_block *a)
9995 /* Writeback is conditional on the base register not being loaded. */
9996 a->w = !(a->list & (1 << a->rn));
9997 /* BitCount(list) < 1 is UNPREDICTABLE */
9998 return do_ldm(s, a, 1);
10002 * Branch, branch with link
10005 static bool trans_B(DisasContext *s, arg_i *a)
10007 gen_jmp(s, read_pc(s) + a->imm);
10008 return true;
10011 static bool trans_B_cond_thumb(DisasContext *s, arg_ci *a)
10013 /* This has cond from encoding, required to be outside IT block. */
10014 if (a->cond >= 0xe) {
10015 return false;
10017 if (s->condexec_mask) {
10018 unallocated_encoding(s);
10019 return true;
10021 arm_skip_unless(s, a->cond);
10022 gen_jmp(s, read_pc(s) + a->imm);
10023 return true;
10026 static bool trans_BL(DisasContext *s, arg_i *a)
10028 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
10029 gen_jmp(s, read_pc(s) + a->imm);
10030 return true;
10033 static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
10035 TCGv_i32 tmp;
10037 /* For A32, ARCH(5) is checked near the start of the uncond block. */
10038 if (s->thumb && (a->imm & 2)) {
10039 return false;
10041 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
10042 tmp = tcg_const_i32(!s->thumb);
10043 store_cpu_field(tmp, thumb);
10044 gen_jmp(s, (read_pc(s) & ~3) + a->imm);
10045 return true;
10048 static bool trans_BL_BLX_prefix(DisasContext *s, arg_BL_BLX_prefix *a)
10050 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
10051 tcg_gen_movi_i32(cpu_R[14], read_pc(s) + (a->imm << 12));
10052 return true;
10055 static bool trans_BL_suffix(DisasContext *s, arg_BL_suffix *a)
10057 TCGv_i32 tmp = tcg_temp_new_i32();
10059 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
10060 tcg_gen_addi_i32(tmp, cpu_R[14], (a->imm << 1) | 1);
10061 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | 1);
10062 gen_bx(s, tmp);
10063 return true;
10066 static bool trans_BLX_suffix(DisasContext *s, arg_BLX_suffix *a)
10068 TCGv_i32 tmp;
10070 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
10071 if (!ENABLE_ARCH_5) {
10072 return false;
10074 tmp = tcg_temp_new_i32();
10075 tcg_gen_addi_i32(tmp, cpu_R[14], a->imm << 1);
10076 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
10077 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | 1);
10078 gen_bx(s, tmp);
10079 return true;
10082 static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
10084 TCGv_i32 addr, tmp;
10086 tmp = load_reg(s, a->rm);
10087 if (half) {
10088 tcg_gen_add_i32(tmp, tmp, tmp);
10090 addr = load_reg(s, a->rn);
10091 tcg_gen_add_i32(addr, addr, tmp);
10093 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
10094 half ? MO_UW | s->be_data : MO_UB);
10095 tcg_temp_free_i32(addr);
10097 tcg_gen_add_i32(tmp, tmp, tmp);
10098 tcg_gen_addi_i32(tmp, tmp, read_pc(s));
10099 store_reg(s, 15, tmp);
10100 return true;
10103 static bool trans_TBB(DisasContext *s, arg_tbranch *a)
10105 return op_tbranch(s, a, false);
10108 static bool trans_TBH(DisasContext *s, arg_tbranch *a)
10110 return op_tbranch(s, a, true);
10113 static bool trans_CBZ(DisasContext *s, arg_CBZ *a)
10115 TCGv_i32 tmp = load_reg(s, a->rn);
10117 arm_gen_condlabel(s);
10118 tcg_gen_brcondi_i32(a->nz ? TCG_COND_EQ : TCG_COND_NE,
10119 tmp, 0, s->condlabel);
10120 tcg_temp_free_i32(tmp);
10121 gen_jmp(s, read_pc(s) + a->imm);
10122 return true;
10126 * Supervisor call - both T32 & A32 come here so we need to check
10127 * which mode we are in when checking for semihosting.
10130 static bool trans_SVC(DisasContext *s, arg_SVC *a)
10132 const uint32_t semihost_imm = s->thumb ? 0xab : 0x123456;
10134 if (!arm_dc_feature(s, ARM_FEATURE_M) && semihosting_enabled() &&
10135 #ifndef CONFIG_USER_ONLY
10136 !IS_USER(s) &&
10137 #endif
10138 (a->imm == semihost_imm)) {
10139 gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
10140 } else {
10141 gen_set_pc_im(s, s->base.pc_next);
10142 s->svc_imm = a->imm;
10143 s->base.is_jmp = DISAS_SWI;
10145 return true;
10149 * Unconditional system instructions
10152 static bool trans_RFE(DisasContext *s, arg_RFE *a)
10154 static const int8_t pre_offset[4] = {
10155 /* DA */ -4, /* IA */ 0, /* DB */ -8, /* IB */ 4
10157 static const int8_t post_offset[4] = {
10158 /* DA */ -8, /* IA */ 4, /* DB */ -4, /* IB */ 0
10160 TCGv_i32 addr, t1, t2;
10162 if (!ENABLE_ARCH_6 || arm_dc_feature(s, ARM_FEATURE_M)) {
10163 return false;
10165 if (IS_USER(s)) {
10166 unallocated_encoding(s);
10167 return true;
10170 addr = load_reg(s, a->rn);
10171 tcg_gen_addi_i32(addr, addr, pre_offset[a->pu]);
10173 /* Load PC into tmp and CPSR into tmp2. */
10174 t1 = tcg_temp_new_i32();
10175 gen_aa32_ld32u(s, t1, addr, get_mem_index(s));
10176 tcg_gen_addi_i32(addr, addr, 4);
10177 t2 = tcg_temp_new_i32();
10178 gen_aa32_ld32u(s, t2, addr, get_mem_index(s));
10180 if (a->w) {
10181 /* Base writeback. */
10182 tcg_gen_addi_i32(addr, addr, post_offset[a->pu]);
10183 store_reg(s, a->rn, addr);
10184 } else {
10185 tcg_temp_free_i32(addr);
10187 gen_rfe(s, t1, t2);
10188 return true;
10191 static bool trans_SRS(DisasContext *s, arg_SRS *a)
10193 if (!ENABLE_ARCH_6 || arm_dc_feature(s, ARM_FEATURE_M)) {
10194 return false;
10196 gen_srs(s, a->mode, a->pu, a->w);
10197 return true;
10200 static bool trans_CPS(DisasContext *s, arg_CPS *a)
10202 uint32_t mask, val;
10204 if (!ENABLE_ARCH_6 || arm_dc_feature(s, ARM_FEATURE_M)) {
10205 return false;
10207 if (IS_USER(s)) {
10208 /* Implemented as NOP in user mode. */
10209 return true;
10211 /* TODO: There are quite a lot of UNPREDICTABLE argument combinations. */
10213 mask = val = 0;
10214 if (a->imod & 2) {
10215 if (a->A) {
10216 mask |= CPSR_A;
10218 if (a->I) {
10219 mask |= CPSR_I;
10221 if (a->F) {
10222 mask |= CPSR_F;
10224 if (a->imod & 1) {
10225 val |= mask;
10228 if (a->M) {
10229 mask |= CPSR_M;
10230 val |= a->mode;
10232 if (mask) {
10233 gen_set_psr_im(s, mask, 0, val);
10235 return true;
10238 static bool trans_CPS_v7m(DisasContext *s, arg_CPS_v7m *a)
10240 TCGv_i32 tmp, addr, el;
10242 if (!arm_dc_feature(s, ARM_FEATURE_M)) {
10243 return false;
10245 if (IS_USER(s)) {
10246 /* Implemented as NOP in user mode. */
10247 return true;
10250 tmp = tcg_const_i32(a->im);
10251 /* FAULTMASK */
10252 if (a->F) {
10253 addr = tcg_const_i32(19);
10254 gen_helper_v7m_msr(cpu_env, addr, tmp);
10255 tcg_temp_free_i32(addr);
10257 /* PRIMASK */
10258 if (a->I) {
10259 addr = tcg_const_i32(16);
10260 gen_helper_v7m_msr(cpu_env, addr, tmp);
10261 tcg_temp_free_i32(addr);
10263 el = tcg_const_i32(s->current_el);
10264 gen_helper_rebuild_hflags_m32(cpu_env, el);
10265 tcg_temp_free_i32(el);
10266 tcg_temp_free_i32(tmp);
10267 gen_lookup_tb(s);
10268 return true;
10272 * Clear-Exclusive, Barriers
10275 static bool trans_CLREX(DisasContext *s, arg_CLREX *a)
10277 if (s->thumb
10278 ? !ENABLE_ARCH_7 && !arm_dc_feature(s, ARM_FEATURE_M)
10279 : !ENABLE_ARCH_6K) {
10280 return false;
10282 gen_clrex(s);
10283 return true;
10286 static bool trans_DSB(DisasContext *s, arg_DSB *a)
10288 if (!ENABLE_ARCH_7 && !arm_dc_feature(s, ARM_FEATURE_M)) {
10289 return false;
10291 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
10292 return true;
10295 static bool trans_DMB(DisasContext *s, arg_DMB *a)
10297 return trans_DSB(s, NULL);
10300 static bool trans_ISB(DisasContext *s, arg_ISB *a)
10302 if (!ENABLE_ARCH_7 && !arm_dc_feature(s, ARM_FEATURE_M)) {
10303 return false;
10306 * We need to break the TB after this insn to execute
10307 * self-modifying code correctly and also to take
10308 * any pending interrupts immediately.
10310 gen_goto_tb(s, 0, s->base.pc_next);
10311 return true;
10314 static bool trans_SB(DisasContext *s, arg_SB *a)
10316 if (!dc_isar_feature(aa32_sb, s)) {
10317 return false;
10320 * TODO: There is no speculation barrier opcode
10321 * for TCG; MB and end the TB instead.
10323 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
10324 gen_goto_tb(s, 0, s->base.pc_next);
10325 return true;
10328 static bool trans_SETEND(DisasContext *s, arg_SETEND *a)
10330 if (!ENABLE_ARCH_6) {
10331 return false;
10333 if (a->E != (s->be_data == MO_BE)) {
10334 gen_helper_setend(cpu_env);
10335 s->base.is_jmp = DISAS_UPDATE;
10337 return true;
10341 * Preload instructions
10342 * All are nops, contingent on the appropriate arch level.
10345 static bool trans_PLD(DisasContext *s, arg_PLD *a)
10347 return ENABLE_ARCH_5TE;
10350 static bool trans_PLDW(DisasContext *s, arg_PLD *a)
10352 return arm_dc_feature(s, ARM_FEATURE_V7MP);
10355 static bool trans_PLI(DisasContext *s, arg_PLD *a)
10357 return ENABLE_ARCH_7;
10361 * If-then
10364 static bool trans_IT(DisasContext *s, arg_IT *a)
10366 int cond_mask = a->cond_mask;
10369 * No actual code generated for this insn, just setup state.
10371 * Combinations of firstcond and mask which set up an 0b1111
10372 * condition are UNPREDICTABLE; we take the CONSTRAINED
10373 * UNPREDICTABLE choice to treat 0b1111 the same as 0b1110,
10374 * i.e. both meaning "execute always".
10376 s->condexec_cond = (cond_mask >> 4) & 0xe;
10377 s->condexec_mask = cond_mask & 0x1f;
10378 return true;
10382 * Legacy decoder.
10385 static void disas_arm_insn(DisasContext *s, unsigned int insn)
10387 unsigned int cond = insn >> 28;
10389 /* M variants do not implement ARM mode; this must raise the INVSTATE
10390 * UsageFault exception.
10392 if (arm_dc_feature(s, ARM_FEATURE_M)) {
10393 gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
10394 default_exception_el(s));
10395 return;
10398 if (cond == 0xf) {
10399 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
10400 * choose to UNDEF. In ARMv5 and above the space is used
10401 * for miscellaneous unconditional instructions.
10403 ARCH(5);
10405 /* Unconditional instructions. */
10406 /* TODO: Perhaps merge these into one decodetree output file. */
10407 if (disas_a32_uncond(s, insn) ||
10408 disas_vfp_uncond(s, insn) ||
10409 disas_neon_dp(s, insn) ||
10410 disas_neon_ls(s, insn) ||
10411 disas_neon_shared(s, insn)) {
10412 return;
10414 /* fall back to legacy decoder */
10416 if (((insn >> 25) & 7) == 1) {
10417 /* NEON Data processing. */
10418 if (disas_neon_data_insn(s, insn)) {
10419 goto illegal_op;
10421 return;
10423 if ((insn & 0x0e000f00) == 0x0c000100) {
10424 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
10425 /* iWMMXt register transfer. */
10426 if (extract32(s->c15_cpar, 1, 1)) {
10427 if (!disas_iwmmxt_insn(s, insn)) {
10428 return;
10433 goto illegal_op;
10435 if (cond != 0xe) {
10436 /* if not always execute, we generate a conditional jump to
10437 next instruction */
10438 arm_skip_unless(s, cond);
10441 /* TODO: Perhaps merge these into one decodetree output file. */
10442 if (disas_a32(s, insn) ||
10443 disas_vfp(s, insn)) {
10444 return;
10446 /* fall back to legacy decoder */
10448 switch ((insn >> 24) & 0xf) {
10449 case 0xc:
10450 case 0xd:
10451 case 0xe:
10452 if (((insn >> 8) & 0xe) == 10) {
10453 /* VFP, but failed disas_vfp. */
10454 goto illegal_op;
10456 if (disas_coproc_insn(s, insn)) {
10457 /* Coprocessor. */
10458 goto illegal_op;
10460 break;
10461 default:
10462 illegal_op:
10463 unallocated_encoding(s);
10464 break;
10468 static bool thumb_insn_is_16bit(DisasContext *s, uint32_t pc, uint32_t insn)
10471 * Return true if this is a 16 bit instruction. We must be precise
10472 * about this (matching the decode).
10474 if ((insn >> 11) < 0x1d) {
10475 /* Definitely a 16-bit instruction */
10476 return true;
10479 /* Top five bits 0b11101 / 0b11110 / 0b11111 : this is the
10480 * first half of a 32-bit Thumb insn. Thumb-1 cores might
10481 * end up actually treating this as two 16-bit insns, though,
10482 * if it's half of a bl/blx pair that might span a page boundary.
10484 if (arm_dc_feature(s, ARM_FEATURE_THUMB2) ||
10485 arm_dc_feature(s, ARM_FEATURE_M)) {
10486 /* Thumb2 cores (including all M profile ones) always treat
10487 * 32-bit insns as 32-bit.
10489 return false;
10492 if ((insn >> 11) == 0x1e && pc - s->page_start < TARGET_PAGE_SIZE - 3) {
10493 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix, and the suffix
10494 * is not on the next page; we merge this into a 32-bit
10495 * insn.
10497 return false;
10499 /* 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF);
10500 * 0b1111_1xxx_xxxx_xxxx : BL suffix;
10501 * 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix on the end of a page
10502 * -- handle as single 16 bit insn
10504 return true;
10507 /* Translate a 32-bit thumb instruction. */
10508 static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
10511 * ARMv6-M supports a limited subset of Thumb2 instructions.
10512 * Other Thumb1 architectures allow only 32-bit
10513 * combined BL/BLX prefix and suffix.
10515 if (arm_dc_feature(s, ARM_FEATURE_M) &&
10516 !arm_dc_feature(s, ARM_FEATURE_V7)) {
10517 int i;
10518 bool found = false;
10519 static const uint32_t armv6m_insn[] = {0xf3808000 /* msr */,
10520 0xf3b08040 /* dsb */,
10521 0xf3b08050 /* dmb */,
10522 0xf3b08060 /* isb */,
10523 0xf3e08000 /* mrs */,
10524 0xf000d000 /* bl */};
10525 static const uint32_t armv6m_mask[] = {0xffe0d000,
10526 0xfff0d0f0,
10527 0xfff0d0f0,
10528 0xfff0d0f0,
10529 0xffe0d000,
10530 0xf800d000};
10532 for (i = 0; i < ARRAY_SIZE(armv6m_insn); i++) {
10533 if ((insn & armv6m_mask[i]) == armv6m_insn[i]) {
10534 found = true;
10535 break;
10538 if (!found) {
10539 goto illegal_op;
10541 } else if ((insn & 0xf800e800) != 0xf000e800) {
10542 ARCH(6T2);
10545 if ((insn & 0xef000000) == 0xef000000) {
10547 * T32 encodings 0b111p_1111_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq
10548 * transform into
10549 * A32 encodings 0b1111_001p_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq
10551 uint32_t a32_insn = (insn & 0xe2ffffff) |
10552 ((insn & (1 << 28)) >> 4) | (1 << 28);
10554 if (disas_neon_dp(s, a32_insn)) {
10555 return;
10559 if ((insn & 0xff100000) == 0xf9000000) {
10561 * T32 encodings 0b1111_1001_ppp0_qqqq_qqqq_qqqq_qqqq_qqqq
10562 * transform into
10563 * A32 encodings 0b1111_0100_ppp0_qqqq_qqqq_qqqq_qqqq_qqqq
10565 uint32_t a32_insn = (insn & 0x00ffffff) | 0xf4000000;
10567 if (disas_neon_ls(s, a32_insn)) {
10568 return;
10573 * TODO: Perhaps merge these into one decodetree output file.
10574 * Note disas_vfp is written for a32 with cond field in the
10575 * top nibble. The t32 encoding requires 0xe in the top nibble.
10577 if (disas_t32(s, insn) ||
10578 disas_vfp_uncond(s, insn) ||
10579 disas_neon_shared(s, insn) ||
10580 ((insn >> 28) == 0xe && disas_vfp(s, insn))) {
10581 return;
10583 /* fall back to legacy decoder */
10585 switch ((insn >> 25) & 0xf) {
10586 case 0: case 1: case 2: case 3:
10587 /* 16-bit instructions. Should never happen. */
10588 abort();
10589 case 6: case 7: case 14: case 15:
10590 /* Coprocessor. */
10591 if (arm_dc_feature(s, ARM_FEATURE_M)) {
10592 /* 0b111x_11xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx */
10593 if (extract32(insn, 24, 2) == 3) {
10594 goto illegal_op; /* op0 = 0b11 : unallocated */
10597 if (((insn >> 8) & 0xe) == 10 &&
10598 dc_isar_feature(aa32_fpsp_v2, s)) {
10599 /* FP, and the CPU supports it */
10600 goto illegal_op;
10601 } else {
10602 /* All other insns: NOCP */
10603 gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
10604 syn_uncategorized(),
10605 default_exception_el(s));
10607 break;
10609 if (((insn >> 24) & 3) == 3) {
10610 /* Translate into the equivalent ARM encoding. */
10611 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
10612 if (disas_neon_data_insn(s, insn)) {
10613 goto illegal_op;
10615 } else if (((insn >> 8) & 0xe) == 10) {
10616 /* VFP, but failed disas_vfp. */
10617 goto illegal_op;
10618 } else {
10619 if (insn & (1 << 28))
10620 goto illegal_op;
10621 if (disas_coproc_insn(s, insn)) {
10622 goto illegal_op;
10625 break;
10626 case 12:
10627 goto illegal_op;
10628 default:
10629 illegal_op:
10630 unallocated_encoding(s);
10634 static void disas_thumb_insn(DisasContext *s, uint32_t insn)
10636 if (!disas_t16(s, insn)) {
10637 unallocated_encoding(s);
10641 static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
10643 /* Return true if the insn at dc->base.pc_next might cross a page boundary.
10644 * (False positives are OK, false negatives are not.)
10645 * We know this is a Thumb insn, and our caller ensures we are
10646 * only called if dc->base.pc_next is less than 4 bytes from the page
10647 * boundary, so we cross the page if the first 16 bits indicate
10648 * that this is a 32 bit insn.
10650 uint16_t insn = arm_lduw_code(env, s->base.pc_next, s->sctlr_b);
10652 return !thumb_insn_is_16bit(s, s->base.pc_next, insn);
10655 static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
10657 DisasContext *dc = container_of(dcbase, DisasContext, base);
10658 CPUARMState *env = cs->env_ptr;
10659 ARMCPU *cpu = env_archcpu(env);
10660 uint32_t tb_flags = dc->base.tb->flags;
10661 uint32_t condexec, core_mmu_idx;
10663 dc->isar = &cpu->isar;
10664 dc->condjmp = 0;
10666 dc->aarch64 = 0;
10667 /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
10668 * there is no secure EL1, so we route exceptions to EL3.
10670 dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
10671 !arm_el_is_aa64(env, 3);
10672 dc->thumb = FIELD_EX32(tb_flags, TBFLAG_AM32, THUMB);
10673 dc->be_data = FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
10674 condexec = FIELD_EX32(tb_flags, TBFLAG_AM32, CONDEXEC);
10675 dc->condexec_mask = (condexec & 0xf) << 1;
10676 dc->condexec_cond = condexec >> 4;
10678 core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX);
10679 dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
10680 dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
10681 #if !defined(CONFIG_USER_ONLY)
10682 dc->user = (dc->current_el == 0);
10683 #endif
10684 dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL);
10686 if (arm_feature(env, ARM_FEATURE_M)) {
10687 dc->vfp_enabled = 1;
10688 dc->be_data = MO_TE;
10689 dc->v7m_handler_mode = FIELD_EX32(tb_flags, TBFLAG_M32, HANDLER);
10690 dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
10691 regime_is_secure(env, dc->mmu_idx);
10692 dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_M32, STACKCHECK);
10693 dc->v8m_fpccr_s_wrong =
10694 FIELD_EX32(tb_flags, TBFLAG_M32, FPCCR_S_WRONG);
10695 dc->v7m_new_fp_ctxt_needed =
10696 FIELD_EX32(tb_flags, TBFLAG_M32, NEW_FP_CTXT_NEEDED);
10697 dc->v7m_lspact = FIELD_EX32(tb_flags, TBFLAG_M32, LSPACT);
10698 } else {
10699 dc->be_data =
10700 FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
10701 dc->debug_target_el =
10702 FIELD_EX32(tb_flags, TBFLAG_ANY, DEBUG_TARGET_EL);
10703 dc->sctlr_b = FIELD_EX32(tb_flags, TBFLAG_A32, SCTLR_B);
10704 dc->hstr_active = FIELD_EX32(tb_flags, TBFLAG_A32, HSTR_ACTIVE);
10705 dc->ns = FIELD_EX32(tb_flags, TBFLAG_A32, NS);
10706 dc->vfp_enabled = FIELD_EX32(tb_flags, TBFLAG_A32, VFPEN);
10707 if (arm_feature(env, ARM_FEATURE_XSCALE)) {
10708 dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
10709 } else {
10710 dc->vec_len = FIELD_EX32(tb_flags, TBFLAG_A32, VECLEN);
10711 dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
10714 dc->cp_regs = cpu->cp_regs;
10715 dc->features = env->features;
10717 /* Single step state. The code-generation logic here is:
10718 * SS_ACTIVE == 0:
10719 * generate code with no special handling for single-stepping (except
10720 * that anything that can make us go to SS_ACTIVE == 1 must end the TB;
10721 * this happens anyway because those changes are all system register or
10722 * PSTATE writes).
10723 * SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
10724 * emit code for one insn
10725 * emit code to clear PSTATE.SS
10726 * emit code to generate software step exception for completed step
10727 * end TB (as usual for having generated an exception)
10728 * SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
10729 * emit code to generate a software step exception
10730 * end the TB
10732 dc->ss_active = FIELD_EX32(tb_flags, TBFLAG_ANY, SS_ACTIVE);
10733 dc->pstate_ss = FIELD_EX32(tb_flags, TBFLAG_ANY, PSTATE_SS);
10734 dc->is_ldex = false;
10736 dc->page_start = dc->base.pc_first & TARGET_PAGE_MASK;
10738 /* If architectural single step active, limit to 1. */
10739 if (is_singlestepping(dc)) {
10740 dc->base.max_insns = 1;
10743 /* ARM is a fixed-length ISA. Bound the number of insns to execute
10744 to those left on the page. */
10745 if (!dc->thumb) {
10746 int bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
10747 dc->base.max_insns = MIN(dc->base.max_insns, bound);
10750 cpu_V0 = tcg_temp_new_i64();
10751 cpu_V1 = tcg_temp_new_i64();
10752 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
10753 cpu_M0 = tcg_temp_new_i64();
10756 static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
10758 DisasContext *dc = container_of(dcbase, DisasContext, base);
10760 /* A note on handling of the condexec (IT) bits:
10762 * We want to avoid the overhead of having to write the updated condexec
10763 * bits back to the CPUARMState for every instruction in an IT block. So:
10764 * (1) if the condexec bits are not already zero then we write
10765 * zero back into the CPUARMState now. This avoids complications trying
10766 * to do it at the end of the block. (For example if we don't do this
10767 * it's hard to identify whether we can safely skip writing condexec
10768 * at the end of the TB, which we definitely want to do for the case
10769 * where a TB doesn't do anything with the IT state at all.)
10770 * (2) if we are going to leave the TB then we call gen_set_condexec()
10771 * which will write the correct value into CPUARMState if zero is wrong.
10772 * This is done both for leaving the TB at the end, and for leaving
10773 * it because of an exception we know will happen, which is done in
10774 * gen_exception_insn(). The latter is necessary because we need to
10775 * leave the TB with the PC/IT state just prior to execution of the
10776 * instruction which caused the exception.
10777 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
10778 * then the CPUARMState will be wrong and we need to reset it.
10779 * This is handled in the same way as restoration of the
10780 * PC in these situations; we save the value of the condexec bits
10781 * for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
10782 * then uses this to restore them after an exception.
10784 * Note that there are no instructions which can read the condexec
10785 * bits, and none which can write non-static values to them, so
10786 * we don't need to care about whether CPUARMState is correct in the
10787 * middle of a TB.
10790 /* Reset the conditional execution bits immediately. This avoids
10791 complications trying to do it at the end of the block. */
10792 if (dc->condexec_mask || dc->condexec_cond) {
10793 TCGv_i32 tmp = tcg_temp_new_i32();
10794 tcg_gen_movi_i32(tmp, 0);
10795 store_cpu_field(tmp, condexec_bits);
10799 static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
10801 DisasContext *dc = container_of(dcbase, DisasContext, base);
10803 tcg_gen_insn_start(dc->base.pc_next,
10804 (dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
10806 dc->insn_start = tcg_last_op();
10809 static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
10810 const CPUBreakpoint *bp)
10812 DisasContext *dc = container_of(dcbase, DisasContext, base);
10814 if (bp->flags & BP_CPU) {
10815 gen_set_condexec(dc);
10816 gen_set_pc_im(dc, dc->base.pc_next);
10817 gen_helper_check_breakpoints(cpu_env);
10818 /* End the TB early; it's likely not going to be executed */
10819 dc->base.is_jmp = DISAS_TOO_MANY;
10820 } else {
10821 gen_exception_internal_insn(dc, dc->base.pc_next, EXCP_DEBUG);
10822 /* The address covered by the breakpoint must be
10823 included in [tb->pc, tb->pc + tb->size) in order
10824 to for it to be properly cleared -- thus we
10825 increment the PC here so that the logic setting
10826 tb->size below does the right thing. */
10827 /* TODO: Advance PC by correct instruction length to
10828 * avoid disassembler error messages */
10829 dc->base.pc_next += 2;
10830 dc->base.is_jmp = DISAS_NORETURN;
10833 return true;
10836 static bool arm_pre_translate_insn(DisasContext *dc)
10838 #ifdef CONFIG_USER_ONLY
10839 /* Intercept jump to the magic kernel page. */
10840 if (dc->base.pc_next >= 0xffff0000) {
10841 /* We always get here via a jump, so know we are not in a
10842 conditional execution block. */
10843 gen_exception_internal(EXCP_KERNEL_TRAP);
10844 dc->base.is_jmp = DISAS_NORETURN;
10845 return true;
10847 #endif
10849 if (dc->ss_active && !dc->pstate_ss) {
10850 /* Singlestep state is Active-pending.
10851 * If we're in this state at the start of a TB then either
10852 * a) we just took an exception to an EL which is being debugged
10853 * and this is the first insn in the exception handler
10854 * b) debug exceptions were masked and we just unmasked them
10855 * without changing EL (eg by clearing PSTATE.D)
10856 * In either case we're going to take a swstep exception in the
10857 * "did not step an insn" case, and so the syndrome ISV and EX
10858 * bits should be zero.
10860 assert(dc->base.num_insns == 1);
10861 gen_swstep_exception(dc, 0, 0);
10862 dc->base.is_jmp = DISAS_NORETURN;
10863 return true;
10866 return false;
10869 static void arm_post_translate_insn(DisasContext *dc)
10871 if (dc->condjmp && !dc->base.is_jmp) {
10872 gen_set_label(dc->condlabel);
10873 dc->condjmp = 0;
10875 translator_loop_temp_check(&dc->base);
10878 static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
10880 DisasContext *dc = container_of(dcbase, DisasContext, base);
10881 CPUARMState *env = cpu->env_ptr;
10882 unsigned int insn;
10884 if (arm_pre_translate_insn(dc)) {
10885 return;
10888 dc->pc_curr = dc->base.pc_next;
10889 insn = arm_ldl_code(env, dc->base.pc_next, dc->sctlr_b);
10890 dc->insn = insn;
10891 dc->base.pc_next += 4;
10892 disas_arm_insn(dc, insn);
10894 arm_post_translate_insn(dc);
10896 /* ARM is a fixed-length ISA. We performed the cross-page check
10897 in init_disas_context by adjusting max_insns. */
10900 static bool thumb_insn_is_unconditional(DisasContext *s, uint32_t insn)
10902 /* Return true if this Thumb insn is always unconditional,
10903 * even inside an IT block. This is true of only a very few
10904 * instructions: BKPT, HLT, and SG.
10906 * A larger class of instructions are UNPREDICTABLE if used
10907 * inside an IT block; we do not need to detect those here, because
10908 * what we do by default (perform the cc check and update the IT
10909 * bits state machine) is a permitted CONSTRAINED UNPREDICTABLE
10910 * choice for those situations.
10912 * insn is either a 16-bit or a 32-bit instruction; the two are
10913 * distinguishable because for the 16-bit case the top 16 bits
10914 * are zeroes, and that isn't a valid 32-bit encoding.
10916 if ((insn & 0xffffff00) == 0xbe00) {
10917 /* BKPT */
10918 return true;
10921 if ((insn & 0xffffffc0) == 0xba80 && arm_dc_feature(s, ARM_FEATURE_V8) &&
10922 !arm_dc_feature(s, ARM_FEATURE_M)) {
10923 /* HLT: v8A only. This is unconditional even when it is going to
10924 * UNDEF; see the v8A ARM ARM DDI0487B.a H3.3.
10925 * For v7 cores this was a plain old undefined encoding and so
10926 * honours its cc check. (We might be using the encoding as
10927 * a semihosting trap, but we don't change the cc check behaviour
10928 * on that account, because a debugger connected to a real v7A
10929 * core and emulating semihosting traps by catching the UNDEF
10930 * exception would also only see cases where the cc check passed.
10931 * No guest code should be trying to do a HLT semihosting trap
10932 * in an IT block anyway.
10934 return true;
10937 if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_V8) &&
10938 arm_dc_feature(s, ARM_FEATURE_M)) {
10939 /* SG: v8M only */
10940 return true;
10943 return false;
10946 static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
10948 DisasContext *dc = container_of(dcbase, DisasContext, base);
10949 CPUARMState *env = cpu->env_ptr;
10950 uint32_t insn;
10951 bool is_16bit;
10953 if (arm_pre_translate_insn(dc)) {
10954 return;
10957 dc->pc_curr = dc->base.pc_next;
10958 insn = arm_lduw_code(env, dc->base.pc_next, dc->sctlr_b);
10959 is_16bit = thumb_insn_is_16bit(dc, dc->base.pc_next, insn);
10960 dc->base.pc_next += 2;
10961 if (!is_16bit) {
10962 uint32_t insn2 = arm_lduw_code(env, dc->base.pc_next, dc->sctlr_b);
10964 insn = insn << 16 | insn2;
10965 dc->base.pc_next += 2;
10967 dc->insn = insn;
10969 if (dc->condexec_mask && !thumb_insn_is_unconditional(dc, insn)) {
10970 uint32_t cond = dc->condexec_cond;
10973 * Conditionally skip the insn. Note that both 0xe and 0xf mean
10974 * "always"; 0xf is not "never".
10976 if (cond < 0x0e) {
10977 arm_skip_unless(dc, cond);
10981 if (is_16bit) {
10982 disas_thumb_insn(dc, insn);
10983 } else {
10984 disas_thumb2_insn(dc, insn);
10987 /* Advance the Thumb condexec condition. */
10988 if (dc->condexec_mask) {
10989 dc->condexec_cond = ((dc->condexec_cond & 0xe) |
10990 ((dc->condexec_mask >> 4) & 1));
10991 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
10992 if (dc->condexec_mask == 0) {
10993 dc->condexec_cond = 0;
10997 arm_post_translate_insn(dc);
10999 /* Thumb is a variable-length ISA. Stop translation when the next insn
11000 * will touch a new page. This ensures that prefetch aborts occur at
11001 * the right place.
11003 * We want to stop the TB if the next insn starts in a new page,
11004 * or if it spans between this page and the next. This means that
11005 * if we're looking at the last halfword in the page we need to
11006 * see if it's a 16-bit Thumb insn (which will fit in this TB)
11007 * or a 32-bit Thumb insn (which won't).
11008 * This is to avoid generating a silly TB with a single 16-bit insn
11009 * in it at the end of this page (which would execute correctly
11010 * but isn't very efficient).
11012 if (dc->base.is_jmp == DISAS_NEXT
11013 && (dc->base.pc_next - dc->page_start >= TARGET_PAGE_SIZE
11014 || (dc->base.pc_next - dc->page_start >= TARGET_PAGE_SIZE - 3
11015 && insn_crosses_page(env, dc)))) {
11016 dc->base.is_jmp = DISAS_TOO_MANY;
11020 static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
11022 DisasContext *dc = container_of(dcbase, DisasContext, base);
11024 if (tb_cflags(dc->base.tb) & CF_LAST_IO && dc->condjmp) {
11025 /* FIXME: This can theoretically happen with self-modifying code. */
11026 cpu_abort(cpu, "IO on conditional branch instruction");
11029 /* At this stage dc->condjmp will only be set when the skipped
11030 instruction was a conditional branch or trap, and the PC has
11031 already been written. */
11032 gen_set_condexec(dc);
11033 if (dc->base.is_jmp == DISAS_BX_EXCRET) {
11034 /* Exception return branches need some special case code at the
11035 * end of the TB, which is complex enough that it has to
11036 * handle the single-step vs not and the condition-failed
11037 * insn codepath itself.
11039 gen_bx_excret_final_code(dc);
11040 } else if (unlikely(is_singlestepping(dc))) {
11041 /* Unconditional and "condition passed" instruction codepath. */
11042 switch (dc->base.is_jmp) {
11043 case DISAS_SWI:
11044 gen_ss_advance(dc);
11045 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
11046 default_exception_el(dc));
11047 break;
11048 case DISAS_HVC:
11049 gen_ss_advance(dc);
11050 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
11051 break;
11052 case DISAS_SMC:
11053 gen_ss_advance(dc);
11054 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
11055 break;
11056 case DISAS_NEXT:
11057 case DISAS_TOO_MANY:
11058 case DISAS_UPDATE:
11059 gen_set_pc_im(dc, dc->base.pc_next);
11060 /* fall through */
11061 default:
11062 /* FIXME: Single stepping a WFI insn will not halt the CPU. */
11063 gen_singlestep_exception(dc);
11064 break;
11065 case DISAS_NORETURN:
11066 break;
11068 } else {
11069 /* While branches must always occur at the end of an IT block,
11070 there are a few other things that can cause us to terminate
11071 the TB in the middle of an IT block:
11072 - Exception generating instructions (bkpt, swi, undefined).
11073 - Page boundaries.
11074 - Hardware watchpoints.
11075 Hardware breakpoints have already been handled and skip this code.
11077 switch(dc->base.is_jmp) {
11078 case DISAS_NEXT:
11079 case DISAS_TOO_MANY:
11080 gen_goto_tb(dc, 1, dc->base.pc_next);
11081 break;
11082 case DISAS_JUMP:
11083 gen_goto_ptr();
11084 break;
11085 case DISAS_UPDATE:
11086 gen_set_pc_im(dc, dc->base.pc_next);
11087 /* fall through */
11088 default:
11089 /* indicate that the hash table must be used to find the next TB */
11090 tcg_gen_exit_tb(NULL, 0);
11091 break;
11092 case DISAS_NORETURN:
11093 /* nothing more to generate */
11094 break;
11095 case DISAS_WFI:
11097 TCGv_i32 tmp = tcg_const_i32((dc->thumb &&
11098 !(dc->insn & (1U << 31))) ? 2 : 4);
11100 gen_helper_wfi(cpu_env, tmp);
11101 tcg_temp_free_i32(tmp);
11102 /* The helper doesn't necessarily throw an exception, but we
11103 * must go back to the main loop to check for interrupts anyway.
11105 tcg_gen_exit_tb(NULL, 0);
11106 break;
11108 case DISAS_WFE:
11109 gen_helper_wfe(cpu_env);
11110 break;
11111 case DISAS_YIELD:
11112 gen_helper_yield(cpu_env);
11113 break;
11114 case DISAS_SWI:
11115 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
11116 default_exception_el(dc));
11117 break;
11118 case DISAS_HVC:
11119 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
11120 break;
11121 case DISAS_SMC:
11122 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
11123 break;
11127 if (dc->condjmp) {
11128 /* "Condition failed" instruction codepath for the branch/trap insn */
11129 gen_set_label(dc->condlabel);
11130 gen_set_condexec(dc);
11131 if (unlikely(is_singlestepping(dc))) {
11132 gen_set_pc_im(dc, dc->base.pc_next);
11133 gen_singlestep_exception(dc);
11134 } else {
11135 gen_goto_tb(dc, 1, dc->base.pc_next);
11140 static void arm_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
11142 DisasContext *dc = container_of(dcbase, DisasContext, base);
11144 qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
11145 log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
11148 static const TranslatorOps arm_translator_ops = {
11149 .init_disas_context = arm_tr_init_disas_context,
11150 .tb_start = arm_tr_tb_start,
11151 .insn_start = arm_tr_insn_start,
11152 .breakpoint_check = arm_tr_breakpoint_check,
11153 .translate_insn = arm_tr_translate_insn,
11154 .tb_stop = arm_tr_tb_stop,
11155 .disas_log = arm_tr_disas_log,
11158 static const TranslatorOps thumb_translator_ops = {
11159 .init_disas_context = arm_tr_init_disas_context,
11160 .tb_start = arm_tr_tb_start,
11161 .insn_start = arm_tr_insn_start,
11162 .breakpoint_check = arm_tr_breakpoint_check,
11163 .translate_insn = thumb_tr_translate_insn,
11164 .tb_stop = arm_tr_tb_stop,
11165 .disas_log = arm_tr_disas_log,
11168 /* generate intermediate code for basic block 'tb'. */
11169 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
11171 DisasContext dc = { };
11172 const TranslatorOps *ops = &arm_translator_ops;
11174 if (FIELD_EX32(tb->flags, TBFLAG_AM32, THUMB)) {
11175 ops = &thumb_translator_ops;
11177 #ifdef TARGET_AARCH64
11178 if (FIELD_EX32(tb->flags, TBFLAG_ANY, AARCH64_STATE)) {
11179 ops = &aarch64_translator_ops;
11181 #endif
11183 translator_loop(ops, &dc.base, cpu, tb, max_insns);
11186 void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
11187 target_ulong *data)
11189 if (is_a64(env)) {
11190 env->pc = data[0];
11191 env->condexec_bits = 0;
11192 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
11193 } else {
11194 env->regs[15] = data[0];
11195 env->condexec_bits = data[1];
11196 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;