target/arm: Convert VADD to decodetree
[qemu/ar7.git] / target / arm / translate.c
blob610659041f7e70e575bc2223303c7934bc9114b1
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-op.h"
28 #include "tcg-op-gvec.h"
29 #include "qemu/log.h"
30 #include "qemu/bitops.h"
31 #include "qemu/qemu-print.h"
32 #include "arm_ldst.h"
33 #include "hw/semihosting/semihost.h"
35 #include "exec/helper-proto.h"
36 #include "exec/helper-gen.h"
38 #include "trace-tcg.h"
39 #include "exec/log.h"
42 #define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T)
43 #define ENABLE_ARCH_5 arm_dc_feature(s, ARM_FEATURE_V5)
44 /* currently all emulated v5 cores are also v5TE, so don't bother */
45 #define ENABLE_ARCH_5TE arm_dc_feature(s, ARM_FEATURE_V5)
46 #define ENABLE_ARCH_5J dc_isar_feature(jazelle, s)
47 #define ENABLE_ARCH_6 arm_dc_feature(s, ARM_FEATURE_V6)
48 #define ENABLE_ARCH_6K arm_dc_feature(s, ARM_FEATURE_V6K)
49 #define ENABLE_ARCH_6T2 arm_dc_feature(s, ARM_FEATURE_THUMB2)
50 #define ENABLE_ARCH_7 arm_dc_feature(s, ARM_FEATURE_V7)
51 #define ENABLE_ARCH_8 arm_dc_feature(s, ARM_FEATURE_V8)
53 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
55 #include "translate.h"
57 #if defined(CONFIG_USER_ONLY)
58 #define IS_USER(s) 1
59 #else
60 #define IS_USER(s) (s->user)
61 #endif
63 /* We reuse the same 64-bit temporaries for efficiency. */
64 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
65 static TCGv_i32 cpu_R[16];
66 TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
67 TCGv_i64 cpu_exclusive_addr;
68 TCGv_i64 cpu_exclusive_val;
70 /* FIXME: These should be removed. */
71 static TCGv_i32 cpu_F0s, cpu_F1s;
72 static TCGv_i64 cpu_F0d, cpu_F1d;
74 #include "exec/gen-icount.h"
76 static const char * const regnames[] =
77 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
78 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
80 /* Function prototypes for gen_ functions calling Neon helpers. */
81 typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32,
82 TCGv_i32, TCGv_i32);
84 /* initialize TCG globals. */
85 void arm_translate_init(void)
87 int i;
89 for (i = 0; i < 16; i++) {
90 cpu_R[i] = tcg_global_mem_new_i32(cpu_env,
91 offsetof(CPUARMState, regs[i]),
92 regnames[i]);
94 cpu_CF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, CF), "CF");
95 cpu_NF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, NF), "NF");
96 cpu_VF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, VF), "VF");
97 cpu_ZF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, ZF), "ZF");
99 cpu_exclusive_addr = tcg_global_mem_new_i64(cpu_env,
100 offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
101 cpu_exclusive_val = tcg_global_mem_new_i64(cpu_env,
102 offsetof(CPUARMState, exclusive_val), "exclusive_val");
104 a64_translate_init();
107 /* Flags for the disas_set_da_iss info argument:
108 * lower bits hold the Rt register number, higher bits are flags.
110 typedef enum ISSInfo {
111 ISSNone = 0,
112 ISSRegMask = 0x1f,
113 ISSInvalid = (1 << 5),
114 ISSIsAcqRel = (1 << 6),
115 ISSIsWrite = (1 << 7),
116 ISSIs16Bit = (1 << 8),
117 } ISSInfo;
119 /* Save the syndrome information for a Data Abort */
120 static void disas_set_da_iss(DisasContext *s, TCGMemOp memop, ISSInfo issinfo)
122 uint32_t syn;
123 int sas = memop & MO_SIZE;
124 bool sse = memop & MO_SIGN;
125 bool is_acqrel = issinfo & ISSIsAcqRel;
126 bool is_write = issinfo & ISSIsWrite;
127 bool is_16bit = issinfo & ISSIs16Bit;
128 int srt = issinfo & ISSRegMask;
130 if (issinfo & ISSInvalid) {
131 /* Some callsites want to conditionally provide ISS info,
132 * eg "only if this was not a writeback"
134 return;
137 if (srt == 15) {
138 /* For AArch32, insns where the src/dest is R15 never generate
139 * ISS information. Catching that here saves checking at all
140 * the call sites.
142 return;
145 syn = syn_data_abort_with_iss(0, sas, sse, srt, 0, is_acqrel,
146 0, 0, 0, is_write, 0, is_16bit);
147 disas_set_insn_syndrome(s, syn);
150 static inline int get_a32_user_mem_index(DisasContext *s)
152 /* Return the core mmu_idx to use for A32/T32 "unprivileged load/store"
153 * insns:
154 * if PL2, UNPREDICTABLE (we choose to implement as if PL0)
155 * otherwise, access as if at PL0.
157 switch (s->mmu_idx) {
158 case ARMMMUIdx_S1E2: /* this one is UNPREDICTABLE */
159 case ARMMMUIdx_S12NSE0:
160 case ARMMMUIdx_S12NSE1:
161 return arm_to_core_mmu_idx(ARMMMUIdx_S12NSE0);
162 case ARMMMUIdx_S1E3:
163 case ARMMMUIdx_S1SE0:
164 case ARMMMUIdx_S1SE1:
165 return arm_to_core_mmu_idx(ARMMMUIdx_S1SE0);
166 case ARMMMUIdx_MUser:
167 case ARMMMUIdx_MPriv:
168 return arm_to_core_mmu_idx(ARMMMUIdx_MUser);
169 case ARMMMUIdx_MUserNegPri:
170 case ARMMMUIdx_MPrivNegPri:
171 return arm_to_core_mmu_idx(ARMMMUIdx_MUserNegPri);
172 case ARMMMUIdx_MSUser:
173 case ARMMMUIdx_MSPriv:
174 return arm_to_core_mmu_idx(ARMMMUIdx_MSUser);
175 case ARMMMUIdx_MSUserNegPri:
176 case ARMMMUIdx_MSPrivNegPri:
177 return arm_to_core_mmu_idx(ARMMMUIdx_MSUserNegPri);
178 case ARMMMUIdx_S2NS:
179 default:
180 g_assert_not_reached();
184 static inline TCGv_i32 load_cpu_offset(int offset)
186 TCGv_i32 tmp = tcg_temp_new_i32();
187 tcg_gen_ld_i32(tmp, cpu_env, offset);
188 return tmp;
191 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
193 static inline void store_cpu_offset(TCGv_i32 var, int offset)
195 tcg_gen_st_i32(var, cpu_env, offset);
196 tcg_temp_free_i32(var);
199 #define store_cpu_field(var, name) \
200 store_cpu_offset(var, offsetof(CPUARMState, name))
202 /* Set a variable to the value of a CPU register. */
203 static void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
205 if (reg == 15) {
206 uint32_t addr;
207 /* normally, since we updated PC, we need only to add one insn */
208 if (s->thumb)
209 addr = (long)s->pc + 2;
210 else
211 addr = (long)s->pc + 4;
212 tcg_gen_movi_i32(var, addr);
213 } else {
214 tcg_gen_mov_i32(var, cpu_R[reg]);
218 /* Create a new temporary and set it to the value of a CPU register. */
219 static inline TCGv_i32 load_reg(DisasContext *s, int reg)
221 TCGv_i32 tmp = tcg_temp_new_i32();
222 load_reg_var(s, tmp, reg);
223 return tmp;
226 /* Set a CPU register. The source must be a temporary and will be
227 marked as dead. */
228 static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
230 if (reg == 15) {
231 /* In Thumb mode, we must ignore bit 0.
232 * In ARM mode, for ARMv4 and ARMv5, it is UNPREDICTABLE if bits [1:0]
233 * are not 0b00, but for ARMv6 and above, we must ignore bits [1:0].
234 * We choose to ignore [1:0] in ARM mode for all architecture versions.
236 tcg_gen_andi_i32(var, var, s->thumb ? ~1 : ~3);
237 s->base.is_jmp = DISAS_JUMP;
239 tcg_gen_mov_i32(cpu_R[reg], var);
240 tcg_temp_free_i32(var);
244 * Variant of store_reg which applies v8M stack-limit checks before updating
245 * SP. If the check fails this will result in an exception being taken.
246 * We disable the stack checks for CONFIG_USER_ONLY because we have
247 * no idea what the stack limits should be in that case.
248 * If stack checking is not being done this just acts like store_reg().
250 static void store_sp_checked(DisasContext *s, TCGv_i32 var)
252 #ifndef CONFIG_USER_ONLY
253 if (s->v8m_stackcheck) {
254 gen_helper_v8m_stackcheck(cpu_env, var);
256 #endif
257 store_reg(s, 13, var);
260 /* Value extensions. */
261 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
262 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
263 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
264 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
266 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
267 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
270 static inline void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
272 TCGv_i32 tmp_mask = tcg_const_i32(mask);
273 gen_helper_cpsr_write(cpu_env, var, tmp_mask);
274 tcg_temp_free_i32(tmp_mask);
276 /* Set NZCV flags from the high 4 bits of var. */
277 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
279 static void gen_exception_internal(int excp)
281 TCGv_i32 tcg_excp = tcg_const_i32(excp);
283 assert(excp_is_internal(excp));
284 gen_helper_exception_internal(cpu_env, tcg_excp);
285 tcg_temp_free_i32(tcg_excp);
288 static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el)
290 TCGv_i32 tcg_excp = tcg_const_i32(excp);
291 TCGv_i32 tcg_syn = tcg_const_i32(syndrome);
292 TCGv_i32 tcg_el = tcg_const_i32(target_el);
294 gen_helper_exception_with_syndrome(cpu_env, tcg_excp,
295 tcg_syn, tcg_el);
297 tcg_temp_free_i32(tcg_el);
298 tcg_temp_free_i32(tcg_syn);
299 tcg_temp_free_i32(tcg_excp);
302 static void gen_step_complete_exception(DisasContext *s)
304 /* We just completed step of an insn. Move from Active-not-pending
305 * to Active-pending, and then also take the swstep exception.
306 * This corresponds to making the (IMPDEF) choice to prioritize
307 * swstep exceptions over asynchronous exceptions taken to an exception
308 * level where debug is disabled. This choice has the advantage that
309 * we do not need to maintain internal state corresponding to the
310 * ISV/EX syndrome bits between completion of the step and generation
311 * of the exception, and our syndrome information is always correct.
313 gen_ss_advance(s);
314 gen_exception(EXCP_UDEF, syn_swstep(s->ss_same_el, 1, s->is_ldex),
315 default_exception_el(s));
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 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(var, 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 var)
375 tcg_gen_ext16u_i32(var, var);
376 tcg_gen_bswap16_i32(var, var);
377 tcg_gen_ext16s_i32(var, var);
380 /* Return (b << 32) + a. Mark inputs as dead */
381 static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv_i32 b)
383 TCGv_i64 tmp64 = tcg_temp_new_i64();
385 tcg_gen_extu_i32_i64(tmp64, b);
386 tcg_temp_free_i32(b);
387 tcg_gen_shli_i64(tmp64, tmp64, 32);
388 tcg_gen_add_i64(a, tmp64, a);
390 tcg_temp_free_i64(tmp64);
391 return a;
394 /* Return (b << 32) - a. Mark inputs as dead. */
395 static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv_i32 b)
397 TCGv_i64 tmp64 = tcg_temp_new_i64();
399 tcg_gen_extu_i32_i64(tmp64, b);
400 tcg_temp_free_i32(b);
401 tcg_gen_shli_i64(tmp64, tmp64, 32);
402 tcg_gen_sub_i64(a, tmp64, a);
404 tcg_temp_free_i64(tmp64);
405 return a;
408 /* 32x32->64 multiply. Marks inputs as dead. */
409 static TCGv_i64 gen_mulu_i64_i32(TCGv_i32 a, TCGv_i32 b)
411 TCGv_i32 lo = tcg_temp_new_i32();
412 TCGv_i32 hi = tcg_temp_new_i32();
413 TCGv_i64 ret;
415 tcg_gen_mulu2_i32(lo, hi, a, b);
416 tcg_temp_free_i32(a);
417 tcg_temp_free_i32(b);
419 ret = tcg_temp_new_i64();
420 tcg_gen_concat_i32_i64(ret, lo, hi);
421 tcg_temp_free_i32(lo);
422 tcg_temp_free_i32(hi);
424 return ret;
427 static TCGv_i64 gen_muls_i64_i32(TCGv_i32 a, TCGv_i32 b)
429 TCGv_i32 lo = tcg_temp_new_i32();
430 TCGv_i32 hi = tcg_temp_new_i32();
431 TCGv_i64 ret;
433 tcg_gen_muls2_i32(lo, hi, a, b);
434 tcg_temp_free_i32(a);
435 tcg_temp_free_i32(b);
437 ret = tcg_temp_new_i64();
438 tcg_gen_concat_i32_i64(ret, lo, hi);
439 tcg_temp_free_i32(lo);
440 tcg_temp_free_i32(hi);
442 return ret;
445 /* Swap low and high halfwords. */
446 static void gen_swap_half(TCGv_i32 var)
448 TCGv_i32 tmp = tcg_temp_new_i32();
449 tcg_gen_shri_i32(tmp, var, 16);
450 tcg_gen_shli_i32(var, var, 16);
451 tcg_gen_or_i32(var, var, tmp);
452 tcg_temp_free_i32(tmp);
455 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
456 tmp = (t0 ^ t1) & 0x8000;
457 t0 &= ~0x8000;
458 t1 &= ~0x8000;
459 t0 = (t0 + t1) ^ tmp;
462 static void gen_add16(TCGv_i32 t0, TCGv_i32 t1)
464 TCGv_i32 tmp = tcg_temp_new_i32();
465 tcg_gen_xor_i32(tmp, t0, t1);
466 tcg_gen_andi_i32(tmp, tmp, 0x8000);
467 tcg_gen_andi_i32(t0, t0, ~0x8000);
468 tcg_gen_andi_i32(t1, t1, ~0x8000);
469 tcg_gen_add_i32(t0, t0, t1);
470 tcg_gen_xor_i32(t0, t0, tmp);
471 tcg_temp_free_i32(tmp);
472 tcg_temp_free_i32(t1);
475 /* Set CF to the top bit of var. */
476 static void gen_set_CF_bit31(TCGv_i32 var)
478 tcg_gen_shri_i32(cpu_CF, var, 31);
481 /* Set N and Z flags from var. */
482 static inline void gen_logic_CC(TCGv_i32 var)
484 tcg_gen_mov_i32(cpu_NF, var);
485 tcg_gen_mov_i32(cpu_ZF, var);
488 /* T0 += T1 + CF. */
489 static void gen_adc(TCGv_i32 t0, TCGv_i32 t1)
491 tcg_gen_add_i32(t0, t0, t1);
492 tcg_gen_add_i32(t0, t0, cpu_CF);
495 /* dest = T0 + T1 + CF. */
496 static void gen_add_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
498 tcg_gen_add_i32(dest, t0, t1);
499 tcg_gen_add_i32(dest, dest, cpu_CF);
502 /* dest = T0 - T1 + CF - 1. */
503 static void gen_sub_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
505 tcg_gen_sub_i32(dest, t0, t1);
506 tcg_gen_add_i32(dest, dest, cpu_CF);
507 tcg_gen_subi_i32(dest, dest, 1);
510 /* dest = T0 + T1. Compute C, N, V and Z flags */
511 static void gen_add_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
513 TCGv_i32 tmp = tcg_temp_new_i32();
514 tcg_gen_movi_i32(tmp, 0);
515 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, t1, tmp);
516 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
517 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
518 tcg_gen_xor_i32(tmp, t0, t1);
519 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
520 tcg_temp_free_i32(tmp);
521 tcg_gen_mov_i32(dest, cpu_NF);
524 /* dest = T0 + T1 + CF. Compute C, N, V and Z flags */
525 static void gen_adc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
527 TCGv_i32 tmp = tcg_temp_new_i32();
528 if (TCG_TARGET_HAS_add2_i32) {
529 tcg_gen_movi_i32(tmp, 0);
530 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp);
531 tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1, tmp);
532 } else {
533 TCGv_i64 q0 = tcg_temp_new_i64();
534 TCGv_i64 q1 = tcg_temp_new_i64();
535 tcg_gen_extu_i32_i64(q0, t0);
536 tcg_gen_extu_i32_i64(q1, t1);
537 tcg_gen_add_i64(q0, q0, q1);
538 tcg_gen_extu_i32_i64(q1, cpu_CF);
539 tcg_gen_add_i64(q0, q0, q1);
540 tcg_gen_extr_i64_i32(cpu_NF, cpu_CF, q0);
541 tcg_temp_free_i64(q0);
542 tcg_temp_free_i64(q1);
544 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
545 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
546 tcg_gen_xor_i32(tmp, t0, t1);
547 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
548 tcg_temp_free_i32(tmp);
549 tcg_gen_mov_i32(dest, cpu_NF);
552 /* dest = T0 - T1. Compute C, N, V and Z flags */
553 static void gen_sub_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
555 TCGv_i32 tmp;
556 tcg_gen_sub_i32(cpu_NF, t0, t1);
557 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
558 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0, t1);
559 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
560 tmp = tcg_temp_new_i32();
561 tcg_gen_xor_i32(tmp, t0, t1);
562 tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
563 tcg_temp_free_i32(tmp);
564 tcg_gen_mov_i32(dest, cpu_NF);
567 /* dest = T0 + ~T1 + CF. Compute C, N, V and Z flags */
568 static void gen_sbc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
570 TCGv_i32 tmp = tcg_temp_new_i32();
571 tcg_gen_not_i32(tmp, t1);
572 gen_adc_CC(dest, t0, tmp);
573 tcg_temp_free_i32(tmp);
576 #define GEN_SHIFT(name) \
577 static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \
579 TCGv_i32 tmp1, tmp2, tmp3; \
580 tmp1 = tcg_temp_new_i32(); \
581 tcg_gen_andi_i32(tmp1, t1, 0xff); \
582 tmp2 = tcg_const_i32(0); \
583 tmp3 = tcg_const_i32(0x1f); \
584 tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
585 tcg_temp_free_i32(tmp3); \
586 tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
587 tcg_gen_##name##_i32(dest, tmp2, tmp1); \
588 tcg_temp_free_i32(tmp2); \
589 tcg_temp_free_i32(tmp1); \
591 GEN_SHIFT(shl)
592 GEN_SHIFT(shr)
593 #undef GEN_SHIFT
595 static void gen_sar(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
597 TCGv_i32 tmp1, tmp2;
598 tmp1 = tcg_temp_new_i32();
599 tcg_gen_andi_i32(tmp1, t1, 0xff);
600 tmp2 = tcg_const_i32(0x1f);
601 tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1);
602 tcg_temp_free_i32(tmp2);
603 tcg_gen_sar_i32(dest, t0, tmp1);
604 tcg_temp_free_i32(tmp1);
607 static void shifter_out_im(TCGv_i32 var, int shift)
609 if (shift == 0) {
610 tcg_gen_andi_i32(cpu_CF, var, 1);
611 } else {
612 tcg_gen_shri_i32(cpu_CF, var, shift);
613 if (shift != 31) {
614 tcg_gen_andi_i32(cpu_CF, cpu_CF, 1);
619 /* Shift by immediate. Includes special handling for shift == 0. */
620 static inline void gen_arm_shift_im(TCGv_i32 var, int shiftop,
621 int shift, int flags)
623 switch (shiftop) {
624 case 0: /* LSL */
625 if (shift != 0) {
626 if (flags)
627 shifter_out_im(var, 32 - shift);
628 tcg_gen_shli_i32(var, var, shift);
630 break;
631 case 1: /* LSR */
632 if (shift == 0) {
633 if (flags) {
634 tcg_gen_shri_i32(cpu_CF, var, 31);
636 tcg_gen_movi_i32(var, 0);
637 } else {
638 if (flags)
639 shifter_out_im(var, shift - 1);
640 tcg_gen_shri_i32(var, var, shift);
642 break;
643 case 2: /* ASR */
644 if (shift == 0)
645 shift = 32;
646 if (flags)
647 shifter_out_im(var, shift - 1);
648 if (shift == 32)
649 shift = 31;
650 tcg_gen_sari_i32(var, var, shift);
651 break;
652 case 3: /* ROR/RRX */
653 if (shift != 0) {
654 if (flags)
655 shifter_out_im(var, shift - 1);
656 tcg_gen_rotri_i32(var, var, shift); break;
657 } else {
658 TCGv_i32 tmp = tcg_temp_new_i32();
659 tcg_gen_shli_i32(tmp, cpu_CF, 31);
660 if (flags)
661 shifter_out_im(var, 0);
662 tcg_gen_shri_i32(var, var, 1);
663 tcg_gen_or_i32(var, var, tmp);
664 tcg_temp_free_i32(tmp);
669 static inline void gen_arm_shift_reg(TCGv_i32 var, int shiftop,
670 TCGv_i32 shift, int flags)
672 if (flags) {
673 switch (shiftop) {
674 case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break;
675 case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break;
676 case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break;
677 case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break;
679 } else {
680 switch (shiftop) {
681 case 0:
682 gen_shl(var, var, shift);
683 break;
684 case 1:
685 gen_shr(var, var, shift);
686 break;
687 case 2:
688 gen_sar(var, var, shift);
689 break;
690 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
691 tcg_gen_rotr_i32(var, var, shift); break;
694 tcg_temp_free_i32(shift);
697 #define PAS_OP(pfx) \
698 switch (op2) { \
699 case 0: gen_pas_helper(glue(pfx,add16)); break; \
700 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
701 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
702 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
703 case 4: gen_pas_helper(glue(pfx,add8)); break; \
704 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
706 static void gen_arm_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
708 TCGv_ptr tmp;
710 switch (op1) {
711 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
712 case 1:
713 tmp = tcg_temp_new_ptr();
714 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
715 PAS_OP(s)
716 tcg_temp_free_ptr(tmp);
717 break;
718 case 5:
719 tmp = tcg_temp_new_ptr();
720 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
721 PAS_OP(u)
722 tcg_temp_free_ptr(tmp);
723 break;
724 #undef gen_pas_helper
725 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
726 case 2:
727 PAS_OP(q);
728 break;
729 case 3:
730 PAS_OP(sh);
731 break;
732 case 6:
733 PAS_OP(uq);
734 break;
735 case 7:
736 PAS_OP(uh);
737 break;
738 #undef gen_pas_helper
741 #undef PAS_OP
743 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
744 #define PAS_OP(pfx) \
745 switch (op1) { \
746 case 0: gen_pas_helper(glue(pfx,add8)); break; \
747 case 1: gen_pas_helper(glue(pfx,add16)); break; \
748 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
749 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
750 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
751 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
753 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
755 TCGv_ptr tmp;
757 switch (op2) {
758 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
759 case 0:
760 tmp = tcg_temp_new_ptr();
761 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
762 PAS_OP(s)
763 tcg_temp_free_ptr(tmp);
764 break;
765 case 4:
766 tmp = tcg_temp_new_ptr();
767 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
768 PAS_OP(u)
769 tcg_temp_free_ptr(tmp);
770 break;
771 #undef gen_pas_helper
772 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
773 case 1:
774 PAS_OP(q);
775 break;
776 case 2:
777 PAS_OP(sh);
778 break;
779 case 5:
780 PAS_OP(uq);
781 break;
782 case 6:
783 PAS_OP(uh);
784 break;
785 #undef gen_pas_helper
788 #undef PAS_OP
791 * Generate a conditional based on ARM condition code cc.
792 * This is common between ARM and Aarch64 targets.
794 void arm_test_cc(DisasCompare *cmp, int cc)
796 TCGv_i32 value;
797 TCGCond cond;
798 bool global = true;
800 switch (cc) {
801 case 0: /* eq: Z */
802 case 1: /* ne: !Z */
803 cond = TCG_COND_EQ;
804 value = cpu_ZF;
805 break;
807 case 2: /* cs: C */
808 case 3: /* cc: !C */
809 cond = TCG_COND_NE;
810 value = cpu_CF;
811 break;
813 case 4: /* mi: N */
814 case 5: /* pl: !N */
815 cond = TCG_COND_LT;
816 value = cpu_NF;
817 break;
819 case 6: /* vs: V */
820 case 7: /* vc: !V */
821 cond = TCG_COND_LT;
822 value = cpu_VF;
823 break;
825 case 8: /* hi: C && !Z */
826 case 9: /* ls: !C || Z -> !(C && !Z) */
827 cond = TCG_COND_NE;
828 value = tcg_temp_new_i32();
829 global = false;
830 /* CF is 1 for C, so -CF is an all-bits-set mask for C;
831 ZF is non-zero for !Z; so AND the two subexpressions. */
832 tcg_gen_neg_i32(value, cpu_CF);
833 tcg_gen_and_i32(value, value, cpu_ZF);
834 break;
836 case 10: /* ge: N == V -> N ^ V == 0 */
837 case 11: /* lt: N != V -> N ^ V != 0 */
838 /* Since we're only interested in the sign bit, == 0 is >= 0. */
839 cond = TCG_COND_GE;
840 value = tcg_temp_new_i32();
841 global = false;
842 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
843 break;
845 case 12: /* gt: !Z && N == V */
846 case 13: /* le: Z || N != V */
847 cond = TCG_COND_NE;
848 value = tcg_temp_new_i32();
849 global = false;
850 /* (N == V) is equal to the sign bit of ~(NF ^ VF). Propagate
851 * the sign bit then AND with ZF to yield the result. */
852 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
853 tcg_gen_sari_i32(value, value, 31);
854 tcg_gen_andc_i32(value, cpu_ZF, value);
855 break;
857 case 14: /* always */
858 case 15: /* always */
859 /* Use the ALWAYS condition, which will fold early.
860 * It doesn't matter what we use for the value. */
861 cond = TCG_COND_ALWAYS;
862 value = cpu_ZF;
863 goto no_invert;
865 default:
866 fprintf(stderr, "Bad condition code 0x%x\n", cc);
867 abort();
870 if (cc & 1) {
871 cond = tcg_invert_cond(cond);
874 no_invert:
875 cmp->cond = cond;
876 cmp->value = value;
877 cmp->value_global = global;
880 void arm_free_cc(DisasCompare *cmp)
882 if (!cmp->value_global) {
883 tcg_temp_free_i32(cmp->value);
887 void arm_jump_cc(DisasCompare *cmp, TCGLabel *label)
889 tcg_gen_brcondi_i32(cmp->cond, cmp->value, 0, label);
892 void arm_gen_test_cc(int cc, TCGLabel *label)
894 DisasCompare cmp;
895 arm_test_cc(&cmp, cc);
896 arm_jump_cc(&cmp, label);
897 arm_free_cc(&cmp);
900 static const uint8_t table_logic_cc[16] = {
901 1, /* and */
902 1, /* xor */
903 0, /* sub */
904 0, /* rsb */
905 0, /* add */
906 0, /* adc */
907 0, /* sbc */
908 0, /* rsc */
909 1, /* andl */
910 1, /* xorl */
911 0, /* cmp */
912 0, /* cmn */
913 1, /* orr */
914 1, /* mov */
915 1, /* bic */
916 1, /* mvn */
919 static inline void gen_set_condexec(DisasContext *s)
921 if (s->condexec_mask) {
922 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
923 TCGv_i32 tmp = tcg_temp_new_i32();
924 tcg_gen_movi_i32(tmp, val);
925 store_cpu_field(tmp, condexec_bits);
929 static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
931 tcg_gen_movi_i32(cpu_R[15], val);
934 /* Set PC and Thumb state from an immediate address. */
935 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
937 TCGv_i32 tmp;
939 s->base.is_jmp = DISAS_JUMP;
940 if (s->thumb != (addr & 1)) {
941 tmp = tcg_temp_new_i32();
942 tcg_gen_movi_i32(tmp, addr & 1);
943 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, thumb));
944 tcg_temp_free_i32(tmp);
946 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
949 /* Set PC and Thumb state from var. var is marked as dead. */
950 static inline void gen_bx(DisasContext *s, TCGv_i32 var)
952 s->base.is_jmp = DISAS_JUMP;
953 tcg_gen_andi_i32(cpu_R[15], var, ~1);
954 tcg_gen_andi_i32(var, var, 1);
955 store_cpu_field(var, thumb);
958 /* Set PC and Thumb state from var. var is marked as dead.
959 * For M-profile CPUs, include logic to detect exception-return
960 * branches and handle them. This is needed for Thumb POP/LDM to PC, LDR to PC,
961 * and BX reg, and no others, and happens only for code in Handler mode.
963 static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var)
965 /* Generate the same code here as for a simple bx, but flag via
966 * s->base.is_jmp that we need to do the rest of the work later.
968 gen_bx(s, var);
969 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY) ||
970 (s->v7m_handler_mode && arm_dc_feature(s, ARM_FEATURE_M))) {
971 s->base.is_jmp = DISAS_BX_EXCRET;
975 static inline void gen_bx_excret_final_code(DisasContext *s)
977 /* Generate the code to finish possible exception return and end the TB */
978 TCGLabel *excret_label = gen_new_label();
979 uint32_t min_magic;
981 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY)) {
982 /* Covers FNC_RETURN and EXC_RETURN magic */
983 min_magic = FNC_RETURN_MIN_MAGIC;
984 } else {
985 /* EXC_RETURN magic only */
986 min_magic = EXC_RETURN_MIN_MAGIC;
989 /* Is the new PC value in the magic range indicating exception return? */
990 tcg_gen_brcondi_i32(TCG_COND_GEU, cpu_R[15], min_magic, excret_label);
991 /* No: end the TB as we would for a DISAS_JMP */
992 if (is_singlestepping(s)) {
993 gen_singlestep_exception(s);
994 } else {
995 tcg_gen_exit_tb(NULL, 0);
997 gen_set_label(excret_label);
998 /* Yes: this is an exception return.
999 * At this point in runtime env->regs[15] and env->thumb will hold
1000 * the exception-return magic number, which do_v7m_exception_exit()
1001 * will read. Nothing else will be able to see those values because
1002 * the cpu-exec main loop guarantees that we will always go straight
1003 * from raising the exception to the exception-handling code.
1005 * gen_ss_advance(s) does nothing on M profile currently but
1006 * calling it is conceptually the right thing as we have executed
1007 * this instruction (compare SWI, HVC, SMC handling).
1009 gen_ss_advance(s);
1010 gen_exception_internal(EXCP_EXCEPTION_EXIT);
1013 static inline void gen_bxns(DisasContext *s, int rm)
1015 TCGv_i32 var = load_reg(s, rm);
1017 /* The bxns helper may raise an EXCEPTION_EXIT exception, so in theory
1018 * we need to sync state before calling it, but:
1019 * - we don't need to do gen_set_pc_im() because the bxns helper will
1020 * always set the PC itself
1021 * - we don't need to do gen_set_condexec() because BXNS is UNPREDICTABLE
1022 * unless it's outside an IT block or the last insn in an IT block,
1023 * so we know that condexec == 0 (already set at the top of the TB)
1024 * is correct in the non-UNPREDICTABLE cases, and we can choose
1025 * "zeroes the IT bits" as our UNPREDICTABLE behaviour otherwise.
1027 gen_helper_v7m_bxns(cpu_env, var);
1028 tcg_temp_free_i32(var);
1029 s->base.is_jmp = DISAS_EXIT;
1032 static inline void gen_blxns(DisasContext *s, int rm)
1034 TCGv_i32 var = load_reg(s, rm);
1036 /* We don't need to sync condexec state, for the same reason as bxns.
1037 * We do however need to set the PC, because the blxns helper reads it.
1038 * The blxns helper may throw an exception.
1040 gen_set_pc_im(s, s->pc);
1041 gen_helper_v7m_blxns(cpu_env, var);
1042 tcg_temp_free_i32(var);
1043 s->base.is_jmp = DISAS_EXIT;
1046 /* Variant of store_reg which uses branch&exchange logic when storing
1047 to r15 in ARM architecture v7 and above. The source must be a temporary
1048 and will be marked as dead. */
1049 static inline void store_reg_bx(DisasContext *s, int reg, TCGv_i32 var)
1051 if (reg == 15 && ENABLE_ARCH_7) {
1052 gen_bx(s, var);
1053 } else {
1054 store_reg(s, reg, var);
1058 /* Variant of store_reg which uses branch&exchange logic when storing
1059 * to r15 in ARM architecture v5T and above. This is used for storing
1060 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
1061 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
1062 static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
1064 if (reg == 15 && ENABLE_ARCH_5) {
1065 gen_bx_excret(s, var);
1066 } else {
1067 store_reg(s, reg, var);
1071 #ifdef CONFIG_USER_ONLY
1072 #define IS_USER_ONLY 1
1073 #else
1074 #define IS_USER_ONLY 0
1075 #endif
1077 /* Abstractions of "generate code to do a guest load/store for
1078 * AArch32", where a vaddr is always 32 bits (and is zero
1079 * extended if we're a 64 bit core) and data is also
1080 * 32 bits unless specifically doing a 64 bit access.
1081 * These functions work like tcg_gen_qemu_{ld,st}* except
1082 * that the address argument is TCGv_i32 rather than TCGv.
1085 static inline TCGv gen_aa32_addr(DisasContext *s, TCGv_i32 a32, TCGMemOp op)
1087 TCGv addr = tcg_temp_new();
1088 tcg_gen_extu_i32_tl(addr, a32);
1090 /* Not needed for user-mode BE32, where we use MO_BE instead. */
1091 if (!IS_USER_ONLY && s->sctlr_b && (op & MO_SIZE) < MO_32) {
1092 tcg_gen_xori_tl(addr, addr, 4 - (1 << (op & MO_SIZE)));
1094 return addr;
1097 static void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
1098 int index, TCGMemOp opc)
1100 TCGv addr;
1102 if (arm_dc_feature(s, ARM_FEATURE_M) &&
1103 !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
1104 opc |= MO_ALIGN;
1107 addr = gen_aa32_addr(s, a32, opc);
1108 tcg_gen_qemu_ld_i32(val, addr, index, opc);
1109 tcg_temp_free(addr);
1112 static void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
1113 int index, TCGMemOp opc)
1115 TCGv addr;
1117 if (arm_dc_feature(s, ARM_FEATURE_M) &&
1118 !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
1119 opc |= MO_ALIGN;
1122 addr = gen_aa32_addr(s, a32, opc);
1123 tcg_gen_qemu_st_i32(val, addr, index, opc);
1124 tcg_temp_free(addr);
1127 #define DO_GEN_LD(SUFF, OPC) \
1128 static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
1129 TCGv_i32 a32, int index) \
1131 gen_aa32_ld_i32(s, val, a32, index, OPC | s->be_data); \
1133 static inline void gen_aa32_ld##SUFF##_iss(DisasContext *s, \
1134 TCGv_i32 val, \
1135 TCGv_i32 a32, int index, \
1136 ISSInfo issinfo) \
1138 gen_aa32_ld##SUFF(s, val, a32, index); \
1139 disas_set_da_iss(s, OPC, issinfo); \
1142 #define DO_GEN_ST(SUFF, OPC) \
1143 static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
1144 TCGv_i32 a32, int index) \
1146 gen_aa32_st_i32(s, val, a32, index, OPC | s->be_data); \
1148 static inline void gen_aa32_st##SUFF##_iss(DisasContext *s, \
1149 TCGv_i32 val, \
1150 TCGv_i32 a32, int index, \
1151 ISSInfo issinfo) \
1153 gen_aa32_st##SUFF(s, val, a32, index); \
1154 disas_set_da_iss(s, OPC, issinfo | ISSIsWrite); \
1157 static inline void gen_aa32_frob64(DisasContext *s, TCGv_i64 val)
1159 /* Not needed for user-mode BE32, where we use MO_BE instead. */
1160 if (!IS_USER_ONLY && s->sctlr_b) {
1161 tcg_gen_rotri_i64(val, val, 32);
1165 static void gen_aa32_ld_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
1166 int index, TCGMemOp opc)
1168 TCGv addr = gen_aa32_addr(s, a32, opc);
1169 tcg_gen_qemu_ld_i64(val, addr, index, opc);
1170 gen_aa32_frob64(s, val);
1171 tcg_temp_free(addr);
1174 static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
1175 TCGv_i32 a32, int index)
1177 gen_aa32_ld_i64(s, val, a32, index, MO_Q | s->be_data);
1180 static void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
1181 int index, TCGMemOp opc)
1183 TCGv addr = gen_aa32_addr(s, a32, opc);
1185 /* Not needed for user-mode BE32, where we use MO_BE instead. */
1186 if (!IS_USER_ONLY && s->sctlr_b) {
1187 TCGv_i64 tmp = tcg_temp_new_i64();
1188 tcg_gen_rotri_i64(tmp, val, 32);
1189 tcg_gen_qemu_st_i64(tmp, addr, index, opc);
1190 tcg_temp_free_i64(tmp);
1191 } else {
1192 tcg_gen_qemu_st_i64(val, addr, index, opc);
1194 tcg_temp_free(addr);
1197 static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
1198 TCGv_i32 a32, int index)
1200 gen_aa32_st_i64(s, val, a32, index, MO_Q | s->be_data);
1203 DO_GEN_LD(8s, MO_SB)
1204 DO_GEN_LD(8u, MO_UB)
1205 DO_GEN_LD(16s, MO_SW)
1206 DO_GEN_LD(16u, MO_UW)
1207 DO_GEN_LD(32u, MO_UL)
1208 DO_GEN_ST(8, MO_UB)
1209 DO_GEN_ST(16, MO_UW)
1210 DO_GEN_ST(32, MO_UL)
1212 static inline void gen_hvc(DisasContext *s, int imm16)
1214 /* The pre HVC helper handles cases when HVC gets trapped
1215 * as an undefined insn by runtime configuration (ie before
1216 * the insn really executes).
1218 gen_set_pc_im(s, s->pc - 4);
1219 gen_helper_pre_hvc(cpu_env);
1220 /* Otherwise we will treat this as a real exception which
1221 * happens after execution of the insn. (The distinction matters
1222 * for the PC value reported to the exception handler and also
1223 * for single stepping.)
1225 s->svc_imm = imm16;
1226 gen_set_pc_im(s, s->pc);
1227 s->base.is_jmp = DISAS_HVC;
1230 static inline void gen_smc(DisasContext *s)
1232 /* As with HVC, we may take an exception either before or after
1233 * the insn executes.
1235 TCGv_i32 tmp;
1237 gen_set_pc_im(s, s->pc - 4);
1238 tmp = tcg_const_i32(syn_aa32_smc());
1239 gen_helper_pre_smc(cpu_env, tmp);
1240 tcg_temp_free_i32(tmp);
1241 gen_set_pc_im(s, s->pc);
1242 s->base.is_jmp = DISAS_SMC;
1245 static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
1247 gen_set_condexec(s);
1248 gen_set_pc_im(s, s->pc - offset);
1249 gen_exception_internal(excp);
1250 s->base.is_jmp = DISAS_NORETURN;
1253 static void gen_exception_insn(DisasContext *s, int offset, int excp,
1254 int syn, uint32_t target_el)
1256 gen_set_condexec(s);
1257 gen_set_pc_im(s, s->pc - offset);
1258 gen_exception(excp, syn, target_el);
1259 s->base.is_jmp = DISAS_NORETURN;
1262 static void gen_exception_bkpt_insn(DisasContext *s, int offset, uint32_t syn)
1264 TCGv_i32 tcg_syn;
1266 gen_set_condexec(s);
1267 gen_set_pc_im(s, s->pc - offset);
1268 tcg_syn = tcg_const_i32(syn);
1269 gen_helper_exception_bkpt_insn(cpu_env, tcg_syn);
1270 tcg_temp_free_i32(tcg_syn);
1271 s->base.is_jmp = DISAS_NORETURN;
1274 /* Force a TB lookup after an instruction that changes the CPU state. */
1275 static inline void gen_lookup_tb(DisasContext *s)
1277 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
1278 s->base.is_jmp = DISAS_EXIT;
1281 static inline void gen_hlt(DisasContext *s, int imm)
1283 /* HLT. This has two purposes.
1284 * Architecturally, it is an external halting debug instruction.
1285 * Since QEMU doesn't implement external debug, we treat this as
1286 * it is required for halting debug disabled: it will UNDEF.
1287 * Secondly, "HLT 0x3C" is a T32 semihosting trap instruction,
1288 * and "HLT 0xF000" is an A32 semihosting syscall. These traps
1289 * must trigger semihosting even for ARMv7 and earlier, where
1290 * HLT was an undefined encoding.
1291 * In system mode, we don't allow userspace access to
1292 * semihosting, to provide some semblance of security
1293 * (and for consistency with our 32-bit semihosting).
1295 if (semihosting_enabled() &&
1296 #ifndef CONFIG_USER_ONLY
1297 s->current_el != 0 &&
1298 #endif
1299 (imm == (s->thumb ? 0x3c : 0xf000))) {
1300 gen_exception_internal_insn(s, 0, EXCP_SEMIHOST);
1301 return;
1304 gen_exception_insn(s, s->thumb ? 2 : 4, EXCP_UDEF, syn_uncategorized(),
1305 default_exception_el(s));
1308 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
1309 TCGv_i32 var)
1311 int val, rm, shift, shiftop;
1312 TCGv_i32 offset;
1314 if (!(insn & (1 << 25))) {
1315 /* immediate */
1316 val = insn & 0xfff;
1317 if (!(insn & (1 << 23)))
1318 val = -val;
1319 if (val != 0)
1320 tcg_gen_addi_i32(var, var, val);
1321 } else {
1322 /* shift/register */
1323 rm = (insn) & 0xf;
1324 shift = (insn >> 7) & 0x1f;
1325 shiftop = (insn >> 5) & 3;
1326 offset = load_reg(s, rm);
1327 gen_arm_shift_im(offset, shiftop, shift, 0);
1328 if (!(insn & (1 << 23)))
1329 tcg_gen_sub_i32(var, var, offset);
1330 else
1331 tcg_gen_add_i32(var, var, offset);
1332 tcg_temp_free_i32(offset);
1336 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
1337 int extra, TCGv_i32 var)
1339 int val, rm;
1340 TCGv_i32 offset;
1342 if (insn & (1 << 22)) {
1343 /* immediate */
1344 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
1345 if (!(insn & (1 << 23)))
1346 val = -val;
1347 val += extra;
1348 if (val != 0)
1349 tcg_gen_addi_i32(var, var, val);
1350 } else {
1351 /* register */
1352 if (extra)
1353 tcg_gen_addi_i32(var, var, extra);
1354 rm = (insn) & 0xf;
1355 offset = load_reg(s, rm);
1356 if (!(insn & (1 << 23)))
1357 tcg_gen_sub_i32(var, var, offset);
1358 else
1359 tcg_gen_add_i32(var, var, offset);
1360 tcg_temp_free_i32(offset);
1364 static TCGv_ptr get_fpstatus_ptr(int neon)
1366 TCGv_ptr statusptr = tcg_temp_new_ptr();
1367 int offset;
1368 if (neon) {
1369 offset = offsetof(CPUARMState, vfp.standard_fp_status);
1370 } else {
1371 offset = offsetof(CPUARMState, vfp.fp_status);
1373 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
1374 return statusptr;
1377 #define VFP_OP2(name) \
1378 static inline void gen_vfp_##name(int dp) \
1380 TCGv_ptr fpst = get_fpstatus_ptr(0); \
1381 if (dp) { \
1382 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, fpst); \
1383 } else { \
1384 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, fpst); \
1386 tcg_temp_free_ptr(fpst); \
1389 VFP_OP2(sub)
1390 VFP_OP2(div)
1392 #undef VFP_OP2
1394 static inline void gen_vfp_abs(int dp)
1396 if (dp)
1397 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1398 else
1399 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1402 static inline void gen_vfp_neg(int dp)
1404 if (dp)
1405 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1406 else
1407 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1410 static inline void gen_vfp_sqrt(int dp)
1412 if (dp)
1413 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1414 else
1415 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1418 static inline void gen_vfp_cmp(int dp)
1420 if (dp)
1421 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1422 else
1423 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1426 static inline void gen_vfp_cmpe(int dp)
1428 if (dp)
1429 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1430 else
1431 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1434 static inline void gen_vfp_F1_ld0(int dp)
1436 if (dp)
1437 tcg_gen_movi_i64(cpu_F1d, 0);
1438 else
1439 tcg_gen_movi_i32(cpu_F1s, 0);
1442 #define VFP_GEN_ITOF(name) \
1443 static inline void gen_vfp_##name(int dp, int neon) \
1445 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1446 if (dp) { \
1447 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
1448 } else { \
1449 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1451 tcg_temp_free_ptr(statusptr); \
1454 VFP_GEN_ITOF(uito)
1455 VFP_GEN_ITOF(sito)
1456 #undef VFP_GEN_ITOF
1458 #define VFP_GEN_FTOI(name) \
1459 static inline void gen_vfp_##name(int dp, int neon) \
1461 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1462 if (dp) { \
1463 gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
1464 } else { \
1465 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1467 tcg_temp_free_ptr(statusptr); \
1470 VFP_GEN_FTOI(toui)
1471 VFP_GEN_FTOI(touiz)
1472 VFP_GEN_FTOI(tosi)
1473 VFP_GEN_FTOI(tosiz)
1474 #undef VFP_GEN_FTOI
1476 #define VFP_GEN_FIX(name, round) \
1477 static inline void gen_vfp_##name(int dp, int shift, int neon) \
1479 TCGv_i32 tmp_shift = tcg_const_i32(shift); \
1480 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1481 if (dp) { \
1482 gen_helper_vfp_##name##d##round(cpu_F0d, cpu_F0d, tmp_shift, \
1483 statusptr); \
1484 } else { \
1485 gen_helper_vfp_##name##s##round(cpu_F0s, cpu_F0s, tmp_shift, \
1486 statusptr); \
1488 tcg_temp_free_i32(tmp_shift); \
1489 tcg_temp_free_ptr(statusptr); \
1491 VFP_GEN_FIX(tosh, _round_to_zero)
1492 VFP_GEN_FIX(tosl, _round_to_zero)
1493 VFP_GEN_FIX(touh, _round_to_zero)
1494 VFP_GEN_FIX(toul, _round_to_zero)
1495 VFP_GEN_FIX(shto, )
1496 VFP_GEN_FIX(slto, )
1497 VFP_GEN_FIX(uhto, )
1498 VFP_GEN_FIX(ulto, )
1499 #undef VFP_GEN_FIX
1501 static inline long vfp_reg_offset(bool dp, unsigned reg)
1503 if (dp) {
1504 return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]);
1505 } else {
1506 long ofs = offsetof(CPUARMState, vfp.zregs[reg >> 2].d[(reg >> 1) & 1]);
1507 if (reg & 1) {
1508 ofs += offsetof(CPU_DoubleU, l.upper);
1509 } else {
1510 ofs += offsetof(CPU_DoubleU, l.lower);
1512 return ofs;
1516 /* Return the offset of a 32-bit piece of a NEON register.
1517 zero is the least significant end of the register. */
1518 static inline long
1519 neon_reg_offset (int reg, int n)
1521 int sreg;
1522 sreg = reg * 2 + n;
1523 return vfp_reg_offset(0, sreg);
1526 /* Return the offset of a 2**SIZE piece of a NEON register, at index ELE,
1527 * where 0 is the least significant end of the register.
1529 static inline long
1530 neon_element_offset(int reg, int element, TCGMemOp size)
1532 int element_size = 1 << size;
1533 int ofs = element * element_size;
1534 #ifdef HOST_WORDS_BIGENDIAN
1535 /* Calculate the offset assuming fully little-endian,
1536 * then XOR to account for the order of the 8-byte units.
1538 if (element_size < 8) {
1539 ofs ^= 8 - element_size;
1541 #endif
1542 return neon_reg_offset(reg, 0) + ofs;
1545 static TCGv_i32 neon_load_reg(int reg, int pass)
1547 TCGv_i32 tmp = tcg_temp_new_i32();
1548 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1549 return tmp;
1552 static void neon_load_element(TCGv_i32 var, int reg, int ele, TCGMemOp mop)
1554 long offset = neon_element_offset(reg, ele, mop & MO_SIZE);
1556 switch (mop) {
1557 case MO_UB:
1558 tcg_gen_ld8u_i32(var, cpu_env, offset);
1559 break;
1560 case MO_UW:
1561 tcg_gen_ld16u_i32(var, cpu_env, offset);
1562 break;
1563 case MO_UL:
1564 tcg_gen_ld_i32(var, cpu_env, offset);
1565 break;
1566 default:
1567 g_assert_not_reached();
1571 static void neon_load_element64(TCGv_i64 var, int reg, int ele, TCGMemOp mop)
1573 long offset = neon_element_offset(reg, ele, mop & MO_SIZE);
1575 switch (mop) {
1576 case MO_UB:
1577 tcg_gen_ld8u_i64(var, cpu_env, offset);
1578 break;
1579 case MO_UW:
1580 tcg_gen_ld16u_i64(var, cpu_env, offset);
1581 break;
1582 case MO_UL:
1583 tcg_gen_ld32u_i64(var, cpu_env, offset);
1584 break;
1585 case MO_Q:
1586 tcg_gen_ld_i64(var, cpu_env, offset);
1587 break;
1588 default:
1589 g_assert_not_reached();
1593 static void neon_store_reg(int reg, int pass, TCGv_i32 var)
1595 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1596 tcg_temp_free_i32(var);
1599 static void neon_store_element(int reg, int ele, TCGMemOp size, TCGv_i32 var)
1601 long offset = neon_element_offset(reg, ele, size);
1603 switch (size) {
1604 case MO_8:
1605 tcg_gen_st8_i32(var, cpu_env, offset);
1606 break;
1607 case MO_16:
1608 tcg_gen_st16_i32(var, cpu_env, offset);
1609 break;
1610 case MO_32:
1611 tcg_gen_st_i32(var, cpu_env, offset);
1612 break;
1613 default:
1614 g_assert_not_reached();
1618 static void neon_store_element64(int reg, int ele, TCGMemOp size, TCGv_i64 var)
1620 long offset = neon_element_offset(reg, ele, size);
1622 switch (size) {
1623 case MO_8:
1624 tcg_gen_st8_i64(var, cpu_env, offset);
1625 break;
1626 case MO_16:
1627 tcg_gen_st16_i64(var, cpu_env, offset);
1628 break;
1629 case MO_32:
1630 tcg_gen_st32_i64(var, cpu_env, offset);
1631 break;
1632 case MO_64:
1633 tcg_gen_st_i64(var, cpu_env, offset);
1634 break;
1635 default:
1636 g_assert_not_reached();
1640 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1642 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1645 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1647 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1650 static inline void neon_load_reg32(TCGv_i32 var, int reg)
1652 tcg_gen_ld_i32(var, cpu_env, vfp_reg_offset(false, reg));
1655 static inline void neon_store_reg32(TCGv_i32 var, int reg)
1657 tcg_gen_st_i32(var, cpu_env, vfp_reg_offset(false, reg));
1660 static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
1662 TCGv_ptr ret = tcg_temp_new_ptr();
1663 tcg_gen_addi_ptr(ret, cpu_env, vfp_reg_offset(dp, reg));
1664 return ret;
1667 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1668 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1669 #define tcg_gen_st_f32 tcg_gen_st_i32
1670 #define tcg_gen_st_f64 tcg_gen_st_i64
1672 static inline void gen_mov_F0_vreg(int dp, int reg)
1674 if (dp)
1675 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1676 else
1677 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1680 static inline void gen_mov_F1_vreg(int dp, int reg)
1682 if (dp)
1683 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1684 else
1685 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1688 static inline void gen_mov_vreg_F0(int dp, int reg)
1690 if (dp)
1691 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1692 else
1693 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1696 #define ARM_CP_RW_BIT (1 << 20)
1698 /* Include the VFP decoder */
1699 #include "translate-vfp.inc.c"
1701 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1703 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1706 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1708 tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1711 static inline TCGv_i32 iwmmxt_load_creg(int reg)
1713 TCGv_i32 var = tcg_temp_new_i32();
1714 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1715 return var;
1718 static inline void iwmmxt_store_creg(int reg, TCGv_i32 var)
1720 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1721 tcg_temp_free_i32(var);
1724 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1726 iwmmxt_store_reg(cpu_M0, rn);
1729 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1731 iwmmxt_load_reg(cpu_M0, rn);
1734 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1736 iwmmxt_load_reg(cpu_V1, rn);
1737 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1740 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1742 iwmmxt_load_reg(cpu_V1, rn);
1743 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1746 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1748 iwmmxt_load_reg(cpu_V1, rn);
1749 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1752 #define IWMMXT_OP(name) \
1753 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1755 iwmmxt_load_reg(cpu_V1, rn); \
1756 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1759 #define IWMMXT_OP_ENV(name) \
1760 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1762 iwmmxt_load_reg(cpu_V1, rn); \
1763 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1766 #define IWMMXT_OP_ENV_SIZE(name) \
1767 IWMMXT_OP_ENV(name##b) \
1768 IWMMXT_OP_ENV(name##w) \
1769 IWMMXT_OP_ENV(name##l)
1771 #define IWMMXT_OP_ENV1(name) \
1772 static inline void gen_op_iwmmxt_##name##_M0(void) \
1774 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1777 IWMMXT_OP(maddsq)
1778 IWMMXT_OP(madduq)
1779 IWMMXT_OP(sadb)
1780 IWMMXT_OP(sadw)
1781 IWMMXT_OP(mulslw)
1782 IWMMXT_OP(mulshw)
1783 IWMMXT_OP(mululw)
1784 IWMMXT_OP(muluhw)
1785 IWMMXT_OP(macsw)
1786 IWMMXT_OP(macuw)
1788 IWMMXT_OP_ENV_SIZE(unpackl)
1789 IWMMXT_OP_ENV_SIZE(unpackh)
1791 IWMMXT_OP_ENV1(unpacklub)
1792 IWMMXT_OP_ENV1(unpackluw)
1793 IWMMXT_OP_ENV1(unpacklul)
1794 IWMMXT_OP_ENV1(unpackhub)
1795 IWMMXT_OP_ENV1(unpackhuw)
1796 IWMMXT_OP_ENV1(unpackhul)
1797 IWMMXT_OP_ENV1(unpacklsb)
1798 IWMMXT_OP_ENV1(unpacklsw)
1799 IWMMXT_OP_ENV1(unpacklsl)
1800 IWMMXT_OP_ENV1(unpackhsb)
1801 IWMMXT_OP_ENV1(unpackhsw)
1802 IWMMXT_OP_ENV1(unpackhsl)
1804 IWMMXT_OP_ENV_SIZE(cmpeq)
1805 IWMMXT_OP_ENV_SIZE(cmpgtu)
1806 IWMMXT_OP_ENV_SIZE(cmpgts)
1808 IWMMXT_OP_ENV_SIZE(mins)
1809 IWMMXT_OP_ENV_SIZE(minu)
1810 IWMMXT_OP_ENV_SIZE(maxs)
1811 IWMMXT_OP_ENV_SIZE(maxu)
1813 IWMMXT_OP_ENV_SIZE(subn)
1814 IWMMXT_OP_ENV_SIZE(addn)
1815 IWMMXT_OP_ENV_SIZE(subu)
1816 IWMMXT_OP_ENV_SIZE(addu)
1817 IWMMXT_OP_ENV_SIZE(subs)
1818 IWMMXT_OP_ENV_SIZE(adds)
1820 IWMMXT_OP_ENV(avgb0)
1821 IWMMXT_OP_ENV(avgb1)
1822 IWMMXT_OP_ENV(avgw0)
1823 IWMMXT_OP_ENV(avgw1)
1825 IWMMXT_OP_ENV(packuw)
1826 IWMMXT_OP_ENV(packul)
1827 IWMMXT_OP_ENV(packuq)
1828 IWMMXT_OP_ENV(packsw)
1829 IWMMXT_OP_ENV(packsl)
1830 IWMMXT_OP_ENV(packsq)
1832 static void gen_op_iwmmxt_set_mup(void)
1834 TCGv_i32 tmp;
1835 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1836 tcg_gen_ori_i32(tmp, tmp, 2);
1837 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1840 static void gen_op_iwmmxt_set_cup(void)
1842 TCGv_i32 tmp;
1843 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1844 tcg_gen_ori_i32(tmp, tmp, 1);
1845 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1848 static void gen_op_iwmmxt_setpsr_nz(void)
1850 TCGv_i32 tmp = tcg_temp_new_i32();
1851 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1852 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1855 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1857 iwmmxt_load_reg(cpu_V1, rn);
1858 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1859 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1862 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn,
1863 TCGv_i32 dest)
1865 int rd;
1866 uint32_t offset;
1867 TCGv_i32 tmp;
1869 rd = (insn >> 16) & 0xf;
1870 tmp = load_reg(s, rd);
1872 offset = (insn & 0xff) << ((insn >> 7) & 2);
1873 if (insn & (1 << 24)) {
1874 /* Pre indexed */
1875 if (insn & (1 << 23))
1876 tcg_gen_addi_i32(tmp, tmp, offset);
1877 else
1878 tcg_gen_addi_i32(tmp, tmp, -offset);
1879 tcg_gen_mov_i32(dest, tmp);
1880 if (insn & (1 << 21))
1881 store_reg(s, rd, tmp);
1882 else
1883 tcg_temp_free_i32(tmp);
1884 } else if (insn & (1 << 21)) {
1885 /* Post indexed */
1886 tcg_gen_mov_i32(dest, tmp);
1887 if (insn & (1 << 23))
1888 tcg_gen_addi_i32(tmp, tmp, offset);
1889 else
1890 tcg_gen_addi_i32(tmp, tmp, -offset);
1891 store_reg(s, rd, tmp);
1892 } else if (!(insn & (1 << 23)))
1893 return 1;
1894 return 0;
1897 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest)
1899 int rd = (insn >> 0) & 0xf;
1900 TCGv_i32 tmp;
1902 if (insn & (1 << 8)) {
1903 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1904 return 1;
1905 } else {
1906 tmp = iwmmxt_load_creg(rd);
1908 } else {
1909 tmp = tcg_temp_new_i32();
1910 iwmmxt_load_reg(cpu_V0, rd);
1911 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
1913 tcg_gen_andi_i32(tmp, tmp, mask);
1914 tcg_gen_mov_i32(dest, tmp);
1915 tcg_temp_free_i32(tmp);
1916 return 0;
1919 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
1920 (ie. an undefined instruction). */
1921 static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
1923 int rd, wrd;
1924 int rdhi, rdlo, rd0, rd1, i;
1925 TCGv_i32 addr;
1926 TCGv_i32 tmp, tmp2, tmp3;
1928 if ((insn & 0x0e000e00) == 0x0c000000) {
1929 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1930 wrd = insn & 0xf;
1931 rdlo = (insn >> 12) & 0xf;
1932 rdhi = (insn >> 16) & 0xf;
1933 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1934 iwmmxt_load_reg(cpu_V0, wrd);
1935 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
1936 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1937 tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
1938 } else { /* TMCRR */
1939 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1940 iwmmxt_store_reg(cpu_V0, wrd);
1941 gen_op_iwmmxt_set_mup();
1943 return 0;
1946 wrd = (insn >> 12) & 0xf;
1947 addr = tcg_temp_new_i32();
1948 if (gen_iwmmxt_address(s, insn, addr)) {
1949 tcg_temp_free_i32(addr);
1950 return 1;
1952 if (insn & ARM_CP_RW_BIT) {
1953 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1954 tmp = tcg_temp_new_i32();
1955 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
1956 iwmmxt_store_creg(wrd, tmp);
1957 } else {
1958 i = 1;
1959 if (insn & (1 << 8)) {
1960 if (insn & (1 << 22)) { /* WLDRD */
1961 gen_aa32_ld64(s, cpu_M0, addr, get_mem_index(s));
1962 i = 0;
1963 } else { /* WLDRW wRd */
1964 tmp = tcg_temp_new_i32();
1965 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
1967 } else {
1968 tmp = tcg_temp_new_i32();
1969 if (insn & (1 << 22)) { /* WLDRH */
1970 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
1971 } else { /* WLDRB */
1972 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
1975 if (i) {
1976 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1977 tcg_temp_free_i32(tmp);
1979 gen_op_iwmmxt_movq_wRn_M0(wrd);
1981 } else {
1982 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1983 tmp = iwmmxt_load_creg(wrd);
1984 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
1985 } else {
1986 gen_op_iwmmxt_movq_M0_wRn(wrd);
1987 tmp = tcg_temp_new_i32();
1988 if (insn & (1 << 8)) {
1989 if (insn & (1 << 22)) { /* WSTRD */
1990 gen_aa32_st64(s, cpu_M0, addr, get_mem_index(s));
1991 } else { /* WSTRW wRd */
1992 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1993 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
1995 } else {
1996 if (insn & (1 << 22)) { /* WSTRH */
1997 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
1998 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
1999 } else { /* WSTRB */
2000 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2001 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
2005 tcg_temp_free_i32(tmp);
2007 tcg_temp_free_i32(addr);
2008 return 0;
2011 if ((insn & 0x0f000000) != 0x0e000000)
2012 return 1;
2014 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
2015 case 0x000: /* WOR */
2016 wrd = (insn >> 12) & 0xf;
2017 rd0 = (insn >> 0) & 0xf;
2018 rd1 = (insn >> 16) & 0xf;
2019 gen_op_iwmmxt_movq_M0_wRn(rd0);
2020 gen_op_iwmmxt_orq_M0_wRn(rd1);
2021 gen_op_iwmmxt_setpsr_nz();
2022 gen_op_iwmmxt_movq_wRn_M0(wrd);
2023 gen_op_iwmmxt_set_mup();
2024 gen_op_iwmmxt_set_cup();
2025 break;
2026 case 0x011: /* TMCR */
2027 if (insn & 0xf)
2028 return 1;
2029 rd = (insn >> 12) & 0xf;
2030 wrd = (insn >> 16) & 0xf;
2031 switch (wrd) {
2032 case ARM_IWMMXT_wCID:
2033 case ARM_IWMMXT_wCASF:
2034 break;
2035 case ARM_IWMMXT_wCon:
2036 gen_op_iwmmxt_set_cup();
2037 /* Fall through. */
2038 case ARM_IWMMXT_wCSSF:
2039 tmp = iwmmxt_load_creg(wrd);
2040 tmp2 = load_reg(s, rd);
2041 tcg_gen_andc_i32(tmp, tmp, tmp2);
2042 tcg_temp_free_i32(tmp2);
2043 iwmmxt_store_creg(wrd, tmp);
2044 break;
2045 case ARM_IWMMXT_wCGR0:
2046 case ARM_IWMMXT_wCGR1:
2047 case ARM_IWMMXT_wCGR2:
2048 case ARM_IWMMXT_wCGR3:
2049 gen_op_iwmmxt_set_cup();
2050 tmp = load_reg(s, rd);
2051 iwmmxt_store_creg(wrd, tmp);
2052 break;
2053 default:
2054 return 1;
2056 break;
2057 case 0x100: /* WXOR */
2058 wrd = (insn >> 12) & 0xf;
2059 rd0 = (insn >> 0) & 0xf;
2060 rd1 = (insn >> 16) & 0xf;
2061 gen_op_iwmmxt_movq_M0_wRn(rd0);
2062 gen_op_iwmmxt_xorq_M0_wRn(rd1);
2063 gen_op_iwmmxt_setpsr_nz();
2064 gen_op_iwmmxt_movq_wRn_M0(wrd);
2065 gen_op_iwmmxt_set_mup();
2066 gen_op_iwmmxt_set_cup();
2067 break;
2068 case 0x111: /* TMRC */
2069 if (insn & 0xf)
2070 return 1;
2071 rd = (insn >> 12) & 0xf;
2072 wrd = (insn >> 16) & 0xf;
2073 tmp = iwmmxt_load_creg(wrd);
2074 store_reg(s, rd, tmp);
2075 break;
2076 case 0x300: /* WANDN */
2077 wrd = (insn >> 12) & 0xf;
2078 rd0 = (insn >> 0) & 0xf;
2079 rd1 = (insn >> 16) & 0xf;
2080 gen_op_iwmmxt_movq_M0_wRn(rd0);
2081 tcg_gen_neg_i64(cpu_M0, cpu_M0);
2082 gen_op_iwmmxt_andq_M0_wRn(rd1);
2083 gen_op_iwmmxt_setpsr_nz();
2084 gen_op_iwmmxt_movq_wRn_M0(wrd);
2085 gen_op_iwmmxt_set_mup();
2086 gen_op_iwmmxt_set_cup();
2087 break;
2088 case 0x200: /* WAND */
2089 wrd = (insn >> 12) & 0xf;
2090 rd0 = (insn >> 0) & 0xf;
2091 rd1 = (insn >> 16) & 0xf;
2092 gen_op_iwmmxt_movq_M0_wRn(rd0);
2093 gen_op_iwmmxt_andq_M0_wRn(rd1);
2094 gen_op_iwmmxt_setpsr_nz();
2095 gen_op_iwmmxt_movq_wRn_M0(wrd);
2096 gen_op_iwmmxt_set_mup();
2097 gen_op_iwmmxt_set_cup();
2098 break;
2099 case 0x810: case 0xa10: /* WMADD */
2100 wrd = (insn >> 12) & 0xf;
2101 rd0 = (insn >> 0) & 0xf;
2102 rd1 = (insn >> 16) & 0xf;
2103 gen_op_iwmmxt_movq_M0_wRn(rd0);
2104 if (insn & (1 << 21))
2105 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
2106 else
2107 gen_op_iwmmxt_madduq_M0_wRn(rd1);
2108 gen_op_iwmmxt_movq_wRn_M0(wrd);
2109 gen_op_iwmmxt_set_mup();
2110 break;
2111 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
2112 wrd = (insn >> 12) & 0xf;
2113 rd0 = (insn >> 16) & 0xf;
2114 rd1 = (insn >> 0) & 0xf;
2115 gen_op_iwmmxt_movq_M0_wRn(rd0);
2116 switch ((insn >> 22) & 3) {
2117 case 0:
2118 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
2119 break;
2120 case 1:
2121 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
2122 break;
2123 case 2:
2124 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
2125 break;
2126 case 3:
2127 return 1;
2129 gen_op_iwmmxt_movq_wRn_M0(wrd);
2130 gen_op_iwmmxt_set_mup();
2131 gen_op_iwmmxt_set_cup();
2132 break;
2133 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
2134 wrd = (insn >> 12) & 0xf;
2135 rd0 = (insn >> 16) & 0xf;
2136 rd1 = (insn >> 0) & 0xf;
2137 gen_op_iwmmxt_movq_M0_wRn(rd0);
2138 switch ((insn >> 22) & 3) {
2139 case 0:
2140 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
2141 break;
2142 case 1:
2143 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
2144 break;
2145 case 2:
2146 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
2147 break;
2148 case 3:
2149 return 1;
2151 gen_op_iwmmxt_movq_wRn_M0(wrd);
2152 gen_op_iwmmxt_set_mup();
2153 gen_op_iwmmxt_set_cup();
2154 break;
2155 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
2156 wrd = (insn >> 12) & 0xf;
2157 rd0 = (insn >> 16) & 0xf;
2158 rd1 = (insn >> 0) & 0xf;
2159 gen_op_iwmmxt_movq_M0_wRn(rd0);
2160 if (insn & (1 << 22))
2161 gen_op_iwmmxt_sadw_M0_wRn(rd1);
2162 else
2163 gen_op_iwmmxt_sadb_M0_wRn(rd1);
2164 if (!(insn & (1 << 20)))
2165 gen_op_iwmmxt_addl_M0_wRn(wrd);
2166 gen_op_iwmmxt_movq_wRn_M0(wrd);
2167 gen_op_iwmmxt_set_mup();
2168 break;
2169 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
2170 wrd = (insn >> 12) & 0xf;
2171 rd0 = (insn >> 16) & 0xf;
2172 rd1 = (insn >> 0) & 0xf;
2173 gen_op_iwmmxt_movq_M0_wRn(rd0);
2174 if (insn & (1 << 21)) {
2175 if (insn & (1 << 20))
2176 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
2177 else
2178 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
2179 } else {
2180 if (insn & (1 << 20))
2181 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
2182 else
2183 gen_op_iwmmxt_mululw_M0_wRn(rd1);
2185 gen_op_iwmmxt_movq_wRn_M0(wrd);
2186 gen_op_iwmmxt_set_mup();
2187 break;
2188 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
2189 wrd = (insn >> 12) & 0xf;
2190 rd0 = (insn >> 16) & 0xf;
2191 rd1 = (insn >> 0) & 0xf;
2192 gen_op_iwmmxt_movq_M0_wRn(rd0);
2193 if (insn & (1 << 21))
2194 gen_op_iwmmxt_macsw_M0_wRn(rd1);
2195 else
2196 gen_op_iwmmxt_macuw_M0_wRn(rd1);
2197 if (!(insn & (1 << 20))) {
2198 iwmmxt_load_reg(cpu_V1, wrd);
2199 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
2201 gen_op_iwmmxt_movq_wRn_M0(wrd);
2202 gen_op_iwmmxt_set_mup();
2203 break;
2204 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
2205 wrd = (insn >> 12) & 0xf;
2206 rd0 = (insn >> 16) & 0xf;
2207 rd1 = (insn >> 0) & 0xf;
2208 gen_op_iwmmxt_movq_M0_wRn(rd0);
2209 switch ((insn >> 22) & 3) {
2210 case 0:
2211 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
2212 break;
2213 case 1:
2214 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
2215 break;
2216 case 2:
2217 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
2218 break;
2219 case 3:
2220 return 1;
2222 gen_op_iwmmxt_movq_wRn_M0(wrd);
2223 gen_op_iwmmxt_set_mup();
2224 gen_op_iwmmxt_set_cup();
2225 break;
2226 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
2227 wrd = (insn >> 12) & 0xf;
2228 rd0 = (insn >> 16) & 0xf;
2229 rd1 = (insn >> 0) & 0xf;
2230 gen_op_iwmmxt_movq_M0_wRn(rd0);
2231 if (insn & (1 << 22)) {
2232 if (insn & (1 << 20))
2233 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
2234 else
2235 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
2236 } else {
2237 if (insn & (1 << 20))
2238 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
2239 else
2240 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
2242 gen_op_iwmmxt_movq_wRn_M0(wrd);
2243 gen_op_iwmmxt_set_mup();
2244 gen_op_iwmmxt_set_cup();
2245 break;
2246 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
2247 wrd = (insn >> 12) & 0xf;
2248 rd0 = (insn >> 16) & 0xf;
2249 rd1 = (insn >> 0) & 0xf;
2250 gen_op_iwmmxt_movq_M0_wRn(rd0);
2251 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
2252 tcg_gen_andi_i32(tmp, tmp, 7);
2253 iwmmxt_load_reg(cpu_V1, rd1);
2254 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2255 tcg_temp_free_i32(tmp);
2256 gen_op_iwmmxt_movq_wRn_M0(wrd);
2257 gen_op_iwmmxt_set_mup();
2258 break;
2259 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
2260 if (((insn >> 6) & 3) == 3)
2261 return 1;
2262 rd = (insn >> 12) & 0xf;
2263 wrd = (insn >> 16) & 0xf;
2264 tmp = load_reg(s, rd);
2265 gen_op_iwmmxt_movq_M0_wRn(wrd);
2266 switch ((insn >> 6) & 3) {
2267 case 0:
2268 tmp2 = tcg_const_i32(0xff);
2269 tmp3 = tcg_const_i32((insn & 7) << 3);
2270 break;
2271 case 1:
2272 tmp2 = tcg_const_i32(0xffff);
2273 tmp3 = tcg_const_i32((insn & 3) << 4);
2274 break;
2275 case 2:
2276 tmp2 = tcg_const_i32(0xffffffff);
2277 tmp3 = tcg_const_i32((insn & 1) << 5);
2278 break;
2279 default:
2280 tmp2 = NULL;
2281 tmp3 = NULL;
2283 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
2284 tcg_temp_free_i32(tmp3);
2285 tcg_temp_free_i32(tmp2);
2286 tcg_temp_free_i32(tmp);
2287 gen_op_iwmmxt_movq_wRn_M0(wrd);
2288 gen_op_iwmmxt_set_mup();
2289 break;
2290 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
2291 rd = (insn >> 12) & 0xf;
2292 wrd = (insn >> 16) & 0xf;
2293 if (rd == 15 || ((insn >> 22) & 3) == 3)
2294 return 1;
2295 gen_op_iwmmxt_movq_M0_wRn(wrd);
2296 tmp = tcg_temp_new_i32();
2297 switch ((insn >> 22) & 3) {
2298 case 0:
2299 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
2300 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2301 if (insn & 8) {
2302 tcg_gen_ext8s_i32(tmp, tmp);
2303 } else {
2304 tcg_gen_andi_i32(tmp, tmp, 0xff);
2306 break;
2307 case 1:
2308 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
2309 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2310 if (insn & 8) {
2311 tcg_gen_ext16s_i32(tmp, tmp);
2312 } else {
2313 tcg_gen_andi_i32(tmp, tmp, 0xffff);
2315 break;
2316 case 2:
2317 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
2318 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2319 break;
2321 store_reg(s, rd, tmp);
2322 break;
2323 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
2324 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
2325 return 1;
2326 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
2327 switch ((insn >> 22) & 3) {
2328 case 0:
2329 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
2330 break;
2331 case 1:
2332 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
2333 break;
2334 case 2:
2335 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
2336 break;
2338 tcg_gen_shli_i32(tmp, tmp, 28);
2339 gen_set_nzcv(tmp);
2340 tcg_temp_free_i32(tmp);
2341 break;
2342 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
2343 if (((insn >> 6) & 3) == 3)
2344 return 1;
2345 rd = (insn >> 12) & 0xf;
2346 wrd = (insn >> 16) & 0xf;
2347 tmp = load_reg(s, rd);
2348 switch ((insn >> 6) & 3) {
2349 case 0:
2350 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
2351 break;
2352 case 1:
2353 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
2354 break;
2355 case 2:
2356 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
2357 break;
2359 tcg_temp_free_i32(tmp);
2360 gen_op_iwmmxt_movq_wRn_M0(wrd);
2361 gen_op_iwmmxt_set_mup();
2362 break;
2363 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
2364 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
2365 return 1;
2366 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
2367 tmp2 = tcg_temp_new_i32();
2368 tcg_gen_mov_i32(tmp2, tmp);
2369 switch ((insn >> 22) & 3) {
2370 case 0:
2371 for (i = 0; i < 7; i ++) {
2372 tcg_gen_shli_i32(tmp2, tmp2, 4);
2373 tcg_gen_and_i32(tmp, tmp, tmp2);
2375 break;
2376 case 1:
2377 for (i = 0; i < 3; i ++) {
2378 tcg_gen_shli_i32(tmp2, tmp2, 8);
2379 tcg_gen_and_i32(tmp, tmp, tmp2);
2381 break;
2382 case 2:
2383 tcg_gen_shli_i32(tmp2, tmp2, 16);
2384 tcg_gen_and_i32(tmp, tmp, tmp2);
2385 break;
2387 gen_set_nzcv(tmp);
2388 tcg_temp_free_i32(tmp2);
2389 tcg_temp_free_i32(tmp);
2390 break;
2391 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
2392 wrd = (insn >> 12) & 0xf;
2393 rd0 = (insn >> 16) & 0xf;
2394 gen_op_iwmmxt_movq_M0_wRn(rd0);
2395 switch ((insn >> 22) & 3) {
2396 case 0:
2397 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
2398 break;
2399 case 1:
2400 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
2401 break;
2402 case 2:
2403 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
2404 break;
2405 case 3:
2406 return 1;
2408 gen_op_iwmmxt_movq_wRn_M0(wrd);
2409 gen_op_iwmmxt_set_mup();
2410 break;
2411 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
2412 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
2413 return 1;
2414 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
2415 tmp2 = tcg_temp_new_i32();
2416 tcg_gen_mov_i32(tmp2, tmp);
2417 switch ((insn >> 22) & 3) {
2418 case 0:
2419 for (i = 0; i < 7; i ++) {
2420 tcg_gen_shli_i32(tmp2, tmp2, 4);
2421 tcg_gen_or_i32(tmp, tmp, tmp2);
2423 break;
2424 case 1:
2425 for (i = 0; i < 3; i ++) {
2426 tcg_gen_shli_i32(tmp2, tmp2, 8);
2427 tcg_gen_or_i32(tmp, tmp, tmp2);
2429 break;
2430 case 2:
2431 tcg_gen_shli_i32(tmp2, tmp2, 16);
2432 tcg_gen_or_i32(tmp, tmp, tmp2);
2433 break;
2435 gen_set_nzcv(tmp);
2436 tcg_temp_free_i32(tmp2);
2437 tcg_temp_free_i32(tmp);
2438 break;
2439 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
2440 rd = (insn >> 12) & 0xf;
2441 rd0 = (insn >> 16) & 0xf;
2442 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
2443 return 1;
2444 gen_op_iwmmxt_movq_M0_wRn(rd0);
2445 tmp = tcg_temp_new_i32();
2446 switch ((insn >> 22) & 3) {
2447 case 0:
2448 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
2449 break;
2450 case 1:
2451 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
2452 break;
2453 case 2:
2454 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
2455 break;
2457 store_reg(s, rd, tmp);
2458 break;
2459 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
2460 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2461 wrd = (insn >> 12) & 0xf;
2462 rd0 = (insn >> 16) & 0xf;
2463 rd1 = (insn >> 0) & 0xf;
2464 gen_op_iwmmxt_movq_M0_wRn(rd0);
2465 switch ((insn >> 22) & 3) {
2466 case 0:
2467 if (insn & (1 << 21))
2468 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2469 else
2470 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2471 break;
2472 case 1:
2473 if (insn & (1 << 21))
2474 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2475 else
2476 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2477 break;
2478 case 2:
2479 if (insn & (1 << 21))
2480 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2481 else
2482 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2483 break;
2484 case 3:
2485 return 1;
2487 gen_op_iwmmxt_movq_wRn_M0(wrd);
2488 gen_op_iwmmxt_set_mup();
2489 gen_op_iwmmxt_set_cup();
2490 break;
2491 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2492 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2493 wrd = (insn >> 12) & 0xf;
2494 rd0 = (insn >> 16) & 0xf;
2495 gen_op_iwmmxt_movq_M0_wRn(rd0);
2496 switch ((insn >> 22) & 3) {
2497 case 0:
2498 if (insn & (1 << 21))
2499 gen_op_iwmmxt_unpacklsb_M0();
2500 else
2501 gen_op_iwmmxt_unpacklub_M0();
2502 break;
2503 case 1:
2504 if (insn & (1 << 21))
2505 gen_op_iwmmxt_unpacklsw_M0();
2506 else
2507 gen_op_iwmmxt_unpackluw_M0();
2508 break;
2509 case 2:
2510 if (insn & (1 << 21))
2511 gen_op_iwmmxt_unpacklsl_M0();
2512 else
2513 gen_op_iwmmxt_unpacklul_M0();
2514 break;
2515 case 3:
2516 return 1;
2518 gen_op_iwmmxt_movq_wRn_M0(wrd);
2519 gen_op_iwmmxt_set_mup();
2520 gen_op_iwmmxt_set_cup();
2521 break;
2522 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2523 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2524 wrd = (insn >> 12) & 0xf;
2525 rd0 = (insn >> 16) & 0xf;
2526 gen_op_iwmmxt_movq_M0_wRn(rd0);
2527 switch ((insn >> 22) & 3) {
2528 case 0:
2529 if (insn & (1 << 21))
2530 gen_op_iwmmxt_unpackhsb_M0();
2531 else
2532 gen_op_iwmmxt_unpackhub_M0();
2533 break;
2534 case 1:
2535 if (insn & (1 << 21))
2536 gen_op_iwmmxt_unpackhsw_M0();
2537 else
2538 gen_op_iwmmxt_unpackhuw_M0();
2539 break;
2540 case 2:
2541 if (insn & (1 << 21))
2542 gen_op_iwmmxt_unpackhsl_M0();
2543 else
2544 gen_op_iwmmxt_unpackhul_M0();
2545 break;
2546 case 3:
2547 return 1;
2549 gen_op_iwmmxt_movq_wRn_M0(wrd);
2550 gen_op_iwmmxt_set_mup();
2551 gen_op_iwmmxt_set_cup();
2552 break;
2553 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2554 case 0x214: case 0x614: case 0xa14: case 0xe14:
2555 if (((insn >> 22) & 3) == 0)
2556 return 1;
2557 wrd = (insn >> 12) & 0xf;
2558 rd0 = (insn >> 16) & 0xf;
2559 gen_op_iwmmxt_movq_M0_wRn(rd0);
2560 tmp = tcg_temp_new_i32();
2561 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2562 tcg_temp_free_i32(tmp);
2563 return 1;
2565 switch ((insn >> 22) & 3) {
2566 case 1:
2567 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
2568 break;
2569 case 2:
2570 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
2571 break;
2572 case 3:
2573 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
2574 break;
2576 tcg_temp_free_i32(tmp);
2577 gen_op_iwmmxt_movq_wRn_M0(wrd);
2578 gen_op_iwmmxt_set_mup();
2579 gen_op_iwmmxt_set_cup();
2580 break;
2581 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2582 case 0x014: case 0x414: case 0x814: case 0xc14:
2583 if (((insn >> 22) & 3) == 0)
2584 return 1;
2585 wrd = (insn >> 12) & 0xf;
2586 rd0 = (insn >> 16) & 0xf;
2587 gen_op_iwmmxt_movq_M0_wRn(rd0);
2588 tmp = tcg_temp_new_i32();
2589 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2590 tcg_temp_free_i32(tmp);
2591 return 1;
2593 switch ((insn >> 22) & 3) {
2594 case 1:
2595 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2596 break;
2597 case 2:
2598 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2599 break;
2600 case 3:
2601 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2602 break;
2604 tcg_temp_free_i32(tmp);
2605 gen_op_iwmmxt_movq_wRn_M0(wrd);
2606 gen_op_iwmmxt_set_mup();
2607 gen_op_iwmmxt_set_cup();
2608 break;
2609 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2610 case 0x114: case 0x514: case 0x914: case 0xd14:
2611 if (((insn >> 22) & 3) == 0)
2612 return 1;
2613 wrd = (insn >> 12) & 0xf;
2614 rd0 = (insn >> 16) & 0xf;
2615 gen_op_iwmmxt_movq_M0_wRn(rd0);
2616 tmp = tcg_temp_new_i32();
2617 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2618 tcg_temp_free_i32(tmp);
2619 return 1;
2621 switch ((insn >> 22) & 3) {
2622 case 1:
2623 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2624 break;
2625 case 2:
2626 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2627 break;
2628 case 3:
2629 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2630 break;
2632 tcg_temp_free_i32(tmp);
2633 gen_op_iwmmxt_movq_wRn_M0(wrd);
2634 gen_op_iwmmxt_set_mup();
2635 gen_op_iwmmxt_set_cup();
2636 break;
2637 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2638 case 0x314: case 0x714: case 0xb14: case 0xf14:
2639 if (((insn >> 22) & 3) == 0)
2640 return 1;
2641 wrd = (insn >> 12) & 0xf;
2642 rd0 = (insn >> 16) & 0xf;
2643 gen_op_iwmmxt_movq_M0_wRn(rd0);
2644 tmp = tcg_temp_new_i32();
2645 switch ((insn >> 22) & 3) {
2646 case 1:
2647 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2648 tcg_temp_free_i32(tmp);
2649 return 1;
2651 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2652 break;
2653 case 2:
2654 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2655 tcg_temp_free_i32(tmp);
2656 return 1;
2658 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2659 break;
2660 case 3:
2661 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2662 tcg_temp_free_i32(tmp);
2663 return 1;
2665 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2666 break;
2668 tcg_temp_free_i32(tmp);
2669 gen_op_iwmmxt_movq_wRn_M0(wrd);
2670 gen_op_iwmmxt_set_mup();
2671 gen_op_iwmmxt_set_cup();
2672 break;
2673 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2674 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2675 wrd = (insn >> 12) & 0xf;
2676 rd0 = (insn >> 16) & 0xf;
2677 rd1 = (insn >> 0) & 0xf;
2678 gen_op_iwmmxt_movq_M0_wRn(rd0);
2679 switch ((insn >> 22) & 3) {
2680 case 0:
2681 if (insn & (1 << 21))
2682 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2683 else
2684 gen_op_iwmmxt_minub_M0_wRn(rd1);
2685 break;
2686 case 1:
2687 if (insn & (1 << 21))
2688 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2689 else
2690 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2691 break;
2692 case 2:
2693 if (insn & (1 << 21))
2694 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2695 else
2696 gen_op_iwmmxt_minul_M0_wRn(rd1);
2697 break;
2698 case 3:
2699 return 1;
2701 gen_op_iwmmxt_movq_wRn_M0(wrd);
2702 gen_op_iwmmxt_set_mup();
2703 break;
2704 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2705 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2706 wrd = (insn >> 12) & 0xf;
2707 rd0 = (insn >> 16) & 0xf;
2708 rd1 = (insn >> 0) & 0xf;
2709 gen_op_iwmmxt_movq_M0_wRn(rd0);
2710 switch ((insn >> 22) & 3) {
2711 case 0:
2712 if (insn & (1 << 21))
2713 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2714 else
2715 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2716 break;
2717 case 1:
2718 if (insn & (1 << 21))
2719 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2720 else
2721 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2722 break;
2723 case 2:
2724 if (insn & (1 << 21))
2725 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2726 else
2727 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2728 break;
2729 case 3:
2730 return 1;
2732 gen_op_iwmmxt_movq_wRn_M0(wrd);
2733 gen_op_iwmmxt_set_mup();
2734 break;
2735 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2736 case 0x402: case 0x502: case 0x602: case 0x702:
2737 wrd = (insn >> 12) & 0xf;
2738 rd0 = (insn >> 16) & 0xf;
2739 rd1 = (insn >> 0) & 0xf;
2740 gen_op_iwmmxt_movq_M0_wRn(rd0);
2741 tmp = tcg_const_i32((insn >> 20) & 3);
2742 iwmmxt_load_reg(cpu_V1, rd1);
2743 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2744 tcg_temp_free_i32(tmp);
2745 gen_op_iwmmxt_movq_wRn_M0(wrd);
2746 gen_op_iwmmxt_set_mup();
2747 break;
2748 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2749 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2750 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2751 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2752 wrd = (insn >> 12) & 0xf;
2753 rd0 = (insn >> 16) & 0xf;
2754 rd1 = (insn >> 0) & 0xf;
2755 gen_op_iwmmxt_movq_M0_wRn(rd0);
2756 switch ((insn >> 20) & 0xf) {
2757 case 0x0:
2758 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2759 break;
2760 case 0x1:
2761 gen_op_iwmmxt_subub_M0_wRn(rd1);
2762 break;
2763 case 0x3:
2764 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2765 break;
2766 case 0x4:
2767 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2768 break;
2769 case 0x5:
2770 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2771 break;
2772 case 0x7:
2773 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2774 break;
2775 case 0x8:
2776 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2777 break;
2778 case 0x9:
2779 gen_op_iwmmxt_subul_M0_wRn(rd1);
2780 break;
2781 case 0xb:
2782 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2783 break;
2784 default:
2785 return 1;
2787 gen_op_iwmmxt_movq_wRn_M0(wrd);
2788 gen_op_iwmmxt_set_mup();
2789 gen_op_iwmmxt_set_cup();
2790 break;
2791 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2792 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2793 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2794 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2795 wrd = (insn >> 12) & 0xf;
2796 rd0 = (insn >> 16) & 0xf;
2797 gen_op_iwmmxt_movq_M0_wRn(rd0);
2798 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2799 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2800 tcg_temp_free_i32(tmp);
2801 gen_op_iwmmxt_movq_wRn_M0(wrd);
2802 gen_op_iwmmxt_set_mup();
2803 gen_op_iwmmxt_set_cup();
2804 break;
2805 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2806 case 0x418: case 0x518: case 0x618: case 0x718:
2807 case 0x818: case 0x918: case 0xa18: case 0xb18:
2808 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2809 wrd = (insn >> 12) & 0xf;
2810 rd0 = (insn >> 16) & 0xf;
2811 rd1 = (insn >> 0) & 0xf;
2812 gen_op_iwmmxt_movq_M0_wRn(rd0);
2813 switch ((insn >> 20) & 0xf) {
2814 case 0x0:
2815 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2816 break;
2817 case 0x1:
2818 gen_op_iwmmxt_addub_M0_wRn(rd1);
2819 break;
2820 case 0x3:
2821 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2822 break;
2823 case 0x4:
2824 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2825 break;
2826 case 0x5:
2827 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2828 break;
2829 case 0x7:
2830 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2831 break;
2832 case 0x8:
2833 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2834 break;
2835 case 0x9:
2836 gen_op_iwmmxt_addul_M0_wRn(rd1);
2837 break;
2838 case 0xb:
2839 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2840 break;
2841 default:
2842 return 1;
2844 gen_op_iwmmxt_movq_wRn_M0(wrd);
2845 gen_op_iwmmxt_set_mup();
2846 gen_op_iwmmxt_set_cup();
2847 break;
2848 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2849 case 0x408: case 0x508: case 0x608: case 0x708:
2850 case 0x808: case 0x908: case 0xa08: case 0xb08:
2851 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2852 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2853 return 1;
2854 wrd = (insn >> 12) & 0xf;
2855 rd0 = (insn >> 16) & 0xf;
2856 rd1 = (insn >> 0) & 0xf;
2857 gen_op_iwmmxt_movq_M0_wRn(rd0);
2858 switch ((insn >> 22) & 3) {
2859 case 1:
2860 if (insn & (1 << 21))
2861 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2862 else
2863 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2864 break;
2865 case 2:
2866 if (insn & (1 << 21))
2867 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2868 else
2869 gen_op_iwmmxt_packul_M0_wRn(rd1);
2870 break;
2871 case 3:
2872 if (insn & (1 << 21))
2873 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2874 else
2875 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2876 break;
2878 gen_op_iwmmxt_movq_wRn_M0(wrd);
2879 gen_op_iwmmxt_set_mup();
2880 gen_op_iwmmxt_set_cup();
2881 break;
2882 case 0x201: case 0x203: case 0x205: case 0x207:
2883 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2884 case 0x211: case 0x213: case 0x215: case 0x217:
2885 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2886 wrd = (insn >> 5) & 0xf;
2887 rd0 = (insn >> 12) & 0xf;
2888 rd1 = (insn >> 0) & 0xf;
2889 if (rd0 == 0xf || rd1 == 0xf)
2890 return 1;
2891 gen_op_iwmmxt_movq_M0_wRn(wrd);
2892 tmp = load_reg(s, rd0);
2893 tmp2 = load_reg(s, rd1);
2894 switch ((insn >> 16) & 0xf) {
2895 case 0x0: /* TMIA */
2896 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2897 break;
2898 case 0x8: /* TMIAPH */
2899 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2900 break;
2901 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2902 if (insn & (1 << 16))
2903 tcg_gen_shri_i32(tmp, tmp, 16);
2904 if (insn & (1 << 17))
2905 tcg_gen_shri_i32(tmp2, tmp2, 16);
2906 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2907 break;
2908 default:
2909 tcg_temp_free_i32(tmp2);
2910 tcg_temp_free_i32(tmp);
2911 return 1;
2913 tcg_temp_free_i32(tmp2);
2914 tcg_temp_free_i32(tmp);
2915 gen_op_iwmmxt_movq_wRn_M0(wrd);
2916 gen_op_iwmmxt_set_mup();
2917 break;
2918 default:
2919 return 1;
2922 return 0;
2925 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
2926 (ie. an undefined instruction). */
2927 static int disas_dsp_insn(DisasContext *s, uint32_t insn)
2929 int acc, rd0, rd1, rdhi, rdlo;
2930 TCGv_i32 tmp, tmp2;
2932 if ((insn & 0x0ff00f10) == 0x0e200010) {
2933 /* Multiply with Internal Accumulate Format */
2934 rd0 = (insn >> 12) & 0xf;
2935 rd1 = insn & 0xf;
2936 acc = (insn >> 5) & 7;
2938 if (acc != 0)
2939 return 1;
2941 tmp = load_reg(s, rd0);
2942 tmp2 = load_reg(s, rd1);
2943 switch ((insn >> 16) & 0xf) {
2944 case 0x0: /* MIA */
2945 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2946 break;
2947 case 0x8: /* MIAPH */
2948 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2949 break;
2950 case 0xc: /* MIABB */
2951 case 0xd: /* MIABT */
2952 case 0xe: /* MIATB */
2953 case 0xf: /* MIATT */
2954 if (insn & (1 << 16))
2955 tcg_gen_shri_i32(tmp, tmp, 16);
2956 if (insn & (1 << 17))
2957 tcg_gen_shri_i32(tmp2, tmp2, 16);
2958 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2959 break;
2960 default:
2961 return 1;
2963 tcg_temp_free_i32(tmp2);
2964 tcg_temp_free_i32(tmp);
2966 gen_op_iwmmxt_movq_wRn_M0(acc);
2967 return 0;
2970 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2971 /* Internal Accumulator Access Format */
2972 rdhi = (insn >> 16) & 0xf;
2973 rdlo = (insn >> 12) & 0xf;
2974 acc = insn & 7;
2976 if (acc != 0)
2977 return 1;
2979 if (insn & ARM_CP_RW_BIT) { /* MRA */
2980 iwmmxt_load_reg(cpu_V0, acc);
2981 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
2982 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
2983 tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
2984 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2985 } else { /* MAR */
2986 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2987 iwmmxt_store_reg(cpu_V0, acc);
2989 return 0;
2992 return 1;
2995 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2996 #define VFP_SREG(insn, bigbit, smallbit) \
2997 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2998 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2999 if (arm_dc_feature(s, ARM_FEATURE_VFP3)) { \
3000 reg = (((insn) >> (bigbit)) & 0x0f) \
3001 | (((insn) >> ((smallbit) - 4)) & 0x10); \
3002 } else { \
3003 if (insn & (1 << (smallbit))) \
3004 return 1; \
3005 reg = ((insn) >> (bigbit)) & 0x0f; \
3006 }} while (0)
3008 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
3009 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
3010 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
3011 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
3012 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
3013 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
3015 /* Move between integer and VFP cores. */
3016 static TCGv_i32 gen_vfp_mrs(void)
3018 TCGv_i32 tmp = tcg_temp_new_i32();
3019 tcg_gen_mov_i32(tmp, cpu_F0s);
3020 return tmp;
3023 static void gen_vfp_msr(TCGv_i32 tmp)
3025 tcg_gen_mov_i32(cpu_F0s, tmp);
3026 tcg_temp_free_i32(tmp);
3029 static void gen_neon_dup_low16(TCGv_i32 var)
3031 TCGv_i32 tmp = tcg_temp_new_i32();
3032 tcg_gen_ext16u_i32(var, var);
3033 tcg_gen_shli_i32(tmp, var, 16);
3034 tcg_gen_or_i32(var, var, tmp);
3035 tcg_temp_free_i32(tmp);
3038 static void gen_neon_dup_high16(TCGv_i32 var)
3040 TCGv_i32 tmp = tcg_temp_new_i32();
3041 tcg_gen_andi_i32(var, var, 0xffff0000);
3042 tcg_gen_shri_i32(tmp, var, 16);
3043 tcg_gen_or_i32(var, var, tmp);
3044 tcg_temp_free_i32(tmp);
3048 * Disassemble a VFP instruction. Returns nonzero if an error occurred
3049 * (ie. an undefined instruction).
3051 static int disas_vfp_insn(DisasContext *s, uint32_t insn)
3053 uint32_t rd, rn, rm, op, i, n, delta_d, delta_m, bank_mask;
3054 int dp, veclen;
3055 TCGv_i32 tmp;
3056 TCGv_i32 tmp2;
3058 if (!arm_dc_feature(s, ARM_FEATURE_VFP)) {
3059 return 1;
3063 * If the decodetree decoder handles this insn it will always
3064 * emit code to either execute the insn or generate an appropriate
3065 * exception; so we don't need to ever return non-zero to tell
3066 * the calling code to emit an UNDEF exception.
3068 if (extract32(insn, 28, 4) == 0xf) {
3069 if (disas_vfp_uncond(s, insn)) {
3070 return 0;
3072 } else {
3073 if (disas_vfp(s, insn)) {
3074 return 0;
3078 if (extract32(insn, 28, 4) == 0xf) {
3080 * Encodings with T=1 (Thumb) or unconditional (ARM): these
3081 * were all handled by the decodetree decoder, so any insn
3082 * patterns which get here must be UNDEF.
3084 return 1;
3088 * FIXME: this access check should not take precedence over UNDEF
3089 * for invalid encodings; we will generate incorrect syndrome information
3090 * for attempts to execute invalid vfp/neon encodings with FP disabled.
3092 if (!vfp_access_check(s)) {
3093 return 0;
3096 dp = ((insn & 0xf00) == 0xb00);
3097 switch ((insn >> 24) & 0xf) {
3098 case 0xe:
3099 if (insn & (1 << 4)) {
3100 /* already handled by decodetree */
3101 return 1;
3102 } else {
3103 /* data processing */
3104 bool rd_is_dp = dp;
3105 bool rm_is_dp = dp;
3106 bool no_output = false;
3108 /* The opcode is in bits 23, 21, 20 and 6. */
3109 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
3110 rn = VFP_SREG_N(insn);
3112 switch (op) {
3113 case 0 ... 6:
3114 /* Already handled by decodetree */
3115 return 1;
3116 default:
3117 break;
3120 if (op == 15) {
3121 /* rn is opcode, encoded as per VFP_SREG_N. */
3122 switch (rn) {
3123 case 0x00: /* vmov */
3124 case 0x01: /* vabs */
3125 case 0x02: /* vneg */
3126 case 0x03: /* vsqrt */
3127 break;
3129 case 0x04: /* vcvtb.f64.f16, vcvtb.f32.f16 */
3130 case 0x05: /* vcvtt.f64.f16, vcvtt.f32.f16 */
3132 * VCVTB, VCVTT: only present with the halfprec extension
3133 * UNPREDICTABLE if bit 8 is set prior to ARMv8
3134 * (we choose to UNDEF)
3136 if (dp) {
3137 if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
3138 return 1;
3140 } else {
3141 if (!dc_isar_feature(aa32_fp16_spconv, s)) {
3142 return 1;
3145 rm_is_dp = false;
3146 break;
3147 case 0x06: /* vcvtb.f16.f32, vcvtb.f16.f64 */
3148 case 0x07: /* vcvtt.f16.f32, vcvtt.f16.f64 */
3149 if (dp) {
3150 if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
3151 return 1;
3153 } else {
3154 if (!dc_isar_feature(aa32_fp16_spconv, s)) {
3155 return 1;
3158 rd_is_dp = false;
3159 break;
3161 case 0x08: case 0x0a: /* vcmp, vcmpz */
3162 case 0x09: case 0x0b: /* vcmpe, vcmpez */
3163 no_output = true;
3164 break;
3166 case 0x0c: /* vrintr */
3167 case 0x0d: /* vrintz */
3168 case 0x0e: /* vrintx */
3169 break;
3171 case 0x0f: /* vcvt double<->single */
3172 rd_is_dp = !dp;
3173 break;
3175 case 0x10: /* vcvt.fxx.u32 */
3176 case 0x11: /* vcvt.fxx.s32 */
3177 rm_is_dp = false;
3178 break;
3179 case 0x18: /* vcvtr.u32.fxx */
3180 case 0x19: /* vcvtz.u32.fxx */
3181 case 0x1a: /* vcvtr.s32.fxx */
3182 case 0x1b: /* vcvtz.s32.fxx */
3183 rd_is_dp = false;
3184 break;
3186 case 0x14: /* vcvt fp <-> fixed */
3187 case 0x15:
3188 case 0x16:
3189 case 0x17:
3190 case 0x1c:
3191 case 0x1d:
3192 case 0x1e:
3193 case 0x1f:
3194 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3195 return 1;
3197 /* Immediate frac_bits has same format as SREG_M. */
3198 rm_is_dp = false;
3199 break;
3201 case 0x13: /* vjcvt */
3202 if (!dp || !dc_isar_feature(aa32_jscvt, s)) {
3203 return 1;
3205 rd_is_dp = false;
3206 break;
3208 default:
3209 return 1;
3211 } else if (dp) {
3212 /* rn is register number */
3213 VFP_DREG_N(rn, insn);
3216 if (rd_is_dp) {
3217 VFP_DREG_D(rd, insn);
3218 } else {
3219 rd = VFP_SREG_D(insn);
3221 if (rm_is_dp) {
3222 VFP_DREG_M(rm, insn);
3223 } else {
3224 rm = VFP_SREG_M(insn);
3227 veclen = s->vec_len;
3228 if (op == 15 && rn > 3) {
3229 veclen = 0;
3232 /* Shut up compiler warnings. */
3233 delta_m = 0;
3234 delta_d = 0;
3235 bank_mask = 0;
3237 if (veclen > 0) {
3238 if (dp)
3239 bank_mask = 0xc;
3240 else
3241 bank_mask = 0x18;
3243 /* Figure out what type of vector operation this is. */
3244 if ((rd & bank_mask) == 0) {
3245 /* scalar */
3246 veclen = 0;
3247 } else {
3248 if (dp)
3249 delta_d = (s->vec_stride >> 1) + 1;
3250 else
3251 delta_d = s->vec_stride + 1;
3253 if ((rm & bank_mask) == 0) {
3254 /* mixed scalar/vector */
3255 delta_m = 0;
3256 } else {
3257 /* vector */
3258 delta_m = delta_d;
3263 /* Load the initial operands. */
3264 if (op == 15) {
3265 switch (rn) {
3266 case 0x08: case 0x09: /* Compare */
3267 gen_mov_F0_vreg(dp, rd);
3268 gen_mov_F1_vreg(dp, rm);
3269 break;
3270 case 0x0a: case 0x0b: /* Compare with zero */
3271 gen_mov_F0_vreg(dp, rd);
3272 gen_vfp_F1_ld0(dp);
3273 break;
3274 case 0x14: /* vcvt fp <-> fixed */
3275 case 0x15:
3276 case 0x16:
3277 case 0x17:
3278 case 0x1c:
3279 case 0x1d:
3280 case 0x1e:
3281 case 0x1f:
3282 /* Source and destination the same. */
3283 gen_mov_F0_vreg(dp, rd);
3284 break;
3285 default:
3286 /* One source operand. */
3287 gen_mov_F0_vreg(rm_is_dp, rm);
3288 break;
3290 } else {
3291 /* Two source operands. */
3292 gen_mov_F0_vreg(dp, rn);
3293 gen_mov_F1_vreg(dp, rm);
3296 for (;;) {
3297 /* Perform the calculation. */
3298 switch (op) {
3299 case 7: /* sub: fn - fm */
3300 gen_vfp_sub(dp);
3301 break;
3302 case 8: /* div: fn / fm */
3303 gen_vfp_div(dp);
3304 break;
3305 case 10: /* VFNMA : fd = muladd(-fd, fn, fm) */
3306 case 11: /* VFNMS : fd = muladd(-fd, -fn, fm) */
3307 case 12: /* VFMA : fd = muladd( fd, fn, fm) */
3308 case 13: /* VFMS : fd = muladd( fd, -fn, fm) */
3309 /* These are fused multiply-add, and must be done as one
3310 * floating point operation with no rounding between the
3311 * multiplication and addition steps.
3312 * NB that doing the negations here as separate steps is
3313 * correct : an input NaN should come out with its sign bit
3314 * flipped if it is a negated-input.
3316 if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
3317 return 1;
3319 if (dp) {
3320 TCGv_ptr fpst;
3321 TCGv_i64 frd;
3322 if (op & 1) {
3323 /* VFNMS, VFMS */
3324 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
3326 frd = tcg_temp_new_i64();
3327 tcg_gen_ld_f64(frd, cpu_env, vfp_reg_offset(dp, rd));
3328 if (op & 2) {
3329 /* VFNMA, VFNMS */
3330 gen_helper_vfp_negd(frd, frd);
3332 fpst = get_fpstatus_ptr(0);
3333 gen_helper_vfp_muladdd(cpu_F0d, cpu_F0d,
3334 cpu_F1d, frd, fpst);
3335 tcg_temp_free_ptr(fpst);
3336 tcg_temp_free_i64(frd);
3337 } else {
3338 TCGv_ptr fpst;
3339 TCGv_i32 frd;
3340 if (op & 1) {
3341 /* VFNMS, VFMS */
3342 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
3344 frd = tcg_temp_new_i32();
3345 tcg_gen_ld_f32(frd, cpu_env, vfp_reg_offset(dp, rd));
3346 if (op & 2) {
3347 gen_helper_vfp_negs(frd, frd);
3349 fpst = get_fpstatus_ptr(0);
3350 gen_helper_vfp_muladds(cpu_F0s, cpu_F0s,
3351 cpu_F1s, frd, fpst);
3352 tcg_temp_free_ptr(fpst);
3353 tcg_temp_free_i32(frd);
3355 break;
3356 case 14: /* fconst */
3357 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3358 return 1;
3361 n = (insn << 12) & 0x80000000;
3362 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3363 if (dp) {
3364 if (i & 0x40)
3365 i |= 0x3f80;
3366 else
3367 i |= 0x4000;
3368 n |= i << 16;
3369 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3370 } else {
3371 if (i & 0x40)
3372 i |= 0x780;
3373 else
3374 i |= 0x800;
3375 n |= i << 19;
3376 tcg_gen_movi_i32(cpu_F0s, n);
3378 break;
3379 case 15: /* extension space */
3380 switch (rn) {
3381 case 0: /* cpy */
3382 /* no-op */
3383 break;
3384 case 1: /* abs */
3385 gen_vfp_abs(dp);
3386 break;
3387 case 2: /* neg */
3388 gen_vfp_neg(dp);
3389 break;
3390 case 3: /* sqrt */
3391 gen_vfp_sqrt(dp);
3392 break;
3393 case 4: /* vcvtb.f32.f16, vcvtb.f64.f16 */
3395 TCGv_ptr fpst = get_fpstatus_ptr(false);
3396 TCGv_i32 ahp_mode = get_ahp_flag();
3397 tmp = gen_vfp_mrs();
3398 tcg_gen_ext16u_i32(tmp, tmp);
3399 if (dp) {
3400 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
3401 fpst, ahp_mode);
3402 } else {
3403 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
3404 fpst, ahp_mode);
3406 tcg_temp_free_i32(ahp_mode);
3407 tcg_temp_free_ptr(fpst);
3408 tcg_temp_free_i32(tmp);
3409 break;
3411 case 5: /* vcvtt.f32.f16, vcvtt.f64.f16 */
3413 TCGv_ptr fpst = get_fpstatus_ptr(false);
3414 TCGv_i32 ahp = get_ahp_flag();
3415 tmp = gen_vfp_mrs();
3416 tcg_gen_shri_i32(tmp, tmp, 16);
3417 if (dp) {
3418 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
3419 fpst, ahp);
3420 } else {
3421 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
3422 fpst, ahp);
3424 tcg_temp_free_i32(tmp);
3425 tcg_temp_free_i32(ahp);
3426 tcg_temp_free_ptr(fpst);
3427 break;
3429 case 6: /* vcvtb.f16.f32, vcvtb.f16.f64 */
3431 TCGv_ptr fpst = get_fpstatus_ptr(false);
3432 TCGv_i32 ahp = get_ahp_flag();
3433 tmp = tcg_temp_new_i32();
3435 if (dp) {
3436 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
3437 fpst, ahp);
3438 } else {
3439 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
3440 fpst, ahp);
3442 tcg_temp_free_i32(ahp);
3443 tcg_temp_free_ptr(fpst);
3444 gen_mov_F0_vreg(0, rd);
3445 tmp2 = gen_vfp_mrs();
3446 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3447 tcg_gen_or_i32(tmp, tmp, tmp2);
3448 tcg_temp_free_i32(tmp2);
3449 gen_vfp_msr(tmp);
3450 break;
3452 case 7: /* vcvtt.f16.f32, vcvtt.f16.f64 */
3454 TCGv_ptr fpst = get_fpstatus_ptr(false);
3455 TCGv_i32 ahp = get_ahp_flag();
3456 tmp = tcg_temp_new_i32();
3457 if (dp) {
3458 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
3459 fpst, ahp);
3460 } else {
3461 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
3462 fpst, ahp);
3464 tcg_temp_free_i32(ahp);
3465 tcg_temp_free_ptr(fpst);
3466 tcg_gen_shli_i32(tmp, tmp, 16);
3467 gen_mov_F0_vreg(0, rd);
3468 tmp2 = gen_vfp_mrs();
3469 tcg_gen_ext16u_i32(tmp2, tmp2);
3470 tcg_gen_or_i32(tmp, tmp, tmp2);
3471 tcg_temp_free_i32(tmp2);
3472 gen_vfp_msr(tmp);
3473 break;
3475 case 8: /* cmp */
3476 gen_vfp_cmp(dp);
3477 break;
3478 case 9: /* cmpe */
3479 gen_vfp_cmpe(dp);
3480 break;
3481 case 10: /* cmpz */
3482 gen_vfp_cmp(dp);
3483 break;
3484 case 11: /* cmpez */
3485 gen_vfp_F1_ld0(dp);
3486 gen_vfp_cmpe(dp);
3487 break;
3488 case 12: /* vrintr */
3490 TCGv_ptr fpst = get_fpstatus_ptr(0);
3491 if (dp) {
3492 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
3493 } else {
3494 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
3496 tcg_temp_free_ptr(fpst);
3497 break;
3499 case 13: /* vrintz */
3501 TCGv_ptr fpst = get_fpstatus_ptr(0);
3502 TCGv_i32 tcg_rmode;
3503 tcg_rmode = tcg_const_i32(float_round_to_zero);
3504 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
3505 if (dp) {
3506 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
3507 } else {
3508 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
3510 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
3511 tcg_temp_free_i32(tcg_rmode);
3512 tcg_temp_free_ptr(fpst);
3513 break;
3515 case 14: /* vrintx */
3517 TCGv_ptr fpst = get_fpstatus_ptr(0);
3518 if (dp) {
3519 gen_helper_rintd_exact(cpu_F0d, cpu_F0d, fpst);
3520 } else {
3521 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpst);
3523 tcg_temp_free_ptr(fpst);
3524 break;
3526 case 15: /* single<->double conversion */
3527 if (dp) {
3528 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3529 } else {
3530 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3532 break;
3533 case 16: /* fuito */
3534 gen_vfp_uito(dp, 0);
3535 break;
3536 case 17: /* fsito */
3537 gen_vfp_sito(dp, 0);
3538 break;
3539 case 19: /* vjcvt */
3540 gen_helper_vjcvt(cpu_F0s, cpu_F0d, cpu_env);
3541 break;
3542 case 20: /* fshto */
3543 gen_vfp_shto(dp, 16 - rm, 0);
3544 break;
3545 case 21: /* fslto */
3546 gen_vfp_slto(dp, 32 - rm, 0);
3547 break;
3548 case 22: /* fuhto */
3549 gen_vfp_uhto(dp, 16 - rm, 0);
3550 break;
3551 case 23: /* fulto */
3552 gen_vfp_ulto(dp, 32 - rm, 0);
3553 break;
3554 case 24: /* ftoui */
3555 gen_vfp_toui(dp, 0);
3556 break;
3557 case 25: /* ftouiz */
3558 gen_vfp_touiz(dp, 0);
3559 break;
3560 case 26: /* ftosi */
3561 gen_vfp_tosi(dp, 0);
3562 break;
3563 case 27: /* ftosiz */
3564 gen_vfp_tosiz(dp, 0);
3565 break;
3566 case 28: /* ftosh */
3567 gen_vfp_tosh(dp, 16 - rm, 0);
3568 break;
3569 case 29: /* ftosl */
3570 gen_vfp_tosl(dp, 32 - rm, 0);
3571 break;
3572 case 30: /* ftouh */
3573 gen_vfp_touh(dp, 16 - rm, 0);
3574 break;
3575 case 31: /* ftoul */
3576 gen_vfp_toul(dp, 32 - rm, 0);
3577 break;
3578 default: /* undefined */
3579 g_assert_not_reached();
3581 break;
3582 default: /* undefined */
3583 return 1;
3586 /* Write back the result, if any. */
3587 if (!no_output) {
3588 gen_mov_vreg_F0(rd_is_dp, rd);
3591 /* break out of the loop if we have finished */
3592 if (veclen == 0) {
3593 break;
3596 if (op == 15 && delta_m == 0) {
3597 /* single source one-many */
3598 while (veclen--) {
3599 rd = ((rd + delta_d) & (bank_mask - 1))
3600 | (rd & bank_mask);
3601 gen_mov_vreg_F0(dp, rd);
3603 break;
3605 /* Setup the next operands. */
3606 veclen--;
3607 rd = ((rd + delta_d) & (bank_mask - 1))
3608 | (rd & bank_mask);
3610 if (op == 15) {
3611 /* One source operand. */
3612 rm = ((rm + delta_m) & (bank_mask - 1))
3613 | (rm & bank_mask);
3614 gen_mov_F0_vreg(dp, rm);
3615 } else {
3616 /* Two source operands. */
3617 rn = ((rn + delta_d) & (bank_mask - 1))
3618 | (rn & bank_mask);
3619 gen_mov_F0_vreg(dp, rn);
3620 if (delta_m) {
3621 rm = ((rm + delta_m) & (bank_mask - 1))
3622 | (rm & bank_mask);
3623 gen_mov_F1_vreg(dp, rm);
3628 break;
3629 case 0xc:
3630 case 0xd:
3631 /* Already handled by decodetree */
3632 return 1;
3633 default:
3634 /* Should never happen. */
3635 return 1;
3637 return 0;
3640 static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
3642 #ifndef CONFIG_USER_ONLY
3643 return (s->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
3644 ((s->pc - 1) & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
3645 #else
3646 return true;
3647 #endif
3650 static void gen_goto_ptr(void)
3652 tcg_gen_lookup_and_goto_ptr();
3655 /* This will end the TB but doesn't guarantee we'll return to
3656 * cpu_loop_exec. Any live exit_requests will be processed as we
3657 * enter the next TB.
3659 static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
3661 if (use_goto_tb(s, dest)) {
3662 tcg_gen_goto_tb(n);
3663 gen_set_pc_im(s, dest);
3664 tcg_gen_exit_tb(s->base.tb, n);
3665 } else {
3666 gen_set_pc_im(s, dest);
3667 gen_goto_ptr();
3669 s->base.is_jmp = DISAS_NORETURN;
3672 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3674 if (unlikely(is_singlestepping(s))) {
3675 /* An indirect jump so that we still trigger the debug exception. */
3676 if (s->thumb)
3677 dest |= 1;
3678 gen_bx_im(s, dest);
3679 } else {
3680 gen_goto_tb(s, 0, dest);
3684 static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
3686 if (x)
3687 tcg_gen_sari_i32(t0, t0, 16);
3688 else
3689 gen_sxth(t0);
3690 if (y)
3691 tcg_gen_sari_i32(t1, t1, 16);
3692 else
3693 gen_sxth(t1);
3694 tcg_gen_mul_i32(t0, t0, t1);
3697 /* Return the mask of PSR bits set by a MSR instruction. */
3698 static uint32_t msr_mask(DisasContext *s, int flags, int spsr)
3700 uint32_t mask;
3702 mask = 0;
3703 if (flags & (1 << 0))
3704 mask |= 0xff;
3705 if (flags & (1 << 1))
3706 mask |= 0xff00;
3707 if (flags & (1 << 2))
3708 mask |= 0xff0000;
3709 if (flags & (1 << 3))
3710 mask |= 0xff000000;
3712 /* Mask out undefined bits. */
3713 mask &= ~CPSR_RESERVED;
3714 if (!arm_dc_feature(s, ARM_FEATURE_V4T)) {
3715 mask &= ~CPSR_T;
3717 if (!arm_dc_feature(s, ARM_FEATURE_V5)) {
3718 mask &= ~CPSR_Q; /* V5TE in reality*/
3720 if (!arm_dc_feature(s, ARM_FEATURE_V6)) {
3721 mask &= ~(CPSR_E | CPSR_GE);
3723 if (!arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
3724 mask &= ~CPSR_IT;
3726 /* Mask out execution state and reserved bits. */
3727 if (!spsr) {
3728 mask &= ~(CPSR_EXEC | CPSR_RESERVED);
3730 /* Mask out privileged bits. */
3731 if (IS_USER(s))
3732 mask &= CPSR_USER;
3733 return mask;
3736 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3737 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
3739 TCGv_i32 tmp;
3740 if (spsr) {
3741 /* ??? This is also undefined in system mode. */
3742 if (IS_USER(s))
3743 return 1;
3745 tmp = load_cpu_field(spsr);
3746 tcg_gen_andi_i32(tmp, tmp, ~mask);
3747 tcg_gen_andi_i32(t0, t0, mask);
3748 tcg_gen_or_i32(tmp, tmp, t0);
3749 store_cpu_field(tmp, spsr);
3750 } else {
3751 gen_set_cpsr(t0, mask);
3753 tcg_temp_free_i32(t0);
3754 gen_lookup_tb(s);
3755 return 0;
3758 /* Returns nonzero if access to the PSR is not permitted. */
3759 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3761 TCGv_i32 tmp;
3762 tmp = tcg_temp_new_i32();
3763 tcg_gen_movi_i32(tmp, val);
3764 return gen_set_psr(s, mask, spsr, tmp);
3767 static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
3768 int *tgtmode, int *regno)
3770 /* Decode the r and sysm fields of MSR/MRS banked accesses into
3771 * the target mode and register number, and identify the various
3772 * unpredictable cases.
3773 * MSR (banked) and MRS (banked) are CONSTRAINED UNPREDICTABLE if:
3774 * + executed in user mode
3775 * + using R15 as the src/dest register
3776 * + accessing an unimplemented register
3777 * + accessing a register that's inaccessible at current PL/security state*
3778 * + accessing a register that you could access with a different insn
3779 * We choose to UNDEF in all these cases.
3780 * Since we don't know which of the various AArch32 modes we are in
3781 * we have to defer some checks to runtime.
3782 * Accesses to Monitor mode registers from Secure EL1 (which implies
3783 * that EL3 is AArch64) must trap to EL3.
3785 * If the access checks fail this function will emit code to take
3786 * an exception and return false. Otherwise it will return true,
3787 * and set *tgtmode and *regno appropriately.
3789 int exc_target = default_exception_el(s);
3791 /* These instructions are present only in ARMv8, or in ARMv7 with the
3792 * Virtualization Extensions.
3794 if (!arm_dc_feature(s, ARM_FEATURE_V8) &&
3795 !arm_dc_feature(s, ARM_FEATURE_EL2)) {
3796 goto undef;
3799 if (IS_USER(s) || rn == 15) {
3800 goto undef;
3803 /* The table in the v8 ARM ARM section F5.2.3 describes the encoding
3804 * of registers into (r, sysm).
3806 if (r) {
3807 /* SPSRs for other modes */
3808 switch (sysm) {
3809 case 0xe: /* SPSR_fiq */
3810 *tgtmode = ARM_CPU_MODE_FIQ;
3811 break;
3812 case 0x10: /* SPSR_irq */
3813 *tgtmode = ARM_CPU_MODE_IRQ;
3814 break;
3815 case 0x12: /* SPSR_svc */
3816 *tgtmode = ARM_CPU_MODE_SVC;
3817 break;
3818 case 0x14: /* SPSR_abt */
3819 *tgtmode = ARM_CPU_MODE_ABT;
3820 break;
3821 case 0x16: /* SPSR_und */
3822 *tgtmode = ARM_CPU_MODE_UND;
3823 break;
3824 case 0x1c: /* SPSR_mon */
3825 *tgtmode = ARM_CPU_MODE_MON;
3826 break;
3827 case 0x1e: /* SPSR_hyp */
3828 *tgtmode = ARM_CPU_MODE_HYP;
3829 break;
3830 default: /* unallocated */
3831 goto undef;
3833 /* We arbitrarily assign SPSR a register number of 16. */
3834 *regno = 16;
3835 } else {
3836 /* general purpose registers for other modes */
3837 switch (sysm) {
3838 case 0x0 ... 0x6: /* 0b00xxx : r8_usr ... r14_usr */
3839 *tgtmode = ARM_CPU_MODE_USR;
3840 *regno = sysm + 8;
3841 break;
3842 case 0x8 ... 0xe: /* 0b01xxx : r8_fiq ... r14_fiq */
3843 *tgtmode = ARM_CPU_MODE_FIQ;
3844 *regno = sysm;
3845 break;
3846 case 0x10 ... 0x11: /* 0b1000x : r14_irq, r13_irq */
3847 *tgtmode = ARM_CPU_MODE_IRQ;
3848 *regno = sysm & 1 ? 13 : 14;
3849 break;
3850 case 0x12 ... 0x13: /* 0b1001x : r14_svc, r13_svc */
3851 *tgtmode = ARM_CPU_MODE_SVC;
3852 *regno = sysm & 1 ? 13 : 14;
3853 break;
3854 case 0x14 ... 0x15: /* 0b1010x : r14_abt, r13_abt */
3855 *tgtmode = ARM_CPU_MODE_ABT;
3856 *regno = sysm & 1 ? 13 : 14;
3857 break;
3858 case 0x16 ... 0x17: /* 0b1011x : r14_und, r13_und */
3859 *tgtmode = ARM_CPU_MODE_UND;
3860 *regno = sysm & 1 ? 13 : 14;
3861 break;
3862 case 0x1c ... 0x1d: /* 0b1110x : r14_mon, r13_mon */
3863 *tgtmode = ARM_CPU_MODE_MON;
3864 *regno = sysm & 1 ? 13 : 14;
3865 break;
3866 case 0x1e ... 0x1f: /* 0b1111x : elr_hyp, r13_hyp */
3867 *tgtmode = ARM_CPU_MODE_HYP;
3868 /* Arbitrarily pick 17 for ELR_Hyp (which is not a banked LR!) */
3869 *regno = sysm & 1 ? 13 : 17;
3870 break;
3871 default: /* unallocated */
3872 goto undef;
3876 /* Catch the 'accessing inaccessible register' cases we can detect
3877 * at translate time.
3879 switch (*tgtmode) {
3880 case ARM_CPU_MODE_MON:
3881 if (!arm_dc_feature(s, ARM_FEATURE_EL3) || s->ns) {
3882 goto undef;
3884 if (s->current_el == 1) {
3885 /* If we're in Secure EL1 (which implies that EL3 is AArch64)
3886 * then accesses to Mon registers trap to EL3
3888 exc_target = 3;
3889 goto undef;
3891 break;
3892 case ARM_CPU_MODE_HYP:
3894 * SPSR_hyp and r13_hyp can only be accessed from Monitor mode
3895 * (and so we can forbid accesses from EL2 or below). elr_hyp
3896 * can be accessed also from Hyp mode, so forbid accesses from
3897 * EL0 or EL1.
3899 if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el < 2 ||
3900 (s->current_el < 3 && *regno != 17)) {
3901 goto undef;
3903 break;
3904 default:
3905 break;
3908 return true;
3910 undef:
3911 /* If we get here then some access check did not pass */
3912 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), exc_target);
3913 return false;
3916 static void gen_msr_banked(DisasContext *s, int r, int sysm, int rn)
3918 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
3919 int tgtmode = 0, regno = 0;
3921 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
3922 return;
3925 /* Sync state because msr_banked() can raise exceptions */
3926 gen_set_condexec(s);
3927 gen_set_pc_im(s, s->pc - 4);
3928 tcg_reg = load_reg(s, rn);
3929 tcg_tgtmode = tcg_const_i32(tgtmode);
3930 tcg_regno = tcg_const_i32(regno);
3931 gen_helper_msr_banked(cpu_env, tcg_reg, tcg_tgtmode, tcg_regno);
3932 tcg_temp_free_i32(tcg_tgtmode);
3933 tcg_temp_free_i32(tcg_regno);
3934 tcg_temp_free_i32(tcg_reg);
3935 s->base.is_jmp = DISAS_UPDATE;
3938 static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn)
3940 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
3941 int tgtmode = 0, regno = 0;
3943 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
3944 return;
3947 /* Sync state because mrs_banked() can raise exceptions */
3948 gen_set_condexec(s);
3949 gen_set_pc_im(s, s->pc - 4);
3950 tcg_reg = tcg_temp_new_i32();
3951 tcg_tgtmode = tcg_const_i32(tgtmode);
3952 tcg_regno = tcg_const_i32(regno);
3953 gen_helper_mrs_banked(tcg_reg, cpu_env, tcg_tgtmode, tcg_regno);
3954 tcg_temp_free_i32(tcg_tgtmode);
3955 tcg_temp_free_i32(tcg_regno);
3956 store_reg(s, rn, tcg_reg);
3957 s->base.is_jmp = DISAS_UPDATE;
3960 /* Store value to PC as for an exception return (ie don't
3961 * mask bits). The subsequent call to gen_helper_cpsr_write_eret()
3962 * will do the masking based on the new value of the Thumb bit.
3964 static void store_pc_exc_ret(DisasContext *s, TCGv_i32 pc)
3966 tcg_gen_mov_i32(cpu_R[15], pc);
3967 tcg_temp_free_i32(pc);
3970 /* Generate a v6 exception return. Marks both values as dead. */
3971 static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
3973 store_pc_exc_ret(s, pc);
3974 /* The cpsr_write_eret helper will mask the low bits of PC
3975 * appropriately depending on the new Thumb bit, so it must
3976 * be called after storing the new PC.
3978 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
3979 gen_io_start();
3981 gen_helper_cpsr_write_eret(cpu_env, cpsr);
3982 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
3983 gen_io_end();
3985 tcg_temp_free_i32(cpsr);
3986 /* Must exit loop to check un-masked IRQs */
3987 s->base.is_jmp = DISAS_EXIT;
3990 /* Generate an old-style exception return. Marks pc as dead. */
3991 static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
3993 gen_rfe(s, pc, load_cpu_field(spsr));
3997 * For WFI we will halt the vCPU until an IRQ. For WFE and YIELD we
3998 * only call the helper when running single threaded TCG code to ensure
3999 * the next round-robin scheduled vCPU gets a crack. In MTTCG mode we
4000 * just skip this instruction. Currently the SEV/SEVL instructions
4001 * which are *one* of many ways to wake the CPU from WFE are not
4002 * implemented so we can't sleep like WFI does.
4004 static void gen_nop_hint(DisasContext *s, int val)
4006 switch (val) {
4007 /* When running in MTTCG we don't generate jumps to the yield and
4008 * WFE helpers as it won't affect the scheduling of other vCPUs.
4009 * If we wanted to more completely model WFE/SEV so we don't busy
4010 * spin unnecessarily we would need to do something more involved.
4012 case 1: /* yield */
4013 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
4014 gen_set_pc_im(s, s->pc);
4015 s->base.is_jmp = DISAS_YIELD;
4017 break;
4018 case 3: /* wfi */
4019 gen_set_pc_im(s, s->pc);
4020 s->base.is_jmp = DISAS_WFI;
4021 break;
4022 case 2: /* wfe */
4023 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
4024 gen_set_pc_im(s, s->pc);
4025 s->base.is_jmp = DISAS_WFE;
4027 break;
4028 case 4: /* sev */
4029 case 5: /* sevl */
4030 /* TODO: Implement SEV, SEVL and WFE. May help SMP performance. */
4031 default: /* nop */
4032 break;
4036 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
4038 static inline void gen_neon_add(int size, TCGv_i32 t0, TCGv_i32 t1)
4040 switch (size) {
4041 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
4042 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
4043 case 2: tcg_gen_add_i32(t0, t0, t1); break;
4044 default: abort();
4048 static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
4050 switch (size) {
4051 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
4052 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
4053 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
4054 default: return;
4058 /* 32-bit pairwise ops end up the same as the elementwise versions. */
4059 #define gen_helper_neon_pmax_s32 tcg_gen_smax_i32
4060 #define gen_helper_neon_pmax_u32 tcg_gen_umax_i32
4061 #define gen_helper_neon_pmin_s32 tcg_gen_smin_i32
4062 #define gen_helper_neon_pmin_u32 tcg_gen_umin_i32
4064 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
4065 switch ((size << 1) | u) { \
4066 case 0: \
4067 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
4068 break; \
4069 case 1: \
4070 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
4071 break; \
4072 case 2: \
4073 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
4074 break; \
4075 case 3: \
4076 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
4077 break; \
4078 case 4: \
4079 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
4080 break; \
4081 case 5: \
4082 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
4083 break; \
4084 default: return 1; \
4085 }} while (0)
4087 #define GEN_NEON_INTEGER_OP(name) do { \
4088 switch ((size << 1) | u) { \
4089 case 0: \
4090 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
4091 break; \
4092 case 1: \
4093 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
4094 break; \
4095 case 2: \
4096 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
4097 break; \
4098 case 3: \
4099 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
4100 break; \
4101 case 4: \
4102 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
4103 break; \
4104 case 5: \
4105 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
4106 break; \
4107 default: return 1; \
4108 }} while (0)
4110 static TCGv_i32 neon_load_scratch(int scratch)
4112 TCGv_i32 tmp = tcg_temp_new_i32();
4113 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
4114 return tmp;
4117 static void neon_store_scratch(int scratch, TCGv_i32 var)
4119 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
4120 tcg_temp_free_i32(var);
4123 static inline TCGv_i32 neon_get_scalar(int size, int reg)
4125 TCGv_i32 tmp;
4126 if (size == 1) {
4127 tmp = neon_load_reg(reg & 7, reg >> 4);
4128 if (reg & 8) {
4129 gen_neon_dup_high16(tmp);
4130 } else {
4131 gen_neon_dup_low16(tmp);
4133 } else {
4134 tmp = neon_load_reg(reg & 15, reg >> 4);
4136 return tmp;
4139 static int gen_neon_unzip(int rd, int rm, int size, int q)
4141 TCGv_ptr pd, pm;
4143 if (!q && size == 2) {
4144 return 1;
4146 pd = vfp_reg_ptr(true, rd);
4147 pm = vfp_reg_ptr(true, rm);
4148 if (q) {
4149 switch (size) {
4150 case 0:
4151 gen_helper_neon_qunzip8(pd, pm);
4152 break;
4153 case 1:
4154 gen_helper_neon_qunzip16(pd, pm);
4155 break;
4156 case 2:
4157 gen_helper_neon_qunzip32(pd, pm);
4158 break;
4159 default:
4160 abort();
4162 } else {
4163 switch (size) {
4164 case 0:
4165 gen_helper_neon_unzip8(pd, pm);
4166 break;
4167 case 1:
4168 gen_helper_neon_unzip16(pd, pm);
4169 break;
4170 default:
4171 abort();
4174 tcg_temp_free_ptr(pd);
4175 tcg_temp_free_ptr(pm);
4176 return 0;
4179 static int gen_neon_zip(int rd, int rm, int size, int q)
4181 TCGv_ptr pd, pm;
4183 if (!q && size == 2) {
4184 return 1;
4186 pd = vfp_reg_ptr(true, rd);
4187 pm = vfp_reg_ptr(true, rm);
4188 if (q) {
4189 switch (size) {
4190 case 0:
4191 gen_helper_neon_qzip8(pd, pm);
4192 break;
4193 case 1:
4194 gen_helper_neon_qzip16(pd, pm);
4195 break;
4196 case 2:
4197 gen_helper_neon_qzip32(pd, pm);
4198 break;
4199 default:
4200 abort();
4202 } else {
4203 switch (size) {
4204 case 0:
4205 gen_helper_neon_zip8(pd, pm);
4206 break;
4207 case 1:
4208 gen_helper_neon_zip16(pd, pm);
4209 break;
4210 default:
4211 abort();
4214 tcg_temp_free_ptr(pd);
4215 tcg_temp_free_ptr(pm);
4216 return 0;
4219 static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
4221 TCGv_i32 rd, tmp;
4223 rd = tcg_temp_new_i32();
4224 tmp = tcg_temp_new_i32();
4226 tcg_gen_shli_i32(rd, t0, 8);
4227 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
4228 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
4229 tcg_gen_or_i32(rd, rd, tmp);
4231 tcg_gen_shri_i32(t1, t1, 8);
4232 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
4233 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
4234 tcg_gen_or_i32(t1, t1, tmp);
4235 tcg_gen_mov_i32(t0, rd);
4237 tcg_temp_free_i32(tmp);
4238 tcg_temp_free_i32(rd);
4241 static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
4243 TCGv_i32 rd, tmp;
4245 rd = tcg_temp_new_i32();
4246 tmp = tcg_temp_new_i32();
4248 tcg_gen_shli_i32(rd, t0, 16);
4249 tcg_gen_andi_i32(tmp, t1, 0xffff);
4250 tcg_gen_or_i32(rd, rd, tmp);
4251 tcg_gen_shri_i32(t1, t1, 16);
4252 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
4253 tcg_gen_or_i32(t1, t1, tmp);
4254 tcg_gen_mov_i32(t0, rd);
4256 tcg_temp_free_i32(tmp);
4257 tcg_temp_free_i32(rd);
4261 static struct {
4262 int nregs;
4263 int interleave;
4264 int spacing;
4265 } const neon_ls_element_type[11] = {
4266 {1, 4, 1},
4267 {1, 4, 2},
4268 {4, 1, 1},
4269 {2, 2, 2},
4270 {1, 3, 1},
4271 {1, 3, 2},
4272 {3, 1, 1},
4273 {1, 1, 1},
4274 {1, 2, 1},
4275 {1, 2, 2},
4276 {2, 1, 1}
4279 /* Translate a NEON load/store element instruction. Return nonzero if the
4280 instruction is invalid. */
4281 static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
4283 int rd, rn, rm;
4284 int op;
4285 int nregs;
4286 int interleave;
4287 int spacing;
4288 int stride;
4289 int size;
4290 int reg;
4291 int load;
4292 int n;
4293 int vec_size;
4294 int mmu_idx;
4295 TCGMemOp endian;
4296 TCGv_i32 addr;
4297 TCGv_i32 tmp;
4298 TCGv_i32 tmp2;
4299 TCGv_i64 tmp64;
4301 /* FIXME: this access check should not take precedence over UNDEF
4302 * for invalid encodings; we will generate incorrect syndrome information
4303 * for attempts to execute invalid vfp/neon encodings with FP disabled.
4305 if (s->fp_excp_el) {
4306 gen_exception_insn(s, 4, EXCP_UDEF,
4307 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
4308 return 0;
4311 if (!s->vfp_enabled)
4312 return 1;
4313 VFP_DREG_D(rd, insn);
4314 rn = (insn >> 16) & 0xf;
4315 rm = insn & 0xf;
4316 load = (insn & (1 << 21)) != 0;
4317 endian = s->be_data;
4318 mmu_idx = get_mem_index(s);
4319 if ((insn & (1 << 23)) == 0) {
4320 /* Load store all elements. */
4321 op = (insn >> 8) & 0xf;
4322 size = (insn >> 6) & 3;
4323 if (op > 10)
4324 return 1;
4325 /* Catch UNDEF cases for bad values of align field */
4326 switch (op & 0xc) {
4327 case 4:
4328 if (((insn >> 5) & 1) == 1) {
4329 return 1;
4331 break;
4332 case 8:
4333 if (((insn >> 4) & 3) == 3) {
4334 return 1;
4336 break;
4337 default:
4338 break;
4340 nregs = neon_ls_element_type[op].nregs;
4341 interleave = neon_ls_element_type[op].interleave;
4342 spacing = neon_ls_element_type[op].spacing;
4343 if (size == 3 && (interleave | spacing) != 1) {
4344 return 1;
4346 /* For our purposes, bytes are always little-endian. */
4347 if (size == 0) {
4348 endian = MO_LE;
4350 /* Consecutive little-endian elements from a single register
4351 * can be promoted to a larger little-endian operation.
4353 if (interleave == 1 && endian == MO_LE) {
4354 size = 3;
4356 tmp64 = tcg_temp_new_i64();
4357 addr = tcg_temp_new_i32();
4358 tmp2 = tcg_const_i32(1 << size);
4359 load_reg_var(s, addr, rn);
4360 for (reg = 0; reg < nregs; reg++) {
4361 for (n = 0; n < 8 >> size; n++) {
4362 int xs;
4363 for (xs = 0; xs < interleave; xs++) {
4364 int tt = rd + reg + spacing * xs;
4366 if (load) {
4367 gen_aa32_ld_i64(s, tmp64, addr, mmu_idx, endian | size);
4368 neon_store_element64(tt, n, size, tmp64);
4369 } else {
4370 neon_load_element64(tmp64, tt, n, size);
4371 gen_aa32_st_i64(s, tmp64, addr, mmu_idx, endian | size);
4373 tcg_gen_add_i32(addr, addr, tmp2);
4377 tcg_temp_free_i32(addr);
4378 tcg_temp_free_i32(tmp2);
4379 tcg_temp_free_i64(tmp64);
4380 stride = nregs * interleave * 8;
4381 } else {
4382 size = (insn >> 10) & 3;
4383 if (size == 3) {
4384 /* Load single element to all lanes. */
4385 int a = (insn >> 4) & 1;
4386 if (!load) {
4387 return 1;
4389 size = (insn >> 6) & 3;
4390 nregs = ((insn >> 8) & 3) + 1;
4392 if (size == 3) {
4393 if (nregs != 4 || a == 0) {
4394 return 1;
4396 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
4397 size = 2;
4399 if (nregs == 1 && a == 1 && size == 0) {
4400 return 1;
4402 if (nregs == 3 && a == 1) {
4403 return 1;
4405 addr = tcg_temp_new_i32();
4406 load_reg_var(s, addr, rn);
4408 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write.
4409 * VLD2/3/4 to all lanes: bit 5 indicates register stride.
4411 stride = (insn & (1 << 5)) ? 2 : 1;
4412 vec_size = nregs == 1 ? stride * 8 : 8;
4414 tmp = tcg_temp_new_i32();
4415 for (reg = 0; reg < nregs; reg++) {
4416 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
4417 s->be_data | size);
4418 if ((rd & 1) && vec_size == 16) {
4419 /* We cannot write 16 bytes at once because the
4420 * destination is unaligned.
4422 tcg_gen_gvec_dup_i32(size, neon_reg_offset(rd, 0),
4423 8, 8, tmp);
4424 tcg_gen_gvec_mov(0, neon_reg_offset(rd + 1, 0),
4425 neon_reg_offset(rd, 0), 8, 8);
4426 } else {
4427 tcg_gen_gvec_dup_i32(size, neon_reg_offset(rd, 0),
4428 vec_size, vec_size, tmp);
4430 tcg_gen_addi_i32(addr, addr, 1 << size);
4431 rd += stride;
4433 tcg_temp_free_i32(tmp);
4434 tcg_temp_free_i32(addr);
4435 stride = (1 << size) * nregs;
4436 } else {
4437 /* Single element. */
4438 int idx = (insn >> 4) & 0xf;
4439 int reg_idx;
4440 switch (size) {
4441 case 0:
4442 reg_idx = (insn >> 5) & 7;
4443 stride = 1;
4444 break;
4445 case 1:
4446 reg_idx = (insn >> 6) & 3;
4447 stride = (insn & (1 << 5)) ? 2 : 1;
4448 break;
4449 case 2:
4450 reg_idx = (insn >> 7) & 1;
4451 stride = (insn & (1 << 6)) ? 2 : 1;
4452 break;
4453 default:
4454 abort();
4456 nregs = ((insn >> 8) & 3) + 1;
4457 /* Catch the UNDEF cases. This is unavoidably a bit messy. */
4458 switch (nregs) {
4459 case 1:
4460 if (((idx & (1 << size)) != 0) ||
4461 (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
4462 return 1;
4464 break;
4465 case 3:
4466 if ((idx & 1) != 0) {
4467 return 1;
4469 /* fall through */
4470 case 2:
4471 if (size == 2 && (idx & 2) != 0) {
4472 return 1;
4474 break;
4475 case 4:
4476 if ((size == 2) && ((idx & 3) == 3)) {
4477 return 1;
4479 break;
4480 default:
4481 abort();
4483 if ((rd + stride * (nregs - 1)) > 31) {
4484 /* Attempts to write off the end of the register file
4485 * are UNPREDICTABLE; we choose to UNDEF because otherwise
4486 * the neon_load_reg() would write off the end of the array.
4488 return 1;
4490 tmp = tcg_temp_new_i32();
4491 addr = tcg_temp_new_i32();
4492 load_reg_var(s, addr, rn);
4493 for (reg = 0; reg < nregs; reg++) {
4494 if (load) {
4495 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
4496 s->be_data | size);
4497 neon_store_element(rd, reg_idx, size, tmp);
4498 } else { /* Store */
4499 neon_load_element(tmp, rd, reg_idx, size);
4500 gen_aa32_st_i32(s, tmp, addr, get_mem_index(s),
4501 s->be_data | size);
4503 rd += stride;
4504 tcg_gen_addi_i32(addr, addr, 1 << size);
4506 tcg_temp_free_i32(addr);
4507 tcg_temp_free_i32(tmp);
4508 stride = nregs * (1 << size);
4511 if (rm != 15) {
4512 TCGv_i32 base;
4514 base = load_reg(s, rn);
4515 if (rm == 13) {
4516 tcg_gen_addi_i32(base, base, stride);
4517 } else {
4518 TCGv_i32 index;
4519 index = load_reg(s, rm);
4520 tcg_gen_add_i32(base, base, index);
4521 tcg_temp_free_i32(index);
4523 store_reg(s, rn, base);
4525 return 0;
4528 static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src)
4530 switch (size) {
4531 case 0: gen_helper_neon_narrow_u8(dest, src); break;
4532 case 1: gen_helper_neon_narrow_u16(dest, src); break;
4533 case 2: tcg_gen_extrl_i64_i32(dest, src); break;
4534 default: abort();
4538 static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
4540 switch (size) {
4541 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
4542 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
4543 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
4544 default: abort();
4548 static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src)
4550 switch (size) {
4551 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
4552 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
4553 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
4554 default: abort();
4558 static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
4560 switch (size) {
4561 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
4562 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
4563 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
4564 default: abort();
4568 static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift,
4569 int q, int u)
4571 if (q) {
4572 if (u) {
4573 switch (size) {
4574 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4575 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4576 default: abort();
4578 } else {
4579 switch (size) {
4580 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
4581 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
4582 default: abort();
4585 } else {
4586 if (u) {
4587 switch (size) {
4588 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
4589 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
4590 default: abort();
4592 } else {
4593 switch (size) {
4594 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
4595 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
4596 default: abort();
4602 static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
4604 if (u) {
4605 switch (size) {
4606 case 0: gen_helper_neon_widen_u8(dest, src); break;
4607 case 1: gen_helper_neon_widen_u16(dest, src); break;
4608 case 2: tcg_gen_extu_i32_i64(dest, src); break;
4609 default: abort();
4611 } else {
4612 switch (size) {
4613 case 0: gen_helper_neon_widen_s8(dest, src); break;
4614 case 1: gen_helper_neon_widen_s16(dest, src); break;
4615 case 2: tcg_gen_ext_i32_i64(dest, src); break;
4616 default: abort();
4619 tcg_temp_free_i32(src);
4622 static inline void gen_neon_addl(int size)
4624 switch (size) {
4625 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4626 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4627 case 2: tcg_gen_add_i64(CPU_V001); break;
4628 default: abort();
4632 static inline void gen_neon_subl(int size)
4634 switch (size) {
4635 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4636 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4637 case 2: tcg_gen_sub_i64(CPU_V001); break;
4638 default: abort();
4642 static inline void gen_neon_negl(TCGv_i64 var, int size)
4644 switch (size) {
4645 case 0: gen_helper_neon_negl_u16(var, var); break;
4646 case 1: gen_helper_neon_negl_u32(var, var); break;
4647 case 2:
4648 tcg_gen_neg_i64(var, var);
4649 break;
4650 default: abort();
4654 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4656 switch (size) {
4657 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4658 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4659 default: abort();
4663 static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b,
4664 int size, int u)
4666 TCGv_i64 tmp;
4668 switch ((size << 1) | u) {
4669 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4670 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4671 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4672 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4673 case 4:
4674 tmp = gen_muls_i64_i32(a, b);
4675 tcg_gen_mov_i64(dest, tmp);
4676 tcg_temp_free_i64(tmp);
4677 break;
4678 case 5:
4679 tmp = gen_mulu_i64_i32(a, b);
4680 tcg_gen_mov_i64(dest, tmp);
4681 tcg_temp_free_i64(tmp);
4682 break;
4683 default: abort();
4686 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
4687 Don't forget to clean them now. */
4688 if (size < 2) {
4689 tcg_temp_free_i32(a);
4690 tcg_temp_free_i32(b);
4694 static void gen_neon_narrow_op(int op, int u, int size,
4695 TCGv_i32 dest, TCGv_i64 src)
4697 if (op) {
4698 if (u) {
4699 gen_neon_unarrow_sats(size, dest, src);
4700 } else {
4701 gen_neon_narrow(size, dest, src);
4703 } else {
4704 if (u) {
4705 gen_neon_narrow_satu(size, dest, src);
4706 } else {
4707 gen_neon_narrow_sats(size, dest, src);
4712 /* Symbolic constants for op fields for Neon 3-register same-length.
4713 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
4714 * table A7-9.
4716 #define NEON_3R_VHADD 0
4717 #define NEON_3R_VQADD 1
4718 #define NEON_3R_VRHADD 2
4719 #define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
4720 #define NEON_3R_VHSUB 4
4721 #define NEON_3R_VQSUB 5
4722 #define NEON_3R_VCGT 6
4723 #define NEON_3R_VCGE 7
4724 #define NEON_3R_VSHL 8
4725 #define NEON_3R_VQSHL 9
4726 #define NEON_3R_VRSHL 10
4727 #define NEON_3R_VQRSHL 11
4728 #define NEON_3R_VMAX 12
4729 #define NEON_3R_VMIN 13
4730 #define NEON_3R_VABD 14
4731 #define NEON_3R_VABA 15
4732 #define NEON_3R_VADD_VSUB 16
4733 #define NEON_3R_VTST_VCEQ 17
4734 #define NEON_3R_VML 18 /* VMLA, VMLS */
4735 #define NEON_3R_VMUL 19
4736 #define NEON_3R_VPMAX 20
4737 #define NEON_3R_VPMIN 21
4738 #define NEON_3R_VQDMULH_VQRDMULH 22
4739 #define NEON_3R_VPADD_VQRDMLAH 23
4740 #define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */
4741 #define NEON_3R_VFM_VQRDMLSH 25 /* VFMA, VFMS, VQRDMLSH */
4742 #define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
4743 #define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
4744 #define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
4745 #define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
4746 #define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
4747 #define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */
4749 static const uint8_t neon_3r_sizes[] = {
4750 [NEON_3R_VHADD] = 0x7,
4751 [NEON_3R_VQADD] = 0xf,
4752 [NEON_3R_VRHADD] = 0x7,
4753 [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
4754 [NEON_3R_VHSUB] = 0x7,
4755 [NEON_3R_VQSUB] = 0xf,
4756 [NEON_3R_VCGT] = 0x7,
4757 [NEON_3R_VCGE] = 0x7,
4758 [NEON_3R_VSHL] = 0xf,
4759 [NEON_3R_VQSHL] = 0xf,
4760 [NEON_3R_VRSHL] = 0xf,
4761 [NEON_3R_VQRSHL] = 0xf,
4762 [NEON_3R_VMAX] = 0x7,
4763 [NEON_3R_VMIN] = 0x7,
4764 [NEON_3R_VABD] = 0x7,
4765 [NEON_3R_VABA] = 0x7,
4766 [NEON_3R_VADD_VSUB] = 0xf,
4767 [NEON_3R_VTST_VCEQ] = 0x7,
4768 [NEON_3R_VML] = 0x7,
4769 [NEON_3R_VMUL] = 0x7,
4770 [NEON_3R_VPMAX] = 0x7,
4771 [NEON_3R_VPMIN] = 0x7,
4772 [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
4773 [NEON_3R_VPADD_VQRDMLAH] = 0x7,
4774 [NEON_3R_SHA] = 0xf, /* size field encodes op type */
4775 [NEON_3R_VFM_VQRDMLSH] = 0x7, /* For VFM, size bit 1 encodes op */
4776 [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
4777 [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
4778 [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
4779 [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
4780 [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
4781 [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */
4784 /* Symbolic constants for op fields for Neon 2-register miscellaneous.
4785 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
4786 * table A7-13.
4788 #define NEON_2RM_VREV64 0
4789 #define NEON_2RM_VREV32 1
4790 #define NEON_2RM_VREV16 2
4791 #define NEON_2RM_VPADDL 4
4792 #define NEON_2RM_VPADDL_U 5
4793 #define NEON_2RM_AESE 6 /* Includes AESD */
4794 #define NEON_2RM_AESMC 7 /* Includes AESIMC */
4795 #define NEON_2RM_VCLS 8
4796 #define NEON_2RM_VCLZ 9
4797 #define NEON_2RM_VCNT 10
4798 #define NEON_2RM_VMVN 11
4799 #define NEON_2RM_VPADAL 12
4800 #define NEON_2RM_VPADAL_U 13
4801 #define NEON_2RM_VQABS 14
4802 #define NEON_2RM_VQNEG 15
4803 #define NEON_2RM_VCGT0 16
4804 #define NEON_2RM_VCGE0 17
4805 #define NEON_2RM_VCEQ0 18
4806 #define NEON_2RM_VCLE0 19
4807 #define NEON_2RM_VCLT0 20
4808 #define NEON_2RM_SHA1H 21
4809 #define NEON_2RM_VABS 22
4810 #define NEON_2RM_VNEG 23
4811 #define NEON_2RM_VCGT0_F 24
4812 #define NEON_2RM_VCGE0_F 25
4813 #define NEON_2RM_VCEQ0_F 26
4814 #define NEON_2RM_VCLE0_F 27
4815 #define NEON_2RM_VCLT0_F 28
4816 #define NEON_2RM_VABS_F 30
4817 #define NEON_2RM_VNEG_F 31
4818 #define NEON_2RM_VSWP 32
4819 #define NEON_2RM_VTRN 33
4820 #define NEON_2RM_VUZP 34
4821 #define NEON_2RM_VZIP 35
4822 #define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
4823 #define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
4824 #define NEON_2RM_VSHLL 38
4825 #define NEON_2RM_SHA1SU1 39 /* Includes SHA256SU0 */
4826 #define NEON_2RM_VRINTN 40
4827 #define NEON_2RM_VRINTX 41
4828 #define NEON_2RM_VRINTA 42
4829 #define NEON_2RM_VRINTZ 43
4830 #define NEON_2RM_VCVT_F16_F32 44
4831 #define NEON_2RM_VRINTM 45
4832 #define NEON_2RM_VCVT_F32_F16 46
4833 #define NEON_2RM_VRINTP 47
4834 #define NEON_2RM_VCVTAU 48
4835 #define NEON_2RM_VCVTAS 49
4836 #define NEON_2RM_VCVTNU 50
4837 #define NEON_2RM_VCVTNS 51
4838 #define NEON_2RM_VCVTPU 52
4839 #define NEON_2RM_VCVTPS 53
4840 #define NEON_2RM_VCVTMU 54
4841 #define NEON_2RM_VCVTMS 55
4842 #define NEON_2RM_VRECPE 56
4843 #define NEON_2RM_VRSQRTE 57
4844 #define NEON_2RM_VRECPE_F 58
4845 #define NEON_2RM_VRSQRTE_F 59
4846 #define NEON_2RM_VCVT_FS 60
4847 #define NEON_2RM_VCVT_FU 61
4848 #define NEON_2RM_VCVT_SF 62
4849 #define NEON_2RM_VCVT_UF 63
4851 static int neon_2rm_is_float_op(int op)
4853 /* Return true if this neon 2reg-misc op is float-to-float */
4854 return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
4855 (op >= NEON_2RM_VRINTN && op <= NEON_2RM_VRINTZ) ||
4856 op == NEON_2RM_VRINTM ||
4857 (op >= NEON_2RM_VRINTP && op <= NEON_2RM_VCVTMS) ||
4858 op >= NEON_2RM_VRECPE_F);
4861 static bool neon_2rm_is_v8_op(int op)
4863 /* Return true if this neon 2reg-misc op is ARMv8 and up */
4864 switch (op) {
4865 case NEON_2RM_VRINTN:
4866 case NEON_2RM_VRINTA:
4867 case NEON_2RM_VRINTM:
4868 case NEON_2RM_VRINTP:
4869 case NEON_2RM_VRINTZ:
4870 case NEON_2RM_VRINTX:
4871 case NEON_2RM_VCVTAU:
4872 case NEON_2RM_VCVTAS:
4873 case NEON_2RM_VCVTNU:
4874 case NEON_2RM_VCVTNS:
4875 case NEON_2RM_VCVTPU:
4876 case NEON_2RM_VCVTPS:
4877 case NEON_2RM_VCVTMU:
4878 case NEON_2RM_VCVTMS:
4879 return true;
4880 default:
4881 return false;
4885 /* Each entry in this array has bit n set if the insn allows
4886 * size value n (otherwise it will UNDEF). Since unallocated
4887 * op values will have no bits set they always UNDEF.
4889 static const uint8_t neon_2rm_sizes[] = {
4890 [NEON_2RM_VREV64] = 0x7,
4891 [NEON_2RM_VREV32] = 0x3,
4892 [NEON_2RM_VREV16] = 0x1,
4893 [NEON_2RM_VPADDL] = 0x7,
4894 [NEON_2RM_VPADDL_U] = 0x7,
4895 [NEON_2RM_AESE] = 0x1,
4896 [NEON_2RM_AESMC] = 0x1,
4897 [NEON_2RM_VCLS] = 0x7,
4898 [NEON_2RM_VCLZ] = 0x7,
4899 [NEON_2RM_VCNT] = 0x1,
4900 [NEON_2RM_VMVN] = 0x1,
4901 [NEON_2RM_VPADAL] = 0x7,
4902 [NEON_2RM_VPADAL_U] = 0x7,
4903 [NEON_2RM_VQABS] = 0x7,
4904 [NEON_2RM_VQNEG] = 0x7,
4905 [NEON_2RM_VCGT0] = 0x7,
4906 [NEON_2RM_VCGE0] = 0x7,
4907 [NEON_2RM_VCEQ0] = 0x7,
4908 [NEON_2RM_VCLE0] = 0x7,
4909 [NEON_2RM_VCLT0] = 0x7,
4910 [NEON_2RM_SHA1H] = 0x4,
4911 [NEON_2RM_VABS] = 0x7,
4912 [NEON_2RM_VNEG] = 0x7,
4913 [NEON_2RM_VCGT0_F] = 0x4,
4914 [NEON_2RM_VCGE0_F] = 0x4,
4915 [NEON_2RM_VCEQ0_F] = 0x4,
4916 [NEON_2RM_VCLE0_F] = 0x4,
4917 [NEON_2RM_VCLT0_F] = 0x4,
4918 [NEON_2RM_VABS_F] = 0x4,
4919 [NEON_2RM_VNEG_F] = 0x4,
4920 [NEON_2RM_VSWP] = 0x1,
4921 [NEON_2RM_VTRN] = 0x7,
4922 [NEON_2RM_VUZP] = 0x7,
4923 [NEON_2RM_VZIP] = 0x7,
4924 [NEON_2RM_VMOVN] = 0x7,
4925 [NEON_2RM_VQMOVN] = 0x7,
4926 [NEON_2RM_VSHLL] = 0x7,
4927 [NEON_2RM_SHA1SU1] = 0x4,
4928 [NEON_2RM_VRINTN] = 0x4,
4929 [NEON_2RM_VRINTX] = 0x4,
4930 [NEON_2RM_VRINTA] = 0x4,
4931 [NEON_2RM_VRINTZ] = 0x4,
4932 [NEON_2RM_VCVT_F16_F32] = 0x2,
4933 [NEON_2RM_VRINTM] = 0x4,
4934 [NEON_2RM_VCVT_F32_F16] = 0x2,
4935 [NEON_2RM_VRINTP] = 0x4,
4936 [NEON_2RM_VCVTAU] = 0x4,
4937 [NEON_2RM_VCVTAS] = 0x4,
4938 [NEON_2RM_VCVTNU] = 0x4,
4939 [NEON_2RM_VCVTNS] = 0x4,
4940 [NEON_2RM_VCVTPU] = 0x4,
4941 [NEON_2RM_VCVTPS] = 0x4,
4942 [NEON_2RM_VCVTMU] = 0x4,
4943 [NEON_2RM_VCVTMS] = 0x4,
4944 [NEON_2RM_VRECPE] = 0x4,
4945 [NEON_2RM_VRSQRTE] = 0x4,
4946 [NEON_2RM_VRECPE_F] = 0x4,
4947 [NEON_2RM_VRSQRTE_F] = 0x4,
4948 [NEON_2RM_VCVT_FS] = 0x4,
4949 [NEON_2RM_VCVT_FU] = 0x4,
4950 [NEON_2RM_VCVT_SF] = 0x4,
4951 [NEON_2RM_VCVT_UF] = 0x4,
4955 /* Expand v8.1 simd helper. */
4956 static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
4957 int q, int rd, int rn, int rm)
4959 if (dc_isar_feature(aa32_rdm, s)) {
4960 int opr_sz = (1 + q) * 8;
4961 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
4962 vfp_reg_offset(1, rn),
4963 vfp_reg_offset(1, rm), cpu_env,
4964 opr_sz, opr_sz, 0, fn);
4965 return 0;
4967 return 1;
4970 static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4972 tcg_gen_vec_sar8i_i64(a, a, shift);
4973 tcg_gen_vec_add8_i64(d, d, a);
4976 static void gen_ssra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4978 tcg_gen_vec_sar16i_i64(a, a, shift);
4979 tcg_gen_vec_add16_i64(d, d, a);
4982 static void gen_ssra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
4984 tcg_gen_sari_i32(a, a, shift);
4985 tcg_gen_add_i32(d, d, a);
4988 static void gen_ssra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
4990 tcg_gen_sari_i64(a, a, shift);
4991 tcg_gen_add_i64(d, d, a);
4994 static void gen_ssra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
4996 tcg_gen_sari_vec(vece, a, a, sh);
4997 tcg_gen_add_vec(vece, d, d, a);
5000 static const TCGOpcode vecop_list_ssra[] = {
5001 INDEX_op_sari_vec, INDEX_op_add_vec, 0
5004 const GVecGen2i ssra_op[4] = {
5005 { .fni8 = gen_ssra8_i64,
5006 .fniv = gen_ssra_vec,
5007 .load_dest = true,
5008 .opt_opc = vecop_list_ssra,
5009 .vece = MO_8 },
5010 { .fni8 = gen_ssra16_i64,
5011 .fniv = gen_ssra_vec,
5012 .load_dest = true,
5013 .opt_opc = vecop_list_ssra,
5014 .vece = MO_16 },
5015 { .fni4 = gen_ssra32_i32,
5016 .fniv = gen_ssra_vec,
5017 .load_dest = true,
5018 .opt_opc = vecop_list_ssra,
5019 .vece = MO_32 },
5020 { .fni8 = gen_ssra64_i64,
5021 .fniv = gen_ssra_vec,
5022 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5023 .opt_opc = vecop_list_ssra,
5024 .load_dest = true,
5025 .vece = MO_64 },
5028 static void gen_usra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5030 tcg_gen_vec_shr8i_i64(a, a, shift);
5031 tcg_gen_vec_add8_i64(d, d, a);
5034 static void gen_usra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5036 tcg_gen_vec_shr16i_i64(a, a, shift);
5037 tcg_gen_vec_add16_i64(d, d, a);
5040 static void gen_usra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
5042 tcg_gen_shri_i32(a, a, shift);
5043 tcg_gen_add_i32(d, d, a);
5046 static void gen_usra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5048 tcg_gen_shri_i64(a, a, shift);
5049 tcg_gen_add_i64(d, d, a);
5052 static void gen_usra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
5054 tcg_gen_shri_vec(vece, a, a, sh);
5055 tcg_gen_add_vec(vece, d, d, a);
5058 static const TCGOpcode vecop_list_usra[] = {
5059 INDEX_op_shri_vec, INDEX_op_add_vec, 0
5062 const GVecGen2i usra_op[4] = {
5063 { .fni8 = gen_usra8_i64,
5064 .fniv = gen_usra_vec,
5065 .load_dest = true,
5066 .opt_opc = vecop_list_usra,
5067 .vece = MO_8, },
5068 { .fni8 = gen_usra16_i64,
5069 .fniv = gen_usra_vec,
5070 .load_dest = true,
5071 .opt_opc = vecop_list_usra,
5072 .vece = MO_16, },
5073 { .fni4 = gen_usra32_i32,
5074 .fniv = gen_usra_vec,
5075 .load_dest = true,
5076 .opt_opc = vecop_list_usra,
5077 .vece = MO_32, },
5078 { .fni8 = gen_usra64_i64,
5079 .fniv = gen_usra_vec,
5080 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5081 .load_dest = true,
5082 .opt_opc = vecop_list_usra,
5083 .vece = MO_64, },
5086 static void gen_shr8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5088 uint64_t mask = dup_const(MO_8, 0xff >> shift);
5089 TCGv_i64 t = tcg_temp_new_i64();
5091 tcg_gen_shri_i64(t, a, shift);
5092 tcg_gen_andi_i64(t, t, mask);
5093 tcg_gen_andi_i64(d, d, ~mask);
5094 tcg_gen_or_i64(d, d, t);
5095 tcg_temp_free_i64(t);
5098 static void gen_shr16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5100 uint64_t mask = dup_const(MO_16, 0xffff >> shift);
5101 TCGv_i64 t = tcg_temp_new_i64();
5103 tcg_gen_shri_i64(t, a, shift);
5104 tcg_gen_andi_i64(t, t, mask);
5105 tcg_gen_andi_i64(d, d, ~mask);
5106 tcg_gen_or_i64(d, d, t);
5107 tcg_temp_free_i64(t);
5110 static void gen_shr32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
5112 tcg_gen_shri_i32(a, a, shift);
5113 tcg_gen_deposit_i32(d, d, a, 0, 32 - shift);
5116 static void gen_shr64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5118 tcg_gen_shri_i64(a, a, shift);
5119 tcg_gen_deposit_i64(d, d, a, 0, 64 - shift);
5122 static void gen_shr_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
5124 if (sh == 0) {
5125 tcg_gen_mov_vec(d, a);
5126 } else {
5127 TCGv_vec t = tcg_temp_new_vec_matching(d);
5128 TCGv_vec m = tcg_temp_new_vec_matching(d);
5130 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK((8 << vece) - sh, sh));
5131 tcg_gen_shri_vec(vece, t, a, sh);
5132 tcg_gen_and_vec(vece, d, d, m);
5133 tcg_gen_or_vec(vece, d, d, t);
5135 tcg_temp_free_vec(t);
5136 tcg_temp_free_vec(m);
5140 static const TCGOpcode vecop_list_sri[] = { INDEX_op_shri_vec, 0 };
5142 const GVecGen2i sri_op[4] = {
5143 { .fni8 = gen_shr8_ins_i64,
5144 .fniv = gen_shr_ins_vec,
5145 .load_dest = true,
5146 .opt_opc = vecop_list_sri,
5147 .vece = MO_8 },
5148 { .fni8 = gen_shr16_ins_i64,
5149 .fniv = gen_shr_ins_vec,
5150 .load_dest = true,
5151 .opt_opc = vecop_list_sri,
5152 .vece = MO_16 },
5153 { .fni4 = gen_shr32_ins_i32,
5154 .fniv = gen_shr_ins_vec,
5155 .load_dest = true,
5156 .opt_opc = vecop_list_sri,
5157 .vece = MO_32 },
5158 { .fni8 = gen_shr64_ins_i64,
5159 .fniv = gen_shr_ins_vec,
5160 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5161 .load_dest = true,
5162 .opt_opc = vecop_list_sri,
5163 .vece = MO_64 },
5166 static void gen_shl8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5168 uint64_t mask = dup_const(MO_8, 0xff << shift);
5169 TCGv_i64 t = tcg_temp_new_i64();
5171 tcg_gen_shli_i64(t, a, shift);
5172 tcg_gen_andi_i64(t, t, mask);
5173 tcg_gen_andi_i64(d, d, ~mask);
5174 tcg_gen_or_i64(d, d, t);
5175 tcg_temp_free_i64(t);
5178 static void gen_shl16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5180 uint64_t mask = dup_const(MO_16, 0xffff << shift);
5181 TCGv_i64 t = tcg_temp_new_i64();
5183 tcg_gen_shli_i64(t, a, shift);
5184 tcg_gen_andi_i64(t, t, mask);
5185 tcg_gen_andi_i64(d, d, ~mask);
5186 tcg_gen_or_i64(d, d, t);
5187 tcg_temp_free_i64(t);
5190 static void gen_shl32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
5192 tcg_gen_deposit_i32(d, d, a, shift, 32 - shift);
5195 static void gen_shl64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5197 tcg_gen_deposit_i64(d, d, a, shift, 64 - shift);
5200 static void gen_shl_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
5202 if (sh == 0) {
5203 tcg_gen_mov_vec(d, a);
5204 } else {
5205 TCGv_vec t = tcg_temp_new_vec_matching(d);
5206 TCGv_vec m = tcg_temp_new_vec_matching(d);
5208 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK(0, sh));
5209 tcg_gen_shli_vec(vece, t, a, sh);
5210 tcg_gen_and_vec(vece, d, d, m);
5211 tcg_gen_or_vec(vece, d, d, t);
5213 tcg_temp_free_vec(t);
5214 tcg_temp_free_vec(m);
5218 static const TCGOpcode vecop_list_sli[] = { INDEX_op_shli_vec, 0 };
5220 const GVecGen2i sli_op[4] = {
5221 { .fni8 = gen_shl8_ins_i64,
5222 .fniv = gen_shl_ins_vec,
5223 .load_dest = true,
5224 .opt_opc = vecop_list_sli,
5225 .vece = MO_8 },
5226 { .fni8 = gen_shl16_ins_i64,
5227 .fniv = gen_shl_ins_vec,
5228 .load_dest = true,
5229 .opt_opc = vecop_list_sli,
5230 .vece = MO_16 },
5231 { .fni4 = gen_shl32_ins_i32,
5232 .fniv = gen_shl_ins_vec,
5233 .load_dest = true,
5234 .opt_opc = vecop_list_sli,
5235 .vece = MO_32 },
5236 { .fni8 = gen_shl64_ins_i64,
5237 .fniv = gen_shl_ins_vec,
5238 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5239 .load_dest = true,
5240 .opt_opc = vecop_list_sli,
5241 .vece = MO_64 },
5244 static void gen_mla8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
5246 gen_helper_neon_mul_u8(a, a, b);
5247 gen_helper_neon_add_u8(d, d, a);
5250 static void gen_mls8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
5252 gen_helper_neon_mul_u8(a, a, b);
5253 gen_helper_neon_sub_u8(d, d, a);
5256 static void gen_mla16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
5258 gen_helper_neon_mul_u16(a, a, b);
5259 gen_helper_neon_add_u16(d, d, a);
5262 static void gen_mls16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
5264 gen_helper_neon_mul_u16(a, a, b);
5265 gen_helper_neon_sub_u16(d, d, a);
5268 static void gen_mla32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
5270 tcg_gen_mul_i32(a, a, b);
5271 tcg_gen_add_i32(d, d, a);
5274 static void gen_mls32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
5276 tcg_gen_mul_i32(a, a, b);
5277 tcg_gen_sub_i32(d, d, a);
5280 static void gen_mla64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
5282 tcg_gen_mul_i64(a, a, b);
5283 tcg_gen_add_i64(d, d, a);
5286 static void gen_mls64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
5288 tcg_gen_mul_i64(a, a, b);
5289 tcg_gen_sub_i64(d, d, a);
5292 static void gen_mla_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
5294 tcg_gen_mul_vec(vece, a, a, b);
5295 tcg_gen_add_vec(vece, d, d, a);
5298 static void gen_mls_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
5300 tcg_gen_mul_vec(vece, a, a, b);
5301 tcg_gen_sub_vec(vece, d, d, a);
5304 /* Note that while NEON does not support VMLA and VMLS as 64-bit ops,
5305 * these tables are shared with AArch64 which does support them.
5308 static const TCGOpcode vecop_list_mla[] = {
5309 INDEX_op_mul_vec, INDEX_op_add_vec, 0
5312 static const TCGOpcode vecop_list_mls[] = {
5313 INDEX_op_mul_vec, INDEX_op_sub_vec, 0
5316 const GVecGen3 mla_op[4] = {
5317 { .fni4 = gen_mla8_i32,
5318 .fniv = gen_mla_vec,
5319 .load_dest = true,
5320 .opt_opc = vecop_list_mla,
5321 .vece = MO_8 },
5322 { .fni4 = gen_mla16_i32,
5323 .fniv = gen_mla_vec,
5324 .load_dest = true,
5325 .opt_opc = vecop_list_mla,
5326 .vece = MO_16 },
5327 { .fni4 = gen_mla32_i32,
5328 .fniv = gen_mla_vec,
5329 .load_dest = true,
5330 .opt_opc = vecop_list_mla,
5331 .vece = MO_32 },
5332 { .fni8 = gen_mla64_i64,
5333 .fniv = gen_mla_vec,
5334 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5335 .load_dest = true,
5336 .opt_opc = vecop_list_mla,
5337 .vece = MO_64 },
5340 const GVecGen3 mls_op[4] = {
5341 { .fni4 = gen_mls8_i32,
5342 .fniv = gen_mls_vec,
5343 .load_dest = true,
5344 .opt_opc = vecop_list_mls,
5345 .vece = MO_8 },
5346 { .fni4 = gen_mls16_i32,
5347 .fniv = gen_mls_vec,
5348 .load_dest = true,
5349 .opt_opc = vecop_list_mls,
5350 .vece = MO_16 },
5351 { .fni4 = gen_mls32_i32,
5352 .fniv = gen_mls_vec,
5353 .load_dest = true,
5354 .opt_opc = vecop_list_mls,
5355 .vece = MO_32 },
5356 { .fni8 = gen_mls64_i64,
5357 .fniv = gen_mls_vec,
5358 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5359 .load_dest = true,
5360 .opt_opc = vecop_list_mls,
5361 .vece = MO_64 },
5364 /* CMTST : test is "if (X & Y != 0)". */
5365 static void gen_cmtst_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
5367 tcg_gen_and_i32(d, a, b);
5368 tcg_gen_setcondi_i32(TCG_COND_NE, d, d, 0);
5369 tcg_gen_neg_i32(d, d);
5372 void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
5374 tcg_gen_and_i64(d, a, b);
5375 tcg_gen_setcondi_i64(TCG_COND_NE, d, d, 0);
5376 tcg_gen_neg_i64(d, d);
5379 static void gen_cmtst_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
5381 tcg_gen_and_vec(vece, d, a, b);
5382 tcg_gen_dupi_vec(vece, a, 0);
5383 tcg_gen_cmp_vec(TCG_COND_NE, vece, d, d, a);
5386 static const TCGOpcode vecop_list_cmtst[] = { INDEX_op_cmp_vec, 0 };
5388 const GVecGen3 cmtst_op[4] = {
5389 { .fni4 = gen_helper_neon_tst_u8,
5390 .fniv = gen_cmtst_vec,
5391 .opt_opc = vecop_list_cmtst,
5392 .vece = MO_8 },
5393 { .fni4 = gen_helper_neon_tst_u16,
5394 .fniv = gen_cmtst_vec,
5395 .opt_opc = vecop_list_cmtst,
5396 .vece = MO_16 },
5397 { .fni4 = gen_cmtst_i32,
5398 .fniv = gen_cmtst_vec,
5399 .opt_opc = vecop_list_cmtst,
5400 .vece = MO_32 },
5401 { .fni8 = gen_cmtst_i64,
5402 .fniv = gen_cmtst_vec,
5403 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5404 .opt_opc = vecop_list_cmtst,
5405 .vece = MO_64 },
5408 static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
5409 TCGv_vec a, TCGv_vec b)
5411 TCGv_vec x = tcg_temp_new_vec_matching(t);
5412 tcg_gen_add_vec(vece, x, a, b);
5413 tcg_gen_usadd_vec(vece, t, a, b);
5414 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
5415 tcg_gen_or_vec(vece, sat, sat, x);
5416 tcg_temp_free_vec(x);
5419 static const TCGOpcode vecop_list_uqadd[] = {
5420 INDEX_op_usadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
5423 const GVecGen4 uqadd_op[4] = {
5424 { .fniv = gen_uqadd_vec,
5425 .fno = gen_helper_gvec_uqadd_b,
5426 .write_aofs = true,
5427 .opt_opc = vecop_list_uqadd,
5428 .vece = MO_8 },
5429 { .fniv = gen_uqadd_vec,
5430 .fno = gen_helper_gvec_uqadd_h,
5431 .write_aofs = true,
5432 .opt_opc = vecop_list_uqadd,
5433 .vece = MO_16 },
5434 { .fniv = gen_uqadd_vec,
5435 .fno = gen_helper_gvec_uqadd_s,
5436 .write_aofs = true,
5437 .opt_opc = vecop_list_uqadd,
5438 .vece = MO_32 },
5439 { .fniv = gen_uqadd_vec,
5440 .fno = gen_helper_gvec_uqadd_d,
5441 .write_aofs = true,
5442 .opt_opc = vecop_list_uqadd,
5443 .vece = MO_64 },
5446 static void gen_sqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
5447 TCGv_vec a, TCGv_vec b)
5449 TCGv_vec x = tcg_temp_new_vec_matching(t);
5450 tcg_gen_add_vec(vece, x, a, b);
5451 tcg_gen_ssadd_vec(vece, t, a, b);
5452 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
5453 tcg_gen_or_vec(vece, sat, sat, x);
5454 tcg_temp_free_vec(x);
5457 static const TCGOpcode vecop_list_sqadd[] = {
5458 INDEX_op_ssadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
5461 const GVecGen4 sqadd_op[4] = {
5462 { .fniv = gen_sqadd_vec,
5463 .fno = gen_helper_gvec_sqadd_b,
5464 .opt_opc = vecop_list_sqadd,
5465 .write_aofs = true,
5466 .vece = MO_8 },
5467 { .fniv = gen_sqadd_vec,
5468 .fno = gen_helper_gvec_sqadd_h,
5469 .opt_opc = vecop_list_sqadd,
5470 .write_aofs = true,
5471 .vece = MO_16 },
5472 { .fniv = gen_sqadd_vec,
5473 .fno = gen_helper_gvec_sqadd_s,
5474 .opt_opc = vecop_list_sqadd,
5475 .write_aofs = true,
5476 .vece = MO_32 },
5477 { .fniv = gen_sqadd_vec,
5478 .fno = gen_helper_gvec_sqadd_d,
5479 .opt_opc = vecop_list_sqadd,
5480 .write_aofs = true,
5481 .vece = MO_64 },
5484 static void gen_uqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
5485 TCGv_vec a, TCGv_vec b)
5487 TCGv_vec x = tcg_temp_new_vec_matching(t);
5488 tcg_gen_sub_vec(vece, x, a, b);
5489 tcg_gen_ussub_vec(vece, t, a, b);
5490 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
5491 tcg_gen_or_vec(vece, sat, sat, x);
5492 tcg_temp_free_vec(x);
5495 static const TCGOpcode vecop_list_uqsub[] = {
5496 INDEX_op_ussub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
5499 const GVecGen4 uqsub_op[4] = {
5500 { .fniv = gen_uqsub_vec,
5501 .fno = gen_helper_gvec_uqsub_b,
5502 .opt_opc = vecop_list_uqsub,
5503 .write_aofs = true,
5504 .vece = MO_8 },
5505 { .fniv = gen_uqsub_vec,
5506 .fno = gen_helper_gvec_uqsub_h,
5507 .opt_opc = vecop_list_uqsub,
5508 .write_aofs = true,
5509 .vece = MO_16 },
5510 { .fniv = gen_uqsub_vec,
5511 .fno = gen_helper_gvec_uqsub_s,
5512 .opt_opc = vecop_list_uqsub,
5513 .write_aofs = true,
5514 .vece = MO_32 },
5515 { .fniv = gen_uqsub_vec,
5516 .fno = gen_helper_gvec_uqsub_d,
5517 .opt_opc = vecop_list_uqsub,
5518 .write_aofs = true,
5519 .vece = MO_64 },
5522 static void gen_sqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
5523 TCGv_vec a, TCGv_vec b)
5525 TCGv_vec x = tcg_temp_new_vec_matching(t);
5526 tcg_gen_sub_vec(vece, x, a, b);
5527 tcg_gen_sssub_vec(vece, t, a, b);
5528 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
5529 tcg_gen_or_vec(vece, sat, sat, x);
5530 tcg_temp_free_vec(x);
5533 static const TCGOpcode vecop_list_sqsub[] = {
5534 INDEX_op_sssub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
5537 const GVecGen4 sqsub_op[4] = {
5538 { .fniv = gen_sqsub_vec,
5539 .fno = gen_helper_gvec_sqsub_b,
5540 .opt_opc = vecop_list_sqsub,
5541 .write_aofs = true,
5542 .vece = MO_8 },
5543 { .fniv = gen_sqsub_vec,
5544 .fno = gen_helper_gvec_sqsub_h,
5545 .opt_opc = vecop_list_sqsub,
5546 .write_aofs = true,
5547 .vece = MO_16 },
5548 { .fniv = gen_sqsub_vec,
5549 .fno = gen_helper_gvec_sqsub_s,
5550 .opt_opc = vecop_list_sqsub,
5551 .write_aofs = true,
5552 .vece = MO_32 },
5553 { .fniv = gen_sqsub_vec,
5554 .fno = gen_helper_gvec_sqsub_d,
5555 .opt_opc = vecop_list_sqsub,
5556 .write_aofs = true,
5557 .vece = MO_64 },
5560 /* Translate a NEON data processing instruction. Return nonzero if the
5561 instruction is invalid.
5562 We process data in a mixture of 32-bit and 64-bit chunks.
5563 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
5565 static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
5567 int op;
5568 int q;
5569 int rd, rn, rm, rd_ofs, rn_ofs, rm_ofs;
5570 int size;
5571 int shift;
5572 int pass;
5573 int count;
5574 int pairwise;
5575 int u;
5576 int vec_size;
5577 uint32_t imm;
5578 TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
5579 TCGv_ptr ptr1, ptr2, ptr3;
5580 TCGv_i64 tmp64;
5582 /* FIXME: this access check should not take precedence over UNDEF
5583 * for invalid encodings; we will generate incorrect syndrome information
5584 * for attempts to execute invalid vfp/neon encodings with FP disabled.
5586 if (s->fp_excp_el) {
5587 gen_exception_insn(s, 4, EXCP_UDEF,
5588 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
5589 return 0;
5592 if (!s->vfp_enabled)
5593 return 1;
5594 q = (insn & (1 << 6)) != 0;
5595 u = (insn >> 24) & 1;
5596 VFP_DREG_D(rd, insn);
5597 VFP_DREG_N(rn, insn);
5598 VFP_DREG_M(rm, insn);
5599 size = (insn >> 20) & 3;
5600 vec_size = q ? 16 : 8;
5601 rd_ofs = neon_reg_offset(rd, 0);
5602 rn_ofs = neon_reg_offset(rn, 0);
5603 rm_ofs = neon_reg_offset(rm, 0);
5605 if ((insn & (1 << 23)) == 0) {
5606 /* Three register same length. */
5607 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
5608 /* Catch invalid op and bad size combinations: UNDEF */
5609 if ((neon_3r_sizes[op] & (1 << size)) == 0) {
5610 return 1;
5612 /* All insns of this form UNDEF for either this condition or the
5613 * superset of cases "Q==1"; we catch the latter later.
5615 if (q && ((rd | rn | rm) & 1)) {
5616 return 1;
5618 switch (op) {
5619 case NEON_3R_SHA:
5620 /* The SHA-1/SHA-256 3-register instructions require special
5621 * treatment here, as their size field is overloaded as an
5622 * op type selector, and they all consume their input in a
5623 * single pass.
5625 if (!q) {
5626 return 1;
5628 if (!u) { /* SHA-1 */
5629 if (!dc_isar_feature(aa32_sha1, s)) {
5630 return 1;
5632 ptr1 = vfp_reg_ptr(true, rd);
5633 ptr2 = vfp_reg_ptr(true, rn);
5634 ptr3 = vfp_reg_ptr(true, rm);
5635 tmp4 = tcg_const_i32(size);
5636 gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp4);
5637 tcg_temp_free_i32(tmp4);
5638 } else { /* SHA-256 */
5639 if (!dc_isar_feature(aa32_sha2, s) || size == 3) {
5640 return 1;
5642 ptr1 = vfp_reg_ptr(true, rd);
5643 ptr2 = vfp_reg_ptr(true, rn);
5644 ptr3 = vfp_reg_ptr(true, rm);
5645 switch (size) {
5646 case 0:
5647 gen_helper_crypto_sha256h(ptr1, ptr2, ptr3);
5648 break;
5649 case 1:
5650 gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3);
5651 break;
5652 case 2:
5653 gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3);
5654 break;
5657 tcg_temp_free_ptr(ptr1);
5658 tcg_temp_free_ptr(ptr2);
5659 tcg_temp_free_ptr(ptr3);
5660 return 0;
5662 case NEON_3R_VPADD_VQRDMLAH:
5663 if (!u) {
5664 break; /* VPADD */
5666 /* VQRDMLAH */
5667 switch (size) {
5668 case 1:
5669 return do_v81_helper(s, gen_helper_gvec_qrdmlah_s16,
5670 q, rd, rn, rm);
5671 case 2:
5672 return do_v81_helper(s, gen_helper_gvec_qrdmlah_s32,
5673 q, rd, rn, rm);
5675 return 1;
5677 case NEON_3R_VFM_VQRDMLSH:
5678 if (!u) {
5679 /* VFM, VFMS */
5680 if (size == 1) {
5681 return 1;
5683 break;
5685 /* VQRDMLSH */
5686 switch (size) {
5687 case 1:
5688 return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s16,
5689 q, rd, rn, rm);
5690 case 2:
5691 return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s32,
5692 q, rd, rn, rm);
5694 return 1;
5696 case NEON_3R_LOGIC: /* Logic ops. */
5697 switch ((u << 2) | size) {
5698 case 0: /* VAND */
5699 tcg_gen_gvec_and(0, rd_ofs, rn_ofs, rm_ofs,
5700 vec_size, vec_size);
5701 break;
5702 case 1: /* VBIC */
5703 tcg_gen_gvec_andc(0, rd_ofs, rn_ofs, rm_ofs,
5704 vec_size, vec_size);
5705 break;
5706 case 2: /* VORR */
5707 tcg_gen_gvec_or(0, rd_ofs, rn_ofs, rm_ofs,
5708 vec_size, vec_size);
5709 break;
5710 case 3: /* VORN */
5711 tcg_gen_gvec_orc(0, rd_ofs, rn_ofs, rm_ofs,
5712 vec_size, vec_size);
5713 break;
5714 case 4: /* VEOR */
5715 tcg_gen_gvec_xor(0, rd_ofs, rn_ofs, rm_ofs,
5716 vec_size, vec_size);
5717 break;
5718 case 5: /* VBSL */
5719 tcg_gen_gvec_bitsel(MO_8, rd_ofs, rd_ofs, rn_ofs, rm_ofs,
5720 vec_size, vec_size);
5721 break;
5722 case 6: /* VBIT */
5723 tcg_gen_gvec_bitsel(MO_8, rd_ofs, rm_ofs, rn_ofs, rd_ofs,
5724 vec_size, vec_size);
5725 break;
5726 case 7: /* VBIF */
5727 tcg_gen_gvec_bitsel(MO_8, rd_ofs, rm_ofs, rd_ofs, rn_ofs,
5728 vec_size, vec_size);
5729 break;
5731 return 0;
5733 case NEON_3R_VADD_VSUB:
5734 if (u) {
5735 tcg_gen_gvec_sub(size, rd_ofs, rn_ofs, rm_ofs,
5736 vec_size, vec_size);
5737 } else {
5738 tcg_gen_gvec_add(size, rd_ofs, rn_ofs, rm_ofs,
5739 vec_size, vec_size);
5741 return 0;
5743 case NEON_3R_VQADD:
5744 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
5745 rn_ofs, rm_ofs, vec_size, vec_size,
5746 (u ? uqadd_op : sqadd_op) + size);
5747 return 0;
5749 case NEON_3R_VQSUB:
5750 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
5751 rn_ofs, rm_ofs, vec_size, vec_size,
5752 (u ? uqsub_op : sqsub_op) + size);
5753 return 0;
5755 case NEON_3R_VMUL: /* VMUL */
5756 if (u) {
5757 /* Polynomial case allows only P8 and is handled below. */
5758 if (size != 0) {
5759 return 1;
5761 } else {
5762 tcg_gen_gvec_mul(size, rd_ofs, rn_ofs, rm_ofs,
5763 vec_size, vec_size);
5764 return 0;
5766 break;
5768 case NEON_3R_VML: /* VMLA, VMLS */
5769 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size,
5770 u ? &mls_op[size] : &mla_op[size]);
5771 return 0;
5773 case NEON_3R_VTST_VCEQ:
5774 if (u) { /* VCEQ */
5775 tcg_gen_gvec_cmp(TCG_COND_EQ, size, rd_ofs, rn_ofs, rm_ofs,
5776 vec_size, vec_size);
5777 } else { /* VTST */
5778 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
5779 vec_size, vec_size, &cmtst_op[size]);
5781 return 0;
5783 case NEON_3R_VCGT:
5784 tcg_gen_gvec_cmp(u ? TCG_COND_GTU : TCG_COND_GT, size,
5785 rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
5786 return 0;
5788 case NEON_3R_VCGE:
5789 tcg_gen_gvec_cmp(u ? TCG_COND_GEU : TCG_COND_GE, size,
5790 rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
5791 return 0;
5793 case NEON_3R_VMAX:
5794 if (u) {
5795 tcg_gen_gvec_umax(size, rd_ofs, rn_ofs, rm_ofs,
5796 vec_size, vec_size);
5797 } else {
5798 tcg_gen_gvec_smax(size, rd_ofs, rn_ofs, rm_ofs,
5799 vec_size, vec_size);
5801 return 0;
5802 case NEON_3R_VMIN:
5803 if (u) {
5804 tcg_gen_gvec_umin(size, rd_ofs, rn_ofs, rm_ofs,
5805 vec_size, vec_size);
5806 } else {
5807 tcg_gen_gvec_smin(size, rd_ofs, rn_ofs, rm_ofs,
5808 vec_size, vec_size);
5810 return 0;
5813 if (size == 3) {
5814 /* 64-bit element instructions. */
5815 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5816 neon_load_reg64(cpu_V0, rn + pass);
5817 neon_load_reg64(cpu_V1, rm + pass);
5818 switch (op) {
5819 case NEON_3R_VSHL:
5820 if (u) {
5821 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
5822 } else {
5823 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
5825 break;
5826 case NEON_3R_VQSHL:
5827 if (u) {
5828 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
5829 cpu_V1, cpu_V0);
5830 } else {
5831 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
5832 cpu_V1, cpu_V0);
5834 break;
5835 case NEON_3R_VRSHL:
5836 if (u) {
5837 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
5838 } else {
5839 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
5841 break;
5842 case NEON_3R_VQRSHL:
5843 if (u) {
5844 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
5845 cpu_V1, cpu_V0);
5846 } else {
5847 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
5848 cpu_V1, cpu_V0);
5850 break;
5851 default:
5852 abort();
5854 neon_store_reg64(cpu_V0, rd + pass);
5856 return 0;
5858 pairwise = 0;
5859 switch (op) {
5860 case NEON_3R_VSHL:
5861 case NEON_3R_VQSHL:
5862 case NEON_3R_VRSHL:
5863 case NEON_3R_VQRSHL:
5865 int rtmp;
5866 /* Shift instruction operands are reversed. */
5867 rtmp = rn;
5868 rn = rm;
5869 rm = rtmp;
5871 break;
5872 case NEON_3R_VPADD_VQRDMLAH:
5873 case NEON_3R_VPMAX:
5874 case NEON_3R_VPMIN:
5875 pairwise = 1;
5876 break;
5877 case NEON_3R_FLOAT_ARITH:
5878 pairwise = (u && size < 2); /* if VPADD (float) */
5879 break;
5880 case NEON_3R_FLOAT_MINMAX:
5881 pairwise = u; /* if VPMIN/VPMAX (float) */
5882 break;
5883 case NEON_3R_FLOAT_CMP:
5884 if (!u && size) {
5885 /* no encoding for U=0 C=1x */
5886 return 1;
5888 break;
5889 case NEON_3R_FLOAT_ACMP:
5890 if (!u) {
5891 return 1;
5893 break;
5894 case NEON_3R_FLOAT_MISC:
5895 /* VMAXNM/VMINNM in ARMv8 */
5896 if (u && !arm_dc_feature(s, ARM_FEATURE_V8)) {
5897 return 1;
5899 break;
5900 case NEON_3R_VFM_VQRDMLSH:
5901 if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
5902 return 1;
5904 break;
5905 default:
5906 break;
5909 if (pairwise && q) {
5910 /* All the pairwise insns UNDEF if Q is set */
5911 return 1;
5914 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5916 if (pairwise) {
5917 /* Pairwise. */
5918 if (pass < 1) {
5919 tmp = neon_load_reg(rn, 0);
5920 tmp2 = neon_load_reg(rn, 1);
5921 } else {
5922 tmp = neon_load_reg(rm, 0);
5923 tmp2 = neon_load_reg(rm, 1);
5925 } else {
5926 /* Elementwise. */
5927 tmp = neon_load_reg(rn, pass);
5928 tmp2 = neon_load_reg(rm, pass);
5930 switch (op) {
5931 case NEON_3R_VHADD:
5932 GEN_NEON_INTEGER_OP(hadd);
5933 break;
5934 case NEON_3R_VRHADD:
5935 GEN_NEON_INTEGER_OP(rhadd);
5936 break;
5937 case NEON_3R_VHSUB:
5938 GEN_NEON_INTEGER_OP(hsub);
5939 break;
5940 case NEON_3R_VSHL:
5941 GEN_NEON_INTEGER_OP(shl);
5942 break;
5943 case NEON_3R_VQSHL:
5944 GEN_NEON_INTEGER_OP_ENV(qshl);
5945 break;
5946 case NEON_3R_VRSHL:
5947 GEN_NEON_INTEGER_OP(rshl);
5948 break;
5949 case NEON_3R_VQRSHL:
5950 GEN_NEON_INTEGER_OP_ENV(qrshl);
5951 break;
5952 case NEON_3R_VABD:
5953 GEN_NEON_INTEGER_OP(abd);
5954 break;
5955 case NEON_3R_VABA:
5956 GEN_NEON_INTEGER_OP(abd);
5957 tcg_temp_free_i32(tmp2);
5958 tmp2 = neon_load_reg(rd, pass);
5959 gen_neon_add(size, tmp, tmp2);
5960 break;
5961 case NEON_3R_VMUL:
5962 /* VMUL.P8; other cases already eliminated. */
5963 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
5964 break;
5965 case NEON_3R_VPMAX:
5966 GEN_NEON_INTEGER_OP(pmax);
5967 break;
5968 case NEON_3R_VPMIN:
5969 GEN_NEON_INTEGER_OP(pmin);
5970 break;
5971 case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
5972 if (!u) { /* VQDMULH */
5973 switch (size) {
5974 case 1:
5975 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5976 break;
5977 case 2:
5978 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5979 break;
5980 default: abort();
5982 } else { /* VQRDMULH */
5983 switch (size) {
5984 case 1:
5985 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5986 break;
5987 case 2:
5988 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5989 break;
5990 default: abort();
5993 break;
5994 case NEON_3R_VPADD_VQRDMLAH:
5995 switch (size) {
5996 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
5997 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
5998 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
5999 default: abort();
6001 break;
6002 case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
6004 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6005 switch ((u << 2) | size) {
6006 case 0: /* VADD */
6007 case 4: /* VPADD */
6008 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
6009 break;
6010 case 2: /* VSUB */
6011 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
6012 break;
6013 case 6: /* VABD */
6014 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
6015 break;
6016 default:
6017 abort();
6019 tcg_temp_free_ptr(fpstatus);
6020 break;
6022 case NEON_3R_FLOAT_MULTIPLY:
6024 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6025 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
6026 if (!u) {
6027 tcg_temp_free_i32(tmp2);
6028 tmp2 = neon_load_reg(rd, pass);
6029 if (size == 0) {
6030 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
6031 } else {
6032 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
6035 tcg_temp_free_ptr(fpstatus);
6036 break;
6038 case NEON_3R_FLOAT_CMP:
6040 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6041 if (!u) {
6042 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
6043 } else {
6044 if (size == 0) {
6045 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
6046 } else {
6047 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
6050 tcg_temp_free_ptr(fpstatus);
6051 break;
6053 case NEON_3R_FLOAT_ACMP:
6055 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6056 if (size == 0) {
6057 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
6058 } else {
6059 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
6061 tcg_temp_free_ptr(fpstatus);
6062 break;
6064 case NEON_3R_FLOAT_MINMAX:
6066 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6067 if (size == 0) {
6068 gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus);
6069 } else {
6070 gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus);
6072 tcg_temp_free_ptr(fpstatus);
6073 break;
6075 case NEON_3R_FLOAT_MISC:
6076 if (u) {
6077 /* VMAXNM/VMINNM */
6078 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6079 if (size == 0) {
6080 gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus);
6081 } else {
6082 gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus);
6084 tcg_temp_free_ptr(fpstatus);
6085 } else {
6086 if (size == 0) {
6087 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
6088 } else {
6089 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
6092 break;
6093 case NEON_3R_VFM_VQRDMLSH:
6095 /* VFMA, VFMS: fused multiply-add */
6096 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6097 TCGv_i32 tmp3 = neon_load_reg(rd, pass);
6098 if (size) {
6099 /* VFMS */
6100 gen_helper_vfp_negs(tmp, tmp);
6102 gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus);
6103 tcg_temp_free_i32(tmp3);
6104 tcg_temp_free_ptr(fpstatus);
6105 break;
6107 default:
6108 abort();
6110 tcg_temp_free_i32(tmp2);
6112 /* Save the result. For elementwise operations we can put it
6113 straight into the destination register. For pairwise operations
6114 we have to be careful to avoid clobbering the source operands. */
6115 if (pairwise && rd == rm) {
6116 neon_store_scratch(pass, tmp);
6117 } else {
6118 neon_store_reg(rd, pass, tmp);
6121 } /* for pass */
6122 if (pairwise && rd == rm) {
6123 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6124 tmp = neon_load_scratch(pass);
6125 neon_store_reg(rd, pass, tmp);
6128 /* End of 3 register same size operations. */
6129 } else if (insn & (1 << 4)) {
6130 if ((insn & 0x00380080) != 0) {
6131 /* Two registers and shift. */
6132 op = (insn >> 8) & 0xf;
6133 if (insn & (1 << 7)) {
6134 /* 64-bit shift. */
6135 if (op > 7) {
6136 return 1;
6138 size = 3;
6139 } else {
6140 size = 2;
6141 while ((insn & (1 << (size + 19))) == 0)
6142 size--;
6144 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
6145 if (op < 8) {
6146 /* Shift by immediate:
6147 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
6148 if (q && ((rd | rm) & 1)) {
6149 return 1;
6151 if (!u && (op == 4 || op == 6)) {
6152 return 1;
6154 /* Right shifts are encoded as N - shift, where N is the
6155 element size in bits. */
6156 if (op <= 4) {
6157 shift = shift - (1 << (size + 3));
6160 switch (op) {
6161 case 0: /* VSHR */
6162 /* Right shift comes here negative. */
6163 shift = -shift;
6164 /* Shifts larger than the element size are architecturally
6165 * valid. Unsigned results in all zeros; signed results
6166 * in all sign bits.
6168 if (!u) {
6169 tcg_gen_gvec_sari(size, rd_ofs, rm_ofs,
6170 MIN(shift, (8 << size) - 1),
6171 vec_size, vec_size);
6172 } else if (shift >= 8 << size) {
6173 tcg_gen_gvec_dup8i(rd_ofs, vec_size, vec_size, 0);
6174 } else {
6175 tcg_gen_gvec_shri(size, rd_ofs, rm_ofs, shift,
6176 vec_size, vec_size);
6178 return 0;
6180 case 1: /* VSRA */
6181 /* Right shift comes here negative. */
6182 shift = -shift;
6183 /* Shifts larger than the element size are architecturally
6184 * valid. Unsigned results in all zeros; signed results
6185 * in all sign bits.
6187 if (!u) {
6188 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
6189 MIN(shift, (8 << size) - 1),
6190 &ssra_op[size]);
6191 } else if (shift >= 8 << size) {
6192 /* rd += 0 */
6193 } else {
6194 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
6195 shift, &usra_op[size]);
6197 return 0;
6199 case 4: /* VSRI */
6200 if (!u) {
6201 return 1;
6203 /* Right shift comes here negative. */
6204 shift = -shift;
6205 /* Shift out of range leaves destination unchanged. */
6206 if (shift < 8 << size) {
6207 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
6208 shift, &sri_op[size]);
6210 return 0;
6212 case 5: /* VSHL, VSLI */
6213 if (u) { /* VSLI */
6214 /* Shift out of range leaves destination unchanged. */
6215 if (shift < 8 << size) {
6216 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size,
6217 vec_size, shift, &sli_op[size]);
6219 } else { /* VSHL */
6220 /* Shifts larger than the element size are
6221 * architecturally valid and results in zero.
6223 if (shift >= 8 << size) {
6224 tcg_gen_gvec_dup8i(rd_ofs, vec_size, vec_size, 0);
6225 } else {
6226 tcg_gen_gvec_shli(size, rd_ofs, rm_ofs, shift,
6227 vec_size, vec_size);
6230 return 0;
6233 if (size == 3) {
6234 count = q + 1;
6235 } else {
6236 count = q ? 4: 2;
6239 /* To avoid excessive duplication of ops we implement shift
6240 * by immediate using the variable shift operations.
6242 imm = dup_const(size, shift);
6244 for (pass = 0; pass < count; pass++) {
6245 if (size == 3) {
6246 neon_load_reg64(cpu_V0, rm + pass);
6247 tcg_gen_movi_i64(cpu_V1, imm);
6248 switch (op) {
6249 case 2: /* VRSHR */
6250 case 3: /* VRSRA */
6251 if (u)
6252 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
6253 else
6254 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
6255 break;
6256 case 6: /* VQSHLU */
6257 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
6258 cpu_V0, cpu_V1);
6259 break;
6260 case 7: /* VQSHL */
6261 if (u) {
6262 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
6263 cpu_V0, cpu_V1);
6264 } else {
6265 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
6266 cpu_V0, cpu_V1);
6268 break;
6269 default:
6270 g_assert_not_reached();
6272 if (op == 3) {
6273 /* Accumulate. */
6274 neon_load_reg64(cpu_V1, rd + pass);
6275 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
6277 neon_store_reg64(cpu_V0, rd + pass);
6278 } else { /* size < 3 */
6279 /* Operands in T0 and T1. */
6280 tmp = neon_load_reg(rm, pass);
6281 tmp2 = tcg_temp_new_i32();
6282 tcg_gen_movi_i32(tmp2, imm);
6283 switch (op) {
6284 case 2: /* VRSHR */
6285 case 3: /* VRSRA */
6286 GEN_NEON_INTEGER_OP(rshl);
6287 break;
6288 case 6: /* VQSHLU */
6289 switch (size) {
6290 case 0:
6291 gen_helper_neon_qshlu_s8(tmp, cpu_env,
6292 tmp, tmp2);
6293 break;
6294 case 1:
6295 gen_helper_neon_qshlu_s16(tmp, cpu_env,
6296 tmp, tmp2);
6297 break;
6298 case 2:
6299 gen_helper_neon_qshlu_s32(tmp, cpu_env,
6300 tmp, tmp2);
6301 break;
6302 default:
6303 abort();
6305 break;
6306 case 7: /* VQSHL */
6307 GEN_NEON_INTEGER_OP_ENV(qshl);
6308 break;
6309 default:
6310 g_assert_not_reached();
6312 tcg_temp_free_i32(tmp2);
6314 if (op == 3) {
6315 /* Accumulate. */
6316 tmp2 = neon_load_reg(rd, pass);
6317 gen_neon_add(size, tmp, tmp2);
6318 tcg_temp_free_i32(tmp2);
6320 neon_store_reg(rd, pass, tmp);
6322 } /* for pass */
6323 } else if (op < 10) {
6324 /* Shift by immediate and narrow:
6325 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
6326 int input_unsigned = (op == 8) ? !u : u;
6327 if (rm & 1) {
6328 return 1;
6330 shift = shift - (1 << (size + 3));
6331 size++;
6332 if (size == 3) {
6333 tmp64 = tcg_const_i64(shift);
6334 neon_load_reg64(cpu_V0, rm);
6335 neon_load_reg64(cpu_V1, rm + 1);
6336 for (pass = 0; pass < 2; pass++) {
6337 TCGv_i64 in;
6338 if (pass == 0) {
6339 in = cpu_V0;
6340 } else {
6341 in = cpu_V1;
6343 if (q) {
6344 if (input_unsigned) {
6345 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
6346 } else {
6347 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
6349 } else {
6350 if (input_unsigned) {
6351 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
6352 } else {
6353 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
6356 tmp = tcg_temp_new_i32();
6357 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
6358 neon_store_reg(rd, pass, tmp);
6359 } /* for pass */
6360 tcg_temp_free_i64(tmp64);
6361 } else {
6362 if (size == 1) {
6363 imm = (uint16_t)shift;
6364 imm |= imm << 16;
6365 } else {
6366 /* size == 2 */
6367 imm = (uint32_t)shift;
6369 tmp2 = tcg_const_i32(imm);
6370 tmp4 = neon_load_reg(rm + 1, 0);
6371 tmp5 = neon_load_reg(rm + 1, 1);
6372 for (pass = 0; pass < 2; pass++) {
6373 if (pass == 0) {
6374 tmp = neon_load_reg(rm, 0);
6375 } else {
6376 tmp = tmp4;
6378 gen_neon_shift_narrow(size, tmp, tmp2, q,
6379 input_unsigned);
6380 if (pass == 0) {
6381 tmp3 = neon_load_reg(rm, 1);
6382 } else {
6383 tmp3 = tmp5;
6385 gen_neon_shift_narrow(size, tmp3, tmp2, q,
6386 input_unsigned);
6387 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
6388 tcg_temp_free_i32(tmp);
6389 tcg_temp_free_i32(tmp3);
6390 tmp = tcg_temp_new_i32();
6391 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
6392 neon_store_reg(rd, pass, tmp);
6393 } /* for pass */
6394 tcg_temp_free_i32(tmp2);
6396 } else if (op == 10) {
6397 /* VSHLL, VMOVL */
6398 if (q || (rd & 1)) {
6399 return 1;
6401 tmp = neon_load_reg(rm, 0);
6402 tmp2 = neon_load_reg(rm, 1);
6403 for (pass = 0; pass < 2; pass++) {
6404 if (pass == 1)
6405 tmp = tmp2;
6407 gen_neon_widen(cpu_V0, tmp, size, u);
6409 if (shift != 0) {
6410 /* The shift is less than the width of the source
6411 type, so we can just shift the whole register. */
6412 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
6413 /* Widen the result of shift: we need to clear
6414 * the potential overflow bits resulting from
6415 * left bits of the narrow input appearing as
6416 * right bits of left the neighbour narrow
6417 * input. */
6418 if (size < 2 || !u) {
6419 uint64_t imm64;
6420 if (size == 0) {
6421 imm = (0xffu >> (8 - shift));
6422 imm |= imm << 16;
6423 } else if (size == 1) {
6424 imm = 0xffff >> (16 - shift);
6425 } else {
6426 /* size == 2 */
6427 imm = 0xffffffff >> (32 - shift);
6429 if (size < 2) {
6430 imm64 = imm | (((uint64_t)imm) << 32);
6431 } else {
6432 imm64 = imm;
6434 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
6437 neon_store_reg64(cpu_V0, rd + pass);
6439 } else if (op >= 14) {
6440 /* VCVT fixed-point. */
6441 if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
6442 return 1;
6444 /* We have already masked out the must-be-1 top bit of imm6,
6445 * hence this 32-shift where the ARM ARM has 64-imm6.
6447 shift = 32 - shift;
6448 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6449 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
6450 if (!(op & 1)) {
6451 if (u)
6452 gen_vfp_ulto(0, shift, 1);
6453 else
6454 gen_vfp_slto(0, shift, 1);
6455 } else {
6456 if (u)
6457 gen_vfp_toul(0, shift, 1);
6458 else
6459 gen_vfp_tosl(0, shift, 1);
6461 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
6463 } else {
6464 return 1;
6466 } else { /* (insn & 0x00380080) == 0 */
6467 int invert, reg_ofs, vec_size;
6469 if (q && (rd & 1)) {
6470 return 1;
6473 op = (insn >> 8) & 0xf;
6474 /* One register and immediate. */
6475 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
6476 invert = (insn & (1 << 5)) != 0;
6477 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
6478 * We choose to not special-case this and will behave as if a
6479 * valid constant encoding of 0 had been given.
6481 switch (op) {
6482 case 0: case 1:
6483 /* no-op */
6484 break;
6485 case 2: case 3:
6486 imm <<= 8;
6487 break;
6488 case 4: case 5:
6489 imm <<= 16;
6490 break;
6491 case 6: case 7:
6492 imm <<= 24;
6493 break;
6494 case 8: case 9:
6495 imm |= imm << 16;
6496 break;
6497 case 10: case 11:
6498 imm = (imm << 8) | (imm << 24);
6499 break;
6500 case 12:
6501 imm = (imm << 8) | 0xff;
6502 break;
6503 case 13:
6504 imm = (imm << 16) | 0xffff;
6505 break;
6506 case 14:
6507 imm |= (imm << 8) | (imm << 16) | (imm << 24);
6508 if (invert) {
6509 imm = ~imm;
6511 break;
6512 case 15:
6513 if (invert) {
6514 return 1;
6516 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
6517 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
6518 break;
6520 if (invert) {
6521 imm = ~imm;
6524 reg_ofs = neon_reg_offset(rd, 0);
6525 vec_size = q ? 16 : 8;
6527 if (op & 1 && op < 12) {
6528 if (invert) {
6529 /* The immediate value has already been inverted,
6530 * so BIC becomes AND.
6532 tcg_gen_gvec_andi(MO_32, reg_ofs, reg_ofs, imm,
6533 vec_size, vec_size);
6534 } else {
6535 tcg_gen_gvec_ori(MO_32, reg_ofs, reg_ofs, imm,
6536 vec_size, vec_size);
6538 } else {
6539 /* VMOV, VMVN. */
6540 if (op == 14 && invert) {
6541 TCGv_i64 t64 = tcg_temp_new_i64();
6543 for (pass = 0; pass <= q; ++pass) {
6544 uint64_t val = 0;
6545 int n;
6547 for (n = 0; n < 8; n++) {
6548 if (imm & (1 << (n + pass * 8))) {
6549 val |= 0xffull << (n * 8);
6552 tcg_gen_movi_i64(t64, val);
6553 neon_store_reg64(t64, rd + pass);
6555 tcg_temp_free_i64(t64);
6556 } else {
6557 tcg_gen_gvec_dup32i(reg_ofs, vec_size, vec_size, imm);
6561 } else { /* (insn & 0x00800010 == 0x00800000) */
6562 if (size != 3) {
6563 op = (insn >> 8) & 0xf;
6564 if ((insn & (1 << 6)) == 0) {
6565 /* Three registers of different lengths. */
6566 int src1_wide;
6567 int src2_wide;
6568 int prewiden;
6569 /* undefreq: bit 0 : UNDEF if size == 0
6570 * bit 1 : UNDEF if size == 1
6571 * bit 2 : UNDEF if size == 2
6572 * bit 3 : UNDEF if U == 1
6573 * Note that [2:0] set implies 'always UNDEF'
6575 int undefreq;
6576 /* prewiden, src1_wide, src2_wide, undefreq */
6577 static const int neon_3reg_wide[16][4] = {
6578 {1, 0, 0, 0}, /* VADDL */
6579 {1, 1, 0, 0}, /* VADDW */
6580 {1, 0, 0, 0}, /* VSUBL */
6581 {1, 1, 0, 0}, /* VSUBW */
6582 {0, 1, 1, 0}, /* VADDHN */
6583 {0, 0, 0, 0}, /* VABAL */
6584 {0, 1, 1, 0}, /* VSUBHN */
6585 {0, 0, 0, 0}, /* VABDL */
6586 {0, 0, 0, 0}, /* VMLAL */
6587 {0, 0, 0, 9}, /* VQDMLAL */
6588 {0, 0, 0, 0}, /* VMLSL */
6589 {0, 0, 0, 9}, /* VQDMLSL */
6590 {0, 0, 0, 0}, /* Integer VMULL */
6591 {0, 0, 0, 1}, /* VQDMULL */
6592 {0, 0, 0, 0xa}, /* Polynomial VMULL */
6593 {0, 0, 0, 7}, /* Reserved: always UNDEF */
6596 prewiden = neon_3reg_wide[op][0];
6597 src1_wide = neon_3reg_wide[op][1];
6598 src2_wide = neon_3reg_wide[op][2];
6599 undefreq = neon_3reg_wide[op][3];
6601 if ((undefreq & (1 << size)) ||
6602 ((undefreq & 8) && u)) {
6603 return 1;
6605 if ((src1_wide && (rn & 1)) ||
6606 (src2_wide && (rm & 1)) ||
6607 (!src2_wide && (rd & 1))) {
6608 return 1;
6611 /* Handle VMULL.P64 (Polynomial 64x64 to 128 bit multiply)
6612 * outside the loop below as it only performs a single pass.
6614 if (op == 14 && size == 2) {
6615 TCGv_i64 tcg_rn, tcg_rm, tcg_rd;
6617 if (!dc_isar_feature(aa32_pmull, s)) {
6618 return 1;
6620 tcg_rn = tcg_temp_new_i64();
6621 tcg_rm = tcg_temp_new_i64();
6622 tcg_rd = tcg_temp_new_i64();
6623 neon_load_reg64(tcg_rn, rn);
6624 neon_load_reg64(tcg_rm, rm);
6625 gen_helper_neon_pmull_64_lo(tcg_rd, tcg_rn, tcg_rm);
6626 neon_store_reg64(tcg_rd, rd);
6627 gen_helper_neon_pmull_64_hi(tcg_rd, tcg_rn, tcg_rm);
6628 neon_store_reg64(tcg_rd, rd + 1);
6629 tcg_temp_free_i64(tcg_rn);
6630 tcg_temp_free_i64(tcg_rm);
6631 tcg_temp_free_i64(tcg_rd);
6632 return 0;
6635 /* Avoid overlapping operands. Wide source operands are
6636 always aligned so will never overlap with wide
6637 destinations in problematic ways. */
6638 if (rd == rm && !src2_wide) {
6639 tmp = neon_load_reg(rm, 1);
6640 neon_store_scratch(2, tmp);
6641 } else if (rd == rn && !src1_wide) {
6642 tmp = neon_load_reg(rn, 1);
6643 neon_store_scratch(2, tmp);
6645 tmp3 = NULL;
6646 for (pass = 0; pass < 2; pass++) {
6647 if (src1_wide) {
6648 neon_load_reg64(cpu_V0, rn + pass);
6649 tmp = NULL;
6650 } else {
6651 if (pass == 1 && rd == rn) {
6652 tmp = neon_load_scratch(2);
6653 } else {
6654 tmp = neon_load_reg(rn, pass);
6656 if (prewiden) {
6657 gen_neon_widen(cpu_V0, tmp, size, u);
6660 if (src2_wide) {
6661 neon_load_reg64(cpu_V1, rm + pass);
6662 tmp2 = NULL;
6663 } else {
6664 if (pass == 1 && rd == rm) {
6665 tmp2 = neon_load_scratch(2);
6666 } else {
6667 tmp2 = neon_load_reg(rm, pass);
6669 if (prewiden) {
6670 gen_neon_widen(cpu_V1, tmp2, size, u);
6673 switch (op) {
6674 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
6675 gen_neon_addl(size);
6676 break;
6677 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
6678 gen_neon_subl(size);
6679 break;
6680 case 5: case 7: /* VABAL, VABDL */
6681 switch ((size << 1) | u) {
6682 case 0:
6683 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
6684 break;
6685 case 1:
6686 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
6687 break;
6688 case 2:
6689 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
6690 break;
6691 case 3:
6692 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
6693 break;
6694 case 4:
6695 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
6696 break;
6697 case 5:
6698 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
6699 break;
6700 default: abort();
6702 tcg_temp_free_i32(tmp2);
6703 tcg_temp_free_i32(tmp);
6704 break;
6705 case 8: case 9: case 10: case 11: case 12: case 13:
6706 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
6707 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
6708 break;
6709 case 14: /* Polynomial VMULL */
6710 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
6711 tcg_temp_free_i32(tmp2);
6712 tcg_temp_free_i32(tmp);
6713 break;
6714 default: /* 15 is RESERVED: caught earlier */
6715 abort();
6717 if (op == 13) {
6718 /* VQDMULL */
6719 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6720 neon_store_reg64(cpu_V0, rd + pass);
6721 } else if (op == 5 || (op >= 8 && op <= 11)) {
6722 /* Accumulate. */
6723 neon_load_reg64(cpu_V1, rd + pass);
6724 switch (op) {
6725 case 10: /* VMLSL */
6726 gen_neon_negl(cpu_V0, size);
6727 /* Fall through */
6728 case 5: case 8: /* VABAL, VMLAL */
6729 gen_neon_addl(size);
6730 break;
6731 case 9: case 11: /* VQDMLAL, VQDMLSL */
6732 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6733 if (op == 11) {
6734 gen_neon_negl(cpu_V0, size);
6736 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
6737 break;
6738 default:
6739 abort();
6741 neon_store_reg64(cpu_V0, rd + pass);
6742 } else if (op == 4 || op == 6) {
6743 /* Narrowing operation. */
6744 tmp = tcg_temp_new_i32();
6745 if (!u) {
6746 switch (size) {
6747 case 0:
6748 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
6749 break;
6750 case 1:
6751 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
6752 break;
6753 case 2:
6754 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
6755 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
6756 break;
6757 default: abort();
6759 } else {
6760 switch (size) {
6761 case 0:
6762 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
6763 break;
6764 case 1:
6765 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
6766 break;
6767 case 2:
6768 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
6769 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
6770 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
6771 break;
6772 default: abort();
6775 if (pass == 0) {
6776 tmp3 = tmp;
6777 } else {
6778 neon_store_reg(rd, 0, tmp3);
6779 neon_store_reg(rd, 1, tmp);
6781 } else {
6782 /* Write back the result. */
6783 neon_store_reg64(cpu_V0, rd + pass);
6786 } else {
6787 /* Two registers and a scalar. NB that for ops of this form
6788 * the ARM ARM labels bit 24 as Q, but it is in our variable
6789 * 'u', not 'q'.
6791 if (size == 0) {
6792 return 1;
6794 switch (op) {
6795 case 1: /* Float VMLA scalar */
6796 case 5: /* Floating point VMLS scalar */
6797 case 9: /* Floating point VMUL scalar */
6798 if (size == 1) {
6799 return 1;
6801 /* fall through */
6802 case 0: /* Integer VMLA scalar */
6803 case 4: /* Integer VMLS scalar */
6804 case 8: /* Integer VMUL scalar */
6805 case 12: /* VQDMULH scalar */
6806 case 13: /* VQRDMULH scalar */
6807 if (u && ((rd | rn) & 1)) {
6808 return 1;
6810 tmp = neon_get_scalar(size, rm);
6811 neon_store_scratch(0, tmp);
6812 for (pass = 0; pass < (u ? 4 : 2); pass++) {
6813 tmp = neon_load_scratch(0);
6814 tmp2 = neon_load_reg(rn, pass);
6815 if (op == 12) {
6816 if (size == 1) {
6817 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
6818 } else {
6819 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
6821 } else if (op == 13) {
6822 if (size == 1) {
6823 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
6824 } else {
6825 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
6827 } else if (op & 1) {
6828 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6829 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
6830 tcg_temp_free_ptr(fpstatus);
6831 } else {
6832 switch (size) {
6833 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
6834 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
6835 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
6836 default: abort();
6839 tcg_temp_free_i32(tmp2);
6840 if (op < 8) {
6841 /* Accumulate. */
6842 tmp2 = neon_load_reg(rd, pass);
6843 switch (op) {
6844 case 0:
6845 gen_neon_add(size, tmp, tmp2);
6846 break;
6847 case 1:
6849 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6850 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
6851 tcg_temp_free_ptr(fpstatus);
6852 break;
6854 case 4:
6855 gen_neon_rsb(size, tmp, tmp2);
6856 break;
6857 case 5:
6859 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6860 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
6861 tcg_temp_free_ptr(fpstatus);
6862 break;
6864 default:
6865 abort();
6867 tcg_temp_free_i32(tmp2);
6869 neon_store_reg(rd, pass, tmp);
6871 break;
6872 case 3: /* VQDMLAL scalar */
6873 case 7: /* VQDMLSL scalar */
6874 case 11: /* VQDMULL scalar */
6875 if (u == 1) {
6876 return 1;
6878 /* fall through */
6879 case 2: /* VMLAL sclar */
6880 case 6: /* VMLSL scalar */
6881 case 10: /* VMULL scalar */
6882 if (rd & 1) {
6883 return 1;
6885 tmp2 = neon_get_scalar(size, rm);
6886 /* We need a copy of tmp2 because gen_neon_mull
6887 * deletes it during pass 0. */
6888 tmp4 = tcg_temp_new_i32();
6889 tcg_gen_mov_i32(tmp4, tmp2);
6890 tmp3 = neon_load_reg(rn, 1);
6892 for (pass = 0; pass < 2; pass++) {
6893 if (pass == 0) {
6894 tmp = neon_load_reg(rn, 0);
6895 } else {
6896 tmp = tmp3;
6897 tmp2 = tmp4;
6899 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
6900 if (op != 11) {
6901 neon_load_reg64(cpu_V1, rd + pass);
6903 switch (op) {
6904 case 6:
6905 gen_neon_negl(cpu_V0, size);
6906 /* Fall through */
6907 case 2:
6908 gen_neon_addl(size);
6909 break;
6910 case 3: case 7:
6911 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6912 if (op == 7) {
6913 gen_neon_negl(cpu_V0, size);
6915 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
6916 break;
6917 case 10:
6918 /* no-op */
6919 break;
6920 case 11:
6921 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6922 break;
6923 default:
6924 abort();
6926 neon_store_reg64(cpu_V0, rd + pass);
6928 break;
6929 case 14: /* VQRDMLAH scalar */
6930 case 15: /* VQRDMLSH scalar */
6932 NeonGenThreeOpEnvFn *fn;
6934 if (!dc_isar_feature(aa32_rdm, s)) {
6935 return 1;
6937 if (u && ((rd | rn) & 1)) {
6938 return 1;
6940 if (op == 14) {
6941 if (size == 1) {
6942 fn = gen_helper_neon_qrdmlah_s16;
6943 } else {
6944 fn = gen_helper_neon_qrdmlah_s32;
6946 } else {
6947 if (size == 1) {
6948 fn = gen_helper_neon_qrdmlsh_s16;
6949 } else {
6950 fn = gen_helper_neon_qrdmlsh_s32;
6954 tmp2 = neon_get_scalar(size, rm);
6955 for (pass = 0; pass < (u ? 4 : 2); pass++) {
6956 tmp = neon_load_reg(rn, pass);
6957 tmp3 = neon_load_reg(rd, pass);
6958 fn(tmp, cpu_env, tmp, tmp2, tmp3);
6959 tcg_temp_free_i32(tmp3);
6960 neon_store_reg(rd, pass, tmp);
6962 tcg_temp_free_i32(tmp2);
6964 break;
6965 default:
6966 g_assert_not_reached();
6969 } else { /* size == 3 */
6970 if (!u) {
6971 /* Extract. */
6972 imm = (insn >> 8) & 0xf;
6974 if (imm > 7 && !q)
6975 return 1;
6977 if (q && ((rd | rn | rm) & 1)) {
6978 return 1;
6981 if (imm == 0) {
6982 neon_load_reg64(cpu_V0, rn);
6983 if (q) {
6984 neon_load_reg64(cpu_V1, rn + 1);
6986 } else if (imm == 8) {
6987 neon_load_reg64(cpu_V0, rn + 1);
6988 if (q) {
6989 neon_load_reg64(cpu_V1, rm);
6991 } else if (q) {
6992 tmp64 = tcg_temp_new_i64();
6993 if (imm < 8) {
6994 neon_load_reg64(cpu_V0, rn);
6995 neon_load_reg64(tmp64, rn + 1);
6996 } else {
6997 neon_load_reg64(cpu_V0, rn + 1);
6998 neon_load_reg64(tmp64, rm);
7000 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
7001 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
7002 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
7003 if (imm < 8) {
7004 neon_load_reg64(cpu_V1, rm);
7005 } else {
7006 neon_load_reg64(cpu_V1, rm + 1);
7007 imm -= 8;
7009 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
7010 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
7011 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
7012 tcg_temp_free_i64(tmp64);
7013 } else {
7014 /* BUGFIX */
7015 neon_load_reg64(cpu_V0, rn);
7016 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
7017 neon_load_reg64(cpu_V1, rm);
7018 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
7019 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
7021 neon_store_reg64(cpu_V0, rd);
7022 if (q) {
7023 neon_store_reg64(cpu_V1, rd + 1);
7025 } else if ((insn & (1 << 11)) == 0) {
7026 /* Two register misc. */
7027 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
7028 size = (insn >> 18) & 3;
7029 /* UNDEF for unknown op values and bad op-size combinations */
7030 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
7031 return 1;
7033 if (neon_2rm_is_v8_op(op) &&
7034 !arm_dc_feature(s, ARM_FEATURE_V8)) {
7035 return 1;
7037 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
7038 q && ((rm | rd) & 1)) {
7039 return 1;
7041 switch (op) {
7042 case NEON_2RM_VREV64:
7043 for (pass = 0; pass < (q ? 2 : 1); pass++) {
7044 tmp = neon_load_reg(rm, pass * 2);
7045 tmp2 = neon_load_reg(rm, pass * 2 + 1);
7046 switch (size) {
7047 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
7048 case 1: gen_swap_half(tmp); break;
7049 case 2: /* no-op */ break;
7050 default: abort();
7052 neon_store_reg(rd, pass * 2 + 1, tmp);
7053 if (size == 2) {
7054 neon_store_reg(rd, pass * 2, tmp2);
7055 } else {
7056 switch (size) {
7057 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
7058 case 1: gen_swap_half(tmp2); break;
7059 default: abort();
7061 neon_store_reg(rd, pass * 2, tmp2);
7064 break;
7065 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
7066 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
7067 for (pass = 0; pass < q + 1; pass++) {
7068 tmp = neon_load_reg(rm, pass * 2);
7069 gen_neon_widen(cpu_V0, tmp, size, op & 1);
7070 tmp = neon_load_reg(rm, pass * 2 + 1);
7071 gen_neon_widen(cpu_V1, tmp, size, op & 1);
7072 switch (size) {
7073 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
7074 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
7075 case 2: tcg_gen_add_i64(CPU_V001); break;
7076 default: abort();
7078 if (op >= NEON_2RM_VPADAL) {
7079 /* Accumulate. */
7080 neon_load_reg64(cpu_V1, rd + pass);
7081 gen_neon_addl(size);
7083 neon_store_reg64(cpu_V0, rd + pass);
7085 break;
7086 case NEON_2RM_VTRN:
7087 if (size == 2) {
7088 int n;
7089 for (n = 0; n < (q ? 4 : 2); n += 2) {
7090 tmp = neon_load_reg(rm, n);
7091 tmp2 = neon_load_reg(rd, n + 1);
7092 neon_store_reg(rm, n, tmp2);
7093 neon_store_reg(rd, n + 1, tmp);
7095 } else {
7096 goto elementwise;
7098 break;
7099 case NEON_2RM_VUZP:
7100 if (gen_neon_unzip(rd, rm, size, q)) {
7101 return 1;
7103 break;
7104 case NEON_2RM_VZIP:
7105 if (gen_neon_zip(rd, rm, size, q)) {
7106 return 1;
7108 break;
7109 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
7110 /* also VQMOVUN; op field and mnemonics don't line up */
7111 if (rm & 1) {
7112 return 1;
7114 tmp2 = NULL;
7115 for (pass = 0; pass < 2; pass++) {
7116 neon_load_reg64(cpu_V0, rm + pass);
7117 tmp = tcg_temp_new_i32();
7118 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
7119 tmp, cpu_V0);
7120 if (pass == 0) {
7121 tmp2 = tmp;
7122 } else {
7123 neon_store_reg(rd, 0, tmp2);
7124 neon_store_reg(rd, 1, tmp);
7127 break;
7128 case NEON_2RM_VSHLL:
7129 if (q || (rd & 1)) {
7130 return 1;
7132 tmp = neon_load_reg(rm, 0);
7133 tmp2 = neon_load_reg(rm, 1);
7134 for (pass = 0; pass < 2; pass++) {
7135 if (pass == 1)
7136 tmp = tmp2;
7137 gen_neon_widen(cpu_V0, tmp, size, 1);
7138 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
7139 neon_store_reg64(cpu_V0, rd + pass);
7141 break;
7142 case NEON_2RM_VCVT_F16_F32:
7144 TCGv_ptr fpst;
7145 TCGv_i32 ahp;
7147 if (!dc_isar_feature(aa32_fp16_spconv, s) ||
7148 q || (rm & 1)) {
7149 return 1;
7151 tmp = tcg_temp_new_i32();
7152 tmp2 = tcg_temp_new_i32();
7153 fpst = get_fpstatus_ptr(true);
7154 ahp = get_ahp_flag();
7155 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
7156 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, fpst, ahp);
7157 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
7158 gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, fpst, ahp);
7159 tcg_gen_shli_i32(tmp2, tmp2, 16);
7160 tcg_gen_or_i32(tmp2, tmp2, tmp);
7161 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
7162 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, fpst, ahp);
7163 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
7164 neon_store_reg(rd, 0, tmp2);
7165 tmp2 = tcg_temp_new_i32();
7166 gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, fpst, ahp);
7167 tcg_gen_shli_i32(tmp2, tmp2, 16);
7168 tcg_gen_or_i32(tmp2, tmp2, tmp);
7169 neon_store_reg(rd, 1, tmp2);
7170 tcg_temp_free_i32(tmp);
7171 tcg_temp_free_i32(ahp);
7172 tcg_temp_free_ptr(fpst);
7173 break;
7175 case NEON_2RM_VCVT_F32_F16:
7177 TCGv_ptr fpst;
7178 TCGv_i32 ahp;
7179 if (!dc_isar_feature(aa32_fp16_spconv, s) ||
7180 q || (rd & 1)) {
7181 return 1;
7183 fpst = get_fpstatus_ptr(true);
7184 ahp = get_ahp_flag();
7185 tmp3 = tcg_temp_new_i32();
7186 tmp = neon_load_reg(rm, 0);
7187 tmp2 = neon_load_reg(rm, 1);
7188 tcg_gen_ext16u_i32(tmp3, tmp);
7189 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
7190 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
7191 tcg_gen_shri_i32(tmp3, tmp, 16);
7192 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
7193 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
7194 tcg_temp_free_i32(tmp);
7195 tcg_gen_ext16u_i32(tmp3, tmp2);
7196 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
7197 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
7198 tcg_gen_shri_i32(tmp3, tmp2, 16);
7199 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
7200 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
7201 tcg_temp_free_i32(tmp2);
7202 tcg_temp_free_i32(tmp3);
7203 tcg_temp_free_i32(ahp);
7204 tcg_temp_free_ptr(fpst);
7205 break;
7207 case NEON_2RM_AESE: case NEON_2RM_AESMC:
7208 if (!dc_isar_feature(aa32_aes, s) || ((rm | rd) & 1)) {
7209 return 1;
7211 ptr1 = vfp_reg_ptr(true, rd);
7212 ptr2 = vfp_reg_ptr(true, rm);
7214 /* Bit 6 is the lowest opcode bit; it distinguishes between
7215 * encryption (AESE/AESMC) and decryption (AESD/AESIMC)
7217 tmp3 = tcg_const_i32(extract32(insn, 6, 1));
7219 if (op == NEON_2RM_AESE) {
7220 gen_helper_crypto_aese(ptr1, ptr2, tmp3);
7221 } else {
7222 gen_helper_crypto_aesmc(ptr1, ptr2, tmp3);
7224 tcg_temp_free_ptr(ptr1);
7225 tcg_temp_free_ptr(ptr2);
7226 tcg_temp_free_i32(tmp3);
7227 break;
7228 case NEON_2RM_SHA1H:
7229 if (!dc_isar_feature(aa32_sha1, s) || ((rm | rd) & 1)) {
7230 return 1;
7232 ptr1 = vfp_reg_ptr(true, rd);
7233 ptr2 = vfp_reg_ptr(true, rm);
7235 gen_helper_crypto_sha1h(ptr1, ptr2);
7237 tcg_temp_free_ptr(ptr1);
7238 tcg_temp_free_ptr(ptr2);
7239 break;
7240 case NEON_2RM_SHA1SU1:
7241 if ((rm | rd) & 1) {
7242 return 1;
7244 /* bit 6 (q): set -> SHA256SU0, cleared -> SHA1SU1 */
7245 if (q) {
7246 if (!dc_isar_feature(aa32_sha2, s)) {
7247 return 1;
7249 } else if (!dc_isar_feature(aa32_sha1, s)) {
7250 return 1;
7252 ptr1 = vfp_reg_ptr(true, rd);
7253 ptr2 = vfp_reg_ptr(true, rm);
7254 if (q) {
7255 gen_helper_crypto_sha256su0(ptr1, ptr2);
7256 } else {
7257 gen_helper_crypto_sha1su1(ptr1, ptr2);
7259 tcg_temp_free_ptr(ptr1);
7260 tcg_temp_free_ptr(ptr2);
7261 break;
7263 case NEON_2RM_VMVN:
7264 tcg_gen_gvec_not(0, rd_ofs, rm_ofs, vec_size, vec_size);
7265 break;
7266 case NEON_2RM_VNEG:
7267 tcg_gen_gvec_neg(size, rd_ofs, rm_ofs, vec_size, vec_size);
7268 break;
7269 case NEON_2RM_VABS:
7270 tcg_gen_gvec_abs(size, rd_ofs, rm_ofs, vec_size, vec_size);
7271 break;
7273 default:
7274 elementwise:
7275 for (pass = 0; pass < (q ? 4 : 2); pass++) {
7276 if (neon_2rm_is_float_op(op)) {
7277 tcg_gen_ld_f32(cpu_F0s, cpu_env,
7278 neon_reg_offset(rm, pass));
7279 tmp = NULL;
7280 } else {
7281 tmp = neon_load_reg(rm, pass);
7283 switch (op) {
7284 case NEON_2RM_VREV32:
7285 switch (size) {
7286 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
7287 case 1: gen_swap_half(tmp); break;
7288 default: abort();
7290 break;
7291 case NEON_2RM_VREV16:
7292 gen_rev16(tmp);
7293 break;
7294 case NEON_2RM_VCLS:
7295 switch (size) {
7296 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
7297 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
7298 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
7299 default: abort();
7301 break;
7302 case NEON_2RM_VCLZ:
7303 switch (size) {
7304 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
7305 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
7306 case 2: tcg_gen_clzi_i32(tmp, tmp, 32); break;
7307 default: abort();
7309 break;
7310 case NEON_2RM_VCNT:
7311 gen_helper_neon_cnt_u8(tmp, tmp);
7312 break;
7313 case NEON_2RM_VQABS:
7314 switch (size) {
7315 case 0:
7316 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
7317 break;
7318 case 1:
7319 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
7320 break;
7321 case 2:
7322 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
7323 break;
7324 default: abort();
7326 break;
7327 case NEON_2RM_VQNEG:
7328 switch (size) {
7329 case 0:
7330 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
7331 break;
7332 case 1:
7333 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
7334 break;
7335 case 2:
7336 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
7337 break;
7338 default: abort();
7340 break;
7341 case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
7342 tmp2 = tcg_const_i32(0);
7343 switch(size) {
7344 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
7345 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
7346 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
7347 default: abort();
7349 tcg_temp_free_i32(tmp2);
7350 if (op == NEON_2RM_VCLE0) {
7351 tcg_gen_not_i32(tmp, tmp);
7353 break;
7354 case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
7355 tmp2 = tcg_const_i32(0);
7356 switch(size) {
7357 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
7358 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
7359 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
7360 default: abort();
7362 tcg_temp_free_i32(tmp2);
7363 if (op == NEON_2RM_VCLT0) {
7364 tcg_gen_not_i32(tmp, tmp);
7366 break;
7367 case NEON_2RM_VCEQ0:
7368 tmp2 = tcg_const_i32(0);
7369 switch(size) {
7370 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
7371 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
7372 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
7373 default: abort();
7375 tcg_temp_free_i32(tmp2);
7376 break;
7377 case NEON_2RM_VCGT0_F:
7379 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7380 tmp2 = tcg_const_i32(0);
7381 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
7382 tcg_temp_free_i32(tmp2);
7383 tcg_temp_free_ptr(fpstatus);
7384 break;
7386 case NEON_2RM_VCGE0_F:
7388 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7389 tmp2 = tcg_const_i32(0);
7390 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
7391 tcg_temp_free_i32(tmp2);
7392 tcg_temp_free_ptr(fpstatus);
7393 break;
7395 case NEON_2RM_VCEQ0_F:
7397 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7398 tmp2 = tcg_const_i32(0);
7399 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
7400 tcg_temp_free_i32(tmp2);
7401 tcg_temp_free_ptr(fpstatus);
7402 break;
7404 case NEON_2RM_VCLE0_F:
7406 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7407 tmp2 = tcg_const_i32(0);
7408 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
7409 tcg_temp_free_i32(tmp2);
7410 tcg_temp_free_ptr(fpstatus);
7411 break;
7413 case NEON_2RM_VCLT0_F:
7415 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7416 tmp2 = tcg_const_i32(0);
7417 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
7418 tcg_temp_free_i32(tmp2);
7419 tcg_temp_free_ptr(fpstatus);
7420 break;
7422 case NEON_2RM_VABS_F:
7423 gen_vfp_abs(0);
7424 break;
7425 case NEON_2RM_VNEG_F:
7426 gen_vfp_neg(0);
7427 break;
7428 case NEON_2RM_VSWP:
7429 tmp2 = neon_load_reg(rd, pass);
7430 neon_store_reg(rm, pass, tmp2);
7431 break;
7432 case NEON_2RM_VTRN:
7433 tmp2 = neon_load_reg(rd, pass);
7434 switch (size) {
7435 case 0: gen_neon_trn_u8(tmp, tmp2); break;
7436 case 1: gen_neon_trn_u16(tmp, tmp2); break;
7437 default: abort();
7439 neon_store_reg(rm, pass, tmp2);
7440 break;
7441 case NEON_2RM_VRINTN:
7442 case NEON_2RM_VRINTA:
7443 case NEON_2RM_VRINTM:
7444 case NEON_2RM_VRINTP:
7445 case NEON_2RM_VRINTZ:
7447 TCGv_i32 tcg_rmode;
7448 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7449 int rmode;
7451 if (op == NEON_2RM_VRINTZ) {
7452 rmode = FPROUNDING_ZERO;
7453 } else {
7454 rmode = fp_decode_rm[((op & 0x6) >> 1) ^ 1];
7457 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
7458 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
7459 cpu_env);
7460 gen_helper_rints(cpu_F0s, cpu_F0s, fpstatus);
7461 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
7462 cpu_env);
7463 tcg_temp_free_ptr(fpstatus);
7464 tcg_temp_free_i32(tcg_rmode);
7465 break;
7467 case NEON_2RM_VRINTX:
7469 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7470 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpstatus);
7471 tcg_temp_free_ptr(fpstatus);
7472 break;
7474 case NEON_2RM_VCVTAU:
7475 case NEON_2RM_VCVTAS:
7476 case NEON_2RM_VCVTNU:
7477 case NEON_2RM_VCVTNS:
7478 case NEON_2RM_VCVTPU:
7479 case NEON_2RM_VCVTPS:
7480 case NEON_2RM_VCVTMU:
7481 case NEON_2RM_VCVTMS:
7483 bool is_signed = !extract32(insn, 7, 1);
7484 TCGv_ptr fpst = get_fpstatus_ptr(1);
7485 TCGv_i32 tcg_rmode, tcg_shift;
7486 int rmode = fp_decode_rm[extract32(insn, 8, 2)];
7488 tcg_shift = tcg_const_i32(0);
7489 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
7490 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
7491 cpu_env);
7493 if (is_signed) {
7494 gen_helper_vfp_tosls(cpu_F0s, cpu_F0s,
7495 tcg_shift, fpst);
7496 } else {
7497 gen_helper_vfp_touls(cpu_F0s, cpu_F0s,
7498 tcg_shift, fpst);
7501 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
7502 cpu_env);
7503 tcg_temp_free_i32(tcg_rmode);
7504 tcg_temp_free_i32(tcg_shift);
7505 tcg_temp_free_ptr(fpst);
7506 break;
7508 case NEON_2RM_VRECPE:
7510 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7511 gen_helper_recpe_u32(tmp, tmp, fpstatus);
7512 tcg_temp_free_ptr(fpstatus);
7513 break;
7515 case NEON_2RM_VRSQRTE:
7517 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7518 gen_helper_rsqrte_u32(tmp, tmp, fpstatus);
7519 tcg_temp_free_ptr(fpstatus);
7520 break;
7522 case NEON_2RM_VRECPE_F:
7524 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7525 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, fpstatus);
7526 tcg_temp_free_ptr(fpstatus);
7527 break;
7529 case NEON_2RM_VRSQRTE_F:
7531 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7532 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, fpstatus);
7533 tcg_temp_free_ptr(fpstatus);
7534 break;
7536 case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
7537 gen_vfp_sito(0, 1);
7538 break;
7539 case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
7540 gen_vfp_uito(0, 1);
7541 break;
7542 case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
7543 gen_vfp_tosiz(0, 1);
7544 break;
7545 case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
7546 gen_vfp_touiz(0, 1);
7547 break;
7548 default:
7549 /* Reserved op values were caught by the
7550 * neon_2rm_sizes[] check earlier.
7552 abort();
7554 if (neon_2rm_is_float_op(op)) {
7555 tcg_gen_st_f32(cpu_F0s, cpu_env,
7556 neon_reg_offset(rd, pass));
7557 } else {
7558 neon_store_reg(rd, pass, tmp);
7561 break;
7563 } else if ((insn & (1 << 10)) == 0) {
7564 /* VTBL, VTBX. */
7565 int n = ((insn >> 8) & 3) + 1;
7566 if ((rn + n) > 32) {
7567 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
7568 * helper function running off the end of the register file.
7570 return 1;
7572 n <<= 3;
7573 if (insn & (1 << 6)) {
7574 tmp = neon_load_reg(rd, 0);
7575 } else {
7576 tmp = tcg_temp_new_i32();
7577 tcg_gen_movi_i32(tmp, 0);
7579 tmp2 = neon_load_reg(rm, 0);
7580 ptr1 = vfp_reg_ptr(true, rn);
7581 tmp5 = tcg_const_i32(n);
7582 gen_helper_neon_tbl(tmp2, tmp2, tmp, ptr1, tmp5);
7583 tcg_temp_free_i32(tmp);
7584 if (insn & (1 << 6)) {
7585 tmp = neon_load_reg(rd, 1);
7586 } else {
7587 tmp = tcg_temp_new_i32();
7588 tcg_gen_movi_i32(tmp, 0);
7590 tmp3 = neon_load_reg(rm, 1);
7591 gen_helper_neon_tbl(tmp3, tmp3, tmp, ptr1, tmp5);
7592 tcg_temp_free_i32(tmp5);
7593 tcg_temp_free_ptr(ptr1);
7594 neon_store_reg(rd, 0, tmp2);
7595 neon_store_reg(rd, 1, tmp3);
7596 tcg_temp_free_i32(tmp);
7597 } else if ((insn & 0x380) == 0) {
7598 /* VDUP */
7599 int element;
7600 TCGMemOp size;
7602 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
7603 return 1;
7605 if (insn & (1 << 16)) {
7606 size = MO_8;
7607 element = (insn >> 17) & 7;
7608 } else if (insn & (1 << 17)) {
7609 size = MO_16;
7610 element = (insn >> 18) & 3;
7611 } else {
7612 size = MO_32;
7613 element = (insn >> 19) & 1;
7615 tcg_gen_gvec_dup_mem(size, neon_reg_offset(rd, 0),
7616 neon_element_offset(rm, element, size),
7617 q ? 16 : 8, q ? 16 : 8);
7618 } else {
7619 return 1;
7623 return 0;
7626 /* Advanced SIMD three registers of the same length extension.
7627 * 31 25 23 22 20 16 12 11 10 9 8 3 0
7628 * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
7629 * | 1 1 1 1 1 1 0 | op1 | D | op2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
7630 * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
7632 static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
7634 gen_helper_gvec_3 *fn_gvec = NULL;
7635 gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
7636 int rd, rn, rm, opr_sz;
7637 int data = 0;
7638 int off_rn, off_rm;
7639 bool is_long = false, q = extract32(insn, 6, 1);
7640 bool ptr_is_env = false;
7642 if ((insn & 0xfe200f10) == 0xfc200800) {
7643 /* VCMLA -- 1111 110R R.1S .... .... 1000 ...0 .... */
7644 int size = extract32(insn, 20, 1);
7645 data = extract32(insn, 23, 2); /* rot */
7646 if (!dc_isar_feature(aa32_vcma, s)
7647 || (!size && !dc_isar_feature(aa32_fp16_arith, s))) {
7648 return 1;
7650 fn_gvec_ptr = size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
7651 } else if ((insn & 0xfea00f10) == 0xfc800800) {
7652 /* VCADD -- 1111 110R 1.0S .... .... 1000 ...0 .... */
7653 int size = extract32(insn, 20, 1);
7654 data = extract32(insn, 24, 1); /* rot */
7655 if (!dc_isar_feature(aa32_vcma, s)
7656 || (!size && !dc_isar_feature(aa32_fp16_arith, s))) {
7657 return 1;
7659 fn_gvec_ptr = size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
7660 } else if ((insn & 0xfeb00f00) == 0xfc200d00) {
7661 /* V[US]DOT -- 1111 1100 0.10 .... .... 1101 .Q.U .... */
7662 bool u = extract32(insn, 4, 1);
7663 if (!dc_isar_feature(aa32_dp, s)) {
7664 return 1;
7666 fn_gvec = u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b;
7667 } else if ((insn & 0xff300f10) == 0xfc200810) {
7668 /* VFM[AS]L -- 1111 1100 S.10 .... .... 1000 .Q.1 .... */
7669 int is_s = extract32(insn, 23, 1);
7670 if (!dc_isar_feature(aa32_fhm, s)) {
7671 return 1;
7673 is_long = true;
7674 data = is_s; /* is_2 == 0 */
7675 fn_gvec_ptr = gen_helper_gvec_fmlal_a32;
7676 ptr_is_env = true;
7677 } else {
7678 return 1;
7681 VFP_DREG_D(rd, insn);
7682 if (rd & q) {
7683 return 1;
7685 if (q || !is_long) {
7686 VFP_DREG_N(rn, insn);
7687 VFP_DREG_M(rm, insn);
7688 if ((rn | rm) & q & !is_long) {
7689 return 1;
7691 off_rn = vfp_reg_offset(1, rn);
7692 off_rm = vfp_reg_offset(1, rm);
7693 } else {
7694 rn = VFP_SREG_N(insn);
7695 rm = VFP_SREG_M(insn);
7696 off_rn = vfp_reg_offset(0, rn);
7697 off_rm = vfp_reg_offset(0, rm);
7700 if (s->fp_excp_el) {
7701 gen_exception_insn(s, 4, EXCP_UDEF,
7702 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
7703 return 0;
7705 if (!s->vfp_enabled) {
7706 return 1;
7709 opr_sz = (1 + q) * 8;
7710 if (fn_gvec_ptr) {
7711 TCGv_ptr ptr;
7712 if (ptr_is_env) {
7713 ptr = cpu_env;
7714 } else {
7715 ptr = get_fpstatus_ptr(1);
7717 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
7718 opr_sz, opr_sz, data, fn_gvec_ptr);
7719 if (!ptr_is_env) {
7720 tcg_temp_free_ptr(ptr);
7722 } else {
7723 tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
7724 opr_sz, opr_sz, data, fn_gvec);
7726 return 0;
7729 /* Advanced SIMD two registers and a scalar extension.
7730 * 31 24 23 22 20 16 12 11 10 9 8 3 0
7731 * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
7732 * | 1 1 1 1 1 1 1 0 | o1 | D | o2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
7733 * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
7737 static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
7739 gen_helper_gvec_3 *fn_gvec = NULL;
7740 gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
7741 int rd, rn, rm, opr_sz, data;
7742 int off_rn, off_rm;
7743 bool is_long = false, q = extract32(insn, 6, 1);
7744 bool ptr_is_env = false;
7746 if ((insn & 0xff000f10) == 0xfe000800) {
7747 /* VCMLA (indexed) -- 1111 1110 S.RR .... .... 1000 ...0 .... */
7748 int rot = extract32(insn, 20, 2);
7749 int size = extract32(insn, 23, 1);
7750 int index;
7752 if (!dc_isar_feature(aa32_vcma, s)) {
7753 return 1;
7755 if (size == 0) {
7756 if (!dc_isar_feature(aa32_fp16_arith, s)) {
7757 return 1;
7759 /* For fp16, rm is just Vm, and index is M. */
7760 rm = extract32(insn, 0, 4);
7761 index = extract32(insn, 5, 1);
7762 } else {
7763 /* For fp32, rm is the usual M:Vm, and index is 0. */
7764 VFP_DREG_M(rm, insn);
7765 index = 0;
7767 data = (index << 2) | rot;
7768 fn_gvec_ptr = (size ? gen_helper_gvec_fcmlas_idx
7769 : gen_helper_gvec_fcmlah_idx);
7770 } else if ((insn & 0xffb00f00) == 0xfe200d00) {
7771 /* V[US]DOT -- 1111 1110 0.10 .... .... 1101 .Q.U .... */
7772 int u = extract32(insn, 4, 1);
7774 if (!dc_isar_feature(aa32_dp, s)) {
7775 return 1;
7777 fn_gvec = u ? gen_helper_gvec_udot_idx_b : gen_helper_gvec_sdot_idx_b;
7778 /* rm is just Vm, and index is M. */
7779 data = extract32(insn, 5, 1); /* index */
7780 rm = extract32(insn, 0, 4);
7781 } else if ((insn & 0xffa00f10) == 0xfe000810) {
7782 /* VFM[AS]L -- 1111 1110 0.0S .... .... 1000 .Q.1 .... */
7783 int is_s = extract32(insn, 20, 1);
7784 int vm20 = extract32(insn, 0, 3);
7785 int vm3 = extract32(insn, 3, 1);
7786 int m = extract32(insn, 5, 1);
7787 int index;
7789 if (!dc_isar_feature(aa32_fhm, s)) {
7790 return 1;
7792 if (q) {
7793 rm = vm20;
7794 index = m * 2 + vm3;
7795 } else {
7796 rm = vm20 * 2 + m;
7797 index = vm3;
7799 is_long = true;
7800 data = (index << 2) | is_s; /* is_2 == 0 */
7801 fn_gvec_ptr = gen_helper_gvec_fmlal_idx_a32;
7802 ptr_is_env = true;
7803 } else {
7804 return 1;
7807 VFP_DREG_D(rd, insn);
7808 if (rd & q) {
7809 return 1;
7811 if (q || !is_long) {
7812 VFP_DREG_N(rn, insn);
7813 if (rn & q & !is_long) {
7814 return 1;
7816 off_rn = vfp_reg_offset(1, rn);
7817 off_rm = vfp_reg_offset(1, rm);
7818 } else {
7819 rn = VFP_SREG_N(insn);
7820 off_rn = vfp_reg_offset(0, rn);
7821 off_rm = vfp_reg_offset(0, rm);
7823 if (s->fp_excp_el) {
7824 gen_exception_insn(s, 4, EXCP_UDEF,
7825 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
7826 return 0;
7828 if (!s->vfp_enabled) {
7829 return 1;
7832 opr_sz = (1 + q) * 8;
7833 if (fn_gvec_ptr) {
7834 TCGv_ptr ptr;
7835 if (ptr_is_env) {
7836 ptr = cpu_env;
7837 } else {
7838 ptr = get_fpstatus_ptr(1);
7840 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
7841 opr_sz, opr_sz, data, fn_gvec_ptr);
7842 if (!ptr_is_env) {
7843 tcg_temp_free_ptr(ptr);
7845 } else {
7846 tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
7847 opr_sz, opr_sz, data, fn_gvec);
7849 return 0;
7852 static int disas_coproc_insn(DisasContext *s, uint32_t insn)
7854 int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
7855 const ARMCPRegInfo *ri;
7857 cpnum = (insn >> 8) & 0xf;
7859 /* First check for coprocessor space used for XScale/iwMMXt insns */
7860 if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cpnum < 2)) {
7861 if (extract32(s->c15_cpar, cpnum, 1) == 0) {
7862 return 1;
7864 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
7865 return disas_iwmmxt_insn(s, insn);
7866 } else if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
7867 return disas_dsp_insn(s, insn);
7869 return 1;
7872 /* Otherwise treat as a generic register access */
7873 is64 = (insn & (1 << 25)) == 0;
7874 if (!is64 && ((insn & (1 << 4)) == 0)) {
7875 /* cdp */
7876 return 1;
7879 crm = insn & 0xf;
7880 if (is64) {
7881 crn = 0;
7882 opc1 = (insn >> 4) & 0xf;
7883 opc2 = 0;
7884 rt2 = (insn >> 16) & 0xf;
7885 } else {
7886 crn = (insn >> 16) & 0xf;
7887 opc1 = (insn >> 21) & 7;
7888 opc2 = (insn >> 5) & 7;
7889 rt2 = 0;
7891 isread = (insn >> 20) & 1;
7892 rt = (insn >> 12) & 0xf;
7894 ri = get_arm_cp_reginfo(s->cp_regs,
7895 ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
7896 if (ri) {
7897 /* Check access permissions */
7898 if (!cp_access_ok(s->current_el, ri, isread)) {
7899 return 1;
7902 if (ri->accessfn ||
7903 (arm_dc_feature(s, ARM_FEATURE_XSCALE) && cpnum < 14)) {
7904 /* Emit code to perform further access permissions checks at
7905 * runtime; this may result in an exception.
7906 * Note that on XScale all cp0..c13 registers do an access check
7907 * call in order to handle c15_cpar.
7909 TCGv_ptr tmpptr;
7910 TCGv_i32 tcg_syn, tcg_isread;
7911 uint32_t syndrome;
7913 /* Note that since we are an implementation which takes an
7914 * exception on a trapped conditional instruction only if the
7915 * instruction passes its condition code check, we can take
7916 * advantage of the clause in the ARM ARM that allows us to set
7917 * the COND field in the instruction to 0xE in all cases.
7918 * We could fish the actual condition out of the insn (ARM)
7919 * or the condexec bits (Thumb) but it isn't necessary.
7921 switch (cpnum) {
7922 case 14:
7923 if (is64) {
7924 syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
7925 isread, false);
7926 } else {
7927 syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
7928 rt, isread, false);
7930 break;
7931 case 15:
7932 if (is64) {
7933 syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
7934 isread, false);
7935 } else {
7936 syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
7937 rt, isread, false);
7939 break;
7940 default:
7941 /* ARMv8 defines that only coprocessors 14 and 15 exist,
7942 * so this can only happen if this is an ARMv7 or earlier CPU,
7943 * in which case the syndrome information won't actually be
7944 * guest visible.
7946 assert(!arm_dc_feature(s, ARM_FEATURE_V8));
7947 syndrome = syn_uncategorized();
7948 break;
7951 gen_set_condexec(s);
7952 gen_set_pc_im(s, s->pc - 4);
7953 tmpptr = tcg_const_ptr(ri);
7954 tcg_syn = tcg_const_i32(syndrome);
7955 tcg_isread = tcg_const_i32(isread);
7956 gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn,
7957 tcg_isread);
7958 tcg_temp_free_ptr(tmpptr);
7959 tcg_temp_free_i32(tcg_syn);
7960 tcg_temp_free_i32(tcg_isread);
7963 /* Handle special cases first */
7964 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
7965 case ARM_CP_NOP:
7966 return 0;
7967 case ARM_CP_WFI:
7968 if (isread) {
7969 return 1;
7971 gen_set_pc_im(s, s->pc);
7972 s->base.is_jmp = DISAS_WFI;
7973 return 0;
7974 default:
7975 break;
7978 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
7979 gen_io_start();
7982 if (isread) {
7983 /* Read */
7984 if (is64) {
7985 TCGv_i64 tmp64;
7986 TCGv_i32 tmp;
7987 if (ri->type & ARM_CP_CONST) {
7988 tmp64 = tcg_const_i64(ri->resetvalue);
7989 } else if (ri->readfn) {
7990 TCGv_ptr tmpptr;
7991 tmp64 = tcg_temp_new_i64();
7992 tmpptr = tcg_const_ptr(ri);
7993 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
7994 tcg_temp_free_ptr(tmpptr);
7995 } else {
7996 tmp64 = tcg_temp_new_i64();
7997 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
7999 tmp = tcg_temp_new_i32();
8000 tcg_gen_extrl_i64_i32(tmp, tmp64);
8001 store_reg(s, rt, tmp);
8002 tcg_gen_shri_i64(tmp64, tmp64, 32);
8003 tmp = tcg_temp_new_i32();
8004 tcg_gen_extrl_i64_i32(tmp, tmp64);
8005 tcg_temp_free_i64(tmp64);
8006 store_reg(s, rt2, tmp);
8007 } else {
8008 TCGv_i32 tmp;
8009 if (ri->type & ARM_CP_CONST) {
8010 tmp = tcg_const_i32(ri->resetvalue);
8011 } else if (ri->readfn) {
8012 TCGv_ptr tmpptr;
8013 tmp = tcg_temp_new_i32();
8014 tmpptr = tcg_const_ptr(ri);
8015 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
8016 tcg_temp_free_ptr(tmpptr);
8017 } else {
8018 tmp = load_cpu_offset(ri->fieldoffset);
8020 if (rt == 15) {
8021 /* Destination register of r15 for 32 bit loads sets
8022 * the condition codes from the high 4 bits of the value
8024 gen_set_nzcv(tmp);
8025 tcg_temp_free_i32(tmp);
8026 } else {
8027 store_reg(s, rt, tmp);
8030 } else {
8031 /* Write */
8032 if (ri->type & ARM_CP_CONST) {
8033 /* If not forbidden by access permissions, treat as WI */
8034 return 0;
8037 if (is64) {
8038 TCGv_i32 tmplo, tmphi;
8039 TCGv_i64 tmp64 = tcg_temp_new_i64();
8040 tmplo = load_reg(s, rt);
8041 tmphi = load_reg(s, rt2);
8042 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
8043 tcg_temp_free_i32(tmplo);
8044 tcg_temp_free_i32(tmphi);
8045 if (ri->writefn) {
8046 TCGv_ptr tmpptr = tcg_const_ptr(ri);
8047 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
8048 tcg_temp_free_ptr(tmpptr);
8049 } else {
8050 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
8052 tcg_temp_free_i64(tmp64);
8053 } else {
8054 if (ri->writefn) {
8055 TCGv_i32 tmp;
8056 TCGv_ptr tmpptr;
8057 tmp = load_reg(s, rt);
8058 tmpptr = tcg_const_ptr(ri);
8059 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
8060 tcg_temp_free_ptr(tmpptr);
8061 tcg_temp_free_i32(tmp);
8062 } else {
8063 TCGv_i32 tmp = load_reg(s, rt);
8064 store_cpu_offset(tmp, ri->fieldoffset);
8069 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
8070 /* I/O operations must end the TB here (whether read or write) */
8071 gen_io_end();
8072 gen_lookup_tb(s);
8073 } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
8074 /* We default to ending the TB on a coprocessor register write,
8075 * but allow this to be suppressed by the register definition
8076 * (usually only necessary to work around guest bugs).
8078 gen_lookup_tb(s);
8081 return 0;
8084 /* Unknown register; this might be a guest error or a QEMU
8085 * unimplemented feature.
8087 if (is64) {
8088 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
8089 "64 bit system register cp:%d opc1: %d crm:%d "
8090 "(%s)\n",
8091 isread ? "read" : "write", cpnum, opc1, crm,
8092 s->ns ? "non-secure" : "secure");
8093 } else {
8094 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
8095 "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d "
8096 "(%s)\n",
8097 isread ? "read" : "write", cpnum, opc1, crn, crm, opc2,
8098 s->ns ? "non-secure" : "secure");
8101 return 1;
8105 /* Store a 64-bit value to a register pair. Clobbers val. */
8106 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
8108 TCGv_i32 tmp;
8109 tmp = tcg_temp_new_i32();
8110 tcg_gen_extrl_i64_i32(tmp, val);
8111 store_reg(s, rlow, tmp);
8112 tmp = tcg_temp_new_i32();
8113 tcg_gen_shri_i64(val, val, 32);
8114 tcg_gen_extrl_i64_i32(tmp, val);
8115 store_reg(s, rhigh, tmp);
8118 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
8119 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
8121 TCGv_i64 tmp;
8122 TCGv_i32 tmp2;
8124 /* Load value and extend to 64 bits. */
8125 tmp = tcg_temp_new_i64();
8126 tmp2 = load_reg(s, rlow);
8127 tcg_gen_extu_i32_i64(tmp, tmp2);
8128 tcg_temp_free_i32(tmp2);
8129 tcg_gen_add_i64(val, val, tmp);
8130 tcg_temp_free_i64(tmp);
8133 /* load and add a 64-bit value from a register pair. */
8134 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
8136 TCGv_i64 tmp;
8137 TCGv_i32 tmpl;
8138 TCGv_i32 tmph;
8140 /* Load 64-bit value rd:rn. */
8141 tmpl = load_reg(s, rlow);
8142 tmph = load_reg(s, rhigh);
8143 tmp = tcg_temp_new_i64();
8144 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
8145 tcg_temp_free_i32(tmpl);
8146 tcg_temp_free_i32(tmph);
8147 tcg_gen_add_i64(val, val, tmp);
8148 tcg_temp_free_i64(tmp);
8151 /* Set N and Z flags from hi|lo. */
8152 static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
8154 tcg_gen_mov_i32(cpu_NF, hi);
8155 tcg_gen_or_i32(cpu_ZF, lo, hi);
8158 /* Load/Store exclusive instructions are implemented by remembering
8159 the value/address loaded, and seeing if these are the same
8160 when the store is performed. This should be sufficient to implement
8161 the architecturally mandated semantics, and avoids having to monitor
8162 regular stores. The compare vs the remembered value is done during
8163 the cmpxchg operation, but we must compare the addresses manually. */
8164 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
8165 TCGv_i32 addr, int size)
8167 TCGv_i32 tmp = tcg_temp_new_i32();
8168 TCGMemOp opc = size | MO_ALIGN | s->be_data;
8170 s->is_ldex = true;
8172 if (size == 3) {
8173 TCGv_i32 tmp2 = tcg_temp_new_i32();
8174 TCGv_i64 t64 = tcg_temp_new_i64();
8176 /* For AArch32, architecturally the 32-bit word at the lowest
8177 * address is always Rt and the one at addr+4 is Rt2, even if
8178 * the CPU is big-endian. That means we don't want to do a
8179 * gen_aa32_ld_i64(), which invokes gen_aa32_frob64() as if
8180 * for an architecturally 64-bit access, but instead do a
8181 * 64-bit access using MO_BE if appropriate and then split
8182 * the two halves.
8183 * This only makes a difference for BE32 user-mode, where
8184 * frob64() must not flip the two halves of the 64-bit data
8185 * but this code must treat BE32 user-mode like BE32 system.
8187 TCGv taddr = gen_aa32_addr(s, addr, opc);
8189 tcg_gen_qemu_ld_i64(t64, taddr, get_mem_index(s), opc);
8190 tcg_temp_free(taddr);
8191 tcg_gen_mov_i64(cpu_exclusive_val, t64);
8192 if (s->be_data == MO_BE) {
8193 tcg_gen_extr_i64_i32(tmp2, tmp, t64);
8194 } else {
8195 tcg_gen_extr_i64_i32(tmp, tmp2, t64);
8197 tcg_temp_free_i64(t64);
8199 store_reg(s, rt2, tmp2);
8200 } else {
8201 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), opc);
8202 tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
8205 store_reg(s, rt, tmp);
8206 tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
8209 static void gen_clrex(DisasContext *s)
8211 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
8214 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
8215 TCGv_i32 addr, int size)
8217 TCGv_i32 t0, t1, t2;
8218 TCGv_i64 extaddr;
8219 TCGv taddr;
8220 TCGLabel *done_label;
8221 TCGLabel *fail_label;
8222 TCGMemOp opc = size | MO_ALIGN | s->be_data;
8224 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
8225 [addr] = {Rt};
8226 {Rd} = 0;
8227 } else {
8228 {Rd} = 1;
8229 } */
8230 fail_label = gen_new_label();
8231 done_label = gen_new_label();
8232 extaddr = tcg_temp_new_i64();
8233 tcg_gen_extu_i32_i64(extaddr, addr);
8234 tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
8235 tcg_temp_free_i64(extaddr);
8237 taddr = gen_aa32_addr(s, addr, opc);
8238 t0 = tcg_temp_new_i32();
8239 t1 = load_reg(s, rt);
8240 if (size == 3) {
8241 TCGv_i64 o64 = tcg_temp_new_i64();
8242 TCGv_i64 n64 = tcg_temp_new_i64();
8244 t2 = load_reg(s, rt2);
8245 /* For AArch32, architecturally the 32-bit word at the lowest
8246 * address is always Rt and the one at addr+4 is Rt2, even if
8247 * the CPU is big-endian. Since we're going to treat this as a
8248 * single 64-bit BE store, we need to put the two halves in the
8249 * opposite order for BE to LE, so that they end up in the right
8250 * places.
8251 * We don't want gen_aa32_frob64() because that does the wrong
8252 * thing for BE32 usermode.
8254 if (s->be_data == MO_BE) {
8255 tcg_gen_concat_i32_i64(n64, t2, t1);
8256 } else {
8257 tcg_gen_concat_i32_i64(n64, t1, t2);
8259 tcg_temp_free_i32(t2);
8261 tcg_gen_atomic_cmpxchg_i64(o64, taddr, cpu_exclusive_val, n64,
8262 get_mem_index(s), opc);
8263 tcg_temp_free_i64(n64);
8265 tcg_gen_setcond_i64(TCG_COND_NE, o64, o64, cpu_exclusive_val);
8266 tcg_gen_extrl_i64_i32(t0, o64);
8268 tcg_temp_free_i64(o64);
8269 } else {
8270 t2 = tcg_temp_new_i32();
8271 tcg_gen_extrl_i64_i32(t2, cpu_exclusive_val);
8272 tcg_gen_atomic_cmpxchg_i32(t0, taddr, t2, t1, get_mem_index(s), opc);
8273 tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t2);
8274 tcg_temp_free_i32(t2);
8276 tcg_temp_free_i32(t1);
8277 tcg_temp_free(taddr);
8278 tcg_gen_mov_i32(cpu_R[rd], t0);
8279 tcg_temp_free_i32(t0);
8280 tcg_gen_br(done_label);
8282 gen_set_label(fail_label);
8283 tcg_gen_movi_i32(cpu_R[rd], 1);
8284 gen_set_label(done_label);
8285 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
8288 /* gen_srs:
8289 * @env: CPUARMState
8290 * @s: DisasContext
8291 * @mode: mode field from insn (which stack to store to)
8292 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
8293 * @writeback: true if writeback bit set
8295 * Generate code for the SRS (Store Return State) insn.
8297 static void gen_srs(DisasContext *s,
8298 uint32_t mode, uint32_t amode, bool writeback)
8300 int32_t offset;
8301 TCGv_i32 addr, tmp;
8302 bool undef = false;
8304 /* SRS is:
8305 * - trapped to EL3 if EL3 is AArch64 and we are at Secure EL1
8306 * and specified mode is monitor mode
8307 * - UNDEFINED in Hyp mode
8308 * - UNPREDICTABLE in User or System mode
8309 * - UNPREDICTABLE if the specified mode is:
8310 * -- not implemented
8311 * -- not a valid mode number
8312 * -- a mode that's at a higher exception level
8313 * -- Monitor, if we are Non-secure
8314 * For the UNPREDICTABLE cases we choose to UNDEF.
8316 if (s->current_el == 1 && !s->ns && mode == ARM_CPU_MODE_MON) {
8317 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), 3);
8318 return;
8321 if (s->current_el == 0 || s->current_el == 2) {
8322 undef = true;
8325 switch (mode) {
8326 case ARM_CPU_MODE_USR:
8327 case ARM_CPU_MODE_FIQ:
8328 case ARM_CPU_MODE_IRQ:
8329 case ARM_CPU_MODE_SVC:
8330 case ARM_CPU_MODE_ABT:
8331 case ARM_CPU_MODE_UND:
8332 case ARM_CPU_MODE_SYS:
8333 break;
8334 case ARM_CPU_MODE_HYP:
8335 if (s->current_el == 1 || !arm_dc_feature(s, ARM_FEATURE_EL2)) {
8336 undef = true;
8338 break;
8339 case ARM_CPU_MODE_MON:
8340 /* No need to check specifically for "are we non-secure" because
8341 * we've already made EL0 UNDEF and handled the trap for S-EL1;
8342 * so if this isn't EL3 then we must be non-secure.
8344 if (s->current_el != 3) {
8345 undef = true;
8347 break;
8348 default:
8349 undef = true;
8352 if (undef) {
8353 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
8354 default_exception_el(s));
8355 return;
8358 addr = tcg_temp_new_i32();
8359 tmp = tcg_const_i32(mode);
8360 /* get_r13_banked() will raise an exception if called from System mode */
8361 gen_set_condexec(s);
8362 gen_set_pc_im(s, s->pc - 4);
8363 gen_helper_get_r13_banked(addr, cpu_env, tmp);
8364 tcg_temp_free_i32(tmp);
8365 switch (amode) {
8366 case 0: /* DA */
8367 offset = -4;
8368 break;
8369 case 1: /* IA */
8370 offset = 0;
8371 break;
8372 case 2: /* DB */
8373 offset = -8;
8374 break;
8375 case 3: /* IB */
8376 offset = 4;
8377 break;
8378 default:
8379 abort();
8381 tcg_gen_addi_i32(addr, addr, offset);
8382 tmp = load_reg(s, 14);
8383 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
8384 tcg_temp_free_i32(tmp);
8385 tmp = load_cpu_field(spsr);
8386 tcg_gen_addi_i32(addr, addr, 4);
8387 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
8388 tcg_temp_free_i32(tmp);
8389 if (writeback) {
8390 switch (amode) {
8391 case 0:
8392 offset = -8;
8393 break;
8394 case 1:
8395 offset = 4;
8396 break;
8397 case 2:
8398 offset = -4;
8399 break;
8400 case 3:
8401 offset = 0;
8402 break;
8403 default:
8404 abort();
8406 tcg_gen_addi_i32(addr, addr, offset);
8407 tmp = tcg_const_i32(mode);
8408 gen_helper_set_r13_banked(cpu_env, tmp, addr);
8409 tcg_temp_free_i32(tmp);
8411 tcg_temp_free_i32(addr);
8412 s->base.is_jmp = DISAS_UPDATE;
8415 /* Generate a label used for skipping this instruction */
8416 static void arm_gen_condlabel(DisasContext *s)
8418 if (!s->condjmp) {
8419 s->condlabel = gen_new_label();
8420 s->condjmp = 1;
8424 /* Skip this instruction if the ARM condition is false */
8425 static void arm_skip_unless(DisasContext *s, uint32_t cond)
8427 arm_gen_condlabel(s);
8428 arm_gen_test_cc(cond ^ 1, s->condlabel);
8431 static void disas_arm_insn(DisasContext *s, unsigned int insn)
8433 unsigned int cond, val, op1, i, shift, rm, rs, rn, rd, sh;
8434 TCGv_i32 tmp;
8435 TCGv_i32 tmp2;
8436 TCGv_i32 tmp3;
8437 TCGv_i32 addr;
8438 TCGv_i64 tmp64;
8440 /* M variants do not implement ARM mode; this must raise the INVSTATE
8441 * UsageFault exception.
8443 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8444 gen_exception_insn(s, 4, EXCP_INVSTATE, syn_uncategorized(),
8445 default_exception_el(s));
8446 return;
8448 cond = insn >> 28;
8449 if (cond == 0xf){
8450 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
8451 * choose to UNDEF. In ARMv5 and above the space is used
8452 * for miscellaneous unconditional instructions.
8454 ARCH(5);
8456 /* Unconditional instructions. */
8457 if (((insn >> 25) & 7) == 1) {
8458 /* NEON Data processing. */
8459 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
8460 goto illegal_op;
8463 if (disas_neon_data_insn(s, insn)) {
8464 goto illegal_op;
8466 return;
8468 if ((insn & 0x0f100000) == 0x04000000) {
8469 /* NEON load/store. */
8470 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
8471 goto illegal_op;
8474 if (disas_neon_ls_insn(s, insn)) {
8475 goto illegal_op;
8477 return;
8479 if ((insn & 0x0f000e10) == 0x0e000a00) {
8480 /* VFP. */
8481 if (disas_vfp_insn(s, insn)) {
8482 goto illegal_op;
8484 return;
8486 if (((insn & 0x0f30f000) == 0x0510f000) ||
8487 ((insn & 0x0f30f010) == 0x0710f000)) {
8488 if ((insn & (1 << 22)) == 0) {
8489 /* PLDW; v7MP */
8490 if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
8491 goto illegal_op;
8494 /* Otherwise PLD; v5TE+ */
8495 ARCH(5TE);
8496 return;
8498 if (((insn & 0x0f70f000) == 0x0450f000) ||
8499 ((insn & 0x0f70f010) == 0x0650f000)) {
8500 ARCH(7);
8501 return; /* PLI; V7 */
8503 if (((insn & 0x0f700000) == 0x04100000) ||
8504 ((insn & 0x0f700010) == 0x06100000)) {
8505 if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
8506 goto illegal_op;
8508 return; /* v7MP: Unallocated memory hint: must NOP */
8511 if ((insn & 0x0ffffdff) == 0x01010000) {
8512 ARCH(6);
8513 /* setend */
8514 if (((insn >> 9) & 1) != !!(s->be_data == MO_BE)) {
8515 gen_helper_setend(cpu_env);
8516 s->base.is_jmp = DISAS_UPDATE;
8518 return;
8519 } else if ((insn & 0x0fffff00) == 0x057ff000) {
8520 switch ((insn >> 4) & 0xf) {
8521 case 1: /* clrex */
8522 ARCH(6K);
8523 gen_clrex(s);
8524 return;
8525 case 4: /* dsb */
8526 case 5: /* dmb */
8527 ARCH(7);
8528 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
8529 return;
8530 case 6: /* isb */
8531 /* We need to break the TB after this insn to execute
8532 * self-modifying code correctly and also to take
8533 * any pending interrupts immediately.
8535 gen_goto_tb(s, 0, s->pc & ~1);
8536 return;
8537 case 7: /* sb */
8538 if ((insn & 0xf) || !dc_isar_feature(aa32_sb, s)) {
8539 goto illegal_op;
8542 * TODO: There is no speculation barrier opcode
8543 * for TCG; MB and end the TB instead.
8545 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
8546 gen_goto_tb(s, 0, s->pc & ~1);
8547 return;
8548 default:
8549 goto illegal_op;
8551 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
8552 /* srs */
8553 ARCH(6);
8554 gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21));
8555 return;
8556 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
8557 /* rfe */
8558 int32_t offset;
8559 if (IS_USER(s))
8560 goto illegal_op;
8561 ARCH(6);
8562 rn = (insn >> 16) & 0xf;
8563 addr = load_reg(s, rn);
8564 i = (insn >> 23) & 3;
8565 switch (i) {
8566 case 0: offset = -4; break; /* DA */
8567 case 1: offset = 0; break; /* IA */
8568 case 2: offset = -8; break; /* DB */
8569 case 3: offset = 4; break; /* IB */
8570 default: abort();
8572 if (offset)
8573 tcg_gen_addi_i32(addr, addr, offset);
8574 /* Load PC into tmp and CPSR into tmp2. */
8575 tmp = tcg_temp_new_i32();
8576 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
8577 tcg_gen_addi_i32(addr, addr, 4);
8578 tmp2 = tcg_temp_new_i32();
8579 gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
8580 if (insn & (1 << 21)) {
8581 /* Base writeback. */
8582 switch (i) {
8583 case 0: offset = -8; break;
8584 case 1: offset = 4; break;
8585 case 2: offset = -4; break;
8586 case 3: offset = 0; break;
8587 default: abort();
8589 if (offset)
8590 tcg_gen_addi_i32(addr, addr, offset);
8591 store_reg(s, rn, addr);
8592 } else {
8593 tcg_temp_free_i32(addr);
8595 gen_rfe(s, tmp, tmp2);
8596 return;
8597 } else if ((insn & 0x0e000000) == 0x0a000000) {
8598 /* branch link and change to thumb (blx <offset>) */
8599 int32_t offset;
8601 val = (uint32_t)s->pc;
8602 tmp = tcg_temp_new_i32();
8603 tcg_gen_movi_i32(tmp, val);
8604 store_reg(s, 14, tmp);
8605 /* Sign-extend the 24-bit offset */
8606 offset = (((int32_t)insn) << 8) >> 8;
8607 /* offset * 4 + bit24 * 2 + (thumb bit) */
8608 val += (offset << 2) | ((insn >> 23) & 2) | 1;
8609 /* pipeline offset */
8610 val += 4;
8611 /* protected by ARCH(5); above, near the start of uncond block */
8612 gen_bx_im(s, val);
8613 return;
8614 } else if ((insn & 0x0e000f00) == 0x0c000100) {
8615 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
8616 /* iWMMXt register transfer. */
8617 if (extract32(s->c15_cpar, 1, 1)) {
8618 if (!disas_iwmmxt_insn(s, insn)) {
8619 return;
8623 } else if ((insn & 0x0e000a00) == 0x0c000800
8624 && arm_dc_feature(s, ARM_FEATURE_V8)) {
8625 if (disas_neon_insn_3same_ext(s, insn)) {
8626 goto illegal_op;
8628 return;
8629 } else if ((insn & 0x0f000a00) == 0x0e000800
8630 && arm_dc_feature(s, ARM_FEATURE_V8)) {
8631 if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
8632 goto illegal_op;
8634 return;
8635 } else if ((insn & 0x0fe00000) == 0x0c400000) {
8636 /* Coprocessor double register transfer. */
8637 ARCH(5TE);
8638 } else if ((insn & 0x0f000010) == 0x0e000010) {
8639 /* Additional coprocessor register transfer. */
8640 } else if ((insn & 0x0ff10020) == 0x01000000) {
8641 uint32_t mask;
8642 uint32_t val;
8643 /* cps (privileged) */
8644 if (IS_USER(s))
8645 return;
8646 mask = val = 0;
8647 if (insn & (1 << 19)) {
8648 if (insn & (1 << 8))
8649 mask |= CPSR_A;
8650 if (insn & (1 << 7))
8651 mask |= CPSR_I;
8652 if (insn & (1 << 6))
8653 mask |= CPSR_F;
8654 if (insn & (1 << 18))
8655 val |= mask;
8657 if (insn & (1 << 17)) {
8658 mask |= CPSR_M;
8659 val |= (insn & 0x1f);
8661 if (mask) {
8662 gen_set_psr_im(s, mask, 0, val);
8664 return;
8666 goto illegal_op;
8668 if (cond != 0xe) {
8669 /* if not always execute, we generate a conditional jump to
8670 next instruction */
8671 arm_skip_unless(s, cond);
8673 if ((insn & 0x0f900000) == 0x03000000) {
8674 if ((insn & (1 << 21)) == 0) {
8675 ARCH(6T2);
8676 rd = (insn >> 12) & 0xf;
8677 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
8678 if ((insn & (1 << 22)) == 0) {
8679 /* MOVW */
8680 tmp = tcg_temp_new_i32();
8681 tcg_gen_movi_i32(tmp, val);
8682 } else {
8683 /* MOVT */
8684 tmp = load_reg(s, rd);
8685 tcg_gen_ext16u_i32(tmp, tmp);
8686 tcg_gen_ori_i32(tmp, tmp, val << 16);
8688 store_reg(s, rd, tmp);
8689 } else {
8690 if (((insn >> 12) & 0xf) != 0xf)
8691 goto illegal_op;
8692 if (((insn >> 16) & 0xf) == 0) {
8693 gen_nop_hint(s, insn & 0xff);
8694 } else {
8695 /* CPSR = immediate */
8696 val = insn & 0xff;
8697 shift = ((insn >> 8) & 0xf) * 2;
8698 if (shift)
8699 val = (val >> shift) | (val << (32 - shift));
8700 i = ((insn & (1 << 22)) != 0);
8701 if (gen_set_psr_im(s, msr_mask(s, (insn >> 16) & 0xf, i),
8702 i, val)) {
8703 goto illegal_op;
8707 } else if ((insn & 0x0f900000) == 0x01000000
8708 && (insn & 0x00000090) != 0x00000090) {
8709 /* miscellaneous instructions */
8710 op1 = (insn >> 21) & 3;
8711 sh = (insn >> 4) & 0xf;
8712 rm = insn & 0xf;
8713 switch (sh) {
8714 case 0x0: /* MSR, MRS */
8715 if (insn & (1 << 9)) {
8716 /* MSR (banked) and MRS (banked) */
8717 int sysm = extract32(insn, 16, 4) |
8718 (extract32(insn, 8, 1) << 4);
8719 int r = extract32(insn, 22, 1);
8721 if (op1 & 1) {
8722 /* MSR (banked) */
8723 gen_msr_banked(s, r, sysm, rm);
8724 } else {
8725 /* MRS (banked) */
8726 int rd = extract32(insn, 12, 4);
8728 gen_mrs_banked(s, r, sysm, rd);
8730 break;
8733 /* MSR, MRS (for PSRs) */
8734 if (op1 & 1) {
8735 /* PSR = reg */
8736 tmp = load_reg(s, rm);
8737 i = ((op1 & 2) != 0);
8738 if (gen_set_psr(s, msr_mask(s, (insn >> 16) & 0xf, i), i, tmp))
8739 goto illegal_op;
8740 } else {
8741 /* reg = PSR */
8742 rd = (insn >> 12) & 0xf;
8743 if (op1 & 2) {
8744 if (IS_USER(s))
8745 goto illegal_op;
8746 tmp = load_cpu_field(spsr);
8747 } else {
8748 tmp = tcg_temp_new_i32();
8749 gen_helper_cpsr_read(tmp, cpu_env);
8751 store_reg(s, rd, tmp);
8753 break;
8754 case 0x1:
8755 if (op1 == 1) {
8756 /* branch/exchange thumb (bx). */
8757 ARCH(4T);
8758 tmp = load_reg(s, rm);
8759 gen_bx(s, tmp);
8760 } else if (op1 == 3) {
8761 /* clz */
8762 ARCH(5);
8763 rd = (insn >> 12) & 0xf;
8764 tmp = load_reg(s, rm);
8765 tcg_gen_clzi_i32(tmp, tmp, 32);
8766 store_reg(s, rd, tmp);
8767 } else {
8768 goto illegal_op;
8770 break;
8771 case 0x2:
8772 if (op1 == 1) {
8773 ARCH(5J); /* bxj */
8774 /* Trivial implementation equivalent to bx. */
8775 tmp = load_reg(s, rm);
8776 gen_bx(s, tmp);
8777 } else {
8778 goto illegal_op;
8780 break;
8781 case 0x3:
8782 if (op1 != 1)
8783 goto illegal_op;
8785 ARCH(5);
8786 /* branch link/exchange thumb (blx) */
8787 tmp = load_reg(s, rm);
8788 tmp2 = tcg_temp_new_i32();
8789 tcg_gen_movi_i32(tmp2, s->pc);
8790 store_reg(s, 14, tmp2);
8791 gen_bx(s, tmp);
8792 break;
8793 case 0x4:
8795 /* crc32/crc32c */
8796 uint32_t c = extract32(insn, 8, 4);
8798 /* Check this CPU supports ARMv8 CRC instructions.
8799 * op1 == 3 is UNPREDICTABLE but handle as UNDEFINED.
8800 * Bits 8, 10 and 11 should be zero.
8802 if (!dc_isar_feature(aa32_crc32, s) || op1 == 0x3 || (c & 0xd) != 0) {
8803 goto illegal_op;
8806 rn = extract32(insn, 16, 4);
8807 rd = extract32(insn, 12, 4);
8809 tmp = load_reg(s, rn);
8810 tmp2 = load_reg(s, rm);
8811 if (op1 == 0) {
8812 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
8813 } else if (op1 == 1) {
8814 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
8816 tmp3 = tcg_const_i32(1 << op1);
8817 if (c & 0x2) {
8818 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
8819 } else {
8820 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
8822 tcg_temp_free_i32(tmp2);
8823 tcg_temp_free_i32(tmp3);
8824 store_reg(s, rd, tmp);
8825 break;
8827 case 0x5: /* saturating add/subtract */
8828 ARCH(5TE);
8829 rd = (insn >> 12) & 0xf;
8830 rn = (insn >> 16) & 0xf;
8831 tmp = load_reg(s, rm);
8832 tmp2 = load_reg(s, rn);
8833 if (op1 & 2)
8834 gen_helper_double_saturate(tmp2, cpu_env, tmp2);
8835 if (op1 & 1)
8836 gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2);
8837 else
8838 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
8839 tcg_temp_free_i32(tmp2);
8840 store_reg(s, rd, tmp);
8841 break;
8842 case 0x6: /* ERET */
8843 if (op1 != 3) {
8844 goto illegal_op;
8846 if (!arm_dc_feature(s, ARM_FEATURE_V7VE)) {
8847 goto illegal_op;
8849 if ((insn & 0x000fff0f) != 0x0000000e) {
8850 /* UNPREDICTABLE; we choose to UNDEF */
8851 goto illegal_op;
8854 if (s->current_el == 2) {
8855 tmp = load_cpu_field(elr_el[2]);
8856 } else {
8857 tmp = load_reg(s, 14);
8859 gen_exception_return(s, tmp);
8860 break;
8861 case 7:
8863 int imm16 = extract32(insn, 0, 4) | (extract32(insn, 8, 12) << 4);
8864 switch (op1) {
8865 case 0:
8866 /* HLT */
8867 gen_hlt(s, imm16);
8868 break;
8869 case 1:
8870 /* bkpt */
8871 ARCH(5);
8872 gen_exception_bkpt_insn(s, 4, syn_aa32_bkpt(imm16, false));
8873 break;
8874 case 2:
8875 /* Hypervisor call (v7) */
8876 ARCH(7);
8877 if (IS_USER(s)) {
8878 goto illegal_op;
8880 gen_hvc(s, imm16);
8881 break;
8882 case 3:
8883 /* Secure monitor call (v6+) */
8884 ARCH(6K);
8885 if (IS_USER(s)) {
8886 goto illegal_op;
8888 gen_smc(s);
8889 break;
8890 default:
8891 g_assert_not_reached();
8893 break;
8895 case 0x8: /* signed multiply */
8896 case 0xa:
8897 case 0xc:
8898 case 0xe:
8899 ARCH(5TE);
8900 rs = (insn >> 8) & 0xf;
8901 rn = (insn >> 12) & 0xf;
8902 rd = (insn >> 16) & 0xf;
8903 if (op1 == 1) {
8904 /* (32 * 16) >> 16 */
8905 tmp = load_reg(s, rm);
8906 tmp2 = load_reg(s, rs);
8907 if (sh & 4)
8908 tcg_gen_sari_i32(tmp2, tmp2, 16);
8909 else
8910 gen_sxth(tmp2);
8911 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8912 tcg_gen_shri_i64(tmp64, tmp64, 16);
8913 tmp = tcg_temp_new_i32();
8914 tcg_gen_extrl_i64_i32(tmp, tmp64);
8915 tcg_temp_free_i64(tmp64);
8916 if ((sh & 2) == 0) {
8917 tmp2 = load_reg(s, rn);
8918 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8919 tcg_temp_free_i32(tmp2);
8921 store_reg(s, rd, tmp);
8922 } else {
8923 /* 16 * 16 */
8924 tmp = load_reg(s, rm);
8925 tmp2 = load_reg(s, rs);
8926 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
8927 tcg_temp_free_i32(tmp2);
8928 if (op1 == 2) {
8929 tmp64 = tcg_temp_new_i64();
8930 tcg_gen_ext_i32_i64(tmp64, tmp);
8931 tcg_temp_free_i32(tmp);
8932 gen_addq(s, tmp64, rn, rd);
8933 gen_storeq_reg(s, rn, rd, tmp64);
8934 tcg_temp_free_i64(tmp64);
8935 } else {
8936 if (op1 == 0) {
8937 tmp2 = load_reg(s, rn);
8938 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8939 tcg_temp_free_i32(tmp2);
8941 store_reg(s, rd, tmp);
8944 break;
8945 default:
8946 goto illegal_op;
8948 } else if (((insn & 0x0e000000) == 0 &&
8949 (insn & 0x00000090) != 0x90) ||
8950 ((insn & 0x0e000000) == (1 << 25))) {
8951 int set_cc, logic_cc, shiftop;
8953 op1 = (insn >> 21) & 0xf;
8954 set_cc = (insn >> 20) & 1;
8955 logic_cc = table_logic_cc[op1] & set_cc;
8957 /* data processing instruction */
8958 if (insn & (1 << 25)) {
8959 /* immediate operand */
8960 val = insn & 0xff;
8961 shift = ((insn >> 8) & 0xf) * 2;
8962 if (shift) {
8963 val = (val >> shift) | (val << (32 - shift));
8965 tmp2 = tcg_temp_new_i32();
8966 tcg_gen_movi_i32(tmp2, val);
8967 if (logic_cc && shift) {
8968 gen_set_CF_bit31(tmp2);
8970 } else {
8971 /* register */
8972 rm = (insn) & 0xf;
8973 tmp2 = load_reg(s, rm);
8974 shiftop = (insn >> 5) & 3;
8975 if (!(insn & (1 << 4))) {
8976 shift = (insn >> 7) & 0x1f;
8977 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
8978 } else {
8979 rs = (insn >> 8) & 0xf;
8980 tmp = load_reg(s, rs);
8981 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
8984 if (op1 != 0x0f && op1 != 0x0d) {
8985 rn = (insn >> 16) & 0xf;
8986 tmp = load_reg(s, rn);
8987 } else {
8988 tmp = NULL;
8990 rd = (insn >> 12) & 0xf;
8991 switch(op1) {
8992 case 0x00:
8993 tcg_gen_and_i32(tmp, tmp, tmp2);
8994 if (logic_cc) {
8995 gen_logic_CC(tmp);
8997 store_reg_bx(s, rd, tmp);
8998 break;
8999 case 0x01:
9000 tcg_gen_xor_i32(tmp, tmp, tmp2);
9001 if (logic_cc) {
9002 gen_logic_CC(tmp);
9004 store_reg_bx(s, rd, tmp);
9005 break;
9006 case 0x02:
9007 if (set_cc && rd == 15) {
9008 /* SUBS r15, ... is used for exception return. */
9009 if (IS_USER(s)) {
9010 goto illegal_op;
9012 gen_sub_CC(tmp, tmp, tmp2);
9013 gen_exception_return(s, tmp);
9014 } else {
9015 if (set_cc) {
9016 gen_sub_CC(tmp, tmp, tmp2);
9017 } else {
9018 tcg_gen_sub_i32(tmp, tmp, tmp2);
9020 store_reg_bx(s, rd, tmp);
9022 break;
9023 case 0x03:
9024 if (set_cc) {
9025 gen_sub_CC(tmp, tmp2, tmp);
9026 } else {
9027 tcg_gen_sub_i32(tmp, tmp2, tmp);
9029 store_reg_bx(s, rd, tmp);
9030 break;
9031 case 0x04:
9032 if (set_cc) {
9033 gen_add_CC(tmp, tmp, tmp2);
9034 } else {
9035 tcg_gen_add_i32(tmp, tmp, tmp2);
9037 store_reg_bx(s, rd, tmp);
9038 break;
9039 case 0x05:
9040 if (set_cc) {
9041 gen_adc_CC(tmp, tmp, tmp2);
9042 } else {
9043 gen_add_carry(tmp, tmp, tmp2);
9045 store_reg_bx(s, rd, tmp);
9046 break;
9047 case 0x06:
9048 if (set_cc) {
9049 gen_sbc_CC(tmp, tmp, tmp2);
9050 } else {
9051 gen_sub_carry(tmp, tmp, tmp2);
9053 store_reg_bx(s, rd, tmp);
9054 break;
9055 case 0x07:
9056 if (set_cc) {
9057 gen_sbc_CC(tmp, tmp2, tmp);
9058 } else {
9059 gen_sub_carry(tmp, tmp2, tmp);
9061 store_reg_bx(s, rd, tmp);
9062 break;
9063 case 0x08:
9064 if (set_cc) {
9065 tcg_gen_and_i32(tmp, tmp, tmp2);
9066 gen_logic_CC(tmp);
9068 tcg_temp_free_i32(tmp);
9069 break;
9070 case 0x09:
9071 if (set_cc) {
9072 tcg_gen_xor_i32(tmp, tmp, tmp2);
9073 gen_logic_CC(tmp);
9075 tcg_temp_free_i32(tmp);
9076 break;
9077 case 0x0a:
9078 if (set_cc) {
9079 gen_sub_CC(tmp, tmp, tmp2);
9081 tcg_temp_free_i32(tmp);
9082 break;
9083 case 0x0b:
9084 if (set_cc) {
9085 gen_add_CC(tmp, tmp, tmp2);
9087 tcg_temp_free_i32(tmp);
9088 break;
9089 case 0x0c:
9090 tcg_gen_or_i32(tmp, tmp, tmp2);
9091 if (logic_cc) {
9092 gen_logic_CC(tmp);
9094 store_reg_bx(s, rd, tmp);
9095 break;
9096 case 0x0d:
9097 if (logic_cc && rd == 15) {
9098 /* MOVS r15, ... is used for exception return. */
9099 if (IS_USER(s)) {
9100 goto illegal_op;
9102 gen_exception_return(s, tmp2);
9103 } else {
9104 if (logic_cc) {
9105 gen_logic_CC(tmp2);
9107 store_reg_bx(s, rd, tmp2);
9109 break;
9110 case 0x0e:
9111 tcg_gen_andc_i32(tmp, tmp, tmp2);
9112 if (logic_cc) {
9113 gen_logic_CC(tmp);
9115 store_reg_bx(s, rd, tmp);
9116 break;
9117 default:
9118 case 0x0f:
9119 tcg_gen_not_i32(tmp2, tmp2);
9120 if (logic_cc) {
9121 gen_logic_CC(tmp2);
9123 store_reg_bx(s, rd, tmp2);
9124 break;
9126 if (op1 != 0x0f && op1 != 0x0d) {
9127 tcg_temp_free_i32(tmp2);
9129 } else {
9130 /* other instructions */
9131 op1 = (insn >> 24) & 0xf;
9132 switch(op1) {
9133 case 0x0:
9134 case 0x1:
9135 /* multiplies, extra load/stores */
9136 sh = (insn >> 5) & 3;
9137 if (sh == 0) {
9138 if (op1 == 0x0) {
9139 rd = (insn >> 16) & 0xf;
9140 rn = (insn >> 12) & 0xf;
9141 rs = (insn >> 8) & 0xf;
9142 rm = (insn) & 0xf;
9143 op1 = (insn >> 20) & 0xf;
9144 switch (op1) {
9145 case 0: case 1: case 2: case 3: case 6:
9146 /* 32 bit mul */
9147 tmp = load_reg(s, rs);
9148 tmp2 = load_reg(s, rm);
9149 tcg_gen_mul_i32(tmp, tmp, tmp2);
9150 tcg_temp_free_i32(tmp2);
9151 if (insn & (1 << 22)) {
9152 /* Subtract (mls) */
9153 ARCH(6T2);
9154 tmp2 = load_reg(s, rn);
9155 tcg_gen_sub_i32(tmp, tmp2, tmp);
9156 tcg_temp_free_i32(tmp2);
9157 } else if (insn & (1 << 21)) {
9158 /* Add */
9159 tmp2 = load_reg(s, rn);
9160 tcg_gen_add_i32(tmp, tmp, tmp2);
9161 tcg_temp_free_i32(tmp2);
9163 if (insn & (1 << 20))
9164 gen_logic_CC(tmp);
9165 store_reg(s, rd, tmp);
9166 break;
9167 case 4:
9168 /* 64 bit mul double accumulate (UMAAL) */
9169 ARCH(6);
9170 tmp = load_reg(s, rs);
9171 tmp2 = load_reg(s, rm);
9172 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
9173 gen_addq_lo(s, tmp64, rn);
9174 gen_addq_lo(s, tmp64, rd);
9175 gen_storeq_reg(s, rn, rd, tmp64);
9176 tcg_temp_free_i64(tmp64);
9177 break;
9178 case 8: case 9: case 10: case 11:
9179 case 12: case 13: case 14: case 15:
9180 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
9181 tmp = load_reg(s, rs);
9182 tmp2 = load_reg(s, rm);
9183 if (insn & (1 << 22)) {
9184 tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2);
9185 } else {
9186 tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2);
9188 if (insn & (1 << 21)) { /* mult accumulate */
9189 TCGv_i32 al = load_reg(s, rn);
9190 TCGv_i32 ah = load_reg(s, rd);
9191 tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, al, ah);
9192 tcg_temp_free_i32(al);
9193 tcg_temp_free_i32(ah);
9195 if (insn & (1 << 20)) {
9196 gen_logicq_cc(tmp, tmp2);
9198 store_reg(s, rn, tmp);
9199 store_reg(s, rd, tmp2);
9200 break;
9201 default:
9202 goto illegal_op;
9204 } else {
9205 rn = (insn >> 16) & 0xf;
9206 rd = (insn >> 12) & 0xf;
9207 if (insn & (1 << 23)) {
9208 /* load/store exclusive */
9209 bool is_ld = extract32(insn, 20, 1);
9210 bool is_lasr = !extract32(insn, 8, 1);
9211 int op2 = (insn >> 8) & 3;
9212 op1 = (insn >> 21) & 0x3;
9214 switch (op2) {
9215 case 0: /* lda/stl */
9216 if (op1 == 1) {
9217 goto illegal_op;
9219 ARCH(8);
9220 break;
9221 case 1: /* reserved */
9222 goto illegal_op;
9223 case 2: /* ldaex/stlex */
9224 ARCH(8);
9225 break;
9226 case 3: /* ldrex/strex */
9227 if (op1) {
9228 ARCH(6K);
9229 } else {
9230 ARCH(6);
9232 break;
9235 addr = tcg_temp_local_new_i32();
9236 load_reg_var(s, addr, rn);
9238 if (is_lasr && !is_ld) {
9239 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
9242 if (op2 == 0) {
9243 if (is_ld) {
9244 tmp = tcg_temp_new_i32();
9245 switch (op1) {
9246 case 0: /* lda */
9247 gen_aa32_ld32u_iss(s, tmp, addr,
9248 get_mem_index(s),
9249 rd | ISSIsAcqRel);
9250 break;
9251 case 2: /* ldab */
9252 gen_aa32_ld8u_iss(s, tmp, addr,
9253 get_mem_index(s),
9254 rd | ISSIsAcqRel);
9255 break;
9256 case 3: /* ldah */
9257 gen_aa32_ld16u_iss(s, tmp, addr,
9258 get_mem_index(s),
9259 rd | ISSIsAcqRel);
9260 break;
9261 default:
9262 abort();
9264 store_reg(s, rd, tmp);
9265 } else {
9266 rm = insn & 0xf;
9267 tmp = load_reg(s, rm);
9268 switch (op1) {
9269 case 0: /* stl */
9270 gen_aa32_st32_iss(s, tmp, addr,
9271 get_mem_index(s),
9272 rm | ISSIsAcqRel);
9273 break;
9274 case 2: /* stlb */
9275 gen_aa32_st8_iss(s, tmp, addr,
9276 get_mem_index(s),
9277 rm | ISSIsAcqRel);
9278 break;
9279 case 3: /* stlh */
9280 gen_aa32_st16_iss(s, tmp, addr,
9281 get_mem_index(s),
9282 rm | ISSIsAcqRel);
9283 break;
9284 default:
9285 abort();
9287 tcg_temp_free_i32(tmp);
9289 } else if (is_ld) {
9290 switch (op1) {
9291 case 0: /* ldrex */
9292 gen_load_exclusive(s, rd, 15, addr, 2);
9293 break;
9294 case 1: /* ldrexd */
9295 gen_load_exclusive(s, rd, rd + 1, addr, 3);
9296 break;
9297 case 2: /* ldrexb */
9298 gen_load_exclusive(s, rd, 15, addr, 0);
9299 break;
9300 case 3: /* ldrexh */
9301 gen_load_exclusive(s, rd, 15, addr, 1);
9302 break;
9303 default:
9304 abort();
9306 } else {
9307 rm = insn & 0xf;
9308 switch (op1) {
9309 case 0: /* strex */
9310 gen_store_exclusive(s, rd, rm, 15, addr, 2);
9311 break;
9312 case 1: /* strexd */
9313 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
9314 break;
9315 case 2: /* strexb */
9316 gen_store_exclusive(s, rd, rm, 15, addr, 0);
9317 break;
9318 case 3: /* strexh */
9319 gen_store_exclusive(s, rd, rm, 15, addr, 1);
9320 break;
9321 default:
9322 abort();
9325 tcg_temp_free_i32(addr);
9327 if (is_lasr && is_ld) {
9328 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
9330 } else if ((insn & 0x00300f00) == 0) {
9331 /* 0bcccc_0001_0x00_xxxx_xxxx_0000_1001_xxxx
9332 * - SWP, SWPB
9335 TCGv taddr;
9336 TCGMemOp opc = s->be_data;
9338 rm = (insn) & 0xf;
9340 if (insn & (1 << 22)) {
9341 opc |= MO_UB;
9342 } else {
9343 opc |= MO_UL | MO_ALIGN;
9346 addr = load_reg(s, rn);
9347 taddr = gen_aa32_addr(s, addr, opc);
9348 tcg_temp_free_i32(addr);
9350 tmp = load_reg(s, rm);
9351 tcg_gen_atomic_xchg_i32(tmp, taddr, tmp,
9352 get_mem_index(s), opc);
9353 tcg_temp_free(taddr);
9354 store_reg(s, rd, tmp);
9355 } else {
9356 goto illegal_op;
9359 } else {
9360 int address_offset;
9361 bool load = insn & (1 << 20);
9362 bool wbit = insn & (1 << 21);
9363 bool pbit = insn & (1 << 24);
9364 bool doubleword = false;
9365 ISSInfo issinfo;
9367 /* Misc load/store */
9368 rn = (insn >> 16) & 0xf;
9369 rd = (insn >> 12) & 0xf;
9371 /* ISS not valid if writeback */
9372 issinfo = (pbit & !wbit) ? rd : ISSInvalid;
9374 if (!load && (sh & 2)) {
9375 /* doubleword */
9376 ARCH(5TE);
9377 if (rd & 1) {
9378 /* UNPREDICTABLE; we choose to UNDEF */
9379 goto illegal_op;
9381 load = (sh & 1) == 0;
9382 doubleword = true;
9385 addr = load_reg(s, rn);
9386 if (pbit) {
9387 gen_add_datah_offset(s, insn, 0, addr);
9389 address_offset = 0;
9391 if (doubleword) {
9392 if (!load) {
9393 /* store */
9394 tmp = load_reg(s, rd);
9395 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
9396 tcg_temp_free_i32(tmp);
9397 tcg_gen_addi_i32(addr, addr, 4);
9398 tmp = load_reg(s, rd + 1);
9399 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
9400 tcg_temp_free_i32(tmp);
9401 } else {
9402 /* load */
9403 tmp = tcg_temp_new_i32();
9404 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9405 store_reg(s, rd, tmp);
9406 tcg_gen_addi_i32(addr, addr, 4);
9407 tmp = tcg_temp_new_i32();
9408 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9409 rd++;
9411 address_offset = -4;
9412 } else if (load) {
9413 /* load */
9414 tmp = tcg_temp_new_i32();
9415 switch (sh) {
9416 case 1:
9417 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s),
9418 issinfo);
9419 break;
9420 case 2:
9421 gen_aa32_ld8s_iss(s, tmp, addr, get_mem_index(s),
9422 issinfo);
9423 break;
9424 default:
9425 case 3:
9426 gen_aa32_ld16s_iss(s, tmp, addr, get_mem_index(s),
9427 issinfo);
9428 break;
9430 } else {
9431 /* store */
9432 tmp = load_reg(s, rd);
9433 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), issinfo);
9434 tcg_temp_free_i32(tmp);
9436 /* Perform base writeback before the loaded value to
9437 ensure correct behavior with overlapping index registers.
9438 ldrd with base writeback is undefined if the
9439 destination and index registers overlap. */
9440 if (!pbit) {
9441 gen_add_datah_offset(s, insn, address_offset, addr);
9442 store_reg(s, rn, addr);
9443 } else if (wbit) {
9444 if (address_offset)
9445 tcg_gen_addi_i32(addr, addr, address_offset);
9446 store_reg(s, rn, addr);
9447 } else {
9448 tcg_temp_free_i32(addr);
9450 if (load) {
9451 /* Complete the load. */
9452 store_reg(s, rd, tmp);
9455 break;
9456 case 0x4:
9457 case 0x5:
9458 goto do_ldst;
9459 case 0x6:
9460 case 0x7:
9461 if (insn & (1 << 4)) {
9462 ARCH(6);
9463 /* Armv6 Media instructions. */
9464 rm = insn & 0xf;
9465 rn = (insn >> 16) & 0xf;
9466 rd = (insn >> 12) & 0xf;
9467 rs = (insn >> 8) & 0xf;
9468 switch ((insn >> 23) & 3) {
9469 case 0: /* Parallel add/subtract. */
9470 op1 = (insn >> 20) & 7;
9471 tmp = load_reg(s, rn);
9472 tmp2 = load_reg(s, rm);
9473 sh = (insn >> 5) & 7;
9474 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
9475 goto illegal_op;
9476 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
9477 tcg_temp_free_i32(tmp2);
9478 store_reg(s, rd, tmp);
9479 break;
9480 case 1:
9481 if ((insn & 0x00700020) == 0) {
9482 /* Halfword pack. */
9483 tmp = load_reg(s, rn);
9484 tmp2 = load_reg(s, rm);
9485 shift = (insn >> 7) & 0x1f;
9486 if (insn & (1 << 6)) {
9487 /* pkhtb */
9488 if (shift == 0)
9489 shift = 31;
9490 tcg_gen_sari_i32(tmp2, tmp2, shift);
9491 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
9492 tcg_gen_ext16u_i32(tmp2, tmp2);
9493 } else {
9494 /* pkhbt */
9495 if (shift)
9496 tcg_gen_shli_i32(tmp2, tmp2, shift);
9497 tcg_gen_ext16u_i32(tmp, tmp);
9498 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
9500 tcg_gen_or_i32(tmp, tmp, tmp2);
9501 tcg_temp_free_i32(tmp2);
9502 store_reg(s, rd, tmp);
9503 } else if ((insn & 0x00200020) == 0x00200000) {
9504 /* [us]sat */
9505 tmp = load_reg(s, rm);
9506 shift = (insn >> 7) & 0x1f;
9507 if (insn & (1 << 6)) {
9508 if (shift == 0)
9509 shift = 31;
9510 tcg_gen_sari_i32(tmp, tmp, shift);
9511 } else {
9512 tcg_gen_shli_i32(tmp, tmp, shift);
9514 sh = (insn >> 16) & 0x1f;
9515 tmp2 = tcg_const_i32(sh);
9516 if (insn & (1 << 22))
9517 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
9518 else
9519 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
9520 tcg_temp_free_i32(tmp2);
9521 store_reg(s, rd, tmp);
9522 } else if ((insn & 0x00300fe0) == 0x00200f20) {
9523 /* [us]sat16 */
9524 tmp = load_reg(s, rm);
9525 sh = (insn >> 16) & 0x1f;
9526 tmp2 = tcg_const_i32(sh);
9527 if (insn & (1 << 22))
9528 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
9529 else
9530 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
9531 tcg_temp_free_i32(tmp2);
9532 store_reg(s, rd, tmp);
9533 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
9534 /* Select bytes. */
9535 tmp = load_reg(s, rn);
9536 tmp2 = load_reg(s, rm);
9537 tmp3 = tcg_temp_new_i32();
9538 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
9539 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
9540 tcg_temp_free_i32(tmp3);
9541 tcg_temp_free_i32(tmp2);
9542 store_reg(s, rd, tmp);
9543 } else if ((insn & 0x000003e0) == 0x00000060) {
9544 tmp = load_reg(s, rm);
9545 shift = (insn >> 10) & 3;
9546 /* ??? In many cases it's not necessary to do a
9547 rotate, a shift is sufficient. */
9548 if (shift != 0)
9549 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
9550 op1 = (insn >> 20) & 7;
9551 switch (op1) {
9552 case 0: gen_sxtb16(tmp); break;
9553 case 2: gen_sxtb(tmp); break;
9554 case 3: gen_sxth(tmp); break;
9555 case 4: gen_uxtb16(tmp); break;
9556 case 6: gen_uxtb(tmp); break;
9557 case 7: gen_uxth(tmp); break;
9558 default: goto illegal_op;
9560 if (rn != 15) {
9561 tmp2 = load_reg(s, rn);
9562 if ((op1 & 3) == 0) {
9563 gen_add16(tmp, tmp2);
9564 } else {
9565 tcg_gen_add_i32(tmp, tmp, tmp2);
9566 tcg_temp_free_i32(tmp2);
9569 store_reg(s, rd, tmp);
9570 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
9571 /* rev */
9572 tmp = load_reg(s, rm);
9573 if (insn & (1 << 22)) {
9574 if (insn & (1 << 7)) {
9575 gen_revsh(tmp);
9576 } else {
9577 ARCH(6T2);
9578 gen_helper_rbit(tmp, tmp);
9580 } else {
9581 if (insn & (1 << 7))
9582 gen_rev16(tmp);
9583 else
9584 tcg_gen_bswap32_i32(tmp, tmp);
9586 store_reg(s, rd, tmp);
9587 } else {
9588 goto illegal_op;
9590 break;
9591 case 2: /* Multiplies (Type 3). */
9592 switch ((insn >> 20) & 0x7) {
9593 case 5:
9594 if (((insn >> 6) ^ (insn >> 7)) & 1) {
9595 /* op2 not 00x or 11x : UNDEF */
9596 goto illegal_op;
9598 /* Signed multiply most significant [accumulate].
9599 (SMMUL, SMMLA, SMMLS) */
9600 tmp = load_reg(s, rm);
9601 tmp2 = load_reg(s, rs);
9602 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9604 if (rd != 15) {
9605 tmp = load_reg(s, rd);
9606 if (insn & (1 << 6)) {
9607 tmp64 = gen_subq_msw(tmp64, tmp);
9608 } else {
9609 tmp64 = gen_addq_msw(tmp64, tmp);
9612 if (insn & (1 << 5)) {
9613 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
9615 tcg_gen_shri_i64(tmp64, tmp64, 32);
9616 tmp = tcg_temp_new_i32();
9617 tcg_gen_extrl_i64_i32(tmp, tmp64);
9618 tcg_temp_free_i64(tmp64);
9619 store_reg(s, rn, tmp);
9620 break;
9621 case 0:
9622 case 4:
9623 /* SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD */
9624 if (insn & (1 << 7)) {
9625 goto illegal_op;
9627 tmp = load_reg(s, rm);
9628 tmp2 = load_reg(s, rs);
9629 if (insn & (1 << 5))
9630 gen_swap_half(tmp2);
9631 gen_smul_dual(tmp, tmp2);
9632 if (insn & (1 << 22)) {
9633 /* smlald, smlsld */
9634 TCGv_i64 tmp64_2;
9636 tmp64 = tcg_temp_new_i64();
9637 tmp64_2 = tcg_temp_new_i64();
9638 tcg_gen_ext_i32_i64(tmp64, tmp);
9639 tcg_gen_ext_i32_i64(tmp64_2, tmp2);
9640 tcg_temp_free_i32(tmp);
9641 tcg_temp_free_i32(tmp2);
9642 if (insn & (1 << 6)) {
9643 tcg_gen_sub_i64(tmp64, tmp64, tmp64_2);
9644 } else {
9645 tcg_gen_add_i64(tmp64, tmp64, tmp64_2);
9647 tcg_temp_free_i64(tmp64_2);
9648 gen_addq(s, tmp64, rd, rn);
9649 gen_storeq_reg(s, rd, rn, tmp64);
9650 tcg_temp_free_i64(tmp64);
9651 } else {
9652 /* smuad, smusd, smlad, smlsd */
9653 if (insn & (1 << 6)) {
9654 /* This subtraction cannot overflow. */
9655 tcg_gen_sub_i32(tmp, tmp, tmp2);
9656 } else {
9657 /* This addition cannot overflow 32 bits;
9658 * however it may overflow considered as a
9659 * signed operation, in which case we must set
9660 * the Q flag.
9662 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9664 tcg_temp_free_i32(tmp2);
9665 if (rd != 15)
9667 tmp2 = load_reg(s, rd);
9668 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9669 tcg_temp_free_i32(tmp2);
9671 store_reg(s, rn, tmp);
9673 break;
9674 case 1:
9675 case 3:
9676 /* SDIV, UDIV */
9677 if (!dc_isar_feature(arm_div, s)) {
9678 goto illegal_op;
9680 if (((insn >> 5) & 7) || (rd != 15)) {
9681 goto illegal_op;
9683 tmp = load_reg(s, rm);
9684 tmp2 = load_reg(s, rs);
9685 if (insn & (1 << 21)) {
9686 gen_helper_udiv(tmp, tmp, tmp2);
9687 } else {
9688 gen_helper_sdiv(tmp, tmp, tmp2);
9690 tcg_temp_free_i32(tmp2);
9691 store_reg(s, rn, tmp);
9692 break;
9693 default:
9694 goto illegal_op;
9696 break;
9697 case 3:
9698 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
9699 switch (op1) {
9700 case 0: /* Unsigned sum of absolute differences. */
9701 ARCH(6);
9702 tmp = load_reg(s, rm);
9703 tmp2 = load_reg(s, rs);
9704 gen_helper_usad8(tmp, tmp, tmp2);
9705 tcg_temp_free_i32(tmp2);
9706 if (rd != 15) {
9707 tmp2 = load_reg(s, rd);
9708 tcg_gen_add_i32(tmp, tmp, tmp2);
9709 tcg_temp_free_i32(tmp2);
9711 store_reg(s, rn, tmp);
9712 break;
9713 case 0x20: case 0x24: case 0x28: case 0x2c:
9714 /* Bitfield insert/clear. */
9715 ARCH(6T2);
9716 shift = (insn >> 7) & 0x1f;
9717 i = (insn >> 16) & 0x1f;
9718 if (i < shift) {
9719 /* UNPREDICTABLE; we choose to UNDEF */
9720 goto illegal_op;
9722 i = i + 1 - shift;
9723 if (rm == 15) {
9724 tmp = tcg_temp_new_i32();
9725 tcg_gen_movi_i32(tmp, 0);
9726 } else {
9727 tmp = load_reg(s, rm);
9729 if (i != 32) {
9730 tmp2 = load_reg(s, rd);
9731 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, i);
9732 tcg_temp_free_i32(tmp2);
9734 store_reg(s, rd, tmp);
9735 break;
9736 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
9737 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
9738 ARCH(6T2);
9739 tmp = load_reg(s, rm);
9740 shift = (insn >> 7) & 0x1f;
9741 i = ((insn >> 16) & 0x1f) + 1;
9742 if (shift + i > 32)
9743 goto illegal_op;
9744 if (i < 32) {
9745 if (op1 & 0x20) {
9746 tcg_gen_extract_i32(tmp, tmp, shift, i);
9747 } else {
9748 tcg_gen_sextract_i32(tmp, tmp, shift, i);
9751 store_reg(s, rd, tmp);
9752 break;
9753 default:
9754 goto illegal_op;
9756 break;
9758 break;
9760 do_ldst:
9761 /* Check for undefined extension instructions
9762 * per the ARM Bible IE:
9763 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
9765 sh = (0xf << 20) | (0xf << 4);
9766 if (op1 == 0x7 && ((insn & sh) == sh))
9768 goto illegal_op;
9770 /* load/store byte/word */
9771 rn = (insn >> 16) & 0xf;
9772 rd = (insn >> 12) & 0xf;
9773 tmp2 = load_reg(s, rn);
9774 if ((insn & 0x01200000) == 0x00200000) {
9775 /* ldrt/strt */
9776 i = get_a32_user_mem_index(s);
9777 } else {
9778 i = get_mem_index(s);
9780 if (insn & (1 << 24))
9781 gen_add_data_offset(s, insn, tmp2);
9782 if (insn & (1 << 20)) {
9783 /* load */
9784 tmp = tcg_temp_new_i32();
9785 if (insn & (1 << 22)) {
9786 gen_aa32_ld8u_iss(s, tmp, tmp2, i, rd);
9787 } else {
9788 gen_aa32_ld32u_iss(s, tmp, tmp2, i, rd);
9790 } else {
9791 /* store */
9792 tmp = load_reg(s, rd);
9793 if (insn & (1 << 22)) {
9794 gen_aa32_st8_iss(s, tmp, tmp2, i, rd);
9795 } else {
9796 gen_aa32_st32_iss(s, tmp, tmp2, i, rd);
9798 tcg_temp_free_i32(tmp);
9800 if (!(insn & (1 << 24))) {
9801 gen_add_data_offset(s, insn, tmp2);
9802 store_reg(s, rn, tmp2);
9803 } else if (insn & (1 << 21)) {
9804 store_reg(s, rn, tmp2);
9805 } else {
9806 tcg_temp_free_i32(tmp2);
9808 if (insn & (1 << 20)) {
9809 /* Complete the load. */
9810 store_reg_from_load(s, rd, tmp);
9812 break;
9813 case 0x08:
9814 case 0x09:
9816 int j, n, loaded_base;
9817 bool exc_return = false;
9818 bool is_load = extract32(insn, 20, 1);
9819 bool user = false;
9820 TCGv_i32 loaded_var;
9821 /* load/store multiple words */
9822 /* XXX: store correct base if write back */
9823 if (insn & (1 << 22)) {
9824 /* LDM (user), LDM (exception return) and STM (user) */
9825 if (IS_USER(s))
9826 goto illegal_op; /* only usable in supervisor mode */
9828 if (is_load && extract32(insn, 15, 1)) {
9829 exc_return = true;
9830 } else {
9831 user = true;
9834 rn = (insn >> 16) & 0xf;
9835 addr = load_reg(s, rn);
9837 /* compute total size */
9838 loaded_base = 0;
9839 loaded_var = NULL;
9840 n = 0;
9841 for(i=0;i<16;i++) {
9842 if (insn & (1 << i))
9843 n++;
9845 /* XXX: test invalid n == 0 case ? */
9846 if (insn & (1 << 23)) {
9847 if (insn & (1 << 24)) {
9848 /* pre increment */
9849 tcg_gen_addi_i32(addr, addr, 4);
9850 } else {
9851 /* post increment */
9853 } else {
9854 if (insn & (1 << 24)) {
9855 /* pre decrement */
9856 tcg_gen_addi_i32(addr, addr, -(n * 4));
9857 } else {
9858 /* post decrement */
9859 if (n != 1)
9860 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
9863 j = 0;
9864 for(i=0;i<16;i++) {
9865 if (insn & (1 << i)) {
9866 if (is_load) {
9867 /* load */
9868 tmp = tcg_temp_new_i32();
9869 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9870 if (user) {
9871 tmp2 = tcg_const_i32(i);
9872 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
9873 tcg_temp_free_i32(tmp2);
9874 tcg_temp_free_i32(tmp);
9875 } else if (i == rn) {
9876 loaded_var = tmp;
9877 loaded_base = 1;
9878 } else if (i == 15 && exc_return) {
9879 store_pc_exc_ret(s, tmp);
9880 } else {
9881 store_reg_from_load(s, i, tmp);
9883 } else {
9884 /* store */
9885 if (i == 15) {
9886 /* special case: r15 = PC + 8 */
9887 val = (long)s->pc + 4;
9888 tmp = tcg_temp_new_i32();
9889 tcg_gen_movi_i32(tmp, val);
9890 } else if (user) {
9891 tmp = tcg_temp_new_i32();
9892 tmp2 = tcg_const_i32(i);
9893 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
9894 tcg_temp_free_i32(tmp2);
9895 } else {
9896 tmp = load_reg(s, i);
9898 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
9899 tcg_temp_free_i32(tmp);
9901 j++;
9902 /* no need to add after the last transfer */
9903 if (j != n)
9904 tcg_gen_addi_i32(addr, addr, 4);
9907 if (insn & (1 << 21)) {
9908 /* write back */
9909 if (insn & (1 << 23)) {
9910 if (insn & (1 << 24)) {
9911 /* pre increment */
9912 } else {
9913 /* post increment */
9914 tcg_gen_addi_i32(addr, addr, 4);
9916 } else {
9917 if (insn & (1 << 24)) {
9918 /* pre decrement */
9919 if (n != 1)
9920 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
9921 } else {
9922 /* post decrement */
9923 tcg_gen_addi_i32(addr, addr, -(n * 4));
9926 store_reg(s, rn, addr);
9927 } else {
9928 tcg_temp_free_i32(addr);
9930 if (loaded_base) {
9931 store_reg(s, rn, loaded_var);
9933 if (exc_return) {
9934 /* Restore CPSR from SPSR. */
9935 tmp = load_cpu_field(spsr);
9936 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
9937 gen_io_start();
9939 gen_helper_cpsr_write_eret(cpu_env, tmp);
9940 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
9941 gen_io_end();
9943 tcg_temp_free_i32(tmp);
9944 /* Must exit loop to check un-masked IRQs */
9945 s->base.is_jmp = DISAS_EXIT;
9948 break;
9949 case 0xa:
9950 case 0xb:
9952 int32_t offset;
9954 /* branch (and link) */
9955 val = (int32_t)s->pc;
9956 if (insn & (1 << 24)) {
9957 tmp = tcg_temp_new_i32();
9958 tcg_gen_movi_i32(tmp, val);
9959 store_reg(s, 14, tmp);
9961 offset = sextract32(insn << 2, 0, 26);
9962 val += offset + 4;
9963 gen_jmp(s, val);
9965 break;
9966 case 0xc:
9967 case 0xd:
9968 case 0xe:
9969 if (((insn >> 8) & 0xe) == 10) {
9970 /* VFP. */
9971 if (disas_vfp_insn(s, insn)) {
9972 goto illegal_op;
9974 } else if (disas_coproc_insn(s, insn)) {
9975 /* Coprocessor. */
9976 goto illegal_op;
9978 break;
9979 case 0xf:
9980 /* swi */
9981 gen_set_pc_im(s, s->pc);
9982 s->svc_imm = extract32(insn, 0, 24);
9983 s->base.is_jmp = DISAS_SWI;
9984 break;
9985 default:
9986 illegal_op:
9987 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
9988 default_exception_el(s));
9989 break;
9994 static bool thumb_insn_is_16bit(DisasContext *s, uint32_t insn)
9996 /* Return true if this is a 16 bit instruction. We must be precise
9997 * about this (matching the decode). We assume that s->pc still
9998 * points to the first 16 bits of the insn.
10000 if ((insn >> 11) < 0x1d) {
10001 /* Definitely a 16-bit instruction */
10002 return true;
10005 /* Top five bits 0b11101 / 0b11110 / 0b11111 : this is the
10006 * first half of a 32-bit Thumb insn. Thumb-1 cores might
10007 * end up actually treating this as two 16-bit insns, though,
10008 * if it's half of a bl/blx pair that might span a page boundary.
10010 if (arm_dc_feature(s, ARM_FEATURE_THUMB2) ||
10011 arm_dc_feature(s, ARM_FEATURE_M)) {
10012 /* Thumb2 cores (including all M profile ones) always treat
10013 * 32-bit insns as 32-bit.
10015 return false;
10018 if ((insn >> 11) == 0x1e && s->pc - s->page_start < TARGET_PAGE_SIZE - 3) {
10019 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix, and the suffix
10020 * is not on the next page; we merge this into a 32-bit
10021 * insn.
10023 return false;
10025 /* 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF);
10026 * 0b1111_1xxx_xxxx_xxxx : BL suffix;
10027 * 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix on the end of a page
10028 * -- handle as single 16 bit insn
10030 return true;
10033 /* Return true if this is a Thumb-2 logical op. */
10034 static int
10035 thumb2_logic_op(int op)
10037 return (op < 8);
10040 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
10041 then set condition code flags based on the result of the operation.
10042 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
10043 to the high bit of T1.
10044 Returns zero if the opcode is valid. */
10046 static int
10047 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out,
10048 TCGv_i32 t0, TCGv_i32 t1)
10050 int logic_cc;
10052 logic_cc = 0;
10053 switch (op) {
10054 case 0: /* and */
10055 tcg_gen_and_i32(t0, t0, t1);
10056 logic_cc = conds;
10057 break;
10058 case 1: /* bic */
10059 tcg_gen_andc_i32(t0, t0, t1);
10060 logic_cc = conds;
10061 break;
10062 case 2: /* orr */
10063 tcg_gen_or_i32(t0, t0, t1);
10064 logic_cc = conds;
10065 break;
10066 case 3: /* orn */
10067 tcg_gen_orc_i32(t0, t0, t1);
10068 logic_cc = conds;
10069 break;
10070 case 4: /* eor */
10071 tcg_gen_xor_i32(t0, t0, t1);
10072 logic_cc = conds;
10073 break;
10074 case 8: /* add */
10075 if (conds)
10076 gen_add_CC(t0, t0, t1);
10077 else
10078 tcg_gen_add_i32(t0, t0, t1);
10079 break;
10080 case 10: /* adc */
10081 if (conds)
10082 gen_adc_CC(t0, t0, t1);
10083 else
10084 gen_adc(t0, t1);
10085 break;
10086 case 11: /* sbc */
10087 if (conds) {
10088 gen_sbc_CC(t0, t0, t1);
10089 } else {
10090 gen_sub_carry(t0, t0, t1);
10092 break;
10093 case 13: /* sub */
10094 if (conds)
10095 gen_sub_CC(t0, t0, t1);
10096 else
10097 tcg_gen_sub_i32(t0, t0, t1);
10098 break;
10099 case 14: /* rsb */
10100 if (conds)
10101 gen_sub_CC(t0, t1, t0);
10102 else
10103 tcg_gen_sub_i32(t0, t1, t0);
10104 break;
10105 default: /* 5, 6, 7, 9, 12, 15. */
10106 return 1;
10108 if (logic_cc) {
10109 gen_logic_CC(t0);
10110 if (shifter_out)
10111 gen_set_CF_bit31(t1);
10113 return 0;
10116 /* Translate a 32-bit thumb instruction. */
10117 static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
10119 uint32_t imm, shift, offset;
10120 uint32_t rd, rn, rm, rs;
10121 TCGv_i32 tmp;
10122 TCGv_i32 tmp2;
10123 TCGv_i32 tmp3;
10124 TCGv_i32 addr;
10125 TCGv_i64 tmp64;
10126 int op;
10127 int shiftop;
10128 int conds;
10129 int logic_cc;
10132 * ARMv6-M supports a limited subset of Thumb2 instructions.
10133 * Other Thumb1 architectures allow only 32-bit
10134 * combined BL/BLX prefix and suffix.
10136 if (arm_dc_feature(s, ARM_FEATURE_M) &&
10137 !arm_dc_feature(s, ARM_FEATURE_V7)) {
10138 int i;
10139 bool found = false;
10140 static const uint32_t armv6m_insn[] = {0xf3808000 /* msr */,
10141 0xf3b08040 /* dsb */,
10142 0xf3b08050 /* dmb */,
10143 0xf3b08060 /* isb */,
10144 0xf3e08000 /* mrs */,
10145 0xf000d000 /* bl */};
10146 static const uint32_t armv6m_mask[] = {0xffe0d000,
10147 0xfff0d0f0,
10148 0xfff0d0f0,
10149 0xfff0d0f0,
10150 0xffe0d000,
10151 0xf800d000};
10153 for (i = 0; i < ARRAY_SIZE(armv6m_insn); i++) {
10154 if ((insn & armv6m_mask[i]) == armv6m_insn[i]) {
10155 found = true;
10156 break;
10159 if (!found) {
10160 goto illegal_op;
10162 } else if ((insn & 0xf800e800) != 0xf000e800) {
10163 ARCH(6T2);
10166 rn = (insn >> 16) & 0xf;
10167 rs = (insn >> 12) & 0xf;
10168 rd = (insn >> 8) & 0xf;
10169 rm = insn & 0xf;
10170 switch ((insn >> 25) & 0xf) {
10171 case 0: case 1: case 2: case 3:
10172 /* 16-bit instructions. Should never happen. */
10173 abort();
10174 case 4:
10175 if (insn & (1 << 22)) {
10176 /* 0b1110_100x_x1xx_xxxx_xxxx_xxxx_xxxx_xxxx
10177 * - load/store doubleword, load/store exclusive, ldacq/strel,
10178 * table branch, TT.
10180 if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_M) &&
10181 arm_dc_feature(s, ARM_FEATURE_V8)) {
10182 /* 0b1110_1001_0111_1111_1110_1001_0111_111
10183 * - SG (v8M only)
10184 * The bulk of the behaviour for this instruction is implemented
10185 * in v7m_handle_execute_nsc(), which deals with the insn when
10186 * it is executed by a CPU in non-secure state from memory
10187 * which is Secure & NonSecure-Callable.
10188 * Here we only need to handle the remaining cases:
10189 * * in NS memory (including the "security extension not
10190 * implemented" case) : NOP
10191 * * in S memory but CPU already secure (clear IT bits)
10192 * We know that the attribute for the memory this insn is
10193 * in must match the current CPU state, because otherwise
10194 * get_phys_addr_pmsav8 would have generated an exception.
10196 if (s->v8m_secure) {
10197 /* Like the IT insn, we don't need to generate any code */
10198 s->condexec_cond = 0;
10199 s->condexec_mask = 0;
10201 } else if (insn & 0x01200000) {
10202 /* 0b1110_1000_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
10203 * - load/store dual (post-indexed)
10204 * 0b1111_1001_x10x_xxxx_xxxx_xxxx_xxxx_xxxx
10205 * - load/store dual (literal and immediate)
10206 * 0b1111_1001_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
10207 * - load/store dual (pre-indexed)
10209 bool wback = extract32(insn, 21, 1);
10211 if (rn == 15) {
10212 if (insn & (1 << 21)) {
10213 /* UNPREDICTABLE */
10214 goto illegal_op;
10216 addr = tcg_temp_new_i32();
10217 tcg_gen_movi_i32(addr, s->pc & ~3);
10218 } else {
10219 addr = load_reg(s, rn);
10221 offset = (insn & 0xff) * 4;
10222 if ((insn & (1 << 23)) == 0) {
10223 offset = -offset;
10226 if (s->v8m_stackcheck && rn == 13 && wback) {
10228 * Here 'addr' is the current SP; if offset is +ve we're
10229 * moving SP up, else down. It is UNKNOWN whether the limit
10230 * check triggers when SP starts below the limit and ends
10231 * up above it; check whichever of the current and final
10232 * SP is lower, so QEMU will trigger in that situation.
10234 if ((int32_t)offset < 0) {
10235 TCGv_i32 newsp = tcg_temp_new_i32();
10237 tcg_gen_addi_i32(newsp, addr, offset);
10238 gen_helper_v8m_stackcheck(cpu_env, newsp);
10239 tcg_temp_free_i32(newsp);
10240 } else {
10241 gen_helper_v8m_stackcheck(cpu_env, addr);
10245 if (insn & (1 << 24)) {
10246 tcg_gen_addi_i32(addr, addr, offset);
10247 offset = 0;
10249 if (insn & (1 << 20)) {
10250 /* ldrd */
10251 tmp = tcg_temp_new_i32();
10252 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
10253 store_reg(s, rs, tmp);
10254 tcg_gen_addi_i32(addr, addr, 4);
10255 tmp = tcg_temp_new_i32();
10256 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
10257 store_reg(s, rd, tmp);
10258 } else {
10259 /* strd */
10260 tmp = load_reg(s, rs);
10261 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
10262 tcg_temp_free_i32(tmp);
10263 tcg_gen_addi_i32(addr, addr, 4);
10264 tmp = load_reg(s, rd);
10265 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
10266 tcg_temp_free_i32(tmp);
10268 if (wback) {
10269 /* Base writeback. */
10270 tcg_gen_addi_i32(addr, addr, offset - 4);
10271 store_reg(s, rn, addr);
10272 } else {
10273 tcg_temp_free_i32(addr);
10275 } else if ((insn & (1 << 23)) == 0) {
10276 /* 0b1110_1000_010x_xxxx_xxxx_xxxx_xxxx_xxxx
10277 * - load/store exclusive word
10278 * - TT (v8M only)
10280 if (rs == 15) {
10281 if (!(insn & (1 << 20)) &&
10282 arm_dc_feature(s, ARM_FEATURE_M) &&
10283 arm_dc_feature(s, ARM_FEATURE_V8)) {
10284 /* 0b1110_1000_0100_xxxx_1111_xxxx_xxxx_xxxx
10285 * - TT (v8M only)
10287 bool alt = insn & (1 << 7);
10288 TCGv_i32 addr, op, ttresp;
10290 if ((insn & 0x3f) || rd == 13 || rd == 15 || rn == 15) {
10291 /* we UNDEF for these UNPREDICTABLE cases */
10292 goto illegal_op;
10295 if (alt && !s->v8m_secure) {
10296 goto illegal_op;
10299 addr = load_reg(s, rn);
10300 op = tcg_const_i32(extract32(insn, 6, 2));
10301 ttresp = tcg_temp_new_i32();
10302 gen_helper_v7m_tt(ttresp, cpu_env, addr, op);
10303 tcg_temp_free_i32(addr);
10304 tcg_temp_free_i32(op);
10305 store_reg(s, rd, ttresp);
10306 break;
10308 goto illegal_op;
10310 addr = tcg_temp_local_new_i32();
10311 load_reg_var(s, addr, rn);
10312 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
10313 if (insn & (1 << 20)) {
10314 gen_load_exclusive(s, rs, 15, addr, 2);
10315 } else {
10316 gen_store_exclusive(s, rd, rs, 15, addr, 2);
10318 tcg_temp_free_i32(addr);
10319 } else if ((insn & (7 << 5)) == 0) {
10320 /* Table Branch. */
10321 if (rn == 15) {
10322 addr = tcg_temp_new_i32();
10323 tcg_gen_movi_i32(addr, s->pc);
10324 } else {
10325 addr = load_reg(s, rn);
10327 tmp = load_reg(s, rm);
10328 tcg_gen_add_i32(addr, addr, tmp);
10329 if (insn & (1 << 4)) {
10330 /* tbh */
10331 tcg_gen_add_i32(addr, addr, tmp);
10332 tcg_temp_free_i32(tmp);
10333 tmp = tcg_temp_new_i32();
10334 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
10335 } else { /* tbb */
10336 tcg_temp_free_i32(tmp);
10337 tmp = tcg_temp_new_i32();
10338 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
10340 tcg_temp_free_i32(addr);
10341 tcg_gen_shli_i32(tmp, tmp, 1);
10342 tcg_gen_addi_i32(tmp, tmp, s->pc);
10343 store_reg(s, 15, tmp);
10344 } else {
10345 bool is_lasr = false;
10346 bool is_ld = extract32(insn, 20, 1);
10347 int op2 = (insn >> 6) & 0x3;
10348 op = (insn >> 4) & 0x3;
10349 switch (op2) {
10350 case 0:
10351 goto illegal_op;
10352 case 1:
10353 /* Load/store exclusive byte/halfword/doubleword */
10354 if (op == 2) {
10355 goto illegal_op;
10357 ARCH(7);
10358 break;
10359 case 2:
10360 /* Load-acquire/store-release */
10361 if (op == 3) {
10362 goto illegal_op;
10364 /* Fall through */
10365 case 3:
10366 /* Load-acquire/store-release exclusive */
10367 ARCH(8);
10368 is_lasr = true;
10369 break;
10372 if (is_lasr && !is_ld) {
10373 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
10376 addr = tcg_temp_local_new_i32();
10377 load_reg_var(s, addr, rn);
10378 if (!(op2 & 1)) {
10379 if (is_ld) {
10380 tmp = tcg_temp_new_i32();
10381 switch (op) {
10382 case 0: /* ldab */
10383 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s),
10384 rs | ISSIsAcqRel);
10385 break;
10386 case 1: /* ldah */
10387 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s),
10388 rs | ISSIsAcqRel);
10389 break;
10390 case 2: /* lda */
10391 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s),
10392 rs | ISSIsAcqRel);
10393 break;
10394 default:
10395 abort();
10397 store_reg(s, rs, tmp);
10398 } else {
10399 tmp = load_reg(s, rs);
10400 switch (op) {
10401 case 0: /* stlb */
10402 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s),
10403 rs | ISSIsAcqRel);
10404 break;
10405 case 1: /* stlh */
10406 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s),
10407 rs | ISSIsAcqRel);
10408 break;
10409 case 2: /* stl */
10410 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s),
10411 rs | ISSIsAcqRel);
10412 break;
10413 default:
10414 abort();
10416 tcg_temp_free_i32(tmp);
10418 } else if (is_ld) {
10419 gen_load_exclusive(s, rs, rd, addr, op);
10420 } else {
10421 gen_store_exclusive(s, rm, rs, rd, addr, op);
10423 tcg_temp_free_i32(addr);
10425 if (is_lasr && is_ld) {
10426 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
10429 } else {
10430 /* Load/store multiple, RFE, SRS. */
10431 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
10432 /* RFE, SRS: not available in user mode or on M profile */
10433 if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
10434 goto illegal_op;
10436 if (insn & (1 << 20)) {
10437 /* rfe */
10438 addr = load_reg(s, rn);
10439 if ((insn & (1 << 24)) == 0)
10440 tcg_gen_addi_i32(addr, addr, -8);
10441 /* Load PC into tmp and CPSR into tmp2. */
10442 tmp = tcg_temp_new_i32();
10443 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
10444 tcg_gen_addi_i32(addr, addr, 4);
10445 tmp2 = tcg_temp_new_i32();
10446 gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
10447 if (insn & (1 << 21)) {
10448 /* Base writeback. */
10449 if (insn & (1 << 24)) {
10450 tcg_gen_addi_i32(addr, addr, 4);
10451 } else {
10452 tcg_gen_addi_i32(addr, addr, -4);
10454 store_reg(s, rn, addr);
10455 } else {
10456 tcg_temp_free_i32(addr);
10458 gen_rfe(s, tmp, tmp2);
10459 } else {
10460 /* srs */
10461 gen_srs(s, (insn & 0x1f), (insn & (1 << 24)) ? 1 : 2,
10462 insn & (1 << 21));
10464 } else {
10465 int i, loaded_base = 0;
10466 TCGv_i32 loaded_var;
10467 bool wback = extract32(insn, 21, 1);
10468 /* Load/store multiple. */
10469 addr = load_reg(s, rn);
10470 offset = 0;
10471 for (i = 0; i < 16; i++) {
10472 if (insn & (1 << i))
10473 offset += 4;
10476 if (insn & (1 << 24)) {
10477 tcg_gen_addi_i32(addr, addr, -offset);
10480 if (s->v8m_stackcheck && rn == 13 && wback) {
10482 * If the writeback is incrementing SP rather than
10483 * decrementing it, and the initial SP is below the
10484 * stack limit but the final written-back SP would
10485 * be above, then then we must not perform any memory
10486 * accesses, but it is IMPDEF whether we generate
10487 * an exception. We choose to do so in this case.
10488 * At this point 'addr' is the lowest address, so
10489 * either the original SP (if incrementing) or our
10490 * final SP (if decrementing), so that's what we check.
10492 gen_helper_v8m_stackcheck(cpu_env, addr);
10495 loaded_var = NULL;
10496 for (i = 0; i < 16; i++) {
10497 if ((insn & (1 << i)) == 0)
10498 continue;
10499 if (insn & (1 << 20)) {
10500 /* Load. */
10501 tmp = tcg_temp_new_i32();
10502 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
10503 if (i == 15) {
10504 gen_bx_excret(s, tmp);
10505 } else if (i == rn) {
10506 loaded_var = tmp;
10507 loaded_base = 1;
10508 } else {
10509 store_reg(s, i, tmp);
10511 } else {
10512 /* Store. */
10513 tmp = load_reg(s, i);
10514 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
10515 tcg_temp_free_i32(tmp);
10517 tcg_gen_addi_i32(addr, addr, 4);
10519 if (loaded_base) {
10520 store_reg(s, rn, loaded_var);
10522 if (wback) {
10523 /* Base register writeback. */
10524 if (insn & (1 << 24)) {
10525 tcg_gen_addi_i32(addr, addr, -offset);
10527 /* Fault if writeback register is in register list. */
10528 if (insn & (1 << rn))
10529 goto illegal_op;
10530 store_reg(s, rn, addr);
10531 } else {
10532 tcg_temp_free_i32(addr);
10536 break;
10537 case 5:
10539 op = (insn >> 21) & 0xf;
10540 if (op == 6) {
10541 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10542 goto illegal_op;
10544 /* Halfword pack. */
10545 tmp = load_reg(s, rn);
10546 tmp2 = load_reg(s, rm);
10547 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
10548 if (insn & (1 << 5)) {
10549 /* pkhtb */
10550 if (shift == 0)
10551 shift = 31;
10552 tcg_gen_sari_i32(tmp2, tmp2, shift);
10553 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
10554 tcg_gen_ext16u_i32(tmp2, tmp2);
10555 } else {
10556 /* pkhbt */
10557 if (shift)
10558 tcg_gen_shli_i32(tmp2, tmp2, shift);
10559 tcg_gen_ext16u_i32(tmp, tmp);
10560 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
10562 tcg_gen_or_i32(tmp, tmp, tmp2);
10563 tcg_temp_free_i32(tmp2);
10564 store_reg(s, rd, tmp);
10565 } else {
10566 /* Data processing register constant shift. */
10567 if (rn == 15) {
10568 tmp = tcg_temp_new_i32();
10569 tcg_gen_movi_i32(tmp, 0);
10570 } else {
10571 tmp = load_reg(s, rn);
10573 tmp2 = load_reg(s, rm);
10575 shiftop = (insn >> 4) & 3;
10576 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
10577 conds = (insn & (1 << 20)) != 0;
10578 logic_cc = (conds && thumb2_logic_op(op));
10579 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
10580 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
10581 goto illegal_op;
10582 tcg_temp_free_i32(tmp2);
10583 if (rd == 13 &&
10584 ((op == 2 && rn == 15) ||
10585 (op == 8 && rn == 13) ||
10586 (op == 13 && rn == 13))) {
10587 /* MOV SP, ... or ADD SP, SP, ... or SUB SP, SP, ... */
10588 store_sp_checked(s, tmp);
10589 } else if (rd != 15) {
10590 store_reg(s, rd, tmp);
10591 } else {
10592 tcg_temp_free_i32(tmp);
10595 break;
10596 case 13: /* Misc data processing. */
10597 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
10598 if (op < 4 && (insn & 0xf000) != 0xf000)
10599 goto illegal_op;
10600 switch (op) {
10601 case 0: /* Register controlled shift. */
10602 tmp = load_reg(s, rn);
10603 tmp2 = load_reg(s, rm);
10604 if ((insn & 0x70) != 0)
10605 goto illegal_op;
10607 * 0b1111_1010_0xxx_xxxx_1111_xxxx_0000_xxxx:
10608 * - MOV, MOVS (register-shifted register), flagsetting
10610 op = (insn >> 21) & 3;
10611 logic_cc = (insn & (1 << 20)) != 0;
10612 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
10613 if (logic_cc)
10614 gen_logic_CC(tmp);
10615 store_reg(s, rd, tmp);
10616 break;
10617 case 1: /* Sign/zero extend. */
10618 op = (insn >> 20) & 7;
10619 switch (op) {
10620 case 0: /* SXTAH, SXTH */
10621 case 1: /* UXTAH, UXTH */
10622 case 4: /* SXTAB, SXTB */
10623 case 5: /* UXTAB, UXTB */
10624 break;
10625 case 2: /* SXTAB16, SXTB16 */
10626 case 3: /* UXTAB16, UXTB16 */
10627 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10628 goto illegal_op;
10630 break;
10631 default:
10632 goto illegal_op;
10634 if (rn != 15) {
10635 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10636 goto illegal_op;
10639 tmp = load_reg(s, rm);
10640 shift = (insn >> 4) & 3;
10641 /* ??? In many cases it's not necessary to do a
10642 rotate, a shift is sufficient. */
10643 if (shift != 0)
10644 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
10645 op = (insn >> 20) & 7;
10646 switch (op) {
10647 case 0: gen_sxth(tmp); break;
10648 case 1: gen_uxth(tmp); break;
10649 case 2: gen_sxtb16(tmp); break;
10650 case 3: gen_uxtb16(tmp); break;
10651 case 4: gen_sxtb(tmp); break;
10652 case 5: gen_uxtb(tmp); break;
10653 default:
10654 g_assert_not_reached();
10656 if (rn != 15) {
10657 tmp2 = load_reg(s, rn);
10658 if ((op >> 1) == 1) {
10659 gen_add16(tmp, tmp2);
10660 } else {
10661 tcg_gen_add_i32(tmp, tmp, tmp2);
10662 tcg_temp_free_i32(tmp2);
10665 store_reg(s, rd, tmp);
10666 break;
10667 case 2: /* SIMD add/subtract. */
10668 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10669 goto illegal_op;
10671 op = (insn >> 20) & 7;
10672 shift = (insn >> 4) & 7;
10673 if ((op & 3) == 3 || (shift & 3) == 3)
10674 goto illegal_op;
10675 tmp = load_reg(s, rn);
10676 tmp2 = load_reg(s, rm);
10677 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
10678 tcg_temp_free_i32(tmp2);
10679 store_reg(s, rd, tmp);
10680 break;
10681 case 3: /* Other data processing. */
10682 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
10683 if (op < 4) {
10684 /* Saturating add/subtract. */
10685 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10686 goto illegal_op;
10688 tmp = load_reg(s, rn);
10689 tmp2 = load_reg(s, rm);
10690 if (op & 1)
10691 gen_helper_double_saturate(tmp, cpu_env, tmp);
10692 if (op & 2)
10693 gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);
10694 else
10695 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
10696 tcg_temp_free_i32(tmp2);
10697 } else {
10698 switch (op) {
10699 case 0x0a: /* rbit */
10700 case 0x08: /* rev */
10701 case 0x09: /* rev16 */
10702 case 0x0b: /* revsh */
10703 case 0x18: /* clz */
10704 break;
10705 case 0x10: /* sel */
10706 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10707 goto illegal_op;
10709 break;
10710 case 0x20: /* crc32/crc32c */
10711 case 0x21:
10712 case 0x22:
10713 case 0x28:
10714 case 0x29:
10715 case 0x2a:
10716 if (!dc_isar_feature(aa32_crc32, s)) {
10717 goto illegal_op;
10719 break;
10720 default:
10721 goto illegal_op;
10723 tmp = load_reg(s, rn);
10724 switch (op) {
10725 case 0x0a: /* rbit */
10726 gen_helper_rbit(tmp, tmp);
10727 break;
10728 case 0x08: /* rev */
10729 tcg_gen_bswap32_i32(tmp, tmp);
10730 break;
10731 case 0x09: /* rev16 */
10732 gen_rev16(tmp);
10733 break;
10734 case 0x0b: /* revsh */
10735 gen_revsh(tmp);
10736 break;
10737 case 0x10: /* sel */
10738 tmp2 = load_reg(s, rm);
10739 tmp3 = tcg_temp_new_i32();
10740 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
10741 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
10742 tcg_temp_free_i32(tmp3);
10743 tcg_temp_free_i32(tmp2);
10744 break;
10745 case 0x18: /* clz */
10746 tcg_gen_clzi_i32(tmp, tmp, 32);
10747 break;
10748 case 0x20:
10749 case 0x21:
10750 case 0x22:
10751 case 0x28:
10752 case 0x29:
10753 case 0x2a:
10755 /* crc32/crc32c */
10756 uint32_t sz = op & 0x3;
10757 uint32_t c = op & 0x8;
10759 tmp2 = load_reg(s, rm);
10760 if (sz == 0) {
10761 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
10762 } else if (sz == 1) {
10763 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
10765 tmp3 = tcg_const_i32(1 << sz);
10766 if (c) {
10767 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
10768 } else {
10769 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
10771 tcg_temp_free_i32(tmp2);
10772 tcg_temp_free_i32(tmp3);
10773 break;
10775 default:
10776 g_assert_not_reached();
10779 store_reg(s, rd, tmp);
10780 break;
10781 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
10782 switch ((insn >> 20) & 7) {
10783 case 0: /* 32 x 32 -> 32 */
10784 case 7: /* Unsigned sum of absolute differences. */
10785 break;
10786 case 1: /* 16 x 16 -> 32 */
10787 case 2: /* Dual multiply add. */
10788 case 3: /* 32 * 16 -> 32msb */
10789 case 4: /* Dual multiply subtract. */
10790 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
10791 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10792 goto illegal_op;
10794 break;
10796 op = (insn >> 4) & 0xf;
10797 tmp = load_reg(s, rn);
10798 tmp2 = load_reg(s, rm);
10799 switch ((insn >> 20) & 7) {
10800 case 0: /* 32 x 32 -> 32 */
10801 tcg_gen_mul_i32(tmp, tmp, tmp2);
10802 tcg_temp_free_i32(tmp2);
10803 if (rs != 15) {
10804 tmp2 = load_reg(s, rs);
10805 if (op)
10806 tcg_gen_sub_i32(tmp, tmp2, tmp);
10807 else
10808 tcg_gen_add_i32(tmp, tmp, tmp2);
10809 tcg_temp_free_i32(tmp2);
10811 break;
10812 case 1: /* 16 x 16 -> 32 */
10813 gen_mulxy(tmp, tmp2, op & 2, op & 1);
10814 tcg_temp_free_i32(tmp2);
10815 if (rs != 15) {
10816 tmp2 = load_reg(s, rs);
10817 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
10818 tcg_temp_free_i32(tmp2);
10820 break;
10821 case 2: /* Dual multiply add. */
10822 case 4: /* Dual multiply subtract. */
10823 if (op)
10824 gen_swap_half(tmp2);
10825 gen_smul_dual(tmp, tmp2);
10826 if (insn & (1 << 22)) {
10827 /* This subtraction cannot overflow. */
10828 tcg_gen_sub_i32(tmp, tmp, tmp2);
10829 } else {
10830 /* This addition cannot overflow 32 bits;
10831 * however it may overflow considered as a signed
10832 * operation, in which case we must set the Q flag.
10834 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
10836 tcg_temp_free_i32(tmp2);
10837 if (rs != 15)
10839 tmp2 = load_reg(s, rs);
10840 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
10841 tcg_temp_free_i32(tmp2);
10843 break;
10844 case 3: /* 32 * 16 -> 32msb */
10845 if (op)
10846 tcg_gen_sari_i32(tmp2, tmp2, 16);
10847 else
10848 gen_sxth(tmp2);
10849 tmp64 = gen_muls_i64_i32(tmp, tmp2);
10850 tcg_gen_shri_i64(tmp64, tmp64, 16);
10851 tmp = tcg_temp_new_i32();
10852 tcg_gen_extrl_i64_i32(tmp, tmp64);
10853 tcg_temp_free_i64(tmp64);
10854 if (rs != 15)
10856 tmp2 = load_reg(s, rs);
10857 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
10858 tcg_temp_free_i32(tmp2);
10860 break;
10861 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
10862 tmp64 = gen_muls_i64_i32(tmp, tmp2);
10863 if (rs != 15) {
10864 tmp = load_reg(s, rs);
10865 if (insn & (1 << 20)) {
10866 tmp64 = gen_addq_msw(tmp64, tmp);
10867 } else {
10868 tmp64 = gen_subq_msw(tmp64, tmp);
10871 if (insn & (1 << 4)) {
10872 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
10874 tcg_gen_shri_i64(tmp64, tmp64, 32);
10875 tmp = tcg_temp_new_i32();
10876 tcg_gen_extrl_i64_i32(tmp, tmp64);
10877 tcg_temp_free_i64(tmp64);
10878 break;
10879 case 7: /* Unsigned sum of absolute differences. */
10880 gen_helper_usad8(tmp, tmp, tmp2);
10881 tcg_temp_free_i32(tmp2);
10882 if (rs != 15) {
10883 tmp2 = load_reg(s, rs);
10884 tcg_gen_add_i32(tmp, tmp, tmp2);
10885 tcg_temp_free_i32(tmp2);
10887 break;
10889 store_reg(s, rd, tmp);
10890 break;
10891 case 6: case 7: /* 64-bit multiply, Divide. */
10892 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
10893 tmp = load_reg(s, rn);
10894 tmp2 = load_reg(s, rm);
10895 if ((op & 0x50) == 0x10) {
10896 /* sdiv, udiv */
10897 if (!dc_isar_feature(thumb_div, s)) {
10898 goto illegal_op;
10900 if (op & 0x20)
10901 gen_helper_udiv(tmp, tmp, tmp2);
10902 else
10903 gen_helper_sdiv(tmp, tmp, tmp2);
10904 tcg_temp_free_i32(tmp2);
10905 store_reg(s, rd, tmp);
10906 } else if ((op & 0xe) == 0xc) {
10907 /* Dual multiply accumulate long. */
10908 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10909 tcg_temp_free_i32(tmp);
10910 tcg_temp_free_i32(tmp2);
10911 goto illegal_op;
10913 if (op & 1)
10914 gen_swap_half(tmp2);
10915 gen_smul_dual(tmp, tmp2);
10916 if (op & 0x10) {
10917 tcg_gen_sub_i32(tmp, tmp, tmp2);
10918 } else {
10919 tcg_gen_add_i32(tmp, tmp, tmp2);
10921 tcg_temp_free_i32(tmp2);
10922 /* BUGFIX */
10923 tmp64 = tcg_temp_new_i64();
10924 tcg_gen_ext_i32_i64(tmp64, tmp);
10925 tcg_temp_free_i32(tmp);
10926 gen_addq(s, tmp64, rs, rd);
10927 gen_storeq_reg(s, rs, rd, tmp64);
10928 tcg_temp_free_i64(tmp64);
10929 } else {
10930 if (op & 0x20) {
10931 /* Unsigned 64-bit multiply */
10932 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
10933 } else {
10934 if (op & 8) {
10935 /* smlalxy */
10936 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10937 tcg_temp_free_i32(tmp2);
10938 tcg_temp_free_i32(tmp);
10939 goto illegal_op;
10941 gen_mulxy(tmp, tmp2, op & 2, op & 1);
10942 tcg_temp_free_i32(tmp2);
10943 tmp64 = tcg_temp_new_i64();
10944 tcg_gen_ext_i32_i64(tmp64, tmp);
10945 tcg_temp_free_i32(tmp);
10946 } else {
10947 /* Signed 64-bit multiply */
10948 tmp64 = gen_muls_i64_i32(tmp, tmp2);
10951 if (op & 4) {
10952 /* umaal */
10953 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10954 tcg_temp_free_i64(tmp64);
10955 goto illegal_op;
10957 gen_addq_lo(s, tmp64, rs);
10958 gen_addq_lo(s, tmp64, rd);
10959 } else if (op & 0x40) {
10960 /* 64-bit accumulate. */
10961 gen_addq(s, tmp64, rs, rd);
10963 gen_storeq_reg(s, rs, rd, tmp64);
10964 tcg_temp_free_i64(tmp64);
10966 break;
10968 break;
10969 case 6: case 7: case 14: case 15:
10970 /* Coprocessor. */
10971 if (arm_dc_feature(s, ARM_FEATURE_M)) {
10972 /* 0b111x_11xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx */
10973 if (extract32(insn, 24, 2) == 3) {
10974 goto illegal_op; /* op0 = 0b11 : unallocated */
10978 * Decode VLLDM and VLSTM first: these are nonstandard because:
10979 * * if there is no FPU then these insns must NOP in
10980 * Secure state and UNDEF in Nonsecure state
10981 * * if there is an FPU then these insns do not have
10982 * the usual behaviour that disas_vfp_insn() provides of
10983 * being controlled by CPACR/NSACR enable bits or the
10984 * lazy-stacking logic.
10986 if (arm_dc_feature(s, ARM_FEATURE_V8) &&
10987 (insn & 0xffa00f00) == 0xec200a00) {
10988 /* 0b1110_1100_0x1x_xxxx_xxxx_1010_xxxx_xxxx
10989 * - VLLDM, VLSTM
10990 * We choose to UNDEF if the RAZ bits are non-zero.
10992 if (!s->v8m_secure || (insn & 0x0040f0ff)) {
10993 goto illegal_op;
10996 if (arm_dc_feature(s, ARM_FEATURE_VFP)) {
10997 TCGv_i32 fptr = load_reg(s, rn);
10999 if (extract32(insn, 20, 1)) {
11000 gen_helper_v7m_vlldm(cpu_env, fptr);
11001 } else {
11002 gen_helper_v7m_vlstm(cpu_env, fptr);
11004 tcg_temp_free_i32(fptr);
11006 /* End the TB, because we have updated FP control bits */
11007 s->base.is_jmp = DISAS_UPDATE;
11009 break;
11011 if (arm_dc_feature(s, ARM_FEATURE_VFP) &&
11012 ((insn >> 8) & 0xe) == 10) {
11013 /* FP, and the CPU supports it */
11014 if (disas_vfp_insn(s, insn)) {
11015 goto illegal_op;
11017 break;
11020 /* All other insns: NOCP */
11021 gen_exception_insn(s, 4, EXCP_NOCP, syn_uncategorized(),
11022 default_exception_el(s));
11023 break;
11025 if ((insn & 0xfe000a00) == 0xfc000800
11026 && arm_dc_feature(s, ARM_FEATURE_V8)) {
11027 /* The Thumb2 and ARM encodings are identical. */
11028 if (disas_neon_insn_3same_ext(s, insn)) {
11029 goto illegal_op;
11031 } else if ((insn & 0xff000a00) == 0xfe000800
11032 && arm_dc_feature(s, ARM_FEATURE_V8)) {
11033 /* The Thumb2 and ARM encodings are identical. */
11034 if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
11035 goto illegal_op;
11037 } else if (((insn >> 24) & 3) == 3) {
11038 /* Translate into the equivalent ARM encoding. */
11039 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
11040 if (disas_neon_data_insn(s, insn)) {
11041 goto illegal_op;
11043 } else if (((insn >> 8) & 0xe) == 10) {
11044 if (disas_vfp_insn(s, insn)) {
11045 goto illegal_op;
11047 } else {
11048 if (insn & (1 << 28))
11049 goto illegal_op;
11050 if (disas_coproc_insn(s, insn)) {
11051 goto illegal_op;
11054 break;
11055 case 8: case 9: case 10: case 11:
11056 if (insn & (1 << 15)) {
11057 /* Branches, misc control. */
11058 if (insn & 0x5000) {
11059 /* Unconditional branch. */
11060 /* signextend(hw1[10:0]) -> offset[:12]. */
11061 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
11062 /* hw1[10:0] -> offset[11:1]. */
11063 offset |= (insn & 0x7ff) << 1;
11064 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
11065 offset[24:22] already have the same value because of the
11066 sign extension above. */
11067 offset ^= ((~insn) & (1 << 13)) << 10;
11068 offset ^= ((~insn) & (1 << 11)) << 11;
11070 if (insn & (1 << 14)) {
11071 /* Branch and link. */
11072 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
11075 offset += s->pc;
11076 if (insn & (1 << 12)) {
11077 /* b/bl */
11078 gen_jmp(s, offset);
11079 } else {
11080 /* blx */
11081 offset &= ~(uint32_t)2;
11082 /* thumb2 bx, no need to check */
11083 gen_bx_im(s, offset);
11085 } else if (((insn >> 23) & 7) == 7) {
11086 /* Misc control */
11087 if (insn & (1 << 13))
11088 goto illegal_op;
11090 if (insn & (1 << 26)) {
11091 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11092 goto illegal_op;
11094 if (!(insn & (1 << 20))) {
11095 /* Hypervisor call (v7) */
11096 int imm16 = extract32(insn, 16, 4) << 12
11097 | extract32(insn, 0, 12);
11098 ARCH(7);
11099 if (IS_USER(s)) {
11100 goto illegal_op;
11102 gen_hvc(s, imm16);
11103 } else {
11104 /* Secure monitor call (v6+) */
11105 ARCH(6K);
11106 if (IS_USER(s)) {
11107 goto illegal_op;
11109 gen_smc(s);
11111 } else {
11112 op = (insn >> 20) & 7;
11113 switch (op) {
11114 case 0: /* msr cpsr. */
11115 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11116 tmp = load_reg(s, rn);
11117 /* the constant is the mask and SYSm fields */
11118 addr = tcg_const_i32(insn & 0xfff);
11119 gen_helper_v7m_msr(cpu_env, addr, tmp);
11120 tcg_temp_free_i32(addr);
11121 tcg_temp_free_i32(tmp);
11122 gen_lookup_tb(s);
11123 break;
11125 /* fall through */
11126 case 1: /* msr spsr. */
11127 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11128 goto illegal_op;
11131 if (extract32(insn, 5, 1)) {
11132 /* MSR (banked) */
11133 int sysm = extract32(insn, 8, 4) |
11134 (extract32(insn, 4, 1) << 4);
11135 int r = op & 1;
11137 gen_msr_banked(s, r, sysm, rm);
11138 break;
11141 /* MSR (for PSRs) */
11142 tmp = load_reg(s, rn);
11143 if (gen_set_psr(s,
11144 msr_mask(s, (insn >> 8) & 0xf, op == 1),
11145 op == 1, tmp))
11146 goto illegal_op;
11147 break;
11148 case 2: /* cps, nop-hint. */
11149 if (((insn >> 8) & 7) == 0) {
11150 gen_nop_hint(s, insn & 0xff);
11152 /* Implemented as NOP in user mode. */
11153 if (IS_USER(s))
11154 break;
11155 offset = 0;
11156 imm = 0;
11157 if (insn & (1 << 10)) {
11158 if (insn & (1 << 7))
11159 offset |= CPSR_A;
11160 if (insn & (1 << 6))
11161 offset |= CPSR_I;
11162 if (insn & (1 << 5))
11163 offset |= CPSR_F;
11164 if (insn & (1 << 9))
11165 imm = CPSR_A | CPSR_I | CPSR_F;
11167 if (insn & (1 << 8)) {
11168 offset |= 0x1f;
11169 imm |= (insn & 0x1f);
11171 if (offset) {
11172 gen_set_psr_im(s, offset, 0, imm);
11174 break;
11175 case 3: /* Special control operations. */
11176 if (!arm_dc_feature(s, ARM_FEATURE_V7) &&
11177 !arm_dc_feature(s, ARM_FEATURE_M)) {
11178 goto illegal_op;
11180 op = (insn >> 4) & 0xf;
11181 switch (op) {
11182 case 2: /* clrex */
11183 gen_clrex(s);
11184 break;
11185 case 4: /* dsb */
11186 case 5: /* dmb */
11187 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
11188 break;
11189 case 6: /* isb */
11190 /* We need to break the TB after this insn
11191 * to execute self-modifying code correctly
11192 * and also to take any pending interrupts
11193 * immediately.
11195 gen_goto_tb(s, 0, s->pc & ~1);
11196 break;
11197 case 7: /* sb */
11198 if ((insn & 0xf) || !dc_isar_feature(aa32_sb, s)) {
11199 goto illegal_op;
11202 * TODO: There is no speculation barrier opcode
11203 * for TCG; MB and end the TB instead.
11205 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
11206 gen_goto_tb(s, 0, s->pc & ~1);
11207 break;
11208 default:
11209 goto illegal_op;
11211 break;
11212 case 4: /* bxj */
11213 /* Trivial implementation equivalent to bx.
11214 * This instruction doesn't exist at all for M-profile.
11216 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11217 goto illegal_op;
11219 tmp = load_reg(s, rn);
11220 gen_bx(s, tmp);
11221 break;
11222 case 5: /* Exception return. */
11223 if (IS_USER(s)) {
11224 goto illegal_op;
11226 if (rn != 14 || rd != 15) {
11227 goto illegal_op;
11229 if (s->current_el == 2) {
11230 /* ERET from Hyp uses ELR_Hyp, not LR */
11231 if (insn & 0xff) {
11232 goto illegal_op;
11234 tmp = load_cpu_field(elr_el[2]);
11235 } else {
11236 tmp = load_reg(s, rn);
11237 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
11239 gen_exception_return(s, tmp);
11240 break;
11241 case 6: /* MRS */
11242 if (extract32(insn, 5, 1) &&
11243 !arm_dc_feature(s, ARM_FEATURE_M)) {
11244 /* MRS (banked) */
11245 int sysm = extract32(insn, 16, 4) |
11246 (extract32(insn, 4, 1) << 4);
11248 gen_mrs_banked(s, 0, sysm, rd);
11249 break;
11252 if (extract32(insn, 16, 4) != 0xf) {
11253 goto illegal_op;
11255 if (!arm_dc_feature(s, ARM_FEATURE_M) &&
11256 extract32(insn, 0, 8) != 0) {
11257 goto illegal_op;
11260 /* mrs cpsr */
11261 tmp = tcg_temp_new_i32();
11262 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11263 addr = tcg_const_i32(insn & 0xff);
11264 gen_helper_v7m_mrs(tmp, cpu_env, addr);
11265 tcg_temp_free_i32(addr);
11266 } else {
11267 gen_helper_cpsr_read(tmp, cpu_env);
11269 store_reg(s, rd, tmp);
11270 break;
11271 case 7: /* MRS */
11272 if (extract32(insn, 5, 1) &&
11273 !arm_dc_feature(s, ARM_FEATURE_M)) {
11274 /* MRS (banked) */
11275 int sysm = extract32(insn, 16, 4) |
11276 (extract32(insn, 4, 1) << 4);
11278 gen_mrs_banked(s, 1, sysm, rd);
11279 break;
11282 /* mrs spsr. */
11283 /* Not accessible in user mode. */
11284 if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
11285 goto illegal_op;
11288 if (extract32(insn, 16, 4) != 0xf ||
11289 extract32(insn, 0, 8) != 0) {
11290 goto illegal_op;
11293 tmp = load_cpu_field(spsr);
11294 store_reg(s, rd, tmp);
11295 break;
11298 } else {
11299 /* Conditional branch. */
11300 op = (insn >> 22) & 0xf;
11301 /* Generate a conditional jump to next instruction. */
11302 arm_skip_unless(s, op);
11304 /* offset[11:1] = insn[10:0] */
11305 offset = (insn & 0x7ff) << 1;
11306 /* offset[17:12] = insn[21:16]. */
11307 offset |= (insn & 0x003f0000) >> 4;
11308 /* offset[31:20] = insn[26]. */
11309 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
11310 /* offset[18] = insn[13]. */
11311 offset |= (insn & (1 << 13)) << 5;
11312 /* offset[19] = insn[11]. */
11313 offset |= (insn & (1 << 11)) << 8;
11315 /* jump to the offset */
11316 gen_jmp(s, s->pc + offset);
11318 } else {
11320 * 0b1111_0xxx_xxxx_0xxx_xxxx_xxxx
11321 * - Data-processing (modified immediate, plain binary immediate)
11323 if (insn & (1 << 25)) {
11325 * 0b1111_0x1x_xxxx_0xxx_xxxx_xxxx
11326 * - Data-processing (plain binary immediate)
11328 if (insn & (1 << 24)) {
11329 if (insn & (1 << 20))
11330 goto illegal_op;
11331 /* Bitfield/Saturate. */
11332 op = (insn >> 21) & 7;
11333 imm = insn & 0x1f;
11334 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
11335 if (rn == 15) {
11336 tmp = tcg_temp_new_i32();
11337 tcg_gen_movi_i32(tmp, 0);
11338 } else {
11339 tmp = load_reg(s, rn);
11341 switch (op) {
11342 case 2: /* Signed bitfield extract. */
11343 imm++;
11344 if (shift + imm > 32)
11345 goto illegal_op;
11346 if (imm < 32) {
11347 tcg_gen_sextract_i32(tmp, tmp, shift, imm);
11349 break;
11350 case 6: /* Unsigned bitfield extract. */
11351 imm++;
11352 if (shift + imm > 32)
11353 goto illegal_op;
11354 if (imm < 32) {
11355 tcg_gen_extract_i32(tmp, tmp, shift, imm);
11357 break;
11358 case 3: /* Bitfield insert/clear. */
11359 if (imm < shift)
11360 goto illegal_op;
11361 imm = imm + 1 - shift;
11362 if (imm != 32) {
11363 tmp2 = load_reg(s, rd);
11364 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, imm);
11365 tcg_temp_free_i32(tmp2);
11367 break;
11368 case 7:
11369 goto illegal_op;
11370 default: /* Saturate. */
11371 if (shift) {
11372 if (op & 1)
11373 tcg_gen_sari_i32(tmp, tmp, shift);
11374 else
11375 tcg_gen_shli_i32(tmp, tmp, shift);
11377 tmp2 = tcg_const_i32(imm);
11378 if (op & 4) {
11379 /* Unsigned. */
11380 if ((op & 1) && shift == 0) {
11381 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11382 tcg_temp_free_i32(tmp);
11383 tcg_temp_free_i32(tmp2);
11384 goto illegal_op;
11386 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
11387 } else {
11388 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
11390 } else {
11391 /* Signed. */
11392 if ((op & 1) && shift == 0) {
11393 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11394 tcg_temp_free_i32(tmp);
11395 tcg_temp_free_i32(tmp2);
11396 goto illegal_op;
11398 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
11399 } else {
11400 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
11403 tcg_temp_free_i32(tmp2);
11404 break;
11406 store_reg(s, rd, tmp);
11407 } else {
11408 imm = ((insn & 0x04000000) >> 15)
11409 | ((insn & 0x7000) >> 4) | (insn & 0xff);
11410 if (insn & (1 << 22)) {
11411 /* 16-bit immediate. */
11412 imm |= (insn >> 4) & 0xf000;
11413 if (insn & (1 << 23)) {
11414 /* movt */
11415 tmp = load_reg(s, rd);
11416 tcg_gen_ext16u_i32(tmp, tmp);
11417 tcg_gen_ori_i32(tmp, tmp, imm << 16);
11418 } else {
11419 /* movw */
11420 tmp = tcg_temp_new_i32();
11421 tcg_gen_movi_i32(tmp, imm);
11423 store_reg(s, rd, tmp);
11424 } else {
11425 /* Add/sub 12-bit immediate. */
11426 if (rn == 15) {
11427 offset = s->pc & ~(uint32_t)3;
11428 if (insn & (1 << 23))
11429 offset -= imm;
11430 else
11431 offset += imm;
11432 tmp = tcg_temp_new_i32();
11433 tcg_gen_movi_i32(tmp, offset);
11434 store_reg(s, rd, tmp);
11435 } else {
11436 tmp = load_reg(s, rn);
11437 if (insn & (1 << 23))
11438 tcg_gen_subi_i32(tmp, tmp, imm);
11439 else
11440 tcg_gen_addi_i32(tmp, tmp, imm);
11441 if (rn == 13 && rd == 13) {
11442 /* ADD SP, SP, imm or SUB SP, SP, imm */
11443 store_sp_checked(s, tmp);
11444 } else {
11445 store_reg(s, rd, tmp);
11450 } else {
11452 * 0b1111_0x0x_xxxx_0xxx_xxxx_xxxx
11453 * - Data-processing (modified immediate)
11455 int shifter_out = 0;
11456 /* modified 12-bit immediate. */
11457 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
11458 imm = (insn & 0xff);
11459 switch (shift) {
11460 case 0: /* XY */
11461 /* Nothing to do. */
11462 break;
11463 case 1: /* 00XY00XY */
11464 imm |= imm << 16;
11465 break;
11466 case 2: /* XY00XY00 */
11467 imm |= imm << 16;
11468 imm <<= 8;
11469 break;
11470 case 3: /* XYXYXYXY */
11471 imm |= imm << 16;
11472 imm |= imm << 8;
11473 break;
11474 default: /* Rotated constant. */
11475 shift = (shift << 1) | (imm >> 7);
11476 imm |= 0x80;
11477 imm = imm << (32 - shift);
11478 shifter_out = 1;
11479 break;
11481 tmp2 = tcg_temp_new_i32();
11482 tcg_gen_movi_i32(tmp2, imm);
11483 rn = (insn >> 16) & 0xf;
11484 if (rn == 15) {
11485 tmp = tcg_temp_new_i32();
11486 tcg_gen_movi_i32(tmp, 0);
11487 } else {
11488 tmp = load_reg(s, rn);
11490 op = (insn >> 21) & 0xf;
11491 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
11492 shifter_out, tmp, tmp2))
11493 goto illegal_op;
11494 tcg_temp_free_i32(tmp2);
11495 rd = (insn >> 8) & 0xf;
11496 if (rd == 13 && rn == 13
11497 && (op == 8 || op == 13)) {
11498 /* ADD(S) SP, SP, imm or SUB(S) SP, SP, imm */
11499 store_sp_checked(s, tmp);
11500 } else if (rd != 15) {
11501 store_reg(s, rd, tmp);
11502 } else {
11503 tcg_temp_free_i32(tmp);
11507 break;
11508 case 12: /* Load/store single data item. */
11510 int postinc = 0;
11511 int writeback = 0;
11512 int memidx;
11513 ISSInfo issinfo;
11515 if ((insn & 0x01100000) == 0x01000000) {
11516 if (disas_neon_ls_insn(s, insn)) {
11517 goto illegal_op;
11519 break;
11521 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
11522 if (rs == 15) {
11523 if (!(insn & (1 << 20))) {
11524 goto illegal_op;
11526 if (op != 2) {
11527 /* Byte or halfword load space with dest == r15 : memory hints.
11528 * Catch them early so we don't emit pointless addressing code.
11529 * This space is a mix of:
11530 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
11531 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
11532 * cores)
11533 * unallocated hints, which must be treated as NOPs
11534 * UNPREDICTABLE space, which we NOP or UNDEF depending on
11535 * which is easiest for the decoding logic
11536 * Some space which must UNDEF
11538 int op1 = (insn >> 23) & 3;
11539 int op2 = (insn >> 6) & 0x3f;
11540 if (op & 2) {
11541 goto illegal_op;
11543 if (rn == 15) {
11544 /* UNPREDICTABLE, unallocated hint or
11545 * PLD/PLDW/PLI (literal)
11547 return;
11549 if (op1 & 1) {
11550 return; /* PLD/PLDW/PLI or unallocated hint */
11552 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
11553 return; /* PLD/PLDW/PLI or unallocated hint */
11555 /* UNDEF space, or an UNPREDICTABLE */
11556 goto illegal_op;
11559 memidx = get_mem_index(s);
11560 if (rn == 15) {
11561 addr = tcg_temp_new_i32();
11562 /* PC relative. */
11563 /* s->pc has already been incremented by 4. */
11564 imm = s->pc & 0xfffffffc;
11565 if (insn & (1 << 23))
11566 imm += insn & 0xfff;
11567 else
11568 imm -= insn & 0xfff;
11569 tcg_gen_movi_i32(addr, imm);
11570 } else {
11571 addr = load_reg(s, rn);
11572 if (insn & (1 << 23)) {
11573 /* Positive offset. */
11574 imm = insn & 0xfff;
11575 tcg_gen_addi_i32(addr, addr, imm);
11576 } else {
11577 imm = insn & 0xff;
11578 switch ((insn >> 8) & 0xf) {
11579 case 0x0: /* Shifted Register. */
11580 shift = (insn >> 4) & 0xf;
11581 if (shift > 3) {
11582 tcg_temp_free_i32(addr);
11583 goto illegal_op;
11585 tmp = load_reg(s, rm);
11586 if (shift)
11587 tcg_gen_shli_i32(tmp, tmp, shift);
11588 tcg_gen_add_i32(addr, addr, tmp);
11589 tcg_temp_free_i32(tmp);
11590 break;
11591 case 0xc: /* Negative offset. */
11592 tcg_gen_addi_i32(addr, addr, -imm);
11593 break;
11594 case 0xe: /* User privilege. */
11595 tcg_gen_addi_i32(addr, addr, imm);
11596 memidx = get_a32_user_mem_index(s);
11597 break;
11598 case 0x9: /* Post-decrement. */
11599 imm = -imm;
11600 /* Fall through. */
11601 case 0xb: /* Post-increment. */
11602 postinc = 1;
11603 writeback = 1;
11604 break;
11605 case 0xd: /* Pre-decrement. */
11606 imm = -imm;
11607 /* Fall through. */
11608 case 0xf: /* Pre-increment. */
11609 writeback = 1;
11610 break;
11611 default:
11612 tcg_temp_free_i32(addr);
11613 goto illegal_op;
11618 issinfo = writeback ? ISSInvalid : rs;
11620 if (s->v8m_stackcheck && rn == 13 && writeback) {
11622 * Stackcheck. Here we know 'addr' is the current SP;
11623 * if imm is +ve we're moving SP up, else down. It is
11624 * UNKNOWN whether the limit check triggers when SP starts
11625 * below the limit and ends up above it; we chose to do so.
11627 if ((int32_t)imm < 0) {
11628 TCGv_i32 newsp = tcg_temp_new_i32();
11630 tcg_gen_addi_i32(newsp, addr, imm);
11631 gen_helper_v8m_stackcheck(cpu_env, newsp);
11632 tcg_temp_free_i32(newsp);
11633 } else {
11634 gen_helper_v8m_stackcheck(cpu_env, addr);
11638 if (writeback && !postinc) {
11639 tcg_gen_addi_i32(addr, addr, imm);
11642 if (insn & (1 << 20)) {
11643 /* Load. */
11644 tmp = tcg_temp_new_i32();
11645 switch (op) {
11646 case 0:
11647 gen_aa32_ld8u_iss(s, tmp, addr, memidx, issinfo);
11648 break;
11649 case 4:
11650 gen_aa32_ld8s_iss(s, tmp, addr, memidx, issinfo);
11651 break;
11652 case 1:
11653 gen_aa32_ld16u_iss(s, tmp, addr, memidx, issinfo);
11654 break;
11655 case 5:
11656 gen_aa32_ld16s_iss(s, tmp, addr, memidx, issinfo);
11657 break;
11658 case 2:
11659 gen_aa32_ld32u_iss(s, tmp, addr, memidx, issinfo);
11660 break;
11661 default:
11662 tcg_temp_free_i32(tmp);
11663 tcg_temp_free_i32(addr);
11664 goto illegal_op;
11666 if (rs == 15) {
11667 gen_bx_excret(s, tmp);
11668 } else {
11669 store_reg(s, rs, tmp);
11671 } else {
11672 /* Store. */
11673 tmp = load_reg(s, rs);
11674 switch (op) {
11675 case 0:
11676 gen_aa32_st8_iss(s, tmp, addr, memidx, issinfo);
11677 break;
11678 case 1:
11679 gen_aa32_st16_iss(s, tmp, addr, memidx, issinfo);
11680 break;
11681 case 2:
11682 gen_aa32_st32_iss(s, tmp, addr, memidx, issinfo);
11683 break;
11684 default:
11685 tcg_temp_free_i32(tmp);
11686 tcg_temp_free_i32(addr);
11687 goto illegal_op;
11689 tcg_temp_free_i32(tmp);
11691 if (postinc)
11692 tcg_gen_addi_i32(addr, addr, imm);
11693 if (writeback) {
11694 store_reg(s, rn, addr);
11695 } else {
11696 tcg_temp_free_i32(addr);
11699 break;
11700 default:
11701 goto illegal_op;
11703 return;
11704 illegal_op:
11705 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
11706 default_exception_el(s));
11709 static void disas_thumb_insn(DisasContext *s, uint32_t insn)
11711 uint32_t val, op, rm, rn, rd, shift, cond;
11712 int32_t offset;
11713 int i;
11714 TCGv_i32 tmp;
11715 TCGv_i32 tmp2;
11716 TCGv_i32 addr;
11718 switch (insn >> 12) {
11719 case 0: case 1:
11721 rd = insn & 7;
11722 op = (insn >> 11) & 3;
11723 if (op == 3) {
11725 * 0b0001_1xxx_xxxx_xxxx
11726 * - Add, subtract (three low registers)
11727 * - Add, subtract (two low registers and immediate)
11729 rn = (insn >> 3) & 7;
11730 tmp = load_reg(s, rn);
11731 if (insn & (1 << 10)) {
11732 /* immediate */
11733 tmp2 = tcg_temp_new_i32();
11734 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
11735 } else {
11736 /* reg */
11737 rm = (insn >> 6) & 7;
11738 tmp2 = load_reg(s, rm);
11740 if (insn & (1 << 9)) {
11741 if (s->condexec_mask)
11742 tcg_gen_sub_i32(tmp, tmp, tmp2);
11743 else
11744 gen_sub_CC(tmp, tmp, tmp2);
11745 } else {
11746 if (s->condexec_mask)
11747 tcg_gen_add_i32(tmp, tmp, tmp2);
11748 else
11749 gen_add_CC(tmp, tmp, tmp2);
11751 tcg_temp_free_i32(tmp2);
11752 store_reg(s, rd, tmp);
11753 } else {
11754 /* shift immediate */
11755 rm = (insn >> 3) & 7;
11756 shift = (insn >> 6) & 0x1f;
11757 tmp = load_reg(s, rm);
11758 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
11759 if (!s->condexec_mask)
11760 gen_logic_CC(tmp);
11761 store_reg(s, rd, tmp);
11763 break;
11764 case 2: case 3:
11766 * 0b001x_xxxx_xxxx_xxxx
11767 * - Add, subtract, compare, move (one low register and immediate)
11769 op = (insn >> 11) & 3;
11770 rd = (insn >> 8) & 0x7;
11771 if (op == 0) { /* mov */
11772 tmp = tcg_temp_new_i32();
11773 tcg_gen_movi_i32(tmp, insn & 0xff);
11774 if (!s->condexec_mask)
11775 gen_logic_CC(tmp);
11776 store_reg(s, rd, tmp);
11777 } else {
11778 tmp = load_reg(s, rd);
11779 tmp2 = tcg_temp_new_i32();
11780 tcg_gen_movi_i32(tmp2, insn & 0xff);
11781 switch (op) {
11782 case 1: /* cmp */
11783 gen_sub_CC(tmp, tmp, tmp2);
11784 tcg_temp_free_i32(tmp);
11785 tcg_temp_free_i32(tmp2);
11786 break;
11787 case 2: /* add */
11788 if (s->condexec_mask)
11789 tcg_gen_add_i32(tmp, tmp, tmp2);
11790 else
11791 gen_add_CC(tmp, tmp, tmp2);
11792 tcg_temp_free_i32(tmp2);
11793 store_reg(s, rd, tmp);
11794 break;
11795 case 3: /* sub */
11796 if (s->condexec_mask)
11797 tcg_gen_sub_i32(tmp, tmp, tmp2);
11798 else
11799 gen_sub_CC(tmp, tmp, tmp2);
11800 tcg_temp_free_i32(tmp2);
11801 store_reg(s, rd, tmp);
11802 break;
11805 break;
11806 case 4:
11807 if (insn & (1 << 11)) {
11808 rd = (insn >> 8) & 7;
11809 /* load pc-relative. Bit 1 of PC is ignored. */
11810 val = s->pc + 2 + ((insn & 0xff) * 4);
11811 val &= ~(uint32_t)2;
11812 addr = tcg_temp_new_i32();
11813 tcg_gen_movi_i32(addr, val);
11814 tmp = tcg_temp_new_i32();
11815 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s),
11816 rd | ISSIs16Bit);
11817 tcg_temp_free_i32(addr);
11818 store_reg(s, rd, tmp);
11819 break;
11821 if (insn & (1 << 10)) {
11822 /* 0b0100_01xx_xxxx_xxxx
11823 * - data processing extended, branch and exchange
11825 rd = (insn & 7) | ((insn >> 4) & 8);
11826 rm = (insn >> 3) & 0xf;
11827 op = (insn >> 8) & 3;
11828 switch (op) {
11829 case 0: /* add */
11830 tmp = load_reg(s, rd);
11831 tmp2 = load_reg(s, rm);
11832 tcg_gen_add_i32(tmp, tmp, tmp2);
11833 tcg_temp_free_i32(tmp2);
11834 if (rd == 13) {
11835 /* ADD SP, SP, reg */
11836 store_sp_checked(s, tmp);
11837 } else {
11838 store_reg(s, rd, tmp);
11840 break;
11841 case 1: /* cmp */
11842 tmp = load_reg(s, rd);
11843 tmp2 = load_reg(s, rm);
11844 gen_sub_CC(tmp, tmp, tmp2);
11845 tcg_temp_free_i32(tmp2);
11846 tcg_temp_free_i32(tmp);
11847 break;
11848 case 2: /* mov/cpy */
11849 tmp = load_reg(s, rm);
11850 if (rd == 13) {
11851 /* MOV SP, reg */
11852 store_sp_checked(s, tmp);
11853 } else {
11854 store_reg(s, rd, tmp);
11856 break;
11857 case 3:
11859 /* 0b0100_0111_xxxx_xxxx
11860 * - branch [and link] exchange thumb register
11862 bool link = insn & (1 << 7);
11864 if (insn & 3) {
11865 goto undef;
11867 if (link) {
11868 ARCH(5);
11870 if ((insn & 4)) {
11871 /* BXNS/BLXNS: only exists for v8M with the
11872 * security extensions, and always UNDEF if NonSecure.
11873 * We don't implement these in the user-only mode
11874 * either (in theory you can use them from Secure User
11875 * mode but they are too tied in to system emulation.)
11877 if (!s->v8m_secure || IS_USER_ONLY) {
11878 goto undef;
11880 if (link) {
11881 gen_blxns(s, rm);
11882 } else {
11883 gen_bxns(s, rm);
11885 break;
11887 /* BLX/BX */
11888 tmp = load_reg(s, rm);
11889 if (link) {
11890 val = (uint32_t)s->pc | 1;
11891 tmp2 = tcg_temp_new_i32();
11892 tcg_gen_movi_i32(tmp2, val);
11893 store_reg(s, 14, tmp2);
11894 gen_bx(s, tmp);
11895 } else {
11896 /* Only BX works as exception-return, not BLX */
11897 gen_bx_excret(s, tmp);
11899 break;
11902 break;
11906 * 0b0100_00xx_xxxx_xxxx
11907 * - Data-processing (two low registers)
11909 rd = insn & 7;
11910 rm = (insn >> 3) & 7;
11911 op = (insn >> 6) & 0xf;
11912 if (op == 2 || op == 3 || op == 4 || op == 7) {
11913 /* the shift/rotate ops want the operands backwards */
11914 val = rm;
11915 rm = rd;
11916 rd = val;
11917 val = 1;
11918 } else {
11919 val = 0;
11922 if (op == 9) { /* neg */
11923 tmp = tcg_temp_new_i32();
11924 tcg_gen_movi_i32(tmp, 0);
11925 } else if (op != 0xf) { /* mvn doesn't read its first operand */
11926 tmp = load_reg(s, rd);
11927 } else {
11928 tmp = NULL;
11931 tmp2 = load_reg(s, rm);
11932 switch (op) {
11933 case 0x0: /* and */
11934 tcg_gen_and_i32(tmp, tmp, tmp2);
11935 if (!s->condexec_mask)
11936 gen_logic_CC(tmp);
11937 break;
11938 case 0x1: /* eor */
11939 tcg_gen_xor_i32(tmp, tmp, tmp2);
11940 if (!s->condexec_mask)
11941 gen_logic_CC(tmp);
11942 break;
11943 case 0x2: /* lsl */
11944 if (s->condexec_mask) {
11945 gen_shl(tmp2, tmp2, tmp);
11946 } else {
11947 gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
11948 gen_logic_CC(tmp2);
11950 break;
11951 case 0x3: /* lsr */
11952 if (s->condexec_mask) {
11953 gen_shr(tmp2, tmp2, tmp);
11954 } else {
11955 gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
11956 gen_logic_CC(tmp2);
11958 break;
11959 case 0x4: /* asr */
11960 if (s->condexec_mask) {
11961 gen_sar(tmp2, tmp2, tmp);
11962 } else {
11963 gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
11964 gen_logic_CC(tmp2);
11966 break;
11967 case 0x5: /* adc */
11968 if (s->condexec_mask) {
11969 gen_adc(tmp, tmp2);
11970 } else {
11971 gen_adc_CC(tmp, tmp, tmp2);
11973 break;
11974 case 0x6: /* sbc */
11975 if (s->condexec_mask) {
11976 gen_sub_carry(tmp, tmp, tmp2);
11977 } else {
11978 gen_sbc_CC(tmp, tmp, tmp2);
11980 break;
11981 case 0x7: /* ror */
11982 if (s->condexec_mask) {
11983 tcg_gen_andi_i32(tmp, tmp, 0x1f);
11984 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
11985 } else {
11986 gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);
11987 gen_logic_CC(tmp2);
11989 break;
11990 case 0x8: /* tst */
11991 tcg_gen_and_i32(tmp, tmp, tmp2);
11992 gen_logic_CC(tmp);
11993 rd = 16;
11994 break;
11995 case 0x9: /* neg */
11996 if (s->condexec_mask)
11997 tcg_gen_neg_i32(tmp, tmp2);
11998 else
11999 gen_sub_CC(tmp, tmp, tmp2);
12000 break;
12001 case 0xa: /* cmp */
12002 gen_sub_CC(tmp, tmp, tmp2);
12003 rd = 16;
12004 break;
12005 case 0xb: /* cmn */
12006 gen_add_CC(tmp, tmp, tmp2);
12007 rd = 16;
12008 break;
12009 case 0xc: /* orr */
12010 tcg_gen_or_i32(tmp, tmp, tmp2);
12011 if (!s->condexec_mask)
12012 gen_logic_CC(tmp);
12013 break;
12014 case 0xd: /* mul */
12015 tcg_gen_mul_i32(tmp, tmp, tmp2);
12016 if (!s->condexec_mask)
12017 gen_logic_CC(tmp);
12018 break;
12019 case 0xe: /* bic */
12020 tcg_gen_andc_i32(tmp, tmp, tmp2);
12021 if (!s->condexec_mask)
12022 gen_logic_CC(tmp);
12023 break;
12024 case 0xf: /* mvn */
12025 tcg_gen_not_i32(tmp2, tmp2);
12026 if (!s->condexec_mask)
12027 gen_logic_CC(tmp2);
12028 val = 1;
12029 rm = rd;
12030 break;
12032 if (rd != 16) {
12033 if (val) {
12034 store_reg(s, rm, tmp2);
12035 if (op != 0xf)
12036 tcg_temp_free_i32(tmp);
12037 } else {
12038 store_reg(s, rd, tmp);
12039 tcg_temp_free_i32(tmp2);
12041 } else {
12042 tcg_temp_free_i32(tmp);
12043 tcg_temp_free_i32(tmp2);
12045 break;
12047 case 5:
12048 /* load/store register offset. */
12049 rd = insn & 7;
12050 rn = (insn >> 3) & 7;
12051 rm = (insn >> 6) & 7;
12052 op = (insn >> 9) & 7;
12053 addr = load_reg(s, rn);
12054 tmp = load_reg(s, rm);
12055 tcg_gen_add_i32(addr, addr, tmp);
12056 tcg_temp_free_i32(tmp);
12058 if (op < 3) { /* store */
12059 tmp = load_reg(s, rd);
12060 } else {
12061 tmp = tcg_temp_new_i32();
12064 switch (op) {
12065 case 0: /* str */
12066 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12067 break;
12068 case 1: /* strh */
12069 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12070 break;
12071 case 2: /* strb */
12072 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12073 break;
12074 case 3: /* ldrsb */
12075 gen_aa32_ld8s_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12076 break;
12077 case 4: /* ldr */
12078 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12079 break;
12080 case 5: /* ldrh */
12081 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12082 break;
12083 case 6: /* ldrb */
12084 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12085 break;
12086 case 7: /* ldrsh */
12087 gen_aa32_ld16s_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12088 break;
12090 if (op >= 3) { /* load */
12091 store_reg(s, rd, tmp);
12092 } else {
12093 tcg_temp_free_i32(tmp);
12095 tcg_temp_free_i32(addr);
12096 break;
12098 case 6:
12099 /* load/store word immediate offset */
12100 rd = insn & 7;
12101 rn = (insn >> 3) & 7;
12102 addr = load_reg(s, rn);
12103 val = (insn >> 4) & 0x7c;
12104 tcg_gen_addi_i32(addr, addr, val);
12106 if (insn & (1 << 11)) {
12107 /* load */
12108 tmp = tcg_temp_new_i32();
12109 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
12110 store_reg(s, rd, tmp);
12111 } else {
12112 /* store */
12113 tmp = load_reg(s, rd);
12114 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
12115 tcg_temp_free_i32(tmp);
12117 tcg_temp_free_i32(addr);
12118 break;
12120 case 7:
12121 /* load/store byte immediate offset */
12122 rd = insn & 7;
12123 rn = (insn >> 3) & 7;
12124 addr = load_reg(s, rn);
12125 val = (insn >> 6) & 0x1f;
12126 tcg_gen_addi_i32(addr, addr, val);
12128 if (insn & (1 << 11)) {
12129 /* load */
12130 tmp = tcg_temp_new_i32();
12131 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12132 store_reg(s, rd, tmp);
12133 } else {
12134 /* store */
12135 tmp = load_reg(s, rd);
12136 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12137 tcg_temp_free_i32(tmp);
12139 tcg_temp_free_i32(addr);
12140 break;
12142 case 8:
12143 /* load/store halfword immediate offset */
12144 rd = insn & 7;
12145 rn = (insn >> 3) & 7;
12146 addr = load_reg(s, rn);
12147 val = (insn >> 5) & 0x3e;
12148 tcg_gen_addi_i32(addr, addr, val);
12150 if (insn & (1 << 11)) {
12151 /* load */
12152 tmp = tcg_temp_new_i32();
12153 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12154 store_reg(s, rd, tmp);
12155 } else {
12156 /* store */
12157 tmp = load_reg(s, rd);
12158 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12159 tcg_temp_free_i32(tmp);
12161 tcg_temp_free_i32(addr);
12162 break;
12164 case 9:
12165 /* load/store from stack */
12166 rd = (insn >> 8) & 7;
12167 addr = load_reg(s, 13);
12168 val = (insn & 0xff) * 4;
12169 tcg_gen_addi_i32(addr, addr, val);
12171 if (insn & (1 << 11)) {
12172 /* load */
12173 tmp = tcg_temp_new_i32();
12174 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12175 store_reg(s, rd, tmp);
12176 } else {
12177 /* store */
12178 tmp = load_reg(s, rd);
12179 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12180 tcg_temp_free_i32(tmp);
12182 tcg_temp_free_i32(addr);
12183 break;
12185 case 10:
12187 * 0b1010_xxxx_xxxx_xxxx
12188 * - Add PC/SP (immediate)
12190 rd = (insn >> 8) & 7;
12191 if (insn & (1 << 11)) {
12192 /* SP */
12193 tmp = load_reg(s, 13);
12194 } else {
12195 /* PC. bit 1 is ignored. */
12196 tmp = tcg_temp_new_i32();
12197 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
12199 val = (insn & 0xff) * 4;
12200 tcg_gen_addi_i32(tmp, tmp, val);
12201 store_reg(s, rd, tmp);
12202 break;
12204 case 11:
12205 /* misc */
12206 op = (insn >> 8) & 0xf;
12207 switch (op) {
12208 case 0:
12210 * 0b1011_0000_xxxx_xxxx
12211 * - ADD (SP plus immediate)
12212 * - SUB (SP minus immediate)
12214 tmp = load_reg(s, 13);
12215 val = (insn & 0x7f) * 4;
12216 if (insn & (1 << 7))
12217 val = -(int32_t)val;
12218 tcg_gen_addi_i32(tmp, tmp, val);
12219 store_sp_checked(s, tmp);
12220 break;
12222 case 2: /* sign/zero extend. */
12223 ARCH(6);
12224 rd = insn & 7;
12225 rm = (insn >> 3) & 7;
12226 tmp = load_reg(s, rm);
12227 switch ((insn >> 6) & 3) {
12228 case 0: gen_sxth(tmp); break;
12229 case 1: gen_sxtb(tmp); break;
12230 case 2: gen_uxth(tmp); break;
12231 case 3: gen_uxtb(tmp); break;
12233 store_reg(s, rd, tmp);
12234 break;
12235 case 4: case 5: case 0xc: case 0xd:
12237 * 0b1011_x10x_xxxx_xxxx
12238 * - push/pop
12240 addr = load_reg(s, 13);
12241 if (insn & (1 << 8))
12242 offset = 4;
12243 else
12244 offset = 0;
12245 for (i = 0; i < 8; i++) {
12246 if (insn & (1 << i))
12247 offset += 4;
12249 if ((insn & (1 << 11)) == 0) {
12250 tcg_gen_addi_i32(addr, addr, -offset);
12253 if (s->v8m_stackcheck) {
12255 * Here 'addr' is the lower of "old SP" and "new SP";
12256 * if this is a pop that starts below the limit and ends
12257 * above it, it is UNKNOWN whether the limit check triggers;
12258 * we choose to trigger.
12260 gen_helper_v8m_stackcheck(cpu_env, addr);
12263 for (i = 0; i < 8; i++) {
12264 if (insn & (1 << i)) {
12265 if (insn & (1 << 11)) {
12266 /* pop */
12267 tmp = tcg_temp_new_i32();
12268 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
12269 store_reg(s, i, tmp);
12270 } else {
12271 /* push */
12272 tmp = load_reg(s, i);
12273 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
12274 tcg_temp_free_i32(tmp);
12276 /* advance to the next address. */
12277 tcg_gen_addi_i32(addr, addr, 4);
12280 tmp = NULL;
12281 if (insn & (1 << 8)) {
12282 if (insn & (1 << 11)) {
12283 /* pop pc */
12284 tmp = tcg_temp_new_i32();
12285 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
12286 /* don't set the pc until the rest of the instruction
12287 has completed */
12288 } else {
12289 /* push lr */
12290 tmp = load_reg(s, 14);
12291 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
12292 tcg_temp_free_i32(tmp);
12294 tcg_gen_addi_i32(addr, addr, 4);
12296 if ((insn & (1 << 11)) == 0) {
12297 tcg_gen_addi_i32(addr, addr, -offset);
12299 /* write back the new stack pointer */
12300 store_reg(s, 13, addr);
12301 /* set the new PC value */
12302 if ((insn & 0x0900) == 0x0900) {
12303 store_reg_from_load(s, 15, tmp);
12305 break;
12307 case 1: case 3: case 9: case 11: /* czb */
12308 rm = insn & 7;
12309 tmp = load_reg(s, rm);
12310 arm_gen_condlabel(s);
12311 if (insn & (1 << 11))
12312 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
12313 else
12314 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
12315 tcg_temp_free_i32(tmp);
12316 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
12317 val = (uint32_t)s->pc + 2;
12318 val += offset;
12319 gen_jmp(s, val);
12320 break;
12322 case 15: /* IT, nop-hint. */
12323 if ((insn & 0xf) == 0) {
12324 gen_nop_hint(s, (insn >> 4) & 0xf);
12325 break;
12327 /* If Then. */
12328 s->condexec_cond = (insn >> 4) & 0xe;
12329 s->condexec_mask = insn & 0x1f;
12330 /* No actual code generated for this insn, just setup state. */
12331 break;
12333 case 0xe: /* bkpt */
12335 int imm8 = extract32(insn, 0, 8);
12336 ARCH(5);
12337 gen_exception_bkpt_insn(s, 2, syn_aa32_bkpt(imm8, true));
12338 break;
12341 case 0xa: /* rev, and hlt */
12343 int op1 = extract32(insn, 6, 2);
12345 if (op1 == 2) {
12346 /* HLT */
12347 int imm6 = extract32(insn, 0, 6);
12349 gen_hlt(s, imm6);
12350 break;
12353 /* Otherwise this is rev */
12354 ARCH(6);
12355 rn = (insn >> 3) & 0x7;
12356 rd = insn & 0x7;
12357 tmp = load_reg(s, rn);
12358 switch (op1) {
12359 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
12360 case 1: gen_rev16(tmp); break;
12361 case 3: gen_revsh(tmp); break;
12362 default:
12363 g_assert_not_reached();
12365 store_reg(s, rd, tmp);
12366 break;
12369 case 6:
12370 switch ((insn >> 5) & 7) {
12371 case 2:
12372 /* setend */
12373 ARCH(6);
12374 if (((insn >> 3) & 1) != !!(s->be_data == MO_BE)) {
12375 gen_helper_setend(cpu_env);
12376 s->base.is_jmp = DISAS_UPDATE;
12378 break;
12379 case 3:
12380 /* cps */
12381 ARCH(6);
12382 if (IS_USER(s)) {
12383 break;
12385 if (arm_dc_feature(s, ARM_FEATURE_M)) {
12386 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
12387 /* FAULTMASK */
12388 if (insn & 1) {
12389 addr = tcg_const_i32(19);
12390 gen_helper_v7m_msr(cpu_env, addr, tmp);
12391 tcg_temp_free_i32(addr);
12393 /* PRIMASK */
12394 if (insn & 2) {
12395 addr = tcg_const_i32(16);
12396 gen_helper_v7m_msr(cpu_env, addr, tmp);
12397 tcg_temp_free_i32(addr);
12399 tcg_temp_free_i32(tmp);
12400 gen_lookup_tb(s);
12401 } else {
12402 if (insn & (1 << 4)) {
12403 shift = CPSR_A | CPSR_I | CPSR_F;
12404 } else {
12405 shift = 0;
12407 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
12409 break;
12410 default:
12411 goto undef;
12413 break;
12415 default:
12416 goto undef;
12418 break;
12420 case 12:
12422 /* load/store multiple */
12423 TCGv_i32 loaded_var = NULL;
12424 rn = (insn >> 8) & 0x7;
12425 addr = load_reg(s, rn);
12426 for (i = 0; i < 8; i++) {
12427 if (insn & (1 << i)) {
12428 if (insn & (1 << 11)) {
12429 /* load */
12430 tmp = tcg_temp_new_i32();
12431 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
12432 if (i == rn) {
12433 loaded_var = tmp;
12434 } else {
12435 store_reg(s, i, tmp);
12437 } else {
12438 /* store */
12439 tmp = load_reg(s, i);
12440 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
12441 tcg_temp_free_i32(tmp);
12443 /* advance to the next address */
12444 tcg_gen_addi_i32(addr, addr, 4);
12447 if ((insn & (1 << rn)) == 0) {
12448 /* base reg not in list: base register writeback */
12449 store_reg(s, rn, addr);
12450 } else {
12451 /* base reg in list: if load, complete it now */
12452 if (insn & (1 << 11)) {
12453 store_reg(s, rn, loaded_var);
12455 tcg_temp_free_i32(addr);
12457 break;
12459 case 13:
12460 /* conditional branch or swi */
12461 cond = (insn >> 8) & 0xf;
12462 if (cond == 0xe)
12463 goto undef;
12465 if (cond == 0xf) {
12466 /* swi */
12467 gen_set_pc_im(s, s->pc);
12468 s->svc_imm = extract32(insn, 0, 8);
12469 s->base.is_jmp = DISAS_SWI;
12470 break;
12472 /* generate a conditional jump to next instruction */
12473 arm_skip_unless(s, cond);
12475 /* jump to the offset */
12476 val = (uint32_t)s->pc + 2;
12477 offset = ((int32_t)insn << 24) >> 24;
12478 val += offset << 1;
12479 gen_jmp(s, val);
12480 break;
12482 case 14:
12483 if (insn & (1 << 11)) {
12484 /* thumb_insn_is_16bit() ensures we can't get here for
12485 * a Thumb2 CPU, so this must be a thumb1 split BL/BLX:
12486 * 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF)
12488 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
12489 ARCH(5);
12490 offset = ((insn & 0x7ff) << 1);
12491 tmp = load_reg(s, 14);
12492 tcg_gen_addi_i32(tmp, tmp, offset);
12493 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
12495 tmp2 = tcg_temp_new_i32();
12496 tcg_gen_movi_i32(tmp2, s->pc | 1);
12497 store_reg(s, 14, tmp2);
12498 gen_bx(s, tmp);
12499 break;
12501 /* unconditional branch */
12502 val = (uint32_t)s->pc;
12503 offset = ((int32_t)insn << 21) >> 21;
12504 val += (offset << 1) + 2;
12505 gen_jmp(s, val);
12506 break;
12508 case 15:
12509 /* thumb_insn_is_16bit() ensures we can't get here for
12510 * a Thumb2 CPU, so this must be a thumb1 split BL/BLX.
12512 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
12514 if (insn & (1 << 11)) {
12515 /* 0b1111_1xxx_xxxx_xxxx : BL suffix */
12516 offset = ((insn & 0x7ff) << 1) | 1;
12517 tmp = load_reg(s, 14);
12518 tcg_gen_addi_i32(tmp, tmp, offset);
12520 tmp2 = tcg_temp_new_i32();
12521 tcg_gen_movi_i32(tmp2, s->pc | 1);
12522 store_reg(s, 14, tmp2);
12523 gen_bx(s, tmp);
12524 } else {
12525 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix */
12526 uint32_t uoffset = ((int32_t)insn << 21) >> 9;
12528 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + uoffset);
12530 break;
12532 return;
12533 illegal_op:
12534 undef:
12535 gen_exception_insn(s, 2, EXCP_UDEF, syn_uncategorized(),
12536 default_exception_el(s));
12539 static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
12541 /* Return true if the insn at dc->pc might cross a page boundary.
12542 * (False positives are OK, false negatives are not.)
12543 * We know this is a Thumb insn, and our caller ensures we are
12544 * only called if dc->pc is less than 4 bytes from the page
12545 * boundary, so we cross the page if the first 16 bits indicate
12546 * that this is a 32 bit insn.
12548 uint16_t insn = arm_lduw_code(env, s->pc, s->sctlr_b);
12550 return !thumb_insn_is_16bit(s, insn);
12553 static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
12555 DisasContext *dc = container_of(dcbase, DisasContext, base);
12556 CPUARMState *env = cs->env_ptr;
12557 ARMCPU *cpu = env_archcpu(env);
12558 uint32_t tb_flags = dc->base.tb->flags;
12559 uint32_t condexec, core_mmu_idx;
12561 dc->isar = &cpu->isar;
12562 dc->pc = dc->base.pc_first;
12563 dc->condjmp = 0;
12565 dc->aarch64 = 0;
12566 /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
12567 * there is no secure EL1, so we route exceptions to EL3.
12569 dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
12570 !arm_el_is_aa64(env, 3);
12571 dc->thumb = FIELD_EX32(tb_flags, TBFLAG_A32, THUMB);
12572 dc->sctlr_b = FIELD_EX32(tb_flags, TBFLAG_A32, SCTLR_B);
12573 dc->be_data = FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
12574 condexec = FIELD_EX32(tb_flags, TBFLAG_A32, CONDEXEC);
12575 dc->condexec_mask = (condexec & 0xf) << 1;
12576 dc->condexec_cond = condexec >> 4;
12577 core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX);
12578 dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
12579 dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
12580 #if !defined(CONFIG_USER_ONLY)
12581 dc->user = (dc->current_el == 0);
12582 #endif
12583 dc->ns = FIELD_EX32(tb_flags, TBFLAG_A32, NS);
12584 dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL);
12585 dc->vfp_enabled = FIELD_EX32(tb_flags, TBFLAG_A32, VFPEN);
12586 dc->vec_len = FIELD_EX32(tb_flags, TBFLAG_A32, VECLEN);
12587 if (arm_feature(env, ARM_FEATURE_XSCALE)) {
12588 dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
12589 dc->vec_stride = 0;
12590 } else {
12591 dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
12592 dc->c15_cpar = 0;
12594 dc->v7m_handler_mode = FIELD_EX32(tb_flags, TBFLAG_A32, HANDLER);
12595 dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
12596 regime_is_secure(env, dc->mmu_idx);
12597 dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_A32, STACKCHECK);
12598 dc->v8m_fpccr_s_wrong = FIELD_EX32(tb_flags, TBFLAG_A32, FPCCR_S_WRONG);
12599 dc->v7m_new_fp_ctxt_needed =
12600 FIELD_EX32(tb_flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED);
12601 dc->v7m_lspact = FIELD_EX32(tb_flags, TBFLAG_A32, LSPACT);
12602 dc->cp_regs = cpu->cp_regs;
12603 dc->features = env->features;
12605 /* Single step state. The code-generation logic here is:
12606 * SS_ACTIVE == 0:
12607 * generate code with no special handling for single-stepping (except
12608 * that anything that can make us go to SS_ACTIVE == 1 must end the TB;
12609 * this happens anyway because those changes are all system register or
12610 * PSTATE writes).
12611 * SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
12612 * emit code for one insn
12613 * emit code to clear PSTATE.SS
12614 * emit code to generate software step exception for completed step
12615 * end TB (as usual for having generated an exception)
12616 * SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
12617 * emit code to generate a software step exception
12618 * end the TB
12620 dc->ss_active = FIELD_EX32(tb_flags, TBFLAG_ANY, SS_ACTIVE);
12621 dc->pstate_ss = FIELD_EX32(tb_flags, TBFLAG_ANY, PSTATE_SS);
12622 dc->is_ldex = false;
12623 dc->ss_same_el = false; /* Can't be true since EL_d must be AArch64 */
12625 dc->page_start = dc->base.pc_first & TARGET_PAGE_MASK;
12627 /* If architectural single step active, limit to 1. */
12628 if (is_singlestepping(dc)) {
12629 dc->base.max_insns = 1;
12632 /* ARM is a fixed-length ISA. Bound the number of insns to execute
12633 to those left on the page. */
12634 if (!dc->thumb) {
12635 int bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
12636 dc->base.max_insns = MIN(dc->base.max_insns, bound);
12639 cpu_F0s = tcg_temp_new_i32();
12640 cpu_F1s = tcg_temp_new_i32();
12641 cpu_F0d = tcg_temp_new_i64();
12642 cpu_F1d = tcg_temp_new_i64();
12643 cpu_V0 = cpu_F0d;
12644 cpu_V1 = cpu_F1d;
12645 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
12646 cpu_M0 = tcg_temp_new_i64();
12649 static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
12651 DisasContext *dc = container_of(dcbase, DisasContext, base);
12653 /* A note on handling of the condexec (IT) bits:
12655 * We want to avoid the overhead of having to write the updated condexec
12656 * bits back to the CPUARMState for every instruction in an IT block. So:
12657 * (1) if the condexec bits are not already zero then we write
12658 * zero back into the CPUARMState now. This avoids complications trying
12659 * to do it at the end of the block. (For example if we don't do this
12660 * it's hard to identify whether we can safely skip writing condexec
12661 * at the end of the TB, which we definitely want to do for the case
12662 * where a TB doesn't do anything with the IT state at all.)
12663 * (2) if we are going to leave the TB then we call gen_set_condexec()
12664 * which will write the correct value into CPUARMState if zero is wrong.
12665 * This is done both for leaving the TB at the end, and for leaving
12666 * it because of an exception we know will happen, which is done in
12667 * gen_exception_insn(). The latter is necessary because we need to
12668 * leave the TB with the PC/IT state just prior to execution of the
12669 * instruction which caused the exception.
12670 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
12671 * then the CPUARMState will be wrong and we need to reset it.
12672 * This is handled in the same way as restoration of the
12673 * PC in these situations; we save the value of the condexec bits
12674 * for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
12675 * then uses this to restore them after an exception.
12677 * Note that there are no instructions which can read the condexec
12678 * bits, and none which can write non-static values to them, so
12679 * we don't need to care about whether CPUARMState is correct in the
12680 * middle of a TB.
12683 /* Reset the conditional execution bits immediately. This avoids
12684 complications trying to do it at the end of the block. */
12685 if (dc->condexec_mask || dc->condexec_cond) {
12686 TCGv_i32 tmp = tcg_temp_new_i32();
12687 tcg_gen_movi_i32(tmp, 0);
12688 store_cpu_field(tmp, condexec_bits);
12692 static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
12694 DisasContext *dc = container_of(dcbase, DisasContext, base);
12696 tcg_gen_insn_start(dc->pc,
12697 (dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
12699 dc->insn_start = tcg_last_op();
12702 static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
12703 const CPUBreakpoint *bp)
12705 DisasContext *dc = container_of(dcbase, DisasContext, base);
12707 if (bp->flags & BP_CPU) {
12708 gen_set_condexec(dc);
12709 gen_set_pc_im(dc, dc->pc);
12710 gen_helper_check_breakpoints(cpu_env);
12711 /* End the TB early; it's likely not going to be executed */
12712 dc->base.is_jmp = DISAS_TOO_MANY;
12713 } else {
12714 gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
12715 /* The address covered by the breakpoint must be
12716 included in [tb->pc, tb->pc + tb->size) in order
12717 to for it to be properly cleared -- thus we
12718 increment the PC here so that the logic setting
12719 tb->size below does the right thing. */
12720 /* TODO: Advance PC by correct instruction length to
12721 * avoid disassembler error messages */
12722 dc->pc += 2;
12723 dc->base.is_jmp = DISAS_NORETURN;
12726 return true;
12729 static bool arm_pre_translate_insn(DisasContext *dc)
12731 #ifdef CONFIG_USER_ONLY
12732 /* Intercept jump to the magic kernel page. */
12733 if (dc->pc >= 0xffff0000) {
12734 /* We always get here via a jump, so know we are not in a
12735 conditional execution block. */
12736 gen_exception_internal(EXCP_KERNEL_TRAP);
12737 dc->base.is_jmp = DISAS_NORETURN;
12738 return true;
12740 #endif
12742 if (dc->ss_active && !dc->pstate_ss) {
12743 /* Singlestep state is Active-pending.
12744 * If we're in this state at the start of a TB then either
12745 * a) we just took an exception to an EL which is being debugged
12746 * and this is the first insn in the exception handler
12747 * b) debug exceptions were masked and we just unmasked them
12748 * without changing EL (eg by clearing PSTATE.D)
12749 * In either case we're going to take a swstep exception in the
12750 * "did not step an insn" case, and so the syndrome ISV and EX
12751 * bits should be zero.
12753 assert(dc->base.num_insns == 1);
12754 gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
12755 default_exception_el(dc));
12756 dc->base.is_jmp = DISAS_NORETURN;
12757 return true;
12760 return false;
12763 static void arm_post_translate_insn(DisasContext *dc)
12765 if (dc->condjmp && !dc->base.is_jmp) {
12766 gen_set_label(dc->condlabel);
12767 dc->condjmp = 0;
12769 dc->base.pc_next = dc->pc;
12770 translator_loop_temp_check(&dc->base);
12773 static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
12775 DisasContext *dc = container_of(dcbase, DisasContext, base);
12776 CPUARMState *env = cpu->env_ptr;
12777 unsigned int insn;
12779 if (arm_pre_translate_insn(dc)) {
12780 return;
12783 insn = arm_ldl_code(env, dc->pc, dc->sctlr_b);
12784 dc->insn = insn;
12785 dc->pc += 4;
12786 disas_arm_insn(dc, insn);
12788 arm_post_translate_insn(dc);
12790 /* ARM is a fixed-length ISA. We performed the cross-page check
12791 in init_disas_context by adjusting max_insns. */
12794 static bool thumb_insn_is_unconditional(DisasContext *s, uint32_t insn)
12796 /* Return true if this Thumb insn is always unconditional,
12797 * even inside an IT block. This is true of only a very few
12798 * instructions: BKPT, HLT, and SG.
12800 * A larger class of instructions are UNPREDICTABLE if used
12801 * inside an IT block; we do not need to detect those here, because
12802 * what we do by default (perform the cc check and update the IT
12803 * bits state machine) is a permitted CONSTRAINED UNPREDICTABLE
12804 * choice for those situations.
12806 * insn is either a 16-bit or a 32-bit instruction; the two are
12807 * distinguishable because for the 16-bit case the top 16 bits
12808 * are zeroes, and that isn't a valid 32-bit encoding.
12810 if ((insn & 0xffffff00) == 0xbe00) {
12811 /* BKPT */
12812 return true;
12815 if ((insn & 0xffffffc0) == 0xba80 && arm_dc_feature(s, ARM_FEATURE_V8) &&
12816 !arm_dc_feature(s, ARM_FEATURE_M)) {
12817 /* HLT: v8A only. This is unconditional even when it is going to
12818 * UNDEF; see the v8A ARM ARM DDI0487B.a H3.3.
12819 * For v7 cores this was a plain old undefined encoding and so
12820 * honours its cc check. (We might be using the encoding as
12821 * a semihosting trap, but we don't change the cc check behaviour
12822 * on that account, because a debugger connected to a real v7A
12823 * core and emulating semihosting traps by catching the UNDEF
12824 * exception would also only see cases where the cc check passed.
12825 * No guest code should be trying to do a HLT semihosting trap
12826 * in an IT block anyway.
12828 return true;
12831 if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_V8) &&
12832 arm_dc_feature(s, ARM_FEATURE_M)) {
12833 /* SG: v8M only */
12834 return true;
12837 return false;
12840 static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
12842 DisasContext *dc = container_of(dcbase, DisasContext, base);
12843 CPUARMState *env = cpu->env_ptr;
12844 uint32_t insn;
12845 bool is_16bit;
12847 if (arm_pre_translate_insn(dc)) {
12848 return;
12851 insn = arm_lduw_code(env, dc->pc, dc->sctlr_b);
12852 is_16bit = thumb_insn_is_16bit(dc, insn);
12853 dc->pc += 2;
12854 if (!is_16bit) {
12855 uint32_t insn2 = arm_lduw_code(env, dc->pc, dc->sctlr_b);
12857 insn = insn << 16 | insn2;
12858 dc->pc += 2;
12860 dc->insn = insn;
12862 if (dc->condexec_mask && !thumb_insn_is_unconditional(dc, insn)) {
12863 uint32_t cond = dc->condexec_cond;
12865 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
12866 arm_skip_unless(dc, cond);
12870 if (is_16bit) {
12871 disas_thumb_insn(dc, insn);
12872 } else {
12873 disas_thumb2_insn(dc, insn);
12876 /* Advance the Thumb condexec condition. */
12877 if (dc->condexec_mask) {
12878 dc->condexec_cond = ((dc->condexec_cond & 0xe) |
12879 ((dc->condexec_mask >> 4) & 1));
12880 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
12881 if (dc->condexec_mask == 0) {
12882 dc->condexec_cond = 0;
12886 arm_post_translate_insn(dc);
12888 /* Thumb is a variable-length ISA. Stop translation when the next insn
12889 * will touch a new page. This ensures that prefetch aborts occur at
12890 * the right place.
12892 * We want to stop the TB if the next insn starts in a new page,
12893 * or if it spans between this page and the next. This means that
12894 * if we're looking at the last halfword in the page we need to
12895 * see if it's a 16-bit Thumb insn (which will fit in this TB)
12896 * or a 32-bit Thumb insn (which won't).
12897 * This is to avoid generating a silly TB with a single 16-bit insn
12898 * in it at the end of this page (which would execute correctly
12899 * but isn't very efficient).
12901 if (dc->base.is_jmp == DISAS_NEXT
12902 && (dc->pc - dc->page_start >= TARGET_PAGE_SIZE
12903 || (dc->pc - dc->page_start >= TARGET_PAGE_SIZE - 3
12904 && insn_crosses_page(env, dc)))) {
12905 dc->base.is_jmp = DISAS_TOO_MANY;
12909 static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
12911 DisasContext *dc = container_of(dcbase, DisasContext, base);
12913 if (tb_cflags(dc->base.tb) & CF_LAST_IO && dc->condjmp) {
12914 /* FIXME: This can theoretically happen with self-modifying code. */
12915 cpu_abort(cpu, "IO on conditional branch instruction");
12918 /* At this stage dc->condjmp will only be set when the skipped
12919 instruction was a conditional branch or trap, and the PC has
12920 already been written. */
12921 gen_set_condexec(dc);
12922 if (dc->base.is_jmp == DISAS_BX_EXCRET) {
12923 /* Exception return branches need some special case code at the
12924 * end of the TB, which is complex enough that it has to
12925 * handle the single-step vs not and the condition-failed
12926 * insn codepath itself.
12928 gen_bx_excret_final_code(dc);
12929 } else if (unlikely(is_singlestepping(dc))) {
12930 /* Unconditional and "condition passed" instruction codepath. */
12931 switch (dc->base.is_jmp) {
12932 case DISAS_SWI:
12933 gen_ss_advance(dc);
12934 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
12935 default_exception_el(dc));
12936 break;
12937 case DISAS_HVC:
12938 gen_ss_advance(dc);
12939 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
12940 break;
12941 case DISAS_SMC:
12942 gen_ss_advance(dc);
12943 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
12944 break;
12945 case DISAS_NEXT:
12946 case DISAS_TOO_MANY:
12947 case DISAS_UPDATE:
12948 gen_set_pc_im(dc, dc->pc);
12949 /* fall through */
12950 default:
12951 /* FIXME: Single stepping a WFI insn will not halt the CPU. */
12952 gen_singlestep_exception(dc);
12953 break;
12954 case DISAS_NORETURN:
12955 break;
12957 } else {
12958 /* While branches must always occur at the end of an IT block,
12959 there are a few other things that can cause us to terminate
12960 the TB in the middle of an IT block:
12961 - Exception generating instructions (bkpt, swi, undefined).
12962 - Page boundaries.
12963 - Hardware watchpoints.
12964 Hardware breakpoints have already been handled and skip this code.
12966 switch(dc->base.is_jmp) {
12967 case DISAS_NEXT:
12968 case DISAS_TOO_MANY:
12969 gen_goto_tb(dc, 1, dc->pc);
12970 break;
12971 case DISAS_JUMP:
12972 gen_goto_ptr();
12973 break;
12974 case DISAS_UPDATE:
12975 gen_set_pc_im(dc, dc->pc);
12976 /* fall through */
12977 default:
12978 /* indicate that the hash table must be used to find the next TB */
12979 tcg_gen_exit_tb(NULL, 0);
12980 break;
12981 case DISAS_NORETURN:
12982 /* nothing more to generate */
12983 break;
12984 case DISAS_WFI:
12986 TCGv_i32 tmp = tcg_const_i32((dc->thumb &&
12987 !(dc->insn & (1U << 31))) ? 2 : 4);
12989 gen_helper_wfi(cpu_env, tmp);
12990 tcg_temp_free_i32(tmp);
12991 /* The helper doesn't necessarily throw an exception, but we
12992 * must go back to the main loop to check for interrupts anyway.
12994 tcg_gen_exit_tb(NULL, 0);
12995 break;
12997 case DISAS_WFE:
12998 gen_helper_wfe(cpu_env);
12999 break;
13000 case DISAS_YIELD:
13001 gen_helper_yield(cpu_env);
13002 break;
13003 case DISAS_SWI:
13004 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
13005 default_exception_el(dc));
13006 break;
13007 case DISAS_HVC:
13008 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
13009 break;
13010 case DISAS_SMC:
13011 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
13012 break;
13016 if (dc->condjmp) {
13017 /* "Condition failed" instruction codepath for the branch/trap insn */
13018 gen_set_label(dc->condlabel);
13019 gen_set_condexec(dc);
13020 if (unlikely(is_singlestepping(dc))) {
13021 gen_set_pc_im(dc, dc->pc);
13022 gen_singlestep_exception(dc);
13023 } else {
13024 gen_goto_tb(dc, 1, dc->pc);
13028 /* Functions above can change dc->pc, so re-align db->pc_next */
13029 dc->base.pc_next = dc->pc;
13032 static void arm_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
13034 DisasContext *dc = container_of(dcbase, DisasContext, base);
13036 qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
13037 log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
13040 static const TranslatorOps arm_translator_ops = {
13041 .init_disas_context = arm_tr_init_disas_context,
13042 .tb_start = arm_tr_tb_start,
13043 .insn_start = arm_tr_insn_start,
13044 .breakpoint_check = arm_tr_breakpoint_check,
13045 .translate_insn = arm_tr_translate_insn,
13046 .tb_stop = arm_tr_tb_stop,
13047 .disas_log = arm_tr_disas_log,
13050 static const TranslatorOps thumb_translator_ops = {
13051 .init_disas_context = arm_tr_init_disas_context,
13052 .tb_start = arm_tr_tb_start,
13053 .insn_start = arm_tr_insn_start,
13054 .breakpoint_check = arm_tr_breakpoint_check,
13055 .translate_insn = thumb_tr_translate_insn,
13056 .tb_stop = arm_tr_tb_stop,
13057 .disas_log = arm_tr_disas_log,
13060 /* generate intermediate code for basic block 'tb'. */
13061 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
13063 DisasContext dc;
13064 const TranslatorOps *ops = &arm_translator_ops;
13066 if (FIELD_EX32(tb->flags, TBFLAG_A32, THUMB)) {
13067 ops = &thumb_translator_ops;
13069 #ifdef TARGET_AARCH64
13070 if (FIELD_EX32(tb->flags, TBFLAG_ANY, AARCH64_STATE)) {
13071 ops = &aarch64_translator_ops;
13073 #endif
13075 translator_loop(ops, &dc.base, cpu, tb, max_insns);
13078 void arm_cpu_dump_state(CPUState *cs, FILE *f, int flags)
13080 ARMCPU *cpu = ARM_CPU(cs);
13081 CPUARMState *env = &cpu->env;
13082 int i;
13084 if (is_a64(env)) {
13085 aarch64_cpu_dump_state(cs, f, flags);
13086 return;
13089 for(i=0;i<16;i++) {
13090 qemu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
13091 if ((i % 4) == 3)
13092 qemu_fprintf(f, "\n");
13093 else
13094 qemu_fprintf(f, " ");
13097 if (arm_feature(env, ARM_FEATURE_M)) {
13098 uint32_t xpsr = xpsr_read(env);
13099 const char *mode;
13100 const char *ns_status = "";
13102 if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
13103 ns_status = env->v7m.secure ? "S " : "NS ";
13106 if (xpsr & XPSR_EXCP) {
13107 mode = "handler";
13108 } else {
13109 if (env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_NPRIV_MASK) {
13110 mode = "unpriv-thread";
13111 } else {
13112 mode = "priv-thread";
13116 qemu_fprintf(f, "XPSR=%08x %c%c%c%c %c %s%s\n",
13117 xpsr,
13118 xpsr & XPSR_N ? 'N' : '-',
13119 xpsr & XPSR_Z ? 'Z' : '-',
13120 xpsr & XPSR_C ? 'C' : '-',
13121 xpsr & XPSR_V ? 'V' : '-',
13122 xpsr & XPSR_T ? 'T' : 'A',
13123 ns_status,
13124 mode);
13125 } else {
13126 uint32_t psr = cpsr_read(env);
13127 const char *ns_status = "";
13129 if (arm_feature(env, ARM_FEATURE_EL3) &&
13130 (psr & CPSR_M) != ARM_CPU_MODE_MON) {
13131 ns_status = env->cp15.scr_el3 & SCR_NS ? "NS " : "S ";
13134 qemu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%s%d\n",
13135 psr,
13136 psr & CPSR_N ? 'N' : '-',
13137 psr & CPSR_Z ? 'Z' : '-',
13138 psr & CPSR_C ? 'C' : '-',
13139 psr & CPSR_V ? 'V' : '-',
13140 psr & CPSR_T ? 'T' : 'A',
13141 ns_status,
13142 aarch32_mode_name(psr), (psr & 0x10) ? 32 : 26);
13145 if (flags & CPU_DUMP_FPU) {
13146 int numvfpregs = 0;
13147 if (arm_feature(env, ARM_FEATURE_VFP)) {
13148 numvfpregs += 16;
13150 if (arm_feature(env, ARM_FEATURE_VFP3)) {
13151 numvfpregs += 16;
13153 for (i = 0; i < numvfpregs; i++) {
13154 uint64_t v = *aa32_vfp_dreg(env, i);
13155 qemu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
13156 i * 2, (uint32_t)v,
13157 i * 2 + 1, (uint32_t)(v >> 32),
13158 i, v);
13160 qemu_fprintf(f, "FPSCR: %08x\n", vfp_get_fpscr(env));
13164 void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
13165 target_ulong *data)
13167 if (is_a64(env)) {
13168 env->pc = data[0];
13169 env->condexec_bits = 0;
13170 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
13171 } else {
13172 env->regs[15] = data[0];
13173 env->condexec_bits = data[1];
13174 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;