target/arm: Fix vector operation segfault
[qemu/ar7.git] / target / arm / translate.c
blob298c262825de796b3dfa3264bc8fc9cabf7326b0
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 "exec/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(add)
1390 VFP_OP2(sub)
1391 VFP_OP2(mul)
1392 VFP_OP2(div)
1394 #undef VFP_OP2
1396 static inline void gen_vfp_F1_mul(int dp)
1398 /* Like gen_vfp_mul() but put result in F1 */
1399 TCGv_ptr fpst = get_fpstatus_ptr(0);
1400 if (dp) {
1401 gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, fpst);
1402 } else {
1403 gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, fpst);
1405 tcg_temp_free_ptr(fpst);
1408 static inline void gen_vfp_F1_neg(int dp)
1410 /* Like gen_vfp_neg() but put result in F1 */
1411 if (dp) {
1412 gen_helper_vfp_negd(cpu_F1d, cpu_F0d);
1413 } else {
1414 gen_helper_vfp_negs(cpu_F1s, cpu_F0s);
1418 static inline void gen_vfp_abs(int dp)
1420 if (dp)
1421 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1422 else
1423 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1426 static inline void gen_vfp_neg(int dp)
1428 if (dp)
1429 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1430 else
1431 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1434 static inline void gen_vfp_sqrt(int dp)
1436 if (dp)
1437 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1438 else
1439 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1442 static inline void gen_vfp_cmp(int dp)
1444 if (dp)
1445 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1446 else
1447 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1450 static inline void gen_vfp_cmpe(int dp)
1452 if (dp)
1453 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1454 else
1455 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1458 static inline void gen_vfp_F1_ld0(int dp)
1460 if (dp)
1461 tcg_gen_movi_i64(cpu_F1d, 0);
1462 else
1463 tcg_gen_movi_i32(cpu_F1s, 0);
1466 #define VFP_GEN_ITOF(name) \
1467 static inline void gen_vfp_##name(int dp, int neon) \
1469 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1470 if (dp) { \
1471 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
1472 } else { \
1473 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1475 tcg_temp_free_ptr(statusptr); \
1478 VFP_GEN_ITOF(uito)
1479 VFP_GEN_ITOF(sito)
1480 #undef VFP_GEN_ITOF
1482 #define VFP_GEN_FTOI(name) \
1483 static inline void gen_vfp_##name(int dp, int neon) \
1485 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1486 if (dp) { \
1487 gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
1488 } else { \
1489 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1491 tcg_temp_free_ptr(statusptr); \
1494 VFP_GEN_FTOI(toui)
1495 VFP_GEN_FTOI(touiz)
1496 VFP_GEN_FTOI(tosi)
1497 VFP_GEN_FTOI(tosiz)
1498 #undef VFP_GEN_FTOI
1500 #define VFP_GEN_FIX(name, round) \
1501 static inline void gen_vfp_##name(int dp, int shift, int neon) \
1503 TCGv_i32 tmp_shift = tcg_const_i32(shift); \
1504 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1505 if (dp) { \
1506 gen_helper_vfp_##name##d##round(cpu_F0d, cpu_F0d, tmp_shift, \
1507 statusptr); \
1508 } else { \
1509 gen_helper_vfp_##name##s##round(cpu_F0s, cpu_F0s, tmp_shift, \
1510 statusptr); \
1512 tcg_temp_free_i32(tmp_shift); \
1513 tcg_temp_free_ptr(statusptr); \
1515 VFP_GEN_FIX(tosh, _round_to_zero)
1516 VFP_GEN_FIX(tosl, _round_to_zero)
1517 VFP_GEN_FIX(touh, _round_to_zero)
1518 VFP_GEN_FIX(toul, _round_to_zero)
1519 VFP_GEN_FIX(shto, )
1520 VFP_GEN_FIX(slto, )
1521 VFP_GEN_FIX(uhto, )
1522 VFP_GEN_FIX(ulto, )
1523 #undef VFP_GEN_FIX
1525 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr)
1527 if (dp) {
1528 gen_aa32_ld64(s, cpu_F0d, addr, get_mem_index(s));
1529 } else {
1530 gen_aa32_ld32u(s, cpu_F0s, addr, get_mem_index(s));
1534 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
1536 if (dp) {
1537 gen_aa32_st64(s, cpu_F0d, addr, get_mem_index(s));
1538 } else {
1539 gen_aa32_st32(s, cpu_F0s, addr, get_mem_index(s));
1543 static inline long vfp_reg_offset(bool dp, unsigned reg)
1545 if (dp) {
1546 return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]);
1547 } else {
1548 long ofs = offsetof(CPUARMState, vfp.zregs[reg >> 2].d[(reg >> 1) & 1]);
1549 if (reg & 1) {
1550 ofs += offsetof(CPU_DoubleU, l.upper);
1551 } else {
1552 ofs += offsetof(CPU_DoubleU, l.lower);
1554 return ofs;
1558 /* Return the offset of a 32-bit piece of a NEON register.
1559 zero is the least significant end of the register. */
1560 static inline long
1561 neon_reg_offset (int reg, int n)
1563 int sreg;
1564 sreg = reg * 2 + n;
1565 return vfp_reg_offset(0, sreg);
1568 /* Return the offset of a 2**SIZE piece of a NEON register, at index ELE,
1569 * where 0 is the least significant end of the register.
1571 static inline long
1572 neon_element_offset(int reg, int element, TCGMemOp size)
1574 int element_size = 1 << size;
1575 int ofs = element * element_size;
1576 #ifdef HOST_WORDS_BIGENDIAN
1577 /* Calculate the offset assuming fully little-endian,
1578 * then XOR to account for the order of the 8-byte units.
1580 if (element_size < 8) {
1581 ofs ^= 8 - element_size;
1583 #endif
1584 return neon_reg_offset(reg, 0) + ofs;
1587 static TCGv_i32 neon_load_reg(int reg, int pass)
1589 TCGv_i32 tmp = tcg_temp_new_i32();
1590 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1591 return tmp;
1594 static void neon_load_element(TCGv_i32 var, int reg, int ele, TCGMemOp mop)
1596 long offset = neon_element_offset(reg, ele, mop & MO_SIZE);
1598 switch (mop) {
1599 case MO_UB:
1600 tcg_gen_ld8u_i32(var, cpu_env, offset);
1601 break;
1602 case MO_UW:
1603 tcg_gen_ld16u_i32(var, cpu_env, offset);
1604 break;
1605 case MO_UL:
1606 tcg_gen_ld_i32(var, cpu_env, offset);
1607 break;
1608 default:
1609 g_assert_not_reached();
1613 static void neon_load_element64(TCGv_i64 var, int reg, int ele, TCGMemOp mop)
1615 long offset = neon_element_offset(reg, ele, mop & MO_SIZE);
1617 switch (mop) {
1618 case MO_UB:
1619 tcg_gen_ld8u_i64(var, cpu_env, offset);
1620 break;
1621 case MO_UW:
1622 tcg_gen_ld16u_i64(var, cpu_env, offset);
1623 break;
1624 case MO_UL:
1625 tcg_gen_ld32u_i64(var, cpu_env, offset);
1626 break;
1627 case MO_Q:
1628 tcg_gen_ld_i64(var, cpu_env, offset);
1629 break;
1630 default:
1631 g_assert_not_reached();
1635 static void neon_store_reg(int reg, int pass, TCGv_i32 var)
1637 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1638 tcg_temp_free_i32(var);
1641 static void neon_store_element(int reg, int ele, TCGMemOp size, TCGv_i32 var)
1643 long offset = neon_element_offset(reg, ele, size);
1645 switch (size) {
1646 case MO_8:
1647 tcg_gen_st8_i32(var, cpu_env, offset);
1648 break;
1649 case MO_16:
1650 tcg_gen_st16_i32(var, cpu_env, offset);
1651 break;
1652 case MO_32:
1653 tcg_gen_st_i32(var, cpu_env, offset);
1654 break;
1655 default:
1656 g_assert_not_reached();
1660 static void neon_store_element64(int reg, int ele, TCGMemOp size, TCGv_i64 var)
1662 long offset = neon_element_offset(reg, ele, size);
1664 switch (size) {
1665 case MO_8:
1666 tcg_gen_st8_i64(var, cpu_env, offset);
1667 break;
1668 case MO_16:
1669 tcg_gen_st16_i64(var, cpu_env, offset);
1670 break;
1671 case MO_32:
1672 tcg_gen_st32_i64(var, cpu_env, offset);
1673 break;
1674 case MO_64:
1675 tcg_gen_st_i64(var, cpu_env, offset);
1676 break;
1677 default:
1678 g_assert_not_reached();
1682 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1684 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1687 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1689 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1692 static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
1694 TCGv_ptr ret = tcg_temp_new_ptr();
1695 tcg_gen_addi_ptr(ret, cpu_env, vfp_reg_offset(dp, reg));
1696 return ret;
1699 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1700 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1701 #define tcg_gen_st_f32 tcg_gen_st_i32
1702 #define tcg_gen_st_f64 tcg_gen_st_i64
1704 static inline void gen_mov_F0_vreg(int dp, int reg)
1706 if (dp)
1707 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1708 else
1709 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1712 static inline void gen_mov_F1_vreg(int dp, int reg)
1714 if (dp)
1715 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1716 else
1717 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1720 static inline void gen_mov_vreg_F0(int dp, int reg)
1722 if (dp)
1723 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1724 else
1725 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1728 #define ARM_CP_RW_BIT (1 << 20)
1730 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1732 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1735 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1737 tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1740 static inline TCGv_i32 iwmmxt_load_creg(int reg)
1742 TCGv_i32 var = tcg_temp_new_i32();
1743 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1744 return var;
1747 static inline void iwmmxt_store_creg(int reg, TCGv_i32 var)
1749 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1750 tcg_temp_free_i32(var);
1753 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1755 iwmmxt_store_reg(cpu_M0, rn);
1758 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1760 iwmmxt_load_reg(cpu_M0, rn);
1763 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1765 iwmmxt_load_reg(cpu_V1, rn);
1766 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1769 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1771 iwmmxt_load_reg(cpu_V1, rn);
1772 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1775 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1777 iwmmxt_load_reg(cpu_V1, rn);
1778 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1781 #define IWMMXT_OP(name) \
1782 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1784 iwmmxt_load_reg(cpu_V1, rn); \
1785 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1788 #define IWMMXT_OP_ENV(name) \
1789 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1791 iwmmxt_load_reg(cpu_V1, rn); \
1792 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1795 #define IWMMXT_OP_ENV_SIZE(name) \
1796 IWMMXT_OP_ENV(name##b) \
1797 IWMMXT_OP_ENV(name##w) \
1798 IWMMXT_OP_ENV(name##l)
1800 #define IWMMXT_OP_ENV1(name) \
1801 static inline void gen_op_iwmmxt_##name##_M0(void) \
1803 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1806 IWMMXT_OP(maddsq)
1807 IWMMXT_OP(madduq)
1808 IWMMXT_OP(sadb)
1809 IWMMXT_OP(sadw)
1810 IWMMXT_OP(mulslw)
1811 IWMMXT_OP(mulshw)
1812 IWMMXT_OP(mululw)
1813 IWMMXT_OP(muluhw)
1814 IWMMXT_OP(macsw)
1815 IWMMXT_OP(macuw)
1817 IWMMXT_OP_ENV_SIZE(unpackl)
1818 IWMMXT_OP_ENV_SIZE(unpackh)
1820 IWMMXT_OP_ENV1(unpacklub)
1821 IWMMXT_OP_ENV1(unpackluw)
1822 IWMMXT_OP_ENV1(unpacklul)
1823 IWMMXT_OP_ENV1(unpackhub)
1824 IWMMXT_OP_ENV1(unpackhuw)
1825 IWMMXT_OP_ENV1(unpackhul)
1826 IWMMXT_OP_ENV1(unpacklsb)
1827 IWMMXT_OP_ENV1(unpacklsw)
1828 IWMMXT_OP_ENV1(unpacklsl)
1829 IWMMXT_OP_ENV1(unpackhsb)
1830 IWMMXT_OP_ENV1(unpackhsw)
1831 IWMMXT_OP_ENV1(unpackhsl)
1833 IWMMXT_OP_ENV_SIZE(cmpeq)
1834 IWMMXT_OP_ENV_SIZE(cmpgtu)
1835 IWMMXT_OP_ENV_SIZE(cmpgts)
1837 IWMMXT_OP_ENV_SIZE(mins)
1838 IWMMXT_OP_ENV_SIZE(minu)
1839 IWMMXT_OP_ENV_SIZE(maxs)
1840 IWMMXT_OP_ENV_SIZE(maxu)
1842 IWMMXT_OP_ENV_SIZE(subn)
1843 IWMMXT_OP_ENV_SIZE(addn)
1844 IWMMXT_OP_ENV_SIZE(subu)
1845 IWMMXT_OP_ENV_SIZE(addu)
1846 IWMMXT_OP_ENV_SIZE(subs)
1847 IWMMXT_OP_ENV_SIZE(adds)
1849 IWMMXT_OP_ENV(avgb0)
1850 IWMMXT_OP_ENV(avgb1)
1851 IWMMXT_OP_ENV(avgw0)
1852 IWMMXT_OP_ENV(avgw1)
1854 IWMMXT_OP_ENV(packuw)
1855 IWMMXT_OP_ENV(packul)
1856 IWMMXT_OP_ENV(packuq)
1857 IWMMXT_OP_ENV(packsw)
1858 IWMMXT_OP_ENV(packsl)
1859 IWMMXT_OP_ENV(packsq)
1861 static void gen_op_iwmmxt_set_mup(void)
1863 TCGv_i32 tmp;
1864 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1865 tcg_gen_ori_i32(tmp, tmp, 2);
1866 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1869 static void gen_op_iwmmxt_set_cup(void)
1871 TCGv_i32 tmp;
1872 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1873 tcg_gen_ori_i32(tmp, tmp, 1);
1874 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1877 static void gen_op_iwmmxt_setpsr_nz(void)
1879 TCGv_i32 tmp = tcg_temp_new_i32();
1880 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1881 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1884 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1886 iwmmxt_load_reg(cpu_V1, rn);
1887 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1888 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1891 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn,
1892 TCGv_i32 dest)
1894 int rd;
1895 uint32_t offset;
1896 TCGv_i32 tmp;
1898 rd = (insn >> 16) & 0xf;
1899 tmp = load_reg(s, rd);
1901 offset = (insn & 0xff) << ((insn >> 7) & 2);
1902 if (insn & (1 << 24)) {
1903 /* Pre indexed */
1904 if (insn & (1 << 23))
1905 tcg_gen_addi_i32(tmp, tmp, offset);
1906 else
1907 tcg_gen_addi_i32(tmp, tmp, -offset);
1908 tcg_gen_mov_i32(dest, tmp);
1909 if (insn & (1 << 21))
1910 store_reg(s, rd, tmp);
1911 else
1912 tcg_temp_free_i32(tmp);
1913 } else if (insn & (1 << 21)) {
1914 /* Post indexed */
1915 tcg_gen_mov_i32(dest, tmp);
1916 if (insn & (1 << 23))
1917 tcg_gen_addi_i32(tmp, tmp, offset);
1918 else
1919 tcg_gen_addi_i32(tmp, tmp, -offset);
1920 store_reg(s, rd, tmp);
1921 } else if (!(insn & (1 << 23)))
1922 return 1;
1923 return 0;
1926 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest)
1928 int rd = (insn >> 0) & 0xf;
1929 TCGv_i32 tmp;
1931 if (insn & (1 << 8)) {
1932 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1933 return 1;
1934 } else {
1935 tmp = iwmmxt_load_creg(rd);
1937 } else {
1938 tmp = tcg_temp_new_i32();
1939 iwmmxt_load_reg(cpu_V0, rd);
1940 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
1942 tcg_gen_andi_i32(tmp, tmp, mask);
1943 tcg_gen_mov_i32(dest, tmp);
1944 tcg_temp_free_i32(tmp);
1945 return 0;
1948 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
1949 (ie. an undefined instruction). */
1950 static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
1952 int rd, wrd;
1953 int rdhi, rdlo, rd0, rd1, i;
1954 TCGv_i32 addr;
1955 TCGv_i32 tmp, tmp2, tmp3;
1957 if ((insn & 0x0e000e00) == 0x0c000000) {
1958 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1959 wrd = insn & 0xf;
1960 rdlo = (insn >> 12) & 0xf;
1961 rdhi = (insn >> 16) & 0xf;
1962 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1963 iwmmxt_load_reg(cpu_V0, wrd);
1964 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
1965 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1966 tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
1967 } else { /* TMCRR */
1968 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1969 iwmmxt_store_reg(cpu_V0, wrd);
1970 gen_op_iwmmxt_set_mup();
1972 return 0;
1975 wrd = (insn >> 12) & 0xf;
1976 addr = tcg_temp_new_i32();
1977 if (gen_iwmmxt_address(s, insn, addr)) {
1978 tcg_temp_free_i32(addr);
1979 return 1;
1981 if (insn & ARM_CP_RW_BIT) {
1982 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1983 tmp = tcg_temp_new_i32();
1984 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
1985 iwmmxt_store_creg(wrd, tmp);
1986 } else {
1987 i = 1;
1988 if (insn & (1 << 8)) {
1989 if (insn & (1 << 22)) { /* WLDRD */
1990 gen_aa32_ld64(s, cpu_M0, addr, get_mem_index(s));
1991 i = 0;
1992 } else { /* WLDRW wRd */
1993 tmp = tcg_temp_new_i32();
1994 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
1996 } else {
1997 tmp = tcg_temp_new_i32();
1998 if (insn & (1 << 22)) { /* WLDRH */
1999 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
2000 } else { /* WLDRB */
2001 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
2004 if (i) {
2005 tcg_gen_extu_i32_i64(cpu_M0, tmp);
2006 tcg_temp_free_i32(tmp);
2008 gen_op_iwmmxt_movq_wRn_M0(wrd);
2010 } else {
2011 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
2012 tmp = iwmmxt_load_creg(wrd);
2013 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
2014 } else {
2015 gen_op_iwmmxt_movq_M0_wRn(wrd);
2016 tmp = tcg_temp_new_i32();
2017 if (insn & (1 << 8)) {
2018 if (insn & (1 << 22)) { /* WSTRD */
2019 gen_aa32_st64(s, cpu_M0, addr, get_mem_index(s));
2020 } else { /* WSTRW wRd */
2021 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2022 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
2024 } else {
2025 if (insn & (1 << 22)) { /* WSTRH */
2026 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2027 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
2028 } else { /* WSTRB */
2029 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2030 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
2034 tcg_temp_free_i32(tmp);
2036 tcg_temp_free_i32(addr);
2037 return 0;
2040 if ((insn & 0x0f000000) != 0x0e000000)
2041 return 1;
2043 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
2044 case 0x000: /* WOR */
2045 wrd = (insn >> 12) & 0xf;
2046 rd0 = (insn >> 0) & 0xf;
2047 rd1 = (insn >> 16) & 0xf;
2048 gen_op_iwmmxt_movq_M0_wRn(rd0);
2049 gen_op_iwmmxt_orq_M0_wRn(rd1);
2050 gen_op_iwmmxt_setpsr_nz();
2051 gen_op_iwmmxt_movq_wRn_M0(wrd);
2052 gen_op_iwmmxt_set_mup();
2053 gen_op_iwmmxt_set_cup();
2054 break;
2055 case 0x011: /* TMCR */
2056 if (insn & 0xf)
2057 return 1;
2058 rd = (insn >> 12) & 0xf;
2059 wrd = (insn >> 16) & 0xf;
2060 switch (wrd) {
2061 case ARM_IWMMXT_wCID:
2062 case ARM_IWMMXT_wCASF:
2063 break;
2064 case ARM_IWMMXT_wCon:
2065 gen_op_iwmmxt_set_cup();
2066 /* Fall through. */
2067 case ARM_IWMMXT_wCSSF:
2068 tmp = iwmmxt_load_creg(wrd);
2069 tmp2 = load_reg(s, rd);
2070 tcg_gen_andc_i32(tmp, tmp, tmp2);
2071 tcg_temp_free_i32(tmp2);
2072 iwmmxt_store_creg(wrd, tmp);
2073 break;
2074 case ARM_IWMMXT_wCGR0:
2075 case ARM_IWMMXT_wCGR1:
2076 case ARM_IWMMXT_wCGR2:
2077 case ARM_IWMMXT_wCGR3:
2078 gen_op_iwmmxt_set_cup();
2079 tmp = load_reg(s, rd);
2080 iwmmxt_store_creg(wrd, tmp);
2081 break;
2082 default:
2083 return 1;
2085 break;
2086 case 0x100: /* WXOR */
2087 wrd = (insn >> 12) & 0xf;
2088 rd0 = (insn >> 0) & 0xf;
2089 rd1 = (insn >> 16) & 0xf;
2090 gen_op_iwmmxt_movq_M0_wRn(rd0);
2091 gen_op_iwmmxt_xorq_M0_wRn(rd1);
2092 gen_op_iwmmxt_setpsr_nz();
2093 gen_op_iwmmxt_movq_wRn_M0(wrd);
2094 gen_op_iwmmxt_set_mup();
2095 gen_op_iwmmxt_set_cup();
2096 break;
2097 case 0x111: /* TMRC */
2098 if (insn & 0xf)
2099 return 1;
2100 rd = (insn >> 12) & 0xf;
2101 wrd = (insn >> 16) & 0xf;
2102 tmp = iwmmxt_load_creg(wrd);
2103 store_reg(s, rd, tmp);
2104 break;
2105 case 0x300: /* WANDN */
2106 wrd = (insn >> 12) & 0xf;
2107 rd0 = (insn >> 0) & 0xf;
2108 rd1 = (insn >> 16) & 0xf;
2109 gen_op_iwmmxt_movq_M0_wRn(rd0);
2110 tcg_gen_neg_i64(cpu_M0, cpu_M0);
2111 gen_op_iwmmxt_andq_M0_wRn(rd1);
2112 gen_op_iwmmxt_setpsr_nz();
2113 gen_op_iwmmxt_movq_wRn_M0(wrd);
2114 gen_op_iwmmxt_set_mup();
2115 gen_op_iwmmxt_set_cup();
2116 break;
2117 case 0x200: /* WAND */
2118 wrd = (insn >> 12) & 0xf;
2119 rd0 = (insn >> 0) & 0xf;
2120 rd1 = (insn >> 16) & 0xf;
2121 gen_op_iwmmxt_movq_M0_wRn(rd0);
2122 gen_op_iwmmxt_andq_M0_wRn(rd1);
2123 gen_op_iwmmxt_setpsr_nz();
2124 gen_op_iwmmxt_movq_wRn_M0(wrd);
2125 gen_op_iwmmxt_set_mup();
2126 gen_op_iwmmxt_set_cup();
2127 break;
2128 case 0x810: case 0xa10: /* WMADD */
2129 wrd = (insn >> 12) & 0xf;
2130 rd0 = (insn >> 0) & 0xf;
2131 rd1 = (insn >> 16) & 0xf;
2132 gen_op_iwmmxt_movq_M0_wRn(rd0);
2133 if (insn & (1 << 21))
2134 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
2135 else
2136 gen_op_iwmmxt_madduq_M0_wRn(rd1);
2137 gen_op_iwmmxt_movq_wRn_M0(wrd);
2138 gen_op_iwmmxt_set_mup();
2139 break;
2140 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
2141 wrd = (insn >> 12) & 0xf;
2142 rd0 = (insn >> 16) & 0xf;
2143 rd1 = (insn >> 0) & 0xf;
2144 gen_op_iwmmxt_movq_M0_wRn(rd0);
2145 switch ((insn >> 22) & 3) {
2146 case 0:
2147 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
2148 break;
2149 case 1:
2150 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
2151 break;
2152 case 2:
2153 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
2154 break;
2155 case 3:
2156 return 1;
2158 gen_op_iwmmxt_movq_wRn_M0(wrd);
2159 gen_op_iwmmxt_set_mup();
2160 gen_op_iwmmxt_set_cup();
2161 break;
2162 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
2163 wrd = (insn >> 12) & 0xf;
2164 rd0 = (insn >> 16) & 0xf;
2165 rd1 = (insn >> 0) & 0xf;
2166 gen_op_iwmmxt_movq_M0_wRn(rd0);
2167 switch ((insn >> 22) & 3) {
2168 case 0:
2169 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
2170 break;
2171 case 1:
2172 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
2173 break;
2174 case 2:
2175 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
2176 break;
2177 case 3:
2178 return 1;
2180 gen_op_iwmmxt_movq_wRn_M0(wrd);
2181 gen_op_iwmmxt_set_mup();
2182 gen_op_iwmmxt_set_cup();
2183 break;
2184 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
2185 wrd = (insn >> 12) & 0xf;
2186 rd0 = (insn >> 16) & 0xf;
2187 rd1 = (insn >> 0) & 0xf;
2188 gen_op_iwmmxt_movq_M0_wRn(rd0);
2189 if (insn & (1 << 22))
2190 gen_op_iwmmxt_sadw_M0_wRn(rd1);
2191 else
2192 gen_op_iwmmxt_sadb_M0_wRn(rd1);
2193 if (!(insn & (1 << 20)))
2194 gen_op_iwmmxt_addl_M0_wRn(wrd);
2195 gen_op_iwmmxt_movq_wRn_M0(wrd);
2196 gen_op_iwmmxt_set_mup();
2197 break;
2198 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
2199 wrd = (insn >> 12) & 0xf;
2200 rd0 = (insn >> 16) & 0xf;
2201 rd1 = (insn >> 0) & 0xf;
2202 gen_op_iwmmxt_movq_M0_wRn(rd0);
2203 if (insn & (1 << 21)) {
2204 if (insn & (1 << 20))
2205 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
2206 else
2207 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
2208 } else {
2209 if (insn & (1 << 20))
2210 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
2211 else
2212 gen_op_iwmmxt_mululw_M0_wRn(rd1);
2214 gen_op_iwmmxt_movq_wRn_M0(wrd);
2215 gen_op_iwmmxt_set_mup();
2216 break;
2217 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
2218 wrd = (insn >> 12) & 0xf;
2219 rd0 = (insn >> 16) & 0xf;
2220 rd1 = (insn >> 0) & 0xf;
2221 gen_op_iwmmxt_movq_M0_wRn(rd0);
2222 if (insn & (1 << 21))
2223 gen_op_iwmmxt_macsw_M0_wRn(rd1);
2224 else
2225 gen_op_iwmmxt_macuw_M0_wRn(rd1);
2226 if (!(insn & (1 << 20))) {
2227 iwmmxt_load_reg(cpu_V1, wrd);
2228 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
2230 gen_op_iwmmxt_movq_wRn_M0(wrd);
2231 gen_op_iwmmxt_set_mup();
2232 break;
2233 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
2234 wrd = (insn >> 12) & 0xf;
2235 rd0 = (insn >> 16) & 0xf;
2236 rd1 = (insn >> 0) & 0xf;
2237 gen_op_iwmmxt_movq_M0_wRn(rd0);
2238 switch ((insn >> 22) & 3) {
2239 case 0:
2240 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
2241 break;
2242 case 1:
2243 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
2244 break;
2245 case 2:
2246 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
2247 break;
2248 case 3:
2249 return 1;
2251 gen_op_iwmmxt_movq_wRn_M0(wrd);
2252 gen_op_iwmmxt_set_mup();
2253 gen_op_iwmmxt_set_cup();
2254 break;
2255 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
2256 wrd = (insn >> 12) & 0xf;
2257 rd0 = (insn >> 16) & 0xf;
2258 rd1 = (insn >> 0) & 0xf;
2259 gen_op_iwmmxt_movq_M0_wRn(rd0);
2260 if (insn & (1 << 22)) {
2261 if (insn & (1 << 20))
2262 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
2263 else
2264 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
2265 } else {
2266 if (insn & (1 << 20))
2267 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
2268 else
2269 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
2271 gen_op_iwmmxt_movq_wRn_M0(wrd);
2272 gen_op_iwmmxt_set_mup();
2273 gen_op_iwmmxt_set_cup();
2274 break;
2275 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
2276 wrd = (insn >> 12) & 0xf;
2277 rd0 = (insn >> 16) & 0xf;
2278 rd1 = (insn >> 0) & 0xf;
2279 gen_op_iwmmxt_movq_M0_wRn(rd0);
2280 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
2281 tcg_gen_andi_i32(tmp, tmp, 7);
2282 iwmmxt_load_reg(cpu_V1, rd1);
2283 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2284 tcg_temp_free_i32(tmp);
2285 gen_op_iwmmxt_movq_wRn_M0(wrd);
2286 gen_op_iwmmxt_set_mup();
2287 break;
2288 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
2289 if (((insn >> 6) & 3) == 3)
2290 return 1;
2291 rd = (insn >> 12) & 0xf;
2292 wrd = (insn >> 16) & 0xf;
2293 tmp = load_reg(s, rd);
2294 gen_op_iwmmxt_movq_M0_wRn(wrd);
2295 switch ((insn >> 6) & 3) {
2296 case 0:
2297 tmp2 = tcg_const_i32(0xff);
2298 tmp3 = tcg_const_i32((insn & 7) << 3);
2299 break;
2300 case 1:
2301 tmp2 = tcg_const_i32(0xffff);
2302 tmp3 = tcg_const_i32((insn & 3) << 4);
2303 break;
2304 case 2:
2305 tmp2 = tcg_const_i32(0xffffffff);
2306 tmp3 = tcg_const_i32((insn & 1) << 5);
2307 break;
2308 default:
2309 tmp2 = NULL;
2310 tmp3 = NULL;
2312 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
2313 tcg_temp_free_i32(tmp3);
2314 tcg_temp_free_i32(tmp2);
2315 tcg_temp_free_i32(tmp);
2316 gen_op_iwmmxt_movq_wRn_M0(wrd);
2317 gen_op_iwmmxt_set_mup();
2318 break;
2319 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
2320 rd = (insn >> 12) & 0xf;
2321 wrd = (insn >> 16) & 0xf;
2322 if (rd == 15 || ((insn >> 22) & 3) == 3)
2323 return 1;
2324 gen_op_iwmmxt_movq_M0_wRn(wrd);
2325 tmp = tcg_temp_new_i32();
2326 switch ((insn >> 22) & 3) {
2327 case 0:
2328 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
2329 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2330 if (insn & 8) {
2331 tcg_gen_ext8s_i32(tmp, tmp);
2332 } else {
2333 tcg_gen_andi_i32(tmp, tmp, 0xff);
2335 break;
2336 case 1:
2337 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
2338 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2339 if (insn & 8) {
2340 tcg_gen_ext16s_i32(tmp, tmp);
2341 } else {
2342 tcg_gen_andi_i32(tmp, tmp, 0xffff);
2344 break;
2345 case 2:
2346 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
2347 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2348 break;
2350 store_reg(s, rd, tmp);
2351 break;
2352 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
2353 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
2354 return 1;
2355 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
2356 switch ((insn >> 22) & 3) {
2357 case 0:
2358 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
2359 break;
2360 case 1:
2361 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
2362 break;
2363 case 2:
2364 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
2365 break;
2367 tcg_gen_shli_i32(tmp, tmp, 28);
2368 gen_set_nzcv(tmp);
2369 tcg_temp_free_i32(tmp);
2370 break;
2371 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
2372 if (((insn >> 6) & 3) == 3)
2373 return 1;
2374 rd = (insn >> 12) & 0xf;
2375 wrd = (insn >> 16) & 0xf;
2376 tmp = load_reg(s, rd);
2377 switch ((insn >> 6) & 3) {
2378 case 0:
2379 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
2380 break;
2381 case 1:
2382 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
2383 break;
2384 case 2:
2385 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
2386 break;
2388 tcg_temp_free_i32(tmp);
2389 gen_op_iwmmxt_movq_wRn_M0(wrd);
2390 gen_op_iwmmxt_set_mup();
2391 break;
2392 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
2393 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
2394 return 1;
2395 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
2396 tmp2 = tcg_temp_new_i32();
2397 tcg_gen_mov_i32(tmp2, tmp);
2398 switch ((insn >> 22) & 3) {
2399 case 0:
2400 for (i = 0; i < 7; i ++) {
2401 tcg_gen_shli_i32(tmp2, tmp2, 4);
2402 tcg_gen_and_i32(tmp, tmp, tmp2);
2404 break;
2405 case 1:
2406 for (i = 0; i < 3; i ++) {
2407 tcg_gen_shli_i32(tmp2, tmp2, 8);
2408 tcg_gen_and_i32(tmp, tmp, tmp2);
2410 break;
2411 case 2:
2412 tcg_gen_shli_i32(tmp2, tmp2, 16);
2413 tcg_gen_and_i32(tmp, tmp, tmp2);
2414 break;
2416 gen_set_nzcv(tmp);
2417 tcg_temp_free_i32(tmp2);
2418 tcg_temp_free_i32(tmp);
2419 break;
2420 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
2421 wrd = (insn >> 12) & 0xf;
2422 rd0 = (insn >> 16) & 0xf;
2423 gen_op_iwmmxt_movq_M0_wRn(rd0);
2424 switch ((insn >> 22) & 3) {
2425 case 0:
2426 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
2427 break;
2428 case 1:
2429 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
2430 break;
2431 case 2:
2432 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
2433 break;
2434 case 3:
2435 return 1;
2437 gen_op_iwmmxt_movq_wRn_M0(wrd);
2438 gen_op_iwmmxt_set_mup();
2439 break;
2440 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
2441 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
2442 return 1;
2443 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
2444 tmp2 = tcg_temp_new_i32();
2445 tcg_gen_mov_i32(tmp2, tmp);
2446 switch ((insn >> 22) & 3) {
2447 case 0:
2448 for (i = 0; i < 7; i ++) {
2449 tcg_gen_shli_i32(tmp2, tmp2, 4);
2450 tcg_gen_or_i32(tmp, tmp, tmp2);
2452 break;
2453 case 1:
2454 for (i = 0; i < 3; i ++) {
2455 tcg_gen_shli_i32(tmp2, tmp2, 8);
2456 tcg_gen_or_i32(tmp, tmp, tmp2);
2458 break;
2459 case 2:
2460 tcg_gen_shli_i32(tmp2, tmp2, 16);
2461 tcg_gen_or_i32(tmp, tmp, tmp2);
2462 break;
2464 gen_set_nzcv(tmp);
2465 tcg_temp_free_i32(tmp2);
2466 tcg_temp_free_i32(tmp);
2467 break;
2468 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
2469 rd = (insn >> 12) & 0xf;
2470 rd0 = (insn >> 16) & 0xf;
2471 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
2472 return 1;
2473 gen_op_iwmmxt_movq_M0_wRn(rd0);
2474 tmp = tcg_temp_new_i32();
2475 switch ((insn >> 22) & 3) {
2476 case 0:
2477 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
2478 break;
2479 case 1:
2480 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
2481 break;
2482 case 2:
2483 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
2484 break;
2486 store_reg(s, rd, tmp);
2487 break;
2488 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
2489 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2490 wrd = (insn >> 12) & 0xf;
2491 rd0 = (insn >> 16) & 0xf;
2492 rd1 = (insn >> 0) & 0xf;
2493 gen_op_iwmmxt_movq_M0_wRn(rd0);
2494 switch ((insn >> 22) & 3) {
2495 case 0:
2496 if (insn & (1 << 21))
2497 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2498 else
2499 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2500 break;
2501 case 1:
2502 if (insn & (1 << 21))
2503 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2504 else
2505 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2506 break;
2507 case 2:
2508 if (insn & (1 << 21))
2509 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2510 else
2511 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2512 break;
2513 case 3:
2514 return 1;
2516 gen_op_iwmmxt_movq_wRn_M0(wrd);
2517 gen_op_iwmmxt_set_mup();
2518 gen_op_iwmmxt_set_cup();
2519 break;
2520 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2521 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2522 wrd = (insn >> 12) & 0xf;
2523 rd0 = (insn >> 16) & 0xf;
2524 gen_op_iwmmxt_movq_M0_wRn(rd0);
2525 switch ((insn >> 22) & 3) {
2526 case 0:
2527 if (insn & (1 << 21))
2528 gen_op_iwmmxt_unpacklsb_M0();
2529 else
2530 gen_op_iwmmxt_unpacklub_M0();
2531 break;
2532 case 1:
2533 if (insn & (1 << 21))
2534 gen_op_iwmmxt_unpacklsw_M0();
2535 else
2536 gen_op_iwmmxt_unpackluw_M0();
2537 break;
2538 case 2:
2539 if (insn & (1 << 21))
2540 gen_op_iwmmxt_unpacklsl_M0();
2541 else
2542 gen_op_iwmmxt_unpacklul_M0();
2543 break;
2544 case 3:
2545 return 1;
2547 gen_op_iwmmxt_movq_wRn_M0(wrd);
2548 gen_op_iwmmxt_set_mup();
2549 gen_op_iwmmxt_set_cup();
2550 break;
2551 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2552 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2553 wrd = (insn >> 12) & 0xf;
2554 rd0 = (insn >> 16) & 0xf;
2555 gen_op_iwmmxt_movq_M0_wRn(rd0);
2556 switch ((insn >> 22) & 3) {
2557 case 0:
2558 if (insn & (1 << 21))
2559 gen_op_iwmmxt_unpackhsb_M0();
2560 else
2561 gen_op_iwmmxt_unpackhub_M0();
2562 break;
2563 case 1:
2564 if (insn & (1 << 21))
2565 gen_op_iwmmxt_unpackhsw_M0();
2566 else
2567 gen_op_iwmmxt_unpackhuw_M0();
2568 break;
2569 case 2:
2570 if (insn & (1 << 21))
2571 gen_op_iwmmxt_unpackhsl_M0();
2572 else
2573 gen_op_iwmmxt_unpackhul_M0();
2574 break;
2575 case 3:
2576 return 1;
2578 gen_op_iwmmxt_movq_wRn_M0(wrd);
2579 gen_op_iwmmxt_set_mup();
2580 gen_op_iwmmxt_set_cup();
2581 break;
2582 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2583 case 0x214: case 0x614: case 0xa14: case 0xe14:
2584 if (((insn >> 22) & 3) == 0)
2585 return 1;
2586 wrd = (insn >> 12) & 0xf;
2587 rd0 = (insn >> 16) & 0xf;
2588 gen_op_iwmmxt_movq_M0_wRn(rd0);
2589 tmp = tcg_temp_new_i32();
2590 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2591 tcg_temp_free_i32(tmp);
2592 return 1;
2594 switch ((insn >> 22) & 3) {
2595 case 1:
2596 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
2597 break;
2598 case 2:
2599 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
2600 break;
2601 case 3:
2602 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
2603 break;
2605 tcg_temp_free_i32(tmp);
2606 gen_op_iwmmxt_movq_wRn_M0(wrd);
2607 gen_op_iwmmxt_set_mup();
2608 gen_op_iwmmxt_set_cup();
2609 break;
2610 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2611 case 0x014: case 0x414: case 0x814: case 0xc14:
2612 if (((insn >> 22) & 3) == 0)
2613 return 1;
2614 wrd = (insn >> 12) & 0xf;
2615 rd0 = (insn >> 16) & 0xf;
2616 gen_op_iwmmxt_movq_M0_wRn(rd0);
2617 tmp = tcg_temp_new_i32();
2618 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2619 tcg_temp_free_i32(tmp);
2620 return 1;
2622 switch ((insn >> 22) & 3) {
2623 case 1:
2624 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2625 break;
2626 case 2:
2627 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2628 break;
2629 case 3:
2630 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2631 break;
2633 tcg_temp_free_i32(tmp);
2634 gen_op_iwmmxt_movq_wRn_M0(wrd);
2635 gen_op_iwmmxt_set_mup();
2636 gen_op_iwmmxt_set_cup();
2637 break;
2638 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2639 case 0x114: case 0x514: case 0x914: case 0xd14:
2640 if (((insn >> 22) & 3) == 0)
2641 return 1;
2642 wrd = (insn >> 12) & 0xf;
2643 rd0 = (insn >> 16) & 0xf;
2644 gen_op_iwmmxt_movq_M0_wRn(rd0);
2645 tmp = tcg_temp_new_i32();
2646 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2647 tcg_temp_free_i32(tmp);
2648 return 1;
2650 switch ((insn >> 22) & 3) {
2651 case 1:
2652 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2653 break;
2654 case 2:
2655 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2656 break;
2657 case 3:
2658 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2659 break;
2661 tcg_temp_free_i32(tmp);
2662 gen_op_iwmmxt_movq_wRn_M0(wrd);
2663 gen_op_iwmmxt_set_mup();
2664 gen_op_iwmmxt_set_cup();
2665 break;
2666 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2667 case 0x314: case 0x714: case 0xb14: case 0xf14:
2668 if (((insn >> 22) & 3) == 0)
2669 return 1;
2670 wrd = (insn >> 12) & 0xf;
2671 rd0 = (insn >> 16) & 0xf;
2672 gen_op_iwmmxt_movq_M0_wRn(rd0);
2673 tmp = tcg_temp_new_i32();
2674 switch ((insn >> 22) & 3) {
2675 case 1:
2676 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2677 tcg_temp_free_i32(tmp);
2678 return 1;
2680 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2681 break;
2682 case 2:
2683 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2684 tcg_temp_free_i32(tmp);
2685 return 1;
2687 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2688 break;
2689 case 3:
2690 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2691 tcg_temp_free_i32(tmp);
2692 return 1;
2694 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2695 break;
2697 tcg_temp_free_i32(tmp);
2698 gen_op_iwmmxt_movq_wRn_M0(wrd);
2699 gen_op_iwmmxt_set_mup();
2700 gen_op_iwmmxt_set_cup();
2701 break;
2702 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2703 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2704 wrd = (insn >> 12) & 0xf;
2705 rd0 = (insn >> 16) & 0xf;
2706 rd1 = (insn >> 0) & 0xf;
2707 gen_op_iwmmxt_movq_M0_wRn(rd0);
2708 switch ((insn >> 22) & 3) {
2709 case 0:
2710 if (insn & (1 << 21))
2711 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2712 else
2713 gen_op_iwmmxt_minub_M0_wRn(rd1);
2714 break;
2715 case 1:
2716 if (insn & (1 << 21))
2717 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2718 else
2719 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2720 break;
2721 case 2:
2722 if (insn & (1 << 21))
2723 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2724 else
2725 gen_op_iwmmxt_minul_M0_wRn(rd1);
2726 break;
2727 case 3:
2728 return 1;
2730 gen_op_iwmmxt_movq_wRn_M0(wrd);
2731 gen_op_iwmmxt_set_mup();
2732 break;
2733 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2734 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2735 wrd = (insn >> 12) & 0xf;
2736 rd0 = (insn >> 16) & 0xf;
2737 rd1 = (insn >> 0) & 0xf;
2738 gen_op_iwmmxt_movq_M0_wRn(rd0);
2739 switch ((insn >> 22) & 3) {
2740 case 0:
2741 if (insn & (1 << 21))
2742 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2743 else
2744 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2745 break;
2746 case 1:
2747 if (insn & (1 << 21))
2748 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2749 else
2750 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2751 break;
2752 case 2:
2753 if (insn & (1 << 21))
2754 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2755 else
2756 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2757 break;
2758 case 3:
2759 return 1;
2761 gen_op_iwmmxt_movq_wRn_M0(wrd);
2762 gen_op_iwmmxt_set_mup();
2763 break;
2764 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2765 case 0x402: case 0x502: case 0x602: case 0x702:
2766 wrd = (insn >> 12) & 0xf;
2767 rd0 = (insn >> 16) & 0xf;
2768 rd1 = (insn >> 0) & 0xf;
2769 gen_op_iwmmxt_movq_M0_wRn(rd0);
2770 tmp = tcg_const_i32((insn >> 20) & 3);
2771 iwmmxt_load_reg(cpu_V1, rd1);
2772 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2773 tcg_temp_free_i32(tmp);
2774 gen_op_iwmmxt_movq_wRn_M0(wrd);
2775 gen_op_iwmmxt_set_mup();
2776 break;
2777 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2778 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2779 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2780 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2781 wrd = (insn >> 12) & 0xf;
2782 rd0 = (insn >> 16) & 0xf;
2783 rd1 = (insn >> 0) & 0xf;
2784 gen_op_iwmmxt_movq_M0_wRn(rd0);
2785 switch ((insn >> 20) & 0xf) {
2786 case 0x0:
2787 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2788 break;
2789 case 0x1:
2790 gen_op_iwmmxt_subub_M0_wRn(rd1);
2791 break;
2792 case 0x3:
2793 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2794 break;
2795 case 0x4:
2796 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2797 break;
2798 case 0x5:
2799 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2800 break;
2801 case 0x7:
2802 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2803 break;
2804 case 0x8:
2805 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2806 break;
2807 case 0x9:
2808 gen_op_iwmmxt_subul_M0_wRn(rd1);
2809 break;
2810 case 0xb:
2811 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2812 break;
2813 default:
2814 return 1;
2816 gen_op_iwmmxt_movq_wRn_M0(wrd);
2817 gen_op_iwmmxt_set_mup();
2818 gen_op_iwmmxt_set_cup();
2819 break;
2820 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2821 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2822 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2823 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2824 wrd = (insn >> 12) & 0xf;
2825 rd0 = (insn >> 16) & 0xf;
2826 gen_op_iwmmxt_movq_M0_wRn(rd0);
2827 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2828 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2829 tcg_temp_free_i32(tmp);
2830 gen_op_iwmmxt_movq_wRn_M0(wrd);
2831 gen_op_iwmmxt_set_mup();
2832 gen_op_iwmmxt_set_cup();
2833 break;
2834 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2835 case 0x418: case 0x518: case 0x618: case 0x718:
2836 case 0x818: case 0x918: case 0xa18: case 0xb18:
2837 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2838 wrd = (insn >> 12) & 0xf;
2839 rd0 = (insn >> 16) & 0xf;
2840 rd1 = (insn >> 0) & 0xf;
2841 gen_op_iwmmxt_movq_M0_wRn(rd0);
2842 switch ((insn >> 20) & 0xf) {
2843 case 0x0:
2844 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2845 break;
2846 case 0x1:
2847 gen_op_iwmmxt_addub_M0_wRn(rd1);
2848 break;
2849 case 0x3:
2850 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2851 break;
2852 case 0x4:
2853 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2854 break;
2855 case 0x5:
2856 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2857 break;
2858 case 0x7:
2859 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2860 break;
2861 case 0x8:
2862 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2863 break;
2864 case 0x9:
2865 gen_op_iwmmxt_addul_M0_wRn(rd1);
2866 break;
2867 case 0xb:
2868 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2869 break;
2870 default:
2871 return 1;
2873 gen_op_iwmmxt_movq_wRn_M0(wrd);
2874 gen_op_iwmmxt_set_mup();
2875 gen_op_iwmmxt_set_cup();
2876 break;
2877 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2878 case 0x408: case 0x508: case 0x608: case 0x708:
2879 case 0x808: case 0x908: case 0xa08: case 0xb08:
2880 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2881 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2882 return 1;
2883 wrd = (insn >> 12) & 0xf;
2884 rd0 = (insn >> 16) & 0xf;
2885 rd1 = (insn >> 0) & 0xf;
2886 gen_op_iwmmxt_movq_M0_wRn(rd0);
2887 switch ((insn >> 22) & 3) {
2888 case 1:
2889 if (insn & (1 << 21))
2890 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2891 else
2892 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2893 break;
2894 case 2:
2895 if (insn & (1 << 21))
2896 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2897 else
2898 gen_op_iwmmxt_packul_M0_wRn(rd1);
2899 break;
2900 case 3:
2901 if (insn & (1 << 21))
2902 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2903 else
2904 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2905 break;
2907 gen_op_iwmmxt_movq_wRn_M0(wrd);
2908 gen_op_iwmmxt_set_mup();
2909 gen_op_iwmmxt_set_cup();
2910 break;
2911 case 0x201: case 0x203: case 0x205: case 0x207:
2912 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2913 case 0x211: case 0x213: case 0x215: case 0x217:
2914 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2915 wrd = (insn >> 5) & 0xf;
2916 rd0 = (insn >> 12) & 0xf;
2917 rd1 = (insn >> 0) & 0xf;
2918 if (rd0 == 0xf || rd1 == 0xf)
2919 return 1;
2920 gen_op_iwmmxt_movq_M0_wRn(wrd);
2921 tmp = load_reg(s, rd0);
2922 tmp2 = load_reg(s, rd1);
2923 switch ((insn >> 16) & 0xf) {
2924 case 0x0: /* TMIA */
2925 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2926 break;
2927 case 0x8: /* TMIAPH */
2928 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2929 break;
2930 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2931 if (insn & (1 << 16))
2932 tcg_gen_shri_i32(tmp, tmp, 16);
2933 if (insn & (1 << 17))
2934 tcg_gen_shri_i32(tmp2, tmp2, 16);
2935 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2936 break;
2937 default:
2938 tcg_temp_free_i32(tmp2);
2939 tcg_temp_free_i32(tmp);
2940 return 1;
2942 tcg_temp_free_i32(tmp2);
2943 tcg_temp_free_i32(tmp);
2944 gen_op_iwmmxt_movq_wRn_M0(wrd);
2945 gen_op_iwmmxt_set_mup();
2946 break;
2947 default:
2948 return 1;
2951 return 0;
2954 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
2955 (ie. an undefined instruction). */
2956 static int disas_dsp_insn(DisasContext *s, uint32_t insn)
2958 int acc, rd0, rd1, rdhi, rdlo;
2959 TCGv_i32 tmp, tmp2;
2961 if ((insn & 0x0ff00f10) == 0x0e200010) {
2962 /* Multiply with Internal Accumulate Format */
2963 rd0 = (insn >> 12) & 0xf;
2964 rd1 = insn & 0xf;
2965 acc = (insn >> 5) & 7;
2967 if (acc != 0)
2968 return 1;
2970 tmp = load_reg(s, rd0);
2971 tmp2 = load_reg(s, rd1);
2972 switch ((insn >> 16) & 0xf) {
2973 case 0x0: /* MIA */
2974 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2975 break;
2976 case 0x8: /* MIAPH */
2977 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2978 break;
2979 case 0xc: /* MIABB */
2980 case 0xd: /* MIABT */
2981 case 0xe: /* MIATB */
2982 case 0xf: /* MIATT */
2983 if (insn & (1 << 16))
2984 tcg_gen_shri_i32(tmp, tmp, 16);
2985 if (insn & (1 << 17))
2986 tcg_gen_shri_i32(tmp2, tmp2, 16);
2987 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2988 break;
2989 default:
2990 return 1;
2992 tcg_temp_free_i32(tmp2);
2993 tcg_temp_free_i32(tmp);
2995 gen_op_iwmmxt_movq_wRn_M0(acc);
2996 return 0;
2999 if ((insn & 0x0fe00ff8) == 0x0c400000) {
3000 /* Internal Accumulator Access Format */
3001 rdhi = (insn >> 16) & 0xf;
3002 rdlo = (insn >> 12) & 0xf;
3003 acc = insn & 7;
3005 if (acc != 0)
3006 return 1;
3008 if (insn & ARM_CP_RW_BIT) { /* MRA */
3009 iwmmxt_load_reg(cpu_V0, acc);
3010 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
3011 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
3012 tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
3013 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
3014 } else { /* MAR */
3015 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
3016 iwmmxt_store_reg(cpu_V0, acc);
3018 return 0;
3021 return 1;
3024 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
3025 #define VFP_SREG(insn, bigbit, smallbit) \
3026 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
3027 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
3028 if (arm_dc_feature(s, ARM_FEATURE_VFP3)) { \
3029 reg = (((insn) >> (bigbit)) & 0x0f) \
3030 | (((insn) >> ((smallbit) - 4)) & 0x10); \
3031 } else { \
3032 if (insn & (1 << (smallbit))) \
3033 return 1; \
3034 reg = ((insn) >> (bigbit)) & 0x0f; \
3035 }} while (0)
3037 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
3038 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
3039 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
3040 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
3041 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
3042 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
3044 /* Move between integer and VFP cores. */
3045 static TCGv_i32 gen_vfp_mrs(void)
3047 TCGv_i32 tmp = tcg_temp_new_i32();
3048 tcg_gen_mov_i32(tmp, cpu_F0s);
3049 return tmp;
3052 static void gen_vfp_msr(TCGv_i32 tmp)
3054 tcg_gen_mov_i32(cpu_F0s, tmp);
3055 tcg_temp_free_i32(tmp);
3058 static void gen_neon_dup_low16(TCGv_i32 var)
3060 TCGv_i32 tmp = tcg_temp_new_i32();
3061 tcg_gen_ext16u_i32(var, var);
3062 tcg_gen_shli_i32(tmp, var, 16);
3063 tcg_gen_or_i32(var, var, tmp);
3064 tcg_temp_free_i32(tmp);
3067 static void gen_neon_dup_high16(TCGv_i32 var)
3069 TCGv_i32 tmp = tcg_temp_new_i32();
3070 tcg_gen_andi_i32(var, var, 0xffff0000);
3071 tcg_gen_shri_i32(tmp, var, 16);
3072 tcg_gen_or_i32(var, var, tmp);
3073 tcg_temp_free_i32(tmp);
3076 static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
3077 uint32_t dp)
3079 uint32_t cc = extract32(insn, 20, 2);
3081 if (dp) {
3082 TCGv_i64 frn, frm, dest;
3083 TCGv_i64 tmp, zero, zf, nf, vf;
3085 zero = tcg_const_i64(0);
3087 frn = tcg_temp_new_i64();
3088 frm = tcg_temp_new_i64();
3089 dest = tcg_temp_new_i64();
3091 zf = tcg_temp_new_i64();
3092 nf = tcg_temp_new_i64();
3093 vf = tcg_temp_new_i64();
3095 tcg_gen_extu_i32_i64(zf, cpu_ZF);
3096 tcg_gen_ext_i32_i64(nf, cpu_NF);
3097 tcg_gen_ext_i32_i64(vf, cpu_VF);
3099 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
3100 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
3101 switch (cc) {
3102 case 0: /* eq: Z */
3103 tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero,
3104 frn, frm);
3105 break;
3106 case 1: /* vs: V */
3107 tcg_gen_movcond_i64(TCG_COND_LT, dest, vf, zero,
3108 frn, frm);
3109 break;
3110 case 2: /* ge: N == V -> N ^ V == 0 */
3111 tmp = tcg_temp_new_i64();
3112 tcg_gen_xor_i64(tmp, vf, nf);
3113 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
3114 frn, frm);
3115 tcg_temp_free_i64(tmp);
3116 break;
3117 case 3: /* gt: !Z && N == V */
3118 tcg_gen_movcond_i64(TCG_COND_NE, dest, zf, zero,
3119 frn, frm);
3120 tmp = tcg_temp_new_i64();
3121 tcg_gen_xor_i64(tmp, vf, nf);
3122 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
3123 dest, frm);
3124 tcg_temp_free_i64(tmp);
3125 break;
3127 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
3128 tcg_temp_free_i64(frn);
3129 tcg_temp_free_i64(frm);
3130 tcg_temp_free_i64(dest);
3132 tcg_temp_free_i64(zf);
3133 tcg_temp_free_i64(nf);
3134 tcg_temp_free_i64(vf);
3136 tcg_temp_free_i64(zero);
3137 } else {
3138 TCGv_i32 frn, frm, dest;
3139 TCGv_i32 tmp, zero;
3141 zero = tcg_const_i32(0);
3143 frn = tcg_temp_new_i32();
3144 frm = tcg_temp_new_i32();
3145 dest = tcg_temp_new_i32();
3146 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
3147 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
3148 switch (cc) {
3149 case 0: /* eq: Z */
3150 tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero,
3151 frn, frm);
3152 break;
3153 case 1: /* vs: V */
3154 tcg_gen_movcond_i32(TCG_COND_LT, dest, cpu_VF, zero,
3155 frn, frm);
3156 break;
3157 case 2: /* ge: N == V -> N ^ V == 0 */
3158 tmp = tcg_temp_new_i32();
3159 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
3160 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
3161 frn, frm);
3162 tcg_temp_free_i32(tmp);
3163 break;
3164 case 3: /* gt: !Z && N == V */
3165 tcg_gen_movcond_i32(TCG_COND_NE, dest, cpu_ZF, zero,
3166 frn, frm);
3167 tmp = tcg_temp_new_i32();
3168 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
3169 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
3170 dest, frm);
3171 tcg_temp_free_i32(tmp);
3172 break;
3174 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
3175 tcg_temp_free_i32(frn);
3176 tcg_temp_free_i32(frm);
3177 tcg_temp_free_i32(dest);
3179 tcg_temp_free_i32(zero);
3182 return 0;
3185 static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn,
3186 uint32_t rm, uint32_t dp)
3188 uint32_t vmin = extract32(insn, 6, 1);
3189 TCGv_ptr fpst = get_fpstatus_ptr(0);
3191 if (dp) {
3192 TCGv_i64 frn, frm, dest;
3194 frn = tcg_temp_new_i64();
3195 frm = tcg_temp_new_i64();
3196 dest = tcg_temp_new_i64();
3198 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
3199 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
3200 if (vmin) {
3201 gen_helper_vfp_minnumd(dest, frn, frm, fpst);
3202 } else {
3203 gen_helper_vfp_maxnumd(dest, frn, frm, fpst);
3205 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
3206 tcg_temp_free_i64(frn);
3207 tcg_temp_free_i64(frm);
3208 tcg_temp_free_i64(dest);
3209 } else {
3210 TCGv_i32 frn, frm, dest;
3212 frn = tcg_temp_new_i32();
3213 frm = tcg_temp_new_i32();
3214 dest = tcg_temp_new_i32();
3216 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
3217 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
3218 if (vmin) {
3219 gen_helper_vfp_minnums(dest, frn, frm, fpst);
3220 } else {
3221 gen_helper_vfp_maxnums(dest, frn, frm, fpst);
3223 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
3224 tcg_temp_free_i32(frn);
3225 tcg_temp_free_i32(frm);
3226 tcg_temp_free_i32(dest);
3229 tcg_temp_free_ptr(fpst);
3230 return 0;
3233 static int handle_vrint(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
3234 int rounding)
3236 TCGv_ptr fpst = get_fpstatus_ptr(0);
3237 TCGv_i32 tcg_rmode;
3239 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
3240 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
3242 if (dp) {
3243 TCGv_i64 tcg_op;
3244 TCGv_i64 tcg_res;
3245 tcg_op = tcg_temp_new_i64();
3246 tcg_res = tcg_temp_new_i64();
3247 tcg_gen_ld_f64(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
3248 gen_helper_rintd(tcg_res, tcg_op, fpst);
3249 tcg_gen_st_f64(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
3250 tcg_temp_free_i64(tcg_op);
3251 tcg_temp_free_i64(tcg_res);
3252 } else {
3253 TCGv_i32 tcg_op;
3254 TCGv_i32 tcg_res;
3255 tcg_op = tcg_temp_new_i32();
3256 tcg_res = tcg_temp_new_i32();
3257 tcg_gen_ld_f32(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
3258 gen_helper_rints(tcg_res, tcg_op, fpst);
3259 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
3260 tcg_temp_free_i32(tcg_op);
3261 tcg_temp_free_i32(tcg_res);
3264 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
3265 tcg_temp_free_i32(tcg_rmode);
3267 tcg_temp_free_ptr(fpst);
3268 return 0;
3271 static int handle_vcvt(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
3272 int rounding)
3274 bool is_signed = extract32(insn, 7, 1);
3275 TCGv_ptr fpst = get_fpstatus_ptr(0);
3276 TCGv_i32 tcg_rmode, tcg_shift;
3278 tcg_shift = tcg_const_i32(0);
3280 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
3281 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
3283 if (dp) {
3284 TCGv_i64 tcg_double, tcg_res;
3285 TCGv_i32 tcg_tmp;
3286 /* Rd is encoded as a single precision register even when the source
3287 * is double precision.
3289 rd = ((rd << 1) & 0x1e) | ((rd >> 4) & 0x1);
3290 tcg_double = tcg_temp_new_i64();
3291 tcg_res = tcg_temp_new_i64();
3292 tcg_tmp = tcg_temp_new_i32();
3293 tcg_gen_ld_f64(tcg_double, cpu_env, vfp_reg_offset(1, rm));
3294 if (is_signed) {
3295 gen_helper_vfp_tosld(tcg_res, tcg_double, tcg_shift, fpst);
3296 } else {
3297 gen_helper_vfp_tould(tcg_res, tcg_double, tcg_shift, fpst);
3299 tcg_gen_extrl_i64_i32(tcg_tmp, tcg_res);
3300 tcg_gen_st_f32(tcg_tmp, cpu_env, vfp_reg_offset(0, rd));
3301 tcg_temp_free_i32(tcg_tmp);
3302 tcg_temp_free_i64(tcg_res);
3303 tcg_temp_free_i64(tcg_double);
3304 } else {
3305 TCGv_i32 tcg_single, tcg_res;
3306 tcg_single = tcg_temp_new_i32();
3307 tcg_res = tcg_temp_new_i32();
3308 tcg_gen_ld_f32(tcg_single, cpu_env, vfp_reg_offset(0, rm));
3309 if (is_signed) {
3310 gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst);
3311 } else {
3312 gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst);
3314 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(0, rd));
3315 tcg_temp_free_i32(tcg_res);
3316 tcg_temp_free_i32(tcg_single);
3319 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
3320 tcg_temp_free_i32(tcg_rmode);
3322 tcg_temp_free_i32(tcg_shift);
3324 tcg_temp_free_ptr(fpst);
3326 return 0;
3329 /* Table for converting the most common AArch32 encoding of
3330 * rounding mode to arm_fprounding order (which matches the
3331 * common AArch64 order); see ARM ARM pseudocode FPDecodeRM().
3333 static const uint8_t fp_decode_rm[] = {
3334 FPROUNDING_TIEAWAY,
3335 FPROUNDING_TIEEVEN,
3336 FPROUNDING_POSINF,
3337 FPROUNDING_NEGINF,
3340 static int disas_vfp_misc_insn(DisasContext *s, uint32_t insn)
3342 uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
3344 if (dp) {
3345 VFP_DREG_D(rd, insn);
3346 VFP_DREG_N(rn, insn);
3347 VFP_DREG_M(rm, insn);
3348 } else {
3349 rd = VFP_SREG_D(insn);
3350 rn = VFP_SREG_N(insn);
3351 rm = VFP_SREG_M(insn);
3354 if ((insn & 0x0f800e50) == 0x0e000a00 && dc_isar_feature(aa32_vsel, s)) {
3355 return handle_vsel(insn, rd, rn, rm, dp);
3356 } else if ((insn & 0x0fb00e10) == 0x0e800a00 &&
3357 dc_isar_feature(aa32_vminmaxnm, s)) {
3358 return handle_vminmaxnm(insn, rd, rn, rm, dp);
3359 } else if ((insn & 0x0fbc0ed0) == 0x0eb80a40 &&
3360 dc_isar_feature(aa32_vrint, s)) {
3361 /* VRINTA, VRINTN, VRINTP, VRINTM */
3362 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
3363 return handle_vrint(insn, rd, rm, dp, rounding);
3364 } else if ((insn & 0x0fbc0e50) == 0x0ebc0a40 &&
3365 dc_isar_feature(aa32_vcvt_dr, s)) {
3366 /* VCVTA, VCVTN, VCVTP, VCVTM */
3367 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
3368 return handle_vcvt(insn, rd, rm, dp, rounding);
3370 return 1;
3373 /* Disassemble a VFP instruction. Returns nonzero if an error occurred
3374 (ie. an undefined instruction). */
3375 static int disas_vfp_insn(DisasContext *s, uint32_t insn)
3377 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
3378 int dp, veclen;
3379 TCGv_i32 addr;
3380 TCGv_i32 tmp;
3381 TCGv_i32 tmp2;
3383 if (!arm_dc_feature(s, ARM_FEATURE_VFP)) {
3384 return 1;
3387 /* FIXME: this access check should not take precedence over UNDEF
3388 * for invalid encodings; we will generate incorrect syndrome information
3389 * for attempts to execute invalid vfp/neon encodings with FP disabled.
3391 if (s->fp_excp_el) {
3392 if (arm_dc_feature(s, ARM_FEATURE_M)) {
3393 gen_exception_insn(s, 4, EXCP_NOCP, syn_uncategorized(),
3394 s->fp_excp_el);
3395 } else {
3396 gen_exception_insn(s, 4, EXCP_UDEF,
3397 syn_fp_access_trap(1, 0xe, false),
3398 s->fp_excp_el);
3400 return 0;
3403 if (!s->vfp_enabled) {
3404 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
3405 if ((insn & 0x0fe00fff) != 0x0ee00a10)
3406 return 1;
3407 rn = (insn >> 16) & 0xf;
3408 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC && rn != ARM_VFP_MVFR2
3409 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0) {
3410 return 1;
3414 if (arm_dc_feature(s, ARM_FEATURE_M)) {
3415 /* Handle M-profile lazy FP state mechanics */
3417 /* Trigger lazy-state preservation if necessary */
3418 if (s->v7m_lspact) {
3420 * Lazy state saving affects external memory and also the NVIC,
3421 * so we must mark it as an IO operation for icount.
3423 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
3424 gen_io_start();
3426 gen_helper_v7m_preserve_fp_state(cpu_env);
3427 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
3428 gen_io_end();
3431 * If the preserve_fp_state helper doesn't throw an exception
3432 * then it will clear LSPACT; we don't need to repeat this for
3433 * any further FP insns in this TB.
3435 s->v7m_lspact = false;
3438 /* Update ownership of FP context: set FPCCR.S to match current state */
3439 if (s->v8m_fpccr_s_wrong) {
3440 TCGv_i32 tmp;
3442 tmp = load_cpu_field(v7m.fpccr[M_REG_S]);
3443 if (s->v8m_secure) {
3444 tcg_gen_ori_i32(tmp, tmp, R_V7M_FPCCR_S_MASK);
3445 } else {
3446 tcg_gen_andi_i32(tmp, tmp, ~R_V7M_FPCCR_S_MASK);
3448 store_cpu_field(tmp, v7m.fpccr[M_REG_S]);
3449 /* Don't need to do this for any further FP insns in this TB */
3450 s->v8m_fpccr_s_wrong = false;
3453 if (s->v7m_new_fp_ctxt_needed) {
3455 * Create new FP context by updating CONTROL.FPCA, CONTROL.SFPA
3456 * and the FPSCR.
3458 TCGv_i32 control, fpscr;
3459 uint32_t bits = R_V7M_CONTROL_FPCA_MASK;
3461 fpscr = load_cpu_field(v7m.fpdscr[s->v8m_secure]);
3462 gen_helper_vfp_set_fpscr(cpu_env, fpscr);
3463 tcg_temp_free_i32(fpscr);
3465 * We don't need to arrange to end the TB, because the only
3466 * parts of FPSCR which we cache in the TB flags are the VECLEN
3467 * and VECSTRIDE, and those don't exist for M-profile.
3470 if (s->v8m_secure) {
3471 bits |= R_V7M_CONTROL_SFPA_MASK;
3473 control = load_cpu_field(v7m.control[M_REG_S]);
3474 tcg_gen_ori_i32(control, control, bits);
3475 store_cpu_field(control, v7m.control[M_REG_S]);
3476 /* Don't need to do this for any further FP insns in this TB */
3477 s->v7m_new_fp_ctxt_needed = false;
3481 if (extract32(insn, 28, 4) == 0xf) {
3483 * Encodings with T=1 (Thumb) or unconditional (ARM):
3484 * only used for the "miscellaneous VFP features" added in v8A
3485 * and v7M (and gated on the MVFR2.FPMisc field).
3487 return disas_vfp_misc_insn(s, insn);
3490 dp = ((insn & 0xf00) == 0xb00);
3491 switch ((insn >> 24) & 0xf) {
3492 case 0xe:
3493 if (insn & (1 << 4)) {
3494 /* single register transfer */
3495 rd = (insn >> 12) & 0xf;
3496 if (dp) {
3497 int size;
3498 int pass;
3500 VFP_DREG_N(rn, insn);
3501 if (insn & 0xf)
3502 return 1;
3503 if (insn & 0x00c00060
3504 && !arm_dc_feature(s, ARM_FEATURE_NEON)) {
3505 return 1;
3508 pass = (insn >> 21) & 1;
3509 if (insn & (1 << 22)) {
3510 size = 0;
3511 offset = ((insn >> 5) & 3) * 8;
3512 } else if (insn & (1 << 5)) {
3513 size = 1;
3514 offset = (insn & (1 << 6)) ? 16 : 0;
3515 } else {
3516 size = 2;
3517 offset = 0;
3519 if (insn & ARM_CP_RW_BIT) {
3520 /* vfp->arm */
3521 tmp = neon_load_reg(rn, pass);
3522 switch (size) {
3523 case 0:
3524 if (offset)
3525 tcg_gen_shri_i32(tmp, tmp, offset);
3526 if (insn & (1 << 23))
3527 gen_uxtb(tmp);
3528 else
3529 gen_sxtb(tmp);
3530 break;
3531 case 1:
3532 if (insn & (1 << 23)) {
3533 if (offset) {
3534 tcg_gen_shri_i32(tmp, tmp, 16);
3535 } else {
3536 gen_uxth(tmp);
3538 } else {
3539 if (offset) {
3540 tcg_gen_sari_i32(tmp, tmp, 16);
3541 } else {
3542 gen_sxth(tmp);
3545 break;
3546 case 2:
3547 break;
3549 store_reg(s, rd, tmp);
3550 } else {
3551 /* arm->vfp */
3552 tmp = load_reg(s, rd);
3553 if (insn & (1 << 23)) {
3554 /* VDUP */
3555 int vec_size = pass ? 16 : 8;
3556 tcg_gen_gvec_dup_i32(size, neon_reg_offset(rn, 0),
3557 vec_size, vec_size, tmp);
3558 tcg_temp_free_i32(tmp);
3559 } else {
3560 /* VMOV */
3561 switch (size) {
3562 case 0:
3563 tmp2 = neon_load_reg(rn, pass);
3564 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 8);
3565 tcg_temp_free_i32(tmp2);
3566 break;
3567 case 1:
3568 tmp2 = neon_load_reg(rn, pass);
3569 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 16);
3570 tcg_temp_free_i32(tmp2);
3571 break;
3572 case 2:
3573 break;
3575 neon_store_reg(rn, pass, tmp);
3578 } else { /* !dp */
3579 bool is_sysreg;
3581 if ((insn & 0x6f) != 0x00)
3582 return 1;
3583 rn = VFP_SREG_N(insn);
3585 is_sysreg = extract32(insn, 21, 1);
3587 if (arm_dc_feature(s, ARM_FEATURE_M)) {
3589 * The only M-profile VFP vmrs/vmsr sysreg is FPSCR.
3590 * Writes to R15 are UNPREDICTABLE; we choose to undef.
3592 if (is_sysreg && (rd == 15 || (rn >> 1) != ARM_VFP_FPSCR)) {
3593 return 1;
3597 if (insn & ARM_CP_RW_BIT) {
3598 /* vfp->arm */
3599 if (is_sysreg) {
3600 /* system register */
3601 rn >>= 1;
3603 switch (rn) {
3604 case ARM_VFP_FPSID:
3605 /* VFP2 allows access to FSID from userspace.
3606 VFP3 restricts all id registers to privileged
3607 accesses. */
3608 if (IS_USER(s)
3609 && arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3610 return 1;
3612 tmp = load_cpu_field(vfp.xregs[rn]);
3613 break;
3614 case ARM_VFP_FPEXC:
3615 if (IS_USER(s))
3616 return 1;
3617 tmp = load_cpu_field(vfp.xregs[rn]);
3618 break;
3619 case ARM_VFP_FPINST:
3620 case ARM_VFP_FPINST2:
3621 /* Not present in VFP3. */
3622 if (IS_USER(s)
3623 || arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3624 return 1;
3626 tmp = load_cpu_field(vfp.xregs[rn]);
3627 break;
3628 case ARM_VFP_FPSCR:
3629 if (rd == 15) {
3630 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
3631 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
3632 } else {
3633 tmp = tcg_temp_new_i32();
3634 gen_helper_vfp_get_fpscr(tmp, cpu_env);
3636 break;
3637 case ARM_VFP_MVFR2:
3638 if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
3639 return 1;
3641 /* fall through */
3642 case ARM_VFP_MVFR0:
3643 case ARM_VFP_MVFR1:
3644 if (IS_USER(s)
3645 || !arm_dc_feature(s, ARM_FEATURE_MVFR)) {
3646 return 1;
3648 tmp = load_cpu_field(vfp.xregs[rn]);
3649 break;
3650 default:
3651 return 1;
3653 } else {
3654 gen_mov_F0_vreg(0, rn);
3655 tmp = gen_vfp_mrs();
3657 if (rd == 15) {
3658 /* Set the 4 flag bits in the CPSR. */
3659 gen_set_nzcv(tmp);
3660 tcg_temp_free_i32(tmp);
3661 } else {
3662 store_reg(s, rd, tmp);
3664 } else {
3665 /* arm->vfp */
3666 if (is_sysreg) {
3667 rn >>= 1;
3668 /* system register */
3669 switch (rn) {
3670 case ARM_VFP_FPSID:
3671 case ARM_VFP_MVFR0:
3672 case ARM_VFP_MVFR1:
3673 /* Writes are ignored. */
3674 break;
3675 case ARM_VFP_FPSCR:
3676 tmp = load_reg(s, rd);
3677 gen_helper_vfp_set_fpscr(cpu_env, tmp);
3678 tcg_temp_free_i32(tmp);
3679 gen_lookup_tb(s);
3680 break;
3681 case ARM_VFP_FPEXC:
3682 if (IS_USER(s))
3683 return 1;
3684 /* TODO: VFP subarchitecture support.
3685 * For now, keep the EN bit only */
3686 tmp = load_reg(s, rd);
3687 tcg_gen_andi_i32(tmp, tmp, 1 << 30);
3688 store_cpu_field(tmp, vfp.xregs[rn]);
3689 gen_lookup_tb(s);
3690 break;
3691 case ARM_VFP_FPINST:
3692 case ARM_VFP_FPINST2:
3693 if (IS_USER(s)) {
3694 return 1;
3696 tmp = load_reg(s, rd);
3697 store_cpu_field(tmp, vfp.xregs[rn]);
3698 break;
3699 default:
3700 return 1;
3702 } else {
3703 tmp = load_reg(s, rd);
3704 gen_vfp_msr(tmp);
3705 gen_mov_vreg_F0(0, rn);
3709 } else {
3710 /* data processing */
3711 bool rd_is_dp = dp;
3712 bool rm_is_dp = dp;
3713 bool no_output = false;
3715 /* The opcode is in bits 23, 21, 20 and 6. */
3716 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
3717 rn = VFP_SREG_N(insn);
3719 if (op == 15) {
3720 /* rn is opcode, encoded as per VFP_SREG_N. */
3721 switch (rn) {
3722 case 0x00: /* vmov */
3723 case 0x01: /* vabs */
3724 case 0x02: /* vneg */
3725 case 0x03: /* vsqrt */
3726 break;
3728 case 0x04: /* vcvtb.f64.f16, vcvtb.f32.f16 */
3729 case 0x05: /* vcvtt.f64.f16, vcvtt.f32.f16 */
3731 * VCVTB, VCVTT: only present with the halfprec extension
3732 * UNPREDICTABLE if bit 8 is set prior to ARMv8
3733 * (we choose to UNDEF)
3735 if (dp) {
3736 if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
3737 return 1;
3739 } else {
3740 if (!dc_isar_feature(aa32_fp16_spconv, s)) {
3741 return 1;
3744 rm_is_dp = false;
3745 break;
3746 case 0x06: /* vcvtb.f16.f32, vcvtb.f16.f64 */
3747 case 0x07: /* vcvtt.f16.f32, vcvtt.f16.f64 */
3748 if (dp) {
3749 if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
3750 return 1;
3752 } else {
3753 if (!dc_isar_feature(aa32_fp16_spconv, s)) {
3754 return 1;
3757 rd_is_dp = false;
3758 break;
3760 case 0x08: case 0x0a: /* vcmp, vcmpz */
3761 case 0x09: case 0x0b: /* vcmpe, vcmpez */
3762 no_output = true;
3763 break;
3765 case 0x0c: /* vrintr */
3766 case 0x0d: /* vrintz */
3767 case 0x0e: /* vrintx */
3768 break;
3770 case 0x0f: /* vcvt double<->single */
3771 rd_is_dp = !dp;
3772 break;
3774 case 0x10: /* vcvt.fxx.u32 */
3775 case 0x11: /* vcvt.fxx.s32 */
3776 rm_is_dp = false;
3777 break;
3778 case 0x18: /* vcvtr.u32.fxx */
3779 case 0x19: /* vcvtz.u32.fxx */
3780 case 0x1a: /* vcvtr.s32.fxx */
3781 case 0x1b: /* vcvtz.s32.fxx */
3782 rd_is_dp = false;
3783 break;
3785 case 0x14: /* vcvt fp <-> fixed */
3786 case 0x15:
3787 case 0x16:
3788 case 0x17:
3789 case 0x1c:
3790 case 0x1d:
3791 case 0x1e:
3792 case 0x1f:
3793 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3794 return 1;
3796 /* Immediate frac_bits has same format as SREG_M. */
3797 rm_is_dp = false;
3798 break;
3800 case 0x13: /* vjcvt */
3801 if (!dp || !dc_isar_feature(aa32_jscvt, s)) {
3802 return 1;
3804 rd_is_dp = false;
3805 break;
3807 default:
3808 return 1;
3810 } else if (dp) {
3811 /* rn is register number */
3812 VFP_DREG_N(rn, insn);
3815 if (rd_is_dp) {
3816 VFP_DREG_D(rd, insn);
3817 } else {
3818 rd = VFP_SREG_D(insn);
3820 if (rm_is_dp) {
3821 VFP_DREG_M(rm, insn);
3822 } else {
3823 rm = VFP_SREG_M(insn);
3826 veclen = s->vec_len;
3827 if (op == 15 && rn > 3) {
3828 veclen = 0;
3831 /* Shut up compiler warnings. */
3832 delta_m = 0;
3833 delta_d = 0;
3834 bank_mask = 0;
3836 if (veclen > 0) {
3837 if (dp)
3838 bank_mask = 0xc;
3839 else
3840 bank_mask = 0x18;
3842 /* Figure out what type of vector operation this is. */
3843 if ((rd & bank_mask) == 0) {
3844 /* scalar */
3845 veclen = 0;
3846 } else {
3847 if (dp)
3848 delta_d = (s->vec_stride >> 1) + 1;
3849 else
3850 delta_d = s->vec_stride + 1;
3852 if ((rm & bank_mask) == 0) {
3853 /* mixed scalar/vector */
3854 delta_m = 0;
3855 } else {
3856 /* vector */
3857 delta_m = delta_d;
3862 /* Load the initial operands. */
3863 if (op == 15) {
3864 switch (rn) {
3865 case 0x08: case 0x09: /* Compare */
3866 gen_mov_F0_vreg(dp, rd);
3867 gen_mov_F1_vreg(dp, rm);
3868 break;
3869 case 0x0a: case 0x0b: /* Compare with zero */
3870 gen_mov_F0_vreg(dp, rd);
3871 gen_vfp_F1_ld0(dp);
3872 break;
3873 case 0x14: /* vcvt fp <-> fixed */
3874 case 0x15:
3875 case 0x16:
3876 case 0x17:
3877 case 0x1c:
3878 case 0x1d:
3879 case 0x1e:
3880 case 0x1f:
3881 /* Source and destination the same. */
3882 gen_mov_F0_vreg(dp, rd);
3883 break;
3884 default:
3885 /* One source operand. */
3886 gen_mov_F0_vreg(rm_is_dp, rm);
3887 break;
3889 } else {
3890 /* Two source operands. */
3891 gen_mov_F0_vreg(dp, rn);
3892 gen_mov_F1_vreg(dp, rm);
3895 for (;;) {
3896 /* Perform the calculation. */
3897 switch (op) {
3898 case 0: /* VMLA: fd + (fn * fm) */
3899 /* Note that order of inputs to the add matters for NaNs */
3900 gen_vfp_F1_mul(dp);
3901 gen_mov_F0_vreg(dp, rd);
3902 gen_vfp_add(dp);
3903 break;
3904 case 1: /* VMLS: fd + -(fn * fm) */
3905 gen_vfp_mul(dp);
3906 gen_vfp_F1_neg(dp);
3907 gen_mov_F0_vreg(dp, rd);
3908 gen_vfp_add(dp);
3909 break;
3910 case 2: /* VNMLS: -fd + (fn * fm) */
3911 /* Note that it isn't valid to replace (-A + B) with (B - A)
3912 * or similar plausible looking simplifications
3913 * because this will give wrong results for NaNs.
3915 gen_vfp_F1_mul(dp);
3916 gen_mov_F0_vreg(dp, rd);
3917 gen_vfp_neg(dp);
3918 gen_vfp_add(dp);
3919 break;
3920 case 3: /* VNMLA: -fd + -(fn * fm) */
3921 gen_vfp_mul(dp);
3922 gen_vfp_F1_neg(dp);
3923 gen_mov_F0_vreg(dp, rd);
3924 gen_vfp_neg(dp);
3925 gen_vfp_add(dp);
3926 break;
3927 case 4: /* mul: fn * fm */
3928 gen_vfp_mul(dp);
3929 break;
3930 case 5: /* nmul: -(fn * fm) */
3931 gen_vfp_mul(dp);
3932 gen_vfp_neg(dp);
3933 break;
3934 case 6: /* add: fn + fm */
3935 gen_vfp_add(dp);
3936 break;
3937 case 7: /* sub: fn - fm */
3938 gen_vfp_sub(dp);
3939 break;
3940 case 8: /* div: fn / fm */
3941 gen_vfp_div(dp);
3942 break;
3943 case 10: /* VFNMA : fd = muladd(-fd, fn, fm) */
3944 case 11: /* VFNMS : fd = muladd(-fd, -fn, fm) */
3945 case 12: /* VFMA : fd = muladd( fd, fn, fm) */
3946 case 13: /* VFMS : fd = muladd( fd, -fn, fm) */
3947 /* These are fused multiply-add, and must be done as one
3948 * floating point operation with no rounding between the
3949 * multiplication and addition steps.
3950 * NB that doing the negations here as separate steps is
3951 * correct : an input NaN should come out with its sign bit
3952 * flipped if it is a negated-input.
3954 if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
3955 return 1;
3957 if (dp) {
3958 TCGv_ptr fpst;
3959 TCGv_i64 frd;
3960 if (op & 1) {
3961 /* VFNMS, VFMS */
3962 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
3964 frd = tcg_temp_new_i64();
3965 tcg_gen_ld_f64(frd, cpu_env, vfp_reg_offset(dp, rd));
3966 if (op & 2) {
3967 /* VFNMA, VFNMS */
3968 gen_helper_vfp_negd(frd, frd);
3970 fpst = get_fpstatus_ptr(0);
3971 gen_helper_vfp_muladdd(cpu_F0d, cpu_F0d,
3972 cpu_F1d, frd, fpst);
3973 tcg_temp_free_ptr(fpst);
3974 tcg_temp_free_i64(frd);
3975 } else {
3976 TCGv_ptr fpst;
3977 TCGv_i32 frd;
3978 if (op & 1) {
3979 /* VFNMS, VFMS */
3980 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
3982 frd = tcg_temp_new_i32();
3983 tcg_gen_ld_f32(frd, cpu_env, vfp_reg_offset(dp, rd));
3984 if (op & 2) {
3985 gen_helper_vfp_negs(frd, frd);
3987 fpst = get_fpstatus_ptr(0);
3988 gen_helper_vfp_muladds(cpu_F0s, cpu_F0s,
3989 cpu_F1s, frd, fpst);
3990 tcg_temp_free_ptr(fpst);
3991 tcg_temp_free_i32(frd);
3993 break;
3994 case 14: /* fconst */
3995 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3996 return 1;
3999 n = (insn << 12) & 0x80000000;
4000 i = ((insn >> 12) & 0x70) | (insn & 0xf);
4001 if (dp) {
4002 if (i & 0x40)
4003 i |= 0x3f80;
4004 else
4005 i |= 0x4000;
4006 n |= i << 16;
4007 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
4008 } else {
4009 if (i & 0x40)
4010 i |= 0x780;
4011 else
4012 i |= 0x800;
4013 n |= i << 19;
4014 tcg_gen_movi_i32(cpu_F0s, n);
4016 break;
4017 case 15: /* extension space */
4018 switch (rn) {
4019 case 0: /* cpy */
4020 /* no-op */
4021 break;
4022 case 1: /* abs */
4023 gen_vfp_abs(dp);
4024 break;
4025 case 2: /* neg */
4026 gen_vfp_neg(dp);
4027 break;
4028 case 3: /* sqrt */
4029 gen_vfp_sqrt(dp);
4030 break;
4031 case 4: /* vcvtb.f32.f16, vcvtb.f64.f16 */
4033 TCGv_ptr fpst = get_fpstatus_ptr(false);
4034 TCGv_i32 ahp_mode = get_ahp_flag();
4035 tmp = gen_vfp_mrs();
4036 tcg_gen_ext16u_i32(tmp, tmp);
4037 if (dp) {
4038 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
4039 fpst, ahp_mode);
4040 } else {
4041 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
4042 fpst, ahp_mode);
4044 tcg_temp_free_i32(ahp_mode);
4045 tcg_temp_free_ptr(fpst);
4046 tcg_temp_free_i32(tmp);
4047 break;
4049 case 5: /* vcvtt.f32.f16, vcvtt.f64.f16 */
4051 TCGv_ptr fpst = get_fpstatus_ptr(false);
4052 TCGv_i32 ahp = get_ahp_flag();
4053 tmp = gen_vfp_mrs();
4054 tcg_gen_shri_i32(tmp, tmp, 16);
4055 if (dp) {
4056 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
4057 fpst, ahp);
4058 } else {
4059 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
4060 fpst, ahp);
4062 tcg_temp_free_i32(tmp);
4063 tcg_temp_free_i32(ahp);
4064 tcg_temp_free_ptr(fpst);
4065 break;
4067 case 6: /* vcvtb.f16.f32, vcvtb.f16.f64 */
4069 TCGv_ptr fpst = get_fpstatus_ptr(false);
4070 TCGv_i32 ahp = get_ahp_flag();
4071 tmp = tcg_temp_new_i32();
4073 if (dp) {
4074 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
4075 fpst, ahp);
4076 } else {
4077 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
4078 fpst, ahp);
4080 tcg_temp_free_i32(ahp);
4081 tcg_temp_free_ptr(fpst);
4082 gen_mov_F0_vreg(0, rd);
4083 tmp2 = gen_vfp_mrs();
4084 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
4085 tcg_gen_or_i32(tmp, tmp, tmp2);
4086 tcg_temp_free_i32(tmp2);
4087 gen_vfp_msr(tmp);
4088 break;
4090 case 7: /* vcvtt.f16.f32, vcvtt.f16.f64 */
4092 TCGv_ptr fpst = get_fpstatus_ptr(false);
4093 TCGv_i32 ahp = get_ahp_flag();
4094 tmp = tcg_temp_new_i32();
4095 if (dp) {
4096 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
4097 fpst, ahp);
4098 } else {
4099 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
4100 fpst, ahp);
4102 tcg_temp_free_i32(ahp);
4103 tcg_temp_free_ptr(fpst);
4104 tcg_gen_shli_i32(tmp, tmp, 16);
4105 gen_mov_F0_vreg(0, rd);
4106 tmp2 = gen_vfp_mrs();
4107 tcg_gen_ext16u_i32(tmp2, tmp2);
4108 tcg_gen_or_i32(tmp, tmp, tmp2);
4109 tcg_temp_free_i32(tmp2);
4110 gen_vfp_msr(tmp);
4111 break;
4113 case 8: /* cmp */
4114 gen_vfp_cmp(dp);
4115 break;
4116 case 9: /* cmpe */
4117 gen_vfp_cmpe(dp);
4118 break;
4119 case 10: /* cmpz */
4120 gen_vfp_cmp(dp);
4121 break;
4122 case 11: /* cmpez */
4123 gen_vfp_F1_ld0(dp);
4124 gen_vfp_cmpe(dp);
4125 break;
4126 case 12: /* vrintr */
4128 TCGv_ptr fpst = get_fpstatus_ptr(0);
4129 if (dp) {
4130 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
4131 } else {
4132 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
4134 tcg_temp_free_ptr(fpst);
4135 break;
4137 case 13: /* vrintz */
4139 TCGv_ptr fpst = get_fpstatus_ptr(0);
4140 TCGv_i32 tcg_rmode;
4141 tcg_rmode = tcg_const_i32(float_round_to_zero);
4142 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
4143 if (dp) {
4144 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
4145 } else {
4146 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
4148 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
4149 tcg_temp_free_i32(tcg_rmode);
4150 tcg_temp_free_ptr(fpst);
4151 break;
4153 case 14: /* vrintx */
4155 TCGv_ptr fpst = get_fpstatus_ptr(0);
4156 if (dp) {
4157 gen_helper_rintd_exact(cpu_F0d, cpu_F0d, fpst);
4158 } else {
4159 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpst);
4161 tcg_temp_free_ptr(fpst);
4162 break;
4164 case 15: /* single<->double conversion */
4165 if (dp) {
4166 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
4167 } else {
4168 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
4170 break;
4171 case 16: /* fuito */
4172 gen_vfp_uito(dp, 0);
4173 break;
4174 case 17: /* fsito */
4175 gen_vfp_sito(dp, 0);
4176 break;
4177 case 19: /* vjcvt */
4178 gen_helper_vjcvt(cpu_F0s, cpu_F0d, cpu_env);
4179 break;
4180 case 20: /* fshto */
4181 gen_vfp_shto(dp, 16 - rm, 0);
4182 break;
4183 case 21: /* fslto */
4184 gen_vfp_slto(dp, 32 - rm, 0);
4185 break;
4186 case 22: /* fuhto */
4187 gen_vfp_uhto(dp, 16 - rm, 0);
4188 break;
4189 case 23: /* fulto */
4190 gen_vfp_ulto(dp, 32 - rm, 0);
4191 break;
4192 case 24: /* ftoui */
4193 gen_vfp_toui(dp, 0);
4194 break;
4195 case 25: /* ftouiz */
4196 gen_vfp_touiz(dp, 0);
4197 break;
4198 case 26: /* ftosi */
4199 gen_vfp_tosi(dp, 0);
4200 break;
4201 case 27: /* ftosiz */
4202 gen_vfp_tosiz(dp, 0);
4203 break;
4204 case 28: /* ftosh */
4205 gen_vfp_tosh(dp, 16 - rm, 0);
4206 break;
4207 case 29: /* ftosl */
4208 gen_vfp_tosl(dp, 32 - rm, 0);
4209 break;
4210 case 30: /* ftouh */
4211 gen_vfp_touh(dp, 16 - rm, 0);
4212 break;
4213 case 31: /* ftoul */
4214 gen_vfp_toul(dp, 32 - rm, 0);
4215 break;
4216 default: /* undefined */
4217 g_assert_not_reached();
4219 break;
4220 default: /* undefined */
4221 return 1;
4224 /* Write back the result, if any. */
4225 if (!no_output) {
4226 gen_mov_vreg_F0(rd_is_dp, rd);
4229 /* break out of the loop if we have finished */
4230 if (veclen == 0) {
4231 break;
4234 if (op == 15 && delta_m == 0) {
4235 /* single source one-many */
4236 while (veclen--) {
4237 rd = ((rd + delta_d) & (bank_mask - 1))
4238 | (rd & bank_mask);
4239 gen_mov_vreg_F0(dp, rd);
4241 break;
4243 /* Setup the next operands. */
4244 veclen--;
4245 rd = ((rd + delta_d) & (bank_mask - 1))
4246 | (rd & bank_mask);
4248 if (op == 15) {
4249 /* One source operand. */
4250 rm = ((rm + delta_m) & (bank_mask - 1))
4251 | (rm & bank_mask);
4252 gen_mov_F0_vreg(dp, rm);
4253 } else {
4254 /* Two source operands. */
4255 rn = ((rn + delta_d) & (bank_mask - 1))
4256 | (rn & bank_mask);
4257 gen_mov_F0_vreg(dp, rn);
4258 if (delta_m) {
4259 rm = ((rm + delta_m) & (bank_mask - 1))
4260 | (rm & bank_mask);
4261 gen_mov_F1_vreg(dp, rm);
4266 break;
4267 case 0xc:
4268 case 0xd:
4269 if ((insn & 0x03e00000) == 0x00400000) {
4270 /* two-register transfer */
4271 rn = (insn >> 16) & 0xf;
4272 rd = (insn >> 12) & 0xf;
4273 if (dp) {
4274 VFP_DREG_M(rm, insn);
4275 } else {
4276 rm = VFP_SREG_M(insn);
4279 if (insn & ARM_CP_RW_BIT) {
4280 /* vfp->arm */
4281 if (dp) {
4282 gen_mov_F0_vreg(0, rm * 2);
4283 tmp = gen_vfp_mrs();
4284 store_reg(s, rd, tmp);
4285 gen_mov_F0_vreg(0, rm * 2 + 1);
4286 tmp = gen_vfp_mrs();
4287 store_reg(s, rn, tmp);
4288 } else {
4289 gen_mov_F0_vreg(0, rm);
4290 tmp = gen_vfp_mrs();
4291 store_reg(s, rd, tmp);
4292 gen_mov_F0_vreg(0, rm + 1);
4293 tmp = gen_vfp_mrs();
4294 store_reg(s, rn, tmp);
4296 } else {
4297 /* arm->vfp */
4298 if (dp) {
4299 tmp = load_reg(s, rd);
4300 gen_vfp_msr(tmp);
4301 gen_mov_vreg_F0(0, rm * 2);
4302 tmp = load_reg(s, rn);
4303 gen_vfp_msr(tmp);
4304 gen_mov_vreg_F0(0, rm * 2 + 1);
4305 } else {
4306 tmp = load_reg(s, rd);
4307 gen_vfp_msr(tmp);
4308 gen_mov_vreg_F0(0, rm);
4309 tmp = load_reg(s, rn);
4310 gen_vfp_msr(tmp);
4311 gen_mov_vreg_F0(0, rm + 1);
4314 } else {
4315 /* Load/store */
4316 rn = (insn >> 16) & 0xf;
4317 if (dp)
4318 VFP_DREG_D(rd, insn);
4319 else
4320 rd = VFP_SREG_D(insn);
4321 if ((insn & 0x01200000) == 0x01000000) {
4322 /* Single load/store */
4323 offset = (insn & 0xff) << 2;
4324 if ((insn & (1 << 23)) == 0)
4325 offset = -offset;
4326 if (s->thumb && rn == 15) {
4327 /* This is actually UNPREDICTABLE */
4328 addr = tcg_temp_new_i32();
4329 tcg_gen_movi_i32(addr, s->pc & ~2);
4330 } else {
4331 addr = load_reg(s, rn);
4333 tcg_gen_addi_i32(addr, addr, offset);
4334 if (insn & (1 << 20)) {
4335 gen_vfp_ld(s, dp, addr);
4336 gen_mov_vreg_F0(dp, rd);
4337 } else {
4338 gen_mov_F0_vreg(dp, rd);
4339 gen_vfp_st(s, dp, addr);
4341 tcg_temp_free_i32(addr);
4342 } else {
4343 /* load/store multiple */
4344 int w = insn & (1 << 21);
4345 if (dp)
4346 n = (insn >> 1) & 0x7f;
4347 else
4348 n = insn & 0xff;
4350 if (w && !(((insn >> 23) ^ (insn >> 24)) & 1)) {
4351 /* P == U , W == 1 => UNDEF */
4352 return 1;
4354 if (n == 0 || (rd + n) > 32 || (dp && n > 16)) {
4355 /* UNPREDICTABLE cases for bad immediates: we choose to
4356 * UNDEF to avoid generating huge numbers of TCG ops
4358 return 1;
4360 if (rn == 15 && w) {
4361 /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
4362 return 1;
4365 if (s->thumb && rn == 15) {
4366 /* This is actually UNPREDICTABLE */
4367 addr = tcg_temp_new_i32();
4368 tcg_gen_movi_i32(addr, s->pc & ~2);
4369 } else {
4370 addr = load_reg(s, rn);
4372 if (insn & (1 << 24)) /* pre-decrement */
4373 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
4375 if (s->v8m_stackcheck && rn == 13 && w) {
4377 * Here 'addr' is the lowest address we will store to,
4378 * and is either the old SP (if post-increment) or
4379 * the new SP (if pre-decrement). For post-increment
4380 * where the old value is below the limit and the new
4381 * value is above, it is UNKNOWN whether the limit check
4382 * triggers; we choose to trigger.
4384 gen_helper_v8m_stackcheck(cpu_env, addr);
4387 if (dp)
4388 offset = 8;
4389 else
4390 offset = 4;
4391 for (i = 0; i < n; i++) {
4392 if (insn & ARM_CP_RW_BIT) {
4393 /* load */
4394 gen_vfp_ld(s, dp, addr);
4395 gen_mov_vreg_F0(dp, rd + i);
4396 } else {
4397 /* store */
4398 gen_mov_F0_vreg(dp, rd + i);
4399 gen_vfp_st(s, dp, addr);
4401 tcg_gen_addi_i32(addr, addr, offset);
4403 if (w) {
4404 /* writeback */
4405 if (insn & (1 << 24))
4406 offset = -offset * n;
4407 else if (dp && (insn & 1))
4408 offset = 4;
4409 else
4410 offset = 0;
4412 if (offset != 0)
4413 tcg_gen_addi_i32(addr, addr, offset);
4414 store_reg(s, rn, addr);
4415 } else {
4416 tcg_temp_free_i32(addr);
4420 break;
4421 default:
4422 /* Should never happen. */
4423 return 1;
4425 return 0;
4428 static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
4430 #ifndef CONFIG_USER_ONLY
4431 return (s->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
4432 ((s->pc - 1) & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
4433 #else
4434 return true;
4435 #endif
4438 static void gen_goto_ptr(void)
4440 tcg_gen_lookup_and_goto_ptr();
4443 /* This will end the TB but doesn't guarantee we'll return to
4444 * cpu_loop_exec. Any live exit_requests will be processed as we
4445 * enter the next TB.
4447 static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
4449 if (use_goto_tb(s, dest)) {
4450 tcg_gen_goto_tb(n);
4451 gen_set_pc_im(s, dest);
4452 tcg_gen_exit_tb(s->base.tb, n);
4453 } else {
4454 gen_set_pc_im(s, dest);
4455 gen_goto_ptr();
4457 s->base.is_jmp = DISAS_NORETURN;
4460 static inline void gen_jmp (DisasContext *s, uint32_t dest)
4462 if (unlikely(is_singlestepping(s))) {
4463 /* An indirect jump so that we still trigger the debug exception. */
4464 if (s->thumb)
4465 dest |= 1;
4466 gen_bx_im(s, dest);
4467 } else {
4468 gen_goto_tb(s, 0, dest);
4472 static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
4474 if (x)
4475 tcg_gen_sari_i32(t0, t0, 16);
4476 else
4477 gen_sxth(t0);
4478 if (y)
4479 tcg_gen_sari_i32(t1, t1, 16);
4480 else
4481 gen_sxth(t1);
4482 tcg_gen_mul_i32(t0, t0, t1);
4485 /* Return the mask of PSR bits set by a MSR instruction. */
4486 static uint32_t msr_mask(DisasContext *s, int flags, int spsr)
4488 uint32_t mask;
4490 mask = 0;
4491 if (flags & (1 << 0))
4492 mask |= 0xff;
4493 if (flags & (1 << 1))
4494 mask |= 0xff00;
4495 if (flags & (1 << 2))
4496 mask |= 0xff0000;
4497 if (flags & (1 << 3))
4498 mask |= 0xff000000;
4500 /* Mask out undefined bits. */
4501 mask &= ~CPSR_RESERVED;
4502 if (!arm_dc_feature(s, ARM_FEATURE_V4T)) {
4503 mask &= ~CPSR_T;
4505 if (!arm_dc_feature(s, ARM_FEATURE_V5)) {
4506 mask &= ~CPSR_Q; /* V5TE in reality*/
4508 if (!arm_dc_feature(s, ARM_FEATURE_V6)) {
4509 mask &= ~(CPSR_E | CPSR_GE);
4511 if (!arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
4512 mask &= ~CPSR_IT;
4514 /* Mask out execution state and reserved bits. */
4515 if (!spsr) {
4516 mask &= ~(CPSR_EXEC | CPSR_RESERVED);
4518 /* Mask out privileged bits. */
4519 if (IS_USER(s))
4520 mask &= CPSR_USER;
4521 return mask;
4524 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
4525 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
4527 TCGv_i32 tmp;
4528 if (spsr) {
4529 /* ??? This is also undefined in system mode. */
4530 if (IS_USER(s))
4531 return 1;
4533 tmp = load_cpu_field(spsr);
4534 tcg_gen_andi_i32(tmp, tmp, ~mask);
4535 tcg_gen_andi_i32(t0, t0, mask);
4536 tcg_gen_or_i32(tmp, tmp, t0);
4537 store_cpu_field(tmp, spsr);
4538 } else {
4539 gen_set_cpsr(t0, mask);
4541 tcg_temp_free_i32(t0);
4542 gen_lookup_tb(s);
4543 return 0;
4546 /* Returns nonzero if access to the PSR is not permitted. */
4547 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
4549 TCGv_i32 tmp;
4550 tmp = tcg_temp_new_i32();
4551 tcg_gen_movi_i32(tmp, val);
4552 return gen_set_psr(s, mask, spsr, tmp);
4555 static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
4556 int *tgtmode, int *regno)
4558 /* Decode the r and sysm fields of MSR/MRS banked accesses into
4559 * the target mode and register number, and identify the various
4560 * unpredictable cases.
4561 * MSR (banked) and MRS (banked) are CONSTRAINED UNPREDICTABLE if:
4562 * + executed in user mode
4563 * + using R15 as the src/dest register
4564 * + accessing an unimplemented register
4565 * + accessing a register that's inaccessible at current PL/security state*
4566 * + accessing a register that you could access with a different insn
4567 * We choose to UNDEF in all these cases.
4568 * Since we don't know which of the various AArch32 modes we are in
4569 * we have to defer some checks to runtime.
4570 * Accesses to Monitor mode registers from Secure EL1 (which implies
4571 * that EL3 is AArch64) must trap to EL3.
4573 * If the access checks fail this function will emit code to take
4574 * an exception and return false. Otherwise it will return true,
4575 * and set *tgtmode and *regno appropriately.
4577 int exc_target = default_exception_el(s);
4579 /* These instructions are present only in ARMv8, or in ARMv7 with the
4580 * Virtualization Extensions.
4582 if (!arm_dc_feature(s, ARM_FEATURE_V8) &&
4583 !arm_dc_feature(s, ARM_FEATURE_EL2)) {
4584 goto undef;
4587 if (IS_USER(s) || rn == 15) {
4588 goto undef;
4591 /* The table in the v8 ARM ARM section F5.2.3 describes the encoding
4592 * of registers into (r, sysm).
4594 if (r) {
4595 /* SPSRs for other modes */
4596 switch (sysm) {
4597 case 0xe: /* SPSR_fiq */
4598 *tgtmode = ARM_CPU_MODE_FIQ;
4599 break;
4600 case 0x10: /* SPSR_irq */
4601 *tgtmode = ARM_CPU_MODE_IRQ;
4602 break;
4603 case 0x12: /* SPSR_svc */
4604 *tgtmode = ARM_CPU_MODE_SVC;
4605 break;
4606 case 0x14: /* SPSR_abt */
4607 *tgtmode = ARM_CPU_MODE_ABT;
4608 break;
4609 case 0x16: /* SPSR_und */
4610 *tgtmode = ARM_CPU_MODE_UND;
4611 break;
4612 case 0x1c: /* SPSR_mon */
4613 *tgtmode = ARM_CPU_MODE_MON;
4614 break;
4615 case 0x1e: /* SPSR_hyp */
4616 *tgtmode = ARM_CPU_MODE_HYP;
4617 break;
4618 default: /* unallocated */
4619 goto undef;
4621 /* We arbitrarily assign SPSR a register number of 16. */
4622 *regno = 16;
4623 } else {
4624 /* general purpose registers for other modes */
4625 switch (sysm) {
4626 case 0x0 ... 0x6: /* 0b00xxx : r8_usr ... r14_usr */
4627 *tgtmode = ARM_CPU_MODE_USR;
4628 *regno = sysm + 8;
4629 break;
4630 case 0x8 ... 0xe: /* 0b01xxx : r8_fiq ... r14_fiq */
4631 *tgtmode = ARM_CPU_MODE_FIQ;
4632 *regno = sysm;
4633 break;
4634 case 0x10 ... 0x11: /* 0b1000x : r14_irq, r13_irq */
4635 *tgtmode = ARM_CPU_MODE_IRQ;
4636 *regno = sysm & 1 ? 13 : 14;
4637 break;
4638 case 0x12 ... 0x13: /* 0b1001x : r14_svc, r13_svc */
4639 *tgtmode = ARM_CPU_MODE_SVC;
4640 *regno = sysm & 1 ? 13 : 14;
4641 break;
4642 case 0x14 ... 0x15: /* 0b1010x : r14_abt, r13_abt */
4643 *tgtmode = ARM_CPU_MODE_ABT;
4644 *regno = sysm & 1 ? 13 : 14;
4645 break;
4646 case 0x16 ... 0x17: /* 0b1011x : r14_und, r13_und */
4647 *tgtmode = ARM_CPU_MODE_UND;
4648 *regno = sysm & 1 ? 13 : 14;
4649 break;
4650 case 0x1c ... 0x1d: /* 0b1110x : r14_mon, r13_mon */
4651 *tgtmode = ARM_CPU_MODE_MON;
4652 *regno = sysm & 1 ? 13 : 14;
4653 break;
4654 case 0x1e ... 0x1f: /* 0b1111x : elr_hyp, r13_hyp */
4655 *tgtmode = ARM_CPU_MODE_HYP;
4656 /* Arbitrarily pick 17 for ELR_Hyp (which is not a banked LR!) */
4657 *regno = sysm & 1 ? 13 : 17;
4658 break;
4659 default: /* unallocated */
4660 goto undef;
4664 /* Catch the 'accessing inaccessible register' cases we can detect
4665 * at translate time.
4667 switch (*tgtmode) {
4668 case ARM_CPU_MODE_MON:
4669 if (!arm_dc_feature(s, ARM_FEATURE_EL3) || s->ns) {
4670 goto undef;
4672 if (s->current_el == 1) {
4673 /* If we're in Secure EL1 (which implies that EL3 is AArch64)
4674 * then accesses to Mon registers trap to EL3
4676 exc_target = 3;
4677 goto undef;
4679 break;
4680 case ARM_CPU_MODE_HYP:
4682 * SPSR_hyp and r13_hyp can only be accessed from Monitor mode
4683 * (and so we can forbid accesses from EL2 or below). elr_hyp
4684 * can be accessed also from Hyp mode, so forbid accesses from
4685 * EL0 or EL1.
4687 if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el < 2 ||
4688 (s->current_el < 3 && *regno != 17)) {
4689 goto undef;
4691 break;
4692 default:
4693 break;
4696 return true;
4698 undef:
4699 /* If we get here then some access check did not pass */
4700 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), exc_target);
4701 return false;
4704 static void gen_msr_banked(DisasContext *s, int r, int sysm, int rn)
4706 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
4707 int tgtmode = 0, regno = 0;
4709 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
4710 return;
4713 /* Sync state because msr_banked() can raise exceptions */
4714 gen_set_condexec(s);
4715 gen_set_pc_im(s, s->pc - 4);
4716 tcg_reg = load_reg(s, rn);
4717 tcg_tgtmode = tcg_const_i32(tgtmode);
4718 tcg_regno = tcg_const_i32(regno);
4719 gen_helper_msr_banked(cpu_env, tcg_reg, tcg_tgtmode, tcg_regno);
4720 tcg_temp_free_i32(tcg_tgtmode);
4721 tcg_temp_free_i32(tcg_regno);
4722 tcg_temp_free_i32(tcg_reg);
4723 s->base.is_jmp = DISAS_UPDATE;
4726 static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn)
4728 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
4729 int tgtmode = 0, regno = 0;
4731 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
4732 return;
4735 /* Sync state because mrs_banked() can raise exceptions */
4736 gen_set_condexec(s);
4737 gen_set_pc_im(s, s->pc - 4);
4738 tcg_reg = tcg_temp_new_i32();
4739 tcg_tgtmode = tcg_const_i32(tgtmode);
4740 tcg_regno = tcg_const_i32(regno);
4741 gen_helper_mrs_banked(tcg_reg, cpu_env, tcg_tgtmode, tcg_regno);
4742 tcg_temp_free_i32(tcg_tgtmode);
4743 tcg_temp_free_i32(tcg_regno);
4744 store_reg(s, rn, tcg_reg);
4745 s->base.is_jmp = DISAS_UPDATE;
4748 /* Store value to PC as for an exception return (ie don't
4749 * mask bits). The subsequent call to gen_helper_cpsr_write_eret()
4750 * will do the masking based on the new value of the Thumb bit.
4752 static void store_pc_exc_ret(DisasContext *s, TCGv_i32 pc)
4754 tcg_gen_mov_i32(cpu_R[15], pc);
4755 tcg_temp_free_i32(pc);
4758 /* Generate a v6 exception return. Marks both values as dead. */
4759 static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
4761 store_pc_exc_ret(s, pc);
4762 /* The cpsr_write_eret helper will mask the low bits of PC
4763 * appropriately depending on the new Thumb bit, so it must
4764 * be called after storing the new PC.
4766 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
4767 gen_io_start();
4769 gen_helper_cpsr_write_eret(cpu_env, cpsr);
4770 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
4771 gen_io_end();
4773 tcg_temp_free_i32(cpsr);
4774 /* Must exit loop to check un-masked IRQs */
4775 s->base.is_jmp = DISAS_EXIT;
4778 /* Generate an old-style exception return. Marks pc as dead. */
4779 static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
4781 gen_rfe(s, pc, load_cpu_field(spsr));
4785 * For WFI we will halt the vCPU until an IRQ. For WFE and YIELD we
4786 * only call the helper when running single threaded TCG code to ensure
4787 * the next round-robin scheduled vCPU gets a crack. In MTTCG mode we
4788 * just skip this instruction. Currently the SEV/SEVL instructions
4789 * which are *one* of many ways to wake the CPU from WFE are not
4790 * implemented so we can't sleep like WFI does.
4792 static void gen_nop_hint(DisasContext *s, int val)
4794 switch (val) {
4795 /* When running in MTTCG we don't generate jumps to the yield and
4796 * WFE helpers as it won't affect the scheduling of other vCPUs.
4797 * If we wanted to more completely model WFE/SEV so we don't busy
4798 * spin unnecessarily we would need to do something more involved.
4800 case 1: /* yield */
4801 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
4802 gen_set_pc_im(s, s->pc);
4803 s->base.is_jmp = DISAS_YIELD;
4805 break;
4806 case 3: /* wfi */
4807 gen_set_pc_im(s, s->pc);
4808 s->base.is_jmp = DISAS_WFI;
4809 break;
4810 case 2: /* wfe */
4811 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
4812 gen_set_pc_im(s, s->pc);
4813 s->base.is_jmp = DISAS_WFE;
4815 break;
4816 case 4: /* sev */
4817 case 5: /* sevl */
4818 /* TODO: Implement SEV, SEVL and WFE. May help SMP performance. */
4819 default: /* nop */
4820 break;
4824 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
4826 static inline void gen_neon_add(int size, TCGv_i32 t0, TCGv_i32 t1)
4828 switch (size) {
4829 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
4830 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
4831 case 2: tcg_gen_add_i32(t0, t0, t1); break;
4832 default: abort();
4836 static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
4838 switch (size) {
4839 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
4840 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
4841 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
4842 default: return;
4846 /* 32-bit pairwise ops end up the same as the elementwise versions. */
4847 #define gen_helper_neon_pmax_s32 tcg_gen_smax_i32
4848 #define gen_helper_neon_pmax_u32 tcg_gen_umax_i32
4849 #define gen_helper_neon_pmin_s32 tcg_gen_smin_i32
4850 #define gen_helper_neon_pmin_u32 tcg_gen_umin_i32
4852 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
4853 switch ((size << 1) | u) { \
4854 case 0: \
4855 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
4856 break; \
4857 case 1: \
4858 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
4859 break; \
4860 case 2: \
4861 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
4862 break; \
4863 case 3: \
4864 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
4865 break; \
4866 case 4: \
4867 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
4868 break; \
4869 case 5: \
4870 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
4871 break; \
4872 default: return 1; \
4873 }} while (0)
4875 #define GEN_NEON_INTEGER_OP(name) do { \
4876 switch ((size << 1) | u) { \
4877 case 0: \
4878 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
4879 break; \
4880 case 1: \
4881 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
4882 break; \
4883 case 2: \
4884 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
4885 break; \
4886 case 3: \
4887 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
4888 break; \
4889 case 4: \
4890 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
4891 break; \
4892 case 5: \
4893 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
4894 break; \
4895 default: return 1; \
4896 }} while (0)
4898 static TCGv_i32 neon_load_scratch(int scratch)
4900 TCGv_i32 tmp = tcg_temp_new_i32();
4901 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
4902 return tmp;
4905 static void neon_store_scratch(int scratch, TCGv_i32 var)
4907 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
4908 tcg_temp_free_i32(var);
4911 static inline TCGv_i32 neon_get_scalar(int size, int reg)
4913 TCGv_i32 tmp;
4914 if (size == 1) {
4915 tmp = neon_load_reg(reg & 7, reg >> 4);
4916 if (reg & 8) {
4917 gen_neon_dup_high16(tmp);
4918 } else {
4919 gen_neon_dup_low16(tmp);
4921 } else {
4922 tmp = neon_load_reg(reg & 15, reg >> 4);
4924 return tmp;
4927 static int gen_neon_unzip(int rd, int rm, int size, int q)
4929 TCGv_ptr pd, pm;
4931 if (!q && size == 2) {
4932 return 1;
4934 pd = vfp_reg_ptr(true, rd);
4935 pm = vfp_reg_ptr(true, rm);
4936 if (q) {
4937 switch (size) {
4938 case 0:
4939 gen_helper_neon_qunzip8(pd, pm);
4940 break;
4941 case 1:
4942 gen_helper_neon_qunzip16(pd, pm);
4943 break;
4944 case 2:
4945 gen_helper_neon_qunzip32(pd, pm);
4946 break;
4947 default:
4948 abort();
4950 } else {
4951 switch (size) {
4952 case 0:
4953 gen_helper_neon_unzip8(pd, pm);
4954 break;
4955 case 1:
4956 gen_helper_neon_unzip16(pd, pm);
4957 break;
4958 default:
4959 abort();
4962 tcg_temp_free_ptr(pd);
4963 tcg_temp_free_ptr(pm);
4964 return 0;
4967 static int gen_neon_zip(int rd, int rm, int size, int q)
4969 TCGv_ptr pd, pm;
4971 if (!q && size == 2) {
4972 return 1;
4974 pd = vfp_reg_ptr(true, rd);
4975 pm = vfp_reg_ptr(true, rm);
4976 if (q) {
4977 switch (size) {
4978 case 0:
4979 gen_helper_neon_qzip8(pd, pm);
4980 break;
4981 case 1:
4982 gen_helper_neon_qzip16(pd, pm);
4983 break;
4984 case 2:
4985 gen_helper_neon_qzip32(pd, pm);
4986 break;
4987 default:
4988 abort();
4990 } else {
4991 switch (size) {
4992 case 0:
4993 gen_helper_neon_zip8(pd, pm);
4994 break;
4995 case 1:
4996 gen_helper_neon_zip16(pd, pm);
4997 break;
4998 default:
4999 abort();
5002 tcg_temp_free_ptr(pd);
5003 tcg_temp_free_ptr(pm);
5004 return 0;
5007 static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
5009 TCGv_i32 rd, tmp;
5011 rd = tcg_temp_new_i32();
5012 tmp = tcg_temp_new_i32();
5014 tcg_gen_shli_i32(rd, t0, 8);
5015 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
5016 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
5017 tcg_gen_or_i32(rd, rd, tmp);
5019 tcg_gen_shri_i32(t1, t1, 8);
5020 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
5021 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
5022 tcg_gen_or_i32(t1, t1, tmp);
5023 tcg_gen_mov_i32(t0, rd);
5025 tcg_temp_free_i32(tmp);
5026 tcg_temp_free_i32(rd);
5029 static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
5031 TCGv_i32 rd, tmp;
5033 rd = tcg_temp_new_i32();
5034 tmp = tcg_temp_new_i32();
5036 tcg_gen_shli_i32(rd, t0, 16);
5037 tcg_gen_andi_i32(tmp, t1, 0xffff);
5038 tcg_gen_or_i32(rd, rd, tmp);
5039 tcg_gen_shri_i32(t1, t1, 16);
5040 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
5041 tcg_gen_or_i32(t1, t1, tmp);
5042 tcg_gen_mov_i32(t0, rd);
5044 tcg_temp_free_i32(tmp);
5045 tcg_temp_free_i32(rd);
5049 static struct {
5050 int nregs;
5051 int interleave;
5052 int spacing;
5053 } const neon_ls_element_type[11] = {
5054 {1, 4, 1},
5055 {1, 4, 2},
5056 {4, 1, 1},
5057 {2, 2, 2},
5058 {1, 3, 1},
5059 {1, 3, 2},
5060 {3, 1, 1},
5061 {1, 1, 1},
5062 {1, 2, 1},
5063 {1, 2, 2},
5064 {2, 1, 1}
5067 /* Translate a NEON load/store element instruction. Return nonzero if the
5068 instruction is invalid. */
5069 static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
5071 int rd, rn, rm;
5072 int op;
5073 int nregs;
5074 int interleave;
5075 int spacing;
5076 int stride;
5077 int size;
5078 int reg;
5079 int load;
5080 int n;
5081 int vec_size;
5082 int mmu_idx;
5083 TCGMemOp endian;
5084 TCGv_i32 addr;
5085 TCGv_i32 tmp;
5086 TCGv_i32 tmp2;
5087 TCGv_i64 tmp64;
5089 /* FIXME: this access check should not take precedence over UNDEF
5090 * for invalid encodings; we will generate incorrect syndrome information
5091 * for attempts to execute invalid vfp/neon encodings with FP disabled.
5093 if (s->fp_excp_el) {
5094 gen_exception_insn(s, 4, EXCP_UDEF,
5095 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
5096 return 0;
5099 if (!s->vfp_enabled)
5100 return 1;
5101 VFP_DREG_D(rd, insn);
5102 rn = (insn >> 16) & 0xf;
5103 rm = insn & 0xf;
5104 load = (insn & (1 << 21)) != 0;
5105 endian = s->be_data;
5106 mmu_idx = get_mem_index(s);
5107 if ((insn & (1 << 23)) == 0) {
5108 /* Load store all elements. */
5109 op = (insn >> 8) & 0xf;
5110 size = (insn >> 6) & 3;
5111 if (op > 10)
5112 return 1;
5113 /* Catch UNDEF cases for bad values of align field */
5114 switch (op & 0xc) {
5115 case 4:
5116 if (((insn >> 5) & 1) == 1) {
5117 return 1;
5119 break;
5120 case 8:
5121 if (((insn >> 4) & 3) == 3) {
5122 return 1;
5124 break;
5125 default:
5126 break;
5128 nregs = neon_ls_element_type[op].nregs;
5129 interleave = neon_ls_element_type[op].interleave;
5130 spacing = neon_ls_element_type[op].spacing;
5131 if (size == 3 && (interleave | spacing) != 1) {
5132 return 1;
5134 /* For our purposes, bytes are always little-endian. */
5135 if (size == 0) {
5136 endian = MO_LE;
5138 /* Consecutive little-endian elements from a single register
5139 * can be promoted to a larger little-endian operation.
5141 if (interleave == 1 && endian == MO_LE) {
5142 size = 3;
5144 tmp64 = tcg_temp_new_i64();
5145 addr = tcg_temp_new_i32();
5146 tmp2 = tcg_const_i32(1 << size);
5147 load_reg_var(s, addr, rn);
5148 for (reg = 0; reg < nregs; reg++) {
5149 for (n = 0; n < 8 >> size; n++) {
5150 int xs;
5151 for (xs = 0; xs < interleave; xs++) {
5152 int tt = rd + reg + spacing * xs;
5154 if (load) {
5155 gen_aa32_ld_i64(s, tmp64, addr, mmu_idx, endian | size);
5156 neon_store_element64(tt, n, size, tmp64);
5157 } else {
5158 neon_load_element64(tmp64, tt, n, size);
5159 gen_aa32_st_i64(s, tmp64, addr, mmu_idx, endian | size);
5161 tcg_gen_add_i32(addr, addr, tmp2);
5165 tcg_temp_free_i32(addr);
5166 tcg_temp_free_i32(tmp2);
5167 tcg_temp_free_i64(tmp64);
5168 stride = nregs * interleave * 8;
5169 } else {
5170 size = (insn >> 10) & 3;
5171 if (size == 3) {
5172 /* Load single element to all lanes. */
5173 int a = (insn >> 4) & 1;
5174 if (!load) {
5175 return 1;
5177 size = (insn >> 6) & 3;
5178 nregs = ((insn >> 8) & 3) + 1;
5180 if (size == 3) {
5181 if (nregs != 4 || a == 0) {
5182 return 1;
5184 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
5185 size = 2;
5187 if (nregs == 1 && a == 1 && size == 0) {
5188 return 1;
5190 if (nregs == 3 && a == 1) {
5191 return 1;
5193 addr = tcg_temp_new_i32();
5194 load_reg_var(s, addr, rn);
5196 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write.
5197 * VLD2/3/4 to all lanes: bit 5 indicates register stride.
5199 stride = (insn & (1 << 5)) ? 2 : 1;
5200 vec_size = nregs == 1 ? stride * 8 : 8;
5202 tmp = tcg_temp_new_i32();
5203 for (reg = 0; reg < nregs; reg++) {
5204 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
5205 s->be_data | size);
5206 if ((rd & 1) && vec_size == 16) {
5207 /* We cannot write 16 bytes at once because the
5208 * destination is unaligned.
5210 tcg_gen_gvec_dup_i32(size, neon_reg_offset(rd, 0),
5211 8, 8, tmp);
5212 tcg_gen_gvec_mov(0, neon_reg_offset(rd + 1, 0),
5213 neon_reg_offset(rd, 0), 8, 8);
5214 } else {
5215 tcg_gen_gvec_dup_i32(size, neon_reg_offset(rd, 0),
5216 vec_size, vec_size, tmp);
5218 tcg_gen_addi_i32(addr, addr, 1 << size);
5219 rd += stride;
5221 tcg_temp_free_i32(tmp);
5222 tcg_temp_free_i32(addr);
5223 stride = (1 << size) * nregs;
5224 } else {
5225 /* Single element. */
5226 int idx = (insn >> 4) & 0xf;
5227 int reg_idx;
5228 switch (size) {
5229 case 0:
5230 reg_idx = (insn >> 5) & 7;
5231 stride = 1;
5232 break;
5233 case 1:
5234 reg_idx = (insn >> 6) & 3;
5235 stride = (insn & (1 << 5)) ? 2 : 1;
5236 break;
5237 case 2:
5238 reg_idx = (insn >> 7) & 1;
5239 stride = (insn & (1 << 6)) ? 2 : 1;
5240 break;
5241 default:
5242 abort();
5244 nregs = ((insn >> 8) & 3) + 1;
5245 /* Catch the UNDEF cases. This is unavoidably a bit messy. */
5246 switch (nregs) {
5247 case 1:
5248 if (((idx & (1 << size)) != 0) ||
5249 (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
5250 return 1;
5252 break;
5253 case 3:
5254 if ((idx & 1) != 0) {
5255 return 1;
5257 /* fall through */
5258 case 2:
5259 if (size == 2 && (idx & 2) != 0) {
5260 return 1;
5262 break;
5263 case 4:
5264 if ((size == 2) && ((idx & 3) == 3)) {
5265 return 1;
5267 break;
5268 default:
5269 abort();
5271 if ((rd + stride * (nregs - 1)) > 31) {
5272 /* Attempts to write off the end of the register file
5273 * are UNPREDICTABLE; we choose to UNDEF because otherwise
5274 * the neon_load_reg() would write off the end of the array.
5276 return 1;
5278 tmp = tcg_temp_new_i32();
5279 addr = tcg_temp_new_i32();
5280 load_reg_var(s, addr, rn);
5281 for (reg = 0; reg < nregs; reg++) {
5282 if (load) {
5283 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
5284 s->be_data | size);
5285 neon_store_element(rd, reg_idx, size, tmp);
5286 } else { /* Store */
5287 neon_load_element(tmp, rd, reg_idx, size);
5288 gen_aa32_st_i32(s, tmp, addr, get_mem_index(s),
5289 s->be_data | size);
5291 rd += stride;
5292 tcg_gen_addi_i32(addr, addr, 1 << size);
5294 tcg_temp_free_i32(addr);
5295 tcg_temp_free_i32(tmp);
5296 stride = nregs * (1 << size);
5299 if (rm != 15) {
5300 TCGv_i32 base;
5302 base = load_reg(s, rn);
5303 if (rm == 13) {
5304 tcg_gen_addi_i32(base, base, stride);
5305 } else {
5306 TCGv_i32 index;
5307 index = load_reg(s, rm);
5308 tcg_gen_add_i32(base, base, index);
5309 tcg_temp_free_i32(index);
5311 store_reg(s, rn, base);
5313 return 0;
5316 static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src)
5318 switch (size) {
5319 case 0: gen_helper_neon_narrow_u8(dest, src); break;
5320 case 1: gen_helper_neon_narrow_u16(dest, src); break;
5321 case 2: tcg_gen_extrl_i64_i32(dest, src); break;
5322 default: abort();
5326 static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
5328 switch (size) {
5329 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
5330 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
5331 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
5332 default: abort();
5336 static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src)
5338 switch (size) {
5339 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
5340 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
5341 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
5342 default: abort();
5346 static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
5348 switch (size) {
5349 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
5350 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
5351 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
5352 default: abort();
5356 static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift,
5357 int q, int u)
5359 if (q) {
5360 if (u) {
5361 switch (size) {
5362 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
5363 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
5364 default: abort();
5366 } else {
5367 switch (size) {
5368 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
5369 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
5370 default: abort();
5373 } else {
5374 if (u) {
5375 switch (size) {
5376 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
5377 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
5378 default: abort();
5380 } else {
5381 switch (size) {
5382 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
5383 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
5384 default: abort();
5390 static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
5392 if (u) {
5393 switch (size) {
5394 case 0: gen_helper_neon_widen_u8(dest, src); break;
5395 case 1: gen_helper_neon_widen_u16(dest, src); break;
5396 case 2: tcg_gen_extu_i32_i64(dest, src); break;
5397 default: abort();
5399 } else {
5400 switch (size) {
5401 case 0: gen_helper_neon_widen_s8(dest, src); break;
5402 case 1: gen_helper_neon_widen_s16(dest, src); break;
5403 case 2: tcg_gen_ext_i32_i64(dest, src); break;
5404 default: abort();
5407 tcg_temp_free_i32(src);
5410 static inline void gen_neon_addl(int size)
5412 switch (size) {
5413 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
5414 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
5415 case 2: tcg_gen_add_i64(CPU_V001); break;
5416 default: abort();
5420 static inline void gen_neon_subl(int size)
5422 switch (size) {
5423 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
5424 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
5425 case 2: tcg_gen_sub_i64(CPU_V001); break;
5426 default: abort();
5430 static inline void gen_neon_negl(TCGv_i64 var, int size)
5432 switch (size) {
5433 case 0: gen_helper_neon_negl_u16(var, var); break;
5434 case 1: gen_helper_neon_negl_u32(var, var); break;
5435 case 2:
5436 tcg_gen_neg_i64(var, var);
5437 break;
5438 default: abort();
5442 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
5444 switch (size) {
5445 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
5446 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
5447 default: abort();
5451 static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b,
5452 int size, int u)
5454 TCGv_i64 tmp;
5456 switch ((size << 1) | u) {
5457 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
5458 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
5459 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
5460 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
5461 case 4:
5462 tmp = gen_muls_i64_i32(a, b);
5463 tcg_gen_mov_i64(dest, tmp);
5464 tcg_temp_free_i64(tmp);
5465 break;
5466 case 5:
5467 tmp = gen_mulu_i64_i32(a, b);
5468 tcg_gen_mov_i64(dest, tmp);
5469 tcg_temp_free_i64(tmp);
5470 break;
5471 default: abort();
5474 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
5475 Don't forget to clean them now. */
5476 if (size < 2) {
5477 tcg_temp_free_i32(a);
5478 tcg_temp_free_i32(b);
5482 static void gen_neon_narrow_op(int op, int u, int size,
5483 TCGv_i32 dest, TCGv_i64 src)
5485 if (op) {
5486 if (u) {
5487 gen_neon_unarrow_sats(size, dest, src);
5488 } else {
5489 gen_neon_narrow(size, dest, src);
5491 } else {
5492 if (u) {
5493 gen_neon_narrow_satu(size, dest, src);
5494 } else {
5495 gen_neon_narrow_sats(size, dest, src);
5500 /* Symbolic constants for op fields for Neon 3-register same-length.
5501 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
5502 * table A7-9.
5504 #define NEON_3R_VHADD 0
5505 #define NEON_3R_VQADD 1
5506 #define NEON_3R_VRHADD 2
5507 #define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
5508 #define NEON_3R_VHSUB 4
5509 #define NEON_3R_VQSUB 5
5510 #define NEON_3R_VCGT 6
5511 #define NEON_3R_VCGE 7
5512 #define NEON_3R_VSHL 8
5513 #define NEON_3R_VQSHL 9
5514 #define NEON_3R_VRSHL 10
5515 #define NEON_3R_VQRSHL 11
5516 #define NEON_3R_VMAX 12
5517 #define NEON_3R_VMIN 13
5518 #define NEON_3R_VABD 14
5519 #define NEON_3R_VABA 15
5520 #define NEON_3R_VADD_VSUB 16
5521 #define NEON_3R_VTST_VCEQ 17
5522 #define NEON_3R_VML 18 /* VMLA, VMLS */
5523 #define NEON_3R_VMUL 19
5524 #define NEON_3R_VPMAX 20
5525 #define NEON_3R_VPMIN 21
5526 #define NEON_3R_VQDMULH_VQRDMULH 22
5527 #define NEON_3R_VPADD_VQRDMLAH 23
5528 #define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */
5529 #define NEON_3R_VFM_VQRDMLSH 25 /* VFMA, VFMS, VQRDMLSH */
5530 #define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
5531 #define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
5532 #define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
5533 #define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
5534 #define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
5535 #define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */
5537 static const uint8_t neon_3r_sizes[] = {
5538 [NEON_3R_VHADD] = 0x7,
5539 [NEON_3R_VQADD] = 0xf,
5540 [NEON_3R_VRHADD] = 0x7,
5541 [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
5542 [NEON_3R_VHSUB] = 0x7,
5543 [NEON_3R_VQSUB] = 0xf,
5544 [NEON_3R_VCGT] = 0x7,
5545 [NEON_3R_VCGE] = 0x7,
5546 [NEON_3R_VSHL] = 0xf,
5547 [NEON_3R_VQSHL] = 0xf,
5548 [NEON_3R_VRSHL] = 0xf,
5549 [NEON_3R_VQRSHL] = 0xf,
5550 [NEON_3R_VMAX] = 0x7,
5551 [NEON_3R_VMIN] = 0x7,
5552 [NEON_3R_VABD] = 0x7,
5553 [NEON_3R_VABA] = 0x7,
5554 [NEON_3R_VADD_VSUB] = 0xf,
5555 [NEON_3R_VTST_VCEQ] = 0x7,
5556 [NEON_3R_VML] = 0x7,
5557 [NEON_3R_VMUL] = 0x7,
5558 [NEON_3R_VPMAX] = 0x7,
5559 [NEON_3R_VPMIN] = 0x7,
5560 [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
5561 [NEON_3R_VPADD_VQRDMLAH] = 0x7,
5562 [NEON_3R_SHA] = 0xf, /* size field encodes op type */
5563 [NEON_3R_VFM_VQRDMLSH] = 0x7, /* For VFM, size bit 1 encodes op */
5564 [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
5565 [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
5566 [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
5567 [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
5568 [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
5569 [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */
5572 /* Symbolic constants for op fields for Neon 2-register miscellaneous.
5573 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
5574 * table A7-13.
5576 #define NEON_2RM_VREV64 0
5577 #define NEON_2RM_VREV32 1
5578 #define NEON_2RM_VREV16 2
5579 #define NEON_2RM_VPADDL 4
5580 #define NEON_2RM_VPADDL_U 5
5581 #define NEON_2RM_AESE 6 /* Includes AESD */
5582 #define NEON_2RM_AESMC 7 /* Includes AESIMC */
5583 #define NEON_2RM_VCLS 8
5584 #define NEON_2RM_VCLZ 9
5585 #define NEON_2RM_VCNT 10
5586 #define NEON_2RM_VMVN 11
5587 #define NEON_2RM_VPADAL 12
5588 #define NEON_2RM_VPADAL_U 13
5589 #define NEON_2RM_VQABS 14
5590 #define NEON_2RM_VQNEG 15
5591 #define NEON_2RM_VCGT0 16
5592 #define NEON_2RM_VCGE0 17
5593 #define NEON_2RM_VCEQ0 18
5594 #define NEON_2RM_VCLE0 19
5595 #define NEON_2RM_VCLT0 20
5596 #define NEON_2RM_SHA1H 21
5597 #define NEON_2RM_VABS 22
5598 #define NEON_2RM_VNEG 23
5599 #define NEON_2RM_VCGT0_F 24
5600 #define NEON_2RM_VCGE0_F 25
5601 #define NEON_2RM_VCEQ0_F 26
5602 #define NEON_2RM_VCLE0_F 27
5603 #define NEON_2RM_VCLT0_F 28
5604 #define NEON_2RM_VABS_F 30
5605 #define NEON_2RM_VNEG_F 31
5606 #define NEON_2RM_VSWP 32
5607 #define NEON_2RM_VTRN 33
5608 #define NEON_2RM_VUZP 34
5609 #define NEON_2RM_VZIP 35
5610 #define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
5611 #define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
5612 #define NEON_2RM_VSHLL 38
5613 #define NEON_2RM_SHA1SU1 39 /* Includes SHA256SU0 */
5614 #define NEON_2RM_VRINTN 40
5615 #define NEON_2RM_VRINTX 41
5616 #define NEON_2RM_VRINTA 42
5617 #define NEON_2RM_VRINTZ 43
5618 #define NEON_2RM_VCVT_F16_F32 44
5619 #define NEON_2RM_VRINTM 45
5620 #define NEON_2RM_VCVT_F32_F16 46
5621 #define NEON_2RM_VRINTP 47
5622 #define NEON_2RM_VCVTAU 48
5623 #define NEON_2RM_VCVTAS 49
5624 #define NEON_2RM_VCVTNU 50
5625 #define NEON_2RM_VCVTNS 51
5626 #define NEON_2RM_VCVTPU 52
5627 #define NEON_2RM_VCVTPS 53
5628 #define NEON_2RM_VCVTMU 54
5629 #define NEON_2RM_VCVTMS 55
5630 #define NEON_2RM_VRECPE 56
5631 #define NEON_2RM_VRSQRTE 57
5632 #define NEON_2RM_VRECPE_F 58
5633 #define NEON_2RM_VRSQRTE_F 59
5634 #define NEON_2RM_VCVT_FS 60
5635 #define NEON_2RM_VCVT_FU 61
5636 #define NEON_2RM_VCVT_SF 62
5637 #define NEON_2RM_VCVT_UF 63
5639 static int neon_2rm_is_float_op(int op)
5641 /* Return true if this neon 2reg-misc op is float-to-float */
5642 return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
5643 (op >= NEON_2RM_VRINTN && op <= NEON_2RM_VRINTZ) ||
5644 op == NEON_2RM_VRINTM ||
5645 (op >= NEON_2RM_VRINTP && op <= NEON_2RM_VCVTMS) ||
5646 op >= NEON_2RM_VRECPE_F);
5649 static bool neon_2rm_is_v8_op(int op)
5651 /* Return true if this neon 2reg-misc op is ARMv8 and up */
5652 switch (op) {
5653 case NEON_2RM_VRINTN:
5654 case NEON_2RM_VRINTA:
5655 case NEON_2RM_VRINTM:
5656 case NEON_2RM_VRINTP:
5657 case NEON_2RM_VRINTZ:
5658 case NEON_2RM_VRINTX:
5659 case NEON_2RM_VCVTAU:
5660 case NEON_2RM_VCVTAS:
5661 case NEON_2RM_VCVTNU:
5662 case NEON_2RM_VCVTNS:
5663 case NEON_2RM_VCVTPU:
5664 case NEON_2RM_VCVTPS:
5665 case NEON_2RM_VCVTMU:
5666 case NEON_2RM_VCVTMS:
5667 return true;
5668 default:
5669 return false;
5673 /* Each entry in this array has bit n set if the insn allows
5674 * size value n (otherwise it will UNDEF). Since unallocated
5675 * op values will have no bits set they always UNDEF.
5677 static const uint8_t neon_2rm_sizes[] = {
5678 [NEON_2RM_VREV64] = 0x7,
5679 [NEON_2RM_VREV32] = 0x3,
5680 [NEON_2RM_VREV16] = 0x1,
5681 [NEON_2RM_VPADDL] = 0x7,
5682 [NEON_2RM_VPADDL_U] = 0x7,
5683 [NEON_2RM_AESE] = 0x1,
5684 [NEON_2RM_AESMC] = 0x1,
5685 [NEON_2RM_VCLS] = 0x7,
5686 [NEON_2RM_VCLZ] = 0x7,
5687 [NEON_2RM_VCNT] = 0x1,
5688 [NEON_2RM_VMVN] = 0x1,
5689 [NEON_2RM_VPADAL] = 0x7,
5690 [NEON_2RM_VPADAL_U] = 0x7,
5691 [NEON_2RM_VQABS] = 0x7,
5692 [NEON_2RM_VQNEG] = 0x7,
5693 [NEON_2RM_VCGT0] = 0x7,
5694 [NEON_2RM_VCGE0] = 0x7,
5695 [NEON_2RM_VCEQ0] = 0x7,
5696 [NEON_2RM_VCLE0] = 0x7,
5697 [NEON_2RM_VCLT0] = 0x7,
5698 [NEON_2RM_SHA1H] = 0x4,
5699 [NEON_2RM_VABS] = 0x7,
5700 [NEON_2RM_VNEG] = 0x7,
5701 [NEON_2RM_VCGT0_F] = 0x4,
5702 [NEON_2RM_VCGE0_F] = 0x4,
5703 [NEON_2RM_VCEQ0_F] = 0x4,
5704 [NEON_2RM_VCLE0_F] = 0x4,
5705 [NEON_2RM_VCLT0_F] = 0x4,
5706 [NEON_2RM_VABS_F] = 0x4,
5707 [NEON_2RM_VNEG_F] = 0x4,
5708 [NEON_2RM_VSWP] = 0x1,
5709 [NEON_2RM_VTRN] = 0x7,
5710 [NEON_2RM_VUZP] = 0x7,
5711 [NEON_2RM_VZIP] = 0x7,
5712 [NEON_2RM_VMOVN] = 0x7,
5713 [NEON_2RM_VQMOVN] = 0x7,
5714 [NEON_2RM_VSHLL] = 0x7,
5715 [NEON_2RM_SHA1SU1] = 0x4,
5716 [NEON_2RM_VRINTN] = 0x4,
5717 [NEON_2RM_VRINTX] = 0x4,
5718 [NEON_2RM_VRINTA] = 0x4,
5719 [NEON_2RM_VRINTZ] = 0x4,
5720 [NEON_2RM_VCVT_F16_F32] = 0x2,
5721 [NEON_2RM_VRINTM] = 0x4,
5722 [NEON_2RM_VCVT_F32_F16] = 0x2,
5723 [NEON_2RM_VRINTP] = 0x4,
5724 [NEON_2RM_VCVTAU] = 0x4,
5725 [NEON_2RM_VCVTAS] = 0x4,
5726 [NEON_2RM_VCVTNU] = 0x4,
5727 [NEON_2RM_VCVTNS] = 0x4,
5728 [NEON_2RM_VCVTPU] = 0x4,
5729 [NEON_2RM_VCVTPS] = 0x4,
5730 [NEON_2RM_VCVTMU] = 0x4,
5731 [NEON_2RM_VCVTMS] = 0x4,
5732 [NEON_2RM_VRECPE] = 0x4,
5733 [NEON_2RM_VRSQRTE] = 0x4,
5734 [NEON_2RM_VRECPE_F] = 0x4,
5735 [NEON_2RM_VRSQRTE_F] = 0x4,
5736 [NEON_2RM_VCVT_FS] = 0x4,
5737 [NEON_2RM_VCVT_FU] = 0x4,
5738 [NEON_2RM_VCVT_SF] = 0x4,
5739 [NEON_2RM_VCVT_UF] = 0x4,
5743 /* Expand v8.1 simd helper. */
5744 static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
5745 int q, int rd, int rn, int rm)
5747 if (dc_isar_feature(aa32_rdm, s)) {
5748 int opr_sz = (1 + q) * 8;
5749 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
5750 vfp_reg_offset(1, rn),
5751 vfp_reg_offset(1, rm), cpu_env,
5752 opr_sz, opr_sz, 0, fn);
5753 return 0;
5755 return 1;
5759 * Expanders for VBitOps_VBIF, VBIT, VBSL.
5761 static void gen_bsl_i64(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
5763 tcg_gen_xor_i64(rn, rn, rm);
5764 tcg_gen_and_i64(rn, rn, rd);
5765 tcg_gen_xor_i64(rd, rm, rn);
5768 static void gen_bit_i64(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
5770 tcg_gen_xor_i64(rn, rn, rd);
5771 tcg_gen_and_i64(rn, rn, rm);
5772 tcg_gen_xor_i64(rd, rd, rn);
5775 static void gen_bif_i64(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
5777 tcg_gen_xor_i64(rn, rn, rd);
5778 tcg_gen_andc_i64(rn, rn, rm);
5779 tcg_gen_xor_i64(rd, rd, rn);
5782 static void gen_bsl_vec(unsigned vece, TCGv_vec rd, TCGv_vec rn, TCGv_vec rm)
5784 tcg_gen_xor_vec(vece, rn, rn, rm);
5785 tcg_gen_and_vec(vece, rn, rn, rd);
5786 tcg_gen_xor_vec(vece, rd, rm, rn);
5789 static void gen_bit_vec(unsigned vece, TCGv_vec rd, TCGv_vec rn, TCGv_vec rm)
5791 tcg_gen_xor_vec(vece, rn, rn, rd);
5792 tcg_gen_and_vec(vece, rn, rn, rm);
5793 tcg_gen_xor_vec(vece, rd, rd, rn);
5796 static void gen_bif_vec(unsigned vece, TCGv_vec rd, TCGv_vec rn, TCGv_vec rm)
5798 tcg_gen_xor_vec(vece, rn, rn, rd);
5799 tcg_gen_andc_vec(vece, rn, rn, rm);
5800 tcg_gen_xor_vec(vece, rd, rd, rn);
5803 const GVecGen3 bsl_op = {
5804 .fni8 = gen_bsl_i64,
5805 .fniv = gen_bsl_vec,
5806 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5807 .load_dest = true
5810 const GVecGen3 bit_op = {
5811 .fni8 = gen_bit_i64,
5812 .fniv = gen_bit_vec,
5813 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5814 .load_dest = true
5817 const GVecGen3 bif_op = {
5818 .fni8 = gen_bif_i64,
5819 .fniv = gen_bif_vec,
5820 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5821 .load_dest = true
5824 static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5826 tcg_gen_vec_sar8i_i64(a, a, shift);
5827 tcg_gen_vec_add8_i64(d, d, a);
5830 static void gen_ssra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5832 tcg_gen_vec_sar16i_i64(a, a, shift);
5833 tcg_gen_vec_add16_i64(d, d, a);
5836 static void gen_ssra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
5838 tcg_gen_sari_i32(a, a, shift);
5839 tcg_gen_add_i32(d, d, a);
5842 static void gen_ssra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5844 tcg_gen_sari_i64(a, a, shift);
5845 tcg_gen_add_i64(d, d, a);
5848 static void gen_ssra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
5850 tcg_gen_sari_vec(vece, a, a, sh);
5851 tcg_gen_add_vec(vece, d, d, a);
5854 static const TCGOpcode vecop_list_ssra[] = {
5855 INDEX_op_sari_vec, INDEX_op_add_vec, 0
5858 const GVecGen2i ssra_op[4] = {
5859 { .fni8 = gen_ssra8_i64,
5860 .fniv = gen_ssra_vec,
5861 .load_dest = true,
5862 .opt_opc = vecop_list_ssra,
5863 .vece = MO_8 },
5864 { .fni8 = gen_ssra16_i64,
5865 .fniv = gen_ssra_vec,
5866 .load_dest = true,
5867 .opt_opc = vecop_list_ssra,
5868 .vece = MO_16 },
5869 { .fni4 = gen_ssra32_i32,
5870 .fniv = gen_ssra_vec,
5871 .load_dest = true,
5872 .opt_opc = vecop_list_ssra,
5873 .vece = MO_32 },
5874 { .fni8 = gen_ssra64_i64,
5875 .fniv = gen_ssra_vec,
5876 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5877 .opt_opc = vecop_list_ssra,
5878 .load_dest = true,
5879 .vece = MO_64 },
5882 static void gen_usra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5884 tcg_gen_vec_shr8i_i64(a, a, shift);
5885 tcg_gen_vec_add8_i64(d, d, a);
5888 static void gen_usra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5890 tcg_gen_vec_shr16i_i64(a, a, shift);
5891 tcg_gen_vec_add16_i64(d, d, a);
5894 static void gen_usra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
5896 tcg_gen_shri_i32(a, a, shift);
5897 tcg_gen_add_i32(d, d, a);
5900 static void gen_usra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5902 tcg_gen_shri_i64(a, a, shift);
5903 tcg_gen_add_i64(d, d, a);
5906 static void gen_usra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
5908 tcg_gen_shri_vec(vece, a, a, sh);
5909 tcg_gen_add_vec(vece, d, d, a);
5912 static const TCGOpcode vecop_list_usra[] = {
5913 INDEX_op_shri_vec, INDEX_op_add_vec, 0
5916 const GVecGen2i usra_op[4] = {
5917 { .fni8 = gen_usra8_i64,
5918 .fniv = gen_usra_vec,
5919 .load_dest = true,
5920 .opt_opc = vecop_list_usra,
5921 .vece = MO_8, },
5922 { .fni8 = gen_usra16_i64,
5923 .fniv = gen_usra_vec,
5924 .load_dest = true,
5925 .opt_opc = vecop_list_usra,
5926 .vece = MO_16, },
5927 { .fni4 = gen_usra32_i32,
5928 .fniv = gen_usra_vec,
5929 .load_dest = true,
5930 .opt_opc = vecop_list_usra,
5931 .vece = MO_32, },
5932 { .fni8 = gen_usra64_i64,
5933 .fniv = gen_usra_vec,
5934 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5935 .load_dest = true,
5936 .opt_opc = vecop_list_usra,
5937 .vece = MO_64, },
5940 static void gen_shr8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5942 uint64_t mask = dup_const(MO_8, 0xff >> shift);
5943 TCGv_i64 t = tcg_temp_new_i64();
5945 tcg_gen_shri_i64(t, a, shift);
5946 tcg_gen_andi_i64(t, t, mask);
5947 tcg_gen_andi_i64(d, d, ~mask);
5948 tcg_gen_or_i64(d, d, t);
5949 tcg_temp_free_i64(t);
5952 static void gen_shr16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5954 uint64_t mask = dup_const(MO_16, 0xffff >> shift);
5955 TCGv_i64 t = tcg_temp_new_i64();
5957 tcg_gen_shri_i64(t, a, shift);
5958 tcg_gen_andi_i64(t, t, mask);
5959 tcg_gen_andi_i64(d, d, ~mask);
5960 tcg_gen_or_i64(d, d, t);
5961 tcg_temp_free_i64(t);
5964 static void gen_shr32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
5966 tcg_gen_shri_i32(a, a, shift);
5967 tcg_gen_deposit_i32(d, d, a, 0, 32 - shift);
5970 static void gen_shr64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5972 tcg_gen_shri_i64(a, a, shift);
5973 tcg_gen_deposit_i64(d, d, a, 0, 64 - shift);
5976 static void gen_shr_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
5978 if (sh == 0) {
5979 tcg_gen_mov_vec(d, a);
5980 } else {
5981 TCGv_vec t = tcg_temp_new_vec_matching(d);
5982 TCGv_vec m = tcg_temp_new_vec_matching(d);
5984 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK((8 << vece) - sh, sh));
5985 tcg_gen_shri_vec(vece, t, a, sh);
5986 tcg_gen_and_vec(vece, d, d, m);
5987 tcg_gen_or_vec(vece, d, d, t);
5989 tcg_temp_free_vec(t);
5990 tcg_temp_free_vec(m);
5994 static const TCGOpcode vecop_list_sri[] = { INDEX_op_shri_vec, 0 };
5996 const GVecGen2i sri_op[4] = {
5997 { .fni8 = gen_shr8_ins_i64,
5998 .fniv = gen_shr_ins_vec,
5999 .load_dest = true,
6000 .opt_opc = vecop_list_sri,
6001 .vece = MO_8 },
6002 { .fni8 = gen_shr16_ins_i64,
6003 .fniv = gen_shr_ins_vec,
6004 .load_dest = true,
6005 .opt_opc = vecop_list_sri,
6006 .vece = MO_16 },
6007 { .fni4 = gen_shr32_ins_i32,
6008 .fniv = gen_shr_ins_vec,
6009 .load_dest = true,
6010 .opt_opc = vecop_list_sri,
6011 .vece = MO_32 },
6012 { .fni8 = gen_shr64_ins_i64,
6013 .fniv = gen_shr_ins_vec,
6014 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
6015 .load_dest = true,
6016 .opt_opc = vecop_list_sri,
6017 .vece = MO_64 },
6020 static void gen_shl8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
6022 uint64_t mask = dup_const(MO_8, 0xff << shift);
6023 TCGv_i64 t = tcg_temp_new_i64();
6025 tcg_gen_shli_i64(t, a, shift);
6026 tcg_gen_andi_i64(t, t, mask);
6027 tcg_gen_andi_i64(d, d, ~mask);
6028 tcg_gen_or_i64(d, d, t);
6029 tcg_temp_free_i64(t);
6032 static void gen_shl16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
6034 uint64_t mask = dup_const(MO_16, 0xffff << shift);
6035 TCGv_i64 t = tcg_temp_new_i64();
6037 tcg_gen_shli_i64(t, a, shift);
6038 tcg_gen_andi_i64(t, t, mask);
6039 tcg_gen_andi_i64(d, d, ~mask);
6040 tcg_gen_or_i64(d, d, t);
6041 tcg_temp_free_i64(t);
6044 static void gen_shl32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
6046 tcg_gen_deposit_i32(d, d, a, shift, 32 - shift);
6049 static void gen_shl64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
6051 tcg_gen_deposit_i64(d, d, a, shift, 64 - shift);
6054 static void gen_shl_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
6056 if (sh == 0) {
6057 tcg_gen_mov_vec(d, a);
6058 } else {
6059 TCGv_vec t = tcg_temp_new_vec_matching(d);
6060 TCGv_vec m = tcg_temp_new_vec_matching(d);
6062 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK(0, sh));
6063 tcg_gen_shli_vec(vece, t, a, sh);
6064 tcg_gen_and_vec(vece, d, d, m);
6065 tcg_gen_or_vec(vece, d, d, t);
6067 tcg_temp_free_vec(t);
6068 tcg_temp_free_vec(m);
6072 static const TCGOpcode vecop_list_sli[] = { INDEX_op_shli_vec, 0 };
6074 const GVecGen2i sli_op[4] = {
6075 { .fni8 = gen_shl8_ins_i64,
6076 .fniv = gen_shl_ins_vec,
6077 .load_dest = true,
6078 .opt_opc = vecop_list_sli,
6079 .vece = MO_8 },
6080 { .fni8 = gen_shl16_ins_i64,
6081 .fniv = gen_shl_ins_vec,
6082 .load_dest = true,
6083 .opt_opc = vecop_list_sli,
6084 .vece = MO_16 },
6085 { .fni4 = gen_shl32_ins_i32,
6086 .fniv = gen_shl_ins_vec,
6087 .load_dest = true,
6088 .opt_opc = vecop_list_sli,
6089 .vece = MO_32 },
6090 { .fni8 = gen_shl64_ins_i64,
6091 .fniv = gen_shl_ins_vec,
6092 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
6093 .load_dest = true,
6094 .opt_opc = vecop_list_sli,
6095 .vece = MO_64 },
6098 static void gen_mla8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
6100 gen_helper_neon_mul_u8(a, a, b);
6101 gen_helper_neon_add_u8(d, d, a);
6104 static void gen_mls8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
6106 gen_helper_neon_mul_u8(a, a, b);
6107 gen_helper_neon_sub_u8(d, d, a);
6110 static void gen_mla16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
6112 gen_helper_neon_mul_u16(a, a, b);
6113 gen_helper_neon_add_u16(d, d, a);
6116 static void gen_mls16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
6118 gen_helper_neon_mul_u16(a, a, b);
6119 gen_helper_neon_sub_u16(d, d, a);
6122 static void gen_mla32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
6124 tcg_gen_mul_i32(a, a, b);
6125 tcg_gen_add_i32(d, d, a);
6128 static void gen_mls32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
6130 tcg_gen_mul_i32(a, a, b);
6131 tcg_gen_sub_i32(d, d, a);
6134 static void gen_mla64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
6136 tcg_gen_mul_i64(a, a, b);
6137 tcg_gen_add_i64(d, d, a);
6140 static void gen_mls64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
6142 tcg_gen_mul_i64(a, a, b);
6143 tcg_gen_sub_i64(d, d, a);
6146 static void gen_mla_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
6148 tcg_gen_mul_vec(vece, a, a, b);
6149 tcg_gen_add_vec(vece, d, d, a);
6152 static void gen_mls_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
6154 tcg_gen_mul_vec(vece, a, a, b);
6155 tcg_gen_sub_vec(vece, d, d, a);
6158 /* Note that while NEON does not support VMLA and VMLS as 64-bit ops,
6159 * these tables are shared with AArch64 which does support them.
6162 static const TCGOpcode vecop_list_mla[] = {
6163 INDEX_op_mul_vec, INDEX_op_add_vec, 0
6166 static const TCGOpcode vecop_list_mls[] = {
6167 INDEX_op_mul_vec, INDEX_op_sub_vec, 0
6170 const GVecGen3 mla_op[4] = {
6171 { .fni4 = gen_mla8_i32,
6172 .fniv = gen_mla_vec,
6173 .load_dest = true,
6174 .opt_opc = vecop_list_mla,
6175 .vece = MO_8 },
6176 { .fni4 = gen_mla16_i32,
6177 .fniv = gen_mla_vec,
6178 .load_dest = true,
6179 .opt_opc = vecop_list_mla,
6180 .vece = MO_16 },
6181 { .fni4 = gen_mla32_i32,
6182 .fniv = gen_mla_vec,
6183 .load_dest = true,
6184 .opt_opc = vecop_list_mla,
6185 .vece = MO_32 },
6186 { .fni8 = gen_mla64_i64,
6187 .fniv = gen_mla_vec,
6188 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
6189 .load_dest = true,
6190 .opt_opc = vecop_list_mla,
6191 .vece = MO_64 },
6194 const GVecGen3 mls_op[4] = {
6195 { .fni4 = gen_mls8_i32,
6196 .fniv = gen_mls_vec,
6197 .load_dest = true,
6198 .opt_opc = vecop_list_mls,
6199 .vece = MO_8 },
6200 { .fni4 = gen_mls16_i32,
6201 .fniv = gen_mls_vec,
6202 .load_dest = true,
6203 .opt_opc = vecop_list_mls,
6204 .vece = MO_16 },
6205 { .fni4 = gen_mls32_i32,
6206 .fniv = gen_mls_vec,
6207 .load_dest = true,
6208 .opt_opc = vecop_list_mls,
6209 .vece = MO_32 },
6210 { .fni8 = gen_mls64_i64,
6211 .fniv = gen_mls_vec,
6212 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
6213 .load_dest = true,
6214 .opt_opc = vecop_list_mls,
6215 .vece = MO_64 },
6218 /* CMTST : test is "if (X & Y != 0)". */
6219 static void gen_cmtst_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
6221 tcg_gen_and_i32(d, a, b);
6222 tcg_gen_setcondi_i32(TCG_COND_NE, d, d, 0);
6223 tcg_gen_neg_i32(d, d);
6226 void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
6228 tcg_gen_and_i64(d, a, b);
6229 tcg_gen_setcondi_i64(TCG_COND_NE, d, d, 0);
6230 tcg_gen_neg_i64(d, d);
6233 static void gen_cmtst_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
6235 tcg_gen_and_vec(vece, d, a, b);
6236 tcg_gen_dupi_vec(vece, a, 0);
6237 tcg_gen_cmp_vec(TCG_COND_NE, vece, d, d, a);
6240 static const TCGOpcode vecop_list_cmtst[] = { INDEX_op_cmp_vec, 0 };
6242 const GVecGen3 cmtst_op[4] = {
6243 { .fni4 = gen_helper_neon_tst_u8,
6244 .fniv = gen_cmtst_vec,
6245 .opt_opc = vecop_list_cmtst,
6246 .vece = MO_8 },
6247 { .fni4 = gen_helper_neon_tst_u16,
6248 .fniv = gen_cmtst_vec,
6249 .opt_opc = vecop_list_cmtst,
6250 .vece = MO_16 },
6251 { .fni4 = gen_cmtst_i32,
6252 .fniv = gen_cmtst_vec,
6253 .opt_opc = vecop_list_cmtst,
6254 .vece = MO_32 },
6255 { .fni8 = gen_cmtst_i64,
6256 .fniv = gen_cmtst_vec,
6257 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
6258 .opt_opc = vecop_list_cmtst,
6259 .vece = MO_64 },
6262 static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
6263 TCGv_vec a, TCGv_vec b)
6265 TCGv_vec x = tcg_temp_new_vec_matching(t);
6266 tcg_gen_add_vec(vece, x, a, b);
6267 tcg_gen_usadd_vec(vece, t, a, b);
6268 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
6269 tcg_gen_or_vec(vece, sat, sat, x);
6270 tcg_temp_free_vec(x);
6273 static const TCGOpcode vecop_list_uqadd[] = {
6274 INDEX_op_usadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
6277 const GVecGen4 uqadd_op[4] = {
6278 { .fniv = gen_uqadd_vec,
6279 .fno = gen_helper_gvec_uqadd_b,
6280 .write_aofs = true,
6281 .opt_opc = vecop_list_uqadd,
6282 .vece = MO_8 },
6283 { .fniv = gen_uqadd_vec,
6284 .fno = gen_helper_gvec_uqadd_h,
6285 .write_aofs = true,
6286 .opt_opc = vecop_list_uqadd,
6287 .vece = MO_16 },
6288 { .fniv = gen_uqadd_vec,
6289 .fno = gen_helper_gvec_uqadd_s,
6290 .write_aofs = true,
6291 .opt_opc = vecop_list_uqadd,
6292 .vece = MO_32 },
6293 { .fniv = gen_uqadd_vec,
6294 .fno = gen_helper_gvec_uqadd_d,
6295 .write_aofs = true,
6296 .opt_opc = vecop_list_uqadd,
6297 .vece = MO_64 },
6300 static void gen_sqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
6301 TCGv_vec a, TCGv_vec b)
6303 TCGv_vec x = tcg_temp_new_vec_matching(t);
6304 tcg_gen_add_vec(vece, x, a, b);
6305 tcg_gen_ssadd_vec(vece, t, a, b);
6306 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
6307 tcg_gen_or_vec(vece, sat, sat, x);
6308 tcg_temp_free_vec(x);
6311 static const TCGOpcode vecop_list_sqadd[] = {
6312 INDEX_op_ssadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
6315 const GVecGen4 sqadd_op[4] = {
6316 { .fniv = gen_sqadd_vec,
6317 .fno = gen_helper_gvec_sqadd_b,
6318 .opt_opc = vecop_list_sqadd,
6319 .write_aofs = true,
6320 .vece = MO_8 },
6321 { .fniv = gen_sqadd_vec,
6322 .fno = gen_helper_gvec_sqadd_h,
6323 .opt_opc = vecop_list_sqadd,
6324 .write_aofs = true,
6325 .vece = MO_16 },
6326 { .fniv = gen_sqadd_vec,
6327 .fno = gen_helper_gvec_sqadd_s,
6328 .opt_opc = vecop_list_sqadd,
6329 .write_aofs = true,
6330 .vece = MO_32 },
6331 { .fniv = gen_sqadd_vec,
6332 .fno = gen_helper_gvec_sqadd_d,
6333 .opt_opc = vecop_list_sqadd,
6334 .write_aofs = true,
6335 .vece = MO_64 },
6338 static void gen_uqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
6339 TCGv_vec a, TCGv_vec b)
6341 TCGv_vec x = tcg_temp_new_vec_matching(t);
6342 tcg_gen_sub_vec(vece, x, a, b);
6343 tcg_gen_ussub_vec(vece, t, a, b);
6344 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
6345 tcg_gen_or_vec(vece, sat, sat, x);
6346 tcg_temp_free_vec(x);
6349 static const TCGOpcode vecop_list_uqsub[] = {
6350 INDEX_op_ussub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
6353 const GVecGen4 uqsub_op[4] = {
6354 { .fniv = gen_uqsub_vec,
6355 .fno = gen_helper_gvec_uqsub_b,
6356 .opt_opc = vecop_list_uqsub,
6357 .write_aofs = true,
6358 .vece = MO_8 },
6359 { .fniv = gen_uqsub_vec,
6360 .fno = gen_helper_gvec_uqsub_h,
6361 .opt_opc = vecop_list_uqsub,
6362 .write_aofs = true,
6363 .vece = MO_16 },
6364 { .fniv = gen_uqsub_vec,
6365 .fno = gen_helper_gvec_uqsub_s,
6366 .opt_opc = vecop_list_uqsub,
6367 .write_aofs = true,
6368 .vece = MO_32 },
6369 { .fniv = gen_uqsub_vec,
6370 .fno = gen_helper_gvec_uqsub_d,
6371 .opt_opc = vecop_list_uqsub,
6372 .write_aofs = true,
6373 .vece = MO_64 },
6376 static void gen_sqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
6377 TCGv_vec a, TCGv_vec b)
6379 TCGv_vec x = tcg_temp_new_vec_matching(t);
6380 tcg_gen_sub_vec(vece, x, a, b);
6381 tcg_gen_sssub_vec(vece, t, a, b);
6382 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
6383 tcg_gen_or_vec(vece, sat, sat, x);
6384 tcg_temp_free_vec(x);
6387 static const TCGOpcode vecop_list_sqsub[] = {
6388 INDEX_op_sssub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
6391 const GVecGen4 sqsub_op[4] = {
6392 { .fniv = gen_sqsub_vec,
6393 .fno = gen_helper_gvec_sqsub_b,
6394 .opt_opc = vecop_list_sqsub,
6395 .write_aofs = true,
6396 .vece = MO_8 },
6397 { .fniv = gen_sqsub_vec,
6398 .fno = gen_helper_gvec_sqsub_h,
6399 .opt_opc = vecop_list_sqsub,
6400 .write_aofs = true,
6401 .vece = MO_16 },
6402 { .fniv = gen_sqsub_vec,
6403 .fno = gen_helper_gvec_sqsub_s,
6404 .opt_opc = vecop_list_sqsub,
6405 .write_aofs = true,
6406 .vece = MO_32 },
6407 { .fniv = gen_sqsub_vec,
6408 .fno = gen_helper_gvec_sqsub_d,
6409 .opt_opc = vecop_list_sqsub,
6410 .write_aofs = true,
6411 .vece = MO_64 },
6414 /* Translate a NEON data processing instruction. Return nonzero if the
6415 instruction is invalid.
6416 We process data in a mixture of 32-bit and 64-bit chunks.
6417 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
6419 static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
6421 int op;
6422 int q;
6423 int rd, rn, rm, rd_ofs, rn_ofs, rm_ofs;
6424 int size;
6425 int shift;
6426 int pass;
6427 int count;
6428 int pairwise;
6429 int u;
6430 int vec_size;
6431 uint32_t imm;
6432 TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
6433 TCGv_ptr ptr1, ptr2, ptr3;
6434 TCGv_i64 tmp64;
6436 /* FIXME: this access check should not take precedence over UNDEF
6437 * for invalid encodings; we will generate incorrect syndrome information
6438 * for attempts to execute invalid vfp/neon encodings with FP disabled.
6440 if (s->fp_excp_el) {
6441 gen_exception_insn(s, 4, EXCP_UDEF,
6442 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
6443 return 0;
6446 if (!s->vfp_enabled)
6447 return 1;
6448 q = (insn & (1 << 6)) != 0;
6449 u = (insn >> 24) & 1;
6450 VFP_DREG_D(rd, insn);
6451 VFP_DREG_N(rn, insn);
6452 VFP_DREG_M(rm, insn);
6453 size = (insn >> 20) & 3;
6454 vec_size = q ? 16 : 8;
6455 rd_ofs = neon_reg_offset(rd, 0);
6456 rn_ofs = neon_reg_offset(rn, 0);
6457 rm_ofs = neon_reg_offset(rm, 0);
6459 if ((insn & (1 << 23)) == 0) {
6460 /* Three register same length. */
6461 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
6462 /* Catch invalid op and bad size combinations: UNDEF */
6463 if ((neon_3r_sizes[op] & (1 << size)) == 0) {
6464 return 1;
6466 /* All insns of this form UNDEF for either this condition or the
6467 * superset of cases "Q==1"; we catch the latter later.
6469 if (q && ((rd | rn | rm) & 1)) {
6470 return 1;
6472 switch (op) {
6473 case NEON_3R_SHA:
6474 /* The SHA-1/SHA-256 3-register instructions require special
6475 * treatment here, as their size field is overloaded as an
6476 * op type selector, and they all consume their input in a
6477 * single pass.
6479 if (!q) {
6480 return 1;
6482 if (!u) { /* SHA-1 */
6483 if (!dc_isar_feature(aa32_sha1, s)) {
6484 return 1;
6486 ptr1 = vfp_reg_ptr(true, rd);
6487 ptr2 = vfp_reg_ptr(true, rn);
6488 ptr3 = vfp_reg_ptr(true, rm);
6489 tmp4 = tcg_const_i32(size);
6490 gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp4);
6491 tcg_temp_free_i32(tmp4);
6492 } else { /* SHA-256 */
6493 if (!dc_isar_feature(aa32_sha2, s) || size == 3) {
6494 return 1;
6496 ptr1 = vfp_reg_ptr(true, rd);
6497 ptr2 = vfp_reg_ptr(true, rn);
6498 ptr3 = vfp_reg_ptr(true, rm);
6499 switch (size) {
6500 case 0:
6501 gen_helper_crypto_sha256h(ptr1, ptr2, ptr3);
6502 break;
6503 case 1:
6504 gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3);
6505 break;
6506 case 2:
6507 gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3);
6508 break;
6511 tcg_temp_free_ptr(ptr1);
6512 tcg_temp_free_ptr(ptr2);
6513 tcg_temp_free_ptr(ptr3);
6514 return 0;
6516 case NEON_3R_VPADD_VQRDMLAH:
6517 if (!u) {
6518 break; /* VPADD */
6520 /* VQRDMLAH */
6521 switch (size) {
6522 case 1:
6523 return do_v81_helper(s, gen_helper_gvec_qrdmlah_s16,
6524 q, rd, rn, rm);
6525 case 2:
6526 return do_v81_helper(s, gen_helper_gvec_qrdmlah_s32,
6527 q, rd, rn, rm);
6529 return 1;
6531 case NEON_3R_VFM_VQRDMLSH:
6532 if (!u) {
6533 /* VFM, VFMS */
6534 if (size == 1) {
6535 return 1;
6537 break;
6539 /* VQRDMLSH */
6540 switch (size) {
6541 case 1:
6542 return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s16,
6543 q, rd, rn, rm);
6544 case 2:
6545 return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s32,
6546 q, rd, rn, rm);
6548 return 1;
6550 case NEON_3R_LOGIC: /* Logic ops. */
6551 switch ((u << 2) | size) {
6552 case 0: /* VAND */
6553 tcg_gen_gvec_and(0, rd_ofs, rn_ofs, rm_ofs,
6554 vec_size, vec_size);
6555 break;
6556 case 1: /* VBIC */
6557 tcg_gen_gvec_andc(0, rd_ofs, rn_ofs, rm_ofs,
6558 vec_size, vec_size);
6559 break;
6560 case 2: /* VORR */
6561 tcg_gen_gvec_or(0, rd_ofs, rn_ofs, rm_ofs,
6562 vec_size, vec_size);
6563 break;
6564 case 3: /* VORN */
6565 tcg_gen_gvec_orc(0, rd_ofs, rn_ofs, rm_ofs,
6566 vec_size, vec_size);
6567 break;
6568 case 4: /* VEOR */
6569 tcg_gen_gvec_xor(0, rd_ofs, rn_ofs, rm_ofs,
6570 vec_size, vec_size);
6571 break;
6572 case 5: /* VBSL */
6573 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
6574 vec_size, vec_size, &bsl_op);
6575 break;
6576 case 6: /* VBIT */
6577 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
6578 vec_size, vec_size, &bit_op);
6579 break;
6580 case 7: /* VBIF */
6581 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
6582 vec_size, vec_size, &bif_op);
6583 break;
6585 return 0;
6587 case NEON_3R_VADD_VSUB:
6588 if (u) {
6589 tcg_gen_gvec_sub(size, rd_ofs, rn_ofs, rm_ofs,
6590 vec_size, vec_size);
6591 } else {
6592 tcg_gen_gvec_add(size, rd_ofs, rn_ofs, rm_ofs,
6593 vec_size, vec_size);
6595 return 0;
6597 case NEON_3R_VQADD:
6598 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
6599 rn_ofs, rm_ofs, vec_size, vec_size,
6600 (u ? uqadd_op : sqadd_op) + size);
6601 return 0;
6603 case NEON_3R_VQSUB:
6604 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
6605 rn_ofs, rm_ofs, vec_size, vec_size,
6606 (u ? uqsub_op : sqsub_op) + size);
6607 return 0;
6609 case NEON_3R_VMUL: /* VMUL */
6610 if (u) {
6611 /* Polynomial case allows only P8 and is handled below. */
6612 if (size != 0) {
6613 return 1;
6615 } else {
6616 tcg_gen_gvec_mul(size, rd_ofs, rn_ofs, rm_ofs,
6617 vec_size, vec_size);
6618 return 0;
6620 break;
6622 case NEON_3R_VML: /* VMLA, VMLS */
6623 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size,
6624 u ? &mls_op[size] : &mla_op[size]);
6625 return 0;
6627 case NEON_3R_VTST_VCEQ:
6628 if (u) { /* VCEQ */
6629 tcg_gen_gvec_cmp(TCG_COND_EQ, size, rd_ofs, rn_ofs, rm_ofs,
6630 vec_size, vec_size);
6631 } else { /* VTST */
6632 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
6633 vec_size, vec_size, &cmtst_op[size]);
6635 return 0;
6637 case NEON_3R_VCGT:
6638 tcg_gen_gvec_cmp(u ? TCG_COND_GTU : TCG_COND_GT, size,
6639 rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
6640 return 0;
6642 case NEON_3R_VCGE:
6643 tcg_gen_gvec_cmp(u ? TCG_COND_GEU : TCG_COND_GE, size,
6644 rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
6645 return 0;
6647 case NEON_3R_VMAX:
6648 if (u) {
6649 tcg_gen_gvec_umax(size, rd_ofs, rn_ofs, rm_ofs,
6650 vec_size, vec_size);
6651 } else {
6652 tcg_gen_gvec_smax(size, rd_ofs, rn_ofs, rm_ofs,
6653 vec_size, vec_size);
6655 return 0;
6656 case NEON_3R_VMIN:
6657 if (u) {
6658 tcg_gen_gvec_umin(size, rd_ofs, rn_ofs, rm_ofs,
6659 vec_size, vec_size);
6660 } else {
6661 tcg_gen_gvec_smin(size, rd_ofs, rn_ofs, rm_ofs,
6662 vec_size, vec_size);
6664 return 0;
6667 if (size == 3) {
6668 /* 64-bit element instructions. */
6669 for (pass = 0; pass < (q ? 2 : 1); pass++) {
6670 neon_load_reg64(cpu_V0, rn + pass);
6671 neon_load_reg64(cpu_V1, rm + pass);
6672 switch (op) {
6673 case NEON_3R_VSHL:
6674 if (u) {
6675 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
6676 } else {
6677 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
6679 break;
6680 case NEON_3R_VQSHL:
6681 if (u) {
6682 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
6683 cpu_V1, cpu_V0);
6684 } else {
6685 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
6686 cpu_V1, cpu_V0);
6688 break;
6689 case NEON_3R_VRSHL:
6690 if (u) {
6691 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
6692 } else {
6693 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
6695 break;
6696 case NEON_3R_VQRSHL:
6697 if (u) {
6698 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
6699 cpu_V1, cpu_V0);
6700 } else {
6701 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
6702 cpu_V1, cpu_V0);
6704 break;
6705 default:
6706 abort();
6708 neon_store_reg64(cpu_V0, rd + pass);
6710 return 0;
6712 pairwise = 0;
6713 switch (op) {
6714 case NEON_3R_VSHL:
6715 case NEON_3R_VQSHL:
6716 case NEON_3R_VRSHL:
6717 case NEON_3R_VQRSHL:
6719 int rtmp;
6720 /* Shift instruction operands are reversed. */
6721 rtmp = rn;
6722 rn = rm;
6723 rm = rtmp;
6725 break;
6726 case NEON_3R_VPADD_VQRDMLAH:
6727 case NEON_3R_VPMAX:
6728 case NEON_3R_VPMIN:
6729 pairwise = 1;
6730 break;
6731 case NEON_3R_FLOAT_ARITH:
6732 pairwise = (u && size < 2); /* if VPADD (float) */
6733 break;
6734 case NEON_3R_FLOAT_MINMAX:
6735 pairwise = u; /* if VPMIN/VPMAX (float) */
6736 break;
6737 case NEON_3R_FLOAT_CMP:
6738 if (!u && size) {
6739 /* no encoding for U=0 C=1x */
6740 return 1;
6742 break;
6743 case NEON_3R_FLOAT_ACMP:
6744 if (!u) {
6745 return 1;
6747 break;
6748 case NEON_3R_FLOAT_MISC:
6749 /* VMAXNM/VMINNM in ARMv8 */
6750 if (u && !arm_dc_feature(s, ARM_FEATURE_V8)) {
6751 return 1;
6753 break;
6754 case NEON_3R_VFM_VQRDMLSH:
6755 if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
6756 return 1;
6758 break;
6759 default:
6760 break;
6763 if (pairwise && q) {
6764 /* All the pairwise insns UNDEF if Q is set */
6765 return 1;
6768 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6770 if (pairwise) {
6771 /* Pairwise. */
6772 if (pass < 1) {
6773 tmp = neon_load_reg(rn, 0);
6774 tmp2 = neon_load_reg(rn, 1);
6775 } else {
6776 tmp = neon_load_reg(rm, 0);
6777 tmp2 = neon_load_reg(rm, 1);
6779 } else {
6780 /* Elementwise. */
6781 tmp = neon_load_reg(rn, pass);
6782 tmp2 = neon_load_reg(rm, pass);
6784 switch (op) {
6785 case NEON_3R_VHADD:
6786 GEN_NEON_INTEGER_OP(hadd);
6787 break;
6788 case NEON_3R_VRHADD:
6789 GEN_NEON_INTEGER_OP(rhadd);
6790 break;
6791 case NEON_3R_VHSUB:
6792 GEN_NEON_INTEGER_OP(hsub);
6793 break;
6794 case NEON_3R_VSHL:
6795 GEN_NEON_INTEGER_OP(shl);
6796 break;
6797 case NEON_3R_VQSHL:
6798 GEN_NEON_INTEGER_OP_ENV(qshl);
6799 break;
6800 case NEON_3R_VRSHL:
6801 GEN_NEON_INTEGER_OP(rshl);
6802 break;
6803 case NEON_3R_VQRSHL:
6804 GEN_NEON_INTEGER_OP_ENV(qrshl);
6805 break;
6806 case NEON_3R_VABD:
6807 GEN_NEON_INTEGER_OP(abd);
6808 break;
6809 case NEON_3R_VABA:
6810 GEN_NEON_INTEGER_OP(abd);
6811 tcg_temp_free_i32(tmp2);
6812 tmp2 = neon_load_reg(rd, pass);
6813 gen_neon_add(size, tmp, tmp2);
6814 break;
6815 case NEON_3R_VMUL:
6816 /* VMUL.P8; other cases already eliminated. */
6817 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
6818 break;
6819 case NEON_3R_VPMAX:
6820 GEN_NEON_INTEGER_OP(pmax);
6821 break;
6822 case NEON_3R_VPMIN:
6823 GEN_NEON_INTEGER_OP(pmin);
6824 break;
6825 case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
6826 if (!u) { /* VQDMULH */
6827 switch (size) {
6828 case 1:
6829 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
6830 break;
6831 case 2:
6832 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
6833 break;
6834 default: abort();
6836 } else { /* VQRDMULH */
6837 switch (size) {
6838 case 1:
6839 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
6840 break;
6841 case 2:
6842 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
6843 break;
6844 default: abort();
6847 break;
6848 case NEON_3R_VPADD_VQRDMLAH:
6849 switch (size) {
6850 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
6851 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
6852 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
6853 default: abort();
6855 break;
6856 case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
6858 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6859 switch ((u << 2) | size) {
6860 case 0: /* VADD */
6861 case 4: /* VPADD */
6862 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
6863 break;
6864 case 2: /* VSUB */
6865 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
6866 break;
6867 case 6: /* VABD */
6868 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
6869 break;
6870 default:
6871 abort();
6873 tcg_temp_free_ptr(fpstatus);
6874 break;
6876 case NEON_3R_FLOAT_MULTIPLY:
6878 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6879 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
6880 if (!u) {
6881 tcg_temp_free_i32(tmp2);
6882 tmp2 = neon_load_reg(rd, pass);
6883 if (size == 0) {
6884 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
6885 } else {
6886 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
6889 tcg_temp_free_ptr(fpstatus);
6890 break;
6892 case NEON_3R_FLOAT_CMP:
6894 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6895 if (!u) {
6896 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
6897 } else {
6898 if (size == 0) {
6899 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
6900 } else {
6901 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
6904 tcg_temp_free_ptr(fpstatus);
6905 break;
6907 case NEON_3R_FLOAT_ACMP:
6909 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6910 if (size == 0) {
6911 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
6912 } else {
6913 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
6915 tcg_temp_free_ptr(fpstatus);
6916 break;
6918 case NEON_3R_FLOAT_MINMAX:
6920 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6921 if (size == 0) {
6922 gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus);
6923 } else {
6924 gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus);
6926 tcg_temp_free_ptr(fpstatus);
6927 break;
6929 case NEON_3R_FLOAT_MISC:
6930 if (u) {
6931 /* VMAXNM/VMINNM */
6932 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6933 if (size == 0) {
6934 gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus);
6935 } else {
6936 gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus);
6938 tcg_temp_free_ptr(fpstatus);
6939 } else {
6940 if (size == 0) {
6941 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
6942 } else {
6943 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
6946 break;
6947 case NEON_3R_VFM_VQRDMLSH:
6949 /* VFMA, VFMS: fused multiply-add */
6950 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6951 TCGv_i32 tmp3 = neon_load_reg(rd, pass);
6952 if (size) {
6953 /* VFMS */
6954 gen_helper_vfp_negs(tmp, tmp);
6956 gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus);
6957 tcg_temp_free_i32(tmp3);
6958 tcg_temp_free_ptr(fpstatus);
6959 break;
6961 default:
6962 abort();
6964 tcg_temp_free_i32(tmp2);
6966 /* Save the result. For elementwise operations we can put it
6967 straight into the destination register. For pairwise operations
6968 we have to be careful to avoid clobbering the source operands. */
6969 if (pairwise && rd == rm) {
6970 neon_store_scratch(pass, tmp);
6971 } else {
6972 neon_store_reg(rd, pass, tmp);
6975 } /* for pass */
6976 if (pairwise && rd == rm) {
6977 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6978 tmp = neon_load_scratch(pass);
6979 neon_store_reg(rd, pass, tmp);
6982 /* End of 3 register same size operations. */
6983 } else if (insn & (1 << 4)) {
6984 if ((insn & 0x00380080) != 0) {
6985 /* Two registers and shift. */
6986 op = (insn >> 8) & 0xf;
6987 if (insn & (1 << 7)) {
6988 /* 64-bit shift. */
6989 if (op > 7) {
6990 return 1;
6992 size = 3;
6993 } else {
6994 size = 2;
6995 while ((insn & (1 << (size + 19))) == 0)
6996 size--;
6998 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
6999 if (op < 8) {
7000 /* Shift by immediate:
7001 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
7002 if (q && ((rd | rm) & 1)) {
7003 return 1;
7005 if (!u && (op == 4 || op == 6)) {
7006 return 1;
7008 /* Right shifts are encoded as N - shift, where N is the
7009 element size in bits. */
7010 if (op <= 4) {
7011 shift = shift - (1 << (size + 3));
7014 switch (op) {
7015 case 0: /* VSHR */
7016 /* Right shift comes here negative. */
7017 shift = -shift;
7018 /* Shifts larger than the element size are architecturally
7019 * valid. Unsigned results in all zeros; signed results
7020 * in all sign bits.
7022 if (!u) {
7023 tcg_gen_gvec_sari(size, rd_ofs, rm_ofs,
7024 MIN(shift, (8 << size) - 1),
7025 vec_size, vec_size);
7026 } else if (shift >= 8 << size) {
7027 tcg_gen_gvec_dup8i(rd_ofs, vec_size, vec_size, 0);
7028 } else {
7029 tcg_gen_gvec_shri(size, rd_ofs, rm_ofs, shift,
7030 vec_size, vec_size);
7032 return 0;
7034 case 1: /* VSRA */
7035 /* Right shift comes here negative. */
7036 shift = -shift;
7037 /* Shifts larger than the element size are architecturally
7038 * valid. Unsigned results in all zeros; signed results
7039 * in all sign bits.
7041 if (!u) {
7042 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
7043 MIN(shift, (8 << size) - 1),
7044 &ssra_op[size]);
7045 } else if (shift >= 8 << size) {
7046 /* rd += 0 */
7047 } else {
7048 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
7049 shift, &usra_op[size]);
7051 return 0;
7053 case 4: /* VSRI */
7054 if (!u) {
7055 return 1;
7057 /* Right shift comes here negative. */
7058 shift = -shift;
7059 /* Shift out of range leaves destination unchanged. */
7060 if (shift < 8 << size) {
7061 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
7062 shift, &sri_op[size]);
7064 return 0;
7066 case 5: /* VSHL, VSLI */
7067 if (u) { /* VSLI */
7068 /* Shift out of range leaves destination unchanged. */
7069 if (shift < 8 << size) {
7070 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size,
7071 vec_size, shift, &sli_op[size]);
7073 } else { /* VSHL */
7074 /* Shifts larger than the element size are
7075 * architecturally valid and results in zero.
7077 if (shift >= 8 << size) {
7078 tcg_gen_gvec_dup8i(rd_ofs, vec_size, vec_size, 0);
7079 } else {
7080 tcg_gen_gvec_shli(size, rd_ofs, rm_ofs, shift,
7081 vec_size, vec_size);
7084 return 0;
7087 if (size == 3) {
7088 count = q + 1;
7089 } else {
7090 count = q ? 4: 2;
7093 /* To avoid excessive duplication of ops we implement shift
7094 * by immediate using the variable shift operations.
7096 imm = dup_const(size, shift);
7098 for (pass = 0; pass < count; pass++) {
7099 if (size == 3) {
7100 neon_load_reg64(cpu_V0, rm + pass);
7101 tcg_gen_movi_i64(cpu_V1, imm);
7102 switch (op) {
7103 case 2: /* VRSHR */
7104 case 3: /* VRSRA */
7105 if (u)
7106 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
7107 else
7108 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
7109 break;
7110 case 6: /* VQSHLU */
7111 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
7112 cpu_V0, cpu_V1);
7113 break;
7114 case 7: /* VQSHL */
7115 if (u) {
7116 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
7117 cpu_V0, cpu_V1);
7118 } else {
7119 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
7120 cpu_V0, cpu_V1);
7122 break;
7123 default:
7124 g_assert_not_reached();
7126 if (op == 3) {
7127 /* Accumulate. */
7128 neon_load_reg64(cpu_V1, rd + pass);
7129 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
7131 neon_store_reg64(cpu_V0, rd + pass);
7132 } else { /* size < 3 */
7133 /* Operands in T0 and T1. */
7134 tmp = neon_load_reg(rm, pass);
7135 tmp2 = tcg_temp_new_i32();
7136 tcg_gen_movi_i32(tmp2, imm);
7137 switch (op) {
7138 case 2: /* VRSHR */
7139 case 3: /* VRSRA */
7140 GEN_NEON_INTEGER_OP(rshl);
7141 break;
7142 case 6: /* VQSHLU */
7143 switch (size) {
7144 case 0:
7145 gen_helper_neon_qshlu_s8(tmp, cpu_env,
7146 tmp, tmp2);
7147 break;
7148 case 1:
7149 gen_helper_neon_qshlu_s16(tmp, cpu_env,
7150 tmp, tmp2);
7151 break;
7152 case 2:
7153 gen_helper_neon_qshlu_s32(tmp, cpu_env,
7154 tmp, tmp2);
7155 break;
7156 default:
7157 abort();
7159 break;
7160 case 7: /* VQSHL */
7161 GEN_NEON_INTEGER_OP_ENV(qshl);
7162 break;
7163 default:
7164 g_assert_not_reached();
7166 tcg_temp_free_i32(tmp2);
7168 if (op == 3) {
7169 /* Accumulate. */
7170 tmp2 = neon_load_reg(rd, pass);
7171 gen_neon_add(size, tmp, tmp2);
7172 tcg_temp_free_i32(tmp2);
7174 neon_store_reg(rd, pass, tmp);
7176 } /* for pass */
7177 } else if (op < 10) {
7178 /* Shift by immediate and narrow:
7179 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
7180 int input_unsigned = (op == 8) ? !u : u;
7181 if (rm & 1) {
7182 return 1;
7184 shift = shift - (1 << (size + 3));
7185 size++;
7186 if (size == 3) {
7187 tmp64 = tcg_const_i64(shift);
7188 neon_load_reg64(cpu_V0, rm);
7189 neon_load_reg64(cpu_V1, rm + 1);
7190 for (pass = 0; pass < 2; pass++) {
7191 TCGv_i64 in;
7192 if (pass == 0) {
7193 in = cpu_V0;
7194 } else {
7195 in = cpu_V1;
7197 if (q) {
7198 if (input_unsigned) {
7199 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
7200 } else {
7201 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
7203 } else {
7204 if (input_unsigned) {
7205 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
7206 } else {
7207 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
7210 tmp = tcg_temp_new_i32();
7211 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
7212 neon_store_reg(rd, pass, tmp);
7213 } /* for pass */
7214 tcg_temp_free_i64(tmp64);
7215 } else {
7216 if (size == 1) {
7217 imm = (uint16_t)shift;
7218 imm |= imm << 16;
7219 } else {
7220 /* size == 2 */
7221 imm = (uint32_t)shift;
7223 tmp2 = tcg_const_i32(imm);
7224 tmp4 = neon_load_reg(rm + 1, 0);
7225 tmp5 = neon_load_reg(rm + 1, 1);
7226 for (pass = 0; pass < 2; pass++) {
7227 if (pass == 0) {
7228 tmp = neon_load_reg(rm, 0);
7229 } else {
7230 tmp = tmp4;
7232 gen_neon_shift_narrow(size, tmp, tmp2, q,
7233 input_unsigned);
7234 if (pass == 0) {
7235 tmp3 = neon_load_reg(rm, 1);
7236 } else {
7237 tmp3 = tmp5;
7239 gen_neon_shift_narrow(size, tmp3, tmp2, q,
7240 input_unsigned);
7241 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
7242 tcg_temp_free_i32(tmp);
7243 tcg_temp_free_i32(tmp3);
7244 tmp = tcg_temp_new_i32();
7245 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
7246 neon_store_reg(rd, pass, tmp);
7247 } /* for pass */
7248 tcg_temp_free_i32(tmp2);
7250 } else if (op == 10) {
7251 /* VSHLL, VMOVL */
7252 if (q || (rd & 1)) {
7253 return 1;
7255 tmp = neon_load_reg(rm, 0);
7256 tmp2 = neon_load_reg(rm, 1);
7257 for (pass = 0; pass < 2; pass++) {
7258 if (pass == 1)
7259 tmp = tmp2;
7261 gen_neon_widen(cpu_V0, tmp, size, u);
7263 if (shift != 0) {
7264 /* The shift is less than the width of the source
7265 type, so we can just shift the whole register. */
7266 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
7267 /* Widen the result of shift: we need to clear
7268 * the potential overflow bits resulting from
7269 * left bits of the narrow input appearing as
7270 * right bits of left the neighbour narrow
7271 * input. */
7272 if (size < 2 || !u) {
7273 uint64_t imm64;
7274 if (size == 0) {
7275 imm = (0xffu >> (8 - shift));
7276 imm |= imm << 16;
7277 } else if (size == 1) {
7278 imm = 0xffff >> (16 - shift);
7279 } else {
7280 /* size == 2 */
7281 imm = 0xffffffff >> (32 - shift);
7283 if (size < 2) {
7284 imm64 = imm | (((uint64_t)imm) << 32);
7285 } else {
7286 imm64 = imm;
7288 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
7291 neon_store_reg64(cpu_V0, rd + pass);
7293 } else if (op >= 14) {
7294 /* VCVT fixed-point. */
7295 if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
7296 return 1;
7298 /* We have already masked out the must-be-1 top bit of imm6,
7299 * hence this 32-shift where the ARM ARM has 64-imm6.
7301 shift = 32 - shift;
7302 for (pass = 0; pass < (q ? 4 : 2); pass++) {
7303 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
7304 if (!(op & 1)) {
7305 if (u)
7306 gen_vfp_ulto(0, shift, 1);
7307 else
7308 gen_vfp_slto(0, shift, 1);
7309 } else {
7310 if (u)
7311 gen_vfp_toul(0, shift, 1);
7312 else
7313 gen_vfp_tosl(0, shift, 1);
7315 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
7317 } else {
7318 return 1;
7320 } else { /* (insn & 0x00380080) == 0 */
7321 int invert, reg_ofs, vec_size;
7323 if (q && (rd & 1)) {
7324 return 1;
7327 op = (insn >> 8) & 0xf;
7328 /* One register and immediate. */
7329 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
7330 invert = (insn & (1 << 5)) != 0;
7331 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
7332 * We choose to not special-case this and will behave as if a
7333 * valid constant encoding of 0 had been given.
7335 switch (op) {
7336 case 0: case 1:
7337 /* no-op */
7338 break;
7339 case 2: case 3:
7340 imm <<= 8;
7341 break;
7342 case 4: case 5:
7343 imm <<= 16;
7344 break;
7345 case 6: case 7:
7346 imm <<= 24;
7347 break;
7348 case 8: case 9:
7349 imm |= imm << 16;
7350 break;
7351 case 10: case 11:
7352 imm = (imm << 8) | (imm << 24);
7353 break;
7354 case 12:
7355 imm = (imm << 8) | 0xff;
7356 break;
7357 case 13:
7358 imm = (imm << 16) | 0xffff;
7359 break;
7360 case 14:
7361 imm |= (imm << 8) | (imm << 16) | (imm << 24);
7362 if (invert) {
7363 imm = ~imm;
7365 break;
7366 case 15:
7367 if (invert) {
7368 return 1;
7370 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
7371 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
7372 break;
7374 if (invert) {
7375 imm = ~imm;
7378 reg_ofs = neon_reg_offset(rd, 0);
7379 vec_size = q ? 16 : 8;
7381 if (op & 1 && op < 12) {
7382 if (invert) {
7383 /* The immediate value has already been inverted,
7384 * so BIC becomes AND.
7386 tcg_gen_gvec_andi(MO_32, reg_ofs, reg_ofs, imm,
7387 vec_size, vec_size);
7388 } else {
7389 tcg_gen_gvec_ori(MO_32, reg_ofs, reg_ofs, imm,
7390 vec_size, vec_size);
7392 } else {
7393 /* VMOV, VMVN. */
7394 if (op == 14 && invert) {
7395 TCGv_i64 t64 = tcg_temp_new_i64();
7397 for (pass = 0; pass <= q; ++pass) {
7398 uint64_t val = 0;
7399 int n;
7401 for (n = 0; n < 8; n++) {
7402 if (imm & (1 << (n + pass * 8))) {
7403 val |= 0xffull << (n * 8);
7406 tcg_gen_movi_i64(t64, val);
7407 neon_store_reg64(t64, rd + pass);
7409 tcg_temp_free_i64(t64);
7410 } else {
7411 tcg_gen_gvec_dup32i(reg_ofs, vec_size, vec_size, imm);
7415 } else { /* (insn & 0x00800010 == 0x00800000) */
7416 if (size != 3) {
7417 op = (insn >> 8) & 0xf;
7418 if ((insn & (1 << 6)) == 0) {
7419 /* Three registers of different lengths. */
7420 int src1_wide;
7421 int src2_wide;
7422 int prewiden;
7423 /* undefreq: bit 0 : UNDEF if size == 0
7424 * bit 1 : UNDEF if size == 1
7425 * bit 2 : UNDEF if size == 2
7426 * bit 3 : UNDEF if U == 1
7427 * Note that [2:0] set implies 'always UNDEF'
7429 int undefreq;
7430 /* prewiden, src1_wide, src2_wide, undefreq */
7431 static const int neon_3reg_wide[16][4] = {
7432 {1, 0, 0, 0}, /* VADDL */
7433 {1, 1, 0, 0}, /* VADDW */
7434 {1, 0, 0, 0}, /* VSUBL */
7435 {1, 1, 0, 0}, /* VSUBW */
7436 {0, 1, 1, 0}, /* VADDHN */
7437 {0, 0, 0, 0}, /* VABAL */
7438 {0, 1, 1, 0}, /* VSUBHN */
7439 {0, 0, 0, 0}, /* VABDL */
7440 {0, 0, 0, 0}, /* VMLAL */
7441 {0, 0, 0, 9}, /* VQDMLAL */
7442 {0, 0, 0, 0}, /* VMLSL */
7443 {0, 0, 0, 9}, /* VQDMLSL */
7444 {0, 0, 0, 0}, /* Integer VMULL */
7445 {0, 0, 0, 1}, /* VQDMULL */
7446 {0, 0, 0, 0xa}, /* Polynomial VMULL */
7447 {0, 0, 0, 7}, /* Reserved: always UNDEF */
7450 prewiden = neon_3reg_wide[op][0];
7451 src1_wide = neon_3reg_wide[op][1];
7452 src2_wide = neon_3reg_wide[op][2];
7453 undefreq = neon_3reg_wide[op][3];
7455 if ((undefreq & (1 << size)) ||
7456 ((undefreq & 8) && u)) {
7457 return 1;
7459 if ((src1_wide && (rn & 1)) ||
7460 (src2_wide && (rm & 1)) ||
7461 (!src2_wide && (rd & 1))) {
7462 return 1;
7465 /* Handle VMULL.P64 (Polynomial 64x64 to 128 bit multiply)
7466 * outside the loop below as it only performs a single pass.
7468 if (op == 14 && size == 2) {
7469 TCGv_i64 tcg_rn, tcg_rm, tcg_rd;
7471 if (!dc_isar_feature(aa32_pmull, s)) {
7472 return 1;
7474 tcg_rn = tcg_temp_new_i64();
7475 tcg_rm = tcg_temp_new_i64();
7476 tcg_rd = tcg_temp_new_i64();
7477 neon_load_reg64(tcg_rn, rn);
7478 neon_load_reg64(tcg_rm, rm);
7479 gen_helper_neon_pmull_64_lo(tcg_rd, tcg_rn, tcg_rm);
7480 neon_store_reg64(tcg_rd, rd);
7481 gen_helper_neon_pmull_64_hi(tcg_rd, tcg_rn, tcg_rm);
7482 neon_store_reg64(tcg_rd, rd + 1);
7483 tcg_temp_free_i64(tcg_rn);
7484 tcg_temp_free_i64(tcg_rm);
7485 tcg_temp_free_i64(tcg_rd);
7486 return 0;
7489 /* Avoid overlapping operands. Wide source operands are
7490 always aligned so will never overlap with wide
7491 destinations in problematic ways. */
7492 if (rd == rm && !src2_wide) {
7493 tmp = neon_load_reg(rm, 1);
7494 neon_store_scratch(2, tmp);
7495 } else if (rd == rn && !src1_wide) {
7496 tmp = neon_load_reg(rn, 1);
7497 neon_store_scratch(2, tmp);
7499 tmp3 = NULL;
7500 for (pass = 0; pass < 2; pass++) {
7501 if (src1_wide) {
7502 neon_load_reg64(cpu_V0, rn + pass);
7503 tmp = NULL;
7504 } else {
7505 if (pass == 1 && rd == rn) {
7506 tmp = neon_load_scratch(2);
7507 } else {
7508 tmp = neon_load_reg(rn, pass);
7510 if (prewiden) {
7511 gen_neon_widen(cpu_V0, tmp, size, u);
7514 if (src2_wide) {
7515 neon_load_reg64(cpu_V1, rm + pass);
7516 tmp2 = NULL;
7517 } else {
7518 if (pass == 1 && rd == rm) {
7519 tmp2 = neon_load_scratch(2);
7520 } else {
7521 tmp2 = neon_load_reg(rm, pass);
7523 if (prewiden) {
7524 gen_neon_widen(cpu_V1, tmp2, size, u);
7527 switch (op) {
7528 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
7529 gen_neon_addl(size);
7530 break;
7531 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
7532 gen_neon_subl(size);
7533 break;
7534 case 5: case 7: /* VABAL, VABDL */
7535 switch ((size << 1) | u) {
7536 case 0:
7537 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
7538 break;
7539 case 1:
7540 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
7541 break;
7542 case 2:
7543 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
7544 break;
7545 case 3:
7546 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
7547 break;
7548 case 4:
7549 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
7550 break;
7551 case 5:
7552 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
7553 break;
7554 default: abort();
7556 tcg_temp_free_i32(tmp2);
7557 tcg_temp_free_i32(tmp);
7558 break;
7559 case 8: case 9: case 10: case 11: case 12: case 13:
7560 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
7561 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
7562 break;
7563 case 14: /* Polynomial VMULL */
7564 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
7565 tcg_temp_free_i32(tmp2);
7566 tcg_temp_free_i32(tmp);
7567 break;
7568 default: /* 15 is RESERVED: caught earlier */
7569 abort();
7571 if (op == 13) {
7572 /* VQDMULL */
7573 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
7574 neon_store_reg64(cpu_V0, rd + pass);
7575 } else if (op == 5 || (op >= 8 && op <= 11)) {
7576 /* Accumulate. */
7577 neon_load_reg64(cpu_V1, rd + pass);
7578 switch (op) {
7579 case 10: /* VMLSL */
7580 gen_neon_negl(cpu_V0, size);
7581 /* Fall through */
7582 case 5: case 8: /* VABAL, VMLAL */
7583 gen_neon_addl(size);
7584 break;
7585 case 9: case 11: /* VQDMLAL, VQDMLSL */
7586 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
7587 if (op == 11) {
7588 gen_neon_negl(cpu_V0, size);
7590 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
7591 break;
7592 default:
7593 abort();
7595 neon_store_reg64(cpu_V0, rd + pass);
7596 } else if (op == 4 || op == 6) {
7597 /* Narrowing operation. */
7598 tmp = tcg_temp_new_i32();
7599 if (!u) {
7600 switch (size) {
7601 case 0:
7602 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
7603 break;
7604 case 1:
7605 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
7606 break;
7607 case 2:
7608 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
7609 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
7610 break;
7611 default: abort();
7613 } else {
7614 switch (size) {
7615 case 0:
7616 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
7617 break;
7618 case 1:
7619 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
7620 break;
7621 case 2:
7622 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
7623 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
7624 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
7625 break;
7626 default: abort();
7629 if (pass == 0) {
7630 tmp3 = tmp;
7631 } else {
7632 neon_store_reg(rd, 0, tmp3);
7633 neon_store_reg(rd, 1, tmp);
7635 } else {
7636 /* Write back the result. */
7637 neon_store_reg64(cpu_V0, rd + pass);
7640 } else {
7641 /* Two registers and a scalar. NB that for ops of this form
7642 * the ARM ARM labels bit 24 as Q, but it is in our variable
7643 * 'u', not 'q'.
7645 if (size == 0) {
7646 return 1;
7648 switch (op) {
7649 case 1: /* Float VMLA scalar */
7650 case 5: /* Floating point VMLS scalar */
7651 case 9: /* Floating point VMUL scalar */
7652 if (size == 1) {
7653 return 1;
7655 /* fall through */
7656 case 0: /* Integer VMLA scalar */
7657 case 4: /* Integer VMLS scalar */
7658 case 8: /* Integer VMUL scalar */
7659 case 12: /* VQDMULH scalar */
7660 case 13: /* VQRDMULH scalar */
7661 if (u && ((rd | rn) & 1)) {
7662 return 1;
7664 tmp = neon_get_scalar(size, rm);
7665 neon_store_scratch(0, tmp);
7666 for (pass = 0; pass < (u ? 4 : 2); pass++) {
7667 tmp = neon_load_scratch(0);
7668 tmp2 = neon_load_reg(rn, pass);
7669 if (op == 12) {
7670 if (size == 1) {
7671 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
7672 } else {
7673 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
7675 } else if (op == 13) {
7676 if (size == 1) {
7677 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
7678 } else {
7679 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
7681 } else if (op & 1) {
7682 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7683 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
7684 tcg_temp_free_ptr(fpstatus);
7685 } else {
7686 switch (size) {
7687 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
7688 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
7689 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
7690 default: abort();
7693 tcg_temp_free_i32(tmp2);
7694 if (op < 8) {
7695 /* Accumulate. */
7696 tmp2 = neon_load_reg(rd, pass);
7697 switch (op) {
7698 case 0:
7699 gen_neon_add(size, tmp, tmp2);
7700 break;
7701 case 1:
7703 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7704 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
7705 tcg_temp_free_ptr(fpstatus);
7706 break;
7708 case 4:
7709 gen_neon_rsb(size, tmp, tmp2);
7710 break;
7711 case 5:
7713 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7714 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
7715 tcg_temp_free_ptr(fpstatus);
7716 break;
7718 default:
7719 abort();
7721 tcg_temp_free_i32(tmp2);
7723 neon_store_reg(rd, pass, tmp);
7725 break;
7726 case 3: /* VQDMLAL scalar */
7727 case 7: /* VQDMLSL scalar */
7728 case 11: /* VQDMULL scalar */
7729 if (u == 1) {
7730 return 1;
7732 /* fall through */
7733 case 2: /* VMLAL sclar */
7734 case 6: /* VMLSL scalar */
7735 case 10: /* VMULL scalar */
7736 if (rd & 1) {
7737 return 1;
7739 tmp2 = neon_get_scalar(size, rm);
7740 /* We need a copy of tmp2 because gen_neon_mull
7741 * deletes it during pass 0. */
7742 tmp4 = tcg_temp_new_i32();
7743 tcg_gen_mov_i32(tmp4, tmp2);
7744 tmp3 = neon_load_reg(rn, 1);
7746 for (pass = 0; pass < 2; pass++) {
7747 if (pass == 0) {
7748 tmp = neon_load_reg(rn, 0);
7749 } else {
7750 tmp = tmp3;
7751 tmp2 = tmp4;
7753 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
7754 if (op != 11) {
7755 neon_load_reg64(cpu_V1, rd + pass);
7757 switch (op) {
7758 case 6:
7759 gen_neon_negl(cpu_V0, size);
7760 /* Fall through */
7761 case 2:
7762 gen_neon_addl(size);
7763 break;
7764 case 3: case 7:
7765 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
7766 if (op == 7) {
7767 gen_neon_negl(cpu_V0, size);
7769 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
7770 break;
7771 case 10:
7772 /* no-op */
7773 break;
7774 case 11:
7775 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
7776 break;
7777 default:
7778 abort();
7780 neon_store_reg64(cpu_V0, rd + pass);
7782 break;
7783 case 14: /* VQRDMLAH scalar */
7784 case 15: /* VQRDMLSH scalar */
7786 NeonGenThreeOpEnvFn *fn;
7788 if (!dc_isar_feature(aa32_rdm, s)) {
7789 return 1;
7791 if (u && ((rd | rn) & 1)) {
7792 return 1;
7794 if (op == 14) {
7795 if (size == 1) {
7796 fn = gen_helper_neon_qrdmlah_s16;
7797 } else {
7798 fn = gen_helper_neon_qrdmlah_s32;
7800 } else {
7801 if (size == 1) {
7802 fn = gen_helper_neon_qrdmlsh_s16;
7803 } else {
7804 fn = gen_helper_neon_qrdmlsh_s32;
7808 tmp2 = neon_get_scalar(size, rm);
7809 for (pass = 0; pass < (u ? 4 : 2); pass++) {
7810 tmp = neon_load_reg(rn, pass);
7811 tmp3 = neon_load_reg(rd, pass);
7812 fn(tmp, cpu_env, tmp, tmp2, tmp3);
7813 tcg_temp_free_i32(tmp3);
7814 neon_store_reg(rd, pass, tmp);
7816 tcg_temp_free_i32(tmp2);
7818 break;
7819 default:
7820 g_assert_not_reached();
7823 } else { /* size == 3 */
7824 if (!u) {
7825 /* Extract. */
7826 imm = (insn >> 8) & 0xf;
7828 if (imm > 7 && !q)
7829 return 1;
7831 if (q && ((rd | rn | rm) & 1)) {
7832 return 1;
7835 if (imm == 0) {
7836 neon_load_reg64(cpu_V0, rn);
7837 if (q) {
7838 neon_load_reg64(cpu_V1, rn + 1);
7840 } else if (imm == 8) {
7841 neon_load_reg64(cpu_V0, rn + 1);
7842 if (q) {
7843 neon_load_reg64(cpu_V1, rm);
7845 } else if (q) {
7846 tmp64 = tcg_temp_new_i64();
7847 if (imm < 8) {
7848 neon_load_reg64(cpu_V0, rn);
7849 neon_load_reg64(tmp64, rn + 1);
7850 } else {
7851 neon_load_reg64(cpu_V0, rn + 1);
7852 neon_load_reg64(tmp64, rm);
7854 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
7855 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
7856 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
7857 if (imm < 8) {
7858 neon_load_reg64(cpu_V1, rm);
7859 } else {
7860 neon_load_reg64(cpu_V1, rm + 1);
7861 imm -= 8;
7863 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
7864 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
7865 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
7866 tcg_temp_free_i64(tmp64);
7867 } else {
7868 /* BUGFIX */
7869 neon_load_reg64(cpu_V0, rn);
7870 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
7871 neon_load_reg64(cpu_V1, rm);
7872 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
7873 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
7875 neon_store_reg64(cpu_V0, rd);
7876 if (q) {
7877 neon_store_reg64(cpu_V1, rd + 1);
7879 } else if ((insn & (1 << 11)) == 0) {
7880 /* Two register misc. */
7881 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
7882 size = (insn >> 18) & 3;
7883 /* UNDEF for unknown op values and bad op-size combinations */
7884 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
7885 return 1;
7887 if (neon_2rm_is_v8_op(op) &&
7888 !arm_dc_feature(s, ARM_FEATURE_V8)) {
7889 return 1;
7891 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
7892 q && ((rm | rd) & 1)) {
7893 return 1;
7895 switch (op) {
7896 case NEON_2RM_VREV64:
7897 for (pass = 0; pass < (q ? 2 : 1); pass++) {
7898 tmp = neon_load_reg(rm, pass * 2);
7899 tmp2 = neon_load_reg(rm, pass * 2 + 1);
7900 switch (size) {
7901 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
7902 case 1: gen_swap_half(tmp); break;
7903 case 2: /* no-op */ break;
7904 default: abort();
7906 neon_store_reg(rd, pass * 2 + 1, tmp);
7907 if (size == 2) {
7908 neon_store_reg(rd, pass * 2, tmp2);
7909 } else {
7910 switch (size) {
7911 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
7912 case 1: gen_swap_half(tmp2); break;
7913 default: abort();
7915 neon_store_reg(rd, pass * 2, tmp2);
7918 break;
7919 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
7920 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
7921 for (pass = 0; pass < q + 1; pass++) {
7922 tmp = neon_load_reg(rm, pass * 2);
7923 gen_neon_widen(cpu_V0, tmp, size, op & 1);
7924 tmp = neon_load_reg(rm, pass * 2 + 1);
7925 gen_neon_widen(cpu_V1, tmp, size, op & 1);
7926 switch (size) {
7927 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
7928 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
7929 case 2: tcg_gen_add_i64(CPU_V001); break;
7930 default: abort();
7932 if (op >= NEON_2RM_VPADAL) {
7933 /* Accumulate. */
7934 neon_load_reg64(cpu_V1, rd + pass);
7935 gen_neon_addl(size);
7937 neon_store_reg64(cpu_V0, rd + pass);
7939 break;
7940 case NEON_2RM_VTRN:
7941 if (size == 2) {
7942 int n;
7943 for (n = 0; n < (q ? 4 : 2); n += 2) {
7944 tmp = neon_load_reg(rm, n);
7945 tmp2 = neon_load_reg(rd, n + 1);
7946 neon_store_reg(rm, n, tmp2);
7947 neon_store_reg(rd, n + 1, tmp);
7949 } else {
7950 goto elementwise;
7952 break;
7953 case NEON_2RM_VUZP:
7954 if (gen_neon_unzip(rd, rm, size, q)) {
7955 return 1;
7957 break;
7958 case NEON_2RM_VZIP:
7959 if (gen_neon_zip(rd, rm, size, q)) {
7960 return 1;
7962 break;
7963 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
7964 /* also VQMOVUN; op field and mnemonics don't line up */
7965 if (rm & 1) {
7966 return 1;
7968 tmp2 = NULL;
7969 for (pass = 0; pass < 2; pass++) {
7970 neon_load_reg64(cpu_V0, rm + pass);
7971 tmp = tcg_temp_new_i32();
7972 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
7973 tmp, cpu_V0);
7974 if (pass == 0) {
7975 tmp2 = tmp;
7976 } else {
7977 neon_store_reg(rd, 0, tmp2);
7978 neon_store_reg(rd, 1, tmp);
7981 break;
7982 case NEON_2RM_VSHLL:
7983 if (q || (rd & 1)) {
7984 return 1;
7986 tmp = neon_load_reg(rm, 0);
7987 tmp2 = neon_load_reg(rm, 1);
7988 for (pass = 0; pass < 2; pass++) {
7989 if (pass == 1)
7990 tmp = tmp2;
7991 gen_neon_widen(cpu_V0, tmp, size, 1);
7992 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
7993 neon_store_reg64(cpu_V0, rd + pass);
7995 break;
7996 case NEON_2RM_VCVT_F16_F32:
7998 TCGv_ptr fpst;
7999 TCGv_i32 ahp;
8001 if (!dc_isar_feature(aa32_fp16_spconv, s) ||
8002 q || (rm & 1)) {
8003 return 1;
8005 tmp = tcg_temp_new_i32();
8006 tmp2 = tcg_temp_new_i32();
8007 fpst = get_fpstatus_ptr(true);
8008 ahp = get_ahp_flag();
8009 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
8010 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, fpst, ahp);
8011 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
8012 gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, fpst, ahp);
8013 tcg_gen_shli_i32(tmp2, tmp2, 16);
8014 tcg_gen_or_i32(tmp2, tmp2, tmp);
8015 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
8016 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, fpst, ahp);
8017 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
8018 neon_store_reg(rd, 0, tmp2);
8019 tmp2 = tcg_temp_new_i32();
8020 gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, fpst, ahp);
8021 tcg_gen_shli_i32(tmp2, tmp2, 16);
8022 tcg_gen_or_i32(tmp2, tmp2, tmp);
8023 neon_store_reg(rd, 1, tmp2);
8024 tcg_temp_free_i32(tmp);
8025 tcg_temp_free_i32(ahp);
8026 tcg_temp_free_ptr(fpst);
8027 break;
8029 case NEON_2RM_VCVT_F32_F16:
8031 TCGv_ptr fpst;
8032 TCGv_i32 ahp;
8033 if (!dc_isar_feature(aa32_fp16_spconv, s) ||
8034 q || (rd & 1)) {
8035 return 1;
8037 fpst = get_fpstatus_ptr(true);
8038 ahp = get_ahp_flag();
8039 tmp3 = tcg_temp_new_i32();
8040 tmp = neon_load_reg(rm, 0);
8041 tmp2 = neon_load_reg(rm, 1);
8042 tcg_gen_ext16u_i32(tmp3, tmp);
8043 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
8044 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
8045 tcg_gen_shri_i32(tmp3, tmp, 16);
8046 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
8047 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
8048 tcg_temp_free_i32(tmp);
8049 tcg_gen_ext16u_i32(tmp3, tmp2);
8050 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
8051 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
8052 tcg_gen_shri_i32(tmp3, tmp2, 16);
8053 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
8054 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
8055 tcg_temp_free_i32(tmp2);
8056 tcg_temp_free_i32(tmp3);
8057 tcg_temp_free_i32(ahp);
8058 tcg_temp_free_ptr(fpst);
8059 break;
8061 case NEON_2RM_AESE: case NEON_2RM_AESMC:
8062 if (!dc_isar_feature(aa32_aes, s) || ((rm | rd) & 1)) {
8063 return 1;
8065 ptr1 = vfp_reg_ptr(true, rd);
8066 ptr2 = vfp_reg_ptr(true, rm);
8068 /* Bit 6 is the lowest opcode bit; it distinguishes between
8069 * encryption (AESE/AESMC) and decryption (AESD/AESIMC)
8071 tmp3 = tcg_const_i32(extract32(insn, 6, 1));
8073 if (op == NEON_2RM_AESE) {
8074 gen_helper_crypto_aese(ptr1, ptr2, tmp3);
8075 } else {
8076 gen_helper_crypto_aesmc(ptr1, ptr2, tmp3);
8078 tcg_temp_free_ptr(ptr1);
8079 tcg_temp_free_ptr(ptr2);
8080 tcg_temp_free_i32(tmp3);
8081 break;
8082 case NEON_2RM_SHA1H:
8083 if (!dc_isar_feature(aa32_sha1, s) || ((rm | rd) & 1)) {
8084 return 1;
8086 ptr1 = vfp_reg_ptr(true, rd);
8087 ptr2 = vfp_reg_ptr(true, rm);
8089 gen_helper_crypto_sha1h(ptr1, ptr2);
8091 tcg_temp_free_ptr(ptr1);
8092 tcg_temp_free_ptr(ptr2);
8093 break;
8094 case NEON_2RM_SHA1SU1:
8095 if ((rm | rd) & 1) {
8096 return 1;
8098 /* bit 6 (q): set -> SHA256SU0, cleared -> SHA1SU1 */
8099 if (q) {
8100 if (!dc_isar_feature(aa32_sha2, s)) {
8101 return 1;
8103 } else if (!dc_isar_feature(aa32_sha1, s)) {
8104 return 1;
8106 ptr1 = vfp_reg_ptr(true, rd);
8107 ptr2 = vfp_reg_ptr(true, rm);
8108 if (q) {
8109 gen_helper_crypto_sha256su0(ptr1, ptr2);
8110 } else {
8111 gen_helper_crypto_sha1su1(ptr1, ptr2);
8113 tcg_temp_free_ptr(ptr1);
8114 tcg_temp_free_ptr(ptr2);
8115 break;
8117 case NEON_2RM_VMVN:
8118 tcg_gen_gvec_not(0, rd_ofs, rm_ofs, vec_size, vec_size);
8119 break;
8120 case NEON_2RM_VNEG:
8121 tcg_gen_gvec_neg(size, rd_ofs, rm_ofs, vec_size, vec_size);
8122 break;
8123 case NEON_2RM_VABS:
8124 tcg_gen_gvec_abs(size, rd_ofs, rm_ofs, vec_size, vec_size);
8125 break;
8127 default:
8128 elementwise:
8129 for (pass = 0; pass < (q ? 4 : 2); pass++) {
8130 if (neon_2rm_is_float_op(op)) {
8131 tcg_gen_ld_f32(cpu_F0s, cpu_env,
8132 neon_reg_offset(rm, pass));
8133 tmp = NULL;
8134 } else {
8135 tmp = neon_load_reg(rm, pass);
8137 switch (op) {
8138 case NEON_2RM_VREV32:
8139 switch (size) {
8140 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
8141 case 1: gen_swap_half(tmp); break;
8142 default: abort();
8144 break;
8145 case NEON_2RM_VREV16:
8146 gen_rev16(tmp);
8147 break;
8148 case NEON_2RM_VCLS:
8149 switch (size) {
8150 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
8151 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
8152 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
8153 default: abort();
8155 break;
8156 case NEON_2RM_VCLZ:
8157 switch (size) {
8158 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
8159 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
8160 case 2: tcg_gen_clzi_i32(tmp, tmp, 32); break;
8161 default: abort();
8163 break;
8164 case NEON_2RM_VCNT:
8165 gen_helper_neon_cnt_u8(tmp, tmp);
8166 break;
8167 case NEON_2RM_VQABS:
8168 switch (size) {
8169 case 0:
8170 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
8171 break;
8172 case 1:
8173 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
8174 break;
8175 case 2:
8176 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
8177 break;
8178 default: abort();
8180 break;
8181 case NEON_2RM_VQNEG:
8182 switch (size) {
8183 case 0:
8184 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
8185 break;
8186 case 1:
8187 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
8188 break;
8189 case 2:
8190 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
8191 break;
8192 default: abort();
8194 break;
8195 case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
8196 tmp2 = tcg_const_i32(0);
8197 switch(size) {
8198 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
8199 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
8200 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
8201 default: abort();
8203 tcg_temp_free_i32(tmp2);
8204 if (op == NEON_2RM_VCLE0) {
8205 tcg_gen_not_i32(tmp, tmp);
8207 break;
8208 case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
8209 tmp2 = tcg_const_i32(0);
8210 switch(size) {
8211 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
8212 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
8213 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
8214 default: abort();
8216 tcg_temp_free_i32(tmp2);
8217 if (op == NEON_2RM_VCLT0) {
8218 tcg_gen_not_i32(tmp, tmp);
8220 break;
8221 case NEON_2RM_VCEQ0:
8222 tmp2 = tcg_const_i32(0);
8223 switch(size) {
8224 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
8225 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
8226 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
8227 default: abort();
8229 tcg_temp_free_i32(tmp2);
8230 break;
8231 case NEON_2RM_VCGT0_F:
8233 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8234 tmp2 = tcg_const_i32(0);
8235 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
8236 tcg_temp_free_i32(tmp2);
8237 tcg_temp_free_ptr(fpstatus);
8238 break;
8240 case NEON_2RM_VCGE0_F:
8242 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8243 tmp2 = tcg_const_i32(0);
8244 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
8245 tcg_temp_free_i32(tmp2);
8246 tcg_temp_free_ptr(fpstatus);
8247 break;
8249 case NEON_2RM_VCEQ0_F:
8251 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8252 tmp2 = tcg_const_i32(0);
8253 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
8254 tcg_temp_free_i32(tmp2);
8255 tcg_temp_free_ptr(fpstatus);
8256 break;
8258 case NEON_2RM_VCLE0_F:
8260 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8261 tmp2 = tcg_const_i32(0);
8262 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
8263 tcg_temp_free_i32(tmp2);
8264 tcg_temp_free_ptr(fpstatus);
8265 break;
8267 case NEON_2RM_VCLT0_F:
8269 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8270 tmp2 = tcg_const_i32(0);
8271 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
8272 tcg_temp_free_i32(tmp2);
8273 tcg_temp_free_ptr(fpstatus);
8274 break;
8276 case NEON_2RM_VABS_F:
8277 gen_vfp_abs(0);
8278 break;
8279 case NEON_2RM_VNEG_F:
8280 gen_vfp_neg(0);
8281 break;
8282 case NEON_2RM_VSWP:
8283 tmp2 = neon_load_reg(rd, pass);
8284 neon_store_reg(rm, pass, tmp2);
8285 break;
8286 case NEON_2RM_VTRN:
8287 tmp2 = neon_load_reg(rd, pass);
8288 switch (size) {
8289 case 0: gen_neon_trn_u8(tmp, tmp2); break;
8290 case 1: gen_neon_trn_u16(tmp, tmp2); break;
8291 default: abort();
8293 neon_store_reg(rm, pass, tmp2);
8294 break;
8295 case NEON_2RM_VRINTN:
8296 case NEON_2RM_VRINTA:
8297 case NEON_2RM_VRINTM:
8298 case NEON_2RM_VRINTP:
8299 case NEON_2RM_VRINTZ:
8301 TCGv_i32 tcg_rmode;
8302 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8303 int rmode;
8305 if (op == NEON_2RM_VRINTZ) {
8306 rmode = FPROUNDING_ZERO;
8307 } else {
8308 rmode = fp_decode_rm[((op & 0x6) >> 1) ^ 1];
8311 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
8312 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
8313 cpu_env);
8314 gen_helper_rints(cpu_F0s, cpu_F0s, fpstatus);
8315 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
8316 cpu_env);
8317 tcg_temp_free_ptr(fpstatus);
8318 tcg_temp_free_i32(tcg_rmode);
8319 break;
8321 case NEON_2RM_VRINTX:
8323 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8324 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpstatus);
8325 tcg_temp_free_ptr(fpstatus);
8326 break;
8328 case NEON_2RM_VCVTAU:
8329 case NEON_2RM_VCVTAS:
8330 case NEON_2RM_VCVTNU:
8331 case NEON_2RM_VCVTNS:
8332 case NEON_2RM_VCVTPU:
8333 case NEON_2RM_VCVTPS:
8334 case NEON_2RM_VCVTMU:
8335 case NEON_2RM_VCVTMS:
8337 bool is_signed = !extract32(insn, 7, 1);
8338 TCGv_ptr fpst = get_fpstatus_ptr(1);
8339 TCGv_i32 tcg_rmode, tcg_shift;
8340 int rmode = fp_decode_rm[extract32(insn, 8, 2)];
8342 tcg_shift = tcg_const_i32(0);
8343 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
8344 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
8345 cpu_env);
8347 if (is_signed) {
8348 gen_helper_vfp_tosls(cpu_F0s, cpu_F0s,
8349 tcg_shift, fpst);
8350 } else {
8351 gen_helper_vfp_touls(cpu_F0s, cpu_F0s,
8352 tcg_shift, fpst);
8355 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
8356 cpu_env);
8357 tcg_temp_free_i32(tcg_rmode);
8358 tcg_temp_free_i32(tcg_shift);
8359 tcg_temp_free_ptr(fpst);
8360 break;
8362 case NEON_2RM_VRECPE:
8364 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8365 gen_helper_recpe_u32(tmp, tmp, fpstatus);
8366 tcg_temp_free_ptr(fpstatus);
8367 break;
8369 case NEON_2RM_VRSQRTE:
8371 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8372 gen_helper_rsqrte_u32(tmp, tmp, fpstatus);
8373 tcg_temp_free_ptr(fpstatus);
8374 break;
8376 case NEON_2RM_VRECPE_F:
8378 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8379 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, fpstatus);
8380 tcg_temp_free_ptr(fpstatus);
8381 break;
8383 case NEON_2RM_VRSQRTE_F:
8385 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8386 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, fpstatus);
8387 tcg_temp_free_ptr(fpstatus);
8388 break;
8390 case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
8391 gen_vfp_sito(0, 1);
8392 break;
8393 case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
8394 gen_vfp_uito(0, 1);
8395 break;
8396 case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
8397 gen_vfp_tosiz(0, 1);
8398 break;
8399 case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
8400 gen_vfp_touiz(0, 1);
8401 break;
8402 default:
8403 /* Reserved op values were caught by the
8404 * neon_2rm_sizes[] check earlier.
8406 abort();
8408 if (neon_2rm_is_float_op(op)) {
8409 tcg_gen_st_f32(cpu_F0s, cpu_env,
8410 neon_reg_offset(rd, pass));
8411 } else {
8412 neon_store_reg(rd, pass, tmp);
8415 break;
8417 } else if ((insn & (1 << 10)) == 0) {
8418 /* VTBL, VTBX. */
8419 int n = ((insn >> 8) & 3) + 1;
8420 if ((rn + n) > 32) {
8421 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
8422 * helper function running off the end of the register file.
8424 return 1;
8426 n <<= 3;
8427 if (insn & (1 << 6)) {
8428 tmp = neon_load_reg(rd, 0);
8429 } else {
8430 tmp = tcg_temp_new_i32();
8431 tcg_gen_movi_i32(tmp, 0);
8433 tmp2 = neon_load_reg(rm, 0);
8434 ptr1 = vfp_reg_ptr(true, rn);
8435 tmp5 = tcg_const_i32(n);
8436 gen_helper_neon_tbl(tmp2, tmp2, tmp, ptr1, tmp5);
8437 tcg_temp_free_i32(tmp);
8438 if (insn & (1 << 6)) {
8439 tmp = neon_load_reg(rd, 1);
8440 } else {
8441 tmp = tcg_temp_new_i32();
8442 tcg_gen_movi_i32(tmp, 0);
8444 tmp3 = neon_load_reg(rm, 1);
8445 gen_helper_neon_tbl(tmp3, tmp3, tmp, ptr1, tmp5);
8446 tcg_temp_free_i32(tmp5);
8447 tcg_temp_free_ptr(ptr1);
8448 neon_store_reg(rd, 0, tmp2);
8449 neon_store_reg(rd, 1, tmp3);
8450 tcg_temp_free_i32(tmp);
8451 } else if ((insn & 0x380) == 0) {
8452 /* VDUP */
8453 int element;
8454 TCGMemOp size;
8456 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
8457 return 1;
8459 if (insn & (1 << 16)) {
8460 size = MO_8;
8461 element = (insn >> 17) & 7;
8462 } else if (insn & (1 << 17)) {
8463 size = MO_16;
8464 element = (insn >> 18) & 3;
8465 } else {
8466 size = MO_32;
8467 element = (insn >> 19) & 1;
8469 tcg_gen_gvec_dup_mem(size, neon_reg_offset(rd, 0),
8470 neon_element_offset(rm, element, size),
8471 q ? 16 : 8, q ? 16 : 8);
8472 } else {
8473 return 1;
8477 return 0;
8480 /* Advanced SIMD three registers of the same length extension.
8481 * 31 25 23 22 20 16 12 11 10 9 8 3 0
8482 * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
8483 * | 1 1 1 1 1 1 0 | op1 | D | op2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
8484 * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
8486 static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
8488 gen_helper_gvec_3 *fn_gvec = NULL;
8489 gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
8490 int rd, rn, rm, opr_sz;
8491 int data = 0;
8492 int off_rn, off_rm;
8493 bool is_long = false, q = extract32(insn, 6, 1);
8494 bool ptr_is_env = false;
8496 if ((insn & 0xfe200f10) == 0xfc200800) {
8497 /* VCMLA -- 1111 110R R.1S .... .... 1000 ...0 .... */
8498 int size = extract32(insn, 20, 1);
8499 data = extract32(insn, 23, 2); /* rot */
8500 if (!dc_isar_feature(aa32_vcma, s)
8501 || (!size && !dc_isar_feature(aa32_fp16_arith, s))) {
8502 return 1;
8504 fn_gvec_ptr = size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
8505 } else if ((insn & 0xfea00f10) == 0xfc800800) {
8506 /* VCADD -- 1111 110R 1.0S .... .... 1000 ...0 .... */
8507 int size = extract32(insn, 20, 1);
8508 data = extract32(insn, 24, 1); /* rot */
8509 if (!dc_isar_feature(aa32_vcma, s)
8510 || (!size && !dc_isar_feature(aa32_fp16_arith, s))) {
8511 return 1;
8513 fn_gvec_ptr = size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
8514 } else if ((insn & 0xfeb00f00) == 0xfc200d00) {
8515 /* V[US]DOT -- 1111 1100 0.10 .... .... 1101 .Q.U .... */
8516 bool u = extract32(insn, 4, 1);
8517 if (!dc_isar_feature(aa32_dp, s)) {
8518 return 1;
8520 fn_gvec = u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b;
8521 } else if ((insn & 0xff300f10) == 0xfc200810) {
8522 /* VFM[AS]L -- 1111 1100 S.10 .... .... 1000 .Q.1 .... */
8523 int is_s = extract32(insn, 23, 1);
8524 if (!dc_isar_feature(aa32_fhm, s)) {
8525 return 1;
8527 is_long = true;
8528 data = is_s; /* is_2 == 0 */
8529 fn_gvec_ptr = gen_helper_gvec_fmlal_a32;
8530 ptr_is_env = true;
8531 } else {
8532 return 1;
8535 VFP_DREG_D(rd, insn);
8536 if (rd & q) {
8537 return 1;
8539 if (q || !is_long) {
8540 VFP_DREG_N(rn, insn);
8541 VFP_DREG_M(rm, insn);
8542 if ((rn | rm) & q & !is_long) {
8543 return 1;
8545 off_rn = vfp_reg_offset(1, rn);
8546 off_rm = vfp_reg_offset(1, rm);
8547 } else {
8548 rn = VFP_SREG_N(insn);
8549 rm = VFP_SREG_M(insn);
8550 off_rn = vfp_reg_offset(0, rn);
8551 off_rm = vfp_reg_offset(0, rm);
8554 if (s->fp_excp_el) {
8555 gen_exception_insn(s, 4, EXCP_UDEF,
8556 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
8557 return 0;
8559 if (!s->vfp_enabled) {
8560 return 1;
8563 opr_sz = (1 + q) * 8;
8564 if (fn_gvec_ptr) {
8565 TCGv_ptr ptr;
8566 if (ptr_is_env) {
8567 ptr = cpu_env;
8568 } else {
8569 ptr = get_fpstatus_ptr(1);
8571 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
8572 opr_sz, opr_sz, data, fn_gvec_ptr);
8573 if (!ptr_is_env) {
8574 tcg_temp_free_ptr(ptr);
8576 } else {
8577 tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
8578 opr_sz, opr_sz, data, fn_gvec);
8580 return 0;
8583 /* Advanced SIMD two registers and a scalar extension.
8584 * 31 24 23 22 20 16 12 11 10 9 8 3 0
8585 * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
8586 * | 1 1 1 1 1 1 1 0 | o1 | D | o2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
8587 * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
8591 static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
8593 gen_helper_gvec_3 *fn_gvec = NULL;
8594 gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
8595 int rd, rn, rm, opr_sz, data;
8596 int off_rn, off_rm;
8597 bool is_long = false, q = extract32(insn, 6, 1);
8598 bool ptr_is_env = false;
8600 if ((insn & 0xff000f10) == 0xfe000800) {
8601 /* VCMLA (indexed) -- 1111 1110 S.RR .... .... 1000 ...0 .... */
8602 int rot = extract32(insn, 20, 2);
8603 int size = extract32(insn, 23, 1);
8604 int index;
8606 if (!dc_isar_feature(aa32_vcma, s)) {
8607 return 1;
8609 if (size == 0) {
8610 if (!dc_isar_feature(aa32_fp16_arith, s)) {
8611 return 1;
8613 /* For fp16, rm is just Vm, and index is M. */
8614 rm = extract32(insn, 0, 4);
8615 index = extract32(insn, 5, 1);
8616 } else {
8617 /* For fp32, rm is the usual M:Vm, and index is 0. */
8618 VFP_DREG_M(rm, insn);
8619 index = 0;
8621 data = (index << 2) | rot;
8622 fn_gvec_ptr = (size ? gen_helper_gvec_fcmlas_idx
8623 : gen_helper_gvec_fcmlah_idx);
8624 } else if ((insn & 0xffb00f00) == 0xfe200d00) {
8625 /* V[US]DOT -- 1111 1110 0.10 .... .... 1101 .Q.U .... */
8626 int u = extract32(insn, 4, 1);
8628 if (!dc_isar_feature(aa32_dp, s)) {
8629 return 1;
8631 fn_gvec = u ? gen_helper_gvec_udot_idx_b : gen_helper_gvec_sdot_idx_b;
8632 /* rm is just Vm, and index is M. */
8633 data = extract32(insn, 5, 1); /* index */
8634 rm = extract32(insn, 0, 4);
8635 } else if ((insn & 0xffa00f10) == 0xfe000810) {
8636 /* VFM[AS]L -- 1111 1110 0.0S .... .... 1000 .Q.1 .... */
8637 int is_s = extract32(insn, 20, 1);
8638 int vm20 = extract32(insn, 0, 3);
8639 int vm3 = extract32(insn, 3, 1);
8640 int m = extract32(insn, 5, 1);
8641 int index;
8643 if (!dc_isar_feature(aa32_fhm, s)) {
8644 return 1;
8646 if (q) {
8647 rm = vm20;
8648 index = m * 2 + vm3;
8649 } else {
8650 rm = vm20 * 2 + m;
8651 index = vm3;
8653 is_long = true;
8654 data = (index << 2) | is_s; /* is_2 == 0 */
8655 fn_gvec_ptr = gen_helper_gvec_fmlal_idx_a32;
8656 ptr_is_env = true;
8657 } else {
8658 return 1;
8661 VFP_DREG_D(rd, insn);
8662 if (rd & q) {
8663 return 1;
8665 if (q || !is_long) {
8666 VFP_DREG_N(rn, insn);
8667 if (rn & q & !is_long) {
8668 return 1;
8670 off_rn = vfp_reg_offset(1, rn);
8671 off_rm = vfp_reg_offset(1, rm);
8672 } else {
8673 rn = VFP_SREG_N(insn);
8674 off_rn = vfp_reg_offset(0, rn);
8675 off_rm = vfp_reg_offset(0, rm);
8677 if (s->fp_excp_el) {
8678 gen_exception_insn(s, 4, EXCP_UDEF,
8679 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
8680 return 0;
8682 if (!s->vfp_enabled) {
8683 return 1;
8686 opr_sz = (1 + q) * 8;
8687 if (fn_gvec_ptr) {
8688 TCGv_ptr ptr;
8689 if (ptr_is_env) {
8690 ptr = cpu_env;
8691 } else {
8692 ptr = get_fpstatus_ptr(1);
8694 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
8695 opr_sz, opr_sz, data, fn_gvec_ptr);
8696 if (!ptr_is_env) {
8697 tcg_temp_free_ptr(ptr);
8699 } else {
8700 tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
8701 opr_sz, opr_sz, data, fn_gvec);
8703 return 0;
8706 static int disas_coproc_insn(DisasContext *s, uint32_t insn)
8708 int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
8709 const ARMCPRegInfo *ri;
8711 cpnum = (insn >> 8) & 0xf;
8713 /* First check for coprocessor space used for XScale/iwMMXt insns */
8714 if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cpnum < 2)) {
8715 if (extract32(s->c15_cpar, cpnum, 1) == 0) {
8716 return 1;
8718 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
8719 return disas_iwmmxt_insn(s, insn);
8720 } else if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
8721 return disas_dsp_insn(s, insn);
8723 return 1;
8726 /* Otherwise treat as a generic register access */
8727 is64 = (insn & (1 << 25)) == 0;
8728 if (!is64 && ((insn & (1 << 4)) == 0)) {
8729 /* cdp */
8730 return 1;
8733 crm = insn & 0xf;
8734 if (is64) {
8735 crn = 0;
8736 opc1 = (insn >> 4) & 0xf;
8737 opc2 = 0;
8738 rt2 = (insn >> 16) & 0xf;
8739 } else {
8740 crn = (insn >> 16) & 0xf;
8741 opc1 = (insn >> 21) & 7;
8742 opc2 = (insn >> 5) & 7;
8743 rt2 = 0;
8745 isread = (insn >> 20) & 1;
8746 rt = (insn >> 12) & 0xf;
8748 ri = get_arm_cp_reginfo(s->cp_regs,
8749 ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
8750 if (ri) {
8751 /* Check access permissions */
8752 if (!cp_access_ok(s->current_el, ri, isread)) {
8753 return 1;
8756 if (ri->accessfn ||
8757 (arm_dc_feature(s, ARM_FEATURE_XSCALE) && cpnum < 14)) {
8758 /* Emit code to perform further access permissions checks at
8759 * runtime; this may result in an exception.
8760 * Note that on XScale all cp0..c13 registers do an access check
8761 * call in order to handle c15_cpar.
8763 TCGv_ptr tmpptr;
8764 TCGv_i32 tcg_syn, tcg_isread;
8765 uint32_t syndrome;
8767 /* Note that since we are an implementation which takes an
8768 * exception on a trapped conditional instruction only if the
8769 * instruction passes its condition code check, we can take
8770 * advantage of the clause in the ARM ARM that allows us to set
8771 * the COND field in the instruction to 0xE in all cases.
8772 * We could fish the actual condition out of the insn (ARM)
8773 * or the condexec bits (Thumb) but it isn't necessary.
8775 switch (cpnum) {
8776 case 14:
8777 if (is64) {
8778 syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
8779 isread, false);
8780 } else {
8781 syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
8782 rt, isread, false);
8784 break;
8785 case 15:
8786 if (is64) {
8787 syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
8788 isread, false);
8789 } else {
8790 syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
8791 rt, isread, false);
8793 break;
8794 default:
8795 /* ARMv8 defines that only coprocessors 14 and 15 exist,
8796 * so this can only happen if this is an ARMv7 or earlier CPU,
8797 * in which case the syndrome information won't actually be
8798 * guest visible.
8800 assert(!arm_dc_feature(s, ARM_FEATURE_V8));
8801 syndrome = syn_uncategorized();
8802 break;
8805 gen_set_condexec(s);
8806 gen_set_pc_im(s, s->pc - 4);
8807 tmpptr = tcg_const_ptr(ri);
8808 tcg_syn = tcg_const_i32(syndrome);
8809 tcg_isread = tcg_const_i32(isread);
8810 gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn,
8811 tcg_isread);
8812 tcg_temp_free_ptr(tmpptr);
8813 tcg_temp_free_i32(tcg_syn);
8814 tcg_temp_free_i32(tcg_isread);
8817 /* Handle special cases first */
8818 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
8819 case ARM_CP_NOP:
8820 return 0;
8821 case ARM_CP_WFI:
8822 if (isread) {
8823 return 1;
8825 gen_set_pc_im(s, s->pc);
8826 s->base.is_jmp = DISAS_WFI;
8827 return 0;
8828 default:
8829 break;
8832 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
8833 gen_io_start();
8836 if (isread) {
8837 /* Read */
8838 if (is64) {
8839 TCGv_i64 tmp64;
8840 TCGv_i32 tmp;
8841 if (ri->type & ARM_CP_CONST) {
8842 tmp64 = tcg_const_i64(ri->resetvalue);
8843 } else if (ri->readfn) {
8844 TCGv_ptr tmpptr;
8845 tmp64 = tcg_temp_new_i64();
8846 tmpptr = tcg_const_ptr(ri);
8847 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
8848 tcg_temp_free_ptr(tmpptr);
8849 } else {
8850 tmp64 = tcg_temp_new_i64();
8851 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
8853 tmp = tcg_temp_new_i32();
8854 tcg_gen_extrl_i64_i32(tmp, tmp64);
8855 store_reg(s, rt, tmp);
8856 tcg_gen_shri_i64(tmp64, tmp64, 32);
8857 tmp = tcg_temp_new_i32();
8858 tcg_gen_extrl_i64_i32(tmp, tmp64);
8859 tcg_temp_free_i64(tmp64);
8860 store_reg(s, rt2, tmp);
8861 } else {
8862 TCGv_i32 tmp;
8863 if (ri->type & ARM_CP_CONST) {
8864 tmp = tcg_const_i32(ri->resetvalue);
8865 } else if (ri->readfn) {
8866 TCGv_ptr tmpptr;
8867 tmp = tcg_temp_new_i32();
8868 tmpptr = tcg_const_ptr(ri);
8869 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
8870 tcg_temp_free_ptr(tmpptr);
8871 } else {
8872 tmp = load_cpu_offset(ri->fieldoffset);
8874 if (rt == 15) {
8875 /* Destination register of r15 for 32 bit loads sets
8876 * the condition codes from the high 4 bits of the value
8878 gen_set_nzcv(tmp);
8879 tcg_temp_free_i32(tmp);
8880 } else {
8881 store_reg(s, rt, tmp);
8884 } else {
8885 /* Write */
8886 if (ri->type & ARM_CP_CONST) {
8887 /* If not forbidden by access permissions, treat as WI */
8888 return 0;
8891 if (is64) {
8892 TCGv_i32 tmplo, tmphi;
8893 TCGv_i64 tmp64 = tcg_temp_new_i64();
8894 tmplo = load_reg(s, rt);
8895 tmphi = load_reg(s, rt2);
8896 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
8897 tcg_temp_free_i32(tmplo);
8898 tcg_temp_free_i32(tmphi);
8899 if (ri->writefn) {
8900 TCGv_ptr tmpptr = tcg_const_ptr(ri);
8901 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
8902 tcg_temp_free_ptr(tmpptr);
8903 } else {
8904 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
8906 tcg_temp_free_i64(tmp64);
8907 } else {
8908 if (ri->writefn) {
8909 TCGv_i32 tmp;
8910 TCGv_ptr tmpptr;
8911 tmp = load_reg(s, rt);
8912 tmpptr = tcg_const_ptr(ri);
8913 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
8914 tcg_temp_free_ptr(tmpptr);
8915 tcg_temp_free_i32(tmp);
8916 } else {
8917 TCGv_i32 tmp = load_reg(s, rt);
8918 store_cpu_offset(tmp, ri->fieldoffset);
8923 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
8924 /* I/O operations must end the TB here (whether read or write) */
8925 gen_io_end();
8926 gen_lookup_tb(s);
8927 } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
8928 /* We default to ending the TB on a coprocessor register write,
8929 * but allow this to be suppressed by the register definition
8930 * (usually only necessary to work around guest bugs).
8932 gen_lookup_tb(s);
8935 return 0;
8938 /* Unknown register; this might be a guest error or a QEMU
8939 * unimplemented feature.
8941 if (is64) {
8942 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
8943 "64 bit system register cp:%d opc1: %d crm:%d "
8944 "(%s)\n",
8945 isread ? "read" : "write", cpnum, opc1, crm,
8946 s->ns ? "non-secure" : "secure");
8947 } else {
8948 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
8949 "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d "
8950 "(%s)\n",
8951 isread ? "read" : "write", cpnum, opc1, crn, crm, opc2,
8952 s->ns ? "non-secure" : "secure");
8955 return 1;
8959 /* Store a 64-bit value to a register pair. Clobbers val. */
8960 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
8962 TCGv_i32 tmp;
8963 tmp = tcg_temp_new_i32();
8964 tcg_gen_extrl_i64_i32(tmp, val);
8965 store_reg(s, rlow, tmp);
8966 tmp = tcg_temp_new_i32();
8967 tcg_gen_shri_i64(val, val, 32);
8968 tcg_gen_extrl_i64_i32(tmp, val);
8969 store_reg(s, rhigh, tmp);
8972 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
8973 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
8975 TCGv_i64 tmp;
8976 TCGv_i32 tmp2;
8978 /* Load value and extend to 64 bits. */
8979 tmp = tcg_temp_new_i64();
8980 tmp2 = load_reg(s, rlow);
8981 tcg_gen_extu_i32_i64(tmp, tmp2);
8982 tcg_temp_free_i32(tmp2);
8983 tcg_gen_add_i64(val, val, tmp);
8984 tcg_temp_free_i64(tmp);
8987 /* load and add a 64-bit value from a register pair. */
8988 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
8990 TCGv_i64 tmp;
8991 TCGv_i32 tmpl;
8992 TCGv_i32 tmph;
8994 /* Load 64-bit value rd:rn. */
8995 tmpl = load_reg(s, rlow);
8996 tmph = load_reg(s, rhigh);
8997 tmp = tcg_temp_new_i64();
8998 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
8999 tcg_temp_free_i32(tmpl);
9000 tcg_temp_free_i32(tmph);
9001 tcg_gen_add_i64(val, val, tmp);
9002 tcg_temp_free_i64(tmp);
9005 /* Set N and Z flags from hi|lo. */
9006 static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
9008 tcg_gen_mov_i32(cpu_NF, hi);
9009 tcg_gen_or_i32(cpu_ZF, lo, hi);
9012 /* Load/Store exclusive instructions are implemented by remembering
9013 the value/address loaded, and seeing if these are the same
9014 when the store is performed. This should be sufficient to implement
9015 the architecturally mandated semantics, and avoids having to monitor
9016 regular stores. The compare vs the remembered value is done during
9017 the cmpxchg operation, but we must compare the addresses manually. */
9018 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
9019 TCGv_i32 addr, int size)
9021 TCGv_i32 tmp = tcg_temp_new_i32();
9022 TCGMemOp opc = size | MO_ALIGN | s->be_data;
9024 s->is_ldex = true;
9026 if (size == 3) {
9027 TCGv_i32 tmp2 = tcg_temp_new_i32();
9028 TCGv_i64 t64 = tcg_temp_new_i64();
9030 /* For AArch32, architecturally the 32-bit word at the lowest
9031 * address is always Rt and the one at addr+4 is Rt2, even if
9032 * the CPU is big-endian. That means we don't want to do a
9033 * gen_aa32_ld_i64(), which invokes gen_aa32_frob64() as if
9034 * for an architecturally 64-bit access, but instead do a
9035 * 64-bit access using MO_BE if appropriate and then split
9036 * the two halves.
9037 * This only makes a difference for BE32 user-mode, where
9038 * frob64() must not flip the two halves of the 64-bit data
9039 * but this code must treat BE32 user-mode like BE32 system.
9041 TCGv taddr = gen_aa32_addr(s, addr, opc);
9043 tcg_gen_qemu_ld_i64(t64, taddr, get_mem_index(s), opc);
9044 tcg_temp_free(taddr);
9045 tcg_gen_mov_i64(cpu_exclusive_val, t64);
9046 if (s->be_data == MO_BE) {
9047 tcg_gen_extr_i64_i32(tmp2, tmp, t64);
9048 } else {
9049 tcg_gen_extr_i64_i32(tmp, tmp2, t64);
9051 tcg_temp_free_i64(t64);
9053 store_reg(s, rt2, tmp2);
9054 } else {
9055 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), opc);
9056 tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
9059 store_reg(s, rt, tmp);
9060 tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
9063 static void gen_clrex(DisasContext *s)
9065 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
9068 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
9069 TCGv_i32 addr, int size)
9071 TCGv_i32 t0, t1, t2;
9072 TCGv_i64 extaddr;
9073 TCGv taddr;
9074 TCGLabel *done_label;
9075 TCGLabel *fail_label;
9076 TCGMemOp opc = size | MO_ALIGN | s->be_data;
9078 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
9079 [addr] = {Rt};
9080 {Rd} = 0;
9081 } else {
9082 {Rd} = 1;
9083 } */
9084 fail_label = gen_new_label();
9085 done_label = gen_new_label();
9086 extaddr = tcg_temp_new_i64();
9087 tcg_gen_extu_i32_i64(extaddr, addr);
9088 tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
9089 tcg_temp_free_i64(extaddr);
9091 taddr = gen_aa32_addr(s, addr, opc);
9092 t0 = tcg_temp_new_i32();
9093 t1 = load_reg(s, rt);
9094 if (size == 3) {
9095 TCGv_i64 o64 = tcg_temp_new_i64();
9096 TCGv_i64 n64 = tcg_temp_new_i64();
9098 t2 = load_reg(s, rt2);
9099 /* For AArch32, architecturally the 32-bit word at the lowest
9100 * address is always Rt and the one at addr+4 is Rt2, even if
9101 * the CPU is big-endian. Since we're going to treat this as a
9102 * single 64-bit BE store, we need to put the two halves in the
9103 * opposite order for BE to LE, so that they end up in the right
9104 * places.
9105 * We don't want gen_aa32_frob64() because that does the wrong
9106 * thing for BE32 usermode.
9108 if (s->be_data == MO_BE) {
9109 tcg_gen_concat_i32_i64(n64, t2, t1);
9110 } else {
9111 tcg_gen_concat_i32_i64(n64, t1, t2);
9113 tcg_temp_free_i32(t2);
9115 tcg_gen_atomic_cmpxchg_i64(o64, taddr, cpu_exclusive_val, n64,
9116 get_mem_index(s), opc);
9117 tcg_temp_free_i64(n64);
9119 tcg_gen_setcond_i64(TCG_COND_NE, o64, o64, cpu_exclusive_val);
9120 tcg_gen_extrl_i64_i32(t0, o64);
9122 tcg_temp_free_i64(o64);
9123 } else {
9124 t2 = tcg_temp_new_i32();
9125 tcg_gen_extrl_i64_i32(t2, cpu_exclusive_val);
9126 tcg_gen_atomic_cmpxchg_i32(t0, taddr, t2, t1, get_mem_index(s), opc);
9127 tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t2);
9128 tcg_temp_free_i32(t2);
9130 tcg_temp_free_i32(t1);
9131 tcg_temp_free(taddr);
9132 tcg_gen_mov_i32(cpu_R[rd], t0);
9133 tcg_temp_free_i32(t0);
9134 tcg_gen_br(done_label);
9136 gen_set_label(fail_label);
9137 tcg_gen_movi_i32(cpu_R[rd], 1);
9138 gen_set_label(done_label);
9139 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
9142 /* gen_srs:
9143 * @env: CPUARMState
9144 * @s: DisasContext
9145 * @mode: mode field from insn (which stack to store to)
9146 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
9147 * @writeback: true if writeback bit set
9149 * Generate code for the SRS (Store Return State) insn.
9151 static void gen_srs(DisasContext *s,
9152 uint32_t mode, uint32_t amode, bool writeback)
9154 int32_t offset;
9155 TCGv_i32 addr, tmp;
9156 bool undef = false;
9158 /* SRS is:
9159 * - trapped to EL3 if EL3 is AArch64 and we are at Secure EL1
9160 * and specified mode is monitor mode
9161 * - UNDEFINED in Hyp mode
9162 * - UNPREDICTABLE in User or System mode
9163 * - UNPREDICTABLE if the specified mode is:
9164 * -- not implemented
9165 * -- not a valid mode number
9166 * -- a mode that's at a higher exception level
9167 * -- Monitor, if we are Non-secure
9168 * For the UNPREDICTABLE cases we choose to UNDEF.
9170 if (s->current_el == 1 && !s->ns && mode == ARM_CPU_MODE_MON) {
9171 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), 3);
9172 return;
9175 if (s->current_el == 0 || s->current_el == 2) {
9176 undef = true;
9179 switch (mode) {
9180 case ARM_CPU_MODE_USR:
9181 case ARM_CPU_MODE_FIQ:
9182 case ARM_CPU_MODE_IRQ:
9183 case ARM_CPU_MODE_SVC:
9184 case ARM_CPU_MODE_ABT:
9185 case ARM_CPU_MODE_UND:
9186 case ARM_CPU_MODE_SYS:
9187 break;
9188 case ARM_CPU_MODE_HYP:
9189 if (s->current_el == 1 || !arm_dc_feature(s, ARM_FEATURE_EL2)) {
9190 undef = true;
9192 break;
9193 case ARM_CPU_MODE_MON:
9194 /* No need to check specifically for "are we non-secure" because
9195 * we've already made EL0 UNDEF and handled the trap for S-EL1;
9196 * so if this isn't EL3 then we must be non-secure.
9198 if (s->current_el != 3) {
9199 undef = true;
9201 break;
9202 default:
9203 undef = true;
9206 if (undef) {
9207 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
9208 default_exception_el(s));
9209 return;
9212 addr = tcg_temp_new_i32();
9213 tmp = tcg_const_i32(mode);
9214 /* get_r13_banked() will raise an exception if called from System mode */
9215 gen_set_condexec(s);
9216 gen_set_pc_im(s, s->pc - 4);
9217 gen_helper_get_r13_banked(addr, cpu_env, tmp);
9218 tcg_temp_free_i32(tmp);
9219 switch (amode) {
9220 case 0: /* DA */
9221 offset = -4;
9222 break;
9223 case 1: /* IA */
9224 offset = 0;
9225 break;
9226 case 2: /* DB */
9227 offset = -8;
9228 break;
9229 case 3: /* IB */
9230 offset = 4;
9231 break;
9232 default:
9233 abort();
9235 tcg_gen_addi_i32(addr, addr, offset);
9236 tmp = load_reg(s, 14);
9237 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
9238 tcg_temp_free_i32(tmp);
9239 tmp = load_cpu_field(spsr);
9240 tcg_gen_addi_i32(addr, addr, 4);
9241 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
9242 tcg_temp_free_i32(tmp);
9243 if (writeback) {
9244 switch (amode) {
9245 case 0:
9246 offset = -8;
9247 break;
9248 case 1:
9249 offset = 4;
9250 break;
9251 case 2:
9252 offset = -4;
9253 break;
9254 case 3:
9255 offset = 0;
9256 break;
9257 default:
9258 abort();
9260 tcg_gen_addi_i32(addr, addr, offset);
9261 tmp = tcg_const_i32(mode);
9262 gen_helper_set_r13_banked(cpu_env, tmp, addr);
9263 tcg_temp_free_i32(tmp);
9265 tcg_temp_free_i32(addr);
9266 s->base.is_jmp = DISAS_UPDATE;
9269 /* Generate a label used for skipping this instruction */
9270 static void arm_gen_condlabel(DisasContext *s)
9272 if (!s->condjmp) {
9273 s->condlabel = gen_new_label();
9274 s->condjmp = 1;
9278 /* Skip this instruction if the ARM condition is false */
9279 static void arm_skip_unless(DisasContext *s, uint32_t cond)
9281 arm_gen_condlabel(s);
9282 arm_gen_test_cc(cond ^ 1, s->condlabel);
9285 static void disas_arm_insn(DisasContext *s, unsigned int insn)
9287 unsigned int cond, val, op1, i, shift, rm, rs, rn, rd, sh;
9288 TCGv_i32 tmp;
9289 TCGv_i32 tmp2;
9290 TCGv_i32 tmp3;
9291 TCGv_i32 addr;
9292 TCGv_i64 tmp64;
9294 /* M variants do not implement ARM mode; this must raise the INVSTATE
9295 * UsageFault exception.
9297 if (arm_dc_feature(s, ARM_FEATURE_M)) {
9298 gen_exception_insn(s, 4, EXCP_INVSTATE, syn_uncategorized(),
9299 default_exception_el(s));
9300 return;
9302 cond = insn >> 28;
9303 if (cond == 0xf){
9304 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
9305 * choose to UNDEF. In ARMv5 and above the space is used
9306 * for miscellaneous unconditional instructions.
9308 ARCH(5);
9310 /* Unconditional instructions. */
9311 if (((insn >> 25) & 7) == 1) {
9312 /* NEON Data processing. */
9313 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
9314 goto illegal_op;
9317 if (disas_neon_data_insn(s, insn)) {
9318 goto illegal_op;
9320 return;
9322 if ((insn & 0x0f100000) == 0x04000000) {
9323 /* NEON load/store. */
9324 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
9325 goto illegal_op;
9328 if (disas_neon_ls_insn(s, insn)) {
9329 goto illegal_op;
9331 return;
9333 if ((insn & 0x0f000e10) == 0x0e000a00) {
9334 /* VFP. */
9335 if (disas_vfp_insn(s, insn)) {
9336 goto illegal_op;
9338 return;
9340 if (((insn & 0x0f30f000) == 0x0510f000) ||
9341 ((insn & 0x0f30f010) == 0x0710f000)) {
9342 if ((insn & (1 << 22)) == 0) {
9343 /* PLDW; v7MP */
9344 if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
9345 goto illegal_op;
9348 /* Otherwise PLD; v5TE+ */
9349 ARCH(5TE);
9350 return;
9352 if (((insn & 0x0f70f000) == 0x0450f000) ||
9353 ((insn & 0x0f70f010) == 0x0650f000)) {
9354 ARCH(7);
9355 return; /* PLI; V7 */
9357 if (((insn & 0x0f700000) == 0x04100000) ||
9358 ((insn & 0x0f700010) == 0x06100000)) {
9359 if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
9360 goto illegal_op;
9362 return; /* v7MP: Unallocated memory hint: must NOP */
9365 if ((insn & 0x0ffffdff) == 0x01010000) {
9366 ARCH(6);
9367 /* setend */
9368 if (((insn >> 9) & 1) != !!(s->be_data == MO_BE)) {
9369 gen_helper_setend(cpu_env);
9370 s->base.is_jmp = DISAS_UPDATE;
9372 return;
9373 } else if ((insn & 0x0fffff00) == 0x057ff000) {
9374 switch ((insn >> 4) & 0xf) {
9375 case 1: /* clrex */
9376 ARCH(6K);
9377 gen_clrex(s);
9378 return;
9379 case 4: /* dsb */
9380 case 5: /* dmb */
9381 ARCH(7);
9382 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
9383 return;
9384 case 6: /* isb */
9385 /* We need to break the TB after this insn to execute
9386 * self-modifying code correctly and also to take
9387 * any pending interrupts immediately.
9389 gen_goto_tb(s, 0, s->pc & ~1);
9390 return;
9391 case 7: /* sb */
9392 if ((insn & 0xf) || !dc_isar_feature(aa32_sb, s)) {
9393 goto illegal_op;
9396 * TODO: There is no speculation barrier opcode
9397 * for TCG; MB and end the TB instead.
9399 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
9400 gen_goto_tb(s, 0, s->pc & ~1);
9401 return;
9402 default:
9403 goto illegal_op;
9405 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
9406 /* srs */
9407 ARCH(6);
9408 gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21));
9409 return;
9410 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
9411 /* rfe */
9412 int32_t offset;
9413 if (IS_USER(s))
9414 goto illegal_op;
9415 ARCH(6);
9416 rn = (insn >> 16) & 0xf;
9417 addr = load_reg(s, rn);
9418 i = (insn >> 23) & 3;
9419 switch (i) {
9420 case 0: offset = -4; break; /* DA */
9421 case 1: offset = 0; break; /* IA */
9422 case 2: offset = -8; break; /* DB */
9423 case 3: offset = 4; break; /* IB */
9424 default: abort();
9426 if (offset)
9427 tcg_gen_addi_i32(addr, addr, offset);
9428 /* Load PC into tmp and CPSR into tmp2. */
9429 tmp = tcg_temp_new_i32();
9430 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9431 tcg_gen_addi_i32(addr, addr, 4);
9432 tmp2 = tcg_temp_new_i32();
9433 gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
9434 if (insn & (1 << 21)) {
9435 /* Base writeback. */
9436 switch (i) {
9437 case 0: offset = -8; break;
9438 case 1: offset = 4; break;
9439 case 2: offset = -4; break;
9440 case 3: offset = 0; break;
9441 default: abort();
9443 if (offset)
9444 tcg_gen_addi_i32(addr, addr, offset);
9445 store_reg(s, rn, addr);
9446 } else {
9447 tcg_temp_free_i32(addr);
9449 gen_rfe(s, tmp, tmp2);
9450 return;
9451 } else if ((insn & 0x0e000000) == 0x0a000000) {
9452 /* branch link and change to thumb (blx <offset>) */
9453 int32_t offset;
9455 val = (uint32_t)s->pc;
9456 tmp = tcg_temp_new_i32();
9457 tcg_gen_movi_i32(tmp, val);
9458 store_reg(s, 14, tmp);
9459 /* Sign-extend the 24-bit offset */
9460 offset = (((int32_t)insn) << 8) >> 8;
9461 /* offset * 4 + bit24 * 2 + (thumb bit) */
9462 val += (offset << 2) | ((insn >> 23) & 2) | 1;
9463 /* pipeline offset */
9464 val += 4;
9465 /* protected by ARCH(5); above, near the start of uncond block */
9466 gen_bx_im(s, val);
9467 return;
9468 } else if ((insn & 0x0e000f00) == 0x0c000100) {
9469 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
9470 /* iWMMXt register transfer. */
9471 if (extract32(s->c15_cpar, 1, 1)) {
9472 if (!disas_iwmmxt_insn(s, insn)) {
9473 return;
9477 } else if ((insn & 0x0e000a00) == 0x0c000800
9478 && arm_dc_feature(s, ARM_FEATURE_V8)) {
9479 if (disas_neon_insn_3same_ext(s, insn)) {
9480 goto illegal_op;
9482 return;
9483 } else if ((insn & 0x0f000a00) == 0x0e000800
9484 && arm_dc_feature(s, ARM_FEATURE_V8)) {
9485 if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
9486 goto illegal_op;
9488 return;
9489 } else if ((insn & 0x0fe00000) == 0x0c400000) {
9490 /* Coprocessor double register transfer. */
9491 ARCH(5TE);
9492 } else if ((insn & 0x0f000010) == 0x0e000010) {
9493 /* Additional coprocessor register transfer. */
9494 } else if ((insn & 0x0ff10020) == 0x01000000) {
9495 uint32_t mask;
9496 uint32_t val;
9497 /* cps (privileged) */
9498 if (IS_USER(s))
9499 return;
9500 mask = val = 0;
9501 if (insn & (1 << 19)) {
9502 if (insn & (1 << 8))
9503 mask |= CPSR_A;
9504 if (insn & (1 << 7))
9505 mask |= CPSR_I;
9506 if (insn & (1 << 6))
9507 mask |= CPSR_F;
9508 if (insn & (1 << 18))
9509 val |= mask;
9511 if (insn & (1 << 17)) {
9512 mask |= CPSR_M;
9513 val |= (insn & 0x1f);
9515 if (mask) {
9516 gen_set_psr_im(s, mask, 0, val);
9518 return;
9520 goto illegal_op;
9522 if (cond != 0xe) {
9523 /* if not always execute, we generate a conditional jump to
9524 next instruction */
9525 arm_skip_unless(s, cond);
9527 if ((insn & 0x0f900000) == 0x03000000) {
9528 if ((insn & (1 << 21)) == 0) {
9529 ARCH(6T2);
9530 rd = (insn >> 12) & 0xf;
9531 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
9532 if ((insn & (1 << 22)) == 0) {
9533 /* MOVW */
9534 tmp = tcg_temp_new_i32();
9535 tcg_gen_movi_i32(tmp, val);
9536 } else {
9537 /* MOVT */
9538 tmp = load_reg(s, rd);
9539 tcg_gen_ext16u_i32(tmp, tmp);
9540 tcg_gen_ori_i32(tmp, tmp, val << 16);
9542 store_reg(s, rd, tmp);
9543 } else {
9544 if (((insn >> 12) & 0xf) != 0xf)
9545 goto illegal_op;
9546 if (((insn >> 16) & 0xf) == 0) {
9547 gen_nop_hint(s, insn & 0xff);
9548 } else {
9549 /* CPSR = immediate */
9550 val = insn & 0xff;
9551 shift = ((insn >> 8) & 0xf) * 2;
9552 if (shift)
9553 val = (val >> shift) | (val << (32 - shift));
9554 i = ((insn & (1 << 22)) != 0);
9555 if (gen_set_psr_im(s, msr_mask(s, (insn >> 16) & 0xf, i),
9556 i, val)) {
9557 goto illegal_op;
9561 } else if ((insn & 0x0f900000) == 0x01000000
9562 && (insn & 0x00000090) != 0x00000090) {
9563 /* miscellaneous instructions */
9564 op1 = (insn >> 21) & 3;
9565 sh = (insn >> 4) & 0xf;
9566 rm = insn & 0xf;
9567 switch (sh) {
9568 case 0x0: /* MSR, MRS */
9569 if (insn & (1 << 9)) {
9570 /* MSR (banked) and MRS (banked) */
9571 int sysm = extract32(insn, 16, 4) |
9572 (extract32(insn, 8, 1) << 4);
9573 int r = extract32(insn, 22, 1);
9575 if (op1 & 1) {
9576 /* MSR (banked) */
9577 gen_msr_banked(s, r, sysm, rm);
9578 } else {
9579 /* MRS (banked) */
9580 int rd = extract32(insn, 12, 4);
9582 gen_mrs_banked(s, r, sysm, rd);
9584 break;
9587 /* MSR, MRS (for PSRs) */
9588 if (op1 & 1) {
9589 /* PSR = reg */
9590 tmp = load_reg(s, rm);
9591 i = ((op1 & 2) != 0);
9592 if (gen_set_psr(s, msr_mask(s, (insn >> 16) & 0xf, i), i, tmp))
9593 goto illegal_op;
9594 } else {
9595 /* reg = PSR */
9596 rd = (insn >> 12) & 0xf;
9597 if (op1 & 2) {
9598 if (IS_USER(s))
9599 goto illegal_op;
9600 tmp = load_cpu_field(spsr);
9601 } else {
9602 tmp = tcg_temp_new_i32();
9603 gen_helper_cpsr_read(tmp, cpu_env);
9605 store_reg(s, rd, tmp);
9607 break;
9608 case 0x1:
9609 if (op1 == 1) {
9610 /* branch/exchange thumb (bx). */
9611 ARCH(4T);
9612 tmp = load_reg(s, rm);
9613 gen_bx(s, tmp);
9614 } else if (op1 == 3) {
9615 /* clz */
9616 ARCH(5);
9617 rd = (insn >> 12) & 0xf;
9618 tmp = load_reg(s, rm);
9619 tcg_gen_clzi_i32(tmp, tmp, 32);
9620 store_reg(s, rd, tmp);
9621 } else {
9622 goto illegal_op;
9624 break;
9625 case 0x2:
9626 if (op1 == 1) {
9627 ARCH(5J); /* bxj */
9628 /* Trivial implementation equivalent to bx. */
9629 tmp = load_reg(s, rm);
9630 gen_bx(s, tmp);
9631 } else {
9632 goto illegal_op;
9634 break;
9635 case 0x3:
9636 if (op1 != 1)
9637 goto illegal_op;
9639 ARCH(5);
9640 /* branch link/exchange thumb (blx) */
9641 tmp = load_reg(s, rm);
9642 tmp2 = tcg_temp_new_i32();
9643 tcg_gen_movi_i32(tmp2, s->pc);
9644 store_reg(s, 14, tmp2);
9645 gen_bx(s, tmp);
9646 break;
9647 case 0x4:
9649 /* crc32/crc32c */
9650 uint32_t c = extract32(insn, 8, 4);
9652 /* Check this CPU supports ARMv8 CRC instructions.
9653 * op1 == 3 is UNPREDICTABLE but handle as UNDEFINED.
9654 * Bits 8, 10 and 11 should be zero.
9656 if (!dc_isar_feature(aa32_crc32, s) || op1 == 0x3 || (c & 0xd) != 0) {
9657 goto illegal_op;
9660 rn = extract32(insn, 16, 4);
9661 rd = extract32(insn, 12, 4);
9663 tmp = load_reg(s, rn);
9664 tmp2 = load_reg(s, rm);
9665 if (op1 == 0) {
9666 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
9667 } else if (op1 == 1) {
9668 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
9670 tmp3 = tcg_const_i32(1 << op1);
9671 if (c & 0x2) {
9672 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
9673 } else {
9674 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
9676 tcg_temp_free_i32(tmp2);
9677 tcg_temp_free_i32(tmp3);
9678 store_reg(s, rd, tmp);
9679 break;
9681 case 0x5: /* saturating add/subtract */
9682 ARCH(5TE);
9683 rd = (insn >> 12) & 0xf;
9684 rn = (insn >> 16) & 0xf;
9685 tmp = load_reg(s, rm);
9686 tmp2 = load_reg(s, rn);
9687 if (op1 & 2)
9688 gen_helper_double_saturate(tmp2, cpu_env, tmp2);
9689 if (op1 & 1)
9690 gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2);
9691 else
9692 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
9693 tcg_temp_free_i32(tmp2);
9694 store_reg(s, rd, tmp);
9695 break;
9696 case 0x6: /* ERET */
9697 if (op1 != 3) {
9698 goto illegal_op;
9700 if (!arm_dc_feature(s, ARM_FEATURE_V7VE)) {
9701 goto illegal_op;
9703 if ((insn & 0x000fff0f) != 0x0000000e) {
9704 /* UNPREDICTABLE; we choose to UNDEF */
9705 goto illegal_op;
9708 if (s->current_el == 2) {
9709 tmp = load_cpu_field(elr_el[2]);
9710 } else {
9711 tmp = load_reg(s, 14);
9713 gen_exception_return(s, tmp);
9714 break;
9715 case 7:
9717 int imm16 = extract32(insn, 0, 4) | (extract32(insn, 8, 12) << 4);
9718 switch (op1) {
9719 case 0:
9720 /* HLT */
9721 gen_hlt(s, imm16);
9722 break;
9723 case 1:
9724 /* bkpt */
9725 ARCH(5);
9726 gen_exception_bkpt_insn(s, 4, syn_aa32_bkpt(imm16, false));
9727 break;
9728 case 2:
9729 /* Hypervisor call (v7) */
9730 ARCH(7);
9731 if (IS_USER(s)) {
9732 goto illegal_op;
9734 gen_hvc(s, imm16);
9735 break;
9736 case 3:
9737 /* Secure monitor call (v6+) */
9738 ARCH(6K);
9739 if (IS_USER(s)) {
9740 goto illegal_op;
9742 gen_smc(s);
9743 break;
9744 default:
9745 g_assert_not_reached();
9747 break;
9749 case 0x8: /* signed multiply */
9750 case 0xa:
9751 case 0xc:
9752 case 0xe:
9753 ARCH(5TE);
9754 rs = (insn >> 8) & 0xf;
9755 rn = (insn >> 12) & 0xf;
9756 rd = (insn >> 16) & 0xf;
9757 if (op1 == 1) {
9758 /* (32 * 16) >> 16 */
9759 tmp = load_reg(s, rm);
9760 tmp2 = load_reg(s, rs);
9761 if (sh & 4)
9762 tcg_gen_sari_i32(tmp2, tmp2, 16);
9763 else
9764 gen_sxth(tmp2);
9765 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9766 tcg_gen_shri_i64(tmp64, tmp64, 16);
9767 tmp = tcg_temp_new_i32();
9768 tcg_gen_extrl_i64_i32(tmp, tmp64);
9769 tcg_temp_free_i64(tmp64);
9770 if ((sh & 2) == 0) {
9771 tmp2 = load_reg(s, rn);
9772 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9773 tcg_temp_free_i32(tmp2);
9775 store_reg(s, rd, tmp);
9776 } else {
9777 /* 16 * 16 */
9778 tmp = load_reg(s, rm);
9779 tmp2 = load_reg(s, rs);
9780 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
9781 tcg_temp_free_i32(tmp2);
9782 if (op1 == 2) {
9783 tmp64 = tcg_temp_new_i64();
9784 tcg_gen_ext_i32_i64(tmp64, tmp);
9785 tcg_temp_free_i32(tmp);
9786 gen_addq(s, tmp64, rn, rd);
9787 gen_storeq_reg(s, rn, rd, tmp64);
9788 tcg_temp_free_i64(tmp64);
9789 } else {
9790 if (op1 == 0) {
9791 tmp2 = load_reg(s, rn);
9792 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9793 tcg_temp_free_i32(tmp2);
9795 store_reg(s, rd, tmp);
9798 break;
9799 default:
9800 goto illegal_op;
9802 } else if (((insn & 0x0e000000) == 0 &&
9803 (insn & 0x00000090) != 0x90) ||
9804 ((insn & 0x0e000000) == (1 << 25))) {
9805 int set_cc, logic_cc, shiftop;
9807 op1 = (insn >> 21) & 0xf;
9808 set_cc = (insn >> 20) & 1;
9809 logic_cc = table_logic_cc[op1] & set_cc;
9811 /* data processing instruction */
9812 if (insn & (1 << 25)) {
9813 /* immediate operand */
9814 val = insn & 0xff;
9815 shift = ((insn >> 8) & 0xf) * 2;
9816 if (shift) {
9817 val = (val >> shift) | (val << (32 - shift));
9819 tmp2 = tcg_temp_new_i32();
9820 tcg_gen_movi_i32(tmp2, val);
9821 if (logic_cc && shift) {
9822 gen_set_CF_bit31(tmp2);
9824 } else {
9825 /* register */
9826 rm = (insn) & 0xf;
9827 tmp2 = load_reg(s, rm);
9828 shiftop = (insn >> 5) & 3;
9829 if (!(insn & (1 << 4))) {
9830 shift = (insn >> 7) & 0x1f;
9831 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
9832 } else {
9833 rs = (insn >> 8) & 0xf;
9834 tmp = load_reg(s, rs);
9835 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
9838 if (op1 != 0x0f && op1 != 0x0d) {
9839 rn = (insn >> 16) & 0xf;
9840 tmp = load_reg(s, rn);
9841 } else {
9842 tmp = NULL;
9844 rd = (insn >> 12) & 0xf;
9845 switch(op1) {
9846 case 0x00:
9847 tcg_gen_and_i32(tmp, tmp, tmp2);
9848 if (logic_cc) {
9849 gen_logic_CC(tmp);
9851 store_reg_bx(s, rd, tmp);
9852 break;
9853 case 0x01:
9854 tcg_gen_xor_i32(tmp, tmp, tmp2);
9855 if (logic_cc) {
9856 gen_logic_CC(tmp);
9858 store_reg_bx(s, rd, tmp);
9859 break;
9860 case 0x02:
9861 if (set_cc && rd == 15) {
9862 /* SUBS r15, ... is used for exception return. */
9863 if (IS_USER(s)) {
9864 goto illegal_op;
9866 gen_sub_CC(tmp, tmp, tmp2);
9867 gen_exception_return(s, tmp);
9868 } else {
9869 if (set_cc) {
9870 gen_sub_CC(tmp, tmp, tmp2);
9871 } else {
9872 tcg_gen_sub_i32(tmp, tmp, tmp2);
9874 store_reg_bx(s, rd, tmp);
9876 break;
9877 case 0x03:
9878 if (set_cc) {
9879 gen_sub_CC(tmp, tmp2, tmp);
9880 } else {
9881 tcg_gen_sub_i32(tmp, tmp2, tmp);
9883 store_reg_bx(s, rd, tmp);
9884 break;
9885 case 0x04:
9886 if (set_cc) {
9887 gen_add_CC(tmp, tmp, tmp2);
9888 } else {
9889 tcg_gen_add_i32(tmp, tmp, tmp2);
9891 store_reg_bx(s, rd, tmp);
9892 break;
9893 case 0x05:
9894 if (set_cc) {
9895 gen_adc_CC(tmp, tmp, tmp2);
9896 } else {
9897 gen_add_carry(tmp, tmp, tmp2);
9899 store_reg_bx(s, rd, tmp);
9900 break;
9901 case 0x06:
9902 if (set_cc) {
9903 gen_sbc_CC(tmp, tmp, tmp2);
9904 } else {
9905 gen_sub_carry(tmp, tmp, tmp2);
9907 store_reg_bx(s, rd, tmp);
9908 break;
9909 case 0x07:
9910 if (set_cc) {
9911 gen_sbc_CC(tmp, tmp2, tmp);
9912 } else {
9913 gen_sub_carry(tmp, tmp2, tmp);
9915 store_reg_bx(s, rd, tmp);
9916 break;
9917 case 0x08:
9918 if (set_cc) {
9919 tcg_gen_and_i32(tmp, tmp, tmp2);
9920 gen_logic_CC(tmp);
9922 tcg_temp_free_i32(tmp);
9923 break;
9924 case 0x09:
9925 if (set_cc) {
9926 tcg_gen_xor_i32(tmp, tmp, tmp2);
9927 gen_logic_CC(tmp);
9929 tcg_temp_free_i32(tmp);
9930 break;
9931 case 0x0a:
9932 if (set_cc) {
9933 gen_sub_CC(tmp, tmp, tmp2);
9935 tcg_temp_free_i32(tmp);
9936 break;
9937 case 0x0b:
9938 if (set_cc) {
9939 gen_add_CC(tmp, tmp, tmp2);
9941 tcg_temp_free_i32(tmp);
9942 break;
9943 case 0x0c:
9944 tcg_gen_or_i32(tmp, tmp, tmp2);
9945 if (logic_cc) {
9946 gen_logic_CC(tmp);
9948 store_reg_bx(s, rd, tmp);
9949 break;
9950 case 0x0d:
9951 if (logic_cc && rd == 15) {
9952 /* MOVS r15, ... is used for exception return. */
9953 if (IS_USER(s)) {
9954 goto illegal_op;
9956 gen_exception_return(s, tmp2);
9957 } else {
9958 if (logic_cc) {
9959 gen_logic_CC(tmp2);
9961 store_reg_bx(s, rd, tmp2);
9963 break;
9964 case 0x0e:
9965 tcg_gen_andc_i32(tmp, tmp, tmp2);
9966 if (logic_cc) {
9967 gen_logic_CC(tmp);
9969 store_reg_bx(s, rd, tmp);
9970 break;
9971 default:
9972 case 0x0f:
9973 tcg_gen_not_i32(tmp2, tmp2);
9974 if (logic_cc) {
9975 gen_logic_CC(tmp2);
9977 store_reg_bx(s, rd, tmp2);
9978 break;
9980 if (op1 != 0x0f && op1 != 0x0d) {
9981 tcg_temp_free_i32(tmp2);
9983 } else {
9984 /* other instructions */
9985 op1 = (insn >> 24) & 0xf;
9986 switch(op1) {
9987 case 0x0:
9988 case 0x1:
9989 /* multiplies, extra load/stores */
9990 sh = (insn >> 5) & 3;
9991 if (sh == 0) {
9992 if (op1 == 0x0) {
9993 rd = (insn >> 16) & 0xf;
9994 rn = (insn >> 12) & 0xf;
9995 rs = (insn >> 8) & 0xf;
9996 rm = (insn) & 0xf;
9997 op1 = (insn >> 20) & 0xf;
9998 switch (op1) {
9999 case 0: case 1: case 2: case 3: case 6:
10000 /* 32 bit mul */
10001 tmp = load_reg(s, rs);
10002 tmp2 = load_reg(s, rm);
10003 tcg_gen_mul_i32(tmp, tmp, tmp2);
10004 tcg_temp_free_i32(tmp2);
10005 if (insn & (1 << 22)) {
10006 /* Subtract (mls) */
10007 ARCH(6T2);
10008 tmp2 = load_reg(s, rn);
10009 tcg_gen_sub_i32(tmp, tmp2, tmp);
10010 tcg_temp_free_i32(tmp2);
10011 } else if (insn & (1 << 21)) {
10012 /* Add */
10013 tmp2 = load_reg(s, rn);
10014 tcg_gen_add_i32(tmp, tmp, tmp2);
10015 tcg_temp_free_i32(tmp2);
10017 if (insn & (1 << 20))
10018 gen_logic_CC(tmp);
10019 store_reg(s, rd, tmp);
10020 break;
10021 case 4:
10022 /* 64 bit mul double accumulate (UMAAL) */
10023 ARCH(6);
10024 tmp = load_reg(s, rs);
10025 tmp2 = load_reg(s, rm);
10026 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
10027 gen_addq_lo(s, tmp64, rn);
10028 gen_addq_lo(s, tmp64, rd);
10029 gen_storeq_reg(s, rn, rd, tmp64);
10030 tcg_temp_free_i64(tmp64);
10031 break;
10032 case 8: case 9: case 10: case 11:
10033 case 12: case 13: case 14: case 15:
10034 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
10035 tmp = load_reg(s, rs);
10036 tmp2 = load_reg(s, rm);
10037 if (insn & (1 << 22)) {
10038 tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2);
10039 } else {
10040 tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2);
10042 if (insn & (1 << 21)) { /* mult accumulate */
10043 TCGv_i32 al = load_reg(s, rn);
10044 TCGv_i32 ah = load_reg(s, rd);
10045 tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, al, ah);
10046 tcg_temp_free_i32(al);
10047 tcg_temp_free_i32(ah);
10049 if (insn & (1 << 20)) {
10050 gen_logicq_cc(tmp, tmp2);
10052 store_reg(s, rn, tmp);
10053 store_reg(s, rd, tmp2);
10054 break;
10055 default:
10056 goto illegal_op;
10058 } else {
10059 rn = (insn >> 16) & 0xf;
10060 rd = (insn >> 12) & 0xf;
10061 if (insn & (1 << 23)) {
10062 /* load/store exclusive */
10063 bool is_ld = extract32(insn, 20, 1);
10064 bool is_lasr = !extract32(insn, 8, 1);
10065 int op2 = (insn >> 8) & 3;
10066 op1 = (insn >> 21) & 0x3;
10068 switch (op2) {
10069 case 0: /* lda/stl */
10070 if (op1 == 1) {
10071 goto illegal_op;
10073 ARCH(8);
10074 break;
10075 case 1: /* reserved */
10076 goto illegal_op;
10077 case 2: /* ldaex/stlex */
10078 ARCH(8);
10079 break;
10080 case 3: /* ldrex/strex */
10081 if (op1) {
10082 ARCH(6K);
10083 } else {
10084 ARCH(6);
10086 break;
10089 addr = tcg_temp_local_new_i32();
10090 load_reg_var(s, addr, rn);
10092 if (is_lasr && !is_ld) {
10093 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
10096 if (op2 == 0) {
10097 if (is_ld) {
10098 tmp = tcg_temp_new_i32();
10099 switch (op1) {
10100 case 0: /* lda */
10101 gen_aa32_ld32u_iss(s, tmp, addr,
10102 get_mem_index(s),
10103 rd | ISSIsAcqRel);
10104 break;
10105 case 2: /* ldab */
10106 gen_aa32_ld8u_iss(s, tmp, addr,
10107 get_mem_index(s),
10108 rd | ISSIsAcqRel);
10109 break;
10110 case 3: /* ldah */
10111 gen_aa32_ld16u_iss(s, tmp, addr,
10112 get_mem_index(s),
10113 rd | ISSIsAcqRel);
10114 break;
10115 default:
10116 abort();
10118 store_reg(s, rd, tmp);
10119 } else {
10120 rm = insn & 0xf;
10121 tmp = load_reg(s, rm);
10122 switch (op1) {
10123 case 0: /* stl */
10124 gen_aa32_st32_iss(s, tmp, addr,
10125 get_mem_index(s),
10126 rm | ISSIsAcqRel);
10127 break;
10128 case 2: /* stlb */
10129 gen_aa32_st8_iss(s, tmp, addr,
10130 get_mem_index(s),
10131 rm | ISSIsAcqRel);
10132 break;
10133 case 3: /* stlh */
10134 gen_aa32_st16_iss(s, tmp, addr,
10135 get_mem_index(s),
10136 rm | ISSIsAcqRel);
10137 break;
10138 default:
10139 abort();
10141 tcg_temp_free_i32(tmp);
10143 } else if (is_ld) {
10144 switch (op1) {
10145 case 0: /* ldrex */
10146 gen_load_exclusive(s, rd, 15, addr, 2);
10147 break;
10148 case 1: /* ldrexd */
10149 gen_load_exclusive(s, rd, rd + 1, addr, 3);
10150 break;
10151 case 2: /* ldrexb */
10152 gen_load_exclusive(s, rd, 15, addr, 0);
10153 break;
10154 case 3: /* ldrexh */
10155 gen_load_exclusive(s, rd, 15, addr, 1);
10156 break;
10157 default:
10158 abort();
10160 } else {
10161 rm = insn & 0xf;
10162 switch (op1) {
10163 case 0: /* strex */
10164 gen_store_exclusive(s, rd, rm, 15, addr, 2);
10165 break;
10166 case 1: /* strexd */
10167 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
10168 break;
10169 case 2: /* strexb */
10170 gen_store_exclusive(s, rd, rm, 15, addr, 0);
10171 break;
10172 case 3: /* strexh */
10173 gen_store_exclusive(s, rd, rm, 15, addr, 1);
10174 break;
10175 default:
10176 abort();
10179 tcg_temp_free_i32(addr);
10181 if (is_lasr && is_ld) {
10182 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
10184 } else if ((insn & 0x00300f00) == 0) {
10185 /* 0bcccc_0001_0x00_xxxx_xxxx_0000_1001_xxxx
10186 * - SWP, SWPB
10189 TCGv taddr;
10190 TCGMemOp opc = s->be_data;
10192 rm = (insn) & 0xf;
10194 if (insn & (1 << 22)) {
10195 opc |= MO_UB;
10196 } else {
10197 opc |= MO_UL | MO_ALIGN;
10200 addr = load_reg(s, rn);
10201 taddr = gen_aa32_addr(s, addr, opc);
10202 tcg_temp_free_i32(addr);
10204 tmp = load_reg(s, rm);
10205 tcg_gen_atomic_xchg_i32(tmp, taddr, tmp,
10206 get_mem_index(s), opc);
10207 tcg_temp_free(taddr);
10208 store_reg(s, rd, tmp);
10209 } else {
10210 goto illegal_op;
10213 } else {
10214 int address_offset;
10215 bool load = insn & (1 << 20);
10216 bool wbit = insn & (1 << 21);
10217 bool pbit = insn & (1 << 24);
10218 bool doubleword = false;
10219 ISSInfo issinfo;
10221 /* Misc load/store */
10222 rn = (insn >> 16) & 0xf;
10223 rd = (insn >> 12) & 0xf;
10225 /* ISS not valid if writeback */
10226 issinfo = (pbit & !wbit) ? rd : ISSInvalid;
10228 if (!load && (sh & 2)) {
10229 /* doubleword */
10230 ARCH(5TE);
10231 if (rd & 1) {
10232 /* UNPREDICTABLE; we choose to UNDEF */
10233 goto illegal_op;
10235 load = (sh & 1) == 0;
10236 doubleword = true;
10239 addr = load_reg(s, rn);
10240 if (pbit) {
10241 gen_add_datah_offset(s, insn, 0, addr);
10243 address_offset = 0;
10245 if (doubleword) {
10246 if (!load) {
10247 /* store */
10248 tmp = load_reg(s, rd);
10249 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
10250 tcg_temp_free_i32(tmp);
10251 tcg_gen_addi_i32(addr, addr, 4);
10252 tmp = load_reg(s, rd + 1);
10253 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
10254 tcg_temp_free_i32(tmp);
10255 } else {
10256 /* load */
10257 tmp = tcg_temp_new_i32();
10258 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
10259 store_reg(s, rd, tmp);
10260 tcg_gen_addi_i32(addr, addr, 4);
10261 tmp = tcg_temp_new_i32();
10262 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
10263 rd++;
10265 address_offset = -4;
10266 } else if (load) {
10267 /* load */
10268 tmp = tcg_temp_new_i32();
10269 switch (sh) {
10270 case 1:
10271 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s),
10272 issinfo);
10273 break;
10274 case 2:
10275 gen_aa32_ld8s_iss(s, tmp, addr, get_mem_index(s),
10276 issinfo);
10277 break;
10278 default:
10279 case 3:
10280 gen_aa32_ld16s_iss(s, tmp, addr, get_mem_index(s),
10281 issinfo);
10282 break;
10284 } else {
10285 /* store */
10286 tmp = load_reg(s, rd);
10287 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), issinfo);
10288 tcg_temp_free_i32(tmp);
10290 /* Perform base writeback before the loaded value to
10291 ensure correct behavior with overlapping index registers.
10292 ldrd with base writeback is undefined if the
10293 destination and index registers overlap. */
10294 if (!pbit) {
10295 gen_add_datah_offset(s, insn, address_offset, addr);
10296 store_reg(s, rn, addr);
10297 } else if (wbit) {
10298 if (address_offset)
10299 tcg_gen_addi_i32(addr, addr, address_offset);
10300 store_reg(s, rn, addr);
10301 } else {
10302 tcg_temp_free_i32(addr);
10304 if (load) {
10305 /* Complete the load. */
10306 store_reg(s, rd, tmp);
10309 break;
10310 case 0x4:
10311 case 0x5:
10312 goto do_ldst;
10313 case 0x6:
10314 case 0x7:
10315 if (insn & (1 << 4)) {
10316 ARCH(6);
10317 /* Armv6 Media instructions. */
10318 rm = insn & 0xf;
10319 rn = (insn >> 16) & 0xf;
10320 rd = (insn >> 12) & 0xf;
10321 rs = (insn >> 8) & 0xf;
10322 switch ((insn >> 23) & 3) {
10323 case 0: /* Parallel add/subtract. */
10324 op1 = (insn >> 20) & 7;
10325 tmp = load_reg(s, rn);
10326 tmp2 = load_reg(s, rm);
10327 sh = (insn >> 5) & 7;
10328 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
10329 goto illegal_op;
10330 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
10331 tcg_temp_free_i32(tmp2);
10332 store_reg(s, rd, tmp);
10333 break;
10334 case 1:
10335 if ((insn & 0x00700020) == 0) {
10336 /* Halfword pack. */
10337 tmp = load_reg(s, rn);
10338 tmp2 = load_reg(s, rm);
10339 shift = (insn >> 7) & 0x1f;
10340 if (insn & (1 << 6)) {
10341 /* pkhtb */
10342 if (shift == 0)
10343 shift = 31;
10344 tcg_gen_sari_i32(tmp2, tmp2, shift);
10345 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
10346 tcg_gen_ext16u_i32(tmp2, tmp2);
10347 } else {
10348 /* pkhbt */
10349 if (shift)
10350 tcg_gen_shli_i32(tmp2, tmp2, shift);
10351 tcg_gen_ext16u_i32(tmp, tmp);
10352 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
10354 tcg_gen_or_i32(tmp, tmp, tmp2);
10355 tcg_temp_free_i32(tmp2);
10356 store_reg(s, rd, tmp);
10357 } else if ((insn & 0x00200020) == 0x00200000) {
10358 /* [us]sat */
10359 tmp = load_reg(s, rm);
10360 shift = (insn >> 7) & 0x1f;
10361 if (insn & (1 << 6)) {
10362 if (shift == 0)
10363 shift = 31;
10364 tcg_gen_sari_i32(tmp, tmp, shift);
10365 } else {
10366 tcg_gen_shli_i32(tmp, tmp, shift);
10368 sh = (insn >> 16) & 0x1f;
10369 tmp2 = tcg_const_i32(sh);
10370 if (insn & (1 << 22))
10371 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
10372 else
10373 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
10374 tcg_temp_free_i32(tmp2);
10375 store_reg(s, rd, tmp);
10376 } else if ((insn & 0x00300fe0) == 0x00200f20) {
10377 /* [us]sat16 */
10378 tmp = load_reg(s, rm);
10379 sh = (insn >> 16) & 0x1f;
10380 tmp2 = tcg_const_i32(sh);
10381 if (insn & (1 << 22))
10382 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
10383 else
10384 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
10385 tcg_temp_free_i32(tmp2);
10386 store_reg(s, rd, tmp);
10387 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
10388 /* Select bytes. */
10389 tmp = load_reg(s, rn);
10390 tmp2 = load_reg(s, rm);
10391 tmp3 = tcg_temp_new_i32();
10392 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
10393 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
10394 tcg_temp_free_i32(tmp3);
10395 tcg_temp_free_i32(tmp2);
10396 store_reg(s, rd, tmp);
10397 } else if ((insn & 0x000003e0) == 0x00000060) {
10398 tmp = load_reg(s, rm);
10399 shift = (insn >> 10) & 3;
10400 /* ??? In many cases it's not necessary to do a
10401 rotate, a shift is sufficient. */
10402 if (shift != 0)
10403 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
10404 op1 = (insn >> 20) & 7;
10405 switch (op1) {
10406 case 0: gen_sxtb16(tmp); break;
10407 case 2: gen_sxtb(tmp); break;
10408 case 3: gen_sxth(tmp); break;
10409 case 4: gen_uxtb16(tmp); break;
10410 case 6: gen_uxtb(tmp); break;
10411 case 7: gen_uxth(tmp); break;
10412 default: goto illegal_op;
10414 if (rn != 15) {
10415 tmp2 = load_reg(s, rn);
10416 if ((op1 & 3) == 0) {
10417 gen_add16(tmp, tmp2);
10418 } else {
10419 tcg_gen_add_i32(tmp, tmp, tmp2);
10420 tcg_temp_free_i32(tmp2);
10423 store_reg(s, rd, tmp);
10424 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
10425 /* rev */
10426 tmp = load_reg(s, rm);
10427 if (insn & (1 << 22)) {
10428 if (insn & (1 << 7)) {
10429 gen_revsh(tmp);
10430 } else {
10431 ARCH(6T2);
10432 gen_helper_rbit(tmp, tmp);
10434 } else {
10435 if (insn & (1 << 7))
10436 gen_rev16(tmp);
10437 else
10438 tcg_gen_bswap32_i32(tmp, tmp);
10440 store_reg(s, rd, tmp);
10441 } else {
10442 goto illegal_op;
10444 break;
10445 case 2: /* Multiplies (Type 3). */
10446 switch ((insn >> 20) & 0x7) {
10447 case 5:
10448 if (((insn >> 6) ^ (insn >> 7)) & 1) {
10449 /* op2 not 00x or 11x : UNDEF */
10450 goto illegal_op;
10452 /* Signed multiply most significant [accumulate].
10453 (SMMUL, SMMLA, SMMLS) */
10454 tmp = load_reg(s, rm);
10455 tmp2 = load_reg(s, rs);
10456 tmp64 = gen_muls_i64_i32(tmp, tmp2);
10458 if (rd != 15) {
10459 tmp = load_reg(s, rd);
10460 if (insn & (1 << 6)) {
10461 tmp64 = gen_subq_msw(tmp64, tmp);
10462 } else {
10463 tmp64 = gen_addq_msw(tmp64, tmp);
10466 if (insn & (1 << 5)) {
10467 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
10469 tcg_gen_shri_i64(tmp64, tmp64, 32);
10470 tmp = tcg_temp_new_i32();
10471 tcg_gen_extrl_i64_i32(tmp, tmp64);
10472 tcg_temp_free_i64(tmp64);
10473 store_reg(s, rn, tmp);
10474 break;
10475 case 0:
10476 case 4:
10477 /* SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD */
10478 if (insn & (1 << 7)) {
10479 goto illegal_op;
10481 tmp = load_reg(s, rm);
10482 tmp2 = load_reg(s, rs);
10483 if (insn & (1 << 5))
10484 gen_swap_half(tmp2);
10485 gen_smul_dual(tmp, tmp2);
10486 if (insn & (1 << 22)) {
10487 /* smlald, smlsld */
10488 TCGv_i64 tmp64_2;
10490 tmp64 = tcg_temp_new_i64();
10491 tmp64_2 = tcg_temp_new_i64();
10492 tcg_gen_ext_i32_i64(tmp64, tmp);
10493 tcg_gen_ext_i32_i64(tmp64_2, tmp2);
10494 tcg_temp_free_i32(tmp);
10495 tcg_temp_free_i32(tmp2);
10496 if (insn & (1 << 6)) {
10497 tcg_gen_sub_i64(tmp64, tmp64, tmp64_2);
10498 } else {
10499 tcg_gen_add_i64(tmp64, tmp64, tmp64_2);
10501 tcg_temp_free_i64(tmp64_2);
10502 gen_addq(s, tmp64, rd, rn);
10503 gen_storeq_reg(s, rd, rn, tmp64);
10504 tcg_temp_free_i64(tmp64);
10505 } else {
10506 /* smuad, smusd, smlad, smlsd */
10507 if (insn & (1 << 6)) {
10508 /* This subtraction cannot overflow. */
10509 tcg_gen_sub_i32(tmp, tmp, tmp2);
10510 } else {
10511 /* This addition cannot overflow 32 bits;
10512 * however it may overflow considered as a
10513 * signed operation, in which case we must set
10514 * the Q flag.
10516 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
10518 tcg_temp_free_i32(tmp2);
10519 if (rd != 15)
10521 tmp2 = load_reg(s, rd);
10522 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
10523 tcg_temp_free_i32(tmp2);
10525 store_reg(s, rn, tmp);
10527 break;
10528 case 1:
10529 case 3:
10530 /* SDIV, UDIV */
10531 if (!dc_isar_feature(arm_div, s)) {
10532 goto illegal_op;
10534 if (((insn >> 5) & 7) || (rd != 15)) {
10535 goto illegal_op;
10537 tmp = load_reg(s, rm);
10538 tmp2 = load_reg(s, rs);
10539 if (insn & (1 << 21)) {
10540 gen_helper_udiv(tmp, tmp, tmp2);
10541 } else {
10542 gen_helper_sdiv(tmp, tmp, tmp2);
10544 tcg_temp_free_i32(tmp2);
10545 store_reg(s, rn, tmp);
10546 break;
10547 default:
10548 goto illegal_op;
10550 break;
10551 case 3:
10552 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
10553 switch (op1) {
10554 case 0: /* Unsigned sum of absolute differences. */
10555 ARCH(6);
10556 tmp = load_reg(s, rm);
10557 tmp2 = load_reg(s, rs);
10558 gen_helper_usad8(tmp, tmp, tmp2);
10559 tcg_temp_free_i32(tmp2);
10560 if (rd != 15) {
10561 tmp2 = load_reg(s, rd);
10562 tcg_gen_add_i32(tmp, tmp, tmp2);
10563 tcg_temp_free_i32(tmp2);
10565 store_reg(s, rn, tmp);
10566 break;
10567 case 0x20: case 0x24: case 0x28: case 0x2c:
10568 /* Bitfield insert/clear. */
10569 ARCH(6T2);
10570 shift = (insn >> 7) & 0x1f;
10571 i = (insn >> 16) & 0x1f;
10572 if (i < shift) {
10573 /* UNPREDICTABLE; we choose to UNDEF */
10574 goto illegal_op;
10576 i = i + 1 - shift;
10577 if (rm == 15) {
10578 tmp = tcg_temp_new_i32();
10579 tcg_gen_movi_i32(tmp, 0);
10580 } else {
10581 tmp = load_reg(s, rm);
10583 if (i != 32) {
10584 tmp2 = load_reg(s, rd);
10585 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, i);
10586 tcg_temp_free_i32(tmp2);
10588 store_reg(s, rd, tmp);
10589 break;
10590 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
10591 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
10592 ARCH(6T2);
10593 tmp = load_reg(s, rm);
10594 shift = (insn >> 7) & 0x1f;
10595 i = ((insn >> 16) & 0x1f) + 1;
10596 if (shift + i > 32)
10597 goto illegal_op;
10598 if (i < 32) {
10599 if (op1 & 0x20) {
10600 tcg_gen_extract_i32(tmp, tmp, shift, i);
10601 } else {
10602 tcg_gen_sextract_i32(tmp, tmp, shift, i);
10605 store_reg(s, rd, tmp);
10606 break;
10607 default:
10608 goto illegal_op;
10610 break;
10612 break;
10614 do_ldst:
10615 /* Check for undefined extension instructions
10616 * per the ARM Bible IE:
10617 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
10619 sh = (0xf << 20) | (0xf << 4);
10620 if (op1 == 0x7 && ((insn & sh) == sh))
10622 goto illegal_op;
10624 /* load/store byte/word */
10625 rn = (insn >> 16) & 0xf;
10626 rd = (insn >> 12) & 0xf;
10627 tmp2 = load_reg(s, rn);
10628 if ((insn & 0x01200000) == 0x00200000) {
10629 /* ldrt/strt */
10630 i = get_a32_user_mem_index(s);
10631 } else {
10632 i = get_mem_index(s);
10634 if (insn & (1 << 24))
10635 gen_add_data_offset(s, insn, tmp2);
10636 if (insn & (1 << 20)) {
10637 /* load */
10638 tmp = tcg_temp_new_i32();
10639 if (insn & (1 << 22)) {
10640 gen_aa32_ld8u_iss(s, tmp, tmp2, i, rd);
10641 } else {
10642 gen_aa32_ld32u_iss(s, tmp, tmp2, i, rd);
10644 } else {
10645 /* store */
10646 tmp = load_reg(s, rd);
10647 if (insn & (1 << 22)) {
10648 gen_aa32_st8_iss(s, tmp, tmp2, i, rd);
10649 } else {
10650 gen_aa32_st32_iss(s, tmp, tmp2, i, rd);
10652 tcg_temp_free_i32(tmp);
10654 if (!(insn & (1 << 24))) {
10655 gen_add_data_offset(s, insn, tmp2);
10656 store_reg(s, rn, tmp2);
10657 } else if (insn & (1 << 21)) {
10658 store_reg(s, rn, tmp2);
10659 } else {
10660 tcg_temp_free_i32(tmp2);
10662 if (insn & (1 << 20)) {
10663 /* Complete the load. */
10664 store_reg_from_load(s, rd, tmp);
10666 break;
10667 case 0x08:
10668 case 0x09:
10670 int j, n, loaded_base;
10671 bool exc_return = false;
10672 bool is_load = extract32(insn, 20, 1);
10673 bool user = false;
10674 TCGv_i32 loaded_var;
10675 /* load/store multiple words */
10676 /* XXX: store correct base if write back */
10677 if (insn & (1 << 22)) {
10678 /* LDM (user), LDM (exception return) and STM (user) */
10679 if (IS_USER(s))
10680 goto illegal_op; /* only usable in supervisor mode */
10682 if (is_load && extract32(insn, 15, 1)) {
10683 exc_return = true;
10684 } else {
10685 user = true;
10688 rn = (insn >> 16) & 0xf;
10689 addr = load_reg(s, rn);
10691 /* compute total size */
10692 loaded_base = 0;
10693 loaded_var = NULL;
10694 n = 0;
10695 for(i=0;i<16;i++) {
10696 if (insn & (1 << i))
10697 n++;
10699 /* XXX: test invalid n == 0 case ? */
10700 if (insn & (1 << 23)) {
10701 if (insn & (1 << 24)) {
10702 /* pre increment */
10703 tcg_gen_addi_i32(addr, addr, 4);
10704 } else {
10705 /* post increment */
10707 } else {
10708 if (insn & (1 << 24)) {
10709 /* pre decrement */
10710 tcg_gen_addi_i32(addr, addr, -(n * 4));
10711 } else {
10712 /* post decrement */
10713 if (n != 1)
10714 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
10717 j = 0;
10718 for(i=0;i<16;i++) {
10719 if (insn & (1 << i)) {
10720 if (is_load) {
10721 /* load */
10722 tmp = tcg_temp_new_i32();
10723 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
10724 if (user) {
10725 tmp2 = tcg_const_i32(i);
10726 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
10727 tcg_temp_free_i32(tmp2);
10728 tcg_temp_free_i32(tmp);
10729 } else if (i == rn) {
10730 loaded_var = tmp;
10731 loaded_base = 1;
10732 } else if (i == 15 && exc_return) {
10733 store_pc_exc_ret(s, tmp);
10734 } else {
10735 store_reg_from_load(s, i, tmp);
10737 } else {
10738 /* store */
10739 if (i == 15) {
10740 /* special case: r15 = PC + 8 */
10741 val = (long)s->pc + 4;
10742 tmp = tcg_temp_new_i32();
10743 tcg_gen_movi_i32(tmp, val);
10744 } else if (user) {
10745 tmp = tcg_temp_new_i32();
10746 tmp2 = tcg_const_i32(i);
10747 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
10748 tcg_temp_free_i32(tmp2);
10749 } else {
10750 tmp = load_reg(s, i);
10752 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
10753 tcg_temp_free_i32(tmp);
10755 j++;
10756 /* no need to add after the last transfer */
10757 if (j != n)
10758 tcg_gen_addi_i32(addr, addr, 4);
10761 if (insn & (1 << 21)) {
10762 /* write back */
10763 if (insn & (1 << 23)) {
10764 if (insn & (1 << 24)) {
10765 /* pre increment */
10766 } else {
10767 /* post increment */
10768 tcg_gen_addi_i32(addr, addr, 4);
10770 } else {
10771 if (insn & (1 << 24)) {
10772 /* pre decrement */
10773 if (n != 1)
10774 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
10775 } else {
10776 /* post decrement */
10777 tcg_gen_addi_i32(addr, addr, -(n * 4));
10780 store_reg(s, rn, addr);
10781 } else {
10782 tcg_temp_free_i32(addr);
10784 if (loaded_base) {
10785 store_reg(s, rn, loaded_var);
10787 if (exc_return) {
10788 /* Restore CPSR from SPSR. */
10789 tmp = load_cpu_field(spsr);
10790 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
10791 gen_io_start();
10793 gen_helper_cpsr_write_eret(cpu_env, tmp);
10794 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
10795 gen_io_end();
10797 tcg_temp_free_i32(tmp);
10798 /* Must exit loop to check un-masked IRQs */
10799 s->base.is_jmp = DISAS_EXIT;
10802 break;
10803 case 0xa:
10804 case 0xb:
10806 int32_t offset;
10808 /* branch (and link) */
10809 val = (int32_t)s->pc;
10810 if (insn & (1 << 24)) {
10811 tmp = tcg_temp_new_i32();
10812 tcg_gen_movi_i32(tmp, val);
10813 store_reg(s, 14, tmp);
10815 offset = sextract32(insn << 2, 0, 26);
10816 val += offset + 4;
10817 gen_jmp(s, val);
10819 break;
10820 case 0xc:
10821 case 0xd:
10822 case 0xe:
10823 if (((insn >> 8) & 0xe) == 10) {
10824 /* VFP. */
10825 if (disas_vfp_insn(s, insn)) {
10826 goto illegal_op;
10828 } else if (disas_coproc_insn(s, insn)) {
10829 /* Coprocessor. */
10830 goto illegal_op;
10832 break;
10833 case 0xf:
10834 /* swi */
10835 gen_set_pc_im(s, s->pc);
10836 s->svc_imm = extract32(insn, 0, 24);
10837 s->base.is_jmp = DISAS_SWI;
10838 break;
10839 default:
10840 illegal_op:
10841 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
10842 default_exception_el(s));
10843 break;
10848 static bool thumb_insn_is_16bit(DisasContext *s, uint32_t insn)
10850 /* Return true if this is a 16 bit instruction. We must be precise
10851 * about this (matching the decode). We assume that s->pc still
10852 * points to the first 16 bits of the insn.
10854 if ((insn >> 11) < 0x1d) {
10855 /* Definitely a 16-bit instruction */
10856 return true;
10859 /* Top five bits 0b11101 / 0b11110 / 0b11111 : this is the
10860 * first half of a 32-bit Thumb insn. Thumb-1 cores might
10861 * end up actually treating this as two 16-bit insns, though,
10862 * if it's half of a bl/blx pair that might span a page boundary.
10864 if (arm_dc_feature(s, ARM_FEATURE_THUMB2) ||
10865 arm_dc_feature(s, ARM_FEATURE_M)) {
10866 /* Thumb2 cores (including all M profile ones) always treat
10867 * 32-bit insns as 32-bit.
10869 return false;
10872 if ((insn >> 11) == 0x1e && s->pc - s->page_start < TARGET_PAGE_SIZE - 3) {
10873 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix, and the suffix
10874 * is not on the next page; we merge this into a 32-bit
10875 * insn.
10877 return false;
10879 /* 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF);
10880 * 0b1111_1xxx_xxxx_xxxx : BL suffix;
10881 * 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix on the end of a page
10882 * -- handle as single 16 bit insn
10884 return true;
10887 /* Return true if this is a Thumb-2 logical op. */
10888 static int
10889 thumb2_logic_op(int op)
10891 return (op < 8);
10894 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
10895 then set condition code flags based on the result of the operation.
10896 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
10897 to the high bit of T1.
10898 Returns zero if the opcode is valid. */
10900 static int
10901 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out,
10902 TCGv_i32 t0, TCGv_i32 t1)
10904 int logic_cc;
10906 logic_cc = 0;
10907 switch (op) {
10908 case 0: /* and */
10909 tcg_gen_and_i32(t0, t0, t1);
10910 logic_cc = conds;
10911 break;
10912 case 1: /* bic */
10913 tcg_gen_andc_i32(t0, t0, t1);
10914 logic_cc = conds;
10915 break;
10916 case 2: /* orr */
10917 tcg_gen_or_i32(t0, t0, t1);
10918 logic_cc = conds;
10919 break;
10920 case 3: /* orn */
10921 tcg_gen_orc_i32(t0, t0, t1);
10922 logic_cc = conds;
10923 break;
10924 case 4: /* eor */
10925 tcg_gen_xor_i32(t0, t0, t1);
10926 logic_cc = conds;
10927 break;
10928 case 8: /* add */
10929 if (conds)
10930 gen_add_CC(t0, t0, t1);
10931 else
10932 tcg_gen_add_i32(t0, t0, t1);
10933 break;
10934 case 10: /* adc */
10935 if (conds)
10936 gen_adc_CC(t0, t0, t1);
10937 else
10938 gen_adc(t0, t1);
10939 break;
10940 case 11: /* sbc */
10941 if (conds) {
10942 gen_sbc_CC(t0, t0, t1);
10943 } else {
10944 gen_sub_carry(t0, t0, t1);
10946 break;
10947 case 13: /* sub */
10948 if (conds)
10949 gen_sub_CC(t0, t0, t1);
10950 else
10951 tcg_gen_sub_i32(t0, t0, t1);
10952 break;
10953 case 14: /* rsb */
10954 if (conds)
10955 gen_sub_CC(t0, t1, t0);
10956 else
10957 tcg_gen_sub_i32(t0, t1, t0);
10958 break;
10959 default: /* 5, 6, 7, 9, 12, 15. */
10960 return 1;
10962 if (logic_cc) {
10963 gen_logic_CC(t0);
10964 if (shifter_out)
10965 gen_set_CF_bit31(t1);
10967 return 0;
10970 /* Translate a 32-bit thumb instruction. */
10971 static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
10973 uint32_t imm, shift, offset;
10974 uint32_t rd, rn, rm, rs;
10975 TCGv_i32 tmp;
10976 TCGv_i32 tmp2;
10977 TCGv_i32 tmp3;
10978 TCGv_i32 addr;
10979 TCGv_i64 tmp64;
10980 int op;
10981 int shiftop;
10982 int conds;
10983 int logic_cc;
10986 * ARMv6-M supports a limited subset of Thumb2 instructions.
10987 * Other Thumb1 architectures allow only 32-bit
10988 * combined BL/BLX prefix and suffix.
10990 if (arm_dc_feature(s, ARM_FEATURE_M) &&
10991 !arm_dc_feature(s, ARM_FEATURE_V7)) {
10992 int i;
10993 bool found = false;
10994 static const uint32_t armv6m_insn[] = {0xf3808000 /* msr */,
10995 0xf3b08040 /* dsb */,
10996 0xf3b08050 /* dmb */,
10997 0xf3b08060 /* isb */,
10998 0xf3e08000 /* mrs */,
10999 0xf000d000 /* bl */};
11000 static const uint32_t armv6m_mask[] = {0xffe0d000,
11001 0xfff0d0f0,
11002 0xfff0d0f0,
11003 0xfff0d0f0,
11004 0xffe0d000,
11005 0xf800d000};
11007 for (i = 0; i < ARRAY_SIZE(armv6m_insn); i++) {
11008 if ((insn & armv6m_mask[i]) == armv6m_insn[i]) {
11009 found = true;
11010 break;
11013 if (!found) {
11014 goto illegal_op;
11016 } else if ((insn & 0xf800e800) != 0xf000e800) {
11017 ARCH(6T2);
11020 rn = (insn >> 16) & 0xf;
11021 rs = (insn >> 12) & 0xf;
11022 rd = (insn >> 8) & 0xf;
11023 rm = insn & 0xf;
11024 switch ((insn >> 25) & 0xf) {
11025 case 0: case 1: case 2: case 3:
11026 /* 16-bit instructions. Should never happen. */
11027 abort();
11028 case 4:
11029 if (insn & (1 << 22)) {
11030 /* 0b1110_100x_x1xx_xxxx_xxxx_xxxx_xxxx_xxxx
11031 * - load/store doubleword, load/store exclusive, ldacq/strel,
11032 * table branch, TT.
11034 if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_M) &&
11035 arm_dc_feature(s, ARM_FEATURE_V8)) {
11036 /* 0b1110_1001_0111_1111_1110_1001_0111_111
11037 * - SG (v8M only)
11038 * The bulk of the behaviour for this instruction is implemented
11039 * in v7m_handle_execute_nsc(), which deals with the insn when
11040 * it is executed by a CPU in non-secure state from memory
11041 * which is Secure & NonSecure-Callable.
11042 * Here we only need to handle the remaining cases:
11043 * * in NS memory (including the "security extension not
11044 * implemented" case) : NOP
11045 * * in S memory but CPU already secure (clear IT bits)
11046 * We know that the attribute for the memory this insn is
11047 * in must match the current CPU state, because otherwise
11048 * get_phys_addr_pmsav8 would have generated an exception.
11050 if (s->v8m_secure) {
11051 /* Like the IT insn, we don't need to generate any code */
11052 s->condexec_cond = 0;
11053 s->condexec_mask = 0;
11055 } else if (insn & 0x01200000) {
11056 /* 0b1110_1000_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
11057 * - load/store dual (post-indexed)
11058 * 0b1111_1001_x10x_xxxx_xxxx_xxxx_xxxx_xxxx
11059 * - load/store dual (literal and immediate)
11060 * 0b1111_1001_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
11061 * - load/store dual (pre-indexed)
11063 bool wback = extract32(insn, 21, 1);
11065 if (rn == 15) {
11066 if (insn & (1 << 21)) {
11067 /* UNPREDICTABLE */
11068 goto illegal_op;
11070 addr = tcg_temp_new_i32();
11071 tcg_gen_movi_i32(addr, s->pc & ~3);
11072 } else {
11073 addr = load_reg(s, rn);
11075 offset = (insn & 0xff) * 4;
11076 if ((insn & (1 << 23)) == 0) {
11077 offset = -offset;
11080 if (s->v8m_stackcheck && rn == 13 && wback) {
11082 * Here 'addr' is the current SP; if offset is +ve we're
11083 * moving SP up, else down. It is UNKNOWN whether the limit
11084 * check triggers when SP starts below the limit and ends
11085 * up above it; check whichever of the current and final
11086 * SP is lower, so QEMU will trigger in that situation.
11088 if ((int32_t)offset < 0) {
11089 TCGv_i32 newsp = tcg_temp_new_i32();
11091 tcg_gen_addi_i32(newsp, addr, offset);
11092 gen_helper_v8m_stackcheck(cpu_env, newsp);
11093 tcg_temp_free_i32(newsp);
11094 } else {
11095 gen_helper_v8m_stackcheck(cpu_env, addr);
11099 if (insn & (1 << 24)) {
11100 tcg_gen_addi_i32(addr, addr, offset);
11101 offset = 0;
11103 if (insn & (1 << 20)) {
11104 /* ldrd */
11105 tmp = tcg_temp_new_i32();
11106 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
11107 store_reg(s, rs, tmp);
11108 tcg_gen_addi_i32(addr, addr, 4);
11109 tmp = tcg_temp_new_i32();
11110 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
11111 store_reg(s, rd, tmp);
11112 } else {
11113 /* strd */
11114 tmp = load_reg(s, rs);
11115 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
11116 tcg_temp_free_i32(tmp);
11117 tcg_gen_addi_i32(addr, addr, 4);
11118 tmp = load_reg(s, rd);
11119 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
11120 tcg_temp_free_i32(tmp);
11122 if (wback) {
11123 /* Base writeback. */
11124 tcg_gen_addi_i32(addr, addr, offset - 4);
11125 store_reg(s, rn, addr);
11126 } else {
11127 tcg_temp_free_i32(addr);
11129 } else if ((insn & (1 << 23)) == 0) {
11130 /* 0b1110_1000_010x_xxxx_xxxx_xxxx_xxxx_xxxx
11131 * - load/store exclusive word
11132 * - TT (v8M only)
11134 if (rs == 15) {
11135 if (!(insn & (1 << 20)) &&
11136 arm_dc_feature(s, ARM_FEATURE_M) &&
11137 arm_dc_feature(s, ARM_FEATURE_V8)) {
11138 /* 0b1110_1000_0100_xxxx_1111_xxxx_xxxx_xxxx
11139 * - TT (v8M only)
11141 bool alt = insn & (1 << 7);
11142 TCGv_i32 addr, op, ttresp;
11144 if ((insn & 0x3f) || rd == 13 || rd == 15 || rn == 15) {
11145 /* we UNDEF for these UNPREDICTABLE cases */
11146 goto illegal_op;
11149 if (alt && !s->v8m_secure) {
11150 goto illegal_op;
11153 addr = load_reg(s, rn);
11154 op = tcg_const_i32(extract32(insn, 6, 2));
11155 ttresp = tcg_temp_new_i32();
11156 gen_helper_v7m_tt(ttresp, cpu_env, addr, op);
11157 tcg_temp_free_i32(addr);
11158 tcg_temp_free_i32(op);
11159 store_reg(s, rd, ttresp);
11160 break;
11162 goto illegal_op;
11164 addr = tcg_temp_local_new_i32();
11165 load_reg_var(s, addr, rn);
11166 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
11167 if (insn & (1 << 20)) {
11168 gen_load_exclusive(s, rs, 15, addr, 2);
11169 } else {
11170 gen_store_exclusive(s, rd, rs, 15, addr, 2);
11172 tcg_temp_free_i32(addr);
11173 } else if ((insn & (7 << 5)) == 0) {
11174 /* Table Branch. */
11175 if (rn == 15) {
11176 addr = tcg_temp_new_i32();
11177 tcg_gen_movi_i32(addr, s->pc);
11178 } else {
11179 addr = load_reg(s, rn);
11181 tmp = load_reg(s, rm);
11182 tcg_gen_add_i32(addr, addr, tmp);
11183 if (insn & (1 << 4)) {
11184 /* tbh */
11185 tcg_gen_add_i32(addr, addr, tmp);
11186 tcg_temp_free_i32(tmp);
11187 tmp = tcg_temp_new_i32();
11188 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
11189 } else { /* tbb */
11190 tcg_temp_free_i32(tmp);
11191 tmp = tcg_temp_new_i32();
11192 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
11194 tcg_temp_free_i32(addr);
11195 tcg_gen_shli_i32(tmp, tmp, 1);
11196 tcg_gen_addi_i32(tmp, tmp, s->pc);
11197 store_reg(s, 15, tmp);
11198 } else {
11199 bool is_lasr = false;
11200 bool is_ld = extract32(insn, 20, 1);
11201 int op2 = (insn >> 6) & 0x3;
11202 op = (insn >> 4) & 0x3;
11203 switch (op2) {
11204 case 0:
11205 goto illegal_op;
11206 case 1:
11207 /* Load/store exclusive byte/halfword/doubleword */
11208 if (op == 2) {
11209 goto illegal_op;
11211 ARCH(7);
11212 break;
11213 case 2:
11214 /* Load-acquire/store-release */
11215 if (op == 3) {
11216 goto illegal_op;
11218 /* Fall through */
11219 case 3:
11220 /* Load-acquire/store-release exclusive */
11221 ARCH(8);
11222 is_lasr = true;
11223 break;
11226 if (is_lasr && !is_ld) {
11227 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
11230 addr = tcg_temp_local_new_i32();
11231 load_reg_var(s, addr, rn);
11232 if (!(op2 & 1)) {
11233 if (is_ld) {
11234 tmp = tcg_temp_new_i32();
11235 switch (op) {
11236 case 0: /* ldab */
11237 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s),
11238 rs | ISSIsAcqRel);
11239 break;
11240 case 1: /* ldah */
11241 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s),
11242 rs | ISSIsAcqRel);
11243 break;
11244 case 2: /* lda */
11245 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s),
11246 rs | ISSIsAcqRel);
11247 break;
11248 default:
11249 abort();
11251 store_reg(s, rs, tmp);
11252 } else {
11253 tmp = load_reg(s, rs);
11254 switch (op) {
11255 case 0: /* stlb */
11256 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s),
11257 rs | ISSIsAcqRel);
11258 break;
11259 case 1: /* stlh */
11260 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s),
11261 rs | ISSIsAcqRel);
11262 break;
11263 case 2: /* stl */
11264 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s),
11265 rs | ISSIsAcqRel);
11266 break;
11267 default:
11268 abort();
11270 tcg_temp_free_i32(tmp);
11272 } else if (is_ld) {
11273 gen_load_exclusive(s, rs, rd, addr, op);
11274 } else {
11275 gen_store_exclusive(s, rm, rs, rd, addr, op);
11277 tcg_temp_free_i32(addr);
11279 if (is_lasr && is_ld) {
11280 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
11283 } else {
11284 /* Load/store multiple, RFE, SRS. */
11285 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
11286 /* RFE, SRS: not available in user mode or on M profile */
11287 if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
11288 goto illegal_op;
11290 if (insn & (1 << 20)) {
11291 /* rfe */
11292 addr = load_reg(s, rn);
11293 if ((insn & (1 << 24)) == 0)
11294 tcg_gen_addi_i32(addr, addr, -8);
11295 /* Load PC into tmp and CPSR into tmp2. */
11296 tmp = tcg_temp_new_i32();
11297 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
11298 tcg_gen_addi_i32(addr, addr, 4);
11299 tmp2 = tcg_temp_new_i32();
11300 gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
11301 if (insn & (1 << 21)) {
11302 /* Base writeback. */
11303 if (insn & (1 << 24)) {
11304 tcg_gen_addi_i32(addr, addr, 4);
11305 } else {
11306 tcg_gen_addi_i32(addr, addr, -4);
11308 store_reg(s, rn, addr);
11309 } else {
11310 tcg_temp_free_i32(addr);
11312 gen_rfe(s, tmp, tmp2);
11313 } else {
11314 /* srs */
11315 gen_srs(s, (insn & 0x1f), (insn & (1 << 24)) ? 1 : 2,
11316 insn & (1 << 21));
11318 } else {
11319 int i, loaded_base = 0;
11320 TCGv_i32 loaded_var;
11321 bool wback = extract32(insn, 21, 1);
11322 /* Load/store multiple. */
11323 addr = load_reg(s, rn);
11324 offset = 0;
11325 for (i = 0; i < 16; i++) {
11326 if (insn & (1 << i))
11327 offset += 4;
11330 if (insn & (1 << 24)) {
11331 tcg_gen_addi_i32(addr, addr, -offset);
11334 if (s->v8m_stackcheck && rn == 13 && wback) {
11336 * If the writeback is incrementing SP rather than
11337 * decrementing it, and the initial SP is below the
11338 * stack limit but the final written-back SP would
11339 * be above, then then we must not perform any memory
11340 * accesses, but it is IMPDEF whether we generate
11341 * an exception. We choose to do so in this case.
11342 * At this point 'addr' is the lowest address, so
11343 * either the original SP (if incrementing) or our
11344 * final SP (if decrementing), so that's what we check.
11346 gen_helper_v8m_stackcheck(cpu_env, addr);
11349 loaded_var = NULL;
11350 for (i = 0; i < 16; i++) {
11351 if ((insn & (1 << i)) == 0)
11352 continue;
11353 if (insn & (1 << 20)) {
11354 /* Load. */
11355 tmp = tcg_temp_new_i32();
11356 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
11357 if (i == 15) {
11358 gen_bx_excret(s, tmp);
11359 } else if (i == rn) {
11360 loaded_var = tmp;
11361 loaded_base = 1;
11362 } else {
11363 store_reg(s, i, tmp);
11365 } else {
11366 /* Store. */
11367 tmp = load_reg(s, i);
11368 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
11369 tcg_temp_free_i32(tmp);
11371 tcg_gen_addi_i32(addr, addr, 4);
11373 if (loaded_base) {
11374 store_reg(s, rn, loaded_var);
11376 if (wback) {
11377 /* Base register writeback. */
11378 if (insn & (1 << 24)) {
11379 tcg_gen_addi_i32(addr, addr, -offset);
11381 /* Fault if writeback register is in register list. */
11382 if (insn & (1 << rn))
11383 goto illegal_op;
11384 store_reg(s, rn, addr);
11385 } else {
11386 tcg_temp_free_i32(addr);
11390 break;
11391 case 5:
11393 op = (insn >> 21) & 0xf;
11394 if (op == 6) {
11395 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11396 goto illegal_op;
11398 /* Halfword pack. */
11399 tmp = load_reg(s, rn);
11400 tmp2 = load_reg(s, rm);
11401 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
11402 if (insn & (1 << 5)) {
11403 /* pkhtb */
11404 if (shift == 0)
11405 shift = 31;
11406 tcg_gen_sari_i32(tmp2, tmp2, shift);
11407 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
11408 tcg_gen_ext16u_i32(tmp2, tmp2);
11409 } else {
11410 /* pkhbt */
11411 if (shift)
11412 tcg_gen_shli_i32(tmp2, tmp2, shift);
11413 tcg_gen_ext16u_i32(tmp, tmp);
11414 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
11416 tcg_gen_or_i32(tmp, tmp, tmp2);
11417 tcg_temp_free_i32(tmp2);
11418 store_reg(s, rd, tmp);
11419 } else {
11420 /* Data processing register constant shift. */
11421 if (rn == 15) {
11422 tmp = tcg_temp_new_i32();
11423 tcg_gen_movi_i32(tmp, 0);
11424 } else {
11425 tmp = load_reg(s, rn);
11427 tmp2 = load_reg(s, rm);
11429 shiftop = (insn >> 4) & 3;
11430 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
11431 conds = (insn & (1 << 20)) != 0;
11432 logic_cc = (conds && thumb2_logic_op(op));
11433 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
11434 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
11435 goto illegal_op;
11436 tcg_temp_free_i32(tmp2);
11437 if (rd == 13 &&
11438 ((op == 2 && rn == 15) ||
11439 (op == 8 && rn == 13) ||
11440 (op == 13 && rn == 13))) {
11441 /* MOV SP, ... or ADD SP, SP, ... or SUB SP, SP, ... */
11442 store_sp_checked(s, tmp);
11443 } else if (rd != 15) {
11444 store_reg(s, rd, tmp);
11445 } else {
11446 tcg_temp_free_i32(tmp);
11449 break;
11450 case 13: /* Misc data processing. */
11451 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
11452 if (op < 4 && (insn & 0xf000) != 0xf000)
11453 goto illegal_op;
11454 switch (op) {
11455 case 0: /* Register controlled shift. */
11456 tmp = load_reg(s, rn);
11457 tmp2 = load_reg(s, rm);
11458 if ((insn & 0x70) != 0)
11459 goto illegal_op;
11461 * 0b1111_1010_0xxx_xxxx_1111_xxxx_0000_xxxx:
11462 * - MOV, MOVS (register-shifted register), flagsetting
11464 op = (insn >> 21) & 3;
11465 logic_cc = (insn & (1 << 20)) != 0;
11466 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
11467 if (logic_cc)
11468 gen_logic_CC(tmp);
11469 store_reg(s, rd, tmp);
11470 break;
11471 case 1: /* Sign/zero extend. */
11472 op = (insn >> 20) & 7;
11473 switch (op) {
11474 case 0: /* SXTAH, SXTH */
11475 case 1: /* UXTAH, UXTH */
11476 case 4: /* SXTAB, SXTB */
11477 case 5: /* UXTAB, UXTB */
11478 break;
11479 case 2: /* SXTAB16, SXTB16 */
11480 case 3: /* UXTAB16, UXTB16 */
11481 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11482 goto illegal_op;
11484 break;
11485 default:
11486 goto illegal_op;
11488 if (rn != 15) {
11489 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11490 goto illegal_op;
11493 tmp = load_reg(s, rm);
11494 shift = (insn >> 4) & 3;
11495 /* ??? In many cases it's not necessary to do a
11496 rotate, a shift is sufficient. */
11497 if (shift != 0)
11498 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
11499 op = (insn >> 20) & 7;
11500 switch (op) {
11501 case 0: gen_sxth(tmp); break;
11502 case 1: gen_uxth(tmp); break;
11503 case 2: gen_sxtb16(tmp); break;
11504 case 3: gen_uxtb16(tmp); break;
11505 case 4: gen_sxtb(tmp); break;
11506 case 5: gen_uxtb(tmp); break;
11507 default:
11508 g_assert_not_reached();
11510 if (rn != 15) {
11511 tmp2 = load_reg(s, rn);
11512 if ((op >> 1) == 1) {
11513 gen_add16(tmp, tmp2);
11514 } else {
11515 tcg_gen_add_i32(tmp, tmp, tmp2);
11516 tcg_temp_free_i32(tmp2);
11519 store_reg(s, rd, tmp);
11520 break;
11521 case 2: /* SIMD add/subtract. */
11522 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11523 goto illegal_op;
11525 op = (insn >> 20) & 7;
11526 shift = (insn >> 4) & 7;
11527 if ((op & 3) == 3 || (shift & 3) == 3)
11528 goto illegal_op;
11529 tmp = load_reg(s, rn);
11530 tmp2 = load_reg(s, rm);
11531 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
11532 tcg_temp_free_i32(tmp2);
11533 store_reg(s, rd, tmp);
11534 break;
11535 case 3: /* Other data processing. */
11536 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
11537 if (op < 4) {
11538 /* Saturating add/subtract. */
11539 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11540 goto illegal_op;
11542 tmp = load_reg(s, rn);
11543 tmp2 = load_reg(s, rm);
11544 if (op & 1)
11545 gen_helper_double_saturate(tmp, cpu_env, tmp);
11546 if (op & 2)
11547 gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);
11548 else
11549 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
11550 tcg_temp_free_i32(tmp2);
11551 } else {
11552 switch (op) {
11553 case 0x0a: /* rbit */
11554 case 0x08: /* rev */
11555 case 0x09: /* rev16 */
11556 case 0x0b: /* revsh */
11557 case 0x18: /* clz */
11558 break;
11559 case 0x10: /* sel */
11560 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11561 goto illegal_op;
11563 break;
11564 case 0x20: /* crc32/crc32c */
11565 case 0x21:
11566 case 0x22:
11567 case 0x28:
11568 case 0x29:
11569 case 0x2a:
11570 if (!dc_isar_feature(aa32_crc32, s)) {
11571 goto illegal_op;
11573 break;
11574 default:
11575 goto illegal_op;
11577 tmp = load_reg(s, rn);
11578 switch (op) {
11579 case 0x0a: /* rbit */
11580 gen_helper_rbit(tmp, tmp);
11581 break;
11582 case 0x08: /* rev */
11583 tcg_gen_bswap32_i32(tmp, tmp);
11584 break;
11585 case 0x09: /* rev16 */
11586 gen_rev16(tmp);
11587 break;
11588 case 0x0b: /* revsh */
11589 gen_revsh(tmp);
11590 break;
11591 case 0x10: /* sel */
11592 tmp2 = load_reg(s, rm);
11593 tmp3 = tcg_temp_new_i32();
11594 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
11595 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
11596 tcg_temp_free_i32(tmp3);
11597 tcg_temp_free_i32(tmp2);
11598 break;
11599 case 0x18: /* clz */
11600 tcg_gen_clzi_i32(tmp, tmp, 32);
11601 break;
11602 case 0x20:
11603 case 0x21:
11604 case 0x22:
11605 case 0x28:
11606 case 0x29:
11607 case 0x2a:
11609 /* crc32/crc32c */
11610 uint32_t sz = op & 0x3;
11611 uint32_t c = op & 0x8;
11613 tmp2 = load_reg(s, rm);
11614 if (sz == 0) {
11615 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
11616 } else if (sz == 1) {
11617 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
11619 tmp3 = tcg_const_i32(1 << sz);
11620 if (c) {
11621 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
11622 } else {
11623 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
11625 tcg_temp_free_i32(tmp2);
11626 tcg_temp_free_i32(tmp3);
11627 break;
11629 default:
11630 g_assert_not_reached();
11633 store_reg(s, rd, tmp);
11634 break;
11635 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
11636 switch ((insn >> 20) & 7) {
11637 case 0: /* 32 x 32 -> 32 */
11638 case 7: /* Unsigned sum of absolute differences. */
11639 break;
11640 case 1: /* 16 x 16 -> 32 */
11641 case 2: /* Dual multiply add. */
11642 case 3: /* 32 * 16 -> 32msb */
11643 case 4: /* Dual multiply subtract. */
11644 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
11645 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11646 goto illegal_op;
11648 break;
11650 op = (insn >> 4) & 0xf;
11651 tmp = load_reg(s, rn);
11652 tmp2 = load_reg(s, rm);
11653 switch ((insn >> 20) & 7) {
11654 case 0: /* 32 x 32 -> 32 */
11655 tcg_gen_mul_i32(tmp, tmp, tmp2);
11656 tcg_temp_free_i32(tmp2);
11657 if (rs != 15) {
11658 tmp2 = load_reg(s, rs);
11659 if (op)
11660 tcg_gen_sub_i32(tmp, tmp2, tmp);
11661 else
11662 tcg_gen_add_i32(tmp, tmp, tmp2);
11663 tcg_temp_free_i32(tmp2);
11665 break;
11666 case 1: /* 16 x 16 -> 32 */
11667 gen_mulxy(tmp, tmp2, op & 2, op & 1);
11668 tcg_temp_free_i32(tmp2);
11669 if (rs != 15) {
11670 tmp2 = load_reg(s, rs);
11671 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
11672 tcg_temp_free_i32(tmp2);
11674 break;
11675 case 2: /* Dual multiply add. */
11676 case 4: /* Dual multiply subtract. */
11677 if (op)
11678 gen_swap_half(tmp2);
11679 gen_smul_dual(tmp, tmp2);
11680 if (insn & (1 << 22)) {
11681 /* This subtraction cannot overflow. */
11682 tcg_gen_sub_i32(tmp, tmp, tmp2);
11683 } else {
11684 /* This addition cannot overflow 32 bits;
11685 * however it may overflow considered as a signed
11686 * operation, in which case we must set the Q flag.
11688 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
11690 tcg_temp_free_i32(tmp2);
11691 if (rs != 15)
11693 tmp2 = load_reg(s, rs);
11694 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
11695 tcg_temp_free_i32(tmp2);
11697 break;
11698 case 3: /* 32 * 16 -> 32msb */
11699 if (op)
11700 tcg_gen_sari_i32(tmp2, tmp2, 16);
11701 else
11702 gen_sxth(tmp2);
11703 tmp64 = gen_muls_i64_i32(tmp, tmp2);
11704 tcg_gen_shri_i64(tmp64, tmp64, 16);
11705 tmp = tcg_temp_new_i32();
11706 tcg_gen_extrl_i64_i32(tmp, tmp64);
11707 tcg_temp_free_i64(tmp64);
11708 if (rs != 15)
11710 tmp2 = load_reg(s, rs);
11711 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
11712 tcg_temp_free_i32(tmp2);
11714 break;
11715 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
11716 tmp64 = gen_muls_i64_i32(tmp, tmp2);
11717 if (rs != 15) {
11718 tmp = load_reg(s, rs);
11719 if (insn & (1 << 20)) {
11720 tmp64 = gen_addq_msw(tmp64, tmp);
11721 } else {
11722 tmp64 = gen_subq_msw(tmp64, tmp);
11725 if (insn & (1 << 4)) {
11726 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
11728 tcg_gen_shri_i64(tmp64, tmp64, 32);
11729 tmp = tcg_temp_new_i32();
11730 tcg_gen_extrl_i64_i32(tmp, tmp64);
11731 tcg_temp_free_i64(tmp64);
11732 break;
11733 case 7: /* Unsigned sum of absolute differences. */
11734 gen_helper_usad8(tmp, tmp, tmp2);
11735 tcg_temp_free_i32(tmp2);
11736 if (rs != 15) {
11737 tmp2 = load_reg(s, rs);
11738 tcg_gen_add_i32(tmp, tmp, tmp2);
11739 tcg_temp_free_i32(tmp2);
11741 break;
11743 store_reg(s, rd, tmp);
11744 break;
11745 case 6: case 7: /* 64-bit multiply, Divide. */
11746 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
11747 tmp = load_reg(s, rn);
11748 tmp2 = load_reg(s, rm);
11749 if ((op & 0x50) == 0x10) {
11750 /* sdiv, udiv */
11751 if (!dc_isar_feature(thumb_div, s)) {
11752 goto illegal_op;
11754 if (op & 0x20)
11755 gen_helper_udiv(tmp, tmp, tmp2);
11756 else
11757 gen_helper_sdiv(tmp, tmp, tmp2);
11758 tcg_temp_free_i32(tmp2);
11759 store_reg(s, rd, tmp);
11760 } else if ((op & 0xe) == 0xc) {
11761 /* Dual multiply accumulate long. */
11762 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11763 tcg_temp_free_i32(tmp);
11764 tcg_temp_free_i32(tmp2);
11765 goto illegal_op;
11767 if (op & 1)
11768 gen_swap_half(tmp2);
11769 gen_smul_dual(tmp, tmp2);
11770 if (op & 0x10) {
11771 tcg_gen_sub_i32(tmp, tmp, tmp2);
11772 } else {
11773 tcg_gen_add_i32(tmp, tmp, tmp2);
11775 tcg_temp_free_i32(tmp2);
11776 /* BUGFIX */
11777 tmp64 = tcg_temp_new_i64();
11778 tcg_gen_ext_i32_i64(tmp64, tmp);
11779 tcg_temp_free_i32(tmp);
11780 gen_addq(s, tmp64, rs, rd);
11781 gen_storeq_reg(s, rs, rd, tmp64);
11782 tcg_temp_free_i64(tmp64);
11783 } else {
11784 if (op & 0x20) {
11785 /* Unsigned 64-bit multiply */
11786 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
11787 } else {
11788 if (op & 8) {
11789 /* smlalxy */
11790 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11791 tcg_temp_free_i32(tmp2);
11792 tcg_temp_free_i32(tmp);
11793 goto illegal_op;
11795 gen_mulxy(tmp, tmp2, op & 2, op & 1);
11796 tcg_temp_free_i32(tmp2);
11797 tmp64 = tcg_temp_new_i64();
11798 tcg_gen_ext_i32_i64(tmp64, tmp);
11799 tcg_temp_free_i32(tmp);
11800 } else {
11801 /* Signed 64-bit multiply */
11802 tmp64 = gen_muls_i64_i32(tmp, tmp2);
11805 if (op & 4) {
11806 /* umaal */
11807 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11808 tcg_temp_free_i64(tmp64);
11809 goto illegal_op;
11811 gen_addq_lo(s, tmp64, rs);
11812 gen_addq_lo(s, tmp64, rd);
11813 } else if (op & 0x40) {
11814 /* 64-bit accumulate. */
11815 gen_addq(s, tmp64, rs, rd);
11817 gen_storeq_reg(s, rs, rd, tmp64);
11818 tcg_temp_free_i64(tmp64);
11820 break;
11822 break;
11823 case 6: case 7: case 14: case 15:
11824 /* Coprocessor. */
11825 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11826 /* 0b111x_11xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx */
11827 if (extract32(insn, 24, 2) == 3) {
11828 goto illegal_op; /* op0 = 0b11 : unallocated */
11832 * Decode VLLDM and VLSTM first: these are nonstandard because:
11833 * * if there is no FPU then these insns must NOP in
11834 * Secure state and UNDEF in Nonsecure state
11835 * * if there is an FPU then these insns do not have
11836 * the usual behaviour that disas_vfp_insn() provides of
11837 * being controlled by CPACR/NSACR enable bits or the
11838 * lazy-stacking logic.
11840 if (arm_dc_feature(s, ARM_FEATURE_V8) &&
11841 (insn & 0xffa00f00) == 0xec200a00) {
11842 /* 0b1110_1100_0x1x_xxxx_xxxx_1010_xxxx_xxxx
11843 * - VLLDM, VLSTM
11844 * We choose to UNDEF if the RAZ bits are non-zero.
11846 if (!s->v8m_secure || (insn & 0x0040f0ff)) {
11847 goto illegal_op;
11850 if (arm_dc_feature(s, ARM_FEATURE_VFP)) {
11851 TCGv_i32 fptr = load_reg(s, rn);
11853 if (extract32(insn, 20, 1)) {
11854 gen_helper_v7m_vlldm(cpu_env, fptr);
11855 } else {
11856 gen_helper_v7m_vlstm(cpu_env, fptr);
11858 tcg_temp_free_i32(fptr);
11860 /* End the TB, because we have updated FP control bits */
11861 s->base.is_jmp = DISAS_UPDATE;
11863 break;
11865 if (arm_dc_feature(s, ARM_FEATURE_VFP) &&
11866 ((insn >> 8) & 0xe) == 10) {
11867 /* FP, and the CPU supports it */
11868 if (disas_vfp_insn(s, insn)) {
11869 goto illegal_op;
11871 break;
11874 /* All other insns: NOCP */
11875 gen_exception_insn(s, 4, EXCP_NOCP, syn_uncategorized(),
11876 default_exception_el(s));
11877 break;
11879 if ((insn & 0xfe000a00) == 0xfc000800
11880 && arm_dc_feature(s, ARM_FEATURE_V8)) {
11881 /* The Thumb2 and ARM encodings are identical. */
11882 if (disas_neon_insn_3same_ext(s, insn)) {
11883 goto illegal_op;
11885 } else if ((insn & 0xff000a00) == 0xfe000800
11886 && arm_dc_feature(s, ARM_FEATURE_V8)) {
11887 /* The Thumb2 and ARM encodings are identical. */
11888 if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
11889 goto illegal_op;
11891 } else if (((insn >> 24) & 3) == 3) {
11892 /* Translate into the equivalent ARM encoding. */
11893 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
11894 if (disas_neon_data_insn(s, insn)) {
11895 goto illegal_op;
11897 } else if (((insn >> 8) & 0xe) == 10) {
11898 if (disas_vfp_insn(s, insn)) {
11899 goto illegal_op;
11901 } else {
11902 if (insn & (1 << 28))
11903 goto illegal_op;
11904 if (disas_coproc_insn(s, insn)) {
11905 goto illegal_op;
11908 break;
11909 case 8: case 9: case 10: case 11:
11910 if (insn & (1 << 15)) {
11911 /* Branches, misc control. */
11912 if (insn & 0x5000) {
11913 /* Unconditional branch. */
11914 /* signextend(hw1[10:0]) -> offset[:12]. */
11915 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
11916 /* hw1[10:0] -> offset[11:1]. */
11917 offset |= (insn & 0x7ff) << 1;
11918 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
11919 offset[24:22] already have the same value because of the
11920 sign extension above. */
11921 offset ^= ((~insn) & (1 << 13)) << 10;
11922 offset ^= ((~insn) & (1 << 11)) << 11;
11924 if (insn & (1 << 14)) {
11925 /* Branch and link. */
11926 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
11929 offset += s->pc;
11930 if (insn & (1 << 12)) {
11931 /* b/bl */
11932 gen_jmp(s, offset);
11933 } else {
11934 /* blx */
11935 offset &= ~(uint32_t)2;
11936 /* thumb2 bx, no need to check */
11937 gen_bx_im(s, offset);
11939 } else if (((insn >> 23) & 7) == 7) {
11940 /* Misc control */
11941 if (insn & (1 << 13))
11942 goto illegal_op;
11944 if (insn & (1 << 26)) {
11945 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11946 goto illegal_op;
11948 if (!(insn & (1 << 20))) {
11949 /* Hypervisor call (v7) */
11950 int imm16 = extract32(insn, 16, 4) << 12
11951 | extract32(insn, 0, 12);
11952 ARCH(7);
11953 if (IS_USER(s)) {
11954 goto illegal_op;
11956 gen_hvc(s, imm16);
11957 } else {
11958 /* Secure monitor call (v6+) */
11959 ARCH(6K);
11960 if (IS_USER(s)) {
11961 goto illegal_op;
11963 gen_smc(s);
11965 } else {
11966 op = (insn >> 20) & 7;
11967 switch (op) {
11968 case 0: /* msr cpsr. */
11969 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11970 tmp = load_reg(s, rn);
11971 /* the constant is the mask and SYSm fields */
11972 addr = tcg_const_i32(insn & 0xfff);
11973 gen_helper_v7m_msr(cpu_env, addr, tmp);
11974 tcg_temp_free_i32(addr);
11975 tcg_temp_free_i32(tmp);
11976 gen_lookup_tb(s);
11977 break;
11979 /* fall through */
11980 case 1: /* msr spsr. */
11981 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11982 goto illegal_op;
11985 if (extract32(insn, 5, 1)) {
11986 /* MSR (banked) */
11987 int sysm = extract32(insn, 8, 4) |
11988 (extract32(insn, 4, 1) << 4);
11989 int r = op & 1;
11991 gen_msr_banked(s, r, sysm, rm);
11992 break;
11995 /* MSR (for PSRs) */
11996 tmp = load_reg(s, rn);
11997 if (gen_set_psr(s,
11998 msr_mask(s, (insn >> 8) & 0xf, op == 1),
11999 op == 1, tmp))
12000 goto illegal_op;
12001 break;
12002 case 2: /* cps, nop-hint. */
12003 if (((insn >> 8) & 7) == 0) {
12004 gen_nop_hint(s, insn & 0xff);
12006 /* Implemented as NOP in user mode. */
12007 if (IS_USER(s))
12008 break;
12009 offset = 0;
12010 imm = 0;
12011 if (insn & (1 << 10)) {
12012 if (insn & (1 << 7))
12013 offset |= CPSR_A;
12014 if (insn & (1 << 6))
12015 offset |= CPSR_I;
12016 if (insn & (1 << 5))
12017 offset |= CPSR_F;
12018 if (insn & (1 << 9))
12019 imm = CPSR_A | CPSR_I | CPSR_F;
12021 if (insn & (1 << 8)) {
12022 offset |= 0x1f;
12023 imm |= (insn & 0x1f);
12025 if (offset) {
12026 gen_set_psr_im(s, offset, 0, imm);
12028 break;
12029 case 3: /* Special control operations. */
12030 if (!arm_dc_feature(s, ARM_FEATURE_V7) &&
12031 !arm_dc_feature(s, ARM_FEATURE_M)) {
12032 goto illegal_op;
12034 op = (insn >> 4) & 0xf;
12035 switch (op) {
12036 case 2: /* clrex */
12037 gen_clrex(s);
12038 break;
12039 case 4: /* dsb */
12040 case 5: /* dmb */
12041 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
12042 break;
12043 case 6: /* isb */
12044 /* We need to break the TB after this insn
12045 * to execute self-modifying code correctly
12046 * and also to take any pending interrupts
12047 * immediately.
12049 gen_goto_tb(s, 0, s->pc & ~1);
12050 break;
12051 case 7: /* sb */
12052 if ((insn & 0xf) || !dc_isar_feature(aa32_sb, s)) {
12053 goto illegal_op;
12056 * TODO: There is no speculation barrier opcode
12057 * for TCG; MB and end the TB instead.
12059 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
12060 gen_goto_tb(s, 0, s->pc & ~1);
12061 break;
12062 default:
12063 goto illegal_op;
12065 break;
12066 case 4: /* bxj */
12067 /* Trivial implementation equivalent to bx.
12068 * This instruction doesn't exist at all for M-profile.
12070 if (arm_dc_feature(s, ARM_FEATURE_M)) {
12071 goto illegal_op;
12073 tmp = load_reg(s, rn);
12074 gen_bx(s, tmp);
12075 break;
12076 case 5: /* Exception return. */
12077 if (IS_USER(s)) {
12078 goto illegal_op;
12080 if (rn != 14 || rd != 15) {
12081 goto illegal_op;
12083 if (s->current_el == 2) {
12084 /* ERET from Hyp uses ELR_Hyp, not LR */
12085 if (insn & 0xff) {
12086 goto illegal_op;
12088 tmp = load_cpu_field(elr_el[2]);
12089 } else {
12090 tmp = load_reg(s, rn);
12091 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
12093 gen_exception_return(s, tmp);
12094 break;
12095 case 6: /* MRS */
12096 if (extract32(insn, 5, 1) &&
12097 !arm_dc_feature(s, ARM_FEATURE_M)) {
12098 /* MRS (banked) */
12099 int sysm = extract32(insn, 16, 4) |
12100 (extract32(insn, 4, 1) << 4);
12102 gen_mrs_banked(s, 0, sysm, rd);
12103 break;
12106 if (extract32(insn, 16, 4) != 0xf) {
12107 goto illegal_op;
12109 if (!arm_dc_feature(s, ARM_FEATURE_M) &&
12110 extract32(insn, 0, 8) != 0) {
12111 goto illegal_op;
12114 /* mrs cpsr */
12115 tmp = tcg_temp_new_i32();
12116 if (arm_dc_feature(s, ARM_FEATURE_M)) {
12117 addr = tcg_const_i32(insn & 0xff);
12118 gen_helper_v7m_mrs(tmp, cpu_env, addr);
12119 tcg_temp_free_i32(addr);
12120 } else {
12121 gen_helper_cpsr_read(tmp, cpu_env);
12123 store_reg(s, rd, tmp);
12124 break;
12125 case 7: /* MRS */
12126 if (extract32(insn, 5, 1) &&
12127 !arm_dc_feature(s, ARM_FEATURE_M)) {
12128 /* MRS (banked) */
12129 int sysm = extract32(insn, 16, 4) |
12130 (extract32(insn, 4, 1) << 4);
12132 gen_mrs_banked(s, 1, sysm, rd);
12133 break;
12136 /* mrs spsr. */
12137 /* Not accessible in user mode. */
12138 if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
12139 goto illegal_op;
12142 if (extract32(insn, 16, 4) != 0xf ||
12143 extract32(insn, 0, 8) != 0) {
12144 goto illegal_op;
12147 tmp = load_cpu_field(spsr);
12148 store_reg(s, rd, tmp);
12149 break;
12152 } else {
12153 /* Conditional branch. */
12154 op = (insn >> 22) & 0xf;
12155 /* Generate a conditional jump to next instruction. */
12156 arm_skip_unless(s, op);
12158 /* offset[11:1] = insn[10:0] */
12159 offset = (insn & 0x7ff) << 1;
12160 /* offset[17:12] = insn[21:16]. */
12161 offset |= (insn & 0x003f0000) >> 4;
12162 /* offset[31:20] = insn[26]. */
12163 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
12164 /* offset[18] = insn[13]. */
12165 offset |= (insn & (1 << 13)) << 5;
12166 /* offset[19] = insn[11]. */
12167 offset |= (insn & (1 << 11)) << 8;
12169 /* jump to the offset */
12170 gen_jmp(s, s->pc + offset);
12172 } else {
12174 * 0b1111_0xxx_xxxx_0xxx_xxxx_xxxx
12175 * - Data-processing (modified immediate, plain binary immediate)
12177 if (insn & (1 << 25)) {
12179 * 0b1111_0x1x_xxxx_0xxx_xxxx_xxxx
12180 * - Data-processing (plain binary immediate)
12182 if (insn & (1 << 24)) {
12183 if (insn & (1 << 20))
12184 goto illegal_op;
12185 /* Bitfield/Saturate. */
12186 op = (insn >> 21) & 7;
12187 imm = insn & 0x1f;
12188 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
12189 if (rn == 15) {
12190 tmp = tcg_temp_new_i32();
12191 tcg_gen_movi_i32(tmp, 0);
12192 } else {
12193 tmp = load_reg(s, rn);
12195 switch (op) {
12196 case 2: /* Signed bitfield extract. */
12197 imm++;
12198 if (shift + imm > 32)
12199 goto illegal_op;
12200 if (imm < 32) {
12201 tcg_gen_sextract_i32(tmp, tmp, shift, imm);
12203 break;
12204 case 6: /* Unsigned bitfield extract. */
12205 imm++;
12206 if (shift + imm > 32)
12207 goto illegal_op;
12208 if (imm < 32) {
12209 tcg_gen_extract_i32(tmp, tmp, shift, imm);
12211 break;
12212 case 3: /* Bitfield insert/clear. */
12213 if (imm < shift)
12214 goto illegal_op;
12215 imm = imm + 1 - shift;
12216 if (imm != 32) {
12217 tmp2 = load_reg(s, rd);
12218 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, imm);
12219 tcg_temp_free_i32(tmp2);
12221 break;
12222 case 7:
12223 goto illegal_op;
12224 default: /* Saturate. */
12225 if (shift) {
12226 if (op & 1)
12227 tcg_gen_sari_i32(tmp, tmp, shift);
12228 else
12229 tcg_gen_shli_i32(tmp, tmp, shift);
12231 tmp2 = tcg_const_i32(imm);
12232 if (op & 4) {
12233 /* Unsigned. */
12234 if ((op & 1) && shift == 0) {
12235 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
12236 tcg_temp_free_i32(tmp);
12237 tcg_temp_free_i32(tmp2);
12238 goto illegal_op;
12240 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
12241 } else {
12242 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
12244 } else {
12245 /* Signed. */
12246 if ((op & 1) && shift == 0) {
12247 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
12248 tcg_temp_free_i32(tmp);
12249 tcg_temp_free_i32(tmp2);
12250 goto illegal_op;
12252 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
12253 } else {
12254 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
12257 tcg_temp_free_i32(tmp2);
12258 break;
12260 store_reg(s, rd, tmp);
12261 } else {
12262 imm = ((insn & 0x04000000) >> 15)
12263 | ((insn & 0x7000) >> 4) | (insn & 0xff);
12264 if (insn & (1 << 22)) {
12265 /* 16-bit immediate. */
12266 imm |= (insn >> 4) & 0xf000;
12267 if (insn & (1 << 23)) {
12268 /* movt */
12269 tmp = load_reg(s, rd);
12270 tcg_gen_ext16u_i32(tmp, tmp);
12271 tcg_gen_ori_i32(tmp, tmp, imm << 16);
12272 } else {
12273 /* movw */
12274 tmp = tcg_temp_new_i32();
12275 tcg_gen_movi_i32(tmp, imm);
12277 store_reg(s, rd, tmp);
12278 } else {
12279 /* Add/sub 12-bit immediate. */
12280 if (rn == 15) {
12281 offset = s->pc & ~(uint32_t)3;
12282 if (insn & (1 << 23))
12283 offset -= imm;
12284 else
12285 offset += imm;
12286 tmp = tcg_temp_new_i32();
12287 tcg_gen_movi_i32(tmp, offset);
12288 store_reg(s, rd, tmp);
12289 } else {
12290 tmp = load_reg(s, rn);
12291 if (insn & (1 << 23))
12292 tcg_gen_subi_i32(tmp, tmp, imm);
12293 else
12294 tcg_gen_addi_i32(tmp, tmp, imm);
12295 if (rn == 13 && rd == 13) {
12296 /* ADD SP, SP, imm or SUB SP, SP, imm */
12297 store_sp_checked(s, tmp);
12298 } else {
12299 store_reg(s, rd, tmp);
12304 } else {
12306 * 0b1111_0x0x_xxxx_0xxx_xxxx_xxxx
12307 * - Data-processing (modified immediate)
12309 int shifter_out = 0;
12310 /* modified 12-bit immediate. */
12311 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
12312 imm = (insn & 0xff);
12313 switch (shift) {
12314 case 0: /* XY */
12315 /* Nothing to do. */
12316 break;
12317 case 1: /* 00XY00XY */
12318 imm |= imm << 16;
12319 break;
12320 case 2: /* XY00XY00 */
12321 imm |= imm << 16;
12322 imm <<= 8;
12323 break;
12324 case 3: /* XYXYXYXY */
12325 imm |= imm << 16;
12326 imm |= imm << 8;
12327 break;
12328 default: /* Rotated constant. */
12329 shift = (shift << 1) | (imm >> 7);
12330 imm |= 0x80;
12331 imm = imm << (32 - shift);
12332 shifter_out = 1;
12333 break;
12335 tmp2 = tcg_temp_new_i32();
12336 tcg_gen_movi_i32(tmp2, imm);
12337 rn = (insn >> 16) & 0xf;
12338 if (rn == 15) {
12339 tmp = tcg_temp_new_i32();
12340 tcg_gen_movi_i32(tmp, 0);
12341 } else {
12342 tmp = load_reg(s, rn);
12344 op = (insn >> 21) & 0xf;
12345 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
12346 shifter_out, tmp, tmp2))
12347 goto illegal_op;
12348 tcg_temp_free_i32(tmp2);
12349 rd = (insn >> 8) & 0xf;
12350 if (rd == 13 && rn == 13
12351 && (op == 8 || op == 13)) {
12352 /* ADD(S) SP, SP, imm or SUB(S) SP, SP, imm */
12353 store_sp_checked(s, tmp);
12354 } else if (rd != 15) {
12355 store_reg(s, rd, tmp);
12356 } else {
12357 tcg_temp_free_i32(tmp);
12361 break;
12362 case 12: /* Load/store single data item. */
12364 int postinc = 0;
12365 int writeback = 0;
12366 int memidx;
12367 ISSInfo issinfo;
12369 if ((insn & 0x01100000) == 0x01000000) {
12370 if (disas_neon_ls_insn(s, insn)) {
12371 goto illegal_op;
12373 break;
12375 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
12376 if (rs == 15) {
12377 if (!(insn & (1 << 20))) {
12378 goto illegal_op;
12380 if (op != 2) {
12381 /* Byte or halfword load space with dest == r15 : memory hints.
12382 * Catch them early so we don't emit pointless addressing code.
12383 * This space is a mix of:
12384 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
12385 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
12386 * cores)
12387 * unallocated hints, which must be treated as NOPs
12388 * UNPREDICTABLE space, which we NOP or UNDEF depending on
12389 * which is easiest for the decoding logic
12390 * Some space which must UNDEF
12392 int op1 = (insn >> 23) & 3;
12393 int op2 = (insn >> 6) & 0x3f;
12394 if (op & 2) {
12395 goto illegal_op;
12397 if (rn == 15) {
12398 /* UNPREDICTABLE, unallocated hint or
12399 * PLD/PLDW/PLI (literal)
12401 return;
12403 if (op1 & 1) {
12404 return; /* PLD/PLDW/PLI or unallocated hint */
12406 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
12407 return; /* PLD/PLDW/PLI or unallocated hint */
12409 /* UNDEF space, or an UNPREDICTABLE */
12410 goto illegal_op;
12413 memidx = get_mem_index(s);
12414 if (rn == 15) {
12415 addr = tcg_temp_new_i32();
12416 /* PC relative. */
12417 /* s->pc has already been incremented by 4. */
12418 imm = s->pc & 0xfffffffc;
12419 if (insn & (1 << 23))
12420 imm += insn & 0xfff;
12421 else
12422 imm -= insn & 0xfff;
12423 tcg_gen_movi_i32(addr, imm);
12424 } else {
12425 addr = load_reg(s, rn);
12426 if (insn & (1 << 23)) {
12427 /* Positive offset. */
12428 imm = insn & 0xfff;
12429 tcg_gen_addi_i32(addr, addr, imm);
12430 } else {
12431 imm = insn & 0xff;
12432 switch ((insn >> 8) & 0xf) {
12433 case 0x0: /* Shifted Register. */
12434 shift = (insn >> 4) & 0xf;
12435 if (shift > 3) {
12436 tcg_temp_free_i32(addr);
12437 goto illegal_op;
12439 tmp = load_reg(s, rm);
12440 if (shift)
12441 tcg_gen_shli_i32(tmp, tmp, shift);
12442 tcg_gen_add_i32(addr, addr, tmp);
12443 tcg_temp_free_i32(tmp);
12444 break;
12445 case 0xc: /* Negative offset. */
12446 tcg_gen_addi_i32(addr, addr, -imm);
12447 break;
12448 case 0xe: /* User privilege. */
12449 tcg_gen_addi_i32(addr, addr, imm);
12450 memidx = get_a32_user_mem_index(s);
12451 break;
12452 case 0x9: /* Post-decrement. */
12453 imm = -imm;
12454 /* Fall through. */
12455 case 0xb: /* Post-increment. */
12456 postinc = 1;
12457 writeback = 1;
12458 break;
12459 case 0xd: /* Pre-decrement. */
12460 imm = -imm;
12461 /* Fall through. */
12462 case 0xf: /* Pre-increment. */
12463 writeback = 1;
12464 break;
12465 default:
12466 tcg_temp_free_i32(addr);
12467 goto illegal_op;
12472 issinfo = writeback ? ISSInvalid : rs;
12474 if (s->v8m_stackcheck && rn == 13 && writeback) {
12476 * Stackcheck. Here we know 'addr' is the current SP;
12477 * if imm is +ve we're moving SP up, else down. It is
12478 * UNKNOWN whether the limit check triggers when SP starts
12479 * below the limit and ends up above it; we chose to do so.
12481 if ((int32_t)imm < 0) {
12482 TCGv_i32 newsp = tcg_temp_new_i32();
12484 tcg_gen_addi_i32(newsp, addr, imm);
12485 gen_helper_v8m_stackcheck(cpu_env, newsp);
12486 tcg_temp_free_i32(newsp);
12487 } else {
12488 gen_helper_v8m_stackcheck(cpu_env, addr);
12492 if (writeback && !postinc) {
12493 tcg_gen_addi_i32(addr, addr, imm);
12496 if (insn & (1 << 20)) {
12497 /* Load. */
12498 tmp = tcg_temp_new_i32();
12499 switch (op) {
12500 case 0:
12501 gen_aa32_ld8u_iss(s, tmp, addr, memidx, issinfo);
12502 break;
12503 case 4:
12504 gen_aa32_ld8s_iss(s, tmp, addr, memidx, issinfo);
12505 break;
12506 case 1:
12507 gen_aa32_ld16u_iss(s, tmp, addr, memidx, issinfo);
12508 break;
12509 case 5:
12510 gen_aa32_ld16s_iss(s, tmp, addr, memidx, issinfo);
12511 break;
12512 case 2:
12513 gen_aa32_ld32u_iss(s, tmp, addr, memidx, issinfo);
12514 break;
12515 default:
12516 tcg_temp_free_i32(tmp);
12517 tcg_temp_free_i32(addr);
12518 goto illegal_op;
12520 if (rs == 15) {
12521 gen_bx_excret(s, tmp);
12522 } else {
12523 store_reg(s, rs, tmp);
12525 } else {
12526 /* Store. */
12527 tmp = load_reg(s, rs);
12528 switch (op) {
12529 case 0:
12530 gen_aa32_st8_iss(s, tmp, addr, memidx, issinfo);
12531 break;
12532 case 1:
12533 gen_aa32_st16_iss(s, tmp, addr, memidx, issinfo);
12534 break;
12535 case 2:
12536 gen_aa32_st32_iss(s, tmp, addr, memidx, issinfo);
12537 break;
12538 default:
12539 tcg_temp_free_i32(tmp);
12540 tcg_temp_free_i32(addr);
12541 goto illegal_op;
12543 tcg_temp_free_i32(tmp);
12545 if (postinc)
12546 tcg_gen_addi_i32(addr, addr, imm);
12547 if (writeback) {
12548 store_reg(s, rn, addr);
12549 } else {
12550 tcg_temp_free_i32(addr);
12553 break;
12554 default:
12555 goto illegal_op;
12557 return;
12558 illegal_op:
12559 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
12560 default_exception_el(s));
12563 static void disas_thumb_insn(DisasContext *s, uint32_t insn)
12565 uint32_t val, op, rm, rn, rd, shift, cond;
12566 int32_t offset;
12567 int i;
12568 TCGv_i32 tmp;
12569 TCGv_i32 tmp2;
12570 TCGv_i32 addr;
12572 switch (insn >> 12) {
12573 case 0: case 1:
12575 rd = insn & 7;
12576 op = (insn >> 11) & 3;
12577 if (op == 3) {
12579 * 0b0001_1xxx_xxxx_xxxx
12580 * - Add, subtract (three low registers)
12581 * - Add, subtract (two low registers and immediate)
12583 rn = (insn >> 3) & 7;
12584 tmp = load_reg(s, rn);
12585 if (insn & (1 << 10)) {
12586 /* immediate */
12587 tmp2 = tcg_temp_new_i32();
12588 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
12589 } else {
12590 /* reg */
12591 rm = (insn >> 6) & 7;
12592 tmp2 = load_reg(s, rm);
12594 if (insn & (1 << 9)) {
12595 if (s->condexec_mask)
12596 tcg_gen_sub_i32(tmp, tmp, tmp2);
12597 else
12598 gen_sub_CC(tmp, tmp, tmp2);
12599 } else {
12600 if (s->condexec_mask)
12601 tcg_gen_add_i32(tmp, tmp, tmp2);
12602 else
12603 gen_add_CC(tmp, tmp, tmp2);
12605 tcg_temp_free_i32(tmp2);
12606 store_reg(s, rd, tmp);
12607 } else {
12608 /* shift immediate */
12609 rm = (insn >> 3) & 7;
12610 shift = (insn >> 6) & 0x1f;
12611 tmp = load_reg(s, rm);
12612 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
12613 if (!s->condexec_mask)
12614 gen_logic_CC(tmp);
12615 store_reg(s, rd, tmp);
12617 break;
12618 case 2: case 3:
12620 * 0b001x_xxxx_xxxx_xxxx
12621 * - Add, subtract, compare, move (one low register and immediate)
12623 op = (insn >> 11) & 3;
12624 rd = (insn >> 8) & 0x7;
12625 if (op == 0) { /* mov */
12626 tmp = tcg_temp_new_i32();
12627 tcg_gen_movi_i32(tmp, insn & 0xff);
12628 if (!s->condexec_mask)
12629 gen_logic_CC(tmp);
12630 store_reg(s, rd, tmp);
12631 } else {
12632 tmp = load_reg(s, rd);
12633 tmp2 = tcg_temp_new_i32();
12634 tcg_gen_movi_i32(tmp2, insn & 0xff);
12635 switch (op) {
12636 case 1: /* cmp */
12637 gen_sub_CC(tmp, tmp, tmp2);
12638 tcg_temp_free_i32(tmp);
12639 tcg_temp_free_i32(tmp2);
12640 break;
12641 case 2: /* add */
12642 if (s->condexec_mask)
12643 tcg_gen_add_i32(tmp, tmp, tmp2);
12644 else
12645 gen_add_CC(tmp, tmp, tmp2);
12646 tcg_temp_free_i32(tmp2);
12647 store_reg(s, rd, tmp);
12648 break;
12649 case 3: /* sub */
12650 if (s->condexec_mask)
12651 tcg_gen_sub_i32(tmp, tmp, tmp2);
12652 else
12653 gen_sub_CC(tmp, tmp, tmp2);
12654 tcg_temp_free_i32(tmp2);
12655 store_reg(s, rd, tmp);
12656 break;
12659 break;
12660 case 4:
12661 if (insn & (1 << 11)) {
12662 rd = (insn >> 8) & 7;
12663 /* load pc-relative. Bit 1 of PC is ignored. */
12664 val = s->pc + 2 + ((insn & 0xff) * 4);
12665 val &= ~(uint32_t)2;
12666 addr = tcg_temp_new_i32();
12667 tcg_gen_movi_i32(addr, val);
12668 tmp = tcg_temp_new_i32();
12669 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s),
12670 rd | ISSIs16Bit);
12671 tcg_temp_free_i32(addr);
12672 store_reg(s, rd, tmp);
12673 break;
12675 if (insn & (1 << 10)) {
12676 /* 0b0100_01xx_xxxx_xxxx
12677 * - data processing extended, branch and exchange
12679 rd = (insn & 7) | ((insn >> 4) & 8);
12680 rm = (insn >> 3) & 0xf;
12681 op = (insn >> 8) & 3;
12682 switch (op) {
12683 case 0: /* add */
12684 tmp = load_reg(s, rd);
12685 tmp2 = load_reg(s, rm);
12686 tcg_gen_add_i32(tmp, tmp, tmp2);
12687 tcg_temp_free_i32(tmp2);
12688 if (rd == 13) {
12689 /* ADD SP, SP, reg */
12690 store_sp_checked(s, tmp);
12691 } else {
12692 store_reg(s, rd, tmp);
12694 break;
12695 case 1: /* cmp */
12696 tmp = load_reg(s, rd);
12697 tmp2 = load_reg(s, rm);
12698 gen_sub_CC(tmp, tmp, tmp2);
12699 tcg_temp_free_i32(tmp2);
12700 tcg_temp_free_i32(tmp);
12701 break;
12702 case 2: /* mov/cpy */
12703 tmp = load_reg(s, rm);
12704 if (rd == 13) {
12705 /* MOV SP, reg */
12706 store_sp_checked(s, tmp);
12707 } else {
12708 store_reg(s, rd, tmp);
12710 break;
12711 case 3:
12713 /* 0b0100_0111_xxxx_xxxx
12714 * - branch [and link] exchange thumb register
12716 bool link = insn & (1 << 7);
12718 if (insn & 3) {
12719 goto undef;
12721 if (link) {
12722 ARCH(5);
12724 if ((insn & 4)) {
12725 /* BXNS/BLXNS: only exists for v8M with the
12726 * security extensions, and always UNDEF if NonSecure.
12727 * We don't implement these in the user-only mode
12728 * either (in theory you can use them from Secure User
12729 * mode but they are too tied in to system emulation.)
12731 if (!s->v8m_secure || IS_USER_ONLY) {
12732 goto undef;
12734 if (link) {
12735 gen_blxns(s, rm);
12736 } else {
12737 gen_bxns(s, rm);
12739 break;
12741 /* BLX/BX */
12742 tmp = load_reg(s, rm);
12743 if (link) {
12744 val = (uint32_t)s->pc | 1;
12745 tmp2 = tcg_temp_new_i32();
12746 tcg_gen_movi_i32(tmp2, val);
12747 store_reg(s, 14, tmp2);
12748 gen_bx(s, tmp);
12749 } else {
12750 /* Only BX works as exception-return, not BLX */
12751 gen_bx_excret(s, tmp);
12753 break;
12756 break;
12760 * 0b0100_00xx_xxxx_xxxx
12761 * - Data-processing (two low registers)
12763 rd = insn & 7;
12764 rm = (insn >> 3) & 7;
12765 op = (insn >> 6) & 0xf;
12766 if (op == 2 || op == 3 || op == 4 || op == 7) {
12767 /* the shift/rotate ops want the operands backwards */
12768 val = rm;
12769 rm = rd;
12770 rd = val;
12771 val = 1;
12772 } else {
12773 val = 0;
12776 if (op == 9) { /* neg */
12777 tmp = tcg_temp_new_i32();
12778 tcg_gen_movi_i32(tmp, 0);
12779 } else if (op != 0xf) { /* mvn doesn't read its first operand */
12780 tmp = load_reg(s, rd);
12781 } else {
12782 tmp = NULL;
12785 tmp2 = load_reg(s, rm);
12786 switch (op) {
12787 case 0x0: /* and */
12788 tcg_gen_and_i32(tmp, tmp, tmp2);
12789 if (!s->condexec_mask)
12790 gen_logic_CC(tmp);
12791 break;
12792 case 0x1: /* eor */
12793 tcg_gen_xor_i32(tmp, tmp, tmp2);
12794 if (!s->condexec_mask)
12795 gen_logic_CC(tmp);
12796 break;
12797 case 0x2: /* lsl */
12798 if (s->condexec_mask) {
12799 gen_shl(tmp2, tmp2, tmp);
12800 } else {
12801 gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
12802 gen_logic_CC(tmp2);
12804 break;
12805 case 0x3: /* lsr */
12806 if (s->condexec_mask) {
12807 gen_shr(tmp2, tmp2, tmp);
12808 } else {
12809 gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
12810 gen_logic_CC(tmp2);
12812 break;
12813 case 0x4: /* asr */
12814 if (s->condexec_mask) {
12815 gen_sar(tmp2, tmp2, tmp);
12816 } else {
12817 gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
12818 gen_logic_CC(tmp2);
12820 break;
12821 case 0x5: /* adc */
12822 if (s->condexec_mask) {
12823 gen_adc(tmp, tmp2);
12824 } else {
12825 gen_adc_CC(tmp, tmp, tmp2);
12827 break;
12828 case 0x6: /* sbc */
12829 if (s->condexec_mask) {
12830 gen_sub_carry(tmp, tmp, tmp2);
12831 } else {
12832 gen_sbc_CC(tmp, tmp, tmp2);
12834 break;
12835 case 0x7: /* ror */
12836 if (s->condexec_mask) {
12837 tcg_gen_andi_i32(tmp, tmp, 0x1f);
12838 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
12839 } else {
12840 gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);
12841 gen_logic_CC(tmp2);
12843 break;
12844 case 0x8: /* tst */
12845 tcg_gen_and_i32(tmp, tmp, tmp2);
12846 gen_logic_CC(tmp);
12847 rd = 16;
12848 break;
12849 case 0x9: /* neg */
12850 if (s->condexec_mask)
12851 tcg_gen_neg_i32(tmp, tmp2);
12852 else
12853 gen_sub_CC(tmp, tmp, tmp2);
12854 break;
12855 case 0xa: /* cmp */
12856 gen_sub_CC(tmp, tmp, tmp2);
12857 rd = 16;
12858 break;
12859 case 0xb: /* cmn */
12860 gen_add_CC(tmp, tmp, tmp2);
12861 rd = 16;
12862 break;
12863 case 0xc: /* orr */
12864 tcg_gen_or_i32(tmp, tmp, tmp2);
12865 if (!s->condexec_mask)
12866 gen_logic_CC(tmp);
12867 break;
12868 case 0xd: /* mul */
12869 tcg_gen_mul_i32(tmp, tmp, tmp2);
12870 if (!s->condexec_mask)
12871 gen_logic_CC(tmp);
12872 break;
12873 case 0xe: /* bic */
12874 tcg_gen_andc_i32(tmp, tmp, tmp2);
12875 if (!s->condexec_mask)
12876 gen_logic_CC(tmp);
12877 break;
12878 case 0xf: /* mvn */
12879 tcg_gen_not_i32(tmp2, tmp2);
12880 if (!s->condexec_mask)
12881 gen_logic_CC(tmp2);
12882 val = 1;
12883 rm = rd;
12884 break;
12886 if (rd != 16) {
12887 if (val) {
12888 store_reg(s, rm, tmp2);
12889 if (op != 0xf)
12890 tcg_temp_free_i32(tmp);
12891 } else {
12892 store_reg(s, rd, tmp);
12893 tcg_temp_free_i32(tmp2);
12895 } else {
12896 tcg_temp_free_i32(tmp);
12897 tcg_temp_free_i32(tmp2);
12899 break;
12901 case 5:
12902 /* load/store register offset. */
12903 rd = insn & 7;
12904 rn = (insn >> 3) & 7;
12905 rm = (insn >> 6) & 7;
12906 op = (insn >> 9) & 7;
12907 addr = load_reg(s, rn);
12908 tmp = load_reg(s, rm);
12909 tcg_gen_add_i32(addr, addr, tmp);
12910 tcg_temp_free_i32(tmp);
12912 if (op < 3) { /* store */
12913 tmp = load_reg(s, rd);
12914 } else {
12915 tmp = tcg_temp_new_i32();
12918 switch (op) {
12919 case 0: /* str */
12920 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12921 break;
12922 case 1: /* strh */
12923 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12924 break;
12925 case 2: /* strb */
12926 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12927 break;
12928 case 3: /* ldrsb */
12929 gen_aa32_ld8s_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12930 break;
12931 case 4: /* ldr */
12932 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12933 break;
12934 case 5: /* ldrh */
12935 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12936 break;
12937 case 6: /* ldrb */
12938 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12939 break;
12940 case 7: /* ldrsh */
12941 gen_aa32_ld16s_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12942 break;
12944 if (op >= 3) { /* load */
12945 store_reg(s, rd, tmp);
12946 } else {
12947 tcg_temp_free_i32(tmp);
12949 tcg_temp_free_i32(addr);
12950 break;
12952 case 6:
12953 /* load/store word immediate offset */
12954 rd = insn & 7;
12955 rn = (insn >> 3) & 7;
12956 addr = load_reg(s, rn);
12957 val = (insn >> 4) & 0x7c;
12958 tcg_gen_addi_i32(addr, addr, val);
12960 if (insn & (1 << 11)) {
12961 /* load */
12962 tmp = tcg_temp_new_i32();
12963 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
12964 store_reg(s, rd, tmp);
12965 } else {
12966 /* store */
12967 tmp = load_reg(s, rd);
12968 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
12969 tcg_temp_free_i32(tmp);
12971 tcg_temp_free_i32(addr);
12972 break;
12974 case 7:
12975 /* load/store byte immediate offset */
12976 rd = insn & 7;
12977 rn = (insn >> 3) & 7;
12978 addr = load_reg(s, rn);
12979 val = (insn >> 6) & 0x1f;
12980 tcg_gen_addi_i32(addr, addr, val);
12982 if (insn & (1 << 11)) {
12983 /* load */
12984 tmp = tcg_temp_new_i32();
12985 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12986 store_reg(s, rd, tmp);
12987 } else {
12988 /* store */
12989 tmp = load_reg(s, rd);
12990 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12991 tcg_temp_free_i32(tmp);
12993 tcg_temp_free_i32(addr);
12994 break;
12996 case 8:
12997 /* load/store halfword immediate offset */
12998 rd = insn & 7;
12999 rn = (insn >> 3) & 7;
13000 addr = load_reg(s, rn);
13001 val = (insn >> 5) & 0x3e;
13002 tcg_gen_addi_i32(addr, addr, val);
13004 if (insn & (1 << 11)) {
13005 /* load */
13006 tmp = tcg_temp_new_i32();
13007 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
13008 store_reg(s, rd, tmp);
13009 } else {
13010 /* store */
13011 tmp = load_reg(s, rd);
13012 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
13013 tcg_temp_free_i32(tmp);
13015 tcg_temp_free_i32(addr);
13016 break;
13018 case 9:
13019 /* load/store from stack */
13020 rd = (insn >> 8) & 7;
13021 addr = load_reg(s, 13);
13022 val = (insn & 0xff) * 4;
13023 tcg_gen_addi_i32(addr, addr, val);
13025 if (insn & (1 << 11)) {
13026 /* load */
13027 tmp = tcg_temp_new_i32();
13028 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
13029 store_reg(s, rd, tmp);
13030 } else {
13031 /* store */
13032 tmp = load_reg(s, rd);
13033 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
13034 tcg_temp_free_i32(tmp);
13036 tcg_temp_free_i32(addr);
13037 break;
13039 case 10:
13041 * 0b1010_xxxx_xxxx_xxxx
13042 * - Add PC/SP (immediate)
13044 rd = (insn >> 8) & 7;
13045 if (insn & (1 << 11)) {
13046 /* SP */
13047 tmp = load_reg(s, 13);
13048 } else {
13049 /* PC. bit 1 is ignored. */
13050 tmp = tcg_temp_new_i32();
13051 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
13053 val = (insn & 0xff) * 4;
13054 tcg_gen_addi_i32(tmp, tmp, val);
13055 store_reg(s, rd, tmp);
13056 break;
13058 case 11:
13059 /* misc */
13060 op = (insn >> 8) & 0xf;
13061 switch (op) {
13062 case 0:
13064 * 0b1011_0000_xxxx_xxxx
13065 * - ADD (SP plus immediate)
13066 * - SUB (SP minus immediate)
13068 tmp = load_reg(s, 13);
13069 val = (insn & 0x7f) * 4;
13070 if (insn & (1 << 7))
13071 val = -(int32_t)val;
13072 tcg_gen_addi_i32(tmp, tmp, val);
13073 store_sp_checked(s, tmp);
13074 break;
13076 case 2: /* sign/zero extend. */
13077 ARCH(6);
13078 rd = insn & 7;
13079 rm = (insn >> 3) & 7;
13080 tmp = load_reg(s, rm);
13081 switch ((insn >> 6) & 3) {
13082 case 0: gen_sxth(tmp); break;
13083 case 1: gen_sxtb(tmp); break;
13084 case 2: gen_uxth(tmp); break;
13085 case 3: gen_uxtb(tmp); break;
13087 store_reg(s, rd, tmp);
13088 break;
13089 case 4: case 5: case 0xc: case 0xd:
13091 * 0b1011_x10x_xxxx_xxxx
13092 * - push/pop
13094 addr = load_reg(s, 13);
13095 if (insn & (1 << 8))
13096 offset = 4;
13097 else
13098 offset = 0;
13099 for (i = 0; i < 8; i++) {
13100 if (insn & (1 << i))
13101 offset += 4;
13103 if ((insn & (1 << 11)) == 0) {
13104 tcg_gen_addi_i32(addr, addr, -offset);
13107 if (s->v8m_stackcheck) {
13109 * Here 'addr' is the lower of "old SP" and "new SP";
13110 * if this is a pop that starts below the limit and ends
13111 * above it, it is UNKNOWN whether the limit check triggers;
13112 * we choose to trigger.
13114 gen_helper_v8m_stackcheck(cpu_env, addr);
13117 for (i = 0; i < 8; i++) {
13118 if (insn & (1 << i)) {
13119 if (insn & (1 << 11)) {
13120 /* pop */
13121 tmp = tcg_temp_new_i32();
13122 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
13123 store_reg(s, i, tmp);
13124 } else {
13125 /* push */
13126 tmp = load_reg(s, i);
13127 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
13128 tcg_temp_free_i32(tmp);
13130 /* advance to the next address. */
13131 tcg_gen_addi_i32(addr, addr, 4);
13134 tmp = NULL;
13135 if (insn & (1 << 8)) {
13136 if (insn & (1 << 11)) {
13137 /* pop pc */
13138 tmp = tcg_temp_new_i32();
13139 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
13140 /* don't set the pc until the rest of the instruction
13141 has completed */
13142 } else {
13143 /* push lr */
13144 tmp = load_reg(s, 14);
13145 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
13146 tcg_temp_free_i32(tmp);
13148 tcg_gen_addi_i32(addr, addr, 4);
13150 if ((insn & (1 << 11)) == 0) {
13151 tcg_gen_addi_i32(addr, addr, -offset);
13153 /* write back the new stack pointer */
13154 store_reg(s, 13, addr);
13155 /* set the new PC value */
13156 if ((insn & 0x0900) == 0x0900) {
13157 store_reg_from_load(s, 15, tmp);
13159 break;
13161 case 1: case 3: case 9: case 11: /* czb */
13162 rm = insn & 7;
13163 tmp = load_reg(s, rm);
13164 arm_gen_condlabel(s);
13165 if (insn & (1 << 11))
13166 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
13167 else
13168 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
13169 tcg_temp_free_i32(tmp);
13170 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
13171 val = (uint32_t)s->pc + 2;
13172 val += offset;
13173 gen_jmp(s, val);
13174 break;
13176 case 15: /* IT, nop-hint. */
13177 if ((insn & 0xf) == 0) {
13178 gen_nop_hint(s, (insn >> 4) & 0xf);
13179 break;
13181 /* If Then. */
13182 s->condexec_cond = (insn >> 4) & 0xe;
13183 s->condexec_mask = insn & 0x1f;
13184 /* No actual code generated for this insn, just setup state. */
13185 break;
13187 case 0xe: /* bkpt */
13189 int imm8 = extract32(insn, 0, 8);
13190 ARCH(5);
13191 gen_exception_bkpt_insn(s, 2, syn_aa32_bkpt(imm8, true));
13192 break;
13195 case 0xa: /* rev, and hlt */
13197 int op1 = extract32(insn, 6, 2);
13199 if (op1 == 2) {
13200 /* HLT */
13201 int imm6 = extract32(insn, 0, 6);
13203 gen_hlt(s, imm6);
13204 break;
13207 /* Otherwise this is rev */
13208 ARCH(6);
13209 rn = (insn >> 3) & 0x7;
13210 rd = insn & 0x7;
13211 tmp = load_reg(s, rn);
13212 switch (op1) {
13213 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
13214 case 1: gen_rev16(tmp); break;
13215 case 3: gen_revsh(tmp); break;
13216 default:
13217 g_assert_not_reached();
13219 store_reg(s, rd, tmp);
13220 break;
13223 case 6:
13224 switch ((insn >> 5) & 7) {
13225 case 2:
13226 /* setend */
13227 ARCH(6);
13228 if (((insn >> 3) & 1) != !!(s->be_data == MO_BE)) {
13229 gen_helper_setend(cpu_env);
13230 s->base.is_jmp = DISAS_UPDATE;
13232 break;
13233 case 3:
13234 /* cps */
13235 ARCH(6);
13236 if (IS_USER(s)) {
13237 break;
13239 if (arm_dc_feature(s, ARM_FEATURE_M)) {
13240 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
13241 /* FAULTMASK */
13242 if (insn & 1) {
13243 addr = tcg_const_i32(19);
13244 gen_helper_v7m_msr(cpu_env, addr, tmp);
13245 tcg_temp_free_i32(addr);
13247 /* PRIMASK */
13248 if (insn & 2) {
13249 addr = tcg_const_i32(16);
13250 gen_helper_v7m_msr(cpu_env, addr, tmp);
13251 tcg_temp_free_i32(addr);
13253 tcg_temp_free_i32(tmp);
13254 gen_lookup_tb(s);
13255 } else {
13256 if (insn & (1 << 4)) {
13257 shift = CPSR_A | CPSR_I | CPSR_F;
13258 } else {
13259 shift = 0;
13261 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
13263 break;
13264 default:
13265 goto undef;
13267 break;
13269 default:
13270 goto undef;
13272 break;
13274 case 12:
13276 /* load/store multiple */
13277 TCGv_i32 loaded_var = NULL;
13278 rn = (insn >> 8) & 0x7;
13279 addr = load_reg(s, rn);
13280 for (i = 0; i < 8; i++) {
13281 if (insn & (1 << i)) {
13282 if (insn & (1 << 11)) {
13283 /* load */
13284 tmp = tcg_temp_new_i32();
13285 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
13286 if (i == rn) {
13287 loaded_var = tmp;
13288 } else {
13289 store_reg(s, i, tmp);
13291 } else {
13292 /* store */
13293 tmp = load_reg(s, i);
13294 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
13295 tcg_temp_free_i32(tmp);
13297 /* advance to the next address */
13298 tcg_gen_addi_i32(addr, addr, 4);
13301 if ((insn & (1 << rn)) == 0) {
13302 /* base reg not in list: base register writeback */
13303 store_reg(s, rn, addr);
13304 } else {
13305 /* base reg in list: if load, complete it now */
13306 if (insn & (1 << 11)) {
13307 store_reg(s, rn, loaded_var);
13309 tcg_temp_free_i32(addr);
13311 break;
13313 case 13:
13314 /* conditional branch or swi */
13315 cond = (insn >> 8) & 0xf;
13316 if (cond == 0xe)
13317 goto undef;
13319 if (cond == 0xf) {
13320 /* swi */
13321 gen_set_pc_im(s, s->pc);
13322 s->svc_imm = extract32(insn, 0, 8);
13323 s->base.is_jmp = DISAS_SWI;
13324 break;
13326 /* generate a conditional jump to next instruction */
13327 arm_skip_unless(s, cond);
13329 /* jump to the offset */
13330 val = (uint32_t)s->pc + 2;
13331 offset = ((int32_t)insn << 24) >> 24;
13332 val += offset << 1;
13333 gen_jmp(s, val);
13334 break;
13336 case 14:
13337 if (insn & (1 << 11)) {
13338 /* thumb_insn_is_16bit() ensures we can't get here for
13339 * a Thumb2 CPU, so this must be a thumb1 split BL/BLX:
13340 * 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF)
13342 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
13343 ARCH(5);
13344 offset = ((insn & 0x7ff) << 1);
13345 tmp = load_reg(s, 14);
13346 tcg_gen_addi_i32(tmp, tmp, offset);
13347 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
13349 tmp2 = tcg_temp_new_i32();
13350 tcg_gen_movi_i32(tmp2, s->pc | 1);
13351 store_reg(s, 14, tmp2);
13352 gen_bx(s, tmp);
13353 break;
13355 /* unconditional branch */
13356 val = (uint32_t)s->pc;
13357 offset = ((int32_t)insn << 21) >> 21;
13358 val += (offset << 1) + 2;
13359 gen_jmp(s, val);
13360 break;
13362 case 15:
13363 /* thumb_insn_is_16bit() ensures we can't get here for
13364 * a Thumb2 CPU, so this must be a thumb1 split BL/BLX.
13366 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
13368 if (insn & (1 << 11)) {
13369 /* 0b1111_1xxx_xxxx_xxxx : BL suffix */
13370 offset = ((insn & 0x7ff) << 1) | 1;
13371 tmp = load_reg(s, 14);
13372 tcg_gen_addi_i32(tmp, tmp, offset);
13374 tmp2 = tcg_temp_new_i32();
13375 tcg_gen_movi_i32(tmp2, s->pc | 1);
13376 store_reg(s, 14, tmp2);
13377 gen_bx(s, tmp);
13378 } else {
13379 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix */
13380 uint32_t uoffset = ((int32_t)insn << 21) >> 9;
13382 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + uoffset);
13384 break;
13386 return;
13387 illegal_op:
13388 undef:
13389 gen_exception_insn(s, 2, EXCP_UDEF, syn_uncategorized(),
13390 default_exception_el(s));
13393 static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
13395 /* Return true if the insn at dc->pc might cross a page boundary.
13396 * (False positives are OK, false negatives are not.)
13397 * We know this is a Thumb insn, and our caller ensures we are
13398 * only called if dc->pc is less than 4 bytes from the page
13399 * boundary, so we cross the page if the first 16 bits indicate
13400 * that this is a 32 bit insn.
13402 uint16_t insn = arm_lduw_code(env, s->pc, s->sctlr_b);
13404 return !thumb_insn_is_16bit(s, insn);
13407 static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
13409 DisasContext *dc = container_of(dcbase, DisasContext, base);
13410 CPUARMState *env = cs->env_ptr;
13411 ARMCPU *cpu = arm_env_get_cpu(env);
13412 uint32_t tb_flags = dc->base.tb->flags;
13413 uint32_t condexec, core_mmu_idx;
13415 dc->isar = &cpu->isar;
13416 dc->pc = dc->base.pc_first;
13417 dc->condjmp = 0;
13419 dc->aarch64 = 0;
13420 /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
13421 * there is no secure EL1, so we route exceptions to EL3.
13423 dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
13424 !arm_el_is_aa64(env, 3);
13425 dc->thumb = FIELD_EX32(tb_flags, TBFLAG_A32, THUMB);
13426 dc->sctlr_b = FIELD_EX32(tb_flags, TBFLAG_A32, SCTLR_B);
13427 dc->be_data = FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
13428 condexec = FIELD_EX32(tb_flags, TBFLAG_A32, CONDEXEC);
13429 dc->condexec_mask = (condexec & 0xf) << 1;
13430 dc->condexec_cond = condexec >> 4;
13431 core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX);
13432 dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
13433 dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
13434 #if !defined(CONFIG_USER_ONLY)
13435 dc->user = (dc->current_el == 0);
13436 #endif
13437 dc->ns = FIELD_EX32(tb_flags, TBFLAG_A32, NS);
13438 dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL);
13439 dc->vfp_enabled = FIELD_EX32(tb_flags, TBFLAG_A32, VFPEN);
13440 dc->vec_len = FIELD_EX32(tb_flags, TBFLAG_A32, VECLEN);
13441 if (arm_feature(env, ARM_FEATURE_XSCALE)) {
13442 dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
13443 dc->vec_stride = 0;
13444 } else {
13445 dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
13446 dc->c15_cpar = 0;
13448 dc->v7m_handler_mode = FIELD_EX32(tb_flags, TBFLAG_A32, HANDLER);
13449 dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
13450 regime_is_secure(env, dc->mmu_idx);
13451 dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_A32, STACKCHECK);
13452 dc->v8m_fpccr_s_wrong = FIELD_EX32(tb_flags, TBFLAG_A32, FPCCR_S_WRONG);
13453 dc->v7m_new_fp_ctxt_needed =
13454 FIELD_EX32(tb_flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED);
13455 dc->v7m_lspact = FIELD_EX32(tb_flags, TBFLAG_A32, LSPACT);
13456 dc->cp_regs = cpu->cp_regs;
13457 dc->features = env->features;
13459 /* Single step state. The code-generation logic here is:
13460 * SS_ACTIVE == 0:
13461 * generate code with no special handling for single-stepping (except
13462 * that anything that can make us go to SS_ACTIVE == 1 must end the TB;
13463 * this happens anyway because those changes are all system register or
13464 * PSTATE writes).
13465 * SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
13466 * emit code for one insn
13467 * emit code to clear PSTATE.SS
13468 * emit code to generate software step exception for completed step
13469 * end TB (as usual for having generated an exception)
13470 * SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
13471 * emit code to generate a software step exception
13472 * end the TB
13474 dc->ss_active = FIELD_EX32(tb_flags, TBFLAG_ANY, SS_ACTIVE);
13475 dc->pstate_ss = FIELD_EX32(tb_flags, TBFLAG_ANY, PSTATE_SS);
13476 dc->is_ldex = false;
13477 dc->ss_same_el = false; /* Can't be true since EL_d must be AArch64 */
13479 dc->page_start = dc->base.pc_first & TARGET_PAGE_MASK;
13481 /* If architectural single step active, limit to 1. */
13482 if (is_singlestepping(dc)) {
13483 dc->base.max_insns = 1;
13486 /* ARM is a fixed-length ISA. Bound the number of insns to execute
13487 to those left on the page. */
13488 if (!dc->thumb) {
13489 int bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
13490 dc->base.max_insns = MIN(dc->base.max_insns, bound);
13493 cpu_F0s = tcg_temp_new_i32();
13494 cpu_F1s = tcg_temp_new_i32();
13495 cpu_F0d = tcg_temp_new_i64();
13496 cpu_F1d = tcg_temp_new_i64();
13497 cpu_V0 = cpu_F0d;
13498 cpu_V1 = cpu_F1d;
13499 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
13500 cpu_M0 = tcg_temp_new_i64();
13503 static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
13505 DisasContext *dc = container_of(dcbase, DisasContext, base);
13507 /* A note on handling of the condexec (IT) bits:
13509 * We want to avoid the overhead of having to write the updated condexec
13510 * bits back to the CPUARMState for every instruction in an IT block. So:
13511 * (1) if the condexec bits are not already zero then we write
13512 * zero back into the CPUARMState now. This avoids complications trying
13513 * to do it at the end of the block. (For example if we don't do this
13514 * it's hard to identify whether we can safely skip writing condexec
13515 * at the end of the TB, which we definitely want to do for the case
13516 * where a TB doesn't do anything with the IT state at all.)
13517 * (2) if we are going to leave the TB then we call gen_set_condexec()
13518 * which will write the correct value into CPUARMState if zero is wrong.
13519 * This is done both for leaving the TB at the end, and for leaving
13520 * it because of an exception we know will happen, which is done in
13521 * gen_exception_insn(). The latter is necessary because we need to
13522 * leave the TB with the PC/IT state just prior to execution of the
13523 * instruction which caused the exception.
13524 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
13525 * then the CPUARMState will be wrong and we need to reset it.
13526 * This is handled in the same way as restoration of the
13527 * PC in these situations; we save the value of the condexec bits
13528 * for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
13529 * then uses this to restore them after an exception.
13531 * Note that there are no instructions which can read the condexec
13532 * bits, and none which can write non-static values to them, so
13533 * we don't need to care about whether CPUARMState is correct in the
13534 * middle of a TB.
13537 /* Reset the conditional execution bits immediately. This avoids
13538 complications trying to do it at the end of the block. */
13539 if (dc->condexec_mask || dc->condexec_cond) {
13540 TCGv_i32 tmp = tcg_temp_new_i32();
13541 tcg_gen_movi_i32(tmp, 0);
13542 store_cpu_field(tmp, condexec_bits);
13546 static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
13548 DisasContext *dc = container_of(dcbase, DisasContext, base);
13550 tcg_gen_insn_start(dc->pc,
13551 (dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
13553 dc->insn_start = tcg_last_op();
13556 static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
13557 const CPUBreakpoint *bp)
13559 DisasContext *dc = container_of(dcbase, DisasContext, base);
13561 if (bp->flags & BP_CPU) {
13562 gen_set_condexec(dc);
13563 gen_set_pc_im(dc, dc->pc);
13564 gen_helper_check_breakpoints(cpu_env);
13565 /* End the TB early; it's likely not going to be executed */
13566 dc->base.is_jmp = DISAS_TOO_MANY;
13567 } else {
13568 gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
13569 /* The address covered by the breakpoint must be
13570 included in [tb->pc, tb->pc + tb->size) in order
13571 to for it to be properly cleared -- thus we
13572 increment the PC here so that the logic setting
13573 tb->size below does the right thing. */
13574 /* TODO: Advance PC by correct instruction length to
13575 * avoid disassembler error messages */
13576 dc->pc += 2;
13577 dc->base.is_jmp = DISAS_NORETURN;
13580 return true;
13583 static bool arm_pre_translate_insn(DisasContext *dc)
13585 #ifdef CONFIG_USER_ONLY
13586 /* Intercept jump to the magic kernel page. */
13587 if (dc->pc >= 0xffff0000) {
13588 /* We always get here via a jump, so know we are not in a
13589 conditional execution block. */
13590 gen_exception_internal(EXCP_KERNEL_TRAP);
13591 dc->base.is_jmp = DISAS_NORETURN;
13592 return true;
13594 #endif
13596 if (dc->ss_active && !dc->pstate_ss) {
13597 /* Singlestep state is Active-pending.
13598 * If we're in this state at the start of a TB then either
13599 * a) we just took an exception to an EL which is being debugged
13600 * and this is the first insn in the exception handler
13601 * b) debug exceptions were masked and we just unmasked them
13602 * without changing EL (eg by clearing PSTATE.D)
13603 * In either case we're going to take a swstep exception in the
13604 * "did not step an insn" case, and so the syndrome ISV and EX
13605 * bits should be zero.
13607 assert(dc->base.num_insns == 1);
13608 gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
13609 default_exception_el(dc));
13610 dc->base.is_jmp = DISAS_NORETURN;
13611 return true;
13614 return false;
13617 static void arm_post_translate_insn(DisasContext *dc)
13619 if (dc->condjmp && !dc->base.is_jmp) {
13620 gen_set_label(dc->condlabel);
13621 dc->condjmp = 0;
13623 dc->base.pc_next = dc->pc;
13624 translator_loop_temp_check(&dc->base);
13627 static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
13629 DisasContext *dc = container_of(dcbase, DisasContext, base);
13630 CPUARMState *env = cpu->env_ptr;
13631 unsigned int insn;
13633 if (arm_pre_translate_insn(dc)) {
13634 return;
13637 insn = arm_ldl_code(env, dc->pc, dc->sctlr_b);
13638 dc->insn = insn;
13639 dc->pc += 4;
13640 disas_arm_insn(dc, insn);
13642 arm_post_translate_insn(dc);
13644 /* ARM is a fixed-length ISA. We performed the cross-page check
13645 in init_disas_context by adjusting max_insns. */
13648 static bool thumb_insn_is_unconditional(DisasContext *s, uint32_t insn)
13650 /* Return true if this Thumb insn is always unconditional,
13651 * even inside an IT block. This is true of only a very few
13652 * instructions: BKPT, HLT, and SG.
13654 * A larger class of instructions are UNPREDICTABLE if used
13655 * inside an IT block; we do not need to detect those here, because
13656 * what we do by default (perform the cc check and update the IT
13657 * bits state machine) is a permitted CONSTRAINED UNPREDICTABLE
13658 * choice for those situations.
13660 * insn is either a 16-bit or a 32-bit instruction; the two are
13661 * distinguishable because for the 16-bit case the top 16 bits
13662 * are zeroes, and that isn't a valid 32-bit encoding.
13664 if ((insn & 0xffffff00) == 0xbe00) {
13665 /* BKPT */
13666 return true;
13669 if ((insn & 0xffffffc0) == 0xba80 && arm_dc_feature(s, ARM_FEATURE_V8) &&
13670 !arm_dc_feature(s, ARM_FEATURE_M)) {
13671 /* HLT: v8A only. This is unconditional even when it is going to
13672 * UNDEF; see the v8A ARM ARM DDI0487B.a H3.3.
13673 * For v7 cores this was a plain old undefined encoding and so
13674 * honours its cc check. (We might be using the encoding as
13675 * a semihosting trap, but we don't change the cc check behaviour
13676 * on that account, because a debugger connected to a real v7A
13677 * core and emulating semihosting traps by catching the UNDEF
13678 * exception would also only see cases where the cc check passed.
13679 * No guest code should be trying to do a HLT semihosting trap
13680 * in an IT block anyway.
13682 return true;
13685 if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_V8) &&
13686 arm_dc_feature(s, ARM_FEATURE_M)) {
13687 /* SG: v8M only */
13688 return true;
13691 return false;
13694 static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
13696 DisasContext *dc = container_of(dcbase, DisasContext, base);
13697 CPUARMState *env = cpu->env_ptr;
13698 uint32_t insn;
13699 bool is_16bit;
13701 if (arm_pre_translate_insn(dc)) {
13702 return;
13705 insn = arm_lduw_code(env, dc->pc, dc->sctlr_b);
13706 is_16bit = thumb_insn_is_16bit(dc, insn);
13707 dc->pc += 2;
13708 if (!is_16bit) {
13709 uint32_t insn2 = arm_lduw_code(env, dc->pc, dc->sctlr_b);
13711 insn = insn << 16 | insn2;
13712 dc->pc += 2;
13714 dc->insn = insn;
13716 if (dc->condexec_mask && !thumb_insn_is_unconditional(dc, insn)) {
13717 uint32_t cond = dc->condexec_cond;
13719 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
13720 arm_skip_unless(dc, cond);
13724 if (is_16bit) {
13725 disas_thumb_insn(dc, insn);
13726 } else {
13727 disas_thumb2_insn(dc, insn);
13730 /* Advance the Thumb condexec condition. */
13731 if (dc->condexec_mask) {
13732 dc->condexec_cond = ((dc->condexec_cond & 0xe) |
13733 ((dc->condexec_mask >> 4) & 1));
13734 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
13735 if (dc->condexec_mask == 0) {
13736 dc->condexec_cond = 0;
13740 arm_post_translate_insn(dc);
13742 /* Thumb is a variable-length ISA. Stop translation when the next insn
13743 * will touch a new page. This ensures that prefetch aborts occur at
13744 * the right place.
13746 * We want to stop the TB if the next insn starts in a new page,
13747 * or if it spans between this page and the next. This means that
13748 * if we're looking at the last halfword in the page we need to
13749 * see if it's a 16-bit Thumb insn (which will fit in this TB)
13750 * or a 32-bit Thumb insn (which won't).
13751 * This is to avoid generating a silly TB with a single 16-bit insn
13752 * in it at the end of this page (which would execute correctly
13753 * but isn't very efficient).
13755 if (dc->base.is_jmp == DISAS_NEXT
13756 && (dc->pc - dc->page_start >= TARGET_PAGE_SIZE
13757 || (dc->pc - dc->page_start >= TARGET_PAGE_SIZE - 3
13758 && insn_crosses_page(env, dc)))) {
13759 dc->base.is_jmp = DISAS_TOO_MANY;
13763 static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
13765 DisasContext *dc = container_of(dcbase, DisasContext, base);
13767 if (tb_cflags(dc->base.tb) & CF_LAST_IO && dc->condjmp) {
13768 /* FIXME: This can theoretically happen with self-modifying code. */
13769 cpu_abort(cpu, "IO on conditional branch instruction");
13772 /* At this stage dc->condjmp will only be set when the skipped
13773 instruction was a conditional branch or trap, and the PC has
13774 already been written. */
13775 gen_set_condexec(dc);
13776 if (dc->base.is_jmp == DISAS_BX_EXCRET) {
13777 /* Exception return branches need some special case code at the
13778 * end of the TB, which is complex enough that it has to
13779 * handle the single-step vs not and the condition-failed
13780 * insn codepath itself.
13782 gen_bx_excret_final_code(dc);
13783 } else if (unlikely(is_singlestepping(dc))) {
13784 /* Unconditional and "condition passed" instruction codepath. */
13785 switch (dc->base.is_jmp) {
13786 case DISAS_SWI:
13787 gen_ss_advance(dc);
13788 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
13789 default_exception_el(dc));
13790 break;
13791 case DISAS_HVC:
13792 gen_ss_advance(dc);
13793 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
13794 break;
13795 case DISAS_SMC:
13796 gen_ss_advance(dc);
13797 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
13798 break;
13799 case DISAS_NEXT:
13800 case DISAS_TOO_MANY:
13801 case DISAS_UPDATE:
13802 gen_set_pc_im(dc, dc->pc);
13803 /* fall through */
13804 default:
13805 /* FIXME: Single stepping a WFI insn will not halt the CPU. */
13806 gen_singlestep_exception(dc);
13807 break;
13808 case DISAS_NORETURN:
13809 break;
13811 } else {
13812 /* While branches must always occur at the end of an IT block,
13813 there are a few other things that can cause us to terminate
13814 the TB in the middle of an IT block:
13815 - Exception generating instructions (bkpt, swi, undefined).
13816 - Page boundaries.
13817 - Hardware watchpoints.
13818 Hardware breakpoints have already been handled and skip this code.
13820 switch(dc->base.is_jmp) {
13821 case DISAS_NEXT:
13822 case DISAS_TOO_MANY:
13823 gen_goto_tb(dc, 1, dc->pc);
13824 break;
13825 case DISAS_JUMP:
13826 gen_goto_ptr();
13827 break;
13828 case DISAS_UPDATE:
13829 gen_set_pc_im(dc, dc->pc);
13830 /* fall through */
13831 default:
13832 /* indicate that the hash table must be used to find the next TB */
13833 tcg_gen_exit_tb(NULL, 0);
13834 break;
13835 case DISAS_NORETURN:
13836 /* nothing more to generate */
13837 break;
13838 case DISAS_WFI:
13840 TCGv_i32 tmp = tcg_const_i32((dc->thumb &&
13841 !(dc->insn & (1U << 31))) ? 2 : 4);
13843 gen_helper_wfi(cpu_env, tmp);
13844 tcg_temp_free_i32(tmp);
13845 /* The helper doesn't necessarily throw an exception, but we
13846 * must go back to the main loop to check for interrupts anyway.
13848 tcg_gen_exit_tb(NULL, 0);
13849 break;
13851 case DISAS_WFE:
13852 gen_helper_wfe(cpu_env);
13853 break;
13854 case DISAS_YIELD:
13855 gen_helper_yield(cpu_env);
13856 break;
13857 case DISAS_SWI:
13858 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
13859 default_exception_el(dc));
13860 break;
13861 case DISAS_HVC:
13862 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
13863 break;
13864 case DISAS_SMC:
13865 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
13866 break;
13870 if (dc->condjmp) {
13871 /* "Condition failed" instruction codepath for the branch/trap insn */
13872 gen_set_label(dc->condlabel);
13873 gen_set_condexec(dc);
13874 if (unlikely(is_singlestepping(dc))) {
13875 gen_set_pc_im(dc, dc->pc);
13876 gen_singlestep_exception(dc);
13877 } else {
13878 gen_goto_tb(dc, 1, dc->pc);
13882 /* Functions above can change dc->pc, so re-align db->pc_next */
13883 dc->base.pc_next = dc->pc;
13886 static void arm_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
13888 DisasContext *dc = container_of(dcbase, DisasContext, base);
13890 qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
13891 log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
13894 static const TranslatorOps arm_translator_ops = {
13895 .init_disas_context = arm_tr_init_disas_context,
13896 .tb_start = arm_tr_tb_start,
13897 .insn_start = arm_tr_insn_start,
13898 .breakpoint_check = arm_tr_breakpoint_check,
13899 .translate_insn = arm_tr_translate_insn,
13900 .tb_stop = arm_tr_tb_stop,
13901 .disas_log = arm_tr_disas_log,
13904 static const TranslatorOps thumb_translator_ops = {
13905 .init_disas_context = arm_tr_init_disas_context,
13906 .tb_start = arm_tr_tb_start,
13907 .insn_start = arm_tr_insn_start,
13908 .breakpoint_check = arm_tr_breakpoint_check,
13909 .translate_insn = thumb_tr_translate_insn,
13910 .tb_stop = arm_tr_tb_stop,
13911 .disas_log = arm_tr_disas_log,
13914 /* generate intermediate code for basic block 'tb'. */
13915 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
13917 DisasContext dc;
13918 const TranslatorOps *ops = &arm_translator_ops;
13920 if (FIELD_EX32(tb->flags, TBFLAG_A32, THUMB)) {
13921 ops = &thumb_translator_ops;
13923 #ifdef TARGET_AARCH64
13924 if (FIELD_EX32(tb->flags, TBFLAG_ANY, AARCH64_STATE)) {
13925 ops = &aarch64_translator_ops;
13927 #endif
13929 translator_loop(ops, &dc.base, cpu, tb, max_insns);
13932 void arm_cpu_dump_state(CPUState *cs, FILE *f, int flags)
13934 ARMCPU *cpu = ARM_CPU(cs);
13935 CPUARMState *env = &cpu->env;
13936 int i;
13938 if (is_a64(env)) {
13939 aarch64_cpu_dump_state(cs, f, flags);
13940 return;
13943 for(i=0;i<16;i++) {
13944 qemu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
13945 if ((i % 4) == 3)
13946 qemu_fprintf(f, "\n");
13947 else
13948 qemu_fprintf(f, " ");
13951 if (arm_feature(env, ARM_FEATURE_M)) {
13952 uint32_t xpsr = xpsr_read(env);
13953 const char *mode;
13954 const char *ns_status = "";
13956 if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
13957 ns_status = env->v7m.secure ? "S " : "NS ";
13960 if (xpsr & XPSR_EXCP) {
13961 mode = "handler";
13962 } else {
13963 if (env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_NPRIV_MASK) {
13964 mode = "unpriv-thread";
13965 } else {
13966 mode = "priv-thread";
13970 qemu_fprintf(f, "XPSR=%08x %c%c%c%c %c %s%s\n",
13971 xpsr,
13972 xpsr & XPSR_N ? 'N' : '-',
13973 xpsr & XPSR_Z ? 'Z' : '-',
13974 xpsr & XPSR_C ? 'C' : '-',
13975 xpsr & XPSR_V ? 'V' : '-',
13976 xpsr & XPSR_T ? 'T' : 'A',
13977 ns_status,
13978 mode);
13979 } else {
13980 uint32_t psr = cpsr_read(env);
13981 const char *ns_status = "";
13983 if (arm_feature(env, ARM_FEATURE_EL3) &&
13984 (psr & CPSR_M) != ARM_CPU_MODE_MON) {
13985 ns_status = env->cp15.scr_el3 & SCR_NS ? "NS " : "S ";
13988 qemu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%s%d\n",
13989 psr,
13990 psr & CPSR_N ? 'N' : '-',
13991 psr & CPSR_Z ? 'Z' : '-',
13992 psr & CPSR_C ? 'C' : '-',
13993 psr & CPSR_V ? 'V' : '-',
13994 psr & CPSR_T ? 'T' : 'A',
13995 ns_status,
13996 aarch32_mode_name(psr), (psr & 0x10) ? 32 : 26);
13999 if (flags & CPU_DUMP_FPU) {
14000 int numvfpregs = 0;
14001 if (arm_feature(env, ARM_FEATURE_VFP)) {
14002 numvfpregs += 16;
14004 if (arm_feature(env, ARM_FEATURE_VFP3)) {
14005 numvfpregs += 16;
14007 for (i = 0; i < numvfpregs; i++) {
14008 uint64_t v = *aa32_vfp_dreg(env, i);
14009 qemu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
14010 i * 2, (uint32_t)v,
14011 i * 2 + 1, (uint32_t)(v >> 32),
14012 i, v);
14014 qemu_fprintf(f, "FPSCR: %08x\n", vfp_get_fpscr(env));
14018 void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
14019 target_ulong *data)
14021 if (is_a64(env)) {
14022 env->pc = data[0];
14023 env->condexec_bits = 0;
14024 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
14025 } else {
14026 env->regs[15] = data[0];
14027 env->condexec_bits = data[1];
14028 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;