target/arm: Convert Neon 2-reg-scalar VQDMULH, VQRDMULH to decodetree
[qemu/ar7.git] / target / arm / translate.c
blob5d0e00f92e0a39c91935c2ecfe4ff7dc0ce32599
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 inline bool use_goto_tb(DisasContext *s, target_ulong dest)
2629 #ifndef CONFIG_USER_ONLY
2630 return (s->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
2631 ((s->base.pc_next - 1) & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
2632 #else
2633 return true;
2634 #endif
2637 static void gen_goto_ptr(void)
2639 tcg_gen_lookup_and_goto_ptr();
2642 /* This will end the TB but doesn't guarantee we'll return to
2643 * cpu_loop_exec. Any live exit_requests will be processed as we
2644 * enter the next TB.
2646 static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
2648 if (use_goto_tb(s, dest)) {
2649 tcg_gen_goto_tb(n);
2650 gen_set_pc_im(s, dest);
2651 tcg_gen_exit_tb(s->base.tb, n);
2652 } else {
2653 gen_set_pc_im(s, dest);
2654 gen_goto_ptr();
2656 s->base.is_jmp = DISAS_NORETURN;
2659 static inline void gen_jmp (DisasContext *s, uint32_t dest)
2661 if (unlikely(is_singlestepping(s))) {
2662 /* An indirect jump so that we still trigger the debug exception. */
2663 gen_set_pc_im(s, dest);
2664 s->base.is_jmp = DISAS_JUMP;
2665 } else {
2666 gen_goto_tb(s, 0, dest);
2670 static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
2672 if (x)
2673 tcg_gen_sari_i32(t0, t0, 16);
2674 else
2675 gen_sxth(t0);
2676 if (y)
2677 tcg_gen_sari_i32(t1, t1, 16);
2678 else
2679 gen_sxth(t1);
2680 tcg_gen_mul_i32(t0, t0, t1);
2683 /* Return the mask of PSR bits set by a MSR instruction. */
2684 static uint32_t msr_mask(DisasContext *s, int flags, int spsr)
2686 uint32_t mask = 0;
2688 if (flags & (1 << 0)) {
2689 mask |= 0xff;
2691 if (flags & (1 << 1)) {
2692 mask |= 0xff00;
2694 if (flags & (1 << 2)) {
2695 mask |= 0xff0000;
2697 if (flags & (1 << 3)) {
2698 mask |= 0xff000000;
2701 /* Mask out undefined and reserved bits. */
2702 mask &= aarch32_cpsr_valid_mask(s->features, s->isar);
2704 /* Mask out execution state. */
2705 if (!spsr) {
2706 mask &= ~CPSR_EXEC;
2709 /* Mask out privileged bits. */
2710 if (IS_USER(s)) {
2711 mask &= CPSR_USER;
2713 return mask;
2716 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
2717 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
2719 TCGv_i32 tmp;
2720 if (spsr) {
2721 /* ??? This is also undefined in system mode. */
2722 if (IS_USER(s))
2723 return 1;
2725 tmp = load_cpu_field(spsr);
2726 tcg_gen_andi_i32(tmp, tmp, ~mask);
2727 tcg_gen_andi_i32(t0, t0, mask);
2728 tcg_gen_or_i32(tmp, tmp, t0);
2729 store_cpu_field(tmp, spsr);
2730 } else {
2731 gen_set_cpsr(t0, mask);
2733 tcg_temp_free_i32(t0);
2734 gen_lookup_tb(s);
2735 return 0;
2738 /* Returns nonzero if access to the PSR is not permitted. */
2739 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
2741 TCGv_i32 tmp;
2742 tmp = tcg_temp_new_i32();
2743 tcg_gen_movi_i32(tmp, val);
2744 return gen_set_psr(s, mask, spsr, tmp);
2747 static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
2748 int *tgtmode, int *regno)
2750 /* Decode the r and sysm fields of MSR/MRS banked accesses into
2751 * the target mode and register number, and identify the various
2752 * unpredictable cases.
2753 * MSR (banked) and MRS (banked) are CONSTRAINED UNPREDICTABLE if:
2754 * + executed in user mode
2755 * + using R15 as the src/dest register
2756 * + accessing an unimplemented register
2757 * + accessing a register that's inaccessible at current PL/security state*
2758 * + accessing a register that you could access with a different insn
2759 * We choose to UNDEF in all these cases.
2760 * Since we don't know which of the various AArch32 modes we are in
2761 * we have to defer some checks to runtime.
2762 * Accesses to Monitor mode registers from Secure EL1 (which implies
2763 * that EL3 is AArch64) must trap to EL3.
2765 * If the access checks fail this function will emit code to take
2766 * an exception and return false. Otherwise it will return true,
2767 * and set *tgtmode and *regno appropriately.
2769 int exc_target = default_exception_el(s);
2771 /* These instructions are present only in ARMv8, or in ARMv7 with the
2772 * Virtualization Extensions.
2774 if (!arm_dc_feature(s, ARM_FEATURE_V8) &&
2775 !arm_dc_feature(s, ARM_FEATURE_EL2)) {
2776 goto undef;
2779 if (IS_USER(s) || rn == 15) {
2780 goto undef;
2783 /* The table in the v8 ARM ARM section F5.2.3 describes the encoding
2784 * of registers into (r, sysm).
2786 if (r) {
2787 /* SPSRs for other modes */
2788 switch (sysm) {
2789 case 0xe: /* SPSR_fiq */
2790 *tgtmode = ARM_CPU_MODE_FIQ;
2791 break;
2792 case 0x10: /* SPSR_irq */
2793 *tgtmode = ARM_CPU_MODE_IRQ;
2794 break;
2795 case 0x12: /* SPSR_svc */
2796 *tgtmode = ARM_CPU_MODE_SVC;
2797 break;
2798 case 0x14: /* SPSR_abt */
2799 *tgtmode = ARM_CPU_MODE_ABT;
2800 break;
2801 case 0x16: /* SPSR_und */
2802 *tgtmode = ARM_CPU_MODE_UND;
2803 break;
2804 case 0x1c: /* SPSR_mon */
2805 *tgtmode = ARM_CPU_MODE_MON;
2806 break;
2807 case 0x1e: /* SPSR_hyp */
2808 *tgtmode = ARM_CPU_MODE_HYP;
2809 break;
2810 default: /* unallocated */
2811 goto undef;
2813 /* We arbitrarily assign SPSR a register number of 16. */
2814 *regno = 16;
2815 } else {
2816 /* general purpose registers for other modes */
2817 switch (sysm) {
2818 case 0x0 ... 0x6: /* 0b00xxx : r8_usr ... r14_usr */
2819 *tgtmode = ARM_CPU_MODE_USR;
2820 *regno = sysm + 8;
2821 break;
2822 case 0x8 ... 0xe: /* 0b01xxx : r8_fiq ... r14_fiq */
2823 *tgtmode = ARM_CPU_MODE_FIQ;
2824 *regno = sysm;
2825 break;
2826 case 0x10 ... 0x11: /* 0b1000x : r14_irq, r13_irq */
2827 *tgtmode = ARM_CPU_MODE_IRQ;
2828 *regno = sysm & 1 ? 13 : 14;
2829 break;
2830 case 0x12 ... 0x13: /* 0b1001x : r14_svc, r13_svc */
2831 *tgtmode = ARM_CPU_MODE_SVC;
2832 *regno = sysm & 1 ? 13 : 14;
2833 break;
2834 case 0x14 ... 0x15: /* 0b1010x : r14_abt, r13_abt */
2835 *tgtmode = ARM_CPU_MODE_ABT;
2836 *regno = sysm & 1 ? 13 : 14;
2837 break;
2838 case 0x16 ... 0x17: /* 0b1011x : r14_und, r13_und */
2839 *tgtmode = ARM_CPU_MODE_UND;
2840 *regno = sysm & 1 ? 13 : 14;
2841 break;
2842 case 0x1c ... 0x1d: /* 0b1110x : r14_mon, r13_mon */
2843 *tgtmode = ARM_CPU_MODE_MON;
2844 *regno = sysm & 1 ? 13 : 14;
2845 break;
2846 case 0x1e ... 0x1f: /* 0b1111x : elr_hyp, r13_hyp */
2847 *tgtmode = ARM_CPU_MODE_HYP;
2848 /* Arbitrarily pick 17 for ELR_Hyp (which is not a banked LR!) */
2849 *regno = sysm & 1 ? 13 : 17;
2850 break;
2851 default: /* unallocated */
2852 goto undef;
2856 /* Catch the 'accessing inaccessible register' cases we can detect
2857 * at translate time.
2859 switch (*tgtmode) {
2860 case ARM_CPU_MODE_MON:
2861 if (!arm_dc_feature(s, ARM_FEATURE_EL3) || s->ns) {
2862 goto undef;
2864 if (s->current_el == 1) {
2865 /* If we're in Secure EL1 (which implies that EL3 is AArch64)
2866 * then accesses to Mon registers trap to EL3
2868 exc_target = 3;
2869 goto undef;
2871 break;
2872 case ARM_CPU_MODE_HYP:
2874 * SPSR_hyp and r13_hyp can only be accessed from Monitor mode
2875 * (and so we can forbid accesses from EL2 or below). elr_hyp
2876 * can be accessed also from Hyp mode, so forbid accesses from
2877 * EL0 or EL1.
2879 if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el < 2 ||
2880 (s->current_el < 3 && *regno != 17)) {
2881 goto undef;
2883 break;
2884 default:
2885 break;
2888 return true;
2890 undef:
2891 /* If we get here then some access check did not pass */
2892 gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
2893 syn_uncategorized(), exc_target);
2894 return false;
2897 static void gen_msr_banked(DisasContext *s, int r, int sysm, int rn)
2899 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
2900 int tgtmode = 0, regno = 0;
2902 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
2903 return;
2906 /* Sync state because msr_banked() can raise exceptions */
2907 gen_set_condexec(s);
2908 gen_set_pc_im(s, s->pc_curr);
2909 tcg_reg = load_reg(s, rn);
2910 tcg_tgtmode = tcg_const_i32(tgtmode);
2911 tcg_regno = tcg_const_i32(regno);
2912 gen_helper_msr_banked(cpu_env, tcg_reg, tcg_tgtmode, tcg_regno);
2913 tcg_temp_free_i32(tcg_tgtmode);
2914 tcg_temp_free_i32(tcg_regno);
2915 tcg_temp_free_i32(tcg_reg);
2916 s->base.is_jmp = DISAS_UPDATE;
2919 static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn)
2921 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
2922 int tgtmode = 0, regno = 0;
2924 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
2925 return;
2928 /* Sync state because mrs_banked() can raise exceptions */
2929 gen_set_condexec(s);
2930 gen_set_pc_im(s, s->pc_curr);
2931 tcg_reg = tcg_temp_new_i32();
2932 tcg_tgtmode = tcg_const_i32(tgtmode);
2933 tcg_regno = tcg_const_i32(regno);
2934 gen_helper_mrs_banked(tcg_reg, cpu_env, tcg_tgtmode, tcg_regno);
2935 tcg_temp_free_i32(tcg_tgtmode);
2936 tcg_temp_free_i32(tcg_regno);
2937 store_reg(s, rn, tcg_reg);
2938 s->base.is_jmp = DISAS_UPDATE;
2941 /* Store value to PC as for an exception return (ie don't
2942 * mask bits). The subsequent call to gen_helper_cpsr_write_eret()
2943 * will do the masking based on the new value of the Thumb bit.
2945 static void store_pc_exc_ret(DisasContext *s, TCGv_i32 pc)
2947 tcg_gen_mov_i32(cpu_R[15], pc);
2948 tcg_temp_free_i32(pc);
2951 /* Generate a v6 exception return. Marks both values as dead. */
2952 static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
2954 store_pc_exc_ret(s, pc);
2955 /* The cpsr_write_eret helper will mask the low bits of PC
2956 * appropriately depending on the new Thumb bit, so it must
2957 * be called after storing the new PC.
2959 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
2960 gen_io_start();
2962 gen_helper_cpsr_write_eret(cpu_env, cpsr);
2963 tcg_temp_free_i32(cpsr);
2964 /* Must exit loop to check un-masked IRQs */
2965 s->base.is_jmp = DISAS_EXIT;
2968 /* Generate an old-style exception return. Marks pc as dead. */
2969 static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
2971 gen_rfe(s, pc, load_cpu_field(spsr));
2974 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
2976 static int gen_neon_unzip(int rd, int rm, int size, int q)
2978 TCGv_ptr pd, pm;
2980 if (!q && size == 2) {
2981 return 1;
2983 pd = vfp_reg_ptr(true, rd);
2984 pm = vfp_reg_ptr(true, rm);
2985 if (q) {
2986 switch (size) {
2987 case 0:
2988 gen_helper_neon_qunzip8(pd, pm);
2989 break;
2990 case 1:
2991 gen_helper_neon_qunzip16(pd, pm);
2992 break;
2993 case 2:
2994 gen_helper_neon_qunzip32(pd, pm);
2995 break;
2996 default:
2997 abort();
2999 } else {
3000 switch (size) {
3001 case 0:
3002 gen_helper_neon_unzip8(pd, pm);
3003 break;
3004 case 1:
3005 gen_helper_neon_unzip16(pd, pm);
3006 break;
3007 default:
3008 abort();
3011 tcg_temp_free_ptr(pd);
3012 tcg_temp_free_ptr(pm);
3013 return 0;
3016 static int gen_neon_zip(int rd, int rm, int size, int q)
3018 TCGv_ptr pd, pm;
3020 if (!q && size == 2) {
3021 return 1;
3023 pd = vfp_reg_ptr(true, rd);
3024 pm = vfp_reg_ptr(true, rm);
3025 if (q) {
3026 switch (size) {
3027 case 0:
3028 gen_helper_neon_qzip8(pd, pm);
3029 break;
3030 case 1:
3031 gen_helper_neon_qzip16(pd, pm);
3032 break;
3033 case 2:
3034 gen_helper_neon_qzip32(pd, pm);
3035 break;
3036 default:
3037 abort();
3039 } else {
3040 switch (size) {
3041 case 0:
3042 gen_helper_neon_zip8(pd, pm);
3043 break;
3044 case 1:
3045 gen_helper_neon_zip16(pd, pm);
3046 break;
3047 default:
3048 abort();
3051 tcg_temp_free_ptr(pd);
3052 tcg_temp_free_ptr(pm);
3053 return 0;
3056 static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
3058 TCGv_i32 rd, tmp;
3060 rd = tcg_temp_new_i32();
3061 tmp = tcg_temp_new_i32();
3063 tcg_gen_shli_i32(rd, t0, 8);
3064 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3065 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3066 tcg_gen_or_i32(rd, rd, tmp);
3068 tcg_gen_shri_i32(t1, t1, 8);
3069 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3070 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3071 tcg_gen_or_i32(t1, t1, tmp);
3072 tcg_gen_mov_i32(t0, rd);
3074 tcg_temp_free_i32(tmp);
3075 tcg_temp_free_i32(rd);
3078 static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
3080 TCGv_i32 rd, tmp;
3082 rd = tcg_temp_new_i32();
3083 tmp = tcg_temp_new_i32();
3085 tcg_gen_shli_i32(rd, t0, 16);
3086 tcg_gen_andi_i32(tmp, t1, 0xffff);
3087 tcg_gen_or_i32(rd, rd, tmp);
3088 tcg_gen_shri_i32(t1, t1, 16);
3089 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3090 tcg_gen_or_i32(t1, t1, tmp);
3091 tcg_gen_mov_i32(t0, rd);
3093 tcg_temp_free_i32(tmp);
3094 tcg_temp_free_i32(rd);
3097 static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src)
3099 switch (size) {
3100 case 0: gen_helper_neon_narrow_u8(dest, src); break;
3101 case 1: gen_helper_neon_narrow_u16(dest, src); break;
3102 case 2: tcg_gen_extrl_i64_i32(dest, src); break;
3103 default: abort();
3107 static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
3109 switch (size) {
3110 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
3111 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
3112 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
3113 default: abort();
3117 static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src)
3119 switch (size) {
3120 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
3121 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
3122 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
3123 default: abort();
3127 static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
3129 switch (size) {
3130 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
3131 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
3132 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
3133 default: abort();
3137 static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
3139 if (u) {
3140 switch (size) {
3141 case 0: gen_helper_neon_widen_u8(dest, src); break;
3142 case 1: gen_helper_neon_widen_u16(dest, src); break;
3143 case 2: tcg_gen_extu_i32_i64(dest, src); break;
3144 default: abort();
3146 } else {
3147 switch (size) {
3148 case 0: gen_helper_neon_widen_s8(dest, src); break;
3149 case 1: gen_helper_neon_widen_s16(dest, src); break;
3150 case 2: tcg_gen_ext_i32_i64(dest, src); break;
3151 default: abort();
3154 tcg_temp_free_i32(src);
3157 static inline void gen_neon_addl(int size)
3159 switch (size) {
3160 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
3161 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
3162 case 2: tcg_gen_add_i64(CPU_V001); break;
3163 default: abort();
3167 static inline void gen_neon_negl(TCGv_i64 var, int size)
3169 switch (size) {
3170 case 0: gen_helper_neon_negl_u16(var, var); break;
3171 case 1: gen_helper_neon_negl_u32(var, var); break;
3172 case 2:
3173 tcg_gen_neg_i64(var, var);
3174 break;
3175 default: abort();
3179 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
3181 switch (size) {
3182 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
3183 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
3184 default: abort();
3188 static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b,
3189 int size, int u)
3191 TCGv_i64 tmp;
3193 switch ((size << 1) | u) {
3194 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
3195 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
3196 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
3197 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
3198 case 4:
3199 tmp = gen_muls_i64_i32(a, b);
3200 tcg_gen_mov_i64(dest, tmp);
3201 tcg_temp_free_i64(tmp);
3202 break;
3203 case 5:
3204 tmp = gen_mulu_i64_i32(a, b);
3205 tcg_gen_mov_i64(dest, tmp);
3206 tcg_temp_free_i64(tmp);
3207 break;
3208 default: abort();
3211 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
3212 Don't forget to clean them now. */
3213 if (size < 2) {
3214 tcg_temp_free_i32(a);
3215 tcg_temp_free_i32(b);
3219 static void gen_neon_narrow_op(int op, int u, int size,
3220 TCGv_i32 dest, TCGv_i64 src)
3222 if (op) {
3223 if (u) {
3224 gen_neon_unarrow_sats(size, dest, src);
3225 } else {
3226 gen_neon_narrow(size, dest, src);
3228 } else {
3229 if (u) {
3230 gen_neon_narrow_satu(size, dest, src);
3231 } else {
3232 gen_neon_narrow_sats(size, dest, src);
3237 /* Symbolic constants for op fields for Neon 2-register miscellaneous.
3238 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
3239 * table A7-13.
3241 #define NEON_2RM_VREV64 0
3242 #define NEON_2RM_VREV32 1
3243 #define NEON_2RM_VREV16 2
3244 #define NEON_2RM_VPADDL 4
3245 #define NEON_2RM_VPADDL_U 5
3246 #define NEON_2RM_AESE 6 /* Includes AESD */
3247 #define NEON_2RM_AESMC 7 /* Includes AESIMC */
3248 #define NEON_2RM_VCLS 8
3249 #define NEON_2RM_VCLZ 9
3250 #define NEON_2RM_VCNT 10
3251 #define NEON_2RM_VMVN 11
3252 #define NEON_2RM_VPADAL 12
3253 #define NEON_2RM_VPADAL_U 13
3254 #define NEON_2RM_VQABS 14
3255 #define NEON_2RM_VQNEG 15
3256 #define NEON_2RM_VCGT0 16
3257 #define NEON_2RM_VCGE0 17
3258 #define NEON_2RM_VCEQ0 18
3259 #define NEON_2RM_VCLE0 19
3260 #define NEON_2RM_VCLT0 20
3261 #define NEON_2RM_SHA1H 21
3262 #define NEON_2RM_VABS 22
3263 #define NEON_2RM_VNEG 23
3264 #define NEON_2RM_VCGT0_F 24
3265 #define NEON_2RM_VCGE0_F 25
3266 #define NEON_2RM_VCEQ0_F 26
3267 #define NEON_2RM_VCLE0_F 27
3268 #define NEON_2RM_VCLT0_F 28
3269 #define NEON_2RM_VABS_F 30
3270 #define NEON_2RM_VNEG_F 31
3271 #define NEON_2RM_VSWP 32
3272 #define NEON_2RM_VTRN 33
3273 #define NEON_2RM_VUZP 34
3274 #define NEON_2RM_VZIP 35
3275 #define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
3276 #define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
3277 #define NEON_2RM_VSHLL 38
3278 #define NEON_2RM_SHA1SU1 39 /* Includes SHA256SU0 */
3279 #define NEON_2RM_VRINTN 40
3280 #define NEON_2RM_VRINTX 41
3281 #define NEON_2RM_VRINTA 42
3282 #define NEON_2RM_VRINTZ 43
3283 #define NEON_2RM_VCVT_F16_F32 44
3284 #define NEON_2RM_VRINTM 45
3285 #define NEON_2RM_VCVT_F32_F16 46
3286 #define NEON_2RM_VRINTP 47
3287 #define NEON_2RM_VCVTAU 48
3288 #define NEON_2RM_VCVTAS 49
3289 #define NEON_2RM_VCVTNU 50
3290 #define NEON_2RM_VCVTNS 51
3291 #define NEON_2RM_VCVTPU 52
3292 #define NEON_2RM_VCVTPS 53
3293 #define NEON_2RM_VCVTMU 54
3294 #define NEON_2RM_VCVTMS 55
3295 #define NEON_2RM_VRECPE 56
3296 #define NEON_2RM_VRSQRTE 57
3297 #define NEON_2RM_VRECPE_F 58
3298 #define NEON_2RM_VRSQRTE_F 59
3299 #define NEON_2RM_VCVT_FS 60
3300 #define NEON_2RM_VCVT_FU 61
3301 #define NEON_2RM_VCVT_SF 62
3302 #define NEON_2RM_VCVT_UF 63
3304 static bool neon_2rm_is_v8_op(int op)
3306 /* Return true if this neon 2reg-misc op is ARMv8 and up */
3307 switch (op) {
3308 case NEON_2RM_VRINTN:
3309 case NEON_2RM_VRINTA:
3310 case NEON_2RM_VRINTM:
3311 case NEON_2RM_VRINTP:
3312 case NEON_2RM_VRINTZ:
3313 case NEON_2RM_VRINTX:
3314 case NEON_2RM_VCVTAU:
3315 case NEON_2RM_VCVTAS:
3316 case NEON_2RM_VCVTNU:
3317 case NEON_2RM_VCVTNS:
3318 case NEON_2RM_VCVTPU:
3319 case NEON_2RM_VCVTPS:
3320 case NEON_2RM_VCVTMU:
3321 case NEON_2RM_VCVTMS:
3322 return true;
3323 default:
3324 return false;
3328 /* Each entry in this array has bit n set if the insn allows
3329 * size value n (otherwise it will UNDEF). Since unallocated
3330 * op values will have no bits set they always UNDEF.
3332 static const uint8_t neon_2rm_sizes[] = {
3333 [NEON_2RM_VREV64] = 0x7,
3334 [NEON_2RM_VREV32] = 0x3,
3335 [NEON_2RM_VREV16] = 0x1,
3336 [NEON_2RM_VPADDL] = 0x7,
3337 [NEON_2RM_VPADDL_U] = 0x7,
3338 [NEON_2RM_AESE] = 0x1,
3339 [NEON_2RM_AESMC] = 0x1,
3340 [NEON_2RM_VCLS] = 0x7,
3341 [NEON_2RM_VCLZ] = 0x7,
3342 [NEON_2RM_VCNT] = 0x1,
3343 [NEON_2RM_VMVN] = 0x1,
3344 [NEON_2RM_VPADAL] = 0x7,
3345 [NEON_2RM_VPADAL_U] = 0x7,
3346 [NEON_2RM_VQABS] = 0x7,
3347 [NEON_2RM_VQNEG] = 0x7,
3348 [NEON_2RM_VCGT0] = 0x7,
3349 [NEON_2RM_VCGE0] = 0x7,
3350 [NEON_2RM_VCEQ0] = 0x7,
3351 [NEON_2RM_VCLE0] = 0x7,
3352 [NEON_2RM_VCLT0] = 0x7,
3353 [NEON_2RM_SHA1H] = 0x4,
3354 [NEON_2RM_VABS] = 0x7,
3355 [NEON_2RM_VNEG] = 0x7,
3356 [NEON_2RM_VCGT0_F] = 0x4,
3357 [NEON_2RM_VCGE0_F] = 0x4,
3358 [NEON_2RM_VCEQ0_F] = 0x4,
3359 [NEON_2RM_VCLE0_F] = 0x4,
3360 [NEON_2RM_VCLT0_F] = 0x4,
3361 [NEON_2RM_VABS_F] = 0x4,
3362 [NEON_2RM_VNEG_F] = 0x4,
3363 [NEON_2RM_VSWP] = 0x1,
3364 [NEON_2RM_VTRN] = 0x7,
3365 [NEON_2RM_VUZP] = 0x7,
3366 [NEON_2RM_VZIP] = 0x7,
3367 [NEON_2RM_VMOVN] = 0x7,
3368 [NEON_2RM_VQMOVN] = 0x7,
3369 [NEON_2RM_VSHLL] = 0x7,
3370 [NEON_2RM_SHA1SU1] = 0x4,
3371 [NEON_2RM_VRINTN] = 0x4,
3372 [NEON_2RM_VRINTX] = 0x4,
3373 [NEON_2RM_VRINTA] = 0x4,
3374 [NEON_2RM_VRINTZ] = 0x4,
3375 [NEON_2RM_VCVT_F16_F32] = 0x2,
3376 [NEON_2RM_VRINTM] = 0x4,
3377 [NEON_2RM_VCVT_F32_F16] = 0x2,
3378 [NEON_2RM_VRINTP] = 0x4,
3379 [NEON_2RM_VCVTAU] = 0x4,
3380 [NEON_2RM_VCVTAS] = 0x4,
3381 [NEON_2RM_VCVTNU] = 0x4,
3382 [NEON_2RM_VCVTNS] = 0x4,
3383 [NEON_2RM_VCVTPU] = 0x4,
3384 [NEON_2RM_VCVTPS] = 0x4,
3385 [NEON_2RM_VCVTMU] = 0x4,
3386 [NEON_2RM_VCVTMS] = 0x4,
3387 [NEON_2RM_VRECPE] = 0x4,
3388 [NEON_2RM_VRSQRTE] = 0x4,
3389 [NEON_2RM_VRECPE_F] = 0x4,
3390 [NEON_2RM_VRSQRTE_F] = 0x4,
3391 [NEON_2RM_VCVT_FS] = 0x4,
3392 [NEON_2RM_VCVT_FU] = 0x4,
3393 [NEON_2RM_VCVT_SF] = 0x4,
3394 [NEON_2RM_VCVT_UF] = 0x4,
3397 static void gen_gvec_fn3_qc(uint32_t rd_ofs, uint32_t rn_ofs, uint32_t rm_ofs,
3398 uint32_t opr_sz, uint32_t max_sz,
3399 gen_helper_gvec_3_ptr *fn)
3401 TCGv_ptr qc_ptr = tcg_temp_new_ptr();
3403 tcg_gen_addi_ptr(qc_ptr, cpu_env, offsetof(CPUARMState, vfp.qc));
3404 tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, qc_ptr,
3405 opr_sz, max_sz, 0, fn);
3406 tcg_temp_free_ptr(qc_ptr);
3409 void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
3410 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
3412 static gen_helper_gvec_3_ptr * const fns[2] = {
3413 gen_helper_gvec_qrdmlah_s16, gen_helper_gvec_qrdmlah_s32
3415 tcg_debug_assert(vece >= 1 && vece <= 2);
3416 gen_gvec_fn3_qc(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, fns[vece - 1]);
3419 void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
3420 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
3422 static gen_helper_gvec_3_ptr * const fns[2] = {
3423 gen_helper_gvec_qrdmlsh_s16, gen_helper_gvec_qrdmlsh_s32
3425 tcg_debug_assert(vece >= 1 && vece <= 2);
3426 gen_gvec_fn3_qc(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, fns[vece - 1]);
3429 #define GEN_CMP0(NAME, COND) \
3430 static void gen_##NAME##0_i32(TCGv_i32 d, TCGv_i32 a) \
3432 tcg_gen_setcondi_i32(COND, d, a, 0); \
3433 tcg_gen_neg_i32(d, d); \
3435 static void gen_##NAME##0_i64(TCGv_i64 d, TCGv_i64 a) \
3437 tcg_gen_setcondi_i64(COND, d, a, 0); \
3438 tcg_gen_neg_i64(d, d); \
3440 static void gen_##NAME##0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) \
3442 TCGv_vec zero = tcg_const_zeros_vec_matching(d); \
3443 tcg_gen_cmp_vec(COND, vece, d, a, zero); \
3444 tcg_temp_free_vec(zero); \
3446 void gen_gvec_##NAME##0(unsigned vece, uint32_t d, uint32_t m, \
3447 uint32_t opr_sz, uint32_t max_sz) \
3449 const GVecGen2 op[4] = { \
3450 { .fno = gen_helper_gvec_##NAME##0_b, \
3451 .fniv = gen_##NAME##0_vec, \
3452 .opt_opc = vecop_list_cmp, \
3453 .vece = MO_8 }, \
3454 { .fno = gen_helper_gvec_##NAME##0_h, \
3455 .fniv = gen_##NAME##0_vec, \
3456 .opt_opc = vecop_list_cmp, \
3457 .vece = MO_16 }, \
3458 { .fni4 = gen_##NAME##0_i32, \
3459 .fniv = gen_##NAME##0_vec, \
3460 .opt_opc = vecop_list_cmp, \
3461 .vece = MO_32 }, \
3462 { .fni8 = gen_##NAME##0_i64, \
3463 .fniv = gen_##NAME##0_vec, \
3464 .opt_opc = vecop_list_cmp, \
3465 .prefer_i64 = TCG_TARGET_REG_BITS == 64, \
3466 .vece = MO_64 }, \
3467 }; \
3468 tcg_gen_gvec_2(d, m, opr_sz, max_sz, &op[vece]); \
3471 static const TCGOpcode vecop_list_cmp[] = {
3472 INDEX_op_cmp_vec, 0
3475 GEN_CMP0(ceq, TCG_COND_EQ)
3476 GEN_CMP0(cle, TCG_COND_LE)
3477 GEN_CMP0(cge, TCG_COND_GE)
3478 GEN_CMP0(clt, TCG_COND_LT)
3479 GEN_CMP0(cgt, TCG_COND_GT)
3481 #undef GEN_CMP0
3483 static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3485 tcg_gen_vec_sar8i_i64(a, a, shift);
3486 tcg_gen_vec_add8_i64(d, d, a);
3489 static void gen_ssra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3491 tcg_gen_vec_sar16i_i64(a, a, shift);
3492 tcg_gen_vec_add16_i64(d, d, a);
3495 static void gen_ssra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
3497 tcg_gen_sari_i32(a, a, shift);
3498 tcg_gen_add_i32(d, d, a);
3501 static void gen_ssra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3503 tcg_gen_sari_i64(a, a, shift);
3504 tcg_gen_add_i64(d, d, a);
3507 static void gen_ssra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3509 tcg_gen_sari_vec(vece, a, a, sh);
3510 tcg_gen_add_vec(vece, d, d, a);
3513 void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3514 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3516 static const TCGOpcode vecop_list[] = {
3517 INDEX_op_sari_vec, INDEX_op_add_vec, 0
3519 static const GVecGen2i ops[4] = {
3520 { .fni8 = gen_ssra8_i64,
3521 .fniv = gen_ssra_vec,
3522 .fno = gen_helper_gvec_ssra_b,
3523 .load_dest = true,
3524 .opt_opc = vecop_list,
3525 .vece = MO_8 },
3526 { .fni8 = gen_ssra16_i64,
3527 .fniv = gen_ssra_vec,
3528 .fno = gen_helper_gvec_ssra_h,
3529 .load_dest = true,
3530 .opt_opc = vecop_list,
3531 .vece = MO_16 },
3532 { .fni4 = gen_ssra32_i32,
3533 .fniv = gen_ssra_vec,
3534 .fno = gen_helper_gvec_ssra_s,
3535 .load_dest = true,
3536 .opt_opc = vecop_list,
3537 .vece = MO_32 },
3538 { .fni8 = gen_ssra64_i64,
3539 .fniv = gen_ssra_vec,
3540 .fno = gen_helper_gvec_ssra_b,
3541 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3542 .opt_opc = vecop_list,
3543 .load_dest = true,
3544 .vece = MO_64 },
3547 /* tszimm encoding produces immediates in the range [1..esize]. */
3548 tcg_debug_assert(shift > 0);
3549 tcg_debug_assert(shift <= (8 << vece));
3552 * Shifts larger than the element size are architecturally valid.
3553 * Signed results in all sign bits.
3555 shift = MIN(shift, (8 << vece) - 1);
3556 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3559 static void gen_usra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3561 tcg_gen_vec_shr8i_i64(a, a, shift);
3562 tcg_gen_vec_add8_i64(d, d, a);
3565 static void gen_usra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3567 tcg_gen_vec_shr16i_i64(a, a, shift);
3568 tcg_gen_vec_add16_i64(d, d, a);
3571 static void gen_usra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
3573 tcg_gen_shri_i32(a, a, shift);
3574 tcg_gen_add_i32(d, d, a);
3577 static void gen_usra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
3579 tcg_gen_shri_i64(a, a, shift);
3580 tcg_gen_add_i64(d, d, a);
3583 static void gen_usra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3585 tcg_gen_shri_vec(vece, a, a, sh);
3586 tcg_gen_add_vec(vece, d, d, a);
3589 void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3590 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3592 static const TCGOpcode vecop_list[] = {
3593 INDEX_op_shri_vec, INDEX_op_add_vec, 0
3595 static const GVecGen2i ops[4] = {
3596 { .fni8 = gen_usra8_i64,
3597 .fniv = gen_usra_vec,
3598 .fno = gen_helper_gvec_usra_b,
3599 .load_dest = true,
3600 .opt_opc = vecop_list,
3601 .vece = MO_8, },
3602 { .fni8 = gen_usra16_i64,
3603 .fniv = gen_usra_vec,
3604 .fno = gen_helper_gvec_usra_h,
3605 .load_dest = true,
3606 .opt_opc = vecop_list,
3607 .vece = MO_16, },
3608 { .fni4 = gen_usra32_i32,
3609 .fniv = gen_usra_vec,
3610 .fno = gen_helper_gvec_usra_s,
3611 .load_dest = true,
3612 .opt_opc = vecop_list,
3613 .vece = MO_32, },
3614 { .fni8 = gen_usra64_i64,
3615 .fniv = gen_usra_vec,
3616 .fno = gen_helper_gvec_usra_d,
3617 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3618 .load_dest = true,
3619 .opt_opc = vecop_list,
3620 .vece = MO_64, },
3623 /* tszimm encoding produces immediates in the range [1..esize]. */
3624 tcg_debug_assert(shift > 0);
3625 tcg_debug_assert(shift <= (8 << vece));
3628 * Shifts larger than the element size are architecturally valid.
3629 * Unsigned results in all zeros as input to accumulate: nop.
3631 if (shift < (8 << vece)) {
3632 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3633 } else {
3634 /* Nop, but we do need to clear the tail. */
3635 tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz);
3640 * Shift one less than the requested amount, and the low bit is
3641 * the rounding bit. For the 8 and 16-bit operations, because we
3642 * mask the low bit, we can perform a normal integer shift instead
3643 * of a vector shift.
3645 static void gen_srshr8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3647 TCGv_i64 t = tcg_temp_new_i64();
3649 tcg_gen_shri_i64(t, a, sh - 1);
3650 tcg_gen_andi_i64(t, t, dup_const(MO_8, 1));
3651 tcg_gen_vec_sar8i_i64(d, a, sh);
3652 tcg_gen_vec_add8_i64(d, d, t);
3653 tcg_temp_free_i64(t);
3656 static void gen_srshr16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3658 TCGv_i64 t = tcg_temp_new_i64();
3660 tcg_gen_shri_i64(t, a, sh - 1);
3661 tcg_gen_andi_i64(t, t, dup_const(MO_16, 1));
3662 tcg_gen_vec_sar16i_i64(d, a, sh);
3663 tcg_gen_vec_add16_i64(d, d, t);
3664 tcg_temp_free_i64(t);
3667 static void gen_srshr32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
3669 TCGv_i32 t = tcg_temp_new_i32();
3671 tcg_gen_extract_i32(t, a, sh - 1, 1);
3672 tcg_gen_sari_i32(d, a, sh);
3673 tcg_gen_add_i32(d, d, t);
3674 tcg_temp_free_i32(t);
3677 static void gen_srshr64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3679 TCGv_i64 t = tcg_temp_new_i64();
3681 tcg_gen_extract_i64(t, a, sh - 1, 1);
3682 tcg_gen_sari_i64(d, a, sh);
3683 tcg_gen_add_i64(d, d, t);
3684 tcg_temp_free_i64(t);
3687 static void gen_srshr_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3689 TCGv_vec t = tcg_temp_new_vec_matching(d);
3690 TCGv_vec ones = tcg_temp_new_vec_matching(d);
3692 tcg_gen_shri_vec(vece, t, a, sh - 1);
3693 tcg_gen_dupi_vec(vece, ones, 1);
3694 tcg_gen_and_vec(vece, t, t, ones);
3695 tcg_gen_sari_vec(vece, d, a, sh);
3696 tcg_gen_add_vec(vece, d, d, t);
3698 tcg_temp_free_vec(t);
3699 tcg_temp_free_vec(ones);
3702 void gen_gvec_srshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3703 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3705 static const TCGOpcode vecop_list[] = {
3706 INDEX_op_shri_vec, INDEX_op_sari_vec, INDEX_op_add_vec, 0
3708 static const GVecGen2i ops[4] = {
3709 { .fni8 = gen_srshr8_i64,
3710 .fniv = gen_srshr_vec,
3711 .fno = gen_helper_gvec_srshr_b,
3712 .opt_opc = vecop_list,
3713 .vece = MO_8 },
3714 { .fni8 = gen_srshr16_i64,
3715 .fniv = gen_srshr_vec,
3716 .fno = gen_helper_gvec_srshr_h,
3717 .opt_opc = vecop_list,
3718 .vece = MO_16 },
3719 { .fni4 = gen_srshr32_i32,
3720 .fniv = gen_srshr_vec,
3721 .fno = gen_helper_gvec_srshr_s,
3722 .opt_opc = vecop_list,
3723 .vece = MO_32 },
3724 { .fni8 = gen_srshr64_i64,
3725 .fniv = gen_srshr_vec,
3726 .fno = gen_helper_gvec_srshr_d,
3727 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3728 .opt_opc = vecop_list,
3729 .vece = MO_64 },
3732 /* tszimm encoding produces immediates in the range [1..esize] */
3733 tcg_debug_assert(shift > 0);
3734 tcg_debug_assert(shift <= (8 << vece));
3736 if (shift == (8 << vece)) {
3738 * Shifts larger than the element size are architecturally valid.
3739 * Signed results in all sign bits. With rounding, this produces
3740 * (-1 + 1) >> 1 == 0, or (0 + 1) >> 1 == 0.
3741 * I.e. always zero.
3743 tcg_gen_gvec_dup_imm(vece, rd_ofs, opr_sz, max_sz, 0);
3744 } else {
3745 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3749 static void gen_srsra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3751 TCGv_i64 t = tcg_temp_new_i64();
3753 gen_srshr8_i64(t, a, sh);
3754 tcg_gen_vec_add8_i64(d, d, t);
3755 tcg_temp_free_i64(t);
3758 static void gen_srsra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3760 TCGv_i64 t = tcg_temp_new_i64();
3762 gen_srshr16_i64(t, a, sh);
3763 tcg_gen_vec_add16_i64(d, d, t);
3764 tcg_temp_free_i64(t);
3767 static void gen_srsra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
3769 TCGv_i32 t = tcg_temp_new_i32();
3771 gen_srshr32_i32(t, a, sh);
3772 tcg_gen_add_i32(d, d, t);
3773 tcg_temp_free_i32(t);
3776 static void gen_srsra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3778 TCGv_i64 t = tcg_temp_new_i64();
3780 gen_srshr64_i64(t, a, sh);
3781 tcg_gen_add_i64(d, d, t);
3782 tcg_temp_free_i64(t);
3785 static void gen_srsra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
3787 TCGv_vec t = tcg_temp_new_vec_matching(d);
3789 gen_srshr_vec(vece, t, a, sh);
3790 tcg_gen_add_vec(vece, d, d, t);
3791 tcg_temp_free_vec(t);
3794 void gen_gvec_srsra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3795 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3797 static const TCGOpcode vecop_list[] = {
3798 INDEX_op_shri_vec, INDEX_op_sari_vec, INDEX_op_add_vec, 0
3800 static const GVecGen2i ops[4] = {
3801 { .fni8 = gen_srsra8_i64,
3802 .fniv = gen_srsra_vec,
3803 .fno = gen_helper_gvec_srsra_b,
3804 .opt_opc = vecop_list,
3805 .load_dest = true,
3806 .vece = MO_8 },
3807 { .fni8 = gen_srsra16_i64,
3808 .fniv = gen_srsra_vec,
3809 .fno = gen_helper_gvec_srsra_h,
3810 .opt_opc = vecop_list,
3811 .load_dest = true,
3812 .vece = MO_16 },
3813 { .fni4 = gen_srsra32_i32,
3814 .fniv = gen_srsra_vec,
3815 .fno = gen_helper_gvec_srsra_s,
3816 .opt_opc = vecop_list,
3817 .load_dest = true,
3818 .vece = MO_32 },
3819 { .fni8 = gen_srsra64_i64,
3820 .fniv = gen_srsra_vec,
3821 .fno = gen_helper_gvec_srsra_d,
3822 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3823 .opt_opc = vecop_list,
3824 .load_dest = true,
3825 .vece = MO_64 },
3828 /* tszimm encoding produces immediates in the range [1..esize] */
3829 tcg_debug_assert(shift > 0);
3830 tcg_debug_assert(shift <= (8 << vece));
3833 * Shifts larger than the element size are architecturally valid.
3834 * Signed results in all sign bits. With rounding, this produces
3835 * (-1 + 1) >> 1 == 0, or (0 + 1) >> 1 == 0.
3836 * I.e. always zero. With accumulation, this leaves D unchanged.
3838 if (shift == (8 << vece)) {
3839 /* Nop, but we do need to clear the tail. */
3840 tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz);
3841 } else {
3842 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3846 static void gen_urshr8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3848 TCGv_i64 t = tcg_temp_new_i64();
3850 tcg_gen_shri_i64(t, a, sh - 1);
3851 tcg_gen_andi_i64(t, t, dup_const(MO_8, 1));
3852 tcg_gen_vec_shr8i_i64(d, a, sh);
3853 tcg_gen_vec_add8_i64(d, d, t);
3854 tcg_temp_free_i64(t);
3857 static void gen_urshr16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3859 TCGv_i64 t = tcg_temp_new_i64();
3861 tcg_gen_shri_i64(t, a, sh - 1);
3862 tcg_gen_andi_i64(t, t, dup_const(MO_16, 1));
3863 tcg_gen_vec_shr16i_i64(d, a, sh);
3864 tcg_gen_vec_add16_i64(d, d, t);
3865 tcg_temp_free_i64(t);
3868 static void gen_urshr32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
3870 TCGv_i32 t = tcg_temp_new_i32();
3872 tcg_gen_extract_i32(t, a, sh - 1, 1);
3873 tcg_gen_shri_i32(d, a, sh);
3874 tcg_gen_add_i32(d, d, t);
3875 tcg_temp_free_i32(t);
3878 static void gen_urshr64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3880 TCGv_i64 t = tcg_temp_new_i64();
3882 tcg_gen_extract_i64(t, a, sh - 1, 1);
3883 tcg_gen_shri_i64(d, a, sh);
3884 tcg_gen_add_i64(d, d, t);
3885 tcg_temp_free_i64(t);
3888 static void gen_urshr_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t shift)
3890 TCGv_vec t = tcg_temp_new_vec_matching(d);
3891 TCGv_vec ones = tcg_temp_new_vec_matching(d);
3893 tcg_gen_shri_vec(vece, t, a, shift - 1);
3894 tcg_gen_dupi_vec(vece, ones, 1);
3895 tcg_gen_and_vec(vece, t, t, ones);
3896 tcg_gen_shri_vec(vece, d, a, shift);
3897 tcg_gen_add_vec(vece, d, d, t);
3899 tcg_temp_free_vec(t);
3900 tcg_temp_free_vec(ones);
3903 void gen_gvec_urshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
3904 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
3906 static const TCGOpcode vecop_list[] = {
3907 INDEX_op_shri_vec, INDEX_op_add_vec, 0
3909 static const GVecGen2i ops[4] = {
3910 { .fni8 = gen_urshr8_i64,
3911 .fniv = gen_urshr_vec,
3912 .fno = gen_helper_gvec_urshr_b,
3913 .opt_opc = vecop_list,
3914 .vece = MO_8 },
3915 { .fni8 = gen_urshr16_i64,
3916 .fniv = gen_urshr_vec,
3917 .fno = gen_helper_gvec_urshr_h,
3918 .opt_opc = vecop_list,
3919 .vece = MO_16 },
3920 { .fni4 = gen_urshr32_i32,
3921 .fniv = gen_urshr_vec,
3922 .fno = gen_helper_gvec_urshr_s,
3923 .opt_opc = vecop_list,
3924 .vece = MO_32 },
3925 { .fni8 = gen_urshr64_i64,
3926 .fniv = gen_urshr_vec,
3927 .fno = gen_helper_gvec_urshr_d,
3928 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
3929 .opt_opc = vecop_list,
3930 .vece = MO_64 },
3933 /* tszimm encoding produces immediates in the range [1..esize] */
3934 tcg_debug_assert(shift > 0);
3935 tcg_debug_assert(shift <= (8 << vece));
3937 if (shift == (8 << vece)) {
3939 * Shifts larger than the element size are architecturally valid.
3940 * Unsigned results in zero. With rounding, this produces a
3941 * copy of the most significant bit.
3943 tcg_gen_gvec_shri(vece, rd_ofs, rm_ofs, shift - 1, opr_sz, max_sz);
3944 } else {
3945 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
3949 static void gen_ursra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3951 TCGv_i64 t = tcg_temp_new_i64();
3953 if (sh == 8) {
3954 tcg_gen_vec_shr8i_i64(t, a, 7);
3955 } else {
3956 gen_urshr8_i64(t, a, sh);
3958 tcg_gen_vec_add8_i64(d, d, t);
3959 tcg_temp_free_i64(t);
3962 static void gen_ursra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3964 TCGv_i64 t = tcg_temp_new_i64();
3966 if (sh == 16) {
3967 tcg_gen_vec_shr16i_i64(t, a, 15);
3968 } else {
3969 gen_urshr16_i64(t, a, sh);
3971 tcg_gen_vec_add16_i64(d, d, t);
3972 tcg_temp_free_i64(t);
3975 static void gen_ursra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
3977 TCGv_i32 t = tcg_temp_new_i32();
3979 if (sh == 32) {
3980 tcg_gen_shri_i32(t, a, 31);
3981 } else {
3982 gen_urshr32_i32(t, a, sh);
3984 tcg_gen_add_i32(d, d, t);
3985 tcg_temp_free_i32(t);
3988 static void gen_ursra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
3990 TCGv_i64 t = tcg_temp_new_i64();
3992 if (sh == 64) {
3993 tcg_gen_shri_i64(t, a, 63);
3994 } else {
3995 gen_urshr64_i64(t, a, sh);
3997 tcg_gen_add_i64(d, d, t);
3998 tcg_temp_free_i64(t);
4001 static void gen_ursra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
4003 TCGv_vec t = tcg_temp_new_vec_matching(d);
4005 if (sh == (8 << vece)) {
4006 tcg_gen_shri_vec(vece, t, a, sh - 1);
4007 } else {
4008 gen_urshr_vec(vece, t, a, sh);
4010 tcg_gen_add_vec(vece, d, d, t);
4011 tcg_temp_free_vec(t);
4014 void gen_gvec_ursra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
4015 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
4017 static const TCGOpcode vecop_list[] = {
4018 INDEX_op_shri_vec, INDEX_op_add_vec, 0
4020 static const GVecGen2i ops[4] = {
4021 { .fni8 = gen_ursra8_i64,
4022 .fniv = gen_ursra_vec,
4023 .fno = gen_helper_gvec_ursra_b,
4024 .opt_opc = vecop_list,
4025 .load_dest = true,
4026 .vece = MO_8 },
4027 { .fni8 = gen_ursra16_i64,
4028 .fniv = gen_ursra_vec,
4029 .fno = gen_helper_gvec_ursra_h,
4030 .opt_opc = vecop_list,
4031 .load_dest = true,
4032 .vece = MO_16 },
4033 { .fni4 = gen_ursra32_i32,
4034 .fniv = gen_ursra_vec,
4035 .fno = gen_helper_gvec_ursra_s,
4036 .opt_opc = vecop_list,
4037 .load_dest = true,
4038 .vece = MO_32 },
4039 { .fni8 = gen_ursra64_i64,
4040 .fniv = gen_ursra_vec,
4041 .fno = gen_helper_gvec_ursra_d,
4042 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4043 .opt_opc = vecop_list,
4044 .load_dest = true,
4045 .vece = MO_64 },
4048 /* tszimm encoding produces immediates in the range [1..esize] */
4049 tcg_debug_assert(shift > 0);
4050 tcg_debug_assert(shift <= (8 << vece));
4052 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
4055 static void gen_shr8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4057 uint64_t mask = dup_const(MO_8, 0xff >> shift);
4058 TCGv_i64 t = tcg_temp_new_i64();
4060 tcg_gen_shri_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_shr16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4069 uint64_t mask = dup_const(MO_16, 0xffff >> shift);
4070 TCGv_i64 t = tcg_temp_new_i64();
4072 tcg_gen_shri_i64(t, a, shift);
4073 tcg_gen_andi_i64(t, t, mask);
4074 tcg_gen_andi_i64(d, d, ~mask);
4075 tcg_gen_or_i64(d, d, t);
4076 tcg_temp_free_i64(t);
4079 static void gen_shr32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
4081 tcg_gen_shri_i32(a, a, shift);
4082 tcg_gen_deposit_i32(d, d, a, 0, 32 - shift);
4085 static void gen_shr64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4087 tcg_gen_shri_i64(a, a, shift);
4088 tcg_gen_deposit_i64(d, d, a, 0, 64 - shift);
4091 static void gen_shr_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
4093 TCGv_vec t = tcg_temp_new_vec_matching(d);
4094 TCGv_vec m = tcg_temp_new_vec_matching(d);
4096 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK((8 << vece) - sh, sh));
4097 tcg_gen_shri_vec(vece, t, a, sh);
4098 tcg_gen_and_vec(vece, d, d, m);
4099 tcg_gen_or_vec(vece, d, d, t);
4101 tcg_temp_free_vec(t);
4102 tcg_temp_free_vec(m);
4105 void gen_gvec_sri(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
4106 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
4108 static const TCGOpcode vecop_list[] = { INDEX_op_shri_vec, 0 };
4109 const GVecGen2i ops[4] = {
4110 { .fni8 = gen_shr8_ins_i64,
4111 .fniv = gen_shr_ins_vec,
4112 .fno = gen_helper_gvec_sri_b,
4113 .load_dest = true,
4114 .opt_opc = vecop_list,
4115 .vece = MO_8 },
4116 { .fni8 = gen_shr16_ins_i64,
4117 .fniv = gen_shr_ins_vec,
4118 .fno = gen_helper_gvec_sri_h,
4119 .load_dest = true,
4120 .opt_opc = vecop_list,
4121 .vece = MO_16 },
4122 { .fni4 = gen_shr32_ins_i32,
4123 .fniv = gen_shr_ins_vec,
4124 .fno = gen_helper_gvec_sri_s,
4125 .load_dest = true,
4126 .opt_opc = vecop_list,
4127 .vece = MO_32 },
4128 { .fni8 = gen_shr64_ins_i64,
4129 .fniv = gen_shr_ins_vec,
4130 .fno = gen_helper_gvec_sri_d,
4131 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4132 .load_dest = true,
4133 .opt_opc = vecop_list,
4134 .vece = MO_64 },
4137 /* tszimm encoding produces immediates in the range [1..esize]. */
4138 tcg_debug_assert(shift > 0);
4139 tcg_debug_assert(shift <= (8 << vece));
4141 /* Shift of esize leaves destination unchanged. */
4142 if (shift < (8 << vece)) {
4143 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
4144 } else {
4145 /* Nop, but we do need to clear the tail. */
4146 tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz);
4150 static void gen_shl8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4152 uint64_t mask = dup_const(MO_8, 0xff << shift);
4153 TCGv_i64 t = tcg_temp_new_i64();
4155 tcg_gen_shli_i64(t, a, shift);
4156 tcg_gen_andi_i64(t, t, mask);
4157 tcg_gen_andi_i64(d, d, ~mask);
4158 tcg_gen_or_i64(d, d, t);
4159 tcg_temp_free_i64(t);
4162 static void gen_shl16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4164 uint64_t mask = dup_const(MO_16, 0xffff << shift);
4165 TCGv_i64 t = tcg_temp_new_i64();
4167 tcg_gen_shli_i64(t, a, shift);
4168 tcg_gen_andi_i64(t, t, mask);
4169 tcg_gen_andi_i64(d, d, ~mask);
4170 tcg_gen_or_i64(d, d, t);
4171 tcg_temp_free_i64(t);
4174 static void gen_shl32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
4176 tcg_gen_deposit_i32(d, d, a, shift, 32 - shift);
4179 static void gen_shl64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4181 tcg_gen_deposit_i64(d, d, a, shift, 64 - shift);
4184 static void gen_shl_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
4186 TCGv_vec t = tcg_temp_new_vec_matching(d);
4187 TCGv_vec m = tcg_temp_new_vec_matching(d);
4189 tcg_gen_shli_vec(vece, t, a, sh);
4190 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK(0, sh));
4191 tcg_gen_and_vec(vece, d, d, m);
4192 tcg_gen_or_vec(vece, d, d, t);
4194 tcg_temp_free_vec(t);
4195 tcg_temp_free_vec(m);
4198 void gen_gvec_sli(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
4199 int64_t shift, uint32_t opr_sz, uint32_t max_sz)
4201 static const TCGOpcode vecop_list[] = { INDEX_op_shli_vec, 0 };
4202 const GVecGen2i ops[4] = {
4203 { .fni8 = gen_shl8_ins_i64,
4204 .fniv = gen_shl_ins_vec,
4205 .fno = gen_helper_gvec_sli_b,
4206 .load_dest = true,
4207 .opt_opc = vecop_list,
4208 .vece = MO_8 },
4209 { .fni8 = gen_shl16_ins_i64,
4210 .fniv = gen_shl_ins_vec,
4211 .fno = gen_helper_gvec_sli_h,
4212 .load_dest = true,
4213 .opt_opc = vecop_list,
4214 .vece = MO_16 },
4215 { .fni4 = gen_shl32_ins_i32,
4216 .fniv = gen_shl_ins_vec,
4217 .fno = gen_helper_gvec_sli_s,
4218 .load_dest = true,
4219 .opt_opc = vecop_list,
4220 .vece = MO_32 },
4221 { .fni8 = gen_shl64_ins_i64,
4222 .fniv = gen_shl_ins_vec,
4223 .fno = gen_helper_gvec_sli_d,
4224 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4225 .load_dest = true,
4226 .opt_opc = vecop_list,
4227 .vece = MO_64 },
4230 /* tszimm encoding produces immediates in the range [0..esize-1]. */
4231 tcg_debug_assert(shift >= 0);
4232 tcg_debug_assert(shift < (8 << vece));
4234 if (shift == 0) {
4235 tcg_gen_gvec_mov(vece, rd_ofs, rm_ofs, opr_sz, max_sz);
4236 } else {
4237 tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
4241 static void gen_mla8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4243 gen_helper_neon_mul_u8(a, a, b);
4244 gen_helper_neon_add_u8(d, d, a);
4247 static void gen_mls8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4249 gen_helper_neon_mul_u8(a, a, b);
4250 gen_helper_neon_sub_u8(d, d, a);
4253 static void gen_mla16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4255 gen_helper_neon_mul_u16(a, a, b);
4256 gen_helper_neon_add_u16(d, d, a);
4259 static void gen_mls16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4261 gen_helper_neon_mul_u16(a, a, b);
4262 gen_helper_neon_sub_u16(d, d, a);
4265 static void gen_mla32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4267 tcg_gen_mul_i32(a, a, b);
4268 tcg_gen_add_i32(d, d, a);
4271 static void gen_mls32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4273 tcg_gen_mul_i32(a, a, b);
4274 tcg_gen_sub_i32(d, d, a);
4277 static void gen_mla64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4279 tcg_gen_mul_i64(a, a, b);
4280 tcg_gen_add_i64(d, d, a);
4283 static void gen_mls64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4285 tcg_gen_mul_i64(a, a, b);
4286 tcg_gen_sub_i64(d, d, a);
4289 static void gen_mla_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4291 tcg_gen_mul_vec(vece, a, a, b);
4292 tcg_gen_add_vec(vece, d, d, a);
4295 static void gen_mls_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4297 tcg_gen_mul_vec(vece, a, a, b);
4298 tcg_gen_sub_vec(vece, d, d, a);
4301 /* Note that while NEON does not support VMLA and VMLS as 64-bit ops,
4302 * these tables are shared with AArch64 which does support them.
4304 void gen_gvec_mla(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4305 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4307 static const TCGOpcode vecop_list[] = {
4308 INDEX_op_mul_vec, INDEX_op_add_vec, 0
4310 static const GVecGen3 ops[4] = {
4311 { .fni4 = gen_mla8_i32,
4312 .fniv = gen_mla_vec,
4313 .load_dest = true,
4314 .opt_opc = vecop_list,
4315 .vece = MO_8 },
4316 { .fni4 = gen_mla16_i32,
4317 .fniv = gen_mla_vec,
4318 .load_dest = true,
4319 .opt_opc = vecop_list,
4320 .vece = MO_16 },
4321 { .fni4 = gen_mla32_i32,
4322 .fniv = gen_mla_vec,
4323 .load_dest = true,
4324 .opt_opc = vecop_list,
4325 .vece = MO_32 },
4326 { .fni8 = gen_mla64_i64,
4327 .fniv = gen_mla_vec,
4328 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4329 .load_dest = true,
4330 .opt_opc = vecop_list,
4331 .vece = MO_64 },
4333 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4336 void gen_gvec_mls(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4337 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4339 static const TCGOpcode vecop_list[] = {
4340 INDEX_op_mul_vec, INDEX_op_sub_vec, 0
4342 static const GVecGen3 ops[4] = {
4343 { .fni4 = gen_mls8_i32,
4344 .fniv = gen_mls_vec,
4345 .load_dest = true,
4346 .opt_opc = vecop_list,
4347 .vece = MO_8 },
4348 { .fni4 = gen_mls16_i32,
4349 .fniv = gen_mls_vec,
4350 .load_dest = true,
4351 .opt_opc = vecop_list,
4352 .vece = MO_16 },
4353 { .fni4 = gen_mls32_i32,
4354 .fniv = gen_mls_vec,
4355 .load_dest = true,
4356 .opt_opc = vecop_list,
4357 .vece = MO_32 },
4358 { .fni8 = gen_mls64_i64,
4359 .fniv = gen_mls_vec,
4360 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4361 .load_dest = true,
4362 .opt_opc = vecop_list,
4363 .vece = MO_64 },
4365 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4368 /* CMTST : test is "if (X & Y != 0)". */
4369 static void gen_cmtst_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4371 tcg_gen_and_i32(d, a, b);
4372 tcg_gen_setcondi_i32(TCG_COND_NE, d, d, 0);
4373 tcg_gen_neg_i32(d, d);
4376 void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4378 tcg_gen_and_i64(d, a, b);
4379 tcg_gen_setcondi_i64(TCG_COND_NE, d, d, 0);
4380 tcg_gen_neg_i64(d, d);
4383 static void gen_cmtst_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4385 tcg_gen_and_vec(vece, d, a, b);
4386 tcg_gen_dupi_vec(vece, a, 0);
4387 tcg_gen_cmp_vec(TCG_COND_NE, vece, d, d, a);
4390 void gen_gvec_cmtst(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4391 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4393 static const TCGOpcode vecop_list[] = { INDEX_op_cmp_vec, 0 };
4394 static const GVecGen3 ops[4] = {
4395 { .fni4 = gen_helper_neon_tst_u8,
4396 .fniv = gen_cmtst_vec,
4397 .opt_opc = vecop_list,
4398 .vece = MO_8 },
4399 { .fni4 = gen_helper_neon_tst_u16,
4400 .fniv = gen_cmtst_vec,
4401 .opt_opc = vecop_list,
4402 .vece = MO_16 },
4403 { .fni4 = gen_cmtst_i32,
4404 .fniv = gen_cmtst_vec,
4405 .opt_opc = vecop_list,
4406 .vece = MO_32 },
4407 { .fni8 = gen_cmtst_i64,
4408 .fniv = gen_cmtst_vec,
4409 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4410 .opt_opc = vecop_list,
4411 .vece = MO_64 },
4413 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4416 void gen_ushl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift)
4418 TCGv_i32 lval = tcg_temp_new_i32();
4419 TCGv_i32 rval = tcg_temp_new_i32();
4420 TCGv_i32 lsh = tcg_temp_new_i32();
4421 TCGv_i32 rsh = tcg_temp_new_i32();
4422 TCGv_i32 zero = tcg_const_i32(0);
4423 TCGv_i32 max = tcg_const_i32(32);
4426 * Rely on the TCG guarantee that out of range shifts produce
4427 * unspecified results, not undefined behaviour (i.e. no trap).
4428 * Discard out-of-range results after the fact.
4430 tcg_gen_ext8s_i32(lsh, shift);
4431 tcg_gen_neg_i32(rsh, lsh);
4432 tcg_gen_shl_i32(lval, src, lsh);
4433 tcg_gen_shr_i32(rval, src, rsh);
4434 tcg_gen_movcond_i32(TCG_COND_LTU, dst, lsh, max, lval, zero);
4435 tcg_gen_movcond_i32(TCG_COND_LTU, dst, rsh, max, rval, dst);
4437 tcg_temp_free_i32(lval);
4438 tcg_temp_free_i32(rval);
4439 tcg_temp_free_i32(lsh);
4440 tcg_temp_free_i32(rsh);
4441 tcg_temp_free_i32(zero);
4442 tcg_temp_free_i32(max);
4445 void gen_ushl_i64(TCGv_i64 dst, TCGv_i64 src, TCGv_i64 shift)
4447 TCGv_i64 lval = tcg_temp_new_i64();
4448 TCGv_i64 rval = tcg_temp_new_i64();
4449 TCGv_i64 lsh = tcg_temp_new_i64();
4450 TCGv_i64 rsh = tcg_temp_new_i64();
4451 TCGv_i64 zero = tcg_const_i64(0);
4452 TCGv_i64 max = tcg_const_i64(64);
4455 * Rely on the TCG guarantee that out of range shifts produce
4456 * unspecified results, not undefined behaviour (i.e. no trap).
4457 * Discard out-of-range results after the fact.
4459 tcg_gen_ext8s_i64(lsh, shift);
4460 tcg_gen_neg_i64(rsh, lsh);
4461 tcg_gen_shl_i64(lval, src, lsh);
4462 tcg_gen_shr_i64(rval, src, rsh);
4463 tcg_gen_movcond_i64(TCG_COND_LTU, dst, lsh, max, lval, zero);
4464 tcg_gen_movcond_i64(TCG_COND_LTU, dst, rsh, max, rval, dst);
4466 tcg_temp_free_i64(lval);
4467 tcg_temp_free_i64(rval);
4468 tcg_temp_free_i64(lsh);
4469 tcg_temp_free_i64(rsh);
4470 tcg_temp_free_i64(zero);
4471 tcg_temp_free_i64(max);
4474 static void gen_ushl_vec(unsigned vece, TCGv_vec dst,
4475 TCGv_vec src, TCGv_vec shift)
4477 TCGv_vec lval = tcg_temp_new_vec_matching(dst);
4478 TCGv_vec rval = tcg_temp_new_vec_matching(dst);
4479 TCGv_vec lsh = tcg_temp_new_vec_matching(dst);
4480 TCGv_vec rsh = tcg_temp_new_vec_matching(dst);
4481 TCGv_vec msk, max;
4483 tcg_gen_neg_vec(vece, rsh, shift);
4484 if (vece == MO_8) {
4485 tcg_gen_mov_vec(lsh, shift);
4486 } else {
4487 msk = tcg_temp_new_vec_matching(dst);
4488 tcg_gen_dupi_vec(vece, msk, 0xff);
4489 tcg_gen_and_vec(vece, lsh, shift, msk);
4490 tcg_gen_and_vec(vece, rsh, rsh, msk);
4491 tcg_temp_free_vec(msk);
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_shlv_vec(vece, lval, src, lsh);
4500 tcg_gen_shrv_vec(vece, rval, src, rsh);
4502 max = tcg_temp_new_vec_matching(dst);
4503 tcg_gen_dupi_vec(vece, max, 8 << vece);
4506 * The choice of LT (signed) and GEU (unsigned) are biased toward
4507 * the instructions of the x86_64 host. For MO_8, the whole byte
4508 * is significant so we must use an unsigned compare; otherwise we
4509 * have already masked to a byte and so a signed compare works.
4510 * Other tcg hosts have a full set of comparisons and do not care.
4512 if (vece == MO_8) {
4513 tcg_gen_cmp_vec(TCG_COND_GEU, vece, lsh, lsh, max);
4514 tcg_gen_cmp_vec(TCG_COND_GEU, vece, rsh, rsh, max);
4515 tcg_gen_andc_vec(vece, lval, lval, lsh);
4516 tcg_gen_andc_vec(vece, rval, rval, rsh);
4517 } else {
4518 tcg_gen_cmp_vec(TCG_COND_LT, vece, lsh, lsh, max);
4519 tcg_gen_cmp_vec(TCG_COND_LT, vece, rsh, rsh, max);
4520 tcg_gen_and_vec(vece, lval, lval, lsh);
4521 tcg_gen_and_vec(vece, rval, rval, rsh);
4523 tcg_gen_or_vec(vece, dst, lval, rval);
4525 tcg_temp_free_vec(max);
4526 tcg_temp_free_vec(lval);
4527 tcg_temp_free_vec(rval);
4528 tcg_temp_free_vec(lsh);
4529 tcg_temp_free_vec(rsh);
4532 void gen_gvec_ushl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4533 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4535 static const TCGOpcode vecop_list[] = {
4536 INDEX_op_neg_vec, INDEX_op_shlv_vec,
4537 INDEX_op_shrv_vec, INDEX_op_cmp_vec, 0
4539 static const GVecGen3 ops[4] = {
4540 { .fniv = gen_ushl_vec,
4541 .fno = gen_helper_gvec_ushl_b,
4542 .opt_opc = vecop_list,
4543 .vece = MO_8 },
4544 { .fniv = gen_ushl_vec,
4545 .fno = gen_helper_gvec_ushl_h,
4546 .opt_opc = vecop_list,
4547 .vece = MO_16 },
4548 { .fni4 = gen_ushl_i32,
4549 .fniv = gen_ushl_vec,
4550 .opt_opc = vecop_list,
4551 .vece = MO_32 },
4552 { .fni8 = gen_ushl_i64,
4553 .fniv = gen_ushl_vec,
4554 .opt_opc = vecop_list,
4555 .vece = MO_64 },
4557 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4560 void gen_sshl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift)
4562 TCGv_i32 lval = tcg_temp_new_i32();
4563 TCGv_i32 rval = tcg_temp_new_i32();
4564 TCGv_i32 lsh = tcg_temp_new_i32();
4565 TCGv_i32 rsh = tcg_temp_new_i32();
4566 TCGv_i32 zero = tcg_const_i32(0);
4567 TCGv_i32 max = tcg_const_i32(31);
4570 * Rely on the TCG guarantee that out of range shifts produce
4571 * unspecified results, not undefined behaviour (i.e. no trap).
4572 * Discard out-of-range results after the fact.
4574 tcg_gen_ext8s_i32(lsh, shift);
4575 tcg_gen_neg_i32(rsh, lsh);
4576 tcg_gen_shl_i32(lval, src, lsh);
4577 tcg_gen_umin_i32(rsh, rsh, max);
4578 tcg_gen_sar_i32(rval, src, rsh);
4579 tcg_gen_movcond_i32(TCG_COND_LEU, lval, lsh, max, lval, zero);
4580 tcg_gen_movcond_i32(TCG_COND_LT, dst, lsh, zero, rval, lval);
4582 tcg_temp_free_i32(lval);
4583 tcg_temp_free_i32(rval);
4584 tcg_temp_free_i32(lsh);
4585 tcg_temp_free_i32(rsh);
4586 tcg_temp_free_i32(zero);
4587 tcg_temp_free_i32(max);
4590 void gen_sshl_i64(TCGv_i64 dst, TCGv_i64 src, TCGv_i64 shift)
4592 TCGv_i64 lval = tcg_temp_new_i64();
4593 TCGv_i64 rval = tcg_temp_new_i64();
4594 TCGv_i64 lsh = tcg_temp_new_i64();
4595 TCGv_i64 rsh = tcg_temp_new_i64();
4596 TCGv_i64 zero = tcg_const_i64(0);
4597 TCGv_i64 max = tcg_const_i64(63);
4600 * Rely on the TCG guarantee that out of range shifts produce
4601 * unspecified results, not undefined behaviour (i.e. no trap).
4602 * Discard out-of-range results after the fact.
4604 tcg_gen_ext8s_i64(lsh, shift);
4605 tcg_gen_neg_i64(rsh, lsh);
4606 tcg_gen_shl_i64(lval, src, lsh);
4607 tcg_gen_umin_i64(rsh, rsh, max);
4608 tcg_gen_sar_i64(rval, src, rsh);
4609 tcg_gen_movcond_i64(TCG_COND_LEU, lval, lsh, max, lval, zero);
4610 tcg_gen_movcond_i64(TCG_COND_LT, dst, lsh, zero, rval, lval);
4612 tcg_temp_free_i64(lval);
4613 tcg_temp_free_i64(rval);
4614 tcg_temp_free_i64(lsh);
4615 tcg_temp_free_i64(rsh);
4616 tcg_temp_free_i64(zero);
4617 tcg_temp_free_i64(max);
4620 static void gen_sshl_vec(unsigned vece, TCGv_vec dst,
4621 TCGv_vec src, TCGv_vec shift)
4623 TCGv_vec lval = tcg_temp_new_vec_matching(dst);
4624 TCGv_vec rval = tcg_temp_new_vec_matching(dst);
4625 TCGv_vec lsh = tcg_temp_new_vec_matching(dst);
4626 TCGv_vec rsh = tcg_temp_new_vec_matching(dst);
4627 TCGv_vec tmp = tcg_temp_new_vec_matching(dst);
4630 * Rely on the TCG guarantee that out of range shifts produce
4631 * unspecified results, not undefined behaviour (i.e. no trap).
4632 * Discard out-of-range results after the fact.
4634 tcg_gen_neg_vec(vece, rsh, shift);
4635 if (vece == MO_8) {
4636 tcg_gen_mov_vec(lsh, shift);
4637 } else {
4638 tcg_gen_dupi_vec(vece, tmp, 0xff);
4639 tcg_gen_and_vec(vece, lsh, shift, tmp);
4640 tcg_gen_and_vec(vece, rsh, rsh, tmp);
4643 /* Bound rsh so out of bound right shift gets -1. */
4644 tcg_gen_dupi_vec(vece, tmp, (8 << vece) - 1);
4645 tcg_gen_umin_vec(vece, rsh, rsh, tmp);
4646 tcg_gen_cmp_vec(TCG_COND_GT, vece, tmp, lsh, tmp);
4648 tcg_gen_shlv_vec(vece, lval, src, lsh);
4649 tcg_gen_sarv_vec(vece, rval, src, rsh);
4651 /* Select in-bound left shift. */
4652 tcg_gen_andc_vec(vece, lval, lval, tmp);
4654 /* Select between left and right shift. */
4655 if (vece == MO_8) {
4656 tcg_gen_dupi_vec(vece, tmp, 0);
4657 tcg_gen_cmpsel_vec(TCG_COND_LT, vece, dst, lsh, tmp, rval, lval);
4658 } else {
4659 tcg_gen_dupi_vec(vece, tmp, 0x80);
4660 tcg_gen_cmpsel_vec(TCG_COND_LT, vece, dst, lsh, tmp, lval, rval);
4663 tcg_temp_free_vec(lval);
4664 tcg_temp_free_vec(rval);
4665 tcg_temp_free_vec(lsh);
4666 tcg_temp_free_vec(rsh);
4667 tcg_temp_free_vec(tmp);
4670 void gen_gvec_sshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4671 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4673 static const TCGOpcode vecop_list[] = {
4674 INDEX_op_neg_vec, INDEX_op_umin_vec, INDEX_op_shlv_vec,
4675 INDEX_op_sarv_vec, INDEX_op_cmp_vec, INDEX_op_cmpsel_vec, 0
4677 static const GVecGen3 ops[4] = {
4678 { .fniv = gen_sshl_vec,
4679 .fno = gen_helper_gvec_sshl_b,
4680 .opt_opc = vecop_list,
4681 .vece = MO_8 },
4682 { .fniv = gen_sshl_vec,
4683 .fno = gen_helper_gvec_sshl_h,
4684 .opt_opc = vecop_list,
4685 .vece = MO_16 },
4686 { .fni4 = gen_sshl_i32,
4687 .fniv = gen_sshl_vec,
4688 .opt_opc = vecop_list,
4689 .vece = MO_32 },
4690 { .fni8 = gen_sshl_i64,
4691 .fniv = gen_sshl_vec,
4692 .opt_opc = vecop_list,
4693 .vece = MO_64 },
4695 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4698 static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4699 TCGv_vec a, TCGv_vec b)
4701 TCGv_vec x = tcg_temp_new_vec_matching(t);
4702 tcg_gen_add_vec(vece, x, a, b);
4703 tcg_gen_usadd_vec(vece, t, a, b);
4704 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4705 tcg_gen_or_vec(vece, sat, sat, x);
4706 tcg_temp_free_vec(x);
4709 void gen_gvec_uqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4710 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4712 static const TCGOpcode vecop_list[] = {
4713 INDEX_op_usadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
4715 static const GVecGen4 ops[4] = {
4716 { .fniv = gen_uqadd_vec,
4717 .fno = gen_helper_gvec_uqadd_b,
4718 .write_aofs = true,
4719 .opt_opc = vecop_list,
4720 .vece = MO_8 },
4721 { .fniv = gen_uqadd_vec,
4722 .fno = gen_helper_gvec_uqadd_h,
4723 .write_aofs = true,
4724 .opt_opc = vecop_list,
4725 .vece = MO_16 },
4726 { .fniv = gen_uqadd_vec,
4727 .fno = gen_helper_gvec_uqadd_s,
4728 .write_aofs = true,
4729 .opt_opc = vecop_list,
4730 .vece = MO_32 },
4731 { .fniv = gen_uqadd_vec,
4732 .fno = gen_helper_gvec_uqadd_d,
4733 .write_aofs = true,
4734 .opt_opc = vecop_list,
4735 .vece = MO_64 },
4737 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4738 rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4741 static void gen_sqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4742 TCGv_vec a, TCGv_vec b)
4744 TCGv_vec x = tcg_temp_new_vec_matching(t);
4745 tcg_gen_add_vec(vece, x, a, b);
4746 tcg_gen_ssadd_vec(vece, t, a, b);
4747 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4748 tcg_gen_or_vec(vece, sat, sat, x);
4749 tcg_temp_free_vec(x);
4752 void gen_gvec_sqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4753 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4755 static const TCGOpcode vecop_list[] = {
4756 INDEX_op_ssadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
4758 static const GVecGen4 ops[4] = {
4759 { .fniv = gen_sqadd_vec,
4760 .fno = gen_helper_gvec_sqadd_b,
4761 .opt_opc = vecop_list,
4762 .write_aofs = true,
4763 .vece = MO_8 },
4764 { .fniv = gen_sqadd_vec,
4765 .fno = gen_helper_gvec_sqadd_h,
4766 .opt_opc = vecop_list,
4767 .write_aofs = true,
4768 .vece = MO_16 },
4769 { .fniv = gen_sqadd_vec,
4770 .fno = gen_helper_gvec_sqadd_s,
4771 .opt_opc = vecop_list,
4772 .write_aofs = true,
4773 .vece = MO_32 },
4774 { .fniv = gen_sqadd_vec,
4775 .fno = gen_helper_gvec_sqadd_d,
4776 .opt_opc = vecop_list,
4777 .write_aofs = true,
4778 .vece = MO_64 },
4780 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4781 rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4784 static void gen_uqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4785 TCGv_vec a, TCGv_vec b)
4787 TCGv_vec x = tcg_temp_new_vec_matching(t);
4788 tcg_gen_sub_vec(vece, x, a, b);
4789 tcg_gen_ussub_vec(vece, t, a, b);
4790 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4791 tcg_gen_or_vec(vece, sat, sat, x);
4792 tcg_temp_free_vec(x);
4795 void gen_gvec_uqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4796 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4798 static const TCGOpcode vecop_list[] = {
4799 INDEX_op_ussub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
4801 static const GVecGen4 ops[4] = {
4802 { .fniv = gen_uqsub_vec,
4803 .fno = gen_helper_gvec_uqsub_b,
4804 .opt_opc = vecop_list,
4805 .write_aofs = true,
4806 .vece = MO_8 },
4807 { .fniv = gen_uqsub_vec,
4808 .fno = gen_helper_gvec_uqsub_h,
4809 .opt_opc = vecop_list,
4810 .write_aofs = true,
4811 .vece = MO_16 },
4812 { .fniv = gen_uqsub_vec,
4813 .fno = gen_helper_gvec_uqsub_s,
4814 .opt_opc = vecop_list,
4815 .write_aofs = true,
4816 .vece = MO_32 },
4817 { .fniv = gen_uqsub_vec,
4818 .fno = gen_helper_gvec_uqsub_d,
4819 .opt_opc = vecop_list,
4820 .write_aofs = true,
4821 .vece = MO_64 },
4823 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4824 rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4827 static void gen_sqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
4828 TCGv_vec a, TCGv_vec b)
4830 TCGv_vec x = tcg_temp_new_vec_matching(t);
4831 tcg_gen_sub_vec(vece, x, a, b);
4832 tcg_gen_sssub_vec(vece, t, a, b);
4833 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
4834 tcg_gen_or_vec(vece, sat, sat, x);
4835 tcg_temp_free_vec(x);
4838 void gen_gvec_sqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4839 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4841 static const TCGOpcode vecop_list[] = {
4842 INDEX_op_sssub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
4844 static const GVecGen4 ops[4] = {
4845 { .fniv = gen_sqsub_vec,
4846 .fno = gen_helper_gvec_sqsub_b,
4847 .opt_opc = vecop_list,
4848 .write_aofs = true,
4849 .vece = MO_8 },
4850 { .fniv = gen_sqsub_vec,
4851 .fno = gen_helper_gvec_sqsub_h,
4852 .opt_opc = vecop_list,
4853 .write_aofs = true,
4854 .vece = MO_16 },
4855 { .fniv = gen_sqsub_vec,
4856 .fno = gen_helper_gvec_sqsub_s,
4857 .opt_opc = vecop_list,
4858 .write_aofs = true,
4859 .vece = MO_32 },
4860 { .fniv = gen_sqsub_vec,
4861 .fno = gen_helper_gvec_sqsub_d,
4862 .opt_opc = vecop_list,
4863 .write_aofs = true,
4864 .vece = MO_64 },
4866 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
4867 rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4870 static void gen_sabd_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4872 TCGv_i32 t = tcg_temp_new_i32();
4874 tcg_gen_sub_i32(t, a, b);
4875 tcg_gen_sub_i32(d, b, a);
4876 tcg_gen_movcond_i32(TCG_COND_LT, d, a, b, d, t);
4877 tcg_temp_free_i32(t);
4880 static void gen_sabd_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4882 TCGv_i64 t = tcg_temp_new_i64();
4884 tcg_gen_sub_i64(t, a, b);
4885 tcg_gen_sub_i64(d, b, a);
4886 tcg_gen_movcond_i64(TCG_COND_LT, d, a, b, d, t);
4887 tcg_temp_free_i64(t);
4890 static void gen_sabd_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4892 TCGv_vec t = tcg_temp_new_vec_matching(d);
4894 tcg_gen_smin_vec(vece, t, a, b);
4895 tcg_gen_smax_vec(vece, d, a, b);
4896 tcg_gen_sub_vec(vece, d, d, t);
4897 tcg_temp_free_vec(t);
4900 void gen_gvec_sabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4901 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4903 static const TCGOpcode vecop_list[] = {
4904 INDEX_op_sub_vec, INDEX_op_smin_vec, INDEX_op_smax_vec, 0
4906 static const GVecGen3 ops[4] = {
4907 { .fniv = gen_sabd_vec,
4908 .fno = gen_helper_gvec_sabd_b,
4909 .opt_opc = vecop_list,
4910 .vece = MO_8 },
4911 { .fniv = gen_sabd_vec,
4912 .fno = gen_helper_gvec_sabd_h,
4913 .opt_opc = vecop_list,
4914 .vece = MO_16 },
4915 { .fni4 = gen_sabd_i32,
4916 .fniv = gen_sabd_vec,
4917 .fno = gen_helper_gvec_sabd_s,
4918 .opt_opc = vecop_list,
4919 .vece = MO_32 },
4920 { .fni8 = gen_sabd_i64,
4921 .fniv = gen_sabd_vec,
4922 .fno = gen_helper_gvec_sabd_d,
4923 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4924 .opt_opc = vecop_list,
4925 .vece = MO_64 },
4927 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4930 static void gen_uabd_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4932 TCGv_i32 t = tcg_temp_new_i32();
4934 tcg_gen_sub_i32(t, a, b);
4935 tcg_gen_sub_i32(d, b, a);
4936 tcg_gen_movcond_i32(TCG_COND_LTU, d, a, b, d, t);
4937 tcg_temp_free_i32(t);
4940 static void gen_uabd_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
4942 TCGv_i64 t = tcg_temp_new_i64();
4944 tcg_gen_sub_i64(t, a, b);
4945 tcg_gen_sub_i64(d, b, a);
4946 tcg_gen_movcond_i64(TCG_COND_LTU, d, a, b, d, t);
4947 tcg_temp_free_i64(t);
4950 static void gen_uabd_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
4952 TCGv_vec t = tcg_temp_new_vec_matching(d);
4954 tcg_gen_umin_vec(vece, t, a, b);
4955 tcg_gen_umax_vec(vece, d, a, b);
4956 tcg_gen_sub_vec(vece, d, d, t);
4957 tcg_temp_free_vec(t);
4960 void gen_gvec_uabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4961 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
4963 static const TCGOpcode vecop_list[] = {
4964 INDEX_op_sub_vec, INDEX_op_umin_vec, INDEX_op_umax_vec, 0
4966 static const GVecGen3 ops[4] = {
4967 { .fniv = gen_uabd_vec,
4968 .fno = gen_helper_gvec_uabd_b,
4969 .opt_opc = vecop_list,
4970 .vece = MO_8 },
4971 { .fniv = gen_uabd_vec,
4972 .fno = gen_helper_gvec_uabd_h,
4973 .opt_opc = vecop_list,
4974 .vece = MO_16 },
4975 { .fni4 = gen_uabd_i32,
4976 .fniv = gen_uabd_vec,
4977 .fno = gen_helper_gvec_uabd_s,
4978 .opt_opc = vecop_list,
4979 .vece = MO_32 },
4980 { .fni8 = gen_uabd_i64,
4981 .fniv = gen_uabd_vec,
4982 .fno = gen_helper_gvec_uabd_d,
4983 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
4984 .opt_opc = vecop_list,
4985 .vece = MO_64 },
4987 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
4990 static void gen_saba_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
4992 TCGv_i32 t = tcg_temp_new_i32();
4993 gen_sabd_i32(t, a, b);
4994 tcg_gen_add_i32(d, d, t);
4995 tcg_temp_free_i32(t);
4998 static void gen_saba_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
5000 TCGv_i64 t = tcg_temp_new_i64();
5001 gen_sabd_i64(t, a, b);
5002 tcg_gen_add_i64(d, d, t);
5003 tcg_temp_free_i64(t);
5006 static void gen_saba_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
5008 TCGv_vec t = tcg_temp_new_vec_matching(d);
5009 gen_sabd_vec(vece, t, a, b);
5010 tcg_gen_add_vec(vece, d, d, t);
5011 tcg_temp_free_vec(t);
5014 void gen_gvec_saba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
5015 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
5017 static const TCGOpcode vecop_list[] = {
5018 INDEX_op_sub_vec, INDEX_op_add_vec,
5019 INDEX_op_smin_vec, INDEX_op_smax_vec, 0
5021 static const GVecGen3 ops[4] = {
5022 { .fniv = gen_saba_vec,
5023 .fno = gen_helper_gvec_saba_b,
5024 .opt_opc = vecop_list,
5025 .load_dest = true,
5026 .vece = MO_8 },
5027 { .fniv = gen_saba_vec,
5028 .fno = gen_helper_gvec_saba_h,
5029 .opt_opc = vecop_list,
5030 .load_dest = true,
5031 .vece = MO_16 },
5032 { .fni4 = gen_saba_i32,
5033 .fniv = gen_saba_vec,
5034 .fno = gen_helper_gvec_saba_s,
5035 .opt_opc = vecop_list,
5036 .load_dest = true,
5037 .vece = MO_32 },
5038 { .fni8 = gen_saba_i64,
5039 .fniv = gen_saba_vec,
5040 .fno = gen_helper_gvec_saba_d,
5041 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5042 .opt_opc = vecop_list,
5043 .load_dest = true,
5044 .vece = MO_64 },
5046 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
5049 static void gen_uaba_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
5051 TCGv_i32 t = tcg_temp_new_i32();
5052 gen_uabd_i32(t, a, b);
5053 tcg_gen_add_i32(d, d, t);
5054 tcg_temp_free_i32(t);
5057 static void gen_uaba_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
5059 TCGv_i64 t = tcg_temp_new_i64();
5060 gen_uabd_i64(t, a, b);
5061 tcg_gen_add_i64(d, d, t);
5062 tcg_temp_free_i64(t);
5065 static void gen_uaba_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
5067 TCGv_vec t = tcg_temp_new_vec_matching(d);
5068 gen_uabd_vec(vece, t, a, b);
5069 tcg_gen_add_vec(vece, d, d, t);
5070 tcg_temp_free_vec(t);
5073 void gen_gvec_uaba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
5074 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
5076 static const TCGOpcode vecop_list[] = {
5077 INDEX_op_sub_vec, INDEX_op_add_vec,
5078 INDEX_op_umin_vec, INDEX_op_umax_vec, 0
5080 static const GVecGen3 ops[4] = {
5081 { .fniv = gen_uaba_vec,
5082 .fno = gen_helper_gvec_uaba_b,
5083 .opt_opc = vecop_list,
5084 .load_dest = true,
5085 .vece = MO_8 },
5086 { .fniv = gen_uaba_vec,
5087 .fno = gen_helper_gvec_uaba_h,
5088 .opt_opc = vecop_list,
5089 .load_dest = true,
5090 .vece = MO_16 },
5091 { .fni4 = gen_uaba_i32,
5092 .fniv = gen_uaba_vec,
5093 .fno = gen_helper_gvec_uaba_s,
5094 .opt_opc = vecop_list,
5095 .load_dest = true,
5096 .vece = MO_32 },
5097 { .fni8 = gen_uaba_i64,
5098 .fniv = gen_uaba_vec,
5099 .fno = gen_helper_gvec_uaba_d,
5100 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5101 .opt_opc = vecop_list,
5102 .load_dest = true,
5103 .vece = MO_64 },
5105 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
5108 /* Translate a NEON data processing instruction. Return nonzero if the
5109 instruction is invalid.
5110 We process data in a mixture of 32-bit and 64-bit chunks.
5111 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
5113 static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
5115 int op;
5116 int q;
5117 int rd, rn, rm, rd_ofs, rm_ofs;
5118 int size;
5119 int pass;
5120 int u;
5121 int vec_size;
5122 uint32_t imm;
5123 TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
5124 TCGv_ptr ptr1;
5125 TCGv_i64 tmp64;
5127 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
5128 return 1;
5131 /* FIXME: this access check should not take precedence over UNDEF
5132 * for invalid encodings; we will generate incorrect syndrome information
5133 * for attempts to execute invalid vfp/neon encodings with FP disabled.
5135 if (s->fp_excp_el) {
5136 gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
5137 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
5138 return 0;
5141 if (!s->vfp_enabled)
5142 return 1;
5143 q = (insn & (1 << 6)) != 0;
5144 u = (insn >> 24) & 1;
5145 VFP_DREG_D(rd, insn);
5146 VFP_DREG_N(rn, insn);
5147 VFP_DREG_M(rm, insn);
5148 size = (insn >> 20) & 3;
5149 vec_size = q ? 16 : 8;
5150 rd_ofs = neon_reg_offset(rd, 0);
5151 rm_ofs = neon_reg_offset(rm, 0);
5153 if ((insn & (1 << 23)) == 0) {
5154 /* Three register same length: handled by decodetree */
5155 return 1;
5156 } else if (insn & (1 << 4)) {
5157 /* Two registers and shift or reg and imm: handled by decodetree */
5158 return 1;
5159 } else { /* (insn & 0x00800010 == 0x00800000) */
5160 if (size != 3) {
5161 op = (insn >> 8) & 0xf;
5162 if ((insn & (1 << 6)) == 0) {
5163 /* Three registers of different lengths: handled by decodetree */
5164 return 1;
5165 } else {
5166 /* Two registers and a scalar. NB that for ops of this form
5167 * the ARM ARM labels bit 24 as Q, but it is in our variable
5168 * 'u', not 'q'.
5170 if (size == 0) {
5171 return 1;
5173 switch (op) {
5174 case 0: /* Integer VMLA scalar */
5175 case 4: /* Integer VMLS scalar */
5176 case 8: /* Integer VMUL scalar */
5177 case 1: /* Float VMLA scalar */
5178 case 5: /* Floating point VMLS scalar */
5179 case 9: /* Floating point VMUL scalar */
5180 case 12: /* VQDMULH scalar */
5181 case 13: /* VQRDMULH scalar */
5182 return 1; /* handled by decodetree */
5184 case 3: /* VQDMLAL scalar */
5185 case 7: /* VQDMLSL scalar */
5186 case 11: /* VQDMULL scalar */
5187 if (u == 1) {
5188 return 1;
5190 /* fall through */
5191 case 2: /* VMLAL sclar */
5192 case 6: /* VMLSL scalar */
5193 case 10: /* VMULL scalar */
5194 if (rd & 1) {
5195 return 1;
5197 tmp2 = neon_get_scalar(size, rm);
5198 /* We need a copy of tmp2 because gen_neon_mull
5199 * deletes it during pass 0. */
5200 tmp4 = tcg_temp_new_i32();
5201 tcg_gen_mov_i32(tmp4, tmp2);
5202 tmp3 = neon_load_reg(rn, 1);
5204 for (pass = 0; pass < 2; pass++) {
5205 if (pass == 0) {
5206 tmp = neon_load_reg(rn, 0);
5207 } else {
5208 tmp = tmp3;
5209 tmp2 = tmp4;
5211 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5212 if (op != 11) {
5213 neon_load_reg64(cpu_V1, rd + pass);
5215 switch (op) {
5216 case 6:
5217 gen_neon_negl(cpu_V0, size);
5218 /* Fall through */
5219 case 2:
5220 gen_neon_addl(size);
5221 break;
5222 case 3: case 7:
5223 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5224 if (op == 7) {
5225 gen_neon_negl(cpu_V0, size);
5227 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5228 break;
5229 case 10:
5230 /* no-op */
5231 break;
5232 case 11:
5233 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5234 break;
5235 default:
5236 abort();
5238 neon_store_reg64(cpu_V0, rd + pass);
5240 break;
5241 case 14: /* VQRDMLAH scalar */
5242 case 15: /* VQRDMLSH scalar */
5244 NeonGenThreeOpEnvFn *fn;
5246 if (!dc_isar_feature(aa32_rdm, s)) {
5247 return 1;
5249 if (u && ((rd | rn) & 1)) {
5250 return 1;
5252 if (op == 14) {
5253 if (size == 1) {
5254 fn = gen_helper_neon_qrdmlah_s16;
5255 } else {
5256 fn = gen_helper_neon_qrdmlah_s32;
5258 } else {
5259 if (size == 1) {
5260 fn = gen_helper_neon_qrdmlsh_s16;
5261 } else {
5262 fn = gen_helper_neon_qrdmlsh_s32;
5266 tmp2 = neon_get_scalar(size, rm);
5267 for (pass = 0; pass < (u ? 4 : 2); pass++) {
5268 tmp = neon_load_reg(rn, pass);
5269 tmp3 = neon_load_reg(rd, pass);
5270 fn(tmp, cpu_env, tmp, tmp2, tmp3);
5271 tcg_temp_free_i32(tmp3);
5272 neon_store_reg(rd, pass, tmp);
5274 tcg_temp_free_i32(tmp2);
5276 break;
5277 default:
5278 g_assert_not_reached();
5281 } else { /* size == 3 */
5282 if (!u) {
5283 /* Extract. */
5284 imm = (insn >> 8) & 0xf;
5286 if (imm > 7 && !q)
5287 return 1;
5289 if (q && ((rd | rn | rm) & 1)) {
5290 return 1;
5293 if (imm == 0) {
5294 neon_load_reg64(cpu_V0, rn);
5295 if (q) {
5296 neon_load_reg64(cpu_V1, rn + 1);
5298 } else if (imm == 8) {
5299 neon_load_reg64(cpu_V0, rn + 1);
5300 if (q) {
5301 neon_load_reg64(cpu_V1, rm);
5303 } else if (q) {
5304 tmp64 = tcg_temp_new_i64();
5305 if (imm < 8) {
5306 neon_load_reg64(cpu_V0, rn);
5307 neon_load_reg64(tmp64, rn + 1);
5308 } else {
5309 neon_load_reg64(cpu_V0, rn + 1);
5310 neon_load_reg64(tmp64, rm);
5312 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5313 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
5314 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5315 if (imm < 8) {
5316 neon_load_reg64(cpu_V1, rm);
5317 } else {
5318 neon_load_reg64(cpu_V1, rm + 1);
5319 imm -= 8;
5321 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5322 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
5323 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
5324 tcg_temp_free_i64(tmp64);
5325 } else {
5326 /* BUGFIX */
5327 neon_load_reg64(cpu_V0, rn);
5328 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
5329 neon_load_reg64(cpu_V1, rm);
5330 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5331 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5333 neon_store_reg64(cpu_V0, rd);
5334 if (q) {
5335 neon_store_reg64(cpu_V1, rd + 1);
5337 } else if ((insn & (1 << 11)) == 0) {
5338 /* Two register misc. */
5339 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5340 size = (insn >> 18) & 3;
5341 /* UNDEF for unknown op values and bad op-size combinations */
5342 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
5343 return 1;
5345 if (neon_2rm_is_v8_op(op) &&
5346 !arm_dc_feature(s, ARM_FEATURE_V8)) {
5347 return 1;
5349 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
5350 q && ((rm | rd) & 1)) {
5351 return 1;
5353 switch (op) {
5354 case NEON_2RM_VREV64:
5355 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5356 tmp = neon_load_reg(rm, pass * 2);
5357 tmp2 = neon_load_reg(rm, pass * 2 + 1);
5358 switch (size) {
5359 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5360 case 1: gen_swap_half(tmp); break;
5361 case 2: /* no-op */ break;
5362 default: abort();
5364 neon_store_reg(rd, pass * 2 + 1, tmp);
5365 if (size == 2) {
5366 neon_store_reg(rd, pass * 2, tmp2);
5367 } else {
5368 switch (size) {
5369 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
5370 case 1: gen_swap_half(tmp2); break;
5371 default: abort();
5373 neon_store_reg(rd, pass * 2, tmp2);
5376 break;
5377 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
5378 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
5379 for (pass = 0; pass < q + 1; pass++) {
5380 tmp = neon_load_reg(rm, pass * 2);
5381 gen_neon_widen(cpu_V0, tmp, size, op & 1);
5382 tmp = neon_load_reg(rm, pass * 2 + 1);
5383 gen_neon_widen(cpu_V1, tmp, size, op & 1);
5384 switch (size) {
5385 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5386 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5387 case 2: tcg_gen_add_i64(CPU_V001); break;
5388 default: abort();
5390 if (op >= NEON_2RM_VPADAL) {
5391 /* Accumulate. */
5392 neon_load_reg64(cpu_V1, rd + pass);
5393 gen_neon_addl(size);
5395 neon_store_reg64(cpu_V0, rd + pass);
5397 break;
5398 case NEON_2RM_VTRN:
5399 if (size == 2) {
5400 int n;
5401 for (n = 0; n < (q ? 4 : 2); n += 2) {
5402 tmp = neon_load_reg(rm, n);
5403 tmp2 = neon_load_reg(rd, n + 1);
5404 neon_store_reg(rm, n, tmp2);
5405 neon_store_reg(rd, n + 1, tmp);
5407 } else {
5408 goto elementwise;
5410 break;
5411 case NEON_2RM_VUZP:
5412 if (gen_neon_unzip(rd, rm, size, q)) {
5413 return 1;
5415 break;
5416 case NEON_2RM_VZIP:
5417 if (gen_neon_zip(rd, rm, size, q)) {
5418 return 1;
5420 break;
5421 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
5422 /* also VQMOVUN; op field and mnemonics don't line up */
5423 if (rm & 1) {
5424 return 1;
5426 tmp2 = NULL;
5427 for (pass = 0; pass < 2; pass++) {
5428 neon_load_reg64(cpu_V0, rm + pass);
5429 tmp = tcg_temp_new_i32();
5430 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
5431 tmp, cpu_V0);
5432 if (pass == 0) {
5433 tmp2 = tmp;
5434 } else {
5435 neon_store_reg(rd, 0, tmp2);
5436 neon_store_reg(rd, 1, tmp);
5439 break;
5440 case NEON_2RM_VSHLL:
5441 if (q || (rd & 1)) {
5442 return 1;
5444 tmp = neon_load_reg(rm, 0);
5445 tmp2 = neon_load_reg(rm, 1);
5446 for (pass = 0; pass < 2; pass++) {
5447 if (pass == 1)
5448 tmp = tmp2;
5449 gen_neon_widen(cpu_V0, tmp, size, 1);
5450 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
5451 neon_store_reg64(cpu_V0, rd + pass);
5453 break;
5454 case NEON_2RM_VCVT_F16_F32:
5456 TCGv_ptr fpst;
5457 TCGv_i32 ahp;
5459 if (!dc_isar_feature(aa32_fp16_spconv, s) ||
5460 q || (rm & 1)) {
5461 return 1;
5463 fpst = get_fpstatus_ptr(true);
5464 ahp = get_ahp_flag();
5465 tmp = neon_load_reg(rm, 0);
5466 gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp);
5467 tmp2 = neon_load_reg(rm, 1);
5468 gen_helper_vfp_fcvt_f32_to_f16(tmp2, tmp2, fpst, ahp);
5469 tcg_gen_shli_i32(tmp2, tmp2, 16);
5470 tcg_gen_or_i32(tmp2, tmp2, tmp);
5471 tcg_temp_free_i32(tmp);
5472 tmp = neon_load_reg(rm, 2);
5473 gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp);
5474 tmp3 = neon_load_reg(rm, 3);
5475 neon_store_reg(rd, 0, tmp2);
5476 gen_helper_vfp_fcvt_f32_to_f16(tmp3, tmp3, fpst, ahp);
5477 tcg_gen_shli_i32(tmp3, tmp3, 16);
5478 tcg_gen_or_i32(tmp3, tmp3, tmp);
5479 neon_store_reg(rd, 1, tmp3);
5480 tcg_temp_free_i32(tmp);
5481 tcg_temp_free_i32(ahp);
5482 tcg_temp_free_ptr(fpst);
5483 break;
5485 case NEON_2RM_VCVT_F32_F16:
5487 TCGv_ptr fpst;
5488 TCGv_i32 ahp;
5489 if (!dc_isar_feature(aa32_fp16_spconv, s) ||
5490 q || (rd & 1)) {
5491 return 1;
5493 fpst = get_fpstatus_ptr(true);
5494 ahp = get_ahp_flag();
5495 tmp3 = tcg_temp_new_i32();
5496 tmp = neon_load_reg(rm, 0);
5497 tmp2 = neon_load_reg(rm, 1);
5498 tcg_gen_ext16u_i32(tmp3, tmp);
5499 gen_helper_vfp_fcvt_f16_to_f32(tmp3, tmp3, fpst, ahp);
5500 neon_store_reg(rd, 0, tmp3);
5501 tcg_gen_shri_i32(tmp, tmp, 16);
5502 gen_helper_vfp_fcvt_f16_to_f32(tmp, tmp, fpst, ahp);
5503 neon_store_reg(rd, 1, tmp);
5504 tmp3 = tcg_temp_new_i32();
5505 tcg_gen_ext16u_i32(tmp3, tmp2);
5506 gen_helper_vfp_fcvt_f16_to_f32(tmp3, tmp3, fpst, ahp);
5507 neon_store_reg(rd, 2, tmp3);
5508 tcg_gen_shri_i32(tmp2, tmp2, 16);
5509 gen_helper_vfp_fcvt_f16_to_f32(tmp2, tmp2, fpst, ahp);
5510 neon_store_reg(rd, 3, tmp2);
5511 tcg_temp_free_i32(ahp);
5512 tcg_temp_free_ptr(fpst);
5513 break;
5515 case NEON_2RM_AESE: case NEON_2RM_AESMC:
5516 if (!dc_isar_feature(aa32_aes, s) || ((rm | rd) & 1)) {
5517 return 1;
5520 * Bit 6 is the lowest opcode bit; it distinguishes
5521 * between encryption (AESE/AESMC) and decryption
5522 * (AESD/AESIMC).
5524 if (op == NEON_2RM_AESE) {
5525 tcg_gen_gvec_3_ool(vfp_reg_offset(true, rd),
5526 vfp_reg_offset(true, rd),
5527 vfp_reg_offset(true, rm),
5528 16, 16, extract32(insn, 6, 1),
5529 gen_helper_crypto_aese);
5530 } else {
5531 tcg_gen_gvec_2_ool(vfp_reg_offset(true, rd),
5532 vfp_reg_offset(true, rm),
5533 16, 16, extract32(insn, 6, 1),
5534 gen_helper_crypto_aesmc);
5536 break;
5537 case NEON_2RM_SHA1H:
5538 if (!dc_isar_feature(aa32_sha1, s) || ((rm | rd) & 1)) {
5539 return 1;
5541 tcg_gen_gvec_2_ool(rd_ofs, rm_ofs, 16, 16, 0,
5542 gen_helper_crypto_sha1h);
5543 break;
5544 case NEON_2RM_SHA1SU1:
5545 if ((rm | rd) & 1) {
5546 return 1;
5548 /* bit 6 (q): set -> SHA256SU0, cleared -> SHA1SU1 */
5549 if (q) {
5550 if (!dc_isar_feature(aa32_sha2, s)) {
5551 return 1;
5553 } else if (!dc_isar_feature(aa32_sha1, s)) {
5554 return 1;
5556 tcg_gen_gvec_2_ool(rd_ofs, rm_ofs, 16, 16, 0,
5557 q ? gen_helper_crypto_sha256su0
5558 : gen_helper_crypto_sha1su1);
5559 break;
5560 case NEON_2RM_VMVN:
5561 tcg_gen_gvec_not(0, rd_ofs, rm_ofs, vec_size, vec_size);
5562 break;
5563 case NEON_2RM_VNEG:
5564 tcg_gen_gvec_neg(size, rd_ofs, rm_ofs, vec_size, vec_size);
5565 break;
5566 case NEON_2RM_VABS:
5567 tcg_gen_gvec_abs(size, rd_ofs, rm_ofs, vec_size, vec_size);
5568 break;
5570 case NEON_2RM_VCEQ0:
5571 gen_gvec_ceq0(size, rd_ofs, rm_ofs, vec_size, vec_size);
5572 break;
5573 case NEON_2RM_VCGT0:
5574 gen_gvec_cgt0(size, rd_ofs, rm_ofs, vec_size, vec_size);
5575 break;
5576 case NEON_2RM_VCLE0:
5577 gen_gvec_cle0(size, rd_ofs, rm_ofs, vec_size, vec_size);
5578 break;
5579 case NEON_2RM_VCGE0:
5580 gen_gvec_cge0(size, rd_ofs, rm_ofs, vec_size, vec_size);
5581 break;
5582 case NEON_2RM_VCLT0:
5583 gen_gvec_clt0(size, rd_ofs, rm_ofs, vec_size, vec_size);
5584 break;
5586 default:
5587 elementwise:
5588 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5589 tmp = neon_load_reg(rm, pass);
5590 switch (op) {
5591 case NEON_2RM_VREV32:
5592 switch (size) {
5593 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5594 case 1: gen_swap_half(tmp); break;
5595 default: abort();
5597 break;
5598 case NEON_2RM_VREV16:
5599 gen_rev16(tmp, tmp);
5600 break;
5601 case NEON_2RM_VCLS:
5602 switch (size) {
5603 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
5604 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
5605 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
5606 default: abort();
5608 break;
5609 case NEON_2RM_VCLZ:
5610 switch (size) {
5611 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
5612 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
5613 case 2: tcg_gen_clzi_i32(tmp, tmp, 32); break;
5614 default: abort();
5616 break;
5617 case NEON_2RM_VCNT:
5618 gen_helper_neon_cnt_u8(tmp, tmp);
5619 break;
5620 case NEON_2RM_VQABS:
5621 switch (size) {
5622 case 0:
5623 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
5624 break;
5625 case 1:
5626 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
5627 break;
5628 case 2:
5629 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
5630 break;
5631 default: abort();
5633 break;
5634 case NEON_2RM_VQNEG:
5635 switch (size) {
5636 case 0:
5637 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
5638 break;
5639 case 1:
5640 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
5641 break;
5642 case 2:
5643 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
5644 break;
5645 default: abort();
5647 break;
5648 case NEON_2RM_VCGT0_F:
5650 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5651 tmp2 = tcg_const_i32(0);
5652 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
5653 tcg_temp_free_i32(tmp2);
5654 tcg_temp_free_ptr(fpstatus);
5655 break;
5657 case NEON_2RM_VCGE0_F:
5659 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5660 tmp2 = tcg_const_i32(0);
5661 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
5662 tcg_temp_free_i32(tmp2);
5663 tcg_temp_free_ptr(fpstatus);
5664 break;
5666 case NEON_2RM_VCEQ0_F:
5668 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5669 tmp2 = tcg_const_i32(0);
5670 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
5671 tcg_temp_free_i32(tmp2);
5672 tcg_temp_free_ptr(fpstatus);
5673 break;
5675 case NEON_2RM_VCLE0_F:
5677 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5678 tmp2 = tcg_const_i32(0);
5679 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
5680 tcg_temp_free_i32(tmp2);
5681 tcg_temp_free_ptr(fpstatus);
5682 break;
5684 case NEON_2RM_VCLT0_F:
5686 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5687 tmp2 = tcg_const_i32(0);
5688 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
5689 tcg_temp_free_i32(tmp2);
5690 tcg_temp_free_ptr(fpstatus);
5691 break;
5693 case NEON_2RM_VABS_F:
5694 gen_helper_vfp_abss(tmp, tmp);
5695 break;
5696 case NEON_2RM_VNEG_F:
5697 gen_helper_vfp_negs(tmp, tmp);
5698 break;
5699 case NEON_2RM_VSWP:
5700 tmp2 = neon_load_reg(rd, pass);
5701 neon_store_reg(rm, pass, tmp2);
5702 break;
5703 case NEON_2RM_VTRN:
5704 tmp2 = neon_load_reg(rd, pass);
5705 switch (size) {
5706 case 0: gen_neon_trn_u8(tmp, tmp2); break;
5707 case 1: gen_neon_trn_u16(tmp, tmp2); break;
5708 default: abort();
5710 neon_store_reg(rm, pass, tmp2);
5711 break;
5712 case NEON_2RM_VRINTN:
5713 case NEON_2RM_VRINTA:
5714 case NEON_2RM_VRINTM:
5715 case NEON_2RM_VRINTP:
5716 case NEON_2RM_VRINTZ:
5718 TCGv_i32 tcg_rmode;
5719 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5720 int rmode;
5722 if (op == NEON_2RM_VRINTZ) {
5723 rmode = FPROUNDING_ZERO;
5724 } else {
5725 rmode = fp_decode_rm[((op & 0x6) >> 1) ^ 1];
5728 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
5729 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
5730 cpu_env);
5731 gen_helper_rints(tmp, tmp, fpstatus);
5732 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
5733 cpu_env);
5734 tcg_temp_free_ptr(fpstatus);
5735 tcg_temp_free_i32(tcg_rmode);
5736 break;
5738 case NEON_2RM_VRINTX:
5740 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5741 gen_helper_rints_exact(tmp, tmp, fpstatus);
5742 tcg_temp_free_ptr(fpstatus);
5743 break;
5745 case NEON_2RM_VCVTAU:
5746 case NEON_2RM_VCVTAS:
5747 case NEON_2RM_VCVTNU:
5748 case NEON_2RM_VCVTNS:
5749 case NEON_2RM_VCVTPU:
5750 case NEON_2RM_VCVTPS:
5751 case NEON_2RM_VCVTMU:
5752 case NEON_2RM_VCVTMS:
5754 bool is_signed = !extract32(insn, 7, 1);
5755 TCGv_ptr fpst = get_fpstatus_ptr(1);
5756 TCGv_i32 tcg_rmode, tcg_shift;
5757 int rmode = fp_decode_rm[extract32(insn, 8, 2)];
5759 tcg_shift = tcg_const_i32(0);
5760 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
5761 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
5762 cpu_env);
5764 if (is_signed) {
5765 gen_helper_vfp_tosls(tmp, tmp,
5766 tcg_shift, fpst);
5767 } else {
5768 gen_helper_vfp_touls(tmp, tmp,
5769 tcg_shift, fpst);
5772 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
5773 cpu_env);
5774 tcg_temp_free_i32(tcg_rmode);
5775 tcg_temp_free_i32(tcg_shift);
5776 tcg_temp_free_ptr(fpst);
5777 break;
5779 case NEON_2RM_VRECPE:
5780 gen_helper_recpe_u32(tmp, tmp);
5781 break;
5782 case NEON_2RM_VRSQRTE:
5783 gen_helper_rsqrte_u32(tmp, tmp);
5784 break;
5785 case NEON_2RM_VRECPE_F:
5787 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5788 gen_helper_recpe_f32(tmp, tmp, fpstatus);
5789 tcg_temp_free_ptr(fpstatus);
5790 break;
5792 case NEON_2RM_VRSQRTE_F:
5794 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5795 gen_helper_rsqrte_f32(tmp, tmp, fpstatus);
5796 tcg_temp_free_ptr(fpstatus);
5797 break;
5799 case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
5801 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5802 gen_helper_vfp_sitos(tmp, tmp, fpstatus);
5803 tcg_temp_free_ptr(fpstatus);
5804 break;
5806 case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
5808 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5809 gen_helper_vfp_uitos(tmp, tmp, fpstatus);
5810 tcg_temp_free_ptr(fpstatus);
5811 break;
5813 case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
5815 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5816 gen_helper_vfp_tosizs(tmp, tmp, fpstatus);
5817 tcg_temp_free_ptr(fpstatus);
5818 break;
5820 case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
5822 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5823 gen_helper_vfp_touizs(tmp, tmp, fpstatus);
5824 tcg_temp_free_ptr(fpstatus);
5825 break;
5827 default:
5828 /* Reserved op values were caught by the
5829 * neon_2rm_sizes[] check earlier.
5831 abort();
5833 neon_store_reg(rd, pass, tmp);
5835 break;
5837 } else if ((insn & (1 << 10)) == 0) {
5838 /* VTBL, VTBX. */
5839 int n = ((insn >> 8) & 3) + 1;
5840 if ((rn + n) > 32) {
5841 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
5842 * helper function running off the end of the register file.
5844 return 1;
5846 n <<= 3;
5847 if (insn & (1 << 6)) {
5848 tmp = neon_load_reg(rd, 0);
5849 } else {
5850 tmp = tcg_temp_new_i32();
5851 tcg_gen_movi_i32(tmp, 0);
5853 tmp2 = neon_load_reg(rm, 0);
5854 ptr1 = vfp_reg_ptr(true, rn);
5855 tmp5 = tcg_const_i32(n);
5856 gen_helper_neon_tbl(tmp2, tmp2, tmp, ptr1, tmp5);
5857 tcg_temp_free_i32(tmp);
5858 if (insn & (1 << 6)) {
5859 tmp = neon_load_reg(rd, 1);
5860 } else {
5861 tmp = tcg_temp_new_i32();
5862 tcg_gen_movi_i32(tmp, 0);
5864 tmp3 = neon_load_reg(rm, 1);
5865 gen_helper_neon_tbl(tmp3, tmp3, tmp, ptr1, tmp5);
5866 tcg_temp_free_i32(tmp5);
5867 tcg_temp_free_ptr(ptr1);
5868 neon_store_reg(rd, 0, tmp2);
5869 neon_store_reg(rd, 1, tmp3);
5870 tcg_temp_free_i32(tmp);
5871 } else if ((insn & 0x380) == 0) {
5872 /* VDUP */
5873 int element;
5874 MemOp size;
5876 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
5877 return 1;
5879 if (insn & (1 << 16)) {
5880 size = MO_8;
5881 element = (insn >> 17) & 7;
5882 } else if (insn & (1 << 17)) {
5883 size = MO_16;
5884 element = (insn >> 18) & 3;
5885 } else {
5886 size = MO_32;
5887 element = (insn >> 19) & 1;
5889 tcg_gen_gvec_dup_mem(size, neon_reg_offset(rd, 0),
5890 neon_element_offset(rm, element, size),
5891 q ? 16 : 8, q ? 16 : 8);
5892 } else {
5893 return 1;
5897 return 0;
5900 static int disas_coproc_insn(DisasContext *s, uint32_t insn)
5902 int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
5903 const ARMCPRegInfo *ri;
5905 cpnum = (insn >> 8) & 0xf;
5907 /* First check for coprocessor space used for XScale/iwMMXt insns */
5908 if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cpnum < 2)) {
5909 if (extract32(s->c15_cpar, cpnum, 1) == 0) {
5910 return 1;
5912 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
5913 return disas_iwmmxt_insn(s, insn);
5914 } else if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
5915 return disas_dsp_insn(s, insn);
5917 return 1;
5920 /* Otherwise treat as a generic register access */
5921 is64 = (insn & (1 << 25)) == 0;
5922 if (!is64 && ((insn & (1 << 4)) == 0)) {
5923 /* cdp */
5924 return 1;
5927 crm = insn & 0xf;
5928 if (is64) {
5929 crn = 0;
5930 opc1 = (insn >> 4) & 0xf;
5931 opc2 = 0;
5932 rt2 = (insn >> 16) & 0xf;
5933 } else {
5934 crn = (insn >> 16) & 0xf;
5935 opc1 = (insn >> 21) & 7;
5936 opc2 = (insn >> 5) & 7;
5937 rt2 = 0;
5939 isread = (insn >> 20) & 1;
5940 rt = (insn >> 12) & 0xf;
5942 ri = get_arm_cp_reginfo(s->cp_regs,
5943 ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
5944 if (ri) {
5945 bool need_exit_tb;
5947 /* Check access permissions */
5948 if (!cp_access_ok(s->current_el, ri, isread)) {
5949 return 1;
5952 if (s->hstr_active || ri->accessfn ||
5953 (arm_dc_feature(s, ARM_FEATURE_XSCALE) && cpnum < 14)) {
5954 /* Emit code to perform further access permissions checks at
5955 * runtime; this may result in an exception.
5956 * Note that on XScale all cp0..c13 registers do an access check
5957 * call in order to handle c15_cpar.
5959 TCGv_ptr tmpptr;
5960 TCGv_i32 tcg_syn, tcg_isread;
5961 uint32_t syndrome;
5963 /* Note that since we are an implementation which takes an
5964 * exception on a trapped conditional instruction only if the
5965 * instruction passes its condition code check, we can take
5966 * advantage of the clause in the ARM ARM that allows us to set
5967 * the COND field in the instruction to 0xE in all cases.
5968 * We could fish the actual condition out of the insn (ARM)
5969 * or the condexec bits (Thumb) but it isn't necessary.
5971 switch (cpnum) {
5972 case 14:
5973 if (is64) {
5974 syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
5975 isread, false);
5976 } else {
5977 syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
5978 rt, isread, false);
5980 break;
5981 case 15:
5982 if (is64) {
5983 syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
5984 isread, false);
5985 } else {
5986 syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
5987 rt, isread, false);
5989 break;
5990 default:
5991 /* ARMv8 defines that only coprocessors 14 and 15 exist,
5992 * so this can only happen if this is an ARMv7 or earlier CPU,
5993 * in which case the syndrome information won't actually be
5994 * guest visible.
5996 assert(!arm_dc_feature(s, ARM_FEATURE_V8));
5997 syndrome = syn_uncategorized();
5998 break;
6001 gen_set_condexec(s);
6002 gen_set_pc_im(s, s->pc_curr);
6003 tmpptr = tcg_const_ptr(ri);
6004 tcg_syn = tcg_const_i32(syndrome);
6005 tcg_isread = tcg_const_i32(isread);
6006 gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn,
6007 tcg_isread);
6008 tcg_temp_free_ptr(tmpptr);
6009 tcg_temp_free_i32(tcg_syn);
6010 tcg_temp_free_i32(tcg_isread);
6011 } else if (ri->type & ARM_CP_RAISES_EXC) {
6013 * The readfn or writefn might raise an exception;
6014 * synchronize the CPU state in case it does.
6016 gen_set_condexec(s);
6017 gen_set_pc_im(s, s->pc_curr);
6020 /* Handle special cases first */
6021 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
6022 case ARM_CP_NOP:
6023 return 0;
6024 case ARM_CP_WFI:
6025 if (isread) {
6026 return 1;
6028 gen_set_pc_im(s, s->base.pc_next);
6029 s->base.is_jmp = DISAS_WFI;
6030 return 0;
6031 default:
6032 break;
6035 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
6036 gen_io_start();
6039 if (isread) {
6040 /* Read */
6041 if (is64) {
6042 TCGv_i64 tmp64;
6043 TCGv_i32 tmp;
6044 if (ri->type & ARM_CP_CONST) {
6045 tmp64 = tcg_const_i64(ri->resetvalue);
6046 } else if (ri->readfn) {
6047 TCGv_ptr tmpptr;
6048 tmp64 = tcg_temp_new_i64();
6049 tmpptr = tcg_const_ptr(ri);
6050 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
6051 tcg_temp_free_ptr(tmpptr);
6052 } else {
6053 tmp64 = tcg_temp_new_i64();
6054 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
6056 tmp = tcg_temp_new_i32();
6057 tcg_gen_extrl_i64_i32(tmp, tmp64);
6058 store_reg(s, rt, tmp);
6059 tmp = tcg_temp_new_i32();
6060 tcg_gen_extrh_i64_i32(tmp, tmp64);
6061 tcg_temp_free_i64(tmp64);
6062 store_reg(s, rt2, tmp);
6063 } else {
6064 TCGv_i32 tmp;
6065 if (ri->type & ARM_CP_CONST) {
6066 tmp = tcg_const_i32(ri->resetvalue);
6067 } else if (ri->readfn) {
6068 TCGv_ptr tmpptr;
6069 tmp = tcg_temp_new_i32();
6070 tmpptr = tcg_const_ptr(ri);
6071 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
6072 tcg_temp_free_ptr(tmpptr);
6073 } else {
6074 tmp = load_cpu_offset(ri->fieldoffset);
6076 if (rt == 15) {
6077 /* Destination register of r15 for 32 bit loads sets
6078 * the condition codes from the high 4 bits of the value
6080 gen_set_nzcv(tmp);
6081 tcg_temp_free_i32(tmp);
6082 } else {
6083 store_reg(s, rt, tmp);
6086 } else {
6087 /* Write */
6088 if (ri->type & ARM_CP_CONST) {
6089 /* If not forbidden by access permissions, treat as WI */
6090 return 0;
6093 if (is64) {
6094 TCGv_i32 tmplo, tmphi;
6095 TCGv_i64 tmp64 = tcg_temp_new_i64();
6096 tmplo = load_reg(s, rt);
6097 tmphi = load_reg(s, rt2);
6098 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
6099 tcg_temp_free_i32(tmplo);
6100 tcg_temp_free_i32(tmphi);
6101 if (ri->writefn) {
6102 TCGv_ptr tmpptr = tcg_const_ptr(ri);
6103 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
6104 tcg_temp_free_ptr(tmpptr);
6105 } else {
6106 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
6108 tcg_temp_free_i64(tmp64);
6109 } else {
6110 if (ri->writefn) {
6111 TCGv_i32 tmp;
6112 TCGv_ptr tmpptr;
6113 tmp = load_reg(s, rt);
6114 tmpptr = tcg_const_ptr(ri);
6115 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
6116 tcg_temp_free_ptr(tmpptr);
6117 tcg_temp_free_i32(tmp);
6118 } else {
6119 TCGv_i32 tmp = load_reg(s, rt);
6120 store_cpu_offset(tmp, ri->fieldoffset);
6125 /* I/O operations must end the TB here (whether read or write) */
6126 need_exit_tb = ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) &&
6127 (ri->type & ARM_CP_IO));
6129 if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
6131 * A write to any coprocessor register that ends a TB
6132 * must rebuild the hflags for the next TB.
6134 TCGv_i32 tcg_el = tcg_const_i32(s->current_el);
6135 if (arm_dc_feature(s, ARM_FEATURE_M)) {
6136 gen_helper_rebuild_hflags_m32(cpu_env, tcg_el);
6137 } else {
6138 if (ri->type & ARM_CP_NEWEL) {
6139 gen_helper_rebuild_hflags_a32_newel(cpu_env);
6140 } else {
6141 gen_helper_rebuild_hflags_a32(cpu_env, tcg_el);
6144 tcg_temp_free_i32(tcg_el);
6146 * We default to ending the TB on a coprocessor register write,
6147 * but allow this to be suppressed by the register definition
6148 * (usually only necessary to work around guest bugs).
6150 need_exit_tb = true;
6152 if (need_exit_tb) {
6153 gen_lookup_tb(s);
6156 return 0;
6159 /* Unknown register; this might be a guest error or a QEMU
6160 * unimplemented feature.
6162 if (is64) {
6163 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
6164 "64 bit system register cp:%d opc1: %d crm:%d "
6165 "(%s)\n",
6166 isread ? "read" : "write", cpnum, opc1, crm,
6167 s->ns ? "non-secure" : "secure");
6168 } else {
6169 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
6170 "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d "
6171 "(%s)\n",
6172 isread ? "read" : "write", cpnum, opc1, crn, crm, opc2,
6173 s->ns ? "non-secure" : "secure");
6176 return 1;
6180 /* Store a 64-bit value to a register pair. Clobbers val. */
6181 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
6183 TCGv_i32 tmp;
6184 tmp = tcg_temp_new_i32();
6185 tcg_gen_extrl_i64_i32(tmp, val);
6186 store_reg(s, rlow, tmp);
6187 tmp = tcg_temp_new_i32();
6188 tcg_gen_extrh_i64_i32(tmp, val);
6189 store_reg(s, rhigh, tmp);
6192 /* load and add a 64-bit value from a register pair. */
6193 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
6195 TCGv_i64 tmp;
6196 TCGv_i32 tmpl;
6197 TCGv_i32 tmph;
6199 /* Load 64-bit value rd:rn. */
6200 tmpl = load_reg(s, rlow);
6201 tmph = load_reg(s, rhigh);
6202 tmp = tcg_temp_new_i64();
6203 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
6204 tcg_temp_free_i32(tmpl);
6205 tcg_temp_free_i32(tmph);
6206 tcg_gen_add_i64(val, val, tmp);
6207 tcg_temp_free_i64(tmp);
6210 /* Set N and Z flags from hi|lo. */
6211 static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
6213 tcg_gen_mov_i32(cpu_NF, hi);
6214 tcg_gen_or_i32(cpu_ZF, lo, hi);
6217 /* Load/Store exclusive instructions are implemented by remembering
6218 the value/address loaded, and seeing if these are the same
6219 when the store is performed. This should be sufficient to implement
6220 the architecturally mandated semantics, and avoids having to monitor
6221 regular stores. The compare vs the remembered value is done during
6222 the cmpxchg operation, but we must compare the addresses manually. */
6223 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
6224 TCGv_i32 addr, int size)
6226 TCGv_i32 tmp = tcg_temp_new_i32();
6227 MemOp opc = size | MO_ALIGN | s->be_data;
6229 s->is_ldex = true;
6231 if (size == 3) {
6232 TCGv_i32 tmp2 = tcg_temp_new_i32();
6233 TCGv_i64 t64 = tcg_temp_new_i64();
6235 /* For AArch32, architecturally the 32-bit word at the lowest
6236 * address is always Rt and the one at addr+4 is Rt2, even if
6237 * the CPU is big-endian. That means we don't want to do a
6238 * gen_aa32_ld_i64(), which invokes gen_aa32_frob64() as if
6239 * for an architecturally 64-bit access, but instead do a
6240 * 64-bit access using MO_BE if appropriate and then split
6241 * the two halves.
6242 * This only makes a difference for BE32 user-mode, where
6243 * frob64() must not flip the two halves of the 64-bit data
6244 * but this code must treat BE32 user-mode like BE32 system.
6246 TCGv taddr = gen_aa32_addr(s, addr, opc);
6248 tcg_gen_qemu_ld_i64(t64, taddr, get_mem_index(s), opc);
6249 tcg_temp_free(taddr);
6250 tcg_gen_mov_i64(cpu_exclusive_val, t64);
6251 if (s->be_data == MO_BE) {
6252 tcg_gen_extr_i64_i32(tmp2, tmp, t64);
6253 } else {
6254 tcg_gen_extr_i64_i32(tmp, tmp2, t64);
6256 tcg_temp_free_i64(t64);
6258 store_reg(s, rt2, tmp2);
6259 } else {
6260 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), opc);
6261 tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
6264 store_reg(s, rt, tmp);
6265 tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
6268 static void gen_clrex(DisasContext *s)
6270 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
6273 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
6274 TCGv_i32 addr, int size)
6276 TCGv_i32 t0, t1, t2;
6277 TCGv_i64 extaddr;
6278 TCGv taddr;
6279 TCGLabel *done_label;
6280 TCGLabel *fail_label;
6281 MemOp opc = size | MO_ALIGN | s->be_data;
6283 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
6284 [addr] = {Rt};
6285 {Rd} = 0;
6286 } else {
6287 {Rd} = 1;
6288 } */
6289 fail_label = gen_new_label();
6290 done_label = gen_new_label();
6291 extaddr = tcg_temp_new_i64();
6292 tcg_gen_extu_i32_i64(extaddr, addr);
6293 tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
6294 tcg_temp_free_i64(extaddr);
6296 taddr = gen_aa32_addr(s, addr, opc);
6297 t0 = tcg_temp_new_i32();
6298 t1 = load_reg(s, rt);
6299 if (size == 3) {
6300 TCGv_i64 o64 = tcg_temp_new_i64();
6301 TCGv_i64 n64 = tcg_temp_new_i64();
6303 t2 = load_reg(s, rt2);
6304 /* For AArch32, architecturally the 32-bit word at the lowest
6305 * address is always Rt and the one at addr+4 is Rt2, even if
6306 * the CPU is big-endian. Since we're going to treat this as a
6307 * single 64-bit BE store, we need to put the two halves in the
6308 * opposite order for BE to LE, so that they end up in the right
6309 * places.
6310 * We don't want gen_aa32_frob64() because that does the wrong
6311 * thing for BE32 usermode.
6313 if (s->be_data == MO_BE) {
6314 tcg_gen_concat_i32_i64(n64, t2, t1);
6315 } else {
6316 tcg_gen_concat_i32_i64(n64, t1, t2);
6318 tcg_temp_free_i32(t2);
6320 tcg_gen_atomic_cmpxchg_i64(o64, taddr, cpu_exclusive_val, n64,
6321 get_mem_index(s), opc);
6322 tcg_temp_free_i64(n64);
6324 tcg_gen_setcond_i64(TCG_COND_NE, o64, o64, cpu_exclusive_val);
6325 tcg_gen_extrl_i64_i32(t0, o64);
6327 tcg_temp_free_i64(o64);
6328 } else {
6329 t2 = tcg_temp_new_i32();
6330 tcg_gen_extrl_i64_i32(t2, cpu_exclusive_val);
6331 tcg_gen_atomic_cmpxchg_i32(t0, taddr, t2, t1, get_mem_index(s), opc);
6332 tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t2);
6333 tcg_temp_free_i32(t2);
6335 tcg_temp_free_i32(t1);
6336 tcg_temp_free(taddr);
6337 tcg_gen_mov_i32(cpu_R[rd], t0);
6338 tcg_temp_free_i32(t0);
6339 tcg_gen_br(done_label);
6341 gen_set_label(fail_label);
6342 tcg_gen_movi_i32(cpu_R[rd], 1);
6343 gen_set_label(done_label);
6344 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
6347 /* gen_srs:
6348 * @env: CPUARMState
6349 * @s: DisasContext
6350 * @mode: mode field from insn (which stack to store to)
6351 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
6352 * @writeback: true if writeback bit set
6354 * Generate code for the SRS (Store Return State) insn.
6356 static void gen_srs(DisasContext *s,
6357 uint32_t mode, uint32_t amode, bool writeback)
6359 int32_t offset;
6360 TCGv_i32 addr, tmp;
6361 bool undef = false;
6363 /* SRS is:
6364 * - trapped to EL3 if EL3 is AArch64 and we are at Secure EL1
6365 * and specified mode is monitor mode
6366 * - UNDEFINED in Hyp mode
6367 * - UNPREDICTABLE in User or System mode
6368 * - UNPREDICTABLE if the specified mode is:
6369 * -- not implemented
6370 * -- not a valid mode number
6371 * -- a mode that's at a higher exception level
6372 * -- Monitor, if we are Non-secure
6373 * For the UNPREDICTABLE cases we choose to UNDEF.
6375 if (s->current_el == 1 && !s->ns && mode == ARM_CPU_MODE_MON) {
6376 gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(), 3);
6377 return;
6380 if (s->current_el == 0 || s->current_el == 2) {
6381 undef = true;
6384 switch (mode) {
6385 case ARM_CPU_MODE_USR:
6386 case ARM_CPU_MODE_FIQ:
6387 case ARM_CPU_MODE_IRQ:
6388 case ARM_CPU_MODE_SVC:
6389 case ARM_CPU_MODE_ABT:
6390 case ARM_CPU_MODE_UND:
6391 case ARM_CPU_MODE_SYS:
6392 break;
6393 case ARM_CPU_MODE_HYP:
6394 if (s->current_el == 1 || !arm_dc_feature(s, ARM_FEATURE_EL2)) {
6395 undef = true;
6397 break;
6398 case ARM_CPU_MODE_MON:
6399 /* No need to check specifically for "are we non-secure" because
6400 * we've already made EL0 UNDEF and handled the trap for S-EL1;
6401 * so if this isn't EL3 then we must be non-secure.
6403 if (s->current_el != 3) {
6404 undef = true;
6406 break;
6407 default:
6408 undef = true;
6411 if (undef) {
6412 unallocated_encoding(s);
6413 return;
6416 addr = tcg_temp_new_i32();
6417 tmp = tcg_const_i32(mode);
6418 /* get_r13_banked() will raise an exception if called from System mode */
6419 gen_set_condexec(s);
6420 gen_set_pc_im(s, s->pc_curr);
6421 gen_helper_get_r13_banked(addr, cpu_env, tmp);
6422 tcg_temp_free_i32(tmp);
6423 switch (amode) {
6424 case 0: /* DA */
6425 offset = -4;
6426 break;
6427 case 1: /* IA */
6428 offset = 0;
6429 break;
6430 case 2: /* DB */
6431 offset = -8;
6432 break;
6433 case 3: /* IB */
6434 offset = 4;
6435 break;
6436 default:
6437 abort();
6439 tcg_gen_addi_i32(addr, addr, offset);
6440 tmp = load_reg(s, 14);
6441 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
6442 tcg_temp_free_i32(tmp);
6443 tmp = load_cpu_field(spsr);
6444 tcg_gen_addi_i32(addr, addr, 4);
6445 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
6446 tcg_temp_free_i32(tmp);
6447 if (writeback) {
6448 switch (amode) {
6449 case 0:
6450 offset = -8;
6451 break;
6452 case 1:
6453 offset = 4;
6454 break;
6455 case 2:
6456 offset = -4;
6457 break;
6458 case 3:
6459 offset = 0;
6460 break;
6461 default:
6462 abort();
6464 tcg_gen_addi_i32(addr, addr, offset);
6465 tmp = tcg_const_i32(mode);
6466 gen_helper_set_r13_banked(cpu_env, tmp, addr);
6467 tcg_temp_free_i32(tmp);
6469 tcg_temp_free_i32(addr);
6470 s->base.is_jmp = DISAS_UPDATE;
6473 /* Generate a label used for skipping this instruction */
6474 static void arm_gen_condlabel(DisasContext *s)
6476 if (!s->condjmp) {
6477 s->condlabel = gen_new_label();
6478 s->condjmp = 1;
6482 /* Skip this instruction if the ARM condition is false */
6483 static void arm_skip_unless(DisasContext *s, uint32_t cond)
6485 arm_gen_condlabel(s);
6486 arm_gen_test_cc(cond ^ 1, s->condlabel);
6491 * Constant expanders for the decoders.
6494 static int negate(DisasContext *s, int x)
6496 return -x;
6499 static int plus_2(DisasContext *s, int x)
6501 return x + 2;
6504 static int times_2(DisasContext *s, int x)
6506 return x * 2;
6509 static int times_4(DisasContext *s, int x)
6511 return x * 4;
6514 /* Return only the rotation part of T32ExpandImm. */
6515 static int t32_expandimm_rot(DisasContext *s, int x)
6517 return x & 0xc00 ? extract32(x, 7, 5) : 0;
6520 /* Return the unrotated immediate from T32ExpandImm. */
6521 static int t32_expandimm_imm(DisasContext *s, int x)
6523 int imm = extract32(x, 0, 8);
6525 switch (extract32(x, 8, 4)) {
6526 case 0: /* XY */
6527 /* Nothing to do. */
6528 break;
6529 case 1: /* 00XY00XY */
6530 imm *= 0x00010001;
6531 break;
6532 case 2: /* XY00XY00 */
6533 imm *= 0x01000100;
6534 break;
6535 case 3: /* XYXYXYXY */
6536 imm *= 0x01010101;
6537 break;
6538 default:
6539 /* Rotated constant. */
6540 imm |= 0x80;
6541 break;
6543 return imm;
6546 static int t32_branch24(DisasContext *s, int x)
6548 /* Convert J1:J2 at x[22:21] to I2:I1, which involves I=J^~S. */
6549 x ^= !(x < 0) * (3 << 21);
6550 /* Append the final zero. */
6551 return x << 1;
6554 static int t16_setflags(DisasContext *s)
6556 return s->condexec_mask == 0;
6559 static int t16_push_list(DisasContext *s, int x)
6561 return (x & 0xff) | (x & 0x100) << (14 - 8);
6564 static int t16_pop_list(DisasContext *s, int x)
6566 return (x & 0xff) | (x & 0x100) << (15 - 8);
6570 * Include the generated decoders.
6573 #include "decode-a32.inc.c"
6574 #include "decode-a32-uncond.inc.c"
6575 #include "decode-t32.inc.c"
6576 #include "decode-t16.inc.c"
6578 /* Helpers to swap operands for reverse-subtract. */
6579 static void gen_rsb(TCGv_i32 dst, TCGv_i32 a, TCGv_i32 b)
6581 tcg_gen_sub_i32(dst, b, a);
6584 static void gen_rsb_CC(TCGv_i32 dst, TCGv_i32 a, TCGv_i32 b)
6586 gen_sub_CC(dst, b, a);
6589 static void gen_rsc(TCGv_i32 dest, TCGv_i32 a, TCGv_i32 b)
6591 gen_sub_carry(dest, b, a);
6594 static void gen_rsc_CC(TCGv_i32 dest, TCGv_i32 a, TCGv_i32 b)
6596 gen_sbc_CC(dest, b, a);
6600 * Helpers for the data processing routines.
6602 * After the computation store the results back.
6603 * This may be suppressed altogether (STREG_NONE), require a runtime
6604 * check against the stack limits (STREG_SP_CHECK), or generate an
6605 * exception return. Oh, or store into a register.
6607 * Always return true, indicating success for a trans_* function.
6609 typedef enum {
6610 STREG_NONE,
6611 STREG_NORMAL,
6612 STREG_SP_CHECK,
6613 STREG_EXC_RET,
6614 } StoreRegKind;
6616 static bool store_reg_kind(DisasContext *s, int rd,
6617 TCGv_i32 val, StoreRegKind kind)
6619 switch (kind) {
6620 case STREG_NONE:
6621 tcg_temp_free_i32(val);
6622 return true;
6623 case STREG_NORMAL:
6624 /* See ALUWritePC: Interworking only from a32 mode. */
6625 if (s->thumb) {
6626 store_reg(s, rd, val);
6627 } else {
6628 store_reg_bx(s, rd, val);
6630 return true;
6631 case STREG_SP_CHECK:
6632 store_sp_checked(s, val);
6633 return true;
6634 case STREG_EXC_RET:
6635 gen_exception_return(s, val);
6636 return true;
6638 g_assert_not_reached();
6642 * Data Processing (register)
6644 * Operate, with set flags, one register source,
6645 * one immediate shifted register source, and a destination.
6647 static bool op_s_rrr_shi(DisasContext *s, arg_s_rrr_shi *a,
6648 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32),
6649 int logic_cc, StoreRegKind kind)
6651 TCGv_i32 tmp1, tmp2;
6653 tmp2 = load_reg(s, a->rm);
6654 gen_arm_shift_im(tmp2, a->shty, a->shim, logic_cc);
6655 tmp1 = load_reg(s, a->rn);
6657 gen(tmp1, tmp1, tmp2);
6658 tcg_temp_free_i32(tmp2);
6660 if (logic_cc) {
6661 gen_logic_CC(tmp1);
6663 return store_reg_kind(s, a->rd, tmp1, kind);
6666 static bool op_s_rxr_shi(DisasContext *s, arg_s_rrr_shi *a,
6667 void (*gen)(TCGv_i32, TCGv_i32),
6668 int logic_cc, StoreRegKind kind)
6670 TCGv_i32 tmp;
6672 tmp = load_reg(s, a->rm);
6673 gen_arm_shift_im(tmp, a->shty, a->shim, logic_cc);
6675 gen(tmp, tmp);
6676 if (logic_cc) {
6677 gen_logic_CC(tmp);
6679 return store_reg_kind(s, a->rd, tmp, kind);
6683 * Data-processing (register-shifted register)
6685 * Operate, with set flags, one register source,
6686 * one register shifted register source, and a destination.
6688 static bool op_s_rrr_shr(DisasContext *s, arg_s_rrr_shr *a,
6689 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32),
6690 int logic_cc, StoreRegKind kind)
6692 TCGv_i32 tmp1, tmp2;
6694 tmp1 = load_reg(s, a->rs);
6695 tmp2 = load_reg(s, a->rm);
6696 gen_arm_shift_reg(tmp2, a->shty, tmp1, logic_cc);
6697 tmp1 = load_reg(s, a->rn);
6699 gen(tmp1, tmp1, tmp2);
6700 tcg_temp_free_i32(tmp2);
6702 if (logic_cc) {
6703 gen_logic_CC(tmp1);
6705 return store_reg_kind(s, a->rd, tmp1, kind);
6708 static bool op_s_rxr_shr(DisasContext *s, arg_s_rrr_shr *a,
6709 void (*gen)(TCGv_i32, TCGv_i32),
6710 int logic_cc, StoreRegKind kind)
6712 TCGv_i32 tmp1, tmp2;
6714 tmp1 = load_reg(s, a->rs);
6715 tmp2 = load_reg(s, a->rm);
6716 gen_arm_shift_reg(tmp2, a->shty, tmp1, logic_cc);
6718 gen(tmp2, tmp2);
6719 if (logic_cc) {
6720 gen_logic_CC(tmp2);
6722 return store_reg_kind(s, a->rd, tmp2, kind);
6726 * Data-processing (immediate)
6728 * Operate, with set flags, one register source,
6729 * one rotated immediate, and a destination.
6731 * Note that logic_cc && a->rot setting CF based on the msb of the
6732 * immediate is the reason why we must pass in the unrotated form
6733 * of the immediate.
6735 static bool op_s_rri_rot(DisasContext *s, arg_s_rri_rot *a,
6736 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32),
6737 int logic_cc, StoreRegKind kind)
6739 TCGv_i32 tmp1, tmp2;
6740 uint32_t imm;
6742 imm = ror32(a->imm, a->rot);
6743 if (logic_cc && a->rot) {
6744 tcg_gen_movi_i32(cpu_CF, imm >> 31);
6746 tmp2 = tcg_const_i32(imm);
6747 tmp1 = load_reg(s, a->rn);
6749 gen(tmp1, tmp1, tmp2);
6750 tcg_temp_free_i32(tmp2);
6752 if (logic_cc) {
6753 gen_logic_CC(tmp1);
6755 return store_reg_kind(s, a->rd, tmp1, kind);
6758 static bool op_s_rxi_rot(DisasContext *s, arg_s_rri_rot *a,
6759 void (*gen)(TCGv_i32, TCGv_i32),
6760 int logic_cc, StoreRegKind kind)
6762 TCGv_i32 tmp;
6763 uint32_t imm;
6765 imm = ror32(a->imm, a->rot);
6766 if (logic_cc && a->rot) {
6767 tcg_gen_movi_i32(cpu_CF, imm >> 31);
6769 tmp = tcg_const_i32(imm);
6771 gen(tmp, tmp);
6772 if (logic_cc) {
6773 gen_logic_CC(tmp);
6775 return store_reg_kind(s, a->rd, tmp, kind);
6778 #define DO_ANY3(NAME, OP, L, K) \
6779 static bool trans_##NAME##_rrri(DisasContext *s, arg_s_rrr_shi *a) \
6780 { StoreRegKind k = (K); return op_s_rrr_shi(s, a, OP, L, k); } \
6781 static bool trans_##NAME##_rrrr(DisasContext *s, arg_s_rrr_shr *a) \
6782 { StoreRegKind k = (K); return op_s_rrr_shr(s, a, OP, L, k); } \
6783 static bool trans_##NAME##_rri(DisasContext *s, arg_s_rri_rot *a) \
6784 { StoreRegKind k = (K); return op_s_rri_rot(s, a, OP, L, k); }
6786 #define DO_ANY2(NAME, OP, L, K) \
6787 static bool trans_##NAME##_rxri(DisasContext *s, arg_s_rrr_shi *a) \
6788 { StoreRegKind k = (K); return op_s_rxr_shi(s, a, OP, L, k); } \
6789 static bool trans_##NAME##_rxrr(DisasContext *s, arg_s_rrr_shr *a) \
6790 { StoreRegKind k = (K); return op_s_rxr_shr(s, a, OP, L, k); } \
6791 static bool trans_##NAME##_rxi(DisasContext *s, arg_s_rri_rot *a) \
6792 { StoreRegKind k = (K); return op_s_rxi_rot(s, a, OP, L, k); }
6794 #define DO_CMP2(NAME, OP, L) \
6795 static bool trans_##NAME##_xrri(DisasContext *s, arg_s_rrr_shi *a) \
6796 { return op_s_rrr_shi(s, a, OP, L, STREG_NONE); } \
6797 static bool trans_##NAME##_xrrr(DisasContext *s, arg_s_rrr_shr *a) \
6798 { return op_s_rrr_shr(s, a, OP, L, STREG_NONE); } \
6799 static bool trans_##NAME##_xri(DisasContext *s, arg_s_rri_rot *a) \
6800 { return op_s_rri_rot(s, a, OP, L, STREG_NONE); }
6802 DO_ANY3(AND, tcg_gen_and_i32, a->s, STREG_NORMAL)
6803 DO_ANY3(EOR, tcg_gen_xor_i32, a->s, STREG_NORMAL)
6804 DO_ANY3(ORR, tcg_gen_or_i32, a->s, STREG_NORMAL)
6805 DO_ANY3(BIC, tcg_gen_andc_i32, a->s, STREG_NORMAL)
6807 DO_ANY3(RSB, a->s ? gen_rsb_CC : gen_rsb, false, STREG_NORMAL)
6808 DO_ANY3(ADC, a->s ? gen_adc_CC : gen_add_carry, false, STREG_NORMAL)
6809 DO_ANY3(SBC, a->s ? gen_sbc_CC : gen_sub_carry, false, STREG_NORMAL)
6810 DO_ANY3(RSC, a->s ? gen_rsc_CC : gen_rsc, false, STREG_NORMAL)
6812 DO_CMP2(TST, tcg_gen_and_i32, true)
6813 DO_CMP2(TEQ, tcg_gen_xor_i32, true)
6814 DO_CMP2(CMN, gen_add_CC, false)
6815 DO_CMP2(CMP, gen_sub_CC, false)
6817 DO_ANY3(ADD, a->s ? gen_add_CC : tcg_gen_add_i32, false,
6818 a->rd == 13 && a->rn == 13 ? STREG_SP_CHECK : STREG_NORMAL)
6821 * Note for the computation of StoreRegKind we return out of the
6822 * middle of the functions that are expanded by DO_ANY3, and that
6823 * we modify a->s via that parameter before it is used by OP.
6825 DO_ANY3(SUB, a->s ? gen_sub_CC : tcg_gen_sub_i32, false,
6827 StoreRegKind ret = STREG_NORMAL;
6828 if (a->rd == 15 && a->s) {
6830 * See ALUExceptionReturn:
6831 * In User mode, UNPREDICTABLE; we choose UNDEF.
6832 * In Hyp mode, UNDEFINED.
6834 if (IS_USER(s) || s->current_el == 2) {
6835 unallocated_encoding(s);
6836 return true;
6838 /* There is no writeback of nzcv to PSTATE. */
6839 a->s = 0;
6840 ret = STREG_EXC_RET;
6841 } else if (a->rd == 13 && a->rn == 13) {
6842 ret = STREG_SP_CHECK;
6844 ret;
6847 DO_ANY2(MOV, tcg_gen_mov_i32, a->s,
6849 StoreRegKind ret = STREG_NORMAL;
6850 if (a->rd == 15 && a->s) {
6852 * See ALUExceptionReturn:
6853 * In User mode, UNPREDICTABLE; we choose UNDEF.
6854 * In Hyp mode, UNDEFINED.
6856 if (IS_USER(s) || s->current_el == 2) {
6857 unallocated_encoding(s);
6858 return true;
6860 /* There is no writeback of nzcv to PSTATE. */
6861 a->s = 0;
6862 ret = STREG_EXC_RET;
6863 } else if (a->rd == 13) {
6864 ret = STREG_SP_CHECK;
6866 ret;
6869 DO_ANY2(MVN, tcg_gen_not_i32, a->s, STREG_NORMAL)
6872 * ORN is only available with T32, so there is no register-shifted-register
6873 * form of the insn. Using the DO_ANY3 macro would create an unused function.
6875 static bool trans_ORN_rrri(DisasContext *s, arg_s_rrr_shi *a)
6877 return op_s_rrr_shi(s, a, tcg_gen_orc_i32, a->s, STREG_NORMAL);
6880 static bool trans_ORN_rri(DisasContext *s, arg_s_rri_rot *a)
6882 return op_s_rri_rot(s, a, tcg_gen_orc_i32, a->s, STREG_NORMAL);
6885 #undef DO_ANY3
6886 #undef DO_ANY2
6887 #undef DO_CMP2
6889 static bool trans_ADR(DisasContext *s, arg_ri *a)
6891 store_reg_bx(s, a->rd, add_reg_for_lit(s, 15, a->imm));
6892 return true;
6895 static bool trans_MOVW(DisasContext *s, arg_MOVW *a)
6897 TCGv_i32 tmp;
6899 if (!ENABLE_ARCH_6T2) {
6900 return false;
6903 tmp = tcg_const_i32(a->imm);
6904 store_reg(s, a->rd, tmp);
6905 return true;
6908 static bool trans_MOVT(DisasContext *s, arg_MOVW *a)
6910 TCGv_i32 tmp;
6912 if (!ENABLE_ARCH_6T2) {
6913 return false;
6916 tmp = load_reg(s, a->rd);
6917 tcg_gen_ext16u_i32(tmp, tmp);
6918 tcg_gen_ori_i32(tmp, tmp, a->imm << 16);
6919 store_reg(s, a->rd, tmp);
6920 return true;
6924 * Multiply and multiply accumulate
6927 static bool op_mla(DisasContext *s, arg_s_rrrr *a, bool add)
6929 TCGv_i32 t1, t2;
6931 t1 = load_reg(s, a->rn);
6932 t2 = load_reg(s, a->rm);
6933 tcg_gen_mul_i32(t1, t1, t2);
6934 tcg_temp_free_i32(t2);
6935 if (add) {
6936 t2 = load_reg(s, a->ra);
6937 tcg_gen_add_i32(t1, t1, t2);
6938 tcg_temp_free_i32(t2);
6940 if (a->s) {
6941 gen_logic_CC(t1);
6943 store_reg(s, a->rd, t1);
6944 return true;
6947 static bool trans_MUL(DisasContext *s, arg_MUL *a)
6949 return op_mla(s, a, false);
6952 static bool trans_MLA(DisasContext *s, arg_MLA *a)
6954 return op_mla(s, a, true);
6957 static bool trans_MLS(DisasContext *s, arg_MLS *a)
6959 TCGv_i32 t1, t2;
6961 if (!ENABLE_ARCH_6T2) {
6962 return false;
6964 t1 = load_reg(s, a->rn);
6965 t2 = load_reg(s, a->rm);
6966 tcg_gen_mul_i32(t1, t1, t2);
6967 tcg_temp_free_i32(t2);
6968 t2 = load_reg(s, a->ra);
6969 tcg_gen_sub_i32(t1, t2, t1);
6970 tcg_temp_free_i32(t2);
6971 store_reg(s, a->rd, t1);
6972 return true;
6975 static bool op_mlal(DisasContext *s, arg_s_rrrr *a, bool uns, bool add)
6977 TCGv_i32 t0, t1, t2, t3;
6979 t0 = load_reg(s, a->rm);
6980 t1 = load_reg(s, a->rn);
6981 if (uns) {
6982 tcg_gen_mulu2_i32(t0, t1, t0, t1);
6983 } else {
6984 tcg_gen_muls2_i32(t0, t1, t0, t1);
6986 if (add) {
6987 t2 = load_reg(s, a->ra);
6988 t3 = load_reg(s, a->rd);
6989 tcg_gen_add2_i32(t0, t1, t0, t1, t2, t3);
6990 tcg_temp_free_i32(t2);
6991 tcg_temp_free_i32(t3);
6993 if (a->s) {
6994 gen_logicq_cc(t0, t1);
6996 store_reg(s, a->ra, t0);
6997 store_reg(s, a->rd, t1);
6998 return true;
7001 static bool trans_UMULL(DisasContext *s, arg_UMULL *a)
7003 return op_mlal(s, a, true, false);
7006 static bool trans_SMULL(DisasContext *s, arg_SMULL *a)
7008 return op_mlal(s, a, false, false);
7011 static bool trans_UMLAL(DisasContext *s, arg_UMLAL *a)
7013 return op_mlal(s, a, true, true);
7016 static bool trans_SMLAL(DisasContext *s, arg_SMLAL *a)
7018 return op_mlal(s, a, false, true);
7021 static bool trans_UMAAL(DisasContext *s, arg_UMAAL *a)
7023 TCGv_i32 t0, t1, t2, zero;
7025 if (s->thumb
7026 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7027 : !ENABLE_ARCH_6) {
7028 return false;
7031 t0 = load_reg(s, a->rm);
7032 t1 = load_reg(s, a->rn);
7033 tcg_gen_mulu2_i32(t0, t1, t0, t1);
7034 zero = tcg_const_i32(0);
7035 t2 = load_reg(s, a->ra);
7036 tcg_gen_add2_i32(t0, t1, t0, t1, t2, zero);
7037 tcg_temp_free_i32(t2);
7038 t2 = load_reg(s, a->rd);
7039 tcg_gen_add2_i32(t0, t1, t0, t1, t2, zero);
7040 tcg_temp_free_i32(t2);
7041 tcg_temp_free_i32(zero);
7042 store_reg(s, a->ra, t0);
7043 store_reg(s, a->rd, t1);
7044 return true;
7048 * Saturating addition and subtraction
7051 static bool op_qaddsub(DisasContext *s, arg_rrr *a, bool add, bool doub)
7053 TCGv_i32 t0, t1;
7055 if (s->thumb
7056 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7057 : !ENABLE_ARCH_5TE) {
7058 return false;
7061 t0 = load_reg(s, a->rm);
7062 t1 = load_reg(s, a->rn);
7063 if (doub) {
7064 gen_helper_add_saturate(t1, cpu_env, t1, t1);
7066 if (add) {
7067 gen_helper_add_saturate(t0, cpu_env, t0, t1);
7068 } else {
7069 gen_helper_sub_saturate(t0, cpu_env, t0, t1);
7071 tcg_temp_free_i32(t1);
7072 store_reg(s, a->rd, t0);
7073 return true;
7076 #define DO_QADDSUB(NAME, ADD, DOUB) \
7077 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
7079 return op_qaddsub(s, a, ADD, DOUB); \
7082 DO_QADDSUB(QADD, true, false)
7083 DO_QADDSUB(QSUB, false, false)
7084 DO_QADDSUB(QDADD, true, true)
7085 DO_QADDSUB(QDSUB, false, true)
7087 #undef DO_QADDSUB
7090 * Halfword multiply and multiply accumulate
7093 static bool op_smlaxxx(DisasContext *s, arg_rrrr *a,
7094 int add_long, bool nt, bool mt)
7096 TCGv_i32 t0, t1, tl, th;
7098 if (s->thumb
7099 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
7100 : !ENABLE_ARCH_5TE) {
7101 return false;
7104 t0 = load_reg(s, a->rn);
7105 t1 = load_reg(s, a->rm);
7106 gen_mulxy(t0, t1, nt, mt);
7107 tcg_temp_free_i32(t1);
7109 switch (add_long) {
7110 case 0:
7111 store_reg(s, a->rd, t0);
7112 break;
7113 case 1:
7114 t1 = load_reg(s, a->ra);
7115 gen_helper_add_setq(t0, cpu_env, t0, t1);
7116 tcg_temp_free_i32(t1);
7117 store_reg(s, a->rd, t0);
7118 break;
7119 case 2:
7120 tl = load_reg(s, a->ra);
7121 th = load_reg(s, a->rd);
7122 /* Sign-extend the 32-bit product to 64 bits. */
7123 t1 = tcg_temp_new_i32();
7124 tcg_gen_sari_i32(t1, t0, 31);
7125 tcg_gen_add2_i32(tl, th, tl, th, t0, t1);
7126 tcg_temp_free_i32(t0);
7127 tcg_temp_free_i32(t1);
7128 store_reg(s, a->ra, tl);
7129 store_reg(s, a->rd, th);
7130 break;
7131 default:
7132 g_assert_not_reached();
7134 return true;
7137 #define DO_SMLAX(NAME, add, nt, mt) \
7138 static bool trans_##NAME(DisasContext *s, arg_rrrr *a) \
7140 return op_smlaxxx(s, a, add, nt, mt); \
7143 DO_SMLAX(SMULBB, 0, 0, 0)
7144 DO_SMLAX(SMULBT, 0, 0, 1)
7145 DO_SMLAX(SMULTB, 0, 1, 0)
7146 DO_SMLAX(SMULTT, 0, 1, 1)
7148 DO_SMLAX(SMLABB, 1, 0, 0)
7149 DO_SMLAX(SMLABT, 1, 0, 1)
7150 DO_SMLAX(SMLATB, 1, 1, 0)
7151 DO_SMLAX(SMLATT, 1, 1, 1)
7153 DO_SMLAX(SMLALBB, 2, 0, 0)
7154 DO_SMLAX(SMLALBT, 2, 0, 1)
7155 DO_SMLAX(SMLALTB, 2, 1, 0)
7156 DO_SMLAX(SMLALTT, 2, 1, 1)
7158 #undef DO_SMLAX
7160 static bool op_smlawx(DisasContext *s, arg_rrrr *a, bool add, bool mt)
7162 TCGv_i32 t0, t1;
7164 if (!ENABLE_ARCH_5TE) {
7165 return false;
7168 t0 = load_reg(s, a->rn);
7169 t1 = load_reg(s, a->rm);
7171 * Since the nominal result is product<47:16>, shift the 16-bit
7172 * input up by 16 bits, so that the result is at product<63:32>.
7174 if (mt) {
7175 tcg_gen_andi_i32(t1, t1, 0xffff0000);
7176 } else {
7177 tcg_gen_shli_i32(t1, t1, 16);
7179 tcg_gen_muls2_i32(t0, t1, t0, t1);
7180 tcg_temp_free_i32(t0);
7181 if (add) {
7182 t0 = load_reg(s, a->ra);
7183 gen_helper_add_setq(t1, cpu_env, t1, t0);
7184 tcg_temp_free_i32(t0);
7186 store_reg(s, a->rd, t1);
7187 return true;
7190 #define DO_SMLAWX(NAME, add, mt) \
7191 static bool trans_##NAME(DisasContext *s, arg_rrrr *a) \
7193 return op_smlawx(s, a, add, mt); \
7196 DO_SMLAWX(SMULWB, 0, 0)
7197 DO_SMLAWX(SMULWT, 0, 1)
7198 DO_SMLAWX(SMLAWB, 1, 0)
7199 DO_SMLAWX(SMLAWT, 1, 1)
7201 #undef DO_SMLAWX
7204 * MSR (immediate) and hints
7207 static bool trans_YIELD(DisasContext *s, arg_YIELD *a)
7210 * When running single-threaded TCG code, use the helper to ensure that
7211 * the next round-robin scheduled vCPU gets a crack. When running in
7212 * MTTCG we don't generate jumps to the helper as it won't affect the
7213 * scheduling of other vCPUs.
7215 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
7216 gen_set_pc_im(s, s->base.pc_next);
7217 s->base.is_jmp = DISAS_YIELD;
7219 return true;
7222 static bool trans_WFE(DisasContext *s, arg_WFE *a)
7225 * When running single-threaded TCG code, use the helper to ensure that
7226 * the next round-robin scheduled vCPU gets a crack. In MTTCG mode we
7227 * just skip this instruction. Currently the SEV/SEVL instructions,
7228 * which are *one* of many ways to wake the CPU from WFE, are not
7229 * implemented so we can't sleep like WFI does.
7231 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
7232 gen_set_pc_im(s, s->base.pc_next);
7233 s->base.is_jmp = DISAS_WFE;
7235 return true;
7238 static bool trans_WFI(DisasContext *s, arg_WFI *a)
7240 /* For WFI, halt the vCPU until an IRQ. */
7241 gen_set_pc_im(s, s->base.pc_next);
7242 s->base.is_jmp = DISAS_WFI;
7243 return true;
7246 static bool trans_NOP(DisasContext *s, arg_NOP *a)
7248 return true;
7251 static bool trans_MSR_imm(DisasContext *s, arg_MSR_imm *a)
7253 uint32_t val = ror32(a->imm, a->rot * 2);
7254 uint32_t mask = msr_mask(s, a->mask, a->r);
7256 if (gen_set_psr_im(s, mask, a->r, val)) {
7257 unallocated_encoding(s);
7259 return true;
7263 * Cyclic Redundancy Check
7266 static bool op_crc32(DisasContext *s, arg_rrr *a, bool c, MemOp sz)
7268 TCGv_i32 t1, t2, t3;
7270 if (!dc_isar_feature(aa32_crc32, s)) {
7271 return false;
7274 t1 = load_reg(s, a->rn);
7275 t2 = load_reg(s, a->rm);
7276 switch (sz) {
7277 case MO_8:
7278 gen_uxtb(t2);
7279 break;
7280 case MO_16:
7281 gen_uxth(t2);
7282 break;
7283 case MO_32:
7284 break;
7285 default:
7286 g_assert_not_reached();
7288 t3 = tcg_const_i32(1 << sz);
7289 if (c) {
7290 gen_helper_crc32c(t1, t1, t2, t3);
7291 } else {
7292 gen_helper_crc32(t1, t1, t2, t3);
7294 tcg_temp_free_i32(t2);
7295 tcg_temp_free_i32(t3);
7296 store_reg(s, a->rd, t1);
7297 return true;
7300 #define DO_CRC32(NAME, c, sz) \
7301 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
7302 { return op_crc32(s, a, c, sz); }
7304 DO_CRC32(CRC32B, false, MO_8)
7305 DO_CRC32(CRC32H, false, MO_16)
7306 DO_CRC32(CRC32W, false, MO_32)
7307 DO_CRC32(CRC32CB, true, MO_8)
7308 DO_CRC32(CRC32CH, true, MO_16)
7309 DO_CRC32(CRC32CW, true, MO_32)
7311 #undef DO_CRC32
7314 * Miscellaneous instructions
7317 static bool trans_MRS_bank(DisasContext *s, arg_MRS_bank *a)
7319 if (arm_dc_feature(s, ARM_FEATURE_M)) {
7320 return false;
7322 gen_mrs_banked(s, a->r, a->sysm, a->rd);
7323 return true;
7326 static bool trans_MSR_bank(DisasContext *s, arg_MSR_bank *a)
7328 if (arm_dc_feature(s, ARM_FEATURE_M)) {
7329 return false;
7331 gen_msr_banked(s, a->r, a->sysm, a->rn);
7332 return true;
7335 static bool trans_MRS_reg(DisasContext *s, arg_MRS_reg *a)
7337 TCGv_i32 tmp;
7339 if (arm_dc_feature(s, ARM_FEATURE_M)) {
7340 return false;
7342 if (a->r) {
7343 if (IS_USER(s)) {
7344 unallocated_encoding(s);
7345 return true;
7347 tmp = load_cpu_field(spsr);
7348 } else {
7349 tmp = tcg_temp_new_i32();
7350 gen_helper_cpsr_read(tmp, cpu_env);
7352 store_reg(s, a->rd, tmp);
7353 return true;
7356 static bool trans_MSR_reg(DisasContext *s, arg_MSR_reg *a)
7358 TCGv_i32 tmp;
7359 uint32_t mask = msr_mask(s, a->mask, a->r);
7361 if (arm_dc_feature(s, ARM_FEATURE_M)) {
7362 return false;
7364 tmp = load_reg(s, a->rn);
7365 if (gen_set_psr(s, mask, a->r, tmp)) {
7366 unallocated_encoding(s);
7368 return true;
7371 static bool trans_MRS_v7m(DisasContext *s, arg_MRS_v7m *a)
7373 TCGv_i32 tmp;
7375 if (!arm_dc_feature(s, ARM_FEATURE_M)) {
7376 return false;
7378 tmp = tcg_const_i32(a->sysm);
7379 gen_helper_v7m_mrs(tmp, cpu_env, tmp);
7380 store_reg(s, a->rd, tmp);
7381 return true;
7384 static bool trans_MSR_v7m(DisasContext *s, arg_MSR_v7m *a)
7386 TCGv_i32 addr, reg;
7388 if (!arm_dc_feature(s, ARM_FEATURE_M)) {
7389 return false;
7391 addr = tcg_const_i32((a->mask << 10) | a->sysm);
7392 reg = load_reg(s, a->rn);
7393 gen_helper_v7m_msr(cpu_env, addr, reg);
7394 tcg_temp_free_i32(addr);
7395 tcg_temp_free_i32(reg);
7396 /* If we wrote to CONTROL, the EL might have changed */
7397 gen_helper_rebuild_hflags_m32_newel(cpu_env);
7398 gen_lookup_tb(s);
7399 return true;
7402 static bool trans_BX(DisasContext *s, arg_BX *a)
7404 if (!ENABLE_ARCH_4T) {
7405 return false;
7407 gen_bx_excret(s, load_reg(s, a->rm));
7408 return true;
7411 static bool trans_BXJ(DisasContext *s, arg_BXJ *a)
7413 if (!ENABLE_ARCH_5J || arm_dc_feature(s, ARM_FEATURE_M)) {
7414 return false;
7416 /* Trivial implementation equivalent to bx. */
7417 gen_bx(s, load_reg(s, a->rm));
7418 return true;
7421 static bool trans_BLX_r(DisasContext *s, arg_BLX_r *a)
7423 TCGv_i32 tmp;
7425 if (!ENABLE_ARCH_5) {
7426 return false;
7428 tmp = load_reg(s, a->rm);
7429 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
7430 gen_bx(s, tmp);
7431 return true;
7435 * BXNS/BLXNS: only exist for v8M with the security extensions,
7436 * and always UNDEF if NonSecure. We don't implement these in
7437 * the user-only mode either (in theory you can use them from
7438 * Secure User mode but they are too tied in to system emulation).
7440 static bool trans_BXNS(DisasContext *s, arg_BXNS *a)
7442 if (!s->v8m_secure || IS_USER_ONLY) {
7443 unallocated_encoding(s);
7444 } else {
7445 gen_bxns(s, a->rm);
7447 return true;
7450 static bool trans_BLXNS(DisasContext *s, arg_BLXNS *a)
7452 if (!s->v8m_secure || IS_USER_ONLY) {
7453 unallocated_encoding(s);
7454 } else {
7455 gen_blxns(s, a->rm);
7457 return true;
7460 static bool trans_CLZ(DisasContext *s, arg_CLZ *a)
7462 TCGv_i32 tmp;
7464 if (!ENABLE_ARCH_5) {
7465 return false;
7467 tmp = load_reg(s, a->rm);
7468 tcg_gen_clzi_i32(tmp, tmp, 32);
7469 store_reg(s, a->rd, tmp);
7470 return true;
7473 static bool trans_ERET(DisasContext *s, arg_ERET *a)
7475 TCGv_i32 tmp;
7477 if (!arm_dc_feature(s, ARM_FEATURE_V7VE)) {
7478 return false;
7480 if (IS_USER(s)) {
7481 unallocated_encoding(s);
7482 return true;
7484 if (s->current_el == 2) {
7485 /* ERET from Hyp uses ELR_Hyp, not LR */
7486 tmp = load_cpu_field(elr_el[2]);
7487 } else {
7488 tmp = load_reg(s, 14);
7490 gen_exception_return(s, tmp);
7491 return true;
7494 static bool trans_HLT(DisasContext *s, arg_HLT *a)
7496 gen_hlt(s, a->imm);
7497 return true;
7500 static bool trans_BKPT(DisasContext *s, arg_BKPT *a)
7502 if (!ENABLE_ARCH_5) {
7503 return false;
7505 if (arm_dc_feature(s, ARM_FEATURE_M) &&
7506 semihosting_enabled() &&
7507 #ifndef CONFIG_USER_ONLY
7508 !IS_USER(s) &&
7509 #endif
7510 (a->imm == 0xab)) {
7511 gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
7512 } else {
7513 gen_exception_bkpt_insn(s, syn_aa32_bkpt(a->imm, false));
7515 return true;
7518 static bool trans_HVC(DisasContext *s, arg_HVC *a)
7520 if (!ENABLE_ARCH_7 || arm_dc_feature(s, ARM_FEATURE_M)) {
7521 return false;
7523 if (IS_USER(s)) {
7524 unallocated_encoding(s);
7525 } else {
7526 gen_hvc(s, a->imm);
7528 return true;
7531 static bool trans_SMC(DisasContext *s, arg_SMC *a)
7533 if (!ENABLE_ARCH_6K || arm_dc_feature(s, ARM_FEATURE_M)) {
7534 return false;
7536 if (IS_USER(s)) {
7537 unallocated_encoding(s);
7538 } else {
7539 gen_smc(s);
7541 return true;
7544 static bool trans_SG(DisasContext *s, arg_SG *a)
7546 if (!arm_dc_feature(s, ARM_FEATURE_M) ||
7547 !arm_dc_feature(s, ARM_FEATURE_V8)) {
7548 return false;
7551 * SG (v8M only)
7552 * The bulk of the behaviour for this instruction is implemented
7553 * in v7m_handle_execute_nsc(), which deals with the insn when
7554 * it is executed by a CPU in non-secure state from memory
7555 * which is Secure & NonSecure-Callable.
7556 * Here we only need to handle the remaining cases:
7557 * * in NS memory (including the "security extension not
7558 * implemented" case) : NOP
7559 * * in S memory but CPU already secure (clear IT bits)
7560 * We know that the attribute for the memory this insn is
7561 * in must match the current CPU state, because otherwise
7562 * get_phys_addr_pmsav8 would have generated an exception.
7564 if (s->v8m_secure) {
7565 /* Like the IT insn, we don't need to generate any code */
7566 s->condexec_cond = 0;
7567 s->condexec_mask = 0;
7569 return true;
7572 static bool trans_TT(DisasContext *s, arg_TT *a)
7574 TCGv_i32 addr, tmp;
7576 if (!arm_dc_feature(s, ARM_FEATURE_M) ||
7577 !arm_dc_feature(s, ARM_FEATURE_V8)) {
7578 return false;
7580 if (a->rd == 13 || a->rd == 15 || a->rn == 15) {
7581 /* We UNDEF for these UNPREDICTABLE cases */
7582 unallocated_encoding(s);
7583 return true;
7585 if (a->A && !s->v8m_secure) {
7586 /* This case is UNDEFINED. */
7587 unallocated_encoding(s);
7588 return true;
7591 addr = load_reg(s, a->rn);
7592 tmp = tcg_const_i32((a->A << 1) | a->T);
7593 gen_helper_v7m_tt(tmp, cpu_env, addr, tmp);
7594 tcg_temp_free_i32(addr);
7595 store_reg(s, a->rd, tmp);
7596 return true;
7600 * Load/store register index
7603 static ISSInfo make_issinfo(DisasContext *s, int rd, bool p, bool w)
7605 ISSInfo ret;
7607 /* ISS not valid if writeback */
7608 if (p && !w) {
7609 ret = rd;
7610 if (s->base.pc_next - s->pc_curr == 2) {
7611 ret |= ISSIs16Bit;
7613 } else {
7614 ret = ISSInvalid;
7616 return ret;
7619 static TCGv_i32 op_addr_rr_pre(DisasContext *s, arg_ldst_rr *a)
7621 TCGv_i32 addr = load_reg(s, a->rn);
7623 if (s->v8m_stackcheck && a->rn == 13 && a->w) {
7624 gen_helper_v8m_stackcheck(cpu_env, addr);
7627 if (a->p) {
7628 TCGv_i32 ofs = load_reg(s, a->rm);
7629 gen_arm_shift_im(ofs, a->shtype, a->shimm, 0);
7630 if (a->u) {
7631 tcg_gen_add_i32(addr, addr, ofs);
7632 } else {
7633 tcg_gen_sub_i32(addr, addr, ofs);
7635 tcg_temp_free_i32(ofs);
7637 return addr;
7640 static void op_addr_rr_post(DisasContext *s, arg_ldst_rr *a,
7641 TCGv_i32 addr, int address_offset)
7643 if (!a->p) {
7644 TCGv_i32 ofs = load_reg(s, a->rm);
7645 gen_arm_shift_im(ofs, a->shtype, a->shimm, 0);
7646 if (a->u) {
7647 tcg_gen_add_i32(addr, addr, ofs);
7648 } else {
7649 tcg_gen_sub_i32(addr, addr, ofs);
7651 tcg_temp_free_i32(ofs);
7652 } else if (!a->w) {
7653 tcg_temp_free_i32(addr);
7654 return;
7656 tcg_gen_addi_i32(addr, addr, address_offset);
7657 store_reg(s, a->rn, addr);
7660 static bool op_load_rr(DisasContext *s, arg_ldst_rr *a,
7661 MemOp mop, int mem_idx)
7663 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w);
7664 TCGv_i32 addr, tmp;
7666 addr = op_addr_rr_pre(s, a);
7668 tmp = tcg_temp_new_i32();
7669 gen_aa32_ld_i32(s, tmp, addr, mem_idx, mop | s->be_data);
7670 disas_set_da_iss(s, mop, issinfo);
7673 * Perform base writeback before the loaded value to
7674 * ensure correct behavior with overlapping index registers.
7676 op_addr_rr_post(s, a, addr, 0);
7677 store_reg_from_load(s, a->rt, tmp);
7678 return true;
7681 static bool op_store_rr(DisasContext *s, arg_ldst_rr *a,
7682 MemOp mop, int mem_idx)
7684 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w) | ISSIsWrite;
7685 TCGv_i32 addr, tmp;
7687 addr = op_addr_rr_pre(s, a);
7689 tmp = load_reg(s, a->rt);
7690 gen_aa32_st_i32(s, tmp, addr, mem_idx, mop | s->be_data);
7691 disas_set_da_iss(s, mop, issinfo);
7692 tcg_temp_free_i32(tmp);
7694 op_addr_rr_post(s, a, addr, 0);
7695 return true;
7698 static bool trans_LDRD_rr(DisasContext *s, arg_ldst_rr *a)
7700 int mem_idx = get_mem_index(s);
7701 TCGv_i32 addr, tmp;
7703 if (!ENABLE_ARCH_5TE) {
7704 return false;
7706 if (a->rt & 1) {
7707 unallocated_encoding(s);
7708 return true;
7710 addr = op_addr_rr_pre(s, a);
7712 tmp = tcg_temp_new_i32();
7713 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
7714 store_reg(s, a->rt, tmp);
7716 tcg_gen_addi_i32(addr, addr, 4);
7718 tmp = tcg_temp_new_i32();
7719 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
7720 store_reg(s, a->rt + 1, tmp);
7722 /* LDRD w/ base writeback is undefined if the registers overlap. */
7723 op_addr_rr_post(s, a, addr, -4);
7724 return true;
7727 static bool trans_STRD_rr(DisasContext *s, arg_ldst_rr *a)
7729 int mem_idx = get_mem_index(s);
7730 TCGv_i32 addr, tmp;
7732 if (!ENABLE_ARCH_5TE) {
7733 return false;
7735 if (a->rt & 1) {
7736 unallocated_encoding(s);
7737 return true;
7739 addr = op_addr_rr_pre(s, a);
7741 tmp = load_reg(s, a->rt);
7742 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
7743 tcg_temp_free_i32(tmp);
7745 tcg_gen_addi_i32(addr, addr, 4);
7747 tmp = load_reg(s, a->rt + 1);
7748 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
7749 tcg_temp_free_i32(tmp);
7751 op_addr_rr_post(s, a, addr, -4);
7752 return true;
7756 * Load/store immediate index
7759 static TCGv_i32 op_addr_ri_pre(DisasContext *s, arg_ldst_ri *a)
7761 int ofs = a->imm;
7763 if (!a->u) {
7764 ofs = -ofs;
7767 if (s->v8m_stackcheck && a->rn == 13 && a->w) {
7769 * Stackcheck. Here we know 'addr' is the current SP;
7770 * U is set if we're moving SP up, else down. It is
7771 * UNKNOWN whether the limit check triggers when SP starts
7772 * below the limit and ends up above it; we chose to do so.
7774 if (!a->u) {
7775 TCGv_i32 newsp = tcg_temp_new_i32();
7776 tcg_gen_addi_i32(newsp, cpu_R[13], ofs);
7777 gen_helper_v8m_stackcheck(cpu_env, newsp);
7778 tcg_temp_free_i32(newsp);
7779 } else {
7780 gen_helper_v8m_stackcheck(cpu_env, cpu_R[13]);
7784 return add_reg_for_lit(s, a->rn, a->p ? ofs : 0);
7787 static void op_addr_ri_post(DisasContext *s, arg_ldst_ri *a,
7788 TCGv_i32 addr, int address_offset)
7790 if (!a->p) {
7791 if (a->u) {
7792 address_offset += a->imm;
7793 } else {
7794 address_offset -= a->imm;
7796 } else if (!a->w) {
7797 tcg_temp_free_i32(addr);
7798 return;
7800 tcg_gen_addi_i32(addr, addr, address_offset);
7801 store_reg(s, a->rn, addr);
7804 static bool op_load_ri(DisasContext *s, arg_ldst_ri *a,
7805 MemOp mop, int mem_idx)
7807 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w);
7808 TCGv_i32 addr, tmp;
7810 addr = op_addr_ri_pre(s, a);
7812 tmp = tcg_temp_new_i32();
7813 gen_aa32_ld_i32(s, tmp, addr, mem_idx, mop | s->be_data);
7814 disas_set_da_iss(s, mop, issinfo);
7817 * Perform base writeback before the loaded value to
7818 * ensure correct behavior with overlapping index registers.
7820 op_addr_ri_post(s, a, addr, 0);
7821 store_reg_from_load(s, a->rt, tmp);
7822 return true;
7825 static bool op_store_ri(DisasContext *s, arg_ldst_ri *a,
7826 MemOp mop, int mem_idx)
7828 ISSInfo issinfo = make_issinfo(s, a->rt, a->p, a->w) | ISSIsWrite;
7829 TCGv_i32 addr, tmp;
7831 addr = op_addr_ri_pre(s, a);
7833 tmp = load_reg(s, a->rt);
7834 gen_aa32_st_i32(s, tmp, addr, mem_idx, mop | s->be_data);
7835 disas_set_da_iss(s, mop, issinfo);
7836 tcg_temp_free_i32(tmp);
7838 op_addr_ri_post(s, a, addr, 0);
7839 return true;
7842 static bool op_ldrd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
7844 int mem_idx = get_mem_index(s);
7845 TCGv_i32 addr, tmp;
7847 addr = op_addr_ri_pre(s, a);
7849 tmp = tcg_temp_new_i32();
7850 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
7851 store_reg(s, a->rt, tmp);
7853 tcg_gen_addi_i32(addr, addr, 4);
7855 tmp = tcg_temp_new_i32();
7856 gen_aa32_ld_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
7857 store_reg(s, rt2, tmp);
7859 /* LDRD w/ base writeback is undefined if the registers overlap. */
7860 op_addr_ri_post(s, a, addr, -4);
7861 return true;
7864 static bool trans_LDRD_ri_a32(DisasContext *s, arg_ldst_ri *a)
7866 if (!ENABLE_ARCH_5TE || (a->rt & 1)) {
7867 return false;
7869 return op_ldrd_ri(s, a, a->rt + 1);
7872 static bool trans_LDRD_ri_t32(DisasContext *s, arg_ldst_ri2 *a)
7874 arg_ldst_ri b = {
7875 .u = a->u, .w = a->w, .p = a->p,
7876 .rn = a->rn, .rt = a->rt, .imm = a->imm
7878 return op_ldrd_ri(s, &b, a->rt2);
7881 static bool op_strd_ri(DisasContext *s, arg_ldst_ri *a, int rt2)
7883 int mem_idx = get_mem_index(s);
7884 TCGv_i32 addr, tmp;
7886 addr = op_addr_ri_pre(s, a);
7888 tmp = load_reg(s, a->rt);
7889 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
7890 tcg_temp_free_i32(tmp);
7892 tcg_gen_addi_i32(addr, addr, 4);
7894 tmp = load_reg(s, rt2);
7895 gen_aa32_st_i32(s, tmp, addr, mem_idx, MO_UL | s->be_data);
7896 tcg_temp_free_i32(tmp);
7898 op_addr_ri_post(s, a, addr, -4);
7899 return true;
7902 static bool trans_STRD_ri_a32(DisasContext *s, arg_ldst_ri *a)
7904 if (!ENABLE_ARCH_5TE || (a->rt & 1)) {
7905 return false;
7907 return op_strd_ri(s, a, a->rt + 1);
7910 static bool trans_STRD_ri_t32(DisasContext *s, arg_ldst_ri2 *a)
7912 arg_ldst_ri b = {
7913 .u = a->u, .w = a->w, .p = a->p,
7914 .rn = a->rn, .rt = a->rt, .imm = a->imm
7916 return op_strd_ri(s, &b, a->rt2);
7919 #define DO_LDST(NAME, WHICH, MEMOP) \
7920 static bool trans_##NAME##_ri(DisasContext *s, arg_ldst_ri *a) \
7922 return op_##WHICH##_ri(s, a, MEMOP, get_mem_index(s)); \
7924 static bool trans_##NAME##T_ri(DisasContext *s, arg_ldst_ri *a) \
7926 return op_##WHICH##_ri(s, a, MEMOP, get_a32_user_mem_index(s)); \
7928 static bool trans_##NAME##_rr(DisasContext *s, arg_ldst_rr *a) \
7930 return op_##WHICH##_rr(s, a, MEMOP, get_mem_index(s)); \
7932 static bool trans_##NAME##T_rr(DisasContext *s, arg_ldst_rr *a) \
7934 return op_##WHICH##_rr(s, a, MEMOP, get_a32_user_mem_index(s)); \
7937 DO_LDST(LDR, load, MO_UL)
7938 DO_LDST(LDRB, load, MO_UB)
7939 DO_LDST(LDRH, load, MO_UW)
7940 DO_LDST(LDRSB, load, MO_SB)
7941 DO_LDST(LDRSH, load, MO_SW)
7943 DO_LDST(STR, store, MO_UL)
7944 DO_LDST(STRB, store, MO_UB)
7945 DO_LDST(STRH, store, MO_UW)
7947 #undef DO_LDST
7950 * Synchronization primitives
7953 static bool op_swp(DisasContext *s, arg_SWP *a, MemOp opc)
7955 TCGv_i32 addr, tmp;
7956 TCGv taddr;
7958 opc |= s->be_data;
7959 addr = load_reg(s, a->rn);
7960 taddr = gen_aa32_addr(s, addr, opc);
7961 tcg_temp_free_i32(addr);
7963 tmp = load_reg(s, a->rt2);
7964 tcg_gen_atomic_xchg_i32(tmp, taddr, tmp, get_mem_index(s), opc);
7965 tcg_temp_free(taddr);
7967 store_reg(s, a->rt, tmp);
7968 return true;
7971 static bool trans_SWP(DisasContext *s, arg_SWP *a)
7973 return op_swp(s, a, MO_UL | MO_ALIGN);
7976 static bool trans_SWPB(DisasContext *s, arg_SWP *a)
7978 return op_swp(s, a, MO_UB);
7982 * Load/Store Exclusive and Load-Acquire/Store-Release
7985 static bool op_strex(DisasContext *s, arg_STREX *a, MemOp mop, bool rel)
7987 TCGv_i32 addr;
7988 /* Some cases stopped being UNPREDICTABLE in v8A (but not v8M) */
7989 bool v8a = ENABLE_ARCH_8 && !arm_dc_feature(s, ARM_FEATURE_M);
7991 /* We UNDEF for these UNPREDICTABLE cases. */
7992 if (a->rd == 15 || a->rn == 15 || a->rt == 15
7993 || a->rd == a->rn || a->rd == a->rt
7994 || (!v8a && s->thumb && (a->rd == 13 || a->rt == 13))
7995 || (mop == MO_64
7996 && (a->rt2 == 15
7997 || a->rd == a->rt2
7998 || (!v8a && s->thumb && a->rt2 == 13)))) {
7999 unallocated_encoding(s);
8000 return true;
8003 if (rel) {
8004 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
8007 addr = tcg_temp_local_new_i32();
8008 load_reg_var(s, addr, a->rn);
8009 tcg_gen_addi_i32(addr, addr, a->imm);
8011 gen_store_exclusive(s, a->rd, a->rt, a->rt2, addr, mop);
8012 tcg_temp_free_i32(addr);
8013 return true;
8016 static bool trans_STREX(DisasContext *s, arg_STREX *a)
8018 if (!ENABLE_ARCH_6) {
8019 return false;
8021 return op_strex(s, a, MO_32, false);
8024 static bool trans_STREXD_a32(DisasContext *s, arg_STREX *a)
8026 if (!ENABLE_ARCH_6K) {
8027 return false;
8029 /* We UNDEF for these UNPREDICTABLE cases. */
8030 if (a->rt & 1) {
8031 unallocated_encoding(s);
8032 return true;
8034 a->rt2 = a->rt + 1;
8035 return op_strex(s, a, MO_64, false);
8038 static bool trans_STREXD_t32(DisasContext *s, arg_STREX *a)
8040 return op_strex(s, a, MO_64, false);
8043 static bool trans_STREXB(DisasContext *s, arg_STREX *a)
8045 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
8046 return false;
8048 return op_strex(s, a, MO_8, false);
8051 static bool trans_STREXH(DisasContext *s, arg_STREX *a)
8053 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
8054 return false;
8056 return op_strex(s, a, MO_16, false);
8059 static bool trans_STLEX(DisasContext *s, arg_STREX *a)
8061 if (!ENABLE_ARCH_8) {
8062 return false;
8064 return op_strex(s, a, MO_32, true);
8067 static bool trans_STLEXD_a32(DisasContext *s, arg_STREX *a)
8069 if (!ENABLE_ARCH_8) {
8070 return false;
8072 /* We UNDEF for these UNPREDICTABLE cases. */
8073 if (a->rt & 1) {
8074 unallocated_encoding(s);
8075 return true;
8077 a->rt2 = a->rt + 1;
8078 return op_strex(s, a, MO_64, true);
8081 static bool trans_STLEXD_t32(DisasContext *s, arg_STREX *a)
8083 if (!ENABLE_ARCH_8) {
8084 return false;
8086 return op_strex(s, a, MO_64, true);
8089 static bool trans_STLEXB(DisasContext *s, arg_STREX *a)
8091 if (!ENABLE_ARCH_8) {
8092 return false;
8094 return op_strex(s, a, MO_8, true);
8097 static bool trans_STLEXH(DisasContext *s, arg_STREX *a)
8099 if (!ENABLE_ARCH_8) {
8100 return false;
8102 return op_strex(s, a, MO_16, true);
8105 static bool op_stl(DisasContext *s, arg_STL *a, MemOp mop)
8107 TCGv_i32 addr, tmp;
8109 if (!ENABLE_ARCH_8) {
8110 return false;
8112 /* We UNDEF for these UNPREDICTABLE cases. */
8113 if (a->rn == 15 || a->rt == 15) {
8114 unallocated_encoding(s);
8115 return true;
8118 addr = load_reg(s, a->rn);
8119 tmp = load_reg(s, a->rt);
8120 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
8121 gen_aa32_st_i32(s, tmp, addr, get_mem_index(s), mop | s->be_data);
8122 disas_set_da_iss(s, mop, a->rt | ISSIsAcqRel | ISSIsWrite);
8124 tcg_temp_free_i32(tmp);
8125 tcg_temp_free_i32(addr);
8126 return true;
8129 static bool trans_STL(DisasContext *s, arg_STL *a)
8131 return op_stl(s, a, MO_UL);
8134 static bool trans_STLB(DisasContext *s, arg_STL *a)
8136 return op_stl(s, a, MO_UB);
8139 static bool trans_STLH(DisasContext *s, arg_STL *a)
8141 return op_stl(s, a, MO_UW);
8144 static bool op_ldrex(DisasContext *s, arg_LDREX *a, MemOp mop, bool acq)
8146 TCGv_i32 addr;
8147 /* Some cases stopped being UNPREDICTABLE in v8A (but not v8M) */
8148 bool v8a = ENABLE_ARCH_8 && !arm_dc_feature(s, ARM_FEATURE_M);
8150 /* We UNDEF for these UNPREDICTABLE cases. */
8151 if (a->rn == 15 || a->rt == 15
8152 || (!v8a && s->thumb && a->rt == 13)
8153 || (mop == MO_64
8154 && (a->rt2 == 15 || a->rt == a->rt2
8155 || (!v8a && s->thumb && a->rt2 == 13)))) {
8156 unallocated_encoding(s);
8157 return true;
8160 addr = tcg_temp_local_new_i32();
8161 load_reg_var(s, addr, a->rn);
8162 tcg_gen_addi_i32(addr, addr, a->imm);
8164 gen_load_exclusive(s, a->rt, a->rt2, addr, mop);
8165 tcg_temp_free_i32(addr);
8167 if (acq) {
8168 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
8170 return true;
8173 static bool trans_LDREX(DisasContext *s, arg_LDREX *a)
8175 if (!ENABLE_ARCH_6) {
8176 return false;
8178 return op_ldrex(s, a, MO_32, false);
8181 static bool trans_LDREXD_a32(DisasContext *s, arg_LDREX *a)
8183 if (!ENABLE_ARCH_6K) {
8184 return false;
8186 /* We UNDEF for these UNPREDICTABLE cases. */
8187 if (a->rt & 1) {
8188 unallocated_encoding(s);
8189 return true;
8191 a->rt2 = a->rt + 1;
8192 return op_ldrex(s, a, MO_64, false);
8195 static bool trans_LDREXD_t32(DisasContext *s, arg_LDREX *a)
8197 return op_ldrex(s, a, MO_64, false);
8200 static bool trans_LDREXB(DisasContext *s, arg_LDREX *a)
8202 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
8203 return false;
8205 return op_ldrex(s, a, MO_8, false);
8208 static bool trans_LDREXH(DisasContext *s, arg_LDREX *a)
8210 if (s->thumb ? !ENABLE_ARCH_7 : !ENABLE_ARCH_6K) {
8211 return false;
8213 return op_ldrex(s, a, MO_16, false);
8216 static bool trans_LDAEX(DisasContext *s, arg_LDREX *a)
8218 if (!ENABLE_ARCH_8) {
8219 return false;
8221 return op_ldrex(s, a, MO_32, true);
8224 static bool trans_LDAEXD_a32(DisasContext *s, arg_LDREX *a)
8226 if (!ENABLE_ARCH_8) {
8227 return false;
8229 /* We UNDEF for these UNPREDICTABLE cases. */
8230 if (a->rt & 1) {
8231 unallocated_encoding(s);
8232 return true;
8234 a->rt2 = a->rt + 1;
8235 return op_ldrex(s, a, MO_64, true);
8238 static bool trans_LDAEXD_t32(DisasContext *s, arg_LDREX *a)
8240 if (!ENABLE_ARCH_8) {
8241 return false;
8243 return op_ldrex(s, a, MO_64, true);
8246 static bool trans_LDAEXB(DisasContext *s, arg_LDREX *a)
8248 if (!ENABLE_ARCH_8) {
8249 return false;
8251 return op_ldrex(s, a, MO_8, true);
8254 static bool trans_LDAEXH(DisasContext *s, arg_LDREX *a)
8256 if (!ENABLE_ARCH_8) {
8257 return false;
8259 return op_ldrex(s, a, MO_16, true);
8262 static bool op_lda(DisasContext *s, arg_LDA *a, MemOp mop)
8264 TCGv_i32 addr, tmp;
8266 if (!ENABLE_ARCH_8) {
8267 return false;
8269 /* We UNDEF for these UNPREDICTABLE cases. */
8270 if (a->rn == 15 || a->rt == 15) {
8271 unallocated_encoding(s);
8272 return true;
8275 addr = load_reg(s, a->rn);
8276 tmp = tcg_temp_new_i32();
8277 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), mop | s->be_data);
8278 disas_set_da_iss(s, mop, a->rt | ISSIsAcqRel);
8279 tcg_temp_free_i32(addr);
8281 store_reg(s, a->rt, tmp);
8282 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
8283 return true;
8286 static bool trans_LDA(DisasContext *s, arg_LDA *a)
8288 return op_lda(s, a, MO_UL);
8291 static bool trans_LDAB(DisasContext *s, arg_LDA *a)
8293 return op_lda(s, a, MO_UB);
8296 static bool trans_LDAH(DisasContext *s, arg_LDA *a)
8298 return op_lda(s, a, MO_UW);
8302 * Media instructions
8305 static bool trans_USADA8(DisasContext *s, arg_USADA8 *a)
8307 TCGv_i32 t1, t2;
8309 if (!ENABLE_ARCH_6) {
8310 return false;
8313 t1 = load_reg(s, a->rn);
8314 t2 = load_reg(s, a->rm);
8315 gen_helper_usad8(t1, t1, t2);
8316 tcg_temp_free_i32(t2);
8317 if (a->ra != 15) {
8318 t2 = load_reg(s, a->ra);
8319 tcg_gen_add_i32(t1, t1, t2);
8320 tcg_temp_free_i32(t2);
8322 store_reg(s, a->rd, t1);
8323 return true;
8326 static bool op_bfx(DisasContext *s, arg_UBFX *a, bool u)
8328 TCGv_i32 tmp;
8329 int width = a->widthm1 + 1;
8330 int shift = a->lsb;
8332 if (!ENABLE_ARCH_6T2) {
8333 return false;
8335 if (shift + width > 32) {
8336 /* UNPREDICTABLE; we choose to UNDEF */
8337 unallocated_encoding(s);
8338 return true;
8341 tmp = load_reg(s, a->rn);
8342 if (u) {
8343 tcg_gen_extract_i32(tmp, tmp, shift, width);
8344 } else {
8345 tcg_gen_sextract_i32(tmp, tmp, shift, width);
8347 store_reg(s, a->rd, tmp);
8348 return true;
8351 static bool trans_SBFX(DisasContext *s, arg_SBFX *a)
8353 return op_bfx(s, a, false);
8356 static bool trans_UBFX(DisasContext *s, arg_UBFX *a)
8358 return op_bfx(s, a, true);
8361 static bool trans_BFCI(DisasContext *s, arg_BFCI *a)
8363 TCGv_i32 tmp;
8364 int msb = a->msb, lsb = a->lsb;
8365 int width;
8367 if (!ENABLE_ARCH_6T2) {
8368 return false;
8370 if (msb < lsb) {
8371 /* UNPREDICTABLE; we choose to UNDEF */
8372 unallocated_encoding(s);
8373 return true;
8376 width = msb + 1 - lsb;
8377 if (a->rn == 15) {
8378 /* BFC */
8379 tmp = tcg_const_i32(0);
8380 } else {
8381 /* BFI */
8382 tmp = load_reg(s, a->rn);
8384 if (width != 32) {
8385 TCGv_i32 tmp2 = load_reg(s, a->rd);
8386 tcg_gen_deposit_i32(tmp, tmp2, tmp, lsb, width);
8387 tcg_temp_free_i32(tmp2);
8389 store_reg(s, a->rd, tmp);
8390 return true;
8393 static bool trans_UDF(DisasContext *s, arg_UDF *a)
8395 unallocated_encoding(s);
8396 return true;
8400 * Parallel addition and subtraction
8403 static bool op_par_addsub(DisasContext *s, arg_rrr *a,
8404 void (*gen)(TCGv_i32, TCGv_i32, TCGv_i32))
8406 TCGv_i32 t0, t1;
8408 if (s->thumb
8409 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
8410 : !ENABLE_ARCH_6) {
8411 return false;
8414 t0 = load_reg(s, a->rn);
8415 t1 = load_reg(s, a->rm);
8417 gen(t0, t0, t1);
8419 tcg_temp_free_i32(t1);
8420 store_reg(s, a->rd, t0);
8421 return true;
8424 static bool op_par_addsub_ge(DisasContext *s, arg_rrr *a,
8425 void (*gen)(TCGv_i32, TCGv_i32,
8426 TCGv_i32, TCGv_ptr))
8428 TCGv_i32 t0, t1;
8429 TCGv_ptr ge;
8431 if (s->thumb
8432 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
8433 : !ENABLE_ARCH_6) {
8434 return false;
8437 t0 = load_reg(s, a->rn);
8438 t1 = load_reg(s, a->rm);
8440 ge = tcg_temp_new_ptr();
8441 tcg_gen_addi_ptr(ge, cpu_env, offsetof(CPUARMState, GE));
8442 gen(t0, t0, t1, ge);
8444 tcg_temp_free_ptr(ge);
8445 tcg_temp_free_i32(t1);
8446 store_reg(s, a->rd, t0);
8447 return true;
8450 #define DO_PAR_ADDSUB(NAME, helper) \
8451 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
8453 return op_par_addsub(s, a, helper); \
8456 #define DO_PAR_ADDSUB_GE(NAME, helper) \
8457 static bool trans_##NAME(DisasContext *s, arg_rrr *a) \
8459 return op_par_addsub_ge(s, a, helper); \
8462 DO_PAR_ADDSUB_GE(SADD16, gen_helper_sadd16)
8463 DO_PAR_ADDSUB_GE(SASX, gen_helper_saddsubx)
8464 DO_PAR_ADDSUB_GE(SSAX, gen_helper_ssubaddx)
8465 DO_PAR_ADDSUB_GE(SSUB16, gen_helper_ssub16)
8466 DO_PAR_ADDSUB_GE(SADD8, gen_helper_sadd8)
8467 DO_PAR_ADDSUB_GE(SSUB8, gen_helper_ssub8)
8469 DO_PAR_ADDSUB_GE(UADD16, gen_helper_uadd16)
8470 DO_PAR_ADDSUB_GE(UASX, gen_helper_uaddsubx)
8471 DO_PAR_ADDSUB_GE(USAX, gen_helper_usubaddx)
8472 DO_PAR_ADDSUB_GE(USUB16, gen_helper_usub16)
8473 DO_PAR_ADDSUB_GE(UADD8, gen_helper_uadd8)
8474 DO_PAR_ADDSUB_GE(USUB8, gen_helper_usub8)
8476 DO_PAR_ADDSUB(QADD16, gen_helper_qadd16)
8477 DO_PAR_ADDSUB(QASX, gen_helper_qaddsubx)
8478 DO_PAR_ADDSUB(QSAX, gen_helper_qsubaddx)
8479 DO_PAR_ADDSUB(QSUB16, gen_helper_qsub16)
8480 DO_PAR_ADDSUB(QADD8, gen_helper_qadd8)
8481 DO_PAR_ADDSUB(QSUB8, gen_helper_qsub8)
8483 DO_PAR_ADDSUB(UQADD16, gen_helper_uqadd16)
8484 DO_PAR_ADDSUB(UQASX, gen_helper_uqaddsubx)
8485 DO_PAR_ADDSUB(UQSAX, gen_helper_uqsubaddx)
8486 DO_PAR_ADDSUB(UQSUB16, gen_helper_uqsub16)
8487 DO_PAR_ADDSUB(UQADD8, gen_helper_uqadd8)
8488 DO_PAR_ADDSUB(UQSUB8, gen_helper_uqsub8)
8490 DO_PAR_ADDSUB(SHADD16, gen_helper_shadd16)
8491 DO_PAR_ADDSUB(SHASX, gen_helper_shaddsubx)
8492 DO_PAR_ADDSUB(SHSAX, gen_helper_shsubaddx)
8493 DO_PAR_ADDSUB(SHSUB16, gen_helper_shsub16)
8494 DO_PAR_ADDSUB(SHADD8, gen_helper_shadd8)
8495 DO_PAR_ADDSUB(SHSUB8, gen_helper_shsub8)
8497 DO_PAR_ADDSUB(UHADD16, gen_helper_uhadd16)
8498 DO_PAR_ADDSUB(UHASX, gen_helper_uhaddsubx)
8499 DO_PAR_ADDSUB(UHSAX, gen_helper_uhsubaddx)
8500 DO_PAR_ADDSUB(UHSUB16, gen_helper_uhsub16)
8501 DO_PAR_ADDSUB(UHADD8, gen_helper_uhadd8)
8502 DO_PAR_ADDSUB(UHSUB8, gen_helper_uhsub8)
8504 #undef DO_PAR_ADDSUB
8505 #undef DO_PAR_ADDSUB_GE
8508 * Packing, unpacking, saturation, and reversal
8511 static bool trans_PKH(DisasContext *s, arg_PKH *a)
8513 TCGv_i32 tn, tm;
8514 int shift = a->imm;
8516 if (s->thumb
8517 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
8518 : !ENABLE_ARCH_6) {
8519 return false;
8522 tn = load_reg(s, a->rn);
8523 tm = load_reg(s, a->rm);
8524 if (a->tb) {
8525 /* PKHTB */
8526 if (shift == 0) {
8527 shift = 31;
8529 tcg_gen_sari_i32(tm, tm, shift);
8530 tcg_gen_deposit_i32(tn, tn, tm, 0, 16);
8531 } else {
8532 /* PKHBT */
8533 tcg_gen_shli_i32(tm, tm, shift);
8534 tcg_gen_deposit_i32(tn, tm, tn, 0, 16);
8536 tcg_temp_free_i32(tm);
8537 store_reg(s, a->rd, tn);
8538 return true;
8541 static bool op_sat(DisasContext *s, arg_sat *a,
8542 void (*gen)(TCGv_i32, TCGv_env, TCGv_i32, TCGv_i32))
8544 TCGv_i32 tmp, satimm;
8545 int shift = a->imm;
8547 if (!ENABLE_ARCH_6) {
8548 return false;
8551 tmp = load_reg(s, a->rn);
8552 if (a->sh) {
8553 tcg_gen_sari_i32(tmp, tmp, shift ? shift : 31);
8554 } else {
8555 tcg_gen_shli_i32(tmp, tmp, shift);
8558 satimm = tcg_const_i32(a->satimm);
8559 gen(tmp, cpu_env, tmp, satimm);
8560 tcg_temp_free_i32(satimm);
8562 store_reg(s, a->rd, tmp);
8563 return true;
8566 static bool trans_SSAT(DisasContext *s, arg_sat *a)
8568 return op_sat(s, a, gen_helper_ssat);
8571 static bool trans_USAT(DisasContext *s, arg_sat *a)
8573 return op_sat(s, a, gen_helper_usat);
8576 static bool trans_SSAT16(DisasContext *s, arg_sat *a)
8578 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
8579 return false;
8581 return op_sat(s, a, gen_helper_ssat16);
8584 static bool trans_USAT16(DisasContext *s, arg_sat *a)
8586 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
8587 return false;
8589 return op_sat(s, a, gen_helper_usat16);
8592 static bool op_xta(DisasContext *s, arg_rrr_rot *a,
8593 void (*gen_extract)(TCGv_i32, TCGv_i32),
8594 void (*gen_add)(TCGv_i32, TCGv_i32, TCGv_i32))
8596 TCGv_i32 tmp;
8598 if (!ENABLE_ARCH_6) {
8599 return false;
8602 tmp = load_reg(s, a->rm);
8604 * TODO: In many cases we could do a shift instead of a rotate.
8605 * Combined with a simple extend, that becomes an extract.
8607 tcg_gen_rotri_i32(tmp, tmp, a->rot * 8);
8608 gen_extract(tmp, tmp);
8610 if (a->rn != 15) {
8611 TCGv_i32 tmp2 = load_reg(s, a->rn);
8612 gen_add(tmp, tmp, tmp2);
8613 tcg_temp_free_i32(tmp2);
8615 store_reg(s, a->rd, tmp);
8616 return true;
8619 static bool trans_SXTAB(DisasContext *s, arg_rrr_rot *a)
8621 return op_xta(s, a, tcg_gen_ext8s_i32, tcg_gen_add_i32);
8624 static bool trans_SXTAH(DisasContext *s, arg_rrr_rot *a)
8626 return op_xta(s, a, tcg_gen_ext16s_i32, tcg_gen_add_i32);
8629 static bool trans_SXTAB16(DisasContext *s, arg_rrr_rot *a)
8631 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
8632 return false;
8634 return op_xta(s, a, gen_helper_sxtb16, gen_add16);
8637 static bool trans_UXTAB(DisasContext *s, arg_rrr_rot *a)
8639 return op_xta(s, a, tcg_gen_ext8u_i32, tcg_gen_add_i32);
8642 static bool trans_UXTAH(DisasContext *s, arg_rrr_rot *a)
8644 return op_xta(s, a, tcg_gen_ext16u_i32, tcg_gen_add_i32);
8647 static bool trans_UXTAB16(DisasContext *s, arg_rrr_rot *a)
8649 if (s->thumb && !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
8650 return false;
8652 return op_xta(s, a, gen_helper_uxtb16, gen_add16);
8655 static bool trans_SEL(DisasContext *s, arg_rrr *a)
8657 TCGv_i32 t1, t2, t3;
8659 if (s->thumb
8660 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
8661 : !ENABLE_ARCH_6) {
8662 return false;
8665 t1 = load_reg(s, a->rn);
8666 t2 = load_reg(s, a->rm);
8667 t3 = tcg_temp_new_i32();
8668 tcg_gen_ld_i32(t3, cpu_env, offsetof(CPUARMState, GE));
8669 gen_helper_sel_flags(t1, t3, t1, t2);
8670 tcg_temp_free_i32(t3);
8671 tcg_temp_free_i32(t2);
8672 store_reg(s, a->rd, t1);
8673 return true;
8676 static bool op_rr(DisasContext *s, arg_rr *a,
8677 void (*gen)(TCGv_i32, TCGv_i32))
8679 TCGv_i32 tmp;
8681 tmp = load_reg(s, a->rm);
8682 gen(tmp, tmp);
8683 store_reg(s, a->rd, tmp);
8684 return true;
8687 static bool trans_REV(DisasContext *s, arg_rr *a)
8689 if (!ENABLE_ARCH_6) {
8690 return false;
8692 return op_rr(s, a, tcg_gen_bswap32_i32);
8695 static bool trans_REV16(DisasContext *s, arg_rr *a)
8697 if (!ENABLE_ARCH_6) {
8698 return false;
8700 return op_rr(s, a, gen_rev16);
8703 static bool trans_REVSH(DisasContext *s, arg_rr *a)
8705 if (!ENABLE_ARCH_6) {
8706 return false;
8708 return op_rr(s, a, gen_revsh);
8711 static bool trans_RBIT(DisasContext *s, arg_rr *a)
8713 if (!ENABLE_ARCH_6T2) {
8714 return false;
8716 return op_rr(s, a, gen_helper_rbit);
8720 * Signed multiply, signed and unsigned divide
8723 static bool op_smlad(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
8725 TCGv_i32 t1, t2;
8727 if (!ENABLE_ARCH_6) {
8728 return false;
8731 t1 = load_reg(s, a->rn);
8732 t2 = load_reg(s, a->rm);
8733 if (m_swap) {
8734 gen_swap_half(t2);
8736 gen_smul_dual(t1, t2);
8738 if (sub) {
8739 /* This subtraction cannot overflow. */
8740 tcg_gen_sub_i32(t1, t1, t2);
8741 } else {
8743 * This addition cannot overflow 32 bits; however it may
8744 * overflow considered as a signed operation, in which case
8745 * we must set the Q flag.
8747 gen_helper_add_setq(t1, cpu_env, t1, t2);
8749 tcg_temp_free_i32(t2);
8751 if (a->ra != 15) {
8752 t2 = load_reg(s, a->ra);
8753 gen_helper_add_setq(t1, cpu_env, t1, t2);
8754 tcg_temp_free_i32(t2);
8756 store_reg(s, a->rd, t1);
8757 return true;
8760 static bool trans_SMLAD(DisasContext *s, arg_rrrr *a)
8762 return op_smlad(s, a, false, false);
8765 static bool trans_SMLADX(DisasContext *s, arg_rrrr *a)
8767 return op_smlad(s, a, true, false);
8770 static bool trans_SMLSD(DisasContext *s, arg_rrrr *a)
8772 return op_smlad(s, a, false, true);
8775 static bool trans_SMLSDX(DisasContext *s, arg_rrrr *a)
8777 return op_smlad(s, a, true, true);
8780 static bool op_smlald(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
8782 TCGv_i32 t1, t2;
8783 TCGv_i64 l1, l2;
8785 if (!ENABLE_ARCH_6) {
8786 return false;
8789 t1 = load_reg(s, a->rn);
8790 t2 = load_reg(s, a->rm);
8791 if (m_swap) {
8792 gen_swap_half(t2);
8794 gen_smul_dual(t1, t2);
8796 l1 = tcg_temp_new_i64();
8797 l2 = tcg_temp_new_i64();
8798 tcg_gen_ext_i32_i64(l1, t1);
8799 tcg_gen_ext_i32_i64(l2, t2);
8800 tcg_temp_free_i32(t1);
8801 tcg_temp_free_i32(t2);
8803 if (sub) {
8804 tcg_gen_sub_i64(l1, l1, l2);
8805 } else {
8806 tcg_gen_add_i64(l1, l1, l2);
8808 tcg_temp_free_i64(l2);
8810 gen_addq(s, l1, a->ra, a->rd);
8811 gen_storeq_reg(s, a->ra, a->rd, l1);
8812 tcg_temp_free_i64(l1);
8813 return true;
8816 static bool trans_SMLALD(DisasContext *s, arg_rrrr *a)
8818 return op_smlald(s, a, false, false);
8821 static bool trans_SMLALDX(DisasContext *s, arg_rrrr *a)
8823 return op_smlald(s, a, true, false);
8826 static bool trans_SMLSLD(DisasContext *s, arg_rrrr *a)
8828 return op_smlald(s, a, false, true);
8831 static bool trans_SMLSLDX(DisasContext *s, arg_rrrr *a)
8833 return op_smlald(s, a, true, true);
8836 static bool op_smmla(DisasContext *s, arg_rrrr *a, bool round, bool sub)
8838 TCGv_i32 t1, t2;
8840 if (s->thumb
8841 ? !arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)
8842 : !ENABLE_ARCH_6) {
8843 return false;
8846 t1 = load_reg(s, a->rn);
8847 t2 = load_reg(s, a->rm);
8848 tcg_gen_muls2_i32(t2, t1, t1, t2);
8850 if (a->ra != 15) {
8851 TCGv_i32 t3 = load_reg(s, a->ra);
8852 if (sub) {
8854 * For SMMLS, we need a 64-bit subtract. Borrow caused by
8855 * a non-zero multiplicand lowpart, and the correct result
8856 * lowpart for rounding.
8858 TCGv_i32 zero = tcg_const_i32(0);
8859 tcg_gen_sub2_i32(t2, t1, zero, t3, t2, t1);
8860 tcg_temp_free_i32(zero);
8861 } else {
8862 tcg_gen_add_i32(t1, t1, t3);
8864 tcg_temp_free_i32(t3);
8866 if (round) {
8868 * Adding 0x80000000 to the 64-bit quantity means that we have
8869 * carry in to the high word when the low word has the msb set.
8871 tcg_gen_shri_i32(t2, t2, 31);
8872 tcg_gen_add_i32(t1, t1, t2);
8874 tcg_temp_free_i32(t2);
8875 store_reg(s, a->rd, t1);
8876 return true;
8879 static bool trans_SMMLA(DisasContext *s, arg_rrrr *a)
8881 return op_smmla(s, a, false, false);
8884 static bool trans_SMMLAR(DisasContext *s, arg_rrrr *a)
8886 return op_smmla(s, a, true, false);
8889 static bool trans_SMMLS(DisasContext *s, arg_rrrr *a)
8891 return op_smmla(s, a, false, true);
8894 static bool trans_SMMLSR(DisasContext *s, arg_rrrr *a)
8896 return op_smmla(s, a, true, true);
8899 static bool op_div(DisasContext *s, arg_rrr *a, bool u)
8901 TCGv_i32 t1, t2;
8903 if (s->thumb
8904 ? !dc_isar_feature(aa32_thumb_div, s)
8905 : !dc_isar_feature(aa32_arm_div, s)) {
8906 return false;
8909 t1 = load_reg(s, a->rn);
8910 t2 = load_reg(s, a->rm);
8911 if (u) {
8912 gen_helper_udiv(t1, t1, t2);
8913 } else {
8914 gen_helper_sdiv(t1, t1, t2);
8916 tcg_temp_free_i32(t2);
8917 store_reg(s, a->rd, t1);
8918 return true;
8921 static bool trans_SDIV(DisasContext *s, arg_rrr *a)
8923 return op_div(s, a, false);
8926 static bool trans_UDIV(DisasContext *s, arg_rrr *a)
8928 return op_div(s, a, true);
8932 * Block data transfer
8935 static TCGv_i32 op_addr_block_pre(DisasContext *s, arg_ldst_block *a, int n)
8937 TCGv_i32 addr = load_reg(s, a->rn);
8939 if (a->b) {
8940 if (a->i) {
8941 /* pre increment */
8942 tcg_gen_addi_i32(addr, addr, 4);
8943 } else {
8944 /* pre decrement */
8945 tcg_gen_addi_i32(addr, addr, -(n * 4));
8947 } else if (!a->i && n != 1) {
8948 /* post decrement */
8949 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
8952 if (s->v8m_stackcheck && a->rn == 13 && a->w) {
8954 * If the writeback is incrementing SP rather than
8955 * decrementing it, and the initial SP is below the
8956 * stack limit but the final written-back SP would
8957 * be above, then then we must not perform any memory
8958 * accesses, but it is IMPDEF whether we generate
8959 * an exception. We choose to do so in this case.
8960 * At this point 'addr' is the lowest address, so
8961 * either the original SP (if incrementing) or our
8962 * final SP (if decrementing), so that's what we check.
8964 gen_helper_v8m_stackcheck(cpu_env, addr);
8967 return addr;
8970 static void op_addr_block_post(DisasContext *s, arg_ldst_block *a,
8971 TCGv_i32 addr, int n)
8973 if (a->w) {
8974 /* write back */
8975 if (!a->b) {
8976 if (a->i) {
8977 /* post increment */
8978 tcg_gen_addi_i32(addr, addr, 4);
8979 } else {
8980 /* post decrement */
8981 tcg_gen_addi_i32(addr, addr, -(n * 4));
8983 } else if (!a->i && n != 1) {
8984 /* pre decrement */
8985 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
8987 store_reg(s, a->rn, addr);
8988 } else {
8989 tcg_temp_free_i32(addr);
8993 static bool op_stm(DisasContext *s, arg_ldst_block *a, int min_n)
8995 int i, j, n, list, mem_idx;
8996 bool user = a->u;
8997 TCGv_i32 addr, tmp, tmp2;
8999 if (user) {
9000 /* STM (user) */
9001 if (IS_USER(s)) {
9002 /* Only usable in supervisor mode. */
9003 unallocated_encoding(s);
9004 return true;
9008 list = a->list;
9009 n = ctpop16(list);
9010 if (n < min_n || a->rn == 15) {
9011 unallocated_encoding(s);
9012 return true;
9015 addr = op_addr_block_pre(s, a, n);
9016 mem_idx = get_mem_index(s);
9018 for (i = j = 0; i < 16; i++) {
9019 if (!(list & (1 << i))) {
9020 continue;
9023 if (user && i != 15) {
9024 tmp = tcg_temp_new_i32();
9025 tmp2 = tcg_const_i32(i);
9026 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
9027 tcg_temp_free_i32(tmp2);
9028 } else {
9029 tmp = load_reg(s, i);
9031 gen_aa32_st32(s, tmp, addr, mem_idx);
9032 tcg_temp_free_i32(tmp);
9034 /* No need to add after the last transfer. */
9035 if (++j != n) {
9036 tcg_gen_addi_i32(addr, addr, 4);
9040 op_addr_block_post(s, a, addr, n);
9041 return true;
9044 static bool trans_STM(DisasContext *s, arg_ldst_block *a)
9046 /* BitCount(list) < 1 is UNPREDICTABLE */
9047 return op_stm(s, a, 1);
9050 static bool trans_STM_t32(DisasContext *s, arg_ldst_block *a)
9052 /* Writeback register in register list is UNPREDICTABLE for T32. */
9053 if (a->w && (a->list & (1 << a->rn))) {
9054 unallocated_encoding(s);
9055 return true;
9057 /* BitCount(list) < 2 is UNPREDICTABLE */
9058 return op_stm(s, a, 2);
9061 static bool do_ldm(DisasContext *s, arg_ldst_block *a, int min_n)
9063 int i, j, n, list, mem_idx;
9064 bool loaded_base;
9065 bool user = a->u;
9066 bool exc_return = false;
9067 TCGv_i32 addr, tmp, tmp2, loaded_var;
9069 if (user) {
9070 /* LDM (user), LDM (exception return) */
9071 if (IS_USER(s)) {
9072 /* Only usable in supervisor mode. */
9073 unallocated_encoding(s);
9074 return true;
9076 if (extract32(a->list, 15, 1)) {
9077 exc_return = true;
9078 user = false;
9079 } else {
9080 /* LDM (user) does not allow writeback. */
9081 if (a->w) {
9082 unallocated_encoding(s);
9083 return true;
9088 list = a->list;
9089 n = ctpop16(list);
9090 if (n < min_n || a->rn == 15) {
9091 unallocated_encoding(s);
9092 return true;
9095 addr = op_addr_block_pre(s, a, n);
9096 mem_idx = get_mem_index(s);
9097 loaded_base = false;
9098 loaded_var = NULL;
9100 for (i = j = 0; i < 16; i++) {
9101 if (!(list & (1 << i))) {
9102 continue;
9105 tmp = tcg_temp_new_i32();
9106 gen_aa32_ld32u(s, tmp, addr, mem_idx);
9107 if (user) {
9108 tmp2 = tcg_const_i32(i);
9109 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
9110 tcg_temp_free_i32(tmp2);
9111 tcg_temp_free_i32(tmp);
9112 } else if (i == a->rn) {
9113 loaded_var = tmp;
9114 loaded_base = true;
9115 } else if (i == 15 && exc_return) {
9116 store_pc_exc_ret(s, tmp);
9117 } else {
9118 store_reg_from_load(s, i, tmp);
9121 /* No need to add after the last transfer. */
9122 if (++j != n) {
9123 tcg_gen_addi_i32(addr, addr, 4);
9127 op_addr_block_post(s, a, addr, n);
9129 if (loaded_base) {
9130 /* Note that we reject base == pc above. */
9131 store_reg(s, a->rn, loaded_var);
9134 if (exc_return) {
9135 /* Restore CPSR from SPSR. */
9136 tmp = load_cpu_field(spsr);
9137 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
9138 gen_io_start();
9140 gen_helper_cpsr_write_eret(cpu_env, tmp);
9141 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
9142 gen_io_end();
9144 tcg_temp_free_i32(tmp);
9145 /* Must exit loop to check un-masked IRQs */
9146 s->base.is_jmp = DISAS_EXIT;
9148 return true;
9151 static bool trans_LDM_a32(DisasContext *s, arg_ldst_block *a)
9154 * Writeback register in register list is UNPREDICTABLE
9155 * for ArchVersion() >= 7. Prior to v7, A32 would write
9156 * an UNKNOWN value to the base register.
9158 if (ENABLE_ARCH_7 && a->w && (a->list & (1 << a->rn))) {
9159 unallocated_encoding(s);
9160 return true;
9162 /* BitCount(list) < 1 is UNPREDICTABLE */
9163 return do_ldm(s, a, 1);
9166 static bool trans_LDM_t32(DisasContext *s, arg_ldst_block *a)
9168 /* Writeback register in register list is UNPREDICTABLE for T32. */
9169 if (a->w && (a->list & (1 << a->rn))) {
9170 unallocated_encoding(s);
9171 return true;
9173 /* BitCount(list) < 2 is UNPREDICTABLE */
9174 return do_ldm(s, a, 2);
9177 static bool trans_LDM_t16(DisasContext *s, arg_ldst_block *a)
9179 /* Writeback is conditional on the base register not being loaded. */
9180 a->w = !(a->list & (1 << a->rn));
9181 /* BitCount(list) < 1 is UNPREDICTABLE */
9182 return do_ldm(s, a, 1);
9186 * Branch, branch with link
9189 static bool trans_B(DisasContext *s, arg_i *a)
9191 gen_jmp(s, read_pc(s) + a->imm);
9192 return true;
9195 static bool trans_B_cond_thumb(DisasContext *s, arg_ci *a)
9197 /* This has cond from encoding, required to be outside IT block. */
9198 if (a->cond >= 0xe) {
9199 return false;
9201 if (s->condexec_mask) {
9202 unallocated_encoding(s);
9203 return true;
9205 arm_skip_unless(s, a->cond);
9206 gen_jmp(s, read_pc(s) + a->imm);
9207 return true;
9210 static bool trans_BL(DisasContext *s, arg_i *a)
9212 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
9213 gen_jmp(s, read_pc(s) + a->imm);
9214 return true;
9217 static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
9219 TCGv_i32 tmp;
9221 /* For A32, ARCH(5) is checked near the start of the uncond block. */
9222 if (s->thumb && (a->imm & 2)) {
9223 return false;
9225 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
9226 tmp = tcg_const_i32(!s->thumb);
9227 store_cpu_field(tmp, thumb);
9228 gen_jmp(s, (read_pc(s) & ~3) + a->imm);
9229 return true;
9232 static bool trans_BL_BLX_prefix(DisasContext *s, arg_BL_BLX_prefix *a)
9234 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
9235 tcg_gen_movi_i32(cpu_R[14], read_pc(s) + (a->imm << 12));
9236 return true;
9239 static bool trans_BL_suffix(DisasContext *s, arg_BL_suffix *a)
9241 TCGv_i32 tmp = tcg_temp_new_i32();
9243 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
9244 tcg_gen_addi_i32(tmp, cpu_R[14], (a->imm << 1) | 1);
9245 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | 1);
9246 gen_bx(s, tmp);
9247 return true;
9250 static bool trans_BLX_suffix(DisasContext *s, arg_BLX_suffix *a)
9252 TCGv_i32 tmp;
9254 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
9255 if (!ENABLE_ARCH_5) {
9256 return false;
9258 tmp = tcg_temp_new_i32();
9259 tcg_gen_addi_i32(tmp, cpu_R[14], a->imm << 1);
9260 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
9261 tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | 1);
9262 gen_bx(s, tmp);
9263 return true;
9266 static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
9268 TCGv_i32 addr, tmp;
9270 tmp = load_reg(s, a->rm);
9271 if (half) {
9272 tcg_gen_add_i32(tmp, tmp, tmp);
9274 addr = load_reg(s, a->rn);
9275 tcg_gen_add_i32(addr, addr, tmp);
9277 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
9278 half ? MO_UW | s->be_data : MO_UB);
9279 tcg_temp_free_i32(addr);
9281 tcg_gen_add_i32(tmp, tmp, tmp);
9282 tcg_gen_addi_i32(tmp, tmp, read_pc(s));
9283 store_reg(s, 15, tmp);
9284 return true;
9287 static bool trans_TBB(DisasContext *s, arg_tbranch *a)
9289 return op_tbranch(s, a, false);
9292 static bool trans_TBH(DisasContext *s, arg_tbranch *a)
9294 return op_tbranch(s, a, true);
9297 static bool trans_CBZ(DisasContext *s, arg_CBZ *a)
9299 TCGv_i32 tmp = load_reg(s, a->rn);
9301 arm_gen_condlabel(s);
9302 tcg_gen_brcondi_i32(a->nz ? TCG_COND_EQ : TCG_COND_NE,
9303 tmp, 0, s->condlabel);
9304 tcg_temp_free_i32(tmp);
9305 gen_jmp(s, read_pc(s) + a->imm);
9306 return true;
9310 * Supervisor call - both T32 & A32 come here so we need to check
9311 * which mode we are in when checking for semihosting.
9314 static bool trans_SVC(DisasContext *s, arg_SVC *a)
9316 const uint32_t semihost_imm = s->thumb ? 0xab : 0x123456;
9318 if (!arm_dc_feature(s, ARM_FEATURE_M) && semihosting_enabled() &&
9319 #ifndef CONFIG_USER_ONLY
9320 !IS_USER(s) &&
9321 #endif
9322 (a->imm == semihost_imm)) {
9323 gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
9324 } else {
9325 gen_set_pc_im(s, s->base.pc_next);
9326 s->svc_imm = a->imm;
9327 s->base.is_jmp = DISAS_SWI;
9329 return true;
9333 * Unconditional system instructions
9336 static bool trans_RFE(DisasContext *s, arg_RFE *a)
9338 static const int8_t pre_offset[4] = {
9339 /* DA */ -4, /* IA */ 0, /* DB */ -8, /* IB */ 4
9341 static const int8_t post_offset[4] = {
9342 /* DA */ -8, /* IA */ 4, /* DB */ -4, /* IB */ 0
9344 TCGv_i32 addr, t1, t2;
9346 if (!ENABLE_ARCH_6 || arm_dc_feature(s, ARM_FEATURE_M)) {
9347 return false;
9349 if (IS_USER(s)) {
9350 unallocated_encoding(s);
9351 return true;
9354 addr = load_reg(s, a->rn);
9355 tcg_gen_addi_i32(addr, addr, pre_offset[a->pu]);
9357 /* Load PC into tmp and CPSR into tmp2. */
9358 t1 = tcg_temp_new_i32();
9359 gen_aa32_ld32u(s, t1, addr, get_mem_index(s));
9360 tcg_gen_addi_i32(addr, addr, 4);
9361 t2 = tcg_temp_new_i32();
9362 gen_aa32_ld32u(s, t2, addr, get_mem_index(s));
9364 if (a->w) {
9365 /* Base writeback. */
9366 tcg_gen_addi_i32(addr, addr, post_offset[a->pu]);
9367 store_reg(s, a->rn, addr);
9368 } else {
9369 tcg_temp_free_i32(addr);
9371 gen_rfe(s, t1, t2);
9372 return true;
9375 static bool trans_SRS(DisasContext *s, arg_SRS *a)
9377 if (!ENABLE_ARCH_6 || arm_dc_feature(s, ARM_FEATURE_M)) {
9378 return false;
9380 gen_srs(s, a->mode, a->pu, a->w);
9381 return true;
9384 static bool trans_CPS(DisasContext *s, arg_CPS *a)
9386 uint32_t mask, val;
9388 if (!ENABLE_ARCH_6 || arm_dc_feature(s, ARM_FEATURE_M)) {
9389 return false;
9391 if (IS_USER(s)) {
9392 /* Implemented as NOP in user mode. */
9393 return true;
9395 /* TODO: There are quite a lot of UNPREDICTABLE argument combinations. */
9397 mask = val = 0;
9398 if (a->imod & 2) {
9399 if (a->A) {
9400 mask |= CPSR_A;
9402 if (a->I) {
9403 mask |= CPSR_I;
9405 if (a->F) {
9406 mask |= CPSR_F;
9408 if (a->imod & 1) {
9409 val |= mask;
9412 if (a->M) {
9413 mask |= CPSR_M;
9414 val |= a->mode;
9416 if (mask) {
9417 gen_set_psr_im(s, mask, 0, val);
9419 return true;
9422 static bool trans_CPS_v7m(DisasContext *s, arg_CPS_v7m *a)
9424 TCGv_i32 tmp, addr, el;
9426 if (!arm_dc_feature(s, ARM_FEATURE_M)) {
9427 return false;
9429 if (IS_USER(s)) {
9430 /* Implemented as NOP in user mode. */
9431 return true;
9434 tmp = tcg_const_i32(a->im);
9435 /* FAULTMASK */
9436 if (a->F) {
9437 addr = tcg_const_i32(19);
9438 gen_helper_v7m_msr(cpu_env, addr, tmp);
9439 tcg_temp_free_i32(addr);
9441 /* PRIMASK */
9442 if (a->I) {
9443 addr = tcg_const_i32(16);
9444 gen_helper_v7m_msr(cpu_env, addr, tmp);
9445 tcg_temp_free_i32(addr);
9447 el = tcg_const_i32(s->current_el);
9448 gen_helper_rebuild_hflags_m32(cpu_env, el);
9449 tcg_temp_free_i32(el);
9450 tcg_temp_free_i32(tmp);
9451 gen_lookup_tb(s);
9452 return true;
9456 * Clear-Exclusive, Barriers
9459 static bool trans_CLREX(DisasContext *s, arg_CLREX *a)
9461 if (s->thumb
9462 ? !ENABLE_ARCH_7 && !arm_dc_feature(s, ARM_FEATURE_M)
9463 : !ENABLE_ARCH_6K) {
9464 return false;
9466 gen_clrex(s);
9467 return true;
9470 static bool trans_DSB(DisasContext *s, arg_DSB *a)
9472 if (!ENABLE_ARCH_7 && !arm_dc_feature(s, ARM_FEATURE_M)) {
9473 return false;
9475 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
9476 return true;
9479 static bool trans_DMB(DisasContext *s, arg_DMB *a)
9481 return trans_DSB(s, NULL);
9484 static bool trans_ISB(DisasContext *s, arg_ISB *a)
9486 if (!ENABLE_ARCH_7 && !arm_dc_feature(s, ARM_FEATURE_M)) {
9487 return false;
9490 * We need to break the TB after this insn to execute
9491 * self-modifying code correctly and also to take
9492 * any pending interrupts immediately.
9494 gen_goto_tb(s, 0, s->base.pc_next);
9495 return true;
9498 static bool trans_SB(DisasContext *s, arg_SB *a)
9500 if (!dc_isar_feature(aa32_sb, s)) {
9501 return false;
9504 * TODO: There is no speculation barrier opcode
9505 * for TCG; MB and end the TB instead.
9507 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
9508 gen_goto_tb(s, 0, s->base.pc_next);
9509 return true;
9512 static bool trans_SETEND(DisasContext *s, arg_SETEND *a)
9514 if (!ENABLE_ARCH_6) {
9515 return false;
9517 if (a->E != (s->be_data == MO_BE)) {
9518 gen_helper_setend(cpu_env);
9519 s->base.is_jmp = DISAS_UPDATE;
9521 return true;
9525 * Preload instructions
9526 * All are nops, contingent on the appropriate arch level.
9529 static bool trans_PLD(DisasContext *s, arg_PLD *a)
9531 return ENABLE_ARCH_5TE;
9534 static bool trans_PLDW(DisasContext *s, arg_PLD *a)
9536 return arm_dc_feature(s, ARM_FEATURE_V7MP);
9539 static bool trans_PLI(DisasContext *s, arg_PLD *a)
9541 return ENABLE_ARCH_7;
9545 * If-then
9548 static bool trans_IT(DisasContext *s, arg_IT *a)
9550 int cond_mask = a->cond_mask;
9553 * No actual code generated for this insn, just setup state.
9555 * Combinations of firstcond and mask which set up an 0b1111
9556 * condition are UNPREDICTABLE; we take the CONSTRAINED
9557 * UNPREDICTABLE choice to treat 0b1111 the same as 0b1110,
9558 * i.e. both meaning "execute always".
9560 s->condexec_cond = (cond_mask >> 4) & 0xe;
9561 s->condexec_mask = cond_mask & 0x1f;
9562 return true;
9566 * Legacy decoder.
9569 static void disas_arm_insn(DisasContext *s, unsigned int insn)
9571 unsigned int cond = insn >> 28;
9573 /* M variants do not implement ARM mode; this must raise the INVSTATE
9574 * UsageFault exception.
9576 if (arm_dc_feature(s, ARM_FEATURE_M)) {
9577 gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
9578 default_exception_el(s));
9579 return;
9582 if (cond == 0xf) {
9583 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
9584 * choose to UNDEF. In ARMv5 and above the space is used
9585 * for miscellaneous unconditional instructions.
9587 ARCH(5);
9589 /* Unconditional instructions. */
9590 /* TODO: Perhaps merge these into one decodetree output file. */
9591 if (disas_a32_uncond(s, insn) ||
9592 disas_vfp_uncond(s, insn) ||
9593 disas_neon_dp(s, insn) ||
9594 disas_neon_ls(s, insn) ||
9595 disas_neon_shared(s, insn)) {
9596 return;
9598 /* fall back to legacy decoder */
9600 if (((insn >> 25) & 7) == 1) {
9601 /* NEON Data processing. */
9602 if (disas_neon_data_insn(s, insn)) {
9603 goto illegal_op;
9605 return;
9607 if ((insn & 0x0e000f00) == 0x0c000100) {
9608 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
9609 /* iWMMXt register transfer. */
9610 if (extract32(s->c15_cpar, 1, 1)) {
9611 if (!disas_iwmmxt_insn(s, insn)) {
9612 return;
9617 goto illegal_op;
9619 if (cond != 0xe) {
9620 /* if not always execute, we generate a conditional jump to
9621 next instruction */
9622 arm_skip_unless(s, cond);
9625 /* TODO: Perhaps merge these into one decodetree output file. */
9626 if (disas_a32(s, insn) ||
9627 disas_vfp(s, insn)) {
9628 return;
9630 /* fall back to legacy decoder */
9632 switch ((insn >> 24) & 0xf) {
9633 case 0xc:
9634 case 0xd:
9635 case 0xe:
9636 if (((insn >> 8) & 0xe) == 10) {
9637 /* VFP, but failed disas_vfp. */
9638 goto illegal_op;
9640 if (disas_coproc_insn(s, insn)) {
9641 /* Coprocessor. */
9642 goto illegal_op;
9644 break;
9645 default:
9646 illegal_op:
9647 unallocated_encoding(s);
9648 break;
9652 static bool thumb_insn_is_16bit(DisasContext *s, uint32_t pc, uint32_t insn)
9655 * Return true if this is a 16 bit instruction. We must be precise
9656 * about this (matching the decode).
9658 if ((insn >> 11) < 0x1d) {
9659 /* Definitely a 16-bit instruction */
9660 return true;
9663 /* Top five bits 0b11101 / 0b11110 / 0b11111 : this is the
9664 * first half of a 32-bit Thumb insn. Thumb-1 cores might
9665 * end up actually treating this as two 16-bit insns, though,
9666 * if it's half of a bl/blx pair that might span a page boundary.
9668 if (arm_dc_feature(s, ARM_FEATURE_THUMB2) ||
9669 arm_dc_feature(s, ARM_FEATURE_M)) {
9670 /* Thumb2 cores (including all M profile ones) always treat
9671 * 32-bit insns as 32-bit.
9673 return false;
9676 if ((insn >> 11) == 0x1e && pc - s->page_start < TARGET_PAGE_SIZE - 3) {
9677 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix, and the suffix
9678 * is not on the next page; we merge this into a 32-bit
9679 * insn.
9681 return false;
9683 /* 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF);
9684 * 0b1111_1xxx_xxxx_xxxx : BL suffix;
9685 * 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix on the end of a page
9686 * -- handle as single 16 bit insn
9688 return true;
9691 /* Translate a 32-bit thumb instruction. */
9692 static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
9695 * ARMv6-M supports a limited subset of Thumb2 instructions.
9696 * Other Thumb1 architectures allow only 32-bit
9697 * combined BL/BLX prefix and suffix.
9699 if (arm_dc_feature(s, ARM_FEATURE_M) &&
9700 !arm_dc_feature(s, ARM_FEATURE_V7)) {
9701 int i;
9702 bool found = false;
9703 static const uint32_t armv6m_insn[] = {0xf3808000 /* msr */,
9704 0xf3b08040 /* dsb */,
9705 0xf3b08050 /* dmb */,
9706 0xf3b08060 /* isb */,
9707 0xf3e08000 /* mrs */,
9708 0xf000d000 /* bl */};
9709 static const uint32_t armv6m_mask[] = {0xffe0d000,
9710 0xfff0d0f0,
9711 0xfff0d0f0,
9712 0xfff0d0f0,
9713 0xffe0d000,
9714 0xf800d000};
9716 for (i = 0; i < ARRAY_SIZE(armv6m_insn); i++) {
9717 if ((insn & armv6m_mask[i]) == armv6m_insn[i]) {
9718 found = true;
9719 break;
9722 if (!found) {
9723 goto illegal_op;
9725 } else if ((insn & 0xf800e800) != 0xf000e800) {
9726 ARCH(6T2);
9729 if ((insn & 0xef000000) == 0xef000000) {
9731 * T32 encodings 0b111p_1111_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq
9732 * transform into
9733 * A32 encodings 0b1111_001p_qqqq_qqqq_qqqq_qqqq_qqqq_qqqq
9735 uint32_t a32_insn = (insn & 0xe2ffffff) |
9736 ((insn & (1 << 28)) >> 4) | (1 << 28);
9738 if (disas_neon_dp(s, a32_insn)) {
9739 return;
9743 if ((insn & 0xff100000) == 0xf9000000) {
9745 * T32 encodings 0b1111_1001_ppp0_qqqq_qqqq_qqqq_qqqq_qqqq
9746 * transform into
9747 * A32 encodings 0b1111_0100_ppp0_qqqq_qqqq_qqqq_qqqq_qqqq
9749 uint32_t a32_insn = (insn & 0x00ffffff) | 0xf4000000;
9751 if (disas_neon_ls(s, a32_insn)) {
9752 return;
9757 * TODO: Perhaps merge these into one decodetree output file.
9758 * Note disas_vfp is written for a32 with cond field in the
9759 * top nibble. The t32 encoding requires 0xe in the top nibble.
9761 if (disas_t32(s, insn) ||
9762 disas_vfp_uncond(s, insn) ||
9763 disas_neon_shared(s, insn) ||
9764 ((insn >> 28) == 0xe && disas_vfp(s, insn))) {
9765 return;
9767 /* fall back to legacy decoder */
9769 switch ((insn >> 25) & 0xf) {
9770 case 0: case 1: case 2: case 3:
9771 /* 16-bit instructions. Should never happen. */
9772 abort();
9773 case 6: case 7: case 14: case 15:
9774 /* Coprocessor. */
9775 if (arm_dc_feature(s, ARM_FEATURE_M)) {
9776 /* 0b111x_11xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx */
9777 if (extract32(insn, 24, 2) == 3) {
9778 goto illegal_op; /* op0 = 0b11 : unallocated */
9781 if (((insn >> 8) & 0xe) == 10 &&
9782 dc_isar_feature(aa32_fpsp_v2, s)) {
9783 /* FP, and the CPU supports it */
9784 goto illegal_op;
9785 } else {
9786 /* All other insns: NOCP */
9787 gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
9788 syn_uncategorized(),
9789 default_exception_el(s));
9791 break;
9793 if (((insn >> 24) & 3) == 3) {
9794 /* Translate into the equivalent ARM encoding. */
9795 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
9796 if (disas_neon_data_insn(s, insn)) {
9797 goto illegal_op;
9799 } else if (((insn >> 8) & 0xe) == 10) {
9800 /* VFP, but failed disas_vfp. */
9801 goto illegal_op;
9802 } else {
9803 if (insn & (1 << 28))
9804 goto illegal_op;
9805 if (disas_coproc_insn(s, insn)) {
9806 goto illegal_op;
9809 break;
9810 case 12:
9811 goto illegal_op;
9812 default:
9813 illegal_op:
9814 unallocated_encoding(s);
9818 static void disas_thumb_insn(DisasContext *s, uint32_t insn)
9820 if (!disas_t16(s, insn)) {
9821 unallocated_encoding(s);
9825 static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
9827 /* Return true if the insn at dc->base.pc_next might cross a page boundary.
9828 * (False positives are OK, false negatives are not.)
9829 * We know this is a Thumb insn, and our caller ensures we are
9830 * only called if dc->base.pc_next is less than 4 bytes from the page
9831 * boundary, so we cross the page if the first 16 bits indicate
9832 * that this is a 32 bit insn.
9834 uint16_t insn = arm_lduw_code(env, s->base.pc_next, s->sctlr_b);
9836 return !thumb_insn_is_16bit(s, s->base.pc_next, insn);
9839 static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
9841 DisasContext *dc = container_of(dcbase, DisasContext, base);
9842 CPUARMState *env = cs->env_ptr;
9843 ARMCPU *cpu = env_archcpu(env);
9844 uint32_t tb_flags = dc->base.tb->flags;
9845 uint32_t condexec, core_mmu_idx;
9847 dc->isar = &cpu->isar;
9848 dc->condjmp = 0;
9850 dc->aarch64 = 0;
9851 /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
9852 * there is no secure EL1, so we route exceptions to EL3.
9854 dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
9855 !arm_el_is_aa64(env, 3);
9856 dc->thumb = FIELD_EX32(tb_flags, TBFLAG_AM32, THUMB);
9857 dc->be_data = FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
9858 condexec = FIELD_EX32(tb_flags, TBFLAG_AM32, CONDEXEC);
9859 dc->condexec_mask = (condexec & 0xf) << 1;
9860 dc->condexec_cond = condexec >> 4;
9862 core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX);
9863 dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
9864 dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
9865 #if !defined(CONFIG_USER_ONLY)
9866 dc->user = (dc->current_el == 0);
9867 #endif
9868 dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL);
9870 if (arm_feature(env, ARM_FEATURE_M)) {
9871 dc->vfp_enabled = 1;
9872 dc->be_data = MO_TE;
9873 dc->v7m_handler_mode = FIELD_EX32(tb_flags, TBFLAG_M32, HANDLER);
9874 dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
9875 regime_is_secure(env, dc->mmu_idx);
9876 dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_M32, STACKCHECK);
9877 dc->v8m_fpccr_s_wrong =
9878 FIELD_EX32(tb_flags, TBFLAG_M32, FPCCR_S_WRONG);
9879 dc->v7m_new_fp_ctxt_needed =
9880 FIELD_EX32(tb_flags, TBFLAG_M32, NEW_FP_CTXT_NEEDED);
9881 dc->v7m_lspact = FIELD_EX32(tb_flags, TBFLAG_M32, LSPACT);
9882 } else {
9883 dc->be_data =
9884 FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
9885 dc->debug_target_el =
9886 FIELD_EX32(tb_flags, TBFLAG_ANY, DEBUG_TARGET_EL);
9887 dc->sctlr_b = FIELD_EX32(tb_flags, TBFLAG_A32, SCTLR_B);
9888 dc->hstr_active = FIELD_EX32(tb_flags, TBFLAG_A32, HSTR_ACTIVE);
9889 dc->ns = FIELD_EX32(tb_flags, TBFLAG_A32, NS);
9890 dc->vfp_enabled = FIELD_EX32(tb_flags, TBFLAG_A32, VFPEN);
9891 if (arm_feature(env, ARM_FEATURE_XSCALE)) {
9892 dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
9893 } else {
9894 dc->vec_len = FIELD_EX32(tb_flags, TBFLAG_A32, VECLEN);
9895 dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
9898 dc->cp_regs = cpu->cp_regs;
9899 dc->features = env->features;
9901 /* Single step state. The code-generation logic here is:
9902 * SS_ACTIVE == 0:
9903 * generate code with no special handling for single-stepping (except
9904 * that anything that can make us go to SS_ACTIVE == 1 must end the TB;
9905 * this happens anyway because those changes are all system register or
9906 * PSTATE writes).
9907 * SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
9908 * emit code for one insn
9909 * emit code to clear PSTATE.SS
9910 * emit code to generate software step exception for completed step
9911 * end TB (as usual for having generated an exception)
9912 * SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
9913 * emit code to generate a software step exception
9914 * end the TB
9916 dc->ss_active = FIELD_EX32(tb_flags, TBFLAG_ANY, SS_ACTIVE);
9917 dc->pstate_ss = FIELD_EX32(tb_flags, TBFLAG_ANY, PSTATE_SS);
9918 dc->is_ldex = false;
9920 dc->page_start = dc->base.pc_first & TARGET_PAGE_MASK;
9922 /* If architectural single step active, limit to 1. */
9923 if (is_singlestepping(dc)) {
9924 dc->base.max_insns = 1;
9927 /* ARM is a fixed-length ISA. Bound the number of insns to execute
9928 to those left on the page. */
9929 if (!dc->thumb) {
9930 int bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
9931 dc->base.max_insns = MIN(dc->base.max_insns, bound);
9934 cpu_V0 = tcg_temp_new_i64();
9935 cpu_V1 = tcg_temp_new_i64();
9936 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
9937 cpu_M0 = tcg_temp_new_i64();
9940 static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
9942 DisasContext *dc = container_of(dcbase, DisasContext, base);
9944 /* A note on handling of the condexec (IT) bits:
9946 * We want to avoid the overhead of having to write the updated condexec
9947 * bits back to the CPUARMState for every instruction in an IT block. So:
9948 * (1) if the condexec bits are not already zero then we write
9949 * zero back into the CPUARMState now. This avoids complications trying
9950 * to do it at the end of the block. (For example if we don't do this
9951 * it's hard to identify whether we can safely skip writing condexec
9952 * at the end of the TB, which we definitely want to do for the case
9953 * where a TB doesn't do anything with the IT state at all.)
9954 * (2) if we are going to leave the TB then we call gen_set_condexec()
9955 * which will write the correct value into CPUARMState if zero is wrong.
9956 * This is done both for leaving the TB at the end, and for leaving
9957 * it because of an exception we know will happen, which is done in
9958 * gen_exception_insn(). The latter is necessary because we need to
9959 * leave the TB with the PC/IT state just prior to execution of the
9960 * instruction which caused the exception.
9961 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
9962 * then the CPUARMState will be wrong and we need to reset it.
9963 * This is handled in the same way as restoration of the
9964 * PC in these situations; we save the value of the condexec bits
9965 * for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
9966 * then uses this to restore them after an exception.
9968 * Note that there are no instructions which can read the condexec
9969 * bits, and none which can write non-static values to them, so
9970 * we don't need to care about whether CPUARMState is correct in the
9971 * middle of a TB.
9974 /* Reset the conditional execution bits immediately. This avoids
9975 complications trying to do it at the end of the block. */
9976 if (dc->condexec_mask || dc->condexec_cond) {
9977 TCGv_i32 tmp = tcg_temp_new_i32();
9978 tcg_gen_movi_i32(tmp, 0);
9979 store_cpu_field(tmp, condexec_bits);
9983 static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
9985 DisasContext *dc = container_of(dcbase, DisasContext, base);
9987 tcg_gen_insn_start(dc->base.pc_next,
9988 (dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
9990 dc->insn_start = tcg_last_op();
9993 static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
9994 const CPUBreakpoint *bp)
9996 DisasContext *dc = container_of(dcbase, DisasContext, base);
9998 if (bp->flags & BP_CPU) {
9999 gen_set_condexec(dc);
10000 gen_set_pc_im(dc, dc->base.pc_next);
10001 gen_helper_check_breakpoints(cpu_env);
10002 /* End the TB early; it's likely not going to be executed */
10003 dc->base.is_jmp = DISAS_TOO_MANY;
10004 } else {
10005 gen_exception_internal_insn(dc, dc->base.pc_next, EXCP_DEBUG);
10006 /* The address covered by the breakpoint must be
10007 included in [tb->pc, tb->pc + tb->size) in order
10008 to for it to be properly cleared -- thus we
10009 increment the PC here so that the logic setting
10010 tb->size below does the right thing. */
10011 /* TODO: Advance PC by correct instruction length to
10012 * avoid disassembler error messages */
10013 dc->base.pc_next += 2;
10014 dc->base.is_jmp = DISAS_NORETURN;
10017 return true;
10020 static bool arm_pre_translate_insn(DisasContext *dc)
10022 #ifdef CONFIG_USER_ONLY
10023 /* Intercept jump to the magic kernel page. */
10024 if (dc->base.pc_next >= 0xffff0000) {
10025 /* We always get here via a jump, so know we are not in a
10026 conditional execution block. */
10027 gen_exception_internal(EXCP_KERNEL_TRAP);
10028 dc->base.is_jmp = DISAS_NORETURN;
10029 return true;
10031 #endif
10033 if (dc->ss_active && !dc->pstate_ss) {
10034 /* Singlestep state is Active-pending.
10035 * If we're in this state at the start of a TB then either
10036 * a) we just took an exception to an EL which is being debugged
10037 * and this is the first insn in the exception handler
10038 * b) debug exceptions were masked and we just unmasked them
10039 * without changing EL (eg by clearing PSTATE.D)
10040 * In either case we're going to take a swstep exception in the
10041 * "did not step an insn" case, and so the syndrome ISV and EX
10042 * bits should be zero.
10044 assert(dc->base.num_insns == 1);
10045 gen_swstep_exception(dc, 0, 0);
10046 dc->base.is_jmp = DISAS_NORETURN;
10047 return true;
10050 return false;
10053 static void arm_post_translate_insn(DisasContext *dc)
10055 if (dc->condjmp && !dc->base.is_jmp) {
10056 gen_set_label(dc->condlabel);
10057 dc->condjmp = 0;
10059 translator_loop_temp_check(&dc->base);
10062 static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
10064 DisasContext *dc = container_of(dcbase, DisasContext, base);
10065 CPUARMState *env = cpu->env_ptr;
10066 unsigned int insn;
10068 if (arm_pre_translate_insn(dc)) {
10069 return;
10072 dc->pc_curr = dc->base.pc_next;
10073 insn = arm_ldl_code(env, dc->base.pc_next, dc->sctlr_b);
10074 dc->insn = insn;
10075 dc->base.pc_next += 4;
10076 disas_arm_insn(dc, insn);
10078 arm_post_translate_insn(dc);
10080 /* ARM is a fixed-length ISA. We performed the cross-page check
10081 in init_disas_context by adjusting max_insns. */
10084 static bool thumb_insn_is_unconditional(DisasContext *s, uint32_t insn)
10086 /* Return true if this Thumb insn is always unconditional,
10087 * even inside an IT block. This is true of only a very few
10088 * instructions: BKPT, HLT, and SG.
10090 * A larger class of instructions are UNPREDICTABLE if used
10091 * inside an IT block; we do not need to detect those here, because
10092 * what we do by default (perform the cc check and update the IT
10093 * bits state machine) is a permitted CONSTRAINED UNPREDICTABLE
10094 * choice for those situations.
10096 * insn is either a 16-bit or a 32-bit instruction; the two are
10097 * distinguishable because for the 16-bit case the top 16 bits
10098 * are zeroes, and that isn't a valid 32-bit encoding.
10100 if ((insn & 0xffffff00) == 0xbe00) {
10101 /* BKPT */
10102 return true;
10105 if ((insn & 0xffffffc0) == 0xba80 && arm_dc_feature(s, ARM_FEATURE_V8) &&
10106 !arm_dc_feature(s, ARM_FEATURE_M)) {
10107 /* HLT: v8A only. This is unconditional even when it is going to
10108 * UNDEF; see the v8A ARM ARM DDI0487B.a H3.3.
10109 * For v7 cores this was a plain old undefined encoding and so
10110 * honours its cc check. (We might be using the encoding as
10111 * a semihosting trap, but we don't change the cc check behaviour
10112 * on that account, because a debugger connected to a real v7A
10113 * core and emulating semihosting traps by catching the UNDEF
10114 * exception would also only see cases where the cc check passed.
10115 * No guest code should be trying to do a HLT semihosting trap
10116 * in an IT block anyway.
10118 return true;
10121 if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_V8) &&
10122 arm_dc_feature(s, ARM_FEATURE_M)) {
10123 /* SG: v8M only */
10124 return true;
10127 return false;
10130 static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
10132 DisasContext *dc = container_of(dcbase, DisasContext, base);
10133 CPUARMState *env = cpu->env_ptr;
10134 uint32_t insn;
10135 bool is_16bit;
10137 if (arm_pre_translate_insn(dc)) {
10138 return;
10141 dc->pc_curr = dc->base.pc_next;
10142 insn = arm_lduw_code(env, dc->base.pc_next, dc->sctlr_b);
10143 is_16bit = thumb_insn_is_16bit(dc, dc->base.pc_next, insn);
10144 dc->base.pc_next += 2;
10145 if (!is_16bit) {
10146 uint32_t insn2 = arm_lduw_code(env, dc->base.pc_next, dc->sctlr_b);
10148 insn = insn << 16 | insn2;
10149 dc->base.pc_next += 2;
10151 dc->insn = insn;
10153 if (dc->condexec_mask && !thumb_insn_is_unconditional(dc, insn)) {
10154 uint32_t cond = dc->condexec_cond;
10157 * Conditionally skip the insn. Note that both 0xe and 0xf mean
10158 * "always"; 0xf is not "never".
10160 if (cond < 0x0e) {
10161 arm_skip_unless(dc, cond);
10165 if (is_16bit) {
10166 disas_thumb_insn(dc, insn);
10167 } else {
10168 disas_thumb2_insn(dc, insn);
10171 /* Advance the Thumb condexec condition. */
10172 if (dc->condexec_mask) {
10173 dc->condexec_cond = ((dc->condexec_cond & 0xe) |
10174 ((dc->condexec_mask >> 4) & 1));
10175 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
10176 if (dc->condexec_mask == 0) {
10177 dc->condexec_cond = 0;
10181 arm_post_translate_insn(dc);
10183 /* Thumb is a variable-length ISA. Stop translation when the next insn
10184 * will touch a new page. This ensures that prefetch aborts occur at
10185 * the right place.
10187 * We want to stop the TB if the next insn starts in a new page,
10188 * or if it spans between this page and the next. This means that
10189 * if we're looking at the last halfword in the page we need to
10190 * see if it's a 16-bit Thumb insn (which will fit in this TB)
10191 * or a 32-bit Thumb insn (which won't).
10192 * This is to avoid generating a silly TB with a single 16-bit insn
10193 * in it at the end of this page (which would execute correctly
10194 * but isn't very efficient).
10196 if (dc->base.is_jmp == DISAS_NEXT
10197 && (dc->base.pc_next - dc->page_start >= TARGET_PAGE_SIZE
10198 || (dc->base.pc_next - dc->page_start >= TARGET_PAGE_SIZE - 3
10199 && insn_crosses_page(env, dc)))) {
10200 dc->base.is_jmp = DISAS_TOO_MANY;
10204 static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
10206 DisasContext *dc = container_of(dcbase, DisasContext, base);
10208 if (tb_cflags(dc->base.tb) & CF_LAST_IO && dc->condjmp) {
10209 /* FIXME: This can theoretically happen with self-modifying code. */
10210 cpu_abort(cpu, "IO on conditional branch instruction");
10213 /* At this stage dc->condjmp will only be set when the skipped
10214 instruction was a conditional branch or trap, and the PC has
10215 already been written. */
10216 gen_set_condexec(dc);
10217 if (dc->base.is_jmp == DISAS_BX_EXCRET) {
10218 /* Exception return branches need some special case code at the
10219 * end of the TB, which is complex enough that it has to
10220 * handle the single-step vs not and the condition-failed
10221 * insn codepath itself.
10223 gen_bx_excret_final_code(dc);
10224 } else if (unlikely(is_singlestepping(dc))) {
10225 /* Unconditional and "condition passed" instruction codepath. */
10226 switch (dc->base.is_jmp) {
10227 case DISAS_SWI:
10228 gen_ss_advance(dc);
10229 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
10230 default_exception_el(dc));
10231 break;
10232 case DISAS_HVC:
10233 gen_ss_advance(dc);
10234 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
10235 break;
10236 case DISAS_SMC:
10237 gen_ss_advance(dc);
10238 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
10239 break;
10240 case DISAS_NEXT:
10241 case DISAS_TOO_MANY:
10242 case DISAS_UPDATE:
10243 gen_set_pc_im(dc, dc->base.pc_next);
10244 /* fall through */
10245 default:
10246 /* FIXME: Single stepping a WFI insn will not halt the CPU. */
10247 gen_singlestep_exception(dc);
10248 break;
10249 case DISAS_NORETURN:
10250 break;
10252 } else {
10253 /* While branches must always occur at the end of an IT block,
10254 there are a few other things that can cause us to terminate
10255 the TB in the middle of an IT block:
10256 - Exception generating instructions (bkpt, swi, undefined).
10257 - Page boundaries.
10258 - Hardware watchpoints.
10259 Hardware breakpoints have already been handled and skip this code.
10261 switch(dc->base.is_jmp) {
10262 case DISAS_NEXT:
10263 case DISAS_TOO_MANY:
10264 gen_goto_tb(dc, 1, dc->base.pc_next);
10265 break;
10266 case DISAS_JUMP:
10267 gen_goto_ptr();
10268 break;
10269 case DISAS_UPDATE:
10270 gen_set_pc_im(dc, dc->base.pc_next);
10271 /* fall through */
10272 default:
10273 /* indicate that the hash table must be used to find the next TB */
10274 tcg_gen_exit_tb(NULL, 0);
10275 break;
10276 case DISAS_NORETURN:
10277 /* nothing more to generate */
10278 break;
10279 case DISAS_WFI:
10281 TCGv_i32 tmp = tcg_const_i32((dc->thumb &&
10282 !(dc->insn & (1U << 31))) ? 2 : 4);
10284 gen_helper_wfi(cpu_env, tmp);
10285 tcg_temp_free_i32(tmp);
10286 /* The helper doesn't necessarily throw an exception, but we
10287 * must go back to the main loop to check for interrupts anyway.
10289 tcg_gen_exit_tb(NULL, 0);
10290 break;
10292 case DISAS_WFE:
10293 gen_helper_wfe(cpu_env);
10294 break;
10295 case DISAS_YIELD:
10296 gen_helper_yield(cpu_env);
10297 break;
10298 case DISAS_SWI:
10299 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
10300 default_exception_el(dc));
10301 break;
10302 case DISAS_HVC:
10303 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
10304 break;
10305 case DISAS_SMC:
10306 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
10307 break;
10311 if (dc->condjmp) {
10312 /* "Condition failed" instruction codepath for the branch/trap insn */
10313 gen_set_label(dc->condlabel);
10314 gen_set_condexec(dc);
10315 if (unlikely(is_singlestepping(dc))) {
10316 gen_set_pc_im(dc, dc->base.pc_next);
10317 gen_singlestep_exception(dc);
10318 } else {
10319 gen_goto_tb(dc, 1, dc->base.pc_next);
10324 static void arm_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
10326 DisasContext *dc = container_of(dcbase, DisasContext, base);
10328 qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
10329 log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
10332 static const TranslatorOps arm_translator_ops = {
10333 .init_disas_context = arm_tr_init_disas_context,
10334 .tb_start = arm_tr_tb_start,
10335 .insn_start = arm_tr_insn_start,
10336 .breakpoint_check = arm_tr_breakpoint_check,
10337 .translate_insn = arm_tr_translate_insn,
10338 .tb_stop = arm_tr_tb_stop,
10339 .disas_log = arm_tr_disas_log,
10342 static const TranslatorOps thumb_translator_ops = {
10343 .init_disas_context = arm_tr_init_disas_context,
10344 .tb_start = arm_tr_tb_start,
10345 .insn_start = arm_tr_insn_start,
10346 .breakpoint_check = arm_tr_breakpoint_check,
10347 .translate_insn = thumb_tr_translate_insn,
10348 .tb_stop = arm_tr_tb_stop,
10349 .disas_log = arm_tr_disas_log,
10352 /* generate intermediate code for basic block 'tb'. */
10353 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
10355 DisasContext dc = { };
10356 const TranslatorOps *ops = &arm_translator_ops;
10358 if (FIELD_EX32(tb->flags, TBFLAG_AM32, THUMB)) {
10359 ops = &thumb_translator_ops;
10361 #ifdef TARGET_AARCH64
10362 if (FIELD_EX32(tb->flags, TBFLAG_ANY, AARCH64_STATE)) {
10363 ops = &aarch64_translator_ops;
10365 #endif
10367 translator_loop(ops, &dc.base, cpu, tb, max_insns);
10370 void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
10371 target_ulong *data)
10373 if (is_a64(env)) {
10374 env->pc = data[0];
10375 env->condexec_bits = 0;
10376 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
10377 } else {
10378 env->regs[15] = data[0];
10379 env->condexec_bits = data[1];
10380 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;