target/arm: Decode FP instructions for M profile
[qemu/ar7.git] / target / arm / translate.c
blob0747f7847a9a6a62f70c591ff106c0b3a36a3794
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 tcg_gen_abs_i32(TCGv_i32 dest, TCGv_i32 src)
609 TCGv_i32 c0 = tcg_const_i32(0);
610 TCGv_i32 tmp = tcg_temp_new_i32();
611 tcg_gen_neg_i32(tmp, src);
612 tcg_gen_movcond_i32(TCG_COND_GT, dest, src, c0, src, tmp);
613 tcg_temp_free_i32(c0);
614 tcg_temp_free_i32(tmp);
617 static void shifter_out_im(TCGv_i32 var, int shift)
619 if (shift == 0) {
620 tcg_gen_andi_i32(cpu_CF, var, 1);
621 } else {
622 tcg_gen_shri_i32(cpu_CF, var, shift);
623 if (shift != 31) {
624 tcg_gen_andi_i32(cpu_CF, cpu_CF, 1);
629 /* Shift by immediate. Includes special handling for shift == 0. */
630 static inline void gen_arm_shift_im(TCGv_i32 var, int shiftop,
631 int shift, int flags)
633 switch (shiftop) {
634 case 0: /* LSL */
635 if (shift != 0) {
636 if (flags)
637 shifter_out_im(var, 32 - shift);
638 tcg_gen_shli_i32(var, var, shift);
640 break;
641 case 1: /* LSR */
642 if (shift == 0) {
643 if (flags) {
644 tcg_gen_shri_i32(cpu_CF, var, 31);
646 tcg_gen_movi_i32(var, 0);
647 } else {
648 if (flags)
649 shifter_out_im(var, shift - 1);
650 tcg_gen_shri_i32(var, var, shift);
652 break;
653 case 2: /* ASR */
654 if (shift == 0)
655 shift = 32;
656 if (flags)
657 shifter_out_im(var, shift - 1);
658 if (shift == 32)
659 shift = 31;
660 tcg_gen_sari_i32(var, var, shift);
661 break;
662 case 3: /* ROR/RRX */
663 if (shift != 0) {
664 if (flags)
665 shifter_out_im(var, shift - 1);
666 tcg_gen_rotri_i32(var, var, shift); break;
667 } else {
668 TCGv_i32 tmp = tcg_temp_new_i32();
669 tcg_gen_shli_i32(tmp, cpu_CF, 31);
670 if (flags)
671 shifter_out_im(var, 0);
672 tcg_gen_shri_i32(var, var, 1);
673 tcg_gen_or_i32(var, var, tmp);
674 tcg_temp_free_i32(tmp);
679 static inline void gen_arm_shift_reg(TCGv_i32 var, int shiftop,
680 TCGv_i32 shift, int flags)
682 if (flags) {
683 switch (shiftop) {
684 case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break;
685 case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break;
686 case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break;
687 case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break;
689 } else {
690 switch (shiftop) {
691 case 0:
692 gen_shl(var, var, shift);
693 break;
694 case 1:
695 gen_shr(var, var, shift);
696 break;
697 case 2:
698 gen_sar(var, var, shift);
699 break;
700 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
701 tcg_gen_rotr_i32(var, var, shift); break;
704 tcg_temp_free_i32(shift);
707 #define PAS_OP(pfx) \
708 switch (op2) { \
709 case 0: gen_pas_helper(glue(pfx,add16)); break; \
710 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
711 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
712 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
713 case 4: gen_pas_helper(glue(pfx,add8)); break; \
714 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
716 static void gen_arm_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
718 TCGv_ptr tmp;
720 switch (op1) {
721 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
722 case 1:
723 tmp = tcg_temp_new_ptr();
724 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
725 PAS_OP(s)
726 tcg_temp_free_ptr(tmp);
727 break;
728 case 5:
729 tmp = tcg_temp_new_ptr();
730 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
731 PAS_OP(u)
732 tcg_temp_free_ptr(tmp);
733 break;
734 #undef gen_pas_helper
735 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
736 case 2:
737 PAS_OP(q);
738 break;
739 case 3:
740 PAS_OP(sh);
741 break;
742 case 6:
743 PAS_OP(uq);
744 break;
745 case 7:
746 PAS_OP(uh);
747 break;
748 #undef gen_pas_helper
751 #undef PAS_OP
753 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
754 #define PAS_OP(pfx) \
755 switch (op1) { \
756 case 0: gen_pas_helper(glue(pfx,add8)); break; \
757 case 1: gen_pas_helper(glue(pfx,add16)); break; \
758 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
759 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
760 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
761 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
763 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
765 TCGv_ptr tmp;
767 switch (op2) {
768 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
769 case 0:
770 tmp = tcg_temp_new_ptr();
771 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
772 PAS_OP(s)
773 tcg_temp_free_ptr(tmp);
774 break;
775 case 4:
776 tmp = tcg_temp_new_ptr();
777 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
778 PAS_OP(u)
779 tcg_temp_free_ptr(tmp);
780 break;
781 #undef gen_pas_helper
782 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
783 case 1:
784 PAS_OP(q);
785 break;
786 case 2:
787 PAS_OP(sh);
788 break;
789 case 5:
790 PAS_OP(uq);
791 break;
792 case 6:
793 PAS_OP(uh);
794 break;
795 #undef gen_pas_helper
798 #undef PAS_OP
801 * Generate a conditional based on ARM condition code cc.
802 * This is common between ARM and Aarch64 targets.
804 void arm_test_cc(DisasCompare *cmp, int cc)
806 TCGv_i32 value;
807 TCGCond cond;
808 bool global = true;
810 switch (cc) {
811 case 0: /* eq: Z */
812 case 1: /* ne: !Z */
813 cond = TCG_COND_EQ;
814 value = cpu_ZF;
815 break;
817 case 2: /* cs: C */
818 case 3: /* cc: !C */
819 cond = TCG_COND_NE;
820 value = cpu_CF;
821 break;
823 case 4: /* mi: N */
824 case 5: /* pl: !N */
825 cond = TCG_COND_LT;
826 value = cpu_NF;
827 break;
829 case 6: /* vs: V */
830 case 7: /* vc: !V */
831 cond = TCG_COND_LT;
832 value = cpu_VF;
833 break;
835 case 8: /* hi: C && !Z */
836 case 9: /* ls: !C || Z -> !(C && !Z) */
837 cond = TCG_COND_NE;
838 value = tcg_temp_new_i32();
839 global = false;
840 /* CF is 1 for C, so -CF is an all-bits-set mask for C;
841 ZF is non-zero for !Z; so AND the two subexpressions. */
842 tcg_gen_neg_i32(value, cpu_CF);
843 tcg_gen_and_i32(value, value, cpu_ZF);
844 break;
846 case 10: /* ge: N == V -> N ^ V == 0 */
847 case 11: /* lt: N != V -> N ^ V != 0 */
848 /* Since we're only interested in the sign bit, == 0 is >= 0. */
849 cond = TCG_COND_GE;
850 value = tcg_temp_new_i32();
851 global = false;
852 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
853 break;
855 case 12: /* gt: !Z && N == V */
856 case 13: /* le: Z || N != V */
857 cond = TCG_COND_NE;
858 value = tcg_temp_new_i32();
859 global = false;
860 /* (N == V) is equal to the sign bit of ~(NF ^ VF). Propagate
861 * the sign bit then AND with ZF to yield the result. */
862 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
863 tcg_gen_sari_i32(value, value, 31);
864 tcg_gen_andc_i32(value, cpu_ZF, value);
865 break;
867 case 14: /* always */
868 case 15: /* always */
869 /* Use the ALWAYS condition, which will fold early.
870 * It doesn't matter what we use for the value. */
871 cond = TCG_COND_ALWAYS;
872 value = cpu_ZF;
873 goto no_invert;
875 default:
876 fprintf(stderr, "Bad condition code 0x%x\n", cc);
877 abort();
880 if (cc & 1) {
881 cond = tcg_invert_cond(cond);
884 no_invert:
885 cmp->cond = cond;
886 cmp->value = value;
887 cmp->value_global = global;
890 void arm_free_cc(DisasCompare *cmp)
892 if (!cmp->value_global) {
893 tcg_temp_free_i32(cmp->value);
897 void arm_jump_cc(DisasCompare *cmp, TCGLabel *label)
899 tcg_gen_brcondi_i32(cmp->cond, cmp->value, 0, label);
902 void arm_gen_test_cc(int cc, TCGLabel *label)
904 DisasCompare cmp;
905 arm_test_cc(&cmp, cc);
906 arm_jump_cc(&cmp, label);
907 arm_free_cc(&cmp);
910 static const uint8_t table_logic_cc[16] = {
911 1, /* and */
912 1, /* xor */
913 0, /* sub */
914 0, /* rsb */
915 0, /* add */
916 0, /* adc */
917 0, /* sbc */
918 0, /* rsc */
919 1, /* andl */
920 1, /* xorl */
921 0, /* cmp */
922 0, /* cmn */
923 1, /* orr */
924 1, /* mov */
925 1, /* bic */
926 1, /* mvn */
929 static inline void gen_set_condexec(DisasContext *s)
931 if (s->condexec_mask) {
932 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
933 TCGv_i32 tmp = tcg_temp_new_i32();
934 tcg_gen_movi_i32(tmp, val);
935 store_cpu_field(tmp, condexec_bits);
939 static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
941 tcg_gen_movi_i32(cpu_R[15], val);
944 /* Set PC and Thumb state from an immediate address. */
945 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
947 TCGv_i32 tmp;
949 s->base.is_jmp = DISAS_JUMP;
950 if (s->thumb != (addr & 1)) {
951 tmp = tcg_temp_new_i32();
952 tcg_gen_movi_i32(tmp, addr & 1);
953 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, thumb));
954 tcg_temp_free_i32(tmp);
956 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
959 /* Set PC and Thumb state from var. var is marked as dead. */
960 static inline void gen_bx(DisasContext *s, TCGv_i32 var)
962 s->base.is_jmp = DISAS_JUMP;
963 tcg_gen_andi_i32(cpu_R[15], var, ~1);
964 tcg_gen_andi_i32(var, var, 1);
965 store_cpu_field(var, thumb);
968 /* Set PC and Thumb state from var. var is marked as dead.
969 * For M-profile CPUs, include logic to detect exception-return
970 * branches and handle them. This is needed for Thumb POP/LDM to PC, LDR to PC,
971 * and BX reg, and no others, and happens only for code in Handler mode.
973 static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var)
975 /* Generate the same code here as for a simple bx, but flag via
976 * s->base.is_jmp that we need to do the rest of the work later.
978 gen_bx(s, var);
979 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY) ||
980 (s->v7m_handler_mode && arm_dc_feature(s, ARM_FEATURE_M))) {
981 s->base.is_jmp = DISAS_BX_EXCRET;
985 static inline void gen_bx_excret_final_code(DisasContext *s)
987 /* Generate the code to finish possible exception return and end the TB */
988 TCGLabel *excret_label = gen_new_label();
989 uint32_t min_magic;
991 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY)) {
992 /* Covers FNC_RETURN and EXC_RETURN magic */
993 min_magic = FNC_RETURN_MIN_MAGIC;
994 } else {
995 /* EXC_RETURN magic only */
996 min_magic = EXC_RETURN_MIN_MAGIC;
999 /* Is the new PC value in the magic range indicating exception return? */
1000 tcg_gen_brcondi_i32(TCG_COND_GEU, cpu_R[15], min_magic, excret_label);
1001 /* No: end the TB as we would for a DISAS_JMP */
1002 if (is_singlestepping(s)) {
1003 gen_singlestep_exception(s);
1004 } else {
1005 tcg_gen_exit_tb(NULL, 0);
1007 gen_set_label(excret_label);
1008 /* Yes: this is an exception return.
1009 * At this point in runtime env->regs[15] and env->thumb will hold
1010 * the exception-return magic number, which do_v7m_exception_exit()
1011 * will read. Nothing else will be able to see those values because
1012 * the cpu-exec main loop guarantees that we will always go straight
1013 * from raising the exception to the exception-handling code.
1015 * gen_ss_advance(s) does nothing on M profile currently but
1016 * calling it is conceptually the right thing as we have executed
1017 * this instruction (compare SWI, HVC, SMC handling).
1019 gen_ss_advance(s);
1020 gen_exception_internal(EXCP_EXCEPTION_EXIT);
1023 static inline void gen_bxns(DisasContext *s, int rm)
1025 TCGv_i32 var = load_reg(s, rm);
1027 /* The bxns helper may raise an EXCEPTION_EXIT exception, so in theory
1028 * we need to sync state before calling it, but:
1029 * - we don't need to do gen_set_pc_im() because the bxns helper will
1030 * always set the PC itself
1031 * - we don't need to do gen_set_condexec() because BXNS is UNPREDICTABLE
1032 * unless it's outside an IT block or the last insn in an IT block,
1033 * so we know that condexec == 0 (already set at the top of the TB)
1034 * is correct in the non-UNPREDICTABLE cases, and we can choose
1035 * "zeroes the IT bits" as our UNPREDICTABLE behaviour otherwise.
1037 gen_helper_v7m_bxns(cpu_env, var);
1038 tcg_temp_free_i32(var);
1039 s->base.is_jmp = DISAS_EXIT;
1042 static inline void gen_blxns(DisasContext *s, int rm)
1044 TCGv_i32 var = load_reg(s, rm);
1046 /* We don't need to sync condexec state, for the same reason as bxns.
1047 * We do however need to set the PC, because the blxns helper reads it.
1048 * The blxns helper may throw an exception.
1050 gen_set_pc_im(s, s->pc);
1051 gen_helper_v7m_blxns(cpu_env, var);
1052 tcg_temp_free_i32(var);
1053 s->base.is_jmp = DISAS_EXIT;
1056 /* Variant of store_reg which uses branch&exchange logic when storing
1057 to r15 in ARM architecture v7 and above. The source must be a temporary
1058 and will be marked as dead. */
1059 static inline void store_reg_bx(DisasContext *s, int reg, TCGv_i32 var)
1061 if (reg == 15 && ENABLE_ARCH_7) {
1062 gen_bx(s, var);
1063 } else {
1064 store_reg(s, reg, var);
1068 /* Variant of store_reg which uses branch&exchange logic when storing
1069 * to r15 in ARM architecture v5T and above. This is used for storing
1070 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
1071 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
1072 static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
1074 if (reg == 15 && ENABLE_ARCH_5) {
1075 gen_bx_excret(s, var);
1076 } else {
1077 store_reg(s, reg, var);
1081 #ifdef CONFIG_USER_ONLY
1082 #define IS_USER_ONLY 1
1083 #else
1084 #define IS_USER_ONLY 0
1085 #endif
1087 /* Abstractions of "generate code to do a guest load/store for
1088 * AArch32", where a vaddr is always 32 bits (and is zero
1089 * extended if we're a 64 bit core) and data is also
1090 * 32 bits unless specifically doing a 64 bit access.
1091 * These functions work like tcg_gen_qemu_{ld,st}* except
1092 * that the address argument is TCGv_i32 rather than TCGv.
1095 static inline TCGv gen_aa32_addr(DisasContext *s, TCGv_i32 a32, TCGMemOp op)
1097 TCGv addr = tcg_temp_new();
1098 tcg_gen_extu_i32_tl(addr, a32);
1100 /* Not needed for user-mode BE32, where we use MO_BE instead. */
1101 if (!IS_USER_ONLY && s->sctlr_b && (op & MO_SIZE) < MO_32) {
1102 tcg_gen_xori_tl(addr, addr, 4 - (1 << (op & MO_SIZE)));
1104 return addr;
1107 static void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
1108 int index, TCGMemOp opc)
1110 TCGv addr;
1112 if (arm_dc_feature(s, ARM_FEATURE_M) &&
1113 !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
1114 opc |= MO_ALIGN;
1117 addr = gen_aa32_addr(s, a32, opc);
1118 tcg_gen_qemu_ld_i32(val, addr, index, opc);
1119 tcg_temp_free(addr);
1122 static void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
1123 int index, TCGMemOp opc)
1125 TCGv addr;
1127 if (arm_dc_feature(s, ARM_FEATURE_M) &&
1128 !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
1129 opc |= MO_ALIGN;
1132 addr = gen_aa32_addr(s, a32, opc);
1133 tcg_gen_qemu_st_i32(val, addr, index, opc);
1134 tcg_temp_free(addr);
1137 #define DO_GEN_LD(SUFF, OPC) \
1138 static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
1139 TCGv_i32 a32, int index) \
1141 gen_aa32_ld_i32(s, val, a32, index, OPC | s->be_data); \
1143 static inline void gen_aa32_ld##SUFF##_iss(DisasContext *s, \
1144 TCGv_i32 val, \
1145 TCGv_i32 a32, int index, \
1146 ISSInfo issinfo) \
1148 gen_aa32_ld##SUFF(s, val, a32, index); \
1149 disas_set_da_iss(s, OPC, issinfo); \
1152 #define DO_GEN_ST(SUFF, OPC) \
1153 static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
1154 TCGv_i32 a32, int index) \
1156 gen_aa32_st_i32(s, val, a32, index, OPC | s->be_data); \
1158 static inline void gen_aa32_st##SUFF##_iss(DisasContext *s, \
1159 TCGv_i32 val, \
1160 TCGv_i32 a32, int index, \
1161 ISSInfo issinfo) \
1163 gen_aa32_st##SUFF(s, val, a32, index); \
1164 disas_set_da_iss(s, OPC, issinfo | ISSIsWrite); \
1167 static inline void gen_aa32_frob64(DisasContext *s, TCGv_i64 val)
1169 /* Not needed for user-mode BE32, where we use MO_BE instead. */
1170 if (!IS_USER_ONLY && s->sctlr_b) {
1171 tcg_gen_rotri_i64(val, val, 32);
1175 static void gen_aa32_ld_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
1176 int index, TCGMemOp opc)
1178 TCGv addr = gen_aa32_addr(s, a32, opc);
1179 tcg_gen_qemu_ld_i64(val, addr, index, opc);
1180 gen_aa32_frob64(s, val);
1181 tcg_temp_free(addr);
1184 static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
1185 TCGv_i32 a32, int index)
1187 gen_aa32_ld_i64(s, val, a32, index, MO_Q | s->be_data);
1190 static void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
1191 int index, TCGMemOp opc)
1193 TCGv addr = gen_aa32_addr(s, a32, opc);
1195 /* Not needed for user-mode BE32, where we use MO_BE instead. */
1196 if (!IS_USER_ONLY && s->sctlr_b) {
1197 TCGv_i64 tmp = tcg_temp_new_i64();
1198 tcg_gen_rotri_i64(tmp, val, 32);
1199 tcg_gen_qemu_st_i64(tmp, addr, index, opc);
1200 tcg_temp_free_i64(tmp);
1201 } else {
1202 tcg_gen_qemu_st_i64(val, addr, index, opc);
1204 tcg_temp_free(addr);
1207 static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
1208 TCGv_i32 a32, int index)
1210 gen_aa32_st_i64(s, val, a32, index, MO_Q | s->be_data);
1213 DO_GEN_LD(8s, MO_SB)
1214 DO_GEN_LD(8u, MO_UB)
1215 DO_GEN_LD(16s, MO_SW)
1216 DO_GEN_LD(16u, MO_UW)
1217 DO_GEN_LD(32u, MO_UL)
1218 DO_GEN_ST(8, MO_UB)
1219 DO_GEN_ST(16, MO_UW)
1220 DO_GEN_ST(32, MO_UL)
1222 static inline void gen_hvc(DisasContext *s, int imm16)
1224 /* The pre HVC helper handles cases when HVC gets trapped
1225 * as an undefined insn by runtime configuration (ie before
1226 * the insn really executes).
1228 gen_set_pc_im(s, s->pc - 4);
1229 gen_helper_pre_hvc(cpu_env);
1230 /* Otherwise we will treat this as a real exception which
1231 * happens after execution of the insn. (The distinction matters
1232 * for the PC value reported to the exception handler and also
1233 * for single stepping.)
1235 s->svc_imm = imm16;
1236 gen_set_pc_im(s, s->pc);
1237 s->base.is_jmp = DISAS_HVC;
1240 static inline void gen_smc(DisasContext *s)
1242 /* As with HVC, we may take an exception either before or after
1243 * the insn executes.
1245 TCGv_i32 tmp;
1247 gen_set_pc_im(s, s->pc - 4);
1248 tmp = tcg_const_i32(syn_aa32_smc());
1249 gen_helper_pre_smc(cpu_env, tmp);
1250 tcg_temp_free_i32(tmp);
1251 gen_set_pc_im(s, s->pc);
1252 s->base.is_jmp = DISAS_SMC;
1255 static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
1257 gen_set_condexec(s);
1258 gen_set_pc_im(s, s->pc - offset);
1259 gen_exception_internal(excp);
1260 s->base.is_jmp = DISAS_NORETURN;
1263 static void gen_exception_insn(DisasContext *s, int offset, int excp,
1264 int syn, uint32_t target_el)
1266 gen_set_condexec(s);
1267 gen_set_pc_im(s, s->pc - offset);
1268 gen_exception(excp, syn, target_el);
1269 s->base.is_jmp = DISAS_NORETURN;
1272 static void gen_exception_bkpt_insn(DisasContext *s, int offset, uint32_t syn)
1274 TCGv_i32 tcg_syn;
1276 gen_set_condexec(s);
1277 gen_set_pc_im(s, s->pc - offset);
1278 tcg_syn = tcg_const_i32(syn);
1279 gen_helper_exception_bkpt_insn(cpu_env, tcg_syn);
1280 tcg_temp_free_i32(tcg_syn);
1281 s->base.is_jmp = DISAS_NORETURN;
1284 /* Force a TB lookup after an instruction that changes the CPU state. */
1285 static inline void gen_lookup_tb(DisasContext *s)
1287 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
1288 s->base.is_jmp = DISAS_EXIT;
1291 static inline void gen_hlt(DisasContext *s, int imm)
1293 /* HLT. This has two purposes.
1294 * Architecturally, it is an external halting debug instruction.
1295 * Since QEMU doesn't implement external debug, we treat this as
1296 * it is required for halting debug disabled: it will UNDEF.
1297 * Secondly, "HLT 0x3C" is a T32 semihosting trap instruction,
1298 * and "HLT 0xF000" is an A32 semihosting syscall. These traps
1299 * must trigger semihosting even for ARMv7 and earlier, where
1300 * HLT was an undefined encoding.
1301 * In system mode, we don't allow userspace access to
1302 * semihosting, to provide some semblance of security
1303 * (and for consistency with our 32-bit semihosting).
1305 if (semihosting_enabled() &&
1306 #ifndef CONFIG_USER_ONLY
1307 s->current_el != 0 &&
1308 #endif
1309 (imm == (s->thumb ? 0x3c : 0xf000))) {
1310 gen_exception_internal_insn(s, 0, EXCP_SEMIHOST);
1311 return;
1314 gen_exception_insn(s, s->thumb ? 2 : 4, EXCP_UDEF, syn_uncategorized(),
1315 default_exception_el(s));
1318 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
1319 TCGv_i32 var)
1321 int val, rm, shift, shiftop;
1322 TCGv_i32 offset;
1324 if (!(insn & (1 << 25))) {
1325 /* immediate */
1326 val = insn & 0xfff;
1327 if (!(insn & (1 << 23)))
1328 val = -val;
1329 if (val != 0)
1330 tcg_gen_addi_i32(var, var, val);
1331 } else {
1332 /* shift/register */
1333 rm = (insn) & 0xf;
1334 shift = (insn >> 7) & 0x1f;
1335 shiftop = (insn >> 5) & 3;
1336 offset = load_reg(s, rm);
1337 gen_arm_shift_im(offset, shiftop, shift, 0);
1338 if (!(insn & (1 << 23)))
1339 tcg_gen_sub_i32(var, var, offset);
1340 else
1341 tcg_gen_add_i32(var, var, offset);
1342 tcg_temp_free_i32(offset);
1346 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
1347 int extra, TCGv_i32 var)
1349 int val, rm;
1350 TCGv_i32 offset;
1352 if (insn & (1 << 22)) {
1353 /* immediate */
1354 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
1355 if (!(insn & (1 << 23)))
1356 val = -val;
1357 val += extra;
1358 if (val != 0)
1359 tcg_gen_addi_i32(var, var, val);
1360 } else {
1361 /* register */
1362 if (extra)
1363 tcg_gen_addi_i32(var, var, extra);
1364 rm = (insn) & 0xf;
1365 offset = load_reg(s, rm);
1366 if (!(insn & (1 << 23)))
1367 tcg_gen_sub_i32(var, var, offset);
1368 else
1369 tcg_gen_add_i32(var, var, offset);
1370 tcg_temp_free_i32(offset);
1374 static TCGv_ptr get_fpstatus_ptr(int neon)
1376 TCGv_ptr statusptr = tcg_temp_new_ptr();
1377 int offset;
1378 if (neon) {
1379 offset = offsetof(CPUARMState, vfp.standard_fp_status);
1380 } else {
1381 offset = offsetof(CPUARMState, vfp.fp_status);
1383 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
1384 return statusptr;
1387 #define VFP_OP2(name) \
1388 static inline void gen_vfp_##name(int dp) \
1390 TCGv_ptr fpst = get_fpstatus_ptr(0); \
1391 if (dp) { \
1392 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, fpst); \
1393 } else { \
1394 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, fpst); \
1396 tcg_temp_free_ptr(fpst); \
1399 VFP_OP2(add)
1400 VFP_OP2(sub)
1401 VFP_OP2(mul)
1402 VFP_OP2(div)
1404 #undef VFP_OP2
1406 static inline void gen_vfp_F1_mul(int dp)
1408 /* Like gen_vfp_mul() but put result in F1 */
1409 TCGv_ptr fpst = get_fpstatus_ptr(0);
1410 if (dp) {
1411 gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, fpst);
1412 } else {
1413 gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, fpst);
1415 tcg_temp_free_ptr(fpst);
1418 static inline void gen_vfp_F1_neg(int dp)
1420 /* Like gen_vfp_neg() but put result in F1 */
1421 if (dp) {
1422 gen_helper_vfp_negd(cpu_F1d, cpu_F0d);
1423 } else {
1424 gen_helper_vfp_negs(cpu_F1s, cpu_F0s);
1428 static inline void gen_vfp_abs(int dp)
1430 if (dp)
1431 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1432 else
1433 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1436 static inline void gen_vfp_neg(int dp)
1438 if (dp)
1439 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1440 else
1441 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1444 static inline void gen_vfp_sqrt(int dp)
1446 if (dp)
1447 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1448 else
1449 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1452 static inline void gen_vfp_cmp(int dp)
1454 if (dp)
1455 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1456 else
1457 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1460 static inline void gen_vfp_cmpe(int dp)
1462 if (dp)
1463 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1464 else
1465 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1468 static inline void gen_vfp_F1_ld0(int dp)
1470 if (dp)
1471 tcg_gen_movi_i64(cpu_F1d, 0);
1472 else
1473 tcg_gen_movi_i32(cpu_F1s, 0);
1476 #define VFP_GEN_ITOF(name) \
1477 static inline void gen_vfp_##name(int dp, int neon) \
1479 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1480 if (dp) { \
1481 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
1482 } else { \
1483 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1485 tcg_temp_free_ptr(statusptr); \
1488 VFP_GEN_ITOF(uito)
1489 VFP_GEN_ITOF(sito)
1490 #undef VFP_GEN_ITOF
1492 #define VFP_GEN_FTOI(name) \
1493 static inline void gen_vfp_##name(int dp, int neon) \
1495 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1496 if (dp) { \
1497 gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
1498 } else { \
1499 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1501 tcg_temp_free_ptr(statusptr); \
1504 VFP_GEN_FTOI(toui)
1505 VFP_GEN_FTOI(touiz)
1506 VFP_GEN_FTOI(tosi)
1507 VFP_GEN_FTOI(tosiz)
1508 #undef VFP_GEN_FTOI
1510 #define VFP_GEN_FIX(name, round) \
1511 static inline void gen_vfp_##name(int dp, int shift, int neon) \
1513 TCGv_i32 tmp_shift = tcg_const_i32(shift); \
1514 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1515 if (dp) { \
1516 gen_helper_vfp_##name##d##round(cpu_F0d, cpu_F0d, tmp_shift, \
1517 statusptr); \
1518 } else { \
1519 gen_helper_vfp_##name##s##round(cpu_F0s, cpu_F0s, tmp_shift, \
1520 statusptr); \
1522 tcg_temp_free_i32(tmp_shift); \
1523 tcg_temp_free_ptr(statusptr); \
1525 VFP_GEN_FIX(tosh, _round_to_zero)
1526 VFP_GEN_FIX(tosl, _round_to_zero)
1527 VFP_GEN_FIX(touh, _round_to_zero)
1528 VFP_GEN_FIX(toul, _round_to_zero)
1529 VFP_GEN_FIX(shto, )
1530 VFP_GEN_FIX(slto, )
1531 VFP_GEN_FIX(uhto, )
1532 VFP_GEN_FIX(ulto, )
1533 #undef VFP_GEN_FIX
1535 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr)
1537 if (dp) {
1538 gen_aa32_ld64(s, cpu_F0d, addr, get_mem_index(s));
1539 } else {
1540 gen_aa32_ld32u(s, cpu_F0s, addr, get_mem_index(s));
1544 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
1546 if (dp) {
1547 gen_aa32_st64(s, cpu_F0d, addr, get_mem_index(s));
1548 } else {
1549 gen_aa32_st32(s, cpu_F0s, addr, get_mem_index(s));
1553 static inline long vfp_reg_offset(bool dp, unsigned reg)
1555 if (dp) {
1556 return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]);
1557 } else {
1558 long ofs = offsetof(CPUARMState, vfp.zregs[reg >> 2].d[(reg >> 1) & 1]);
1559 if (reg & 1) {
1560 ofs += offsetof(CPU_DoubleU, l.upper);
1561 } else {
1562 ofs += offsetof(CPU_DoubleU, l.lower);
1564 return ofs;
1568 /* Return the offset of a 32-bit piece of a NEON register.
1569 zero is the least significant end of the register. */
1570 static inline long
1571 neon_reg_offset (int reg, int n)
1573 int sreg;
1574 sreg = reg * 2 + n;
1575 return vfp_reg_offset(0, sreg);
1578 /* Return the offset of a 2**SIZE piece of a NEON register, at index ELE,
1579 * where 0 is the least significant end of the register.
1581 static inline long
1582 neon_element_offset(int reg, int element, TCGMemOp size)
1584 int element_size = 1 << size;
1585 int ofs = element * element_size;
1586 #ifdef HOST_WORDS_BIGENDIAN
1587 /* Calculate the offset assuming fully little-endian,
1588 * then XOR to account for the order of the 8-byte units.
1590 if (element_size < 8) {
1591 ofs ^= 8 - element_size;
1593 #endif
1594 return neon_reg_offset(reg, 0) + ofs;
1597 static TCGv_i32 neon_load_reg(int reg, int pass)
1599 TCGv_i32 tmp = tcg_temp_new_i32();
1600 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1601 return tmp;
1604 static void neon_load_element(TCGv_i32 var, int reg, int ele, TCGMemOp mop)
1606 long offset = neon_element_offset(reg, ele, mop & MO_SIZE);
1608 switch (mop) {
1609 case MO_UB:
1610 tcg_gen_ld8u_i32(var, cpu_env, offset);
1611 break;
1612 case MO_UW:
1613 tcg_gen_ld16u_i32(var, cpu_env, offset);
1614 break;
1615 case MO_UL:
1616 tcg_gen_ld_i32(var, cpu_env, offset);
1617 break;
1618 default:
1619 g_assert_not_reached();
1623 static void neon_load_element64(TCGv_i64 var, int reg, int ele, TCGMemOp mop)
1625 long offset = neon_element_offset(reg, ele, mop & MO_SIZE);
1627 switch (mop) {
1628 case MO_UB:
1629 tcg_gen_ld8u_i64(var, cpu_env, offset);
1630 break;
1631 case MO_UW:
1632 tcg_gen_ld16u_i64(var, cpu_env, offset);
1633 break;
1634 case MO_UL:
1635 tcg_gen_ld32u_i64(var, cpu_env, offset);
1636 break;
1637 case MO_Q:
1638 tcg_gen_ld_i64(var, cpu_env, offset);
1639 break;
1640 default:
1641 g_assert_not_reached();
1645 static void neon_store_reg(int reg, int pass, TCGv_i32 var)
1647 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1648 tcg_temp_free_i32(var);
1651 static void neon_store_element(int reg, int ele, TCGMemOp size, TCGv_i32 var)
1653 long offset = neon_element_offset(reg, ele, size);
1655 switch (size) {
1656 case MO_8:
1657 tcg_gen_st8_i32(var, cpu_env, offset);
1658 break;
1659 case MO_16:
1660 tcg_gen_st16_i32(var, cpu_env, offset);
1661 break;
1662 case MO_32:
1663 tcg_gen_st_i32(var, cpu_env, offset);
1664 break;
1665 default:
1666 g_assert_not_reached();
1670 static void neon_store_element64(int reg, int ele, TCGMemOp size, TCGv_i64 var)
1672 long offset = neon_element_offset(reg, ele, size);
1674 switch (size) {
1675 case MO_8:
1676 tcg_gen_st8_i64(var, cpu_env, offset);
1677 break;
1678 case MO_16:
1679 tcg_gen_st16_i64(var, cpu_env, offset);
1680 break;
1681 case MO_32:
1682 tcg_gen_st32_i64(var, cpu_env, offset);
1683 break;
1684 case MO_64:
1685 tcg_gen_st_i64(var, cpu_env, offset);
1686 break;
1687 default:
1688 g_assert_not_reached();
1692 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1694 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1697 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1699 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1702 static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
1704 TCGv_ptr ret = tcg_temp_new_ptr();
1705 tcg_gen_addi_ptr(ret, cpu_env, vfp_reg_offset(dp, reg));
1706 return ret;
1709 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1710 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1711 #define tcg_gen_st_f32 tcg_gen_st_i32
1712 #define tcg_gen_st_f64 tcg_gen_st_i64
1714 static inline void gen_mov_F0_vreg(int dp, int reg)
1716 if (dp)
1717 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1718 else
1719 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1722 static inline void gen_mov_F1_vreg(int dp, int reg)
1724 if (dp)
1725 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1726 else
1727 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1730 static inline void gen_mov_vreg_F0(int dp, int reg)
1732 if (dp)
1733 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1734 else
1735 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1738 #define ARM_CP_RW_BIT (1 << 20)
1740 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1742 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1745 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1747 tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1750 static inline TCGv_i32 iwmmxt_load_creg(int reg)
1752 TCGv_i32 var = tcg_temp_new_i32();
1753 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1754 return var;
1757 static inline void iwmmxt_store_creg(int reg, TCGv_i32 var)
1759 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1760 tcg_temp_free_i32(var);
1763 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1765 iwmmxt_store_reg(cpu_M0, rn);
1768 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1770 iwmmxt_load_reg(cpu_M0, rn);
1773 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1775 iwmmxt_load_reg(cpu_V1, rn);
1776 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1779 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1781 iwmmxt_load_reg(cpu_V1, rn);
1782 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1785 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1787 iwmmxt_load_reg(cpu_V1, rn);
1788 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1791 #define IWMMXT_OP(name) \
1792 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1794 iwmmxt_load_reg(cpu_V1, rn); \
1795 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1798 #define IWMMXT_OP_ENV(name) \
1799 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1801 iwmmxt_load_reg(cpu_V1, rn); \
1802 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1805 #define IWMMXT_OP_ENV_SIZE(name) \
1806 IWMMXT_OP_ENV(name##b) \
1807 IWMMXT_OP_ENV(name##w) \
1808 IWMMXT_OP_ENV(name##l)
1810 #define IWMMXT_OP_ENV1(name) \
1811 static inline void gen_op_iwmmxt_##name##_M0(void) \
1813 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1816 IWMMXT_OP(maddsq)
1817 IWMMXT_OP(madduq)
1818 IWMMXT_OP(sadb)
1819 IWMMXT_OP(sadw)
1820 IWMMXT_OP(mulslw)
1821 IWMMXT_OP(mulshw)
1822 IWMMXT_OP(mululw)
1823 IWMMXT_OP(muluhw)
1824 IWMMXT_OP(macsw)
1825 IWMMXT_OP(macuw)
1827 IWMMXT_OP_ENV_SIZE(unpackl)
1828 IWMMXT_OP_ENV_SIZE(unpackh)
1830 IWMMXT_OP_ENV1(unpacklub)
1831 IWMMXT_OP_ENV1(unpackluw)
1832 IWMMXT_OP_ENV1(unpacklul)
1833 IWMMXT_OP_ENV1(unpackhub)
1834 IWMMXT_OP_ENV1(unpackhuw)
1835 IWMMXT_OP_ENV1(unpackhul)
1836 IWMMXT_OP_ENV1(unpacklsb)
1837 IWMMXT_OP_ENV1(unpacklsw)
1838 IWMMXT_OP_ENV1(unpacklsl)
1839 IWMMXT_OP_ENV1(unpackhsb)
1840 IWMMXT_OP_ENV1(unpackhsw)
1841 IWMMXT_OP_ENV1(unpackhsl)
1843 IWMMXT_OP_ENV_SIZE(cmpeq)
1844 IWMMXT_OP_ENV_SIZE(cmpgtu)
1845 IWMMXT_OP_ENV_SIZE(cmpgts)
1847 IWMMXT_OP_ENV_SIZE(mins)
1848 IWMMXT_OP_ENV_SIZE(minu)
1849 IWMMXT_OP_ENV_SIZE(maxs)
1850 IWMMXT_OP_ENV_SIZE(maxu)
1852 IWMMXT_OP_ENV_SIZE(subn)
1853 IWMMXT_OP_ENV_SIZE(addn)
1854 IWMMXT_OP_ENV_SIZE(subu)
1855 IWMMXT_OP_ENV_SIZE(addu)
1856 IWMMXT_OP_ENV_SIZE(subs)
1857 IWMMXT_OP_ENV_SIZE(adds)
1859 IWMMXT_OP_ENV(avgb0)
1860 IWMMXT_OP_ENV(avgb1)
1861 IWMMXT_OP_ENV(avgw0)
1862 IWMMXT_OP_ENV(avgw1)
1864 IWMMXT_OP_ENV(packuw)
1865 IWMMXT_OP_ENV(packul)
1866 IWMMXT_OP_ENV(packuq)
1867 IWMMXT_OP_ENV(packsw)
1868 IWMMXT_OP_ENV(packsl)
1869 IWMMXT_OP_ENV(packsq)
1871 static void gen_op_iwmmxt_set_mup(void)
1873 TCGv_i32 tmp;
1874 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1875 tcg_gen_ori_i32(tmp, tmp, 2);
1876 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1879 static void gen_op_iwmmxt_set_cup(void)
1881 TCGv_i32 tmp;
1882 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1883 tcg_gen_ori_i32(tmp, tmp, 1);
1884 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1887 static void gen_op_iwmmxt_setpsr_nz(void)
1889 TCGv_i32 tmp = tcg_temp_new_i32();
1890 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1891 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1894 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1896 iwmmxt_load_reg(cpu_V1, rn);
1897 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1898 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1901 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn,
1902 TCGv_i32 dest)
1904 int rd;
1905 uint32_t offset;
1906 TCGv_i32 tmp;
1908 rd = (insn >> 16) & 0xf;
1909 tmp = load_reg(s, rd);
1911 offset = (insn & 0xff) << ((insn >> 7) & 2);
1912 if (insn & (1 << 24)) {
1913 /* Pre indexed */
1914 if (insn & (1 << 23))
1915 tcg_gen_addi_i32(tmp, tmp, offset);
1916 else
1917 tcg_gen_addi_i32(tmp, tmp, -offset);
1918 tcg_gen_mov_i32(dest, tmp);
1919 if (insn & (1 << 21))
1920 store_reg(s, rd, tmp);
1921 else
1922 tcg_temp_free_i32(tmp);
1923 } else if (insn & (1 << 21)) {
1924 /* Post indexed */
1925 tcg_gen_mov_i32(dest, tmp);
1926 if (insn & (1 << 23))
1927 tcg_gen_addi_i32(tmp, tmp, offset);
1928 else
1929 tcg_gen_addi_i32(tmp, tmp, -offset);
1930 store_reg(s, rd, tmp);
1931 } else if (!(insn & (1 << 23)))
1932 return 1;
1933 return 0;
1936 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest)
1938 int rd = (insn >> 0) & 0xf;
1939 TCGv_i32 tmp;
1941 if (insn & (1 << 8)) {
1942 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1943 return 1;
1944 } else {
1945 tmp = iwmmxt_load_creg(rd);
1947 } else {
1948 tmp = tcg_temp_new_i32();
1949 iwmmxt_load_reg(cpu_V0, rd);
1950 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
1952 tcg_gen_andi_i32(tmp, tmp, mask);
1953 tcg_gen_mov_i32(dest, tmp);
1954 tcg_temp_free_i32(tmp);
1955 return 0;
1958 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
1959 (ie. an undefined instruction). */
1960 static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
1962 int rd, wrd;
1963 int rdhi, rdlo, rd0, rd1, i;
1964 TCGv_i32 addr;
1965 TCGv_i32 tmp, tmp2, tmp3;
1967 if ((insn & 0x0e000e00) == 0x0c000000) {
1968 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1969 wrd = insn & 0xf;
1970 rdlo = (insn >> 12) & 0xf;
1971 rdhi = (insn >> 16) & 0xf;
1972 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1973 iwmmxt_load_reg(cpu_V0, wrd);
1974 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
1975 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1976 tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
1977 } else { /* TMCRR */
1978 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1979 iwmmxt_store_reg(cpu_V0, wrd);
1980 gen_op_iwmmxt_set_mup();
1982 return 0;
1985 wrd = (insn >> 12) & 0xf;
1986 addr = tcg_temp_new_i32();
1987 if (gen_iwmmxt_address(s, insn, addr)) {
1988 tcg_temp_free_i32(addr);
1989 return 1;
1991 if (insn & ARM_CP_RW_BIT) {
1992 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1993 tmp = tcg_temp_new_i32();
1994 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
1995 iwmmxt_store_creg(wrd, tmp);
1996 } else {
1997 i = 1;
1998 if (insn & (1 << 8)) {
1999 if (insn & (1 << 22)) { /* WLDRD */
2000 gen_aa32_ld64(s, cpu_M0, addr, get_mem_index(s));
2001 i = 0;
2002 } else { /* WLDRW wRd */
2003 tmp = tcg_temp_new_i32();
2004 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
2006 } else {
2007 tmp = tcg_temp_new_i32();
2008 if (insn & (1 << 22)) { /* WLDRH */
2009 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
2010 } else { /* WLDRB */
2011 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
2014 if (i) {
2015 tcg_gen_extu_i32_i64(cpu_M0, tmp);
2016 tcg_temp_free_i32(tmp);
2018 gen_op_iwmmxt_movq_wRn_M0(wrd);
2020 } else {
2021 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
2022 tmp = iwmmxt_load_creg(wrd);
2023 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
2024 } else {
2025 gen_op_iwmmxt_movq_M0_wRn(wrd);
2026 tmp = tcg_temp_new_i32();
2027 if (insn & (1 << 8)) {
2028 if (insn & (1 << 22)) { /* WSTRD */
2029 gen_aa32_st64(s, cpu_M0, addr, get_mem_index(s));
2030 } else { /* WSTRW wRd */
2031 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2032 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
2034 } else {
2035 if (insn & (1 << 22)) { /* WSTRH */
2036 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2037 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
2038 } else { /* WSTRB */
2039 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2040 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
2044 tcg_temp_free_i32(tmp);
2046 tcg_temp_free_i32(addr);
2047 return 0;
2050 if ((insn & 0x0f000000) != 0x0e000000)
2051 return 1;
2053 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
2054 case 0x000: /* WOR */
2055 wrd = (insn >> 12) & 0xf;
2056 rd0 = (insn >> 0) & 0xf;
2057 rd1 = (insn >> 16) & 0xf;
2058 gen_op_iwmmxt_movq_M0_wRn(rd0);
2059 gen_op_iwmmxt_orq_M0_wRn(rd1);
2060 gen_op_iwmmxt_setpsr_nz();
2061 gen_op_iwmmxt_movq_wRn_M0(wrd);
2062 gen_op_iwmmxt_set_mup();
2063 gen_op_iwmmxt_set_cup();
2064 break;
2065 case 0x011: /* TMCR */
2066 if (insn & 0xf)
2067 return 1;
2068 rd = (insn >> 12) & 0xf;
2069 wrd = (insn >> 16) & 0xf;
2070 switch (wrd) {
2071 case ARM_IWMMXT_wCID:
2072 case ARM_IWMMXT_wCASF:
2073 break;
2074 case ARM_IWMMXT_wCon:
2075 gen_op_iwmmxt_set_cup();
2076 /* Fall through. */
2077 case ARM_IWMMXT_wCSSF:
2078 tmp = iwmmxt_load_creg(wrd);
2079 tmp2 = load_reg(s, rd);
2080 tcg_gen_andc_i32(tmp, tmp, tmp2);
2081 tcg_temp_free_i32(tmp2);
2082 iwmmxt_store_creg(wrd, tmp);
2083 break;
2084 case ARM_IWMMXT_wCGR0:
2085 case ARM_IWMMXT_wCGR1:
2086 case ARM_IWMMXT_wCGR2:
2087 case ARM_IWMMXT_wCGR3:
2088 gen_op_iwmmxt_set_cup();
2089 tmp = load_reg(s, rd);
2090 iwmmxt_store_creg(wrd, tmp);
2091 break;
2092 default:
2093 return 1;
2095 break;
2096 case 0x100: /* WXOR */
2097 wrd = (insn >> 12) & 0xf;
2098 rd0 = (insn >> 0) & 0xf;
2099 rd1 = (insn >> 16) & 0xf;
2100 gen_op_iwmmxt_movq_M0_wRn(rd0);
2101 gen_op_iwmmxt_xorq_M0_wRn(rd1);
2102 gen_op_iwmmxt_setpsr_nz();
2103 gen_op_iwmmxt_movq_wRn_M0(wrd);
2104 gen_op_iwmmxt_set_mup();
2105 gen_op_iwmmxt_set_cup();
2106 break;
2107 case 0x111: /* TMRC */
2108 if (insn & 0xf)
2109 return 1;
2110 rd = (insn >> 12) & 0xf;
2111 wrd = (insn >> 16) & 0xf;
2112 tmp = iwmmxt_load_creg(wrd);
2113 store_reg(s, rd, tmp);
2114 break;
2115 case 0x300: /* WANDN */
2116 wrd = (insn >> 12) & 0xf;
2117 rd0 = (insn >> 0) & 0xf;
2118 rd1 = (insn >> 16) & 0xf;
2119 gen_op_iwmmxt_movq_M0_wRn(rd0);
2120 tcg_gen_neg_i64(cpu_M0, cpu_M0);
2121 gen_op_iwmmxt_andq_M0_wRn(rd1);
2122 gen_op_iwmmxt_setpsr_nz();
2123 gen_op_iwmmxt_movq_wRn_M0(wrd);
2124 gen_op_iwmmxt_set_mup();
2125 gen_op_iwmmxt_set_cup();
2126 break;
2127 case 0x200: /* WAND */
2128 wrd = (insn >> 12) & 0xf;
2129 rd0 = (insn >> 0) & 0xf;
2130 rd1 = (insn >> 16) & 0xf;
2131 gen_op_iwmmxt_movq_M0_wRn(rd0);
2132 gen_op_iwmmxt_andq_M0_wRn(rd1);
2133 gen_op_iwmmxt_setpsr_nz();
2134 gen_op_iwmmxt_movq_wRn_M0(wrd);
2135 gen_op_iwmmxt_set_mup();
2136 gen_op_iwmmxt_set_cup();
2137 break;
2138 case 0x810: case 0xa10: /* WMADD */
2139 wrd = (insn >> 12) & 0xf;
2140 rd0 = (insn >> 0) & 0xf;
2141 rd1 = (insn >> 16) & 0xf;
2142 gen_op_iwmmxt_movq_M0_wRn(rd0);
2143 if (insn & (1 << 21))
2144 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
2145 else
2146 gen_op_iwmmxt_madduq_M0_wRn(rd1);
2147 gen_op_iwmmxt_movq_wRn_M0(wrd);
2148 gen_op_iwmmxt_set_mup();
2149 break;
2150 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
2151 wrd = (insn >> 12) & 0xf;
2152 rd0 = (insn >> 16) & 0xf;
2153 rd1 = (insn >> 0) & 0xf;
2154 gen_op_iwmmxt_movq_M0_wRn(rd0);
2155 switch ((insn >> 22) & 3) {
2156 case 0:
2157 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
2158 break;
2159 case 1:
2160 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
2161 break;
2162 case 2:
2163 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
2164 break;
2165 case 3:
2166 return 1;
2168 gen_op_iwmmxt_movq_wRn_M0(wrd);
2169 gen_op_iwmmxt_set_mup();
2170 gen_op_iwmmxt_set_cup();
2171 break;
2172 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
2173 wrd = (insn >> 12) & 0xf;
2174 rd0 = (insn >> 16) & 0xf;
2175 rd1 = (insn >> 0) & 0xf;
2176 gen_op_iwmmxt_movq_M0_wRn(rd0);
2177 switch ((insn >> 22) & 3) {
2178 case 0:
2179 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
2180 break;
2181 case 1:
2182 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
2183 break;
2184 case 2:
2185 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
2186 break;
2187 case 3:
2188 return 1;
2190 gen_op_iwmmxt_movq_wRn_M0(wrd);
2191 gen_op_iwmmxt_set_mup();
2192 gen_op_iwmmxt_set_cup();
2193 break;
2194 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
2195 wrd = (insn >> 12) & 0xf;
2196 rd0 = (insn >> 16) & 0xf;
2197 rd1 = (insn >> 0) & 0xf;
2198 gen_op_iwmmxt_movq_M0_wRn(rd0);
2199 if (insn & (1 << 22))
2200 gen_op_iwmmxt_sadw_M0_wRn(rd1);
2201 else
2202 gen_op_iwmmxt_sadb_M0_wRn(rd1);
2203 if (!(insn & (1 << 20)))
2204 gen_op_iwmmxt_addl_M0_wRn(wrd);
2205 gen_op_iwmmxt_movq_wRn_M0(wrd);
2206 gen_op_iwmmxt_set_mup();
2207 break;
2208 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
2209 wrd = (insn >> 12) & 0xf;
2210 rd0 = (insn >> 16) & 0xf;
2211 rd1 = (insn >> 0) & 0xf;
2212 gen_op_iwmmxt_movq_M0_wRn(rd0);
2213 if (insn & (1 << 21)) {
2214 if (insn & (1 << 20))
2215 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
2216 else
2217 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
2218 } else {
2219 if (insn & (1 << 20))
2220 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
2221 else
2222 gen_op_iwmmxt_mululw_M0_wRn(rd1);
2224 gen_op_iwmmxt_movq_wRn_M0(wrd);
2225 gen_op_iwmmxt_set_mup();
2226 break;
2227 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
2228 wrd = (insn >> 12) & 0xf;
2229 rd0 = (insn >> 16) & 0xf;
2230 rd1 = (insn >> 0) & 0xf;
2231 gen_op_iwmmxt_movq_M0_wRn(rd0);
2232 if (insn & (1 << 21))
2233 gen_op_iwmmxt_macsw_M0_wRn(rd1);
2234 else
2235 gen_op_iwmmxt_macuw_M0_wRn(rd1);
2236 if (!(insn & (1 << 20))) {
2237 iwmmxt_load_reg(cpu_V1, wrd);
2238 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
2240 gen_op_iwmmxt_movq_wRn_M0(wrd);
2241 gen_op_iwmmxt_set_mup();
2242 break;
2243 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
2244 wrd = (insn >> 12) & 0xf;
2245 rd0 = (insn >> 16) & 0xf;
2246 rd1 = (insn >> 0) & 0xf;
2247 gen_op_iwmmxt_movq_M0_wRn(rd0);
2248 switch ((insn >> 22) & 3) {
2249 case 0:
2250 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
2251 break;
2252 case 1:
2253 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
2254 break;
2255 case 2:
2256 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
2257 break;
2258 case 3:
2259 return 1;
2261 gen_op_iwmmxt_movq_wRn_M0(wrd);
2262 gen_op_iwmmxt_set_mup();
2263 gen_op_iwmmxt_set_cup();
2264 break;
2265 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
2266 wrd = (insn >> 12) & 0xf;
2267 rd0 = (insn >> 16) & 0xf;
2268 rd1 = (insn >> 0) & 0xf;
2269 gen_op_iwmmxt_movq_M0_wRn(rd0);
2270 if (insn & (1 << 22)) {
2271 if (insn & (1 << 20))
2272 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
2273 else
2274 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
2275 } else {
2276 if (insn & (1 << 20))
2277 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
2278 else
2279 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
2281 gen_op_iwmmxt_movq_wRn_M0(wrd);
2282 gen_op_iwmmxt_set_mup();
2283 gen_op_iwmmxt_set_cup();
2284 break;
2285 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
2286 wrd = (insn >> 12) & 0xf;
2287 rd0 = (insn >> 16) & 0xf;
2288 rd1 = (insn >> 0) & 0xf;
2289 gen_op_iwmmxt_movq_M0_wRn(rd0);
2290 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
2291 tcg_gen_andi_i32(tmp, tmp, 7);
2292 iwmmxt_load_reg(cpu_V1, rd1);
2293 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2294 tcg_temp_free_i32(tmp);
2295 gen_op_iwmmxt_movq_wRn_M0(wrd);
2296 gen_op_iwmmxt_set_mup();
2297 break;
2298 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
2299 if (((insn >> 6) & 3) == 3)
2300 return 1;
2301 rd = (insn >> 12) & 0xf;
2302 wrd = (insn >> 16) & 0xf;
2303 tmp = load_reg(s, rd);
2304 gen_op_iwmmxt_movq_M0_wRn(wrd);
2305 switch ((insn >> 6) & 3) {
2306 case 0:
2307 tmp2 = tcg_const_i32(0xff);
2308 tmp3 = tcg_const_i32((insn & 7) << 3);
2309 break;
2310 case 1:
2311 tmp2 = tcg_const_i32(0xffff);
2312 tmp3 = tcg_const_i32((insn & 3) << 4);
2313 break;
2314 case 2:
2315 tmp2 = tcg_const_i32(0xffffffff);
2316 tmp3 = tcg_const_i32((insn & 1) << 5);
2317 break;
2318 default:
2319 tmp2 = NULL;
2320 tmp3 = NULL;
2322 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
2323 tcg_temp_free_i32(tmp3);
2324 tcg_temp_free_i32(tmp2);
2325 tcg_temp_free_i32(tmp);
2326 gen_op_iwmmxt_movq_wRn_M0(wrd);
2327 gen_op_iwmmxt_set_mup();
2328 break;
2329 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
2330 rd = (insn >> 12) & 0xf;
2331 wrd = (insn >> 16) & 0xf;
2332 if (rd == 15 || ((insn >> 22) & 3) == 3)
2333 return 1;
2334 gen_op_iwmmxt_movq_M0_wRn(wrd);
2335 tmp = tcg_temp_new_i32();
2336 switch ((insn >> 22) & 3) {
2337 case 0:
2338 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
2339 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2340 if (insn & 8) {
2341 tcg_gen_ext8s_i32(tmp, tmp);
2342 } else {
2343 tcg_gen_andi_i32(tmp, tmp, 0xff);
2345 break;
2346 case 1:
2347 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
2348 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2349 if (insn & 8) {
2350 tcg_gen_ext16s_i32(tmp, tmp);
2351 } else {
2352 tcg_gen_andi_i32(tmp, tmp, 0xffff);
2354 break;
2355 case 2:
2356 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
2357 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2358 break;
2360 store_reg(s, rd, tmp);
2361 break;
2362 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
2363 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
2364 return 1;
2365 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
2366 switch ((insn >> 22) & 3) {
2367 case 0:
2368 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
2369 break;
2370 case 1:
2371 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
2372 break;
2373 case 2:
2374 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
2375 break;
2377 tcg_gen_shli_i32(tmp, tmp, 28);
2378 gen_set_nzcv(tmp);
2379 tcg_temp_free_i32(tmp);
2380 break;
2381 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
2382 if (((insn >> 6) & 3) == 3)
2383 return 1;
2384 rd = (insn >> 12) & 0xf;
2385 wrd = (insn >> 16) & 0xf;
2386 tmp = load_reg(s, rd);
2387 switch ((insn >> 6) & 3) {
2388 case 0:
2389 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
2390 break;
2391 case 1:
2392 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
2393 break;
2394 case 2:
2395 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
2396 break;
2398 tcg_temp_free_i32(tmp);
2399 gen_op_iwmmxt_movq_wRn_M0(wrd);
2400 gen_op_iwmmxt_set_mup();
2401 break;
2402 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
2403 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
2404 return 1;
2405 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
2406 tmp2 = tcg_temp_new_i32();
2407 tcg_gen_mov_i32(tmp2, tmp);
2408 switch ((insn >> 22) & 3) {
2409 case 0:
2410 for (i = 0; i < 7; i ++) {
2411 tcg_gen_shli_i32(tmp2, tmp2, 4);
2412 tcg_gen_and_i32(tmp, tmp, tmp2);
2414 break;
2415 case 1:
2416 for (i = 0; i < 3; i ++) {
2417 tcg_gen_shli_i32(tmp2, tmp2, 8);
2418 tcg_gen_and_i32(tmp, tmp, tmp2);
2420 break;
2421 case 2:
2422 tcg_gen_shli_i32(tmp2, tmp2, 16);
2423 tcg_gen_and_i32(tmp, tmp, tmp2);
2424 break;
2426 gen_set_nzcv(tmp);
2427 tcg_temp_free_i32(tmp2);
2428 tcg_temp_free_i32(tmp);
2429 break;
2430 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
2431 wrd = (insn >> 12) & 0xf;
2432 rd0 = (insn >> 16) & 0xf;
2433 gen_op_iwmmxt_movq_M0_wRn(rd0);
2434 switch ((insn >> 22) & 3) {
2435 case 0:
2436 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
2437 break;
2438 case 1:
2439 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
2440 break;
2441 case 2:
2442 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
2443 break;
2444 case 3:
2445 return 1;
2447 gen_op_iwmmxt_movq_wRn_M0(wrd);
2448 gen_op_iwmmxt_set_mup();
2449 break;
2450 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
2451 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
2452 return 1;
2453 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
2454 tmp2 = tcg_temp_new_i32();
2455 tcg_gen_mov_i32(tmp2, tmp);
2456 switch ((insn >> 22) & 3) {
2457 case 0:
2458 for (i = 0; i < 7; i ++) {
2459 tcg_gen_shli_i32(tmp2, tmp2, 4);
2460 tcg_gen_or_i32(tmp, tmp, tmp2);
2462 break;
2463 case 1:
2464 for (i = 0; i < 3; i ++) {
2465 tcg_gen_shli_i32(tmp2, tmp2, 8);
2466 tcg_gen_or_i32(tmp, tmp, tmp2);
2468 break;
2469 case 2:
2470 tcg_gen_shli_i32(tmp2, tmp2, 16);
2471 tcg_gen_or_i32(tmp, tmp, tmp2);
2472 break;
2474 gen_set_nzcv(tmp);
2475 tcg_temp_free_i32(tmp2);
2476 tcg_temp_free_i32(tmp);
2477 break;
2478 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
2479 rd = (insn >> 12) & 0xf;
2480 rd0 = (insn >> 16) & 0xf;
2481 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
2482 return 1;
2483 gen_op_iwmmxt_movq_M0_wRn(rd0);
2484 tmp = tcg_temp_new_i32();
2485 switch ((insn >> 22) & 3) {
2486 case 0:
2487 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
2488 break;
2489 case 1:
2490 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
2491 break;
2492 case 2:
2493 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
2494 break;
2496 store_reg(s, rd, tmp);
2497 break;
2498 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
2499 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2500 wrd = (insn >> 12) & 0xf;
2501 rd0 = (insn >> 16) & 0xf;
2502 rd1 = (insn >> 0) & 0xf;
2503 gen_op_iwmmxt_movq_M0_wRn(rd0);
2504 switch ((insn >> 22) & 3) {
2505 case 0:
2506 if (insn & (1 << 21))
2507 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2508 else
2509 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2510 break;
2511 case 1:
2512 if (insn & (1 << 21))
2513 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2514 else
2515 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2516 break;
2517 case 2:
2518 if (insn & (1 << 21))
2519 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2520 else
2521 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2522 break;
2523 case 3:
2524 return 1;
2526 gen_op_iwmmxt_movq_wRn_M0(wrd);
2527 gen_op_iwmmxt_set_mup();
2528 gen_op_iwmmxt_set_cup();
2529 break;
2530 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2531 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2532 wrd = (insn >> 12) & 0xf;
2533 rd0 = (insn >> 16) & 0xf;
2534 gen_op_iwmmxt_movq_M0_wRn(rd0);
2535 switch ((insn >> 22) & 3) {
2536 case 0:
2537 if (insn & (1 << 21))
2538 gen_op_iwmmxt_unpacklsb_M0();
2539 else
2540 gen_op_iwmmxt_unpacklub_M0();
2541 break;
2542 case 1:
2543 if (insn & (1 << 21))
2544 gen_op_iwmmxt_unpacklsw_M0();
2545 else
2546 gen_op_iwmmxt_unpackluw_M0();
2547 break;
2548 case 2:
2549 if (insn & (1 << 21))
2550 gen_op_iwmmxt_unpacklsl_M0();
2551 else
2552 gen_op_iwmmxt_unpacklul_M0();
2553 break;
2554 case 3:
2555 return 1;
2557 gen_op_iwmmxt_movq_wRn_M0(wrd);
2558 gen_op_iwmmxt_set_mup();
2559 gen_op_iwmmxt_set_cup();
2560 break;
2561 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2562 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2563 wrd = (insn >> 12) & 0xf;
2564 rd0 = (insn >> 16) & 0xf;
2565 gen_op_iwmmxt_movq_M0_wRn(rd0);
2566 switch ((insn >> 22) & 3) {
2567 case 0:
2568 if (insn & (1 << 21))
2569 gen_op_iwmmxt_unpackhsb_M0();
2570 else
2571 gen_op_iwmmxt_unpackhub_M0();
2572 break;
2573 case 1:
2574 if (insn & (1 << 21))
2575 gen_op_iwmmxt_unpackhsw_M0();
2576 else
2577 gen_op_iwmmxt_unpackhuw_M0();
2578 break;
2579 case 2:
2580 if (insn & (1 << 21))
2581 gen_op_iwmmxt_unpackhsl_M0();
2582 else
2583 gen_op_iwmmxt_unpackhul_M0();
2584 break;
2585 case 3:
2586 return 1;
2588 gen_op_iwmmxt_movq_wRn_M0(wrd);
2589 gen_op_iwmmxt_set_mup();
2590 gen_op_iwmmxt_set_cup();
2591 break;
2592 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2593 case 0x214: case 0x614: case 0xa14: case 0xe14:
2594 if (((insn >> 22) & 3) == 0)
2595 return 1;
2596 wrd = (insn >> 12) & 0xf;
2597 rd0 = (insn >> 16) & 0xf;
2598 gen_op_iwmmxt_movq_M0_wRn(rd0);
2599 tmp = tcg_temp_new_i32();
2600 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2601 tcg_temp_free_i32(tmp);
2602 return 1;
2604 switch ((insn >> 22) & 3) {
2605 case 1:
2606 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
2607 break;
2608 case 2:
2609 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
2610 break;
2611 case 3:
2612 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
2613 break;
2615 tcg_temp_free_i32(tmp);
2616 gen_op_iwmmxt_movq_wRn_M0(wrd);
2617 gen_op_iwmmxt_set_mup();
2618 gen_op_iwmmxt_set_cup();
2619 break;
2620 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2621 case 0x014: case 0x414: case 0x814: case 0xc14:
2622 if (((insn >> 22) & 3) == 0)
2623 return 1;
2624 wrd = (insn >> 12) & 0xf;
2625 rd0 = (insn >> 16) & 0xf;
2626 gen_op_iwmmxt_movq_M0_wRn(rd0);
2627 tmp = tcg_temp_new_i32();
2628 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2629 tcg_temp_free_i32(tmp);
2630 return 1;
2632 switch ((insn >> 22) & 3) {
2633 case 1:
2634 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2635 break;
2636 case 2:
2637 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2638 break;
2639 case 3:
2640 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2641 break;
2643 tcg_temp_free_i32(tmp);
2644 gen_op_iwmmxt_movq_wRn_M0(wrd);
2645 gen_op_iwmmxt_set_mup();
2646 gen_op_iwmmxt_set_cup();
2647 break;
2648 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2649 case 0x114: case 0x514: case 0x914: case 0xd14:
2650 if (((insn >> 22) & 3) == 0)
2651 return 1;
2652 wrd = (insn >> 12) & 0xf;
2653 rd0 = (insn >> 16) & 0xf;
2654 gen_op_iwmmxt_movq_M0_wRn(rd0);
2655 tmp = tcg_temp_new_i32();
2656 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2657 tcg_temp_free_i32(tmp);
2658 return 1;
2660 switch ((insn >> 22) & 3) {
2661 case 1:
2662 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2663 break;
2664 case 2:
2665 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2666 break;
2667 case 3:
2668 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2669 break;
2671 tcg_temp_free_i32(tmp);
2672 gen_op_iwmmxt_movq_wRn_M0(wrd);
2673 gen_op_iwmmxt_set_mup();
2674 gen_op_iwmmxt_set_cup();
2675 break;
2676 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2677 case 0x314: case 0x714: case 0xb14: case 0xf14:
2678 if (((insn >> 22) & 3) == 0)
2679 return 1;
2680 wrd = (insn >> 12) & 0xf;
2681 rd0 = (insn >> 16) & 0xf;
2682 gen_op_iwmmxt_movq_M0_wRn(rd0);
2683 tmp = tcg_temp_new_i32();
2684 switch ((insn >> 22) & 3) {
2685 case 1:
2686 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2687 tcg_temp_free_i32(tmp);
2688 return 1;
2690 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2691 break;
2692 case 2:
2693 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2694 tcg_temp_free_i32(tmp);
2695 return 1;
2697 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2698 break;
2699 case 3:
2700 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2701 tcg_temp_free_i32(tmp);
2702 return 1;
2704 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2705 break;
2707 tcg_temp_free_i32(tmp);
2708 gen_op_iwmmxt_movq_wRn_M0(wrd);
2709 gen_op_iwmmxt_set_mup();
2710 gen_op_iwmmxt_set_cup();
2711 break;
2712 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2713 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2714 wrd = (insn >> 12) & 0xf;
2715 rd0 = (insn >> 16) & 0xf;
2716 rd1 = (insn >> 0) & 0xf;
2717 gen_op_iwmmxt_movq_M0_wRn(rd0);
2718 switch ((insn >> 22) & 3) {
2719 case 0:
2720 if (insn & (1 << 21))
2721 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2722 else
2723 gen_op_iwmmxt_minub_M0_wRn(rd1);
2724 break;
2725 case 1:
2726 if (insn & (1 << 21))
2727 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2728 else
2729 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2730 break;
2731 case 2:
2732 if (insn & (1 << 21))
2733 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2734 else
2735 gen_op_iwmmxt_minul_M0_wRn(rd1);
2736 break;
2737 case 3:
2738 return 1;
2740 gen_op_iwmmxt_movq_wRn_M0(wrd);
2741 gen_op_iwmmxt_set_mup();
2742 break;
2743 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2744 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2745 wrd = (insn >> 12) & 0xf;
2746 rd0 = (insn >> 16) & 0xf;
2747 rd1 = (insn >> 0) & 0xf;
2748 gen_op_iwmmxt_movq_M0_wRn(rd0);
2749 switch ((insn >> 22) & 3) {
2750 case 0:
2751 if (insn & (1 << 21))
2752 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2753 else
2754 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2755 break;
2756 case 1:
2757 if (insn & (1 << 21))
2758 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2759 else
2760 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2761 break;
2762 case 2:
2763 if (insn & (1 << 21))
2764 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2765 else
2766 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2767 break;
2768 case 3:
2769 return 1;
2771 gen_op_iwmmxt_movq_wRn_M0(wrd);
2772 gen_op_iwmmxt_set_mup();
2773 break;
2774 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2775 case 0x402: case 0x502: case 0x602: case 0x702:
2776 wrd = (insn >> 12) & 0xf;
2777 rd0 = (insn >> 16) & 0xf;
2778 rd1 = (insn >> 0) & 0xf;
2779 gen_op_iwmmxt_movq_M0_wRn(rd0);
2780 tmp = tcg_const_i32((insn >> 20) & 3);
2781 iwmmxt_load_reg(cpu_V1, rd1);
2782 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2783 tcg_temp_free_i32(tmp);
2784 gen_op_iwmmxt_movq_wRn_M0(wrd);
2785 gen_op_iwmmxt_set_mup();
2786 break;
2787 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2788 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2789 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2790 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2791 wrd = (insn >> 12) & 0xf;
2792 rd0 = (insn >> 16) & 0xf;
2793 rd1 = (insn >> 0) & 0xf;
2794 gen_op_iwmmxt_movq_M0_wRn(rd0);
2795 switch ((insn >> 20) & 0xf) {
2796 case 0x0:
2797 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2798 break;
2799 case 0x1:
2800 gen_op_iwmmxt_subub_M0_wRn(rd1);
2801 break;
2802 case 0x3:
2803 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2804 break;
2805 case 0x4:
2806 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2807 break;
2808 case 0x5:
2809 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2810 break;
2811 case 0x7:
2812 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2813 break;
2814 case 0x8:
2815 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2816 break;
2817 case 0x9:
2818 gen_op_iwmmxt_subul_M0_wRn(rd1);
2819 break;
2820 case 0xb:
2821 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2822 break;
2823 default:
2824 return 1;
2826 gen_op_iwmmxt_movq_wRn_M0(wrd);
2827 gen_op_iwmmxt_set_mup();
2828 gen_op_iwmmxt_set_cup();
2829 break;
2830 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2831 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2832 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2833 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2834 wrd = (insn >> 12) & 0xf;
2835 rd0 = (insn >> 16) & 0xf;
2836 gen_op_iwmmxt_movq_M0_wRn(rd0);
2837 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2838 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2839 tcg_temp_free_i32(tmp);
2840 gen_op_iwmmxt_movq_wRn_M0(wrd);
2841 gen_op_iwmmxt_set_mup();
2842 gen_op_iwmmxt_set_cup();
2843 break;
2844 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2845 case 0x418: case 0x518: case 0x618: case 0x718:
2846 case 0x818: case 0x918: case 0xa18: case 0xb18:
2847 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2848 wrd = (insn >> 12) & 0xf;
2849 rd0 = (insn >> 16) & 0xf;
2850 rd1 = (insn >> 0) & 0xf;
2851 gen_op_iwmmxt_movq_M0_wRn(rd0);
2852 switch ((insn >> 20) & 0xf) {
2853 case 0x0:
2854 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2855 break;
2856 case 0x1:
2857 gen_op_iwmmxt_addub_M0_wRn(rd1);
2858 break;
2859 case 0x3:
2860 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2861 break;
2862 case 0x4:
2863 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2864 break;
2865 case 0x5:
2866 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2867 break;
2868 case 0x7:
2869 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2870 break;
2871 case 0x8:
2872 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2873 break;
2874 case 0x9:
2875 gen_op_iwmmxt_addul_M0_wRn(rd1);
2876 break;
2877 case 0xb:
2878 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2879 break;
2880 default:
2881 return 1;
2883 gen_op_iwmmxt_movq_wRn_M0(wrd);
2884 gen_op_iwmmxt_set_mup();
2885 gen_op_iwmmxt_set_cup();
2886 break;
2887 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2888 case 0x408: case 0x508: case 0x608: case 0x708:
2889 case 0x808: case 0x908: case 0xa08: case 0xb08:
2890 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2891 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2892 return 1;
2893 wrd = (insn >> 12) & 0xf;
2894 rd0 = (insn >> 16) & 0xf;
2895 rd1 = (insn >> 0) & 0xf;
2896 gen_op_iwmmxt_movq_M0_wRn(rd0);
2897 switch ((insn >> 22) & 3) {
2898 case 1:
2899 if (insn & (1 << 21))
2900 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2901 else
2902 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2903 break;
2904 case 2:
2905 if (insn & (1 << 21))
2906 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2907 else
2908 gen_op_iwmmxt_packul_M0_wRn(rd1);
2909 break;
2910 case 3:
2911 if (insn & (1 << 21))
2912 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2913 else
2914 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2915 break;
2917 gen_op_iwmmxt_movq_wRn_M0(wrd);
2918 gen_op_iwmmxt_set_mup();
2919 gen_op_iwmmxt_set_cup();
2920 break;
2921 case 0x201: case 0x203: case 0x205: case 0x207:
2922 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2923 case 0x211: case 0x213: case 0x215: case 0x217:
2924 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2925 wrd = (insn >> 5) & 0xf;
2926 rd0 = (insn >> 12) & 0xf;
2927 rd1 = (insn >> 0) & 0xf;
2928 if (rd0 == 0xf || rd1 == 0xf)
2929 return 1;
2930 gen_op_iwmmxt_movq_M0_wRn(wrd);
2931 tmp = load_reg(s, rd0);
2932 tmp2 = load_reg(s, rd1);
2933 switch ((insn >> 16) & 0xf) {
2934 case 0x0: /* TMIA */
2935 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2936 break;
2937 case 0x8: /* TMIAPH */
2938 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2939 break;
2940 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2941 if (insn & (1 << 16))
2942 tcg_gen_shri_i32(tmp, tmp, 16);
2943 if (insn & (1 << 17))
2944 tcg_gen_shri_i32(tmp2, tmp2, 16);
2945 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2946 break;
2947 default:
2948 tcg_temp_free_i32(tmp2);
2949 tcg_temp_free_i32(tmp);
2950 return 1;
2952 tcg_temp_free_i32(tmp2);
2953 tcg_temp_free_i32(tmp);
2954 gen_op_iwmmxt_movq_wRn_M0(wrd);
2955 gen_op_iwmmxt_set_mup();
2956 break;
2957 default:
2958 return 1;
2961 return 0;
2964 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
2965 (ie. an undefined instruction). */
2966 static int disas_dsp_insn(DisasContext *s, uint32_t insn)
2968 int acc, rd0, rd1, rdhi, rdlo;
2969 TCGv_i32 tmp, tmp2;
2971 if ((insn & 0x0ff00f10) == 0x0e200010) {
2972 /* Multiply with Internal Accumulate Format */
2973 rd0 = (insn >> 12) & 0xf;
2974 rd1 = insn & 0xf;
2975 acc = (insn >> 5) & 7;
2977 if (acc != 0)
2978 return 1;
2980 tmp = load_reg(s, rd0);
2981 tmp2 = load_reg(s, rd1);
2982 switch ((insn >> 16) & 0xf) {
2983 case 0x0: /* MIA */
2984 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2985 break;
2986 case 0x8: /* MIAPH */
2987 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2988 break;
2989 case 0xc: /* MIABB */
2990 case 0xd: /* MIABT */
2991 case 0xe: /* MIATB */
2992 case 0xf: /* MIATT */
2993 if (insn & (1 << 16))
2994 tcg_gen_shri_i32(tmp, tmp, 16);
2995 if (insn & (1 << 17))
2996 tcg_gen_shri_i32(tmp2, tmp2, 16);
2997 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2998 break;
2999 default:
3000 return 1;
3002 tcg_temp_free_i32(tmp2);
3003 tcg_temp_free_i32(tmp);
3005 gen_op_iwmmxt_movq_wRn_M0(acc);
3006 return 0;
3009 if ((insn & 0x0fe00ff8) == 0x0c400000) {
3010 /* Internal Accumulator Access Format */
3011 rdhi = (insn >> 16) & 0xf;
3012 rdlo = (insn >> 12) & 0xf;
3013 acc = insn & 7;
3015 if (acc != 0)
3016 return 1;
3018 if (insn & ARM_CP_RW_BIT) { /* MRA */
3019 iwmmxt_load_reg(cpu_V0, acc);
3020 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
3021 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
3022 tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
3023 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
3024 } else { /* MAR */
3025 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
3026 iwmmxt_store_reg(cpu_V0, acc);
3028 return 0;
3031 return 1;
3034 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
3035 #define VFP_SREG(insn, bigbit, smallbit) \
3036 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
3037 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
3038 if (arm_dc_feature(s, ARM_FEATURE_VFP3)) { \
3039 reg = (((insn) >> (bigbit)) & 0x0f) \
3040 | (((insn) >> ((smallbit) - 4)) & 0x10); \
3041 } else { \
3042 if (insn & (1 << (smallbit))) \
3043 return 1; \
3044 reg = ((insn) >> (bigbit)) & 0x0f; \
3045 }} while (0)
3047 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
3048 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
3049 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
3050 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
3051 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
3052 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
3054 /* Move between integer and VFP cores. */
3055 static TCGv_i32 gen_vfp_mrs(void)
3057 TCGv_i32 tmp = tcg_temp_new_i32();
3058 tcg_gen_mov_i32(tmp, cpu_F0s);
3059 return tmp;
3062 static void gen_vfp_msr(TCGv_i32 tmp)
3064 tcg_gen_mov_i32(cpu_F0s, tmp);
3065 tcg_temp_free_i32(tmp);
3068 static void gen_neon_dup_low16(TCGv_i32 var)
3070 TCGv_i32 tmp = tcg_temp_new_i32();
3071 tcg_gen_ext16u_i32(var, var);
3072 tcg_gen_shli_i32(tmp, var, 16);
3073 tcg_gen_or_i32(var, var, tmp);
3074 tcg_temp_free_i32(tmp);
3077 static void gen_neon_dup_high16(TCGv_i32 var)
3079 TCGv_i32 tmp = tcg_temp_new_i32();
3080 tcg_gen_andi_i32(var, var, 0xffff0000);
3081 tcg_gen_shri_i32(tmp, var, 16);
3082 tcg_gen_or_i32(var, var, tmp);
3083 tcg_temp_free_i32(tmp);
3086 static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
3087 uint32_t dp)
3089 uint32_t cc = extract32(insn, 20, 2);
3091 if (dp) {
3092 TCGv_i64 frn, frm, dest;
3093 TCGv_i64 tmp, zero, zf, nf, vf;
3095 zero = tcg_const_i64(0);
3097 frn = tcg_temp_new_i64();
3098 frm = tcg_temp_new_i64();
3099 dest = tcg_temp_new_i64();
3101 zf = tcg_temp_new_i64();
3102 nf = tcg_temp_new_i64();
3103 vf = tcg_temp_new_i64();
3105 tcg_gen_extu_i32_i64(zf, cpu_ZF);
3106 tcg_gen_ext_i32_i64(nf, cpu_NF);
3107 tcg_gen_ext_i32_i64(vf, cpu_VF);
3109 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
3110 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
3111 switch (cc) {
3112 case 0: /* eq: Z */
3113 tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero,
3114 frn, frm);
3115 break;
3116 case 1: /* vs: V */
3117 tcg_gen_movcond_i64(TCG_COND_LT, dest, vf, zero,
3118 frn, frm);
3119 break;
3120 case 2: /* ge: N == V -> N ^ V == 0 */
3121 tmp = tcg_temp_new_i64();
3122 tcg_gen_xor_i64(tmp, vf, nf);
3123 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
3124 frn, frm);
3125 tcg_temp_free_i64(tmp);
3126 break;
3127 case 3: /* gt: !Z && N == V */
3128 tcg_gen_movcond_i64(TCG_COND_NE, dest, zf, zero,
3129 frn, frm);
3130 tmp = tcg_temp_new_i64();
3131 tcg_gen_xor_i64(tmp, vf, nf);
3132 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
3133 dest, frm);
3134 tcg_temp_free_i64(tmp);
3135 break;
3137 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
3138 tcg_temp_free_i64(frn);
3139 tcg_temp_free_i64(frm);
3140 tcg_temp_free_i64(dest);
3142 tcg_temp_free_i64(zf);
3143 tcg_temp_free_i64(nf);
3144 tcg_temp_free_i64(vf);
3146 tcg_temp_free_i64(zero);
3147 } else {
3148 TCGv_i32 frn, frm, dest;
3149 TCGv_i32 tmp, zero;
3151 zero = tcg_const_i32(0);
3153 frn = tcg_temp_new_i32();
3154 frm = tcg_temp_new_i32();
3155 dest = tcg_temp_new_i32();
3156 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
3157 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
3158 switch (cc) {
3159 case 0: /* eq: Z */
3160 tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero,
3161 frn, frm);
3162 break;
3163 case 1: /* vs: V */
3164 tcg_gen_movcond_i32(TCG_COND_LT, dest, cpu_VF, zero,
3165 frn, frm);
3166 break;
3167 case 2: /* ge: N == V -> N ^ V == 0 */
3168 tmp = tcg_temp_new_i32();
3169 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
3170 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
3171 frn, frm);
3172 tcg_temp_free_i32(tmp);
3173 break;
3174 case 3: /* gt: !Z && N == V */
3175 tcg_gen_movcond_i32(TCG_COND_NE, dest, cpu_ZF, zero,
3176 frn, frm);
3177 tmp = tcg_temp_new_i32();
3178 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
3179 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
3180 dest, frm);
3181 tcg_temp_free_i32(tmp);
3182 break;
3184 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
3185 tcg_temp_free_i32(frn);
3186 tcg_temp_free_i32(frm);
3187 tcg_temp_free_i32(dest);
3189 tcg_temp_free_i32(zero);
3192 return 0;
3195 static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn,
3196 uint32_t rm, uint32_t dp)
3198 uint32_t vmin = extract32(insn, 6, 1);
3199 TCGv_ptr fpst = get_fpstatus_ptr(0);
3201 if (dp) {
3202 TCGv_i64 frn, frm, dest;
3204 frn = tcg_temp_new_i64();
3205 frm = tcg_temp_new_i64();
3206 dest = tcg_temp_new_i64();
3208 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
3209 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
3210 if (vmin) {
3211 gen_helper_vfp_minnumd(dest, frn, frm, fpst);
3212 } else {
3213 gen_helper_vfp_maxnumd(dest, frn, frm, fpst);
3215 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
3216 tcg_temp_free_i64(frn);
3217 tcg_temp_free_i64(frm);
3218 tcg_temp_free_i64(dest);
3219 } else {
3220 TCGv_i32 frn, frm, dest;
3222 frn = tcg_temp_new_i32();
3223 frm = tcg_temp_new_i32();
3224 dest = tcg_temp_new_i32();
3226 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
3227 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
3228 if (vmin) {
3229 gen_helper_vfp_minnums(dest, frn, frm, fpst);
3230 } else {
3231 gen_helper_vfp_maxnums(dest, frn, frm, fpst);
3233 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
3234 tcg_temp_free_i32(frn);
3235 tcg_temp_free_i32(frm);
3236 tcg_temp_free_i32(dest);
3239 tcg_temp_free_ptr(fpst);
3240 return 0;
3243 static int handle_vrint(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
3244 int rounding)
3246 TCGv_ptr fpst = get_fpstatus_ptr(0);
3247 TCGv_i32 tcg_rmode;
3249 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
3250 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
3252 if (dp) {
3253 TCGv_i64 tcg_op;
3254 TCGv_i64 tcg_res;
3255 tcg_op = tcg_temp_new_i64();
3256 tcg_res = tcg_temp_new_i64();
3257 tcg_gen_ld_f64(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
3258 gen_helper_rintd(tcg_res, tcg_op, fpst);
3259 tcg_gen_st_f64(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
3260 tcg_temp_free_i64(tcg_op);
3261 tcg_temp_free_i64(tcg_res);
3262 } else {
3263 TCGv_i32 tcg_op;
3264 TCGv_i32 tcg_res;
3265 tcg_op = tcg_temp_new_i32();
3266 tcg_res = tcg_temp_new_i32();
3267 tcg_gen_ld_f32(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
3268 gen_helper_rints(tcg_res, tcg_op, fpst);
3269 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
3270 tcg_temp_free_i32(tcg_op);
3271 tcg_temp_free_i32(tcg_res);
3274 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
3275 tcg_temp_free_i32(tcg_rmode);
3277 tcg_temp_free_ptr(fpst);
3278 return 0;
3281 static int handle_vcvt(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
3282 int rounding)
3284 bool is_signed = extract32(insn, 7, 1);
3285 TCGv_ptr fpst = get_fpstatus_ptr(0);
3286 TCGv_i32 tcg_rmode, tcg_shift;
3288 tcg_shift = tcg_const_i32(0);
3290 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
3291 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
3293 if (dp) {
3294 TCGv_i64 tcg_double, tcg_res;
3295 TCGv_i32 tcg_tmp;
3296 /* Rd is encoded as a single precision register even when the source
3297 * is double precision.
3299 rd = ((rd << 1) & 0x1e) | ((rd >> 4) & 0x1);
3300 tcg_double = tcg_temp_new_i64();
3301 tcg_res = tcg_temp_new_i64();
3302 tcg_tmp = tcg_temp_new_i32();
3303 tcg_gen_ld_f64(tcg_double, cpu_env, vfp_reg_offset(1, rm));
3304 if (is_signed) {
3305 gen_helper_vfp_tosld(tcg_res, tcg_double, tcg_shift, fpst);
3306 } else {
3307 gen_helper_vfp_tould(tcg_res, tcg_double, tcg_shift, fpst);
3309 tcg_gen_extrl_i64_i32(tcg_tmp, tcg_res);
3310 tcg_gen_st_f32(tcg_tmp, cpu_env, vfp_reg_offset(0, rd));
3311 tcg_temp_free_i32(tcg_tmp);
3312 tcg_temp_free_i64(tcg_res);
3313 tcg_temp_free_i64(tcg_double);
3314 } else {
3315 TCGv_i32 tcg_single, tcg_res;
3316 tcg_single = tcg_temp_new_i32();
3317 tcg_res = tcg_temp_new_i32();
3318 tcg_gen_ld_f32(tcg_single, cpu_env, vfp_reg_offset(0, rm));
3319 if (is_signed) {
3320 gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst);
3321 } else {
3322 gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst);
3324 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(0, rd));
3325 tcg_temp_free_i32(tcg_res);
3326 tcg_temp_free_i32(tcg_single);
3329 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
3330 tcg_temp_free_i32(tcg_rmode);
3332 tcg_temp_free_i32(tcg_shift);
3334 tcg_temp_free_ptr(fpst);
3336 return 0;
3339 /* Table for converting the most common AArch32 encoding of
3340 * rounding mode to arm_fprounding order (which matches the
3341 * common AArch64 order); see ARM ARM pseudocode FPDecodeRM().
3343 static const uint8_t fp_decode_rm[] = {
3344 FPROUNDING_TIEAWAY,
3345 FPROUNDING_TIEEVEN,
3346 FPROUNDING_POSINF,
3347 FPROUNDING_NEGINF,
3350 static int disas_vfp_misc_insn(DisasContext *s, uint32_t insn)
3352 uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
3354 if (dp) {
3355 VFP_DREG_D(rd, insn);
3356 VFP_DREG_N(rn, insn);
3357 VFP_DREG_M(rm, insn);
3358 } else {
3359 rd = VFP_SREG_D(insn);
3360 rn = VFP_SREG_N(insn);
3361 rm = VFP_SREG_M(insn);
3364 if ((insn & 0x0f800e50) == 0x0e000a00 && dc_isar_feature(aa32_vsel, s)) {
3365 return handle_vsel(insn, rd, rn, rm, dp);
3366 } else if ((insn & 0x0fb00e10) == 0x0e800a00 &&
3367 dc_isar_feature(aa32_vminmaxnm, s)) {
3368 return handle_vminmaxnm(insn, rd, rn, rm, dp);
3369 } else if ((insn & 0x0fbc0ed0) == 0x0eb80a40 &&
3370 dc_isar_feature(aa32_vrint, s)) {
3371 /* VRINTA, VRINTN, VRINTP, VRINTM */
3372 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
3373 return handle_vrint(insn, rd, rm, dp, rounding);
3374 } else if ((insn & 0x0fbc0e50) == 0x0ebc0a40 &&
3375 dc_isar_feature(aa32_vcvt_dr, s)) {
3376 /* VCVTA, VCVTN, VCVTP, VCVTM */
3377 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
3378 return handle_vcvt(insn, rd, rm, dp, rounding);
3380 return 1;
3383 /* Disassemble a VFP instruction. Returns nonzero if an error occurred
3384 (ie. an undefined instruction). */
3385 static int disas_vfp_insn(DisasContext *s, uint32_t insn)
3387 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
3388 int dp, veclen;
3389 TCGv_i32 addr;
3390 TCGv_i32 tmp;
3391 TCGv_i32 tmp2;
3393 if (!arm_dc_feature(s, ARM_FEATURE_VFP)) {
3394 return 1;
3397 /* FIXME: this access check should not take precedence over UNDEF
3398 * for invalid encodings; we will generate incorrect syndrome information
3399 * for attempts to execute invalid vfp/neon encodings with FP disabled.
3401 if (s->fp_excp_el) {
3402 if (arm_dc_feature(s, ARM_FEATURE_M)) {
3403 gen_exception_insn(s, 4, EXCP_NOCP, syn_uncategorized(),
3404 s->fp_excp_el);
3405 } else {
3406 gen_exception_insn(s, 4, EXCP_UDEF,
3407 syn_fp_access_trap(1, 0xe, false),
3408 s->fp_excp_el);
3410 return 0;
3413 if (!s->vfp_enabled) {
3414 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
3415 if ((insn & 0x0fe00fff) != 0x0ee00a10)
3416 return 1;
3417 rn = (insn >> 16) & 0xf;
3418 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC && rn != ARM_VFP_MVFR2
3419 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0) {
3420 return 1;
3424 if (extract32(insn, 28, 4) == 0xf) {
3426 * Encodings with T=1 (Thumb) or unconditional (ARM):
3427 * only used for the "miscellaneous VFP features" added in v8A
3428 * and v7M (and gated on the MVFR2.FPMisc field).
3430 return disas_vfp_misc_insn(s, insn);
3433 dp = ((insn & 0xf00) == 0xb00);
3434 switch ((insn >> 24) & 0xf) {
3435 case 0xe:
3436 if (insn & (1 << 4)) {
3437 /* single register transfer */
3438 rd = (insn >> 12) & 0xf;
3439 if (dp) {
3440 int size;
3441 int pass;
3443 VFP_DREG_N(rn, insn);
3444 if (insn & 0xf)
3445 return 1;
3446 if (insn & 0x00c00060
3447 && !arm_dc_feature(s, ARM_FEATURE_NEON)) {
3448 return 1;
3451 pass = (insn >> 21) & 1;
3452 if (insn & (1 << 22)) {
3453 size = 0;
3454 offset = ((insn >> 5) & 3) * 8;
3455 } else if (insn & (1 << 5)) {
3456 size = 1;
3457 offset = (insn & (1 << 6)) ? 16 : 0;
3458 } else {
3459 size = 2;
3460 offset = 0;
3462 if (insn & ARM_CP_RW_BIT) {
3463 /* vfp->arm */
3464 tmp = neon_load_reg(rn, pass);
3465 switch (size) {
3466 case 0:
3467 if (offset)
3468 tcg_gen_shri_i32(tmp, tmp, offset);
3469 if (insn & (1 << 23))
3470 gen_uxtb(tmp);
3471 else
3472 gen_sxtb(tmp);
3473 break;
3474 case 1:
3475 if (insn & (1 << 23)) {
3476 if (offset) {
3477 tcg_gen_shri_i32(tmp, tmp, 16);
3478 } else {
3479 gen_uxth(tmp);
3481 } else {
3482 if (offset) {
3483 tcg_gen_sari_i32(tmp, tmp, 16);
3484 } else {
3485 gen_sxth(tmp);
3488 break;
3489 case 2:
3490 break;
3492 store_reg(s, rd, tmp);
3493 } else {
3494 /* arm->vfp */
3495 tmp = load_reg(s, rd);
3496 if (insn & (1 << 23)) {
3497 /* VDUP */
3498 int vec_size = pass ? 16 : 8;
3499 tcg_gen_gvec_dup_i32(size, neon_reg_offset(rn, 0),
3500 vec_size, vec_size, tmp);
3501 tcg_temp_free_i32(tmp);
3502 } else {
3503 /* VMOV */
3504 switch (size) {
3505 case 0:
3506 tmp2 = neon_load_reg(rn, pass);
3507 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 8);
3508 tcg_temp_free_i32(tmp2);
3509 break;
3510 case 1:
3511 tmp2 = neon_load_reg(rn, pass);
3512 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 16);
3513 tcg_temp_free_i32(tmp2);
3514 break;
3515 case 2:
3516 break;
3518 neon_store_reg(rn, pass, tmp);
3521 } else { /* !dp */
3522 bool is_sysreg;
3524 if ((insn & 0x6f) != 0x00)
3525 return 1;
3526 rn = VFP_SREG_N(insn);
3528 is_sysreg = extract32(insn, 21, 1);
3530 if (arm_dc_feature(s, ARM_FEATURE_M)) {
3532 * The only M-profile VFP vmrs/vmsr sysreg is FPSCR.
3533 * Writes to R15 are UNPREDICTABLE; we choose to undef.
3535 if (is_sysreg && (rd == 15 || (rn >> 1) != ARM_VFP_FPSCR)) {
3536 return 1;
3540 if (insn & ARM_CP_RW_BIT) {
3541 /* vfp->arm */
3542 if (is_sysreg) {
3543 /* system register */
3544 rn >>= 1;
3546 switch (rn) {
3547 case ARM_VFP_FPSID:
3548 /* VFP2 allows access to FSID from userspace.
3549 VFP3 restricts all id registers to privileged
3550 accesses. */
3551 if (IS_USER(s)
3552 && arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3553 return 1;
3555 tmp = load_cpu_field(vfp.xregs[rn]);
3556 break;
3557 case ARM_VFP_FPEXC:
3558 if (IS_USER(s))
3559 return 1;
3560 tmp = load_cpu_field(vfp.xregs[rn]);
3561 break;
3562 case ARM_VFP_FPINST:
3563 case ARM_VFP_FPINST2:
3564 /* Not present in VFP3. */
3565 if (IS_USER(s)
3566 || arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3567 return 1;
3569 tmp = load_cpu_field(vfp.xregs[rn]);
3570 break;
3571 case ARM_VFP_FPSCR:
3572 if (rd == 15) {
3573 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
3574 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
3575 } else {
3576 tmp = tcg_temp_new_i32();
3577 gen_helper_vfp_get_fpscr(tmp, cpu_env);
3579 break;
3580 case ARM_VFP_MVFR2:
3581 if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
3582 return 1;
3584 /* fall through */
3585 case ARM_VFP_MVFR0:
3586 case ARM_VFP_MVFR1:
3587 if (IS_USER(s)
3588 || !arm_dc_feature(s, ARM_FEATURE_MVFR)) {
3589 return 1;
3591 tmp = load_cpu_field(vfp.xregs[rn]);
3592 break;
3593 default:
3594 return 1;
3596 } else {
3597 gen_mov_F0_vreg(0, rn);
3598 tmp = gen_vfp_mrs();
3600 if (rd == 15) {
3601 /* Set the 4 flag bits in the CPSR. */
3602 gen_set_nzcv(tmp);
3603 tcg_temp_free_i32(tmp);
3604 } else {
3605 store_reg(s, rd, tmp);
3607 } else {
3608 /* arm->vfp */
3609 if (is_sysreg) {
3610 rn >>= 1;
3611 /* system register */
3612 switch (rn) {
3613 case ARM_VFP_FPSID:
3614 case ARM_VFP_MVFR0:
3615 case ARM_VFP_MVFR1:
3616 /* Writes are ignored. */
3617 break;
3618 case ARM_VFP_FPSCR:
3619 tmp = load_reg(s, rd);
3620 gen_helper_vfp_set_fpscr(cpu_env, tmp);
3621 tcg_temp_free_i32(tmp);
3622 gen_lookup_tb(s);
3623 break;
3624 case ARM_VFP_FPEXC:
3625 if (IS_USER(s))
3626 return 1;
3627 /* TODO: VFP subarchitecture support.
3628 * For now, keep the EN bit only */
3629 tmp = load_reg(s, rd);
3630 tcg_gen_andi_i32(tmp, tmp, 1 << 30);
3631 store_cpu_field(tmp, vfp.xregs[rn]);
3632 gen_lookup_tb(s);
3633 break;
3634 case ARM_VFP_FPINST:
3635 case ARM_VFP_FPINST2:
3636 if (IS_USER(s)) {
3637 return 1;
3639 tmp = load_reg(s, rd);
3640 store_cpu_field(tmp, vfp.xregs[rn]);
3641 break;
3642 default:
3643 return 1;
3645 } else {
3646 tmp = load_reg(s, rd);
3647 gen_vfp_msr(tmp);
3648 gen_mov_vreg_F0(0, rn);
3652 } else {
3653 /* data processing */
3654 bool rd_is_dp = dp;
3655 bool rm_is_dp = dp;
3656 bool no_output = false;
3658 /* The opcode is in bits 23, 21, 20 and 6. */
3659 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
3660 rn = VFP_SREG_N(insn);
3662 if (op == 15) {
3663 /* rn is opcode, encoded as per VFP_SREG_N. */
3664 switch (rn) {
3665 case 0x00: /* vmov */
3666 case 0x01: /* vabs */
3667 case 0x02: /* vneg */
3668 case 0x03: /* vsqrt */
3669 break;
3671 case 0x04: /* vcvtb.f64.f16, vcvtb.f32.f16 */
3672 case 0x05: /* vcvtt.f64.f16, vcvtt.f32.f16 */
3674 * VCVTB, VCVTT: only present with the halfprec extension
3675 * UNPREDICTABLE if bit 8 is set prior to ARMv8
3676 * (we choose to UNDEF)
3678 if (dp) {
3679 if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
3680 return 1;
3682 } else {
3683 if (!dc_isar_feature(aa32_fp16_spconv, s)) {
3684 return 1;
3687 rm_is_dp = false;
3688 break;
3689 case 0x06: /* vcvtb.f16.f32, vcvtb.f16.f64 */
3690 case 0x07: /* vcvtt.f16.f32, vcvtt.f16.f64 */
3691 if (dp) {
3692 if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
3693 return 1;
3695 } else {
3696 if (!dc_isar_feature(aa32_fp16_spconv, s)) {
3697 return 1;
3700 rd_is_dp = false;
3701 break;
3703 case 0x08: case 0x0a: /* vcmp, vcmpz */
3704 case 0x09: case 0x0b: /* vcmpe, vcmpez */
3705 no_output = true;
3706 break;
3708 case 0x0c: /* vrintr */
3709 case 0x0d: /* vrintz */
3710 case 0x0e: /* vrintx */
3711 break;
3713 case 0x0f: /* vcvt double<->single */
3714 rd_is_dp = !dp;
3715 break;
3717 case 0x10: /* vcvt.fxx.u32 */
3718 case 0x11: /* vcvt.fxx.s32 */
3719 rm_is_dp = false;
3720 break;
3721 case 0x18: /* vcvtr.u32.fxx */
3722 case 0x19: /* vcvtz.u32.fxx */
3723 case 0x1a: /* vcvtr.s32.fxx */
3724 case 0x1b: /* vcvtz.s32.fxx */
3725 rd_is_dp = false;
3726 break;
3728 case 0x14: /* vcvt fp <-> fixed */
3729 case 0x15:
3730 case 0x16:
3731 case 0x17:
3732 case 0x1c:
3733 case 0x1d:
3734 case 0x1e:
3735 case 0x1f:
3736 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3737 return 1;
3739 /* Immediate frac_bits has same format as SREG_M. */
3740 rm_is_dp = false;
3741 break;
3743 case 0x13: /* vjcvt */
3744 if (!dp || !dc_isar_feature(aa32_jscvt, s)) {
3745 return 1;
3747 rd_is_dp = false;
3748 break;
3750 default:
3751 return 1;
3753 } else if (dp) {
3754 /* rn is register number */
3755 VFP_DREG_N(rn, insn);
3758 if (rd_is_dp) {
3759 VFP_DREG_D(rd, insn);
3760 } else {
3761 rd = VFP_SREG_D(insn);
3763 if (rm_is_dp) {
3764 VFP_DREG_M(rm, insn);
3765 } else {
3766 rm = VFP_SREG_M(insn);
3769 veclen = s->vec_len;
3770 if (op == 15 && rn > 3) {
3771 veclen = 0;
3774 /* Shut up compiler warnings. */
3775 delta_m = 0;
3776 delta_d = 0;
3777 bank_mask = 0;
3779 if (veclen > 0) {
3780 if (dp)
3781 bank_mask = 0xc;
3782 else
3783 bank_mask = 0x18;
3785 /* Figure out what type of vector operation this is. */
3786 if ((rd & bank_mask) == 0) {
3787 /* scalar */
3788 veclen = 0;
3789 } else {
3790 if (dp)
3791 delta_d = (s->vec_stride >> 1) + 1;
3792 else
3793 delta_d = s->vec_stride + 1;
3795 if ((rm & bank_mask) == 0) {
3796 /* mixed scalar/vector */
3797 delta_m = 0;
3798 } else {
3799 /* vector */
3800 delta_m = delta_d;
3805 /* Load the initial operands. */
3806 if (op == 15) {
3807 switch (rn) {
3808 case 0x08: case 0x09: /* Compare */
3809 gen_mov_F0_vreg(dp, rd);
3810 gen_mov_F1_vreg(dp, rm);
3811 break;
3812 case 0x0a: case 0x0b: /* Compare with zero */
3813 gen_mov_F0_vreg(dp, rd);
3814 gen_vfp_F1_ld0(dp);
3815 break;
3816 case 0x14: /* vcvt fp <-> fixed */
3817 case 0x15:
3818 case 0x16:
3819 case 0x17:
3820 case 0x1c:
3821 case 0x1d:
3822 case 0x1e:
3823 case 0x1f:
3824 /* Source and destination the same. */
3825 gen_mov_F0_vreg(dp, rd);
3826 break;
3827 default:
3828 /* One source operand. */
3829 gen_mov_F0_vreg(rm_is_dp, rm);
3830 break;
3832 } else {
3833 /* Two source operands. */
3834 gen_mov_F0_vreg(dp, rn);
3835 gen_mov_F1_vreg(dp, rm);
3838 for (;;) {
3839 /* Perform the calculation. */
3840 switch (op) {
3841 case 0: /* VMLA: fd + (fn * fm) */
3842 /* Note that order of inputs to the add matters for NaNs */
3843 gen_vfp_F1_mul(dp);
3844 gen_mov_F0_vreg(dp, rd);
3845 gen_vfp_add(dp);
3846 break;
3847 case 1: /* VMLS: fd + -(fn * fm) */
3848 gen_vfp_mul(dp);
3849 gen_vfp_F1_neg(dp);
3850 gen_mov_F0_vreg(dp, rd);
3851 gen_vfp_add(dp);
3852 break;
3853 case 2: /* VNMLS: -fd + (fn * fm) */
3854 /* Note that it isn't valid to replace (-A + B) with (B - A)
3855 * or similar plausible looking simplifications
3856 * because this will give wrong results for NaNs.
3858 gen_vfp_F1_mul(dp);
3859 gen_mov_F0_vreg(dp, rd);
3860 gen_vfp_neg(dp);
3861 gen_vfp_add(dp);
3862 break;
3863 case 3: /* VNMLA: -fd + -(fn * fm) */
3864 gen_vfp_mul(dp);
3865 gen_vfp_F1_neg(dp);
3866 gen_mov_F0_vreg(dp, rd);
3867 gen_vfp_neg(dp);
3868 gen_vfp_add(dp);
3869 break;
3870 case 4: /* mul: fn * fm */
3871 gen_vfp_mul(dp);
3872 break;
3873 case 5: /* nmul: -(fn * fm) */
3874 gen_vfp_mul(dp);
3875 gen_vfp_neg(dp);
3876 break;
3877 case 6: /* add: fn + fm */
3878 gen_vfp_add(dp);
3879 break;
3880 case 7: /* sub: fn - fm */
3881 gen_vfp_sub(dp);
3882 break;
3883 case 8: /* div: fn / fm */
3884 gen_vfp_div(dp);
3885 break;
3886 case 10: /* VFNMA : fd = muladd(-fd, fn, fm) */
3887 case 11: /* VFNMS : fd = muladd(-fd, -fn, fm) */
3888 case 12: /* VFMA : fd = muladd( fd, fn, fm) */
3889 case 13: /* VFMS : fd = muladd( fd, -fn, fm) */
3890 /* These are fused multiply-add, and must be done as one
3891 * floating point operation with no rounding between the
3892 * multiplication and addition steps.
3893 * NB that doing the negations here as separate steps is
3894 * correct : an input NaN should come out with its sign bit
3895 * flipped if it is a negated-input.
3897 if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
3898 return 1;
3900 if (dp) {
3901 TCGv_ptr fpst;
3902 TCGv_i64 frd;
3903 if (op & 1) {
3904 /* VFNMS, VFMS */
3905 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
3907 frd = tcg_temp_new_i64();
3908 tcg_gen_ld_f64(frd, cpu_env, vfp_reg_offset(dp, rd));
3909 if (op & 2) {
3910 /* VFNMA, VFNMS */
3911 gen_helper_vfp_negd(frd, frd);
3913 fpst = get_fpstatus_ptr(0);
3914 gen_helper_vfp_muladdd(cpu_F0d, cpu_F0d,
3915 cpu_F1d, frd, fpst);
3916 tcg_temp_free_ptr(fpst);
3917 tcg_temp_free_i64(frd);
3918 } else {
3919 TCGv_ptr fpst;
3920 TCGv_i32 frd;
3921 if (op & 1) {
3922 /* VFNMS, VFMS */
3923 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
3925 frd = tcg_temp_new_i32();
3926 tcg_gen_ld_f32(frd, cpu_env, vfp_reg_offset(dp, rd));
3927 if (op & 2) {
3928 gen_helper_vfp_negs(frd, frd);
3930 fpst = get_fpstatus_ptr(0);
3931 gen_helper_vfp_muladds(cpu_F0s, cpu_F0s,
3932 cpu_F1s, frd, fpst);
3933 tcg_temp_free_ptr(fpst);
3934 tcg_temp_free_i32(frd);
3936 break;
3937 case 14: /* fconst */
3938 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3939 return 1;
3942 n = (insn << 12) & 0x80000000;
3943 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3944 if (dp) {
3945 if (i & 0x40)
3946 i |= 0x3f80;
3947 else
3948 i |= 0x4000;
3949 n |= i << 16;
3950 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3951 } else {
3952 if (i & 0x40)
3953 i |= 0x780;
3954 else
3955 i |= 0x800;
3956 n |= i << 19;
3957 tcg_gen_movi_i32(cpu_F0s, n);
3959 break;
3960 case 15: /* extension space */
3961 switch (rn) {
3962 case 0: /* cpy */
3963 /* no-op */
3964 break;
3965 case 1: /* abs */
3966 gen_vfp_abs(dp);
3967 break;
3968 case 2: /* neg */
3969 gen_vfp_neg(dp);
3970 break;
3971 case 3: /* sqrt */
3972 gen_vfp_sqrt(dp);
3973 break;
3974 case 4: /* vcvtb.f32.f16, vcvtb.f64.f16 */
3976 TCGv_ptr fpst = get_fpstatus_ptr(false);
3977 TCGv_i32 ahp_mode = get_ahp_flag();
3978 tmp = gen_vfp_mrs();
3979 tcg_gen_ext16u_i32(tmp, tmp);
3980 if (dp) {
3981 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
3982 fpst, ahp_mode);
3983 } else {
3984 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
3985 fpst, ahp_mode);
3987 tcg_temp_free_i32(ahp_mode);
3988 tcg_temp_free_ptr(fpst);
3989 tcg_temp_free_i32(tmp);
3990 break;
3992 case 5: /* vcvtt.f32.f16, vcvtt.f64.f16 */
3994 TCGv_ptr fpst = get_fpstatus_ptr(false);
3995 TCGv_i32 ahp = get_ahp_flag();
3996 tmp = gen_vfp_mrs();
3997 tcg_gen_shri_i32(tmp, tmp, 16);
3998 if (dp) {
3999 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
4000 fpst, ahp);
4001 } else {
4002 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
4003 fpst, ahp);
4005 tcg_temp_free_i32(tmp);
4006 tcg_temp_free_i32(ahp);
4007 tcg_temp_free_ptr(fpst);
4008 break;
4010 case 6: /* vcvtb.f16.f32, vcvtb.f16.f64 */
4012 TCGv_ptr fpst = get_fpstatus_ptr(false);
4013 TCGv_i32 ahp = get_ahp_flag();
4014 tmp = tcg_temp_new_i32();
4016 if (dp) {
4017 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
4018 fpst, ahp);
4019 } else {
4020 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
4021 fpst, ahp);
4023 tcg_temp_free_i32(ahp);
4024 tcg_temp_free_ptr(fpst);
4025 gen_mov_F0_vreg(0, rd);
4026 tmp2 = gen_vfp_mrs();
4027 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
4028 tcg_gen_or_i32(tmp, tmp, tmp2);
4029 tcg_temp_free_i32(tmp2);
4030 gen_vfp_msr(tmp);
4031 break;
4033 case 7: /* vcvtt.f16.f32, vcvtt.f16.f64 */
4035 TCGv_ptr fpst = get_fpstatus_ptr(false);
4036 TCGv_i32 ahp = get_ahp_flag();
4037 tmp = tcg_temp_new_i32();
4038 if (dp) {
4039 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
4040 fpst, ahp);
4041 } else {
4042 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
4043 fpst, ahp);
4045 tcg_temp_free_i32(ahp);
4046 tcg_temp_free_ptr(fpst);
4047 tcg_gen_shli_i32(tmp, tmp, 16);
4048 gen_mov_F0_vreg(0, rd);
4049 tmp2 = gen_vfp_mrs();
4050 tcg_gen_ext16u_i32(tmp2, tmp2);
4051 tcg_gen_or_i32(tmp, tmp, tmp2);
4052 tcg_temp_free_i32(tmp2);
4053 gen_vfp_msr(tmp);
4054 break;
4056 case 8: /* cmp */
4057 gen_vfp_cmp(dp);
4058 break;
4059 case 9: /* cmpe */
4060 gen_vfp_cmpe(dp);
4061 break;
4062 case 10: /* cmpz */
4063 gen_vfp_cmp(dp);
4064 break;
4065 case 11: /* cmpez */
4066 gen_vfp_F1_ld0(dp);
4067 gen_vfp_cmpe(dp);
4068 break;
4069 case 12: /* vrintr */
4071 TCGv_ptr fpst = get_fpstatus_ptr(0);
4072 if (dp) {
4073 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
4074 } else {
4075 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
4077 tcg_temp_free_ptr(fpst);
4078 break;
4080 case 13: /* vrintz */
4082 TCGv_ptr fpst = get_fpstatus_ptr(0);
4083 TCGv_i32 tcg_rmode;
4084 tcg_rmode = tcg_const_i32(float_round_to_zero);
4085 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
4086 if (dp) {
4087 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
4088 } else {
4089 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
4091 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
4092 tcg_temp_free_i32(tcg_rmode);
4093 tcg_temp_free_ptr(fpst);
4094 break;
4096 case 14: /* vrintx */
4098 TCGv_ptr fpst = get_fpstatus_ptr(0);
4099 if (dp) {
4100 gen_helper_rintd_exact(cpu_F0d, cpu_F0d, fpst);
4101 } else {
4102 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpst);
4104 tcg_temp_free_ptr(fpst);
4105 break;
4107 case 15: /* single<->double conversion */
4108 if (dp) {
4109 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
4110 } else {
4111 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
4113 break;
4114 case 16: /* fuito */
4115 gen_vfp_uito(dp, 0);
4116 break;
4117 case 17: /* fsito */
4118 gen_vfp_sito(dp, 0);
4119 break;
4120 case 19: /* vjcvt */
4121 gen_helper_vjcvt(cpu_F0s, cpu_F0d, cpu_env);
4122 break;
4123 case 20: /* fshto */
4124 gen_vfp_shto(dp, 16 - rm, 0);
4125 break;
4126 case 21: /* fslto */
4127 gen_vfp_slto(dp, 32 - rm, 0);
4128 break;
4129 case 22: /* fuhto */
4130 gen_vfp_uhto(dp, 16 - rm, 0);
4131 break;
4132 case 23: /* fulto */
4133 gen_vfp_ulto(dp, 32 - rm, 0);
4134 break;
4135 case 24: /* ftoui */
4136 gen_vfp_toui(dp, 0);
4137 break;
4138 case 25: /* ftouiz */
4139 gen_vfp_touiz(dp, 0);
4140 break;
4141 case 26: /* ftosi */
4142 gen_vfp_tosi(dp, 0);
4143 break;
4144 case 27: /* ftosiz */
4145 gen_vfp_tosiz(dp, 0);
4146 break;
4147 case 28: /* ftosh */
4148 gen_vfp_tosh(dp, 16 - rm, 0);
4149 break;
4150 case 29: /* ftosl */
4151 gen_vfp_tosl(dp, 32 - rm, 0);
4152 break;
4153 case 30: /* ftouh */
4154 gen_vfp_touh(dp, 16 - rm, 0);
4155 break;
4156 case 31: /* ftoul */
4157 gen_vfp_toul(dp, 32 - rm, 0);
4158 break;
4159 default: /* undefined */
4160 g_assert_not_reached();
4162 break;
4163 default: /* undefined */
4164 return 1;
4167 /* Write back the result, if any. */
4168 if (!no_output) {
4169 gen_mov_vreg_F0(rd_is_dp, rd);
4172 /* break out of the loop if we have finished */
4173 if (veclen == 0) {
4174 break;
4177 if (op == 15 && delta_m == 0) {
4178 /* single source one-many */
4179 while (veclen--) {
4180 rd = ((rd + delta_d) & (bank_mask - 1))
4181 | (rd & bank_mask);
4182 gen_mov_vreg_F0(dp, rd);
4184 break;
4186 /* Setup the next operands. */
4187 veclen--;
4188 rd = ((rd + delta_d) & (bank_mask - 1))
4189 | (rd & bank_mask);
4191 if (op == 15) {
4192 /* One source operand. */
4193 rm = ((rm + delta_m) & (bank_mask - 1))
4194 | (rm & bank_mask);
4195 gen_mov_F0_vreg(dp, rm);
4196 } else {
4197 /* Two source operands. */
4198 rn = ((rn + delta_d) & (bank_mask - 1))
4199 | (rn & bank_mask);
4200 gen_mov_F0_vreg(dp, rn);
4201 if (delta_m) {
4202 rm = ((rm + delta_m) & (bank_mask - 1))
4203 | (rm & bank_mask);
4204 gen_mov_F1_vreg(dp, rm);
4209 break;
4210 case 0xc:
4211 case 0xd:
4212 if ((insn & 0x03e00000) == 0x00400000) {
4213 /* two-register transfer */
4214 rn = (insn >> 16) & 0xf;
4215 rd = (insn >> 12) & 0xf;
4216 if (dp) {
4217 VFP_DREG_M(rm, insn);
4218 } else {
4219 rm = VFP_SREG_M(insn);
4222 if (insn & ARM_CP_RW_BIT) {
4223 /* vfp->arm */
4224 if (dp) {
4225 gen_mov_F0_vreg(0, rm * 2);
4226 tmp = gen_vfp_mrs();
4227 store_reg(s, rd, tmp);
4228 gen_mov_F0_vreg(0, rm * 2 + 1);
4229 tmp = gen_vfp_mrs();
4230 store_reg(s, rn, tmp);
4231 } else {
4232 gen_mov_F0_vreg(0, rm);
4233 tmp = gen_vfp_mrs();
4234 store_reg(s, rd, tmp);
4235 gen_mov_F0_vreg(0, rm + 1);
4236 tmp = gen_vfp_mrs();
4237 store_reg(s, rn, tmp);
4239 } else {
4240 /* arm->vfp */
4241 if (dp) {
4242 tmp = load_reg(s, rd);
4243 gen_vfp_msr(tmp);
4244 gen_mov_vreg_F0(0, rm * 2);
4245 tmp = load_reg(s, rn);
4246 gen_vfp_msr(tmp);
4247 gen_mov_vreg_F0(0, rm * 2 + 1);
4248 } else {
4249 tmp = load_reg(s, rd);
4250 gen_vfp_msr(tmp);
4251 gen_mov_vreg_F0(0, rm);
4252 tmp = load_reg(s, rn);
4253 gen_vfp_msr(tmp);
4254 gen_mov_vreg_F0(0, rm + 1);
4257 } else {
4258 /* Load/store */
4259 rn = (insn >> 16) & 0xf;
4260 if (dp)
4261 VFP_DREG_D(rd, insn);
4262 else
4263 rd = VFP_SREG_D(insn);
4264 if ((insn & 0x01200000) == 0x01000000) {
4265 /* Single load/store */
4266 offset = (insn & 0xff) << 2;
4267 if ((insn & (1 << 23)) == 0)
4268 offset = -offset;
4269 if (s->thumb && rn == 15) {
4270 /* This is actually UNPREDICTABLE */
4271 addr = tcg_temp_new_i32();
4272 tcg_gen_movi_i32(addr, s->pc & ~2);
4273 } else {
4274 addr = load_reg(s, rn);
4276 tcg_gen_addi_i32(addr, addr, offset);
4277 if (insn & (1 << 20)) {
4278 gen_vfp_ld(s, dp, addr);
4279 gen_mov_vreg_F0(dp, rd);
4280 } else {
4281 gen_mov_F0_vreg(dp, rd);
4282 gen_vfp_st(s, dp, addr);
4284 tcg_temp_free_i32(addr);
4285 } else {
4286 /* load/store multiple */
4287 int w = insn & (1 << 21);
4288 if (dp)
4289 n = (insn >> 1) & 0x7f;
4290 else
4291 n = insn & 0xff;
4293 if (w && !(((insn >> 23) ^ (insn >> 24)) & 1)) {
4294 /* P == U , W == 1 => UNDEF */
4295 return 1;
4297 if (n == 0 || (rd + n) > 32 || (dp && n > 16)) {
4298 /* UNPREDICTABLE cases for bad immediates: we choose to
4299 * UNDEF to avoid generating huge numbers of TCG ops
4301 return 1;
4303 if (rn == 15 && w) {
4304 /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
4305 return 1;
4308 if (s->thumb && rn == 15) {
4309 /* This is actually UNPREDICTABLE */
4310 addr = tcg_temp_new_i32();
4311 tcg_gen_movi_i32(addr, s->pc & ~2);
4312 } else {
4313 addr = load_reg(s, rn);
4315 if (insn & (1 << 24)) /* pre-decrement */
4316 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
4318 if (s->v8m_stackcheck && rn == 13 && w) {
4320 * Here 'addr' is the lowest address we will store to,
4321 * and is either the old SP (if post-increment) or
4322 * the new SP (if pre-decrement). For post-increment
4323 * where the old value is below the limit and the new
4324 * value is above, it is UNKNOWN whether the limit check
4325 * triggers; we choose to trigger.
4327 gen_helper_v8m_stackcheck(cpu_env, addr);
4330 if (dp)
4331 offset = 8;
4332 else
4333 offset = 4;
4334 for (i = 0; i < n; i++) {
4335 if (insn & ARM_CP_RW_BIT) {
4336 /* load */
4337 gen_vfp_ld(s, dp, addr);
4338 gen_mov_vreg_F0(dp, rd + i);
4339 } else {
4340 /* store */
4341 gen_mov_F0_vreg(dp, rd + i);
4342 gen_vfp_st(s, dp, addr);
4344 tcg_gen_addi_i32(addr, addr, offset);
4346 if (w) {
4347 /* writeback */
4348 if (insn & (1 << 24))
4349 offset = -offset * n;
4350 else if (dp && (insn & 1))
4351 offset = 4;
4352 else
4353 offset = 0;
4355 if (offset != 0)
4356 tcg_gen_addi_i32(addr, addr, offset);
4357 store_reg(s, rn, addr);
4358 } else {
4359 tcg_temp_free_i32(addr);
4363 break;
4364 default:
4365 /* Should never happen. */
4366 return 1;
4368 return 0;
4371 static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
4373 #ifndef CONFIG_USER_ONLY
4374 return (s->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
4375 ((s->pc - 1) & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
4376 #else
4377 return true;
4378 #endif
4381 static void gen_goto_ptr(void)
4383 tcg_gen_lookup_and_goto_ptr();
4386 /* This will end the TB but doesn't guarantee we'll return to
4387 * cpu_loop_exec. Any live exit_requests will be processed as we
4388 * enter the next TB.
4390 static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
4392 if (use_goto_tb(s, dest)) {
4393 tcg_gen_goto_tb(n);
4394 gen_set_pc_im(s, dest);
4395 tcg_gen_exit_tb(s->base.tb, n);
4396 } else {
4397 gen_set_pc_im(s, dest);
4398 gen_goto_ptr();
4400 s->base.is_jmp = DISAS_NORETURN;
4403 static inline void gen_jmp (DisasContext *s, uint32_t dest)
4405 if (unlikely(is_singlestepping(s))) {
4406 /* An indirect jump so that we still trigger the debug exception. */
4407 if (s->thumb)
4408 dest |= 1;
4409 gen_bx_im(s, dest);
4410 } else {
4411 gen_goto_tb(s, 0, dest);
4415 static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
4417 if (x)
4418 tcg_gen_sari_i32(t0, t0, 16);
4419 else
4420 gen_sxth(t0);
4421 if (y)
4422 tcg_gen_sari_i32(t1, t1, 16);
4423 else
4424 gen_sxth(t1);
4425 tcg_gen_mul_i32(t0, t0, t1);
4428 /* Return the mask of PSR bits set by a MSR instruction. */
4429 static uint32_t msr_mask(DisasContext *s, int flags, int spsr)
4431 uint32_t mask;
4433 mask = 0;
4434 if (flags & (1 << 0))
4435 mask |= 0xff;
4436 if (flags & (1 << 1))
4437 mask |= 0xff00;
4438 if (flags & (1 << 2))
4439 mask |= 0xff0000;
4440 if (flags & (1 << 3))
4441 mask |= 0xff000000;
4443 /* Mask out undefined bits. */
4444 mask &= ~CPSR_RESERVED;
4445 if (!arm_dc_feature(s, ARM_FEATURE_V4T)) {
4446 mask &= ~CPSR_T;
4448 if (!arm_dc_feature(s, ARM_FEATURE_V5)) {
4449 mask &= ~CPSR_Q; /* V5TE in reality*/
4451 if (!arm_dc_feature(s, ARM_FEATURE_V6)) {
4452 mask &= ~(CPSR_E | CPSR_GE);
4454 if (!arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
4455 mask &= ~CPSR_IT;
4457 /* Mask out execution state and reserved bits. */
4458 if (!spsr) {
4459 mask &= ~(CPSR_EXEC | CPSR_RESERVED);
4461 /* Mask out privileged bits. */
4462 if (IS_USER(s))
4463 mask &= CPSR_USER;
4464 return mask;
4467 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
4468 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
4470 TCGv_i32 tmp;
4471 if (spsr) {
4472 /* ??? This is also undefined in system mode. */
4473 if (IS_USER(s))
4474 return 1;
4476 tmp = load_cpu_field(spsr);
4477 tcg_gen_andi_i32(tmp, tmp, ~mask);
4478 tcg_gen_andi_i32(t0, t0, mask);
4479 tcg_gen_or_i32(tmp, tmp, t0);
4480 store_cpu_field(tmp, spsr);
4481 } else {
4482 gen_set_cpsr(t0, mask);
4484 tcg_temp_free_i32(t0);
4485 gen_lookup_tb(s);
4486 return 0;
4489 /* Returns nonzero if access to the PSR is not permitted. */
4490 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
4492 TCGv_i32 tmp;
4493 tmp = tcg_temp_new_i32();
4494 tcg_gen_movi_i32(tmp, val);
4495 return gen_set_psr(s, mask, spsr, tmp);
4498 static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
4499 int *tgtmode, int *regno)
4501 /* Decode the r and sysm fields of MSR/MRS banked accesses into
4502 * the target mode and register number, and identify the various
4503 * unpredictable cases.
4504 * MSR (banked) and MRS (banked) are CONSTRAINED UNPREDICTABLE if:
4505 * + executed in user mode
4506 * + using R15 as the src/dest register
4507 * + accessing an unimplemented register
4508 * + accessing a register that's inaccessible at current PL/security state*
4509 * + accessing a register that you could access with a different insn
4510 * We choose to UNDEF in all these cases.
4511 * Since we don't know which of the various AArch32 modes we are in
4512 * we have to defer some checks to runtime.
4513 * Accesses to Monitor mode registers from Secure EL1 (which implies
4514 * that EL3 is AArch64) must trap to EL3.
4516 * If the access checks fail this function will emit code to take
4517 * an exception and return false. Otherwise it will return true,
4518 * and set *tgtmode and *regno appropriately.
4520 int exc_target = default_exception_el(s);
4522 /* These instructions are present only in ARMv8, or in ARMv7 with the
4523 * Virtualization Extensions.
4525 if (!arm_dc_feature(s, ARM_FEATURE_V8) &&
4526 !arm_dc_feature(s, ARM_FEATURE_EL2)) {
4527 goto undef;
4530 if (IS_USER(s) || rn == 15) {
4531 goto undef;
4534 /* The table in the v8 ARM ARM section F5.2.3 describes the encoding
4535 * of registers into (r, sysm).
4537 if (r) {
4538 /* SPSRs for other modes */
4539 switch (sysm) {
4540 case 0xe: /* SPSR_fiq */
4541 *tgtmode = ARM_CPU_MODE_FIQ;
4542 break;
4543 case 0x10: /* SPSR_irq */
4544 *tgtmode = ARM_CPU_MODE_IRQ;
4545 break;
4546 case 0x12: /* SPSR_svc */
4547 *tgtmode = ARM_CPU_MODE_SVC;
4548 break;
4549 case 0x14: /* SPSR_abt */
4550 *tgtmode = ARM_CPU_MODE_ABT;
4551 break;
4552 case 0x16: /* SPSR_und */
4553 *tgtmode = ARM_CPU_MODE_UND;
4554 break;
4555 case 0x1c: /* SPSR_mon */
4556 *tgtmode = ARM_CPU_MODE_MON;
4557 break;
4558 case 0x1e: /* SPSR_hyp */
4559 *tgtmode = ARM_CPU_MODE_HYP;
4560 break;
4561 default: /* unallocated */
4562 goto undef;
4564 /* We arbitrarily assign SPSR a register number of 16. */
4565 *regno = 16;
4566 } else {
4567 /* general purpose registers for other modes */
4568 switch (sysm) {
4569 case 0x0 ... 0x6: /* 0b00xxx : r8_usr ... r14_usr */
4570 *tgtmode = ARM_CPU_MODE_USR;
4571 *regno = sysm + 8;
4572 break;
4573 case 0x8 ... 0xe: /* 0b01xxx : r8_fiq ... r14_fiq */
4574 *tgtmode = ARM_CPU_MODE_FIQ;
4575 *regno = sysm;
4576 break;
4577 case 0x10 ... 0x11: /* 0b1000x : r14_irq, r13_irq */
4578 *tgtmode = ARM_CPU_MODE_IRQ;
4579 *regno = sysm & 1 ? 13 : 14;
4580 break;
4581 case 0x12 ... 0x13: /* 0b1001x : r14_svc, r13_svc */
4582 *tgtmode = ARM_CPU_MODE_SVC;
4583 *regno = sysm & 1 ? 13 : 14;
4584 break;
4585 case 0x14 ... 0x15: /* 0b1010x : r14_abt, r13_abt */
4586 *tgtmode = ARM_CPU_MODE_ABT;
4587 *regno = sysm & 1 ? 13 : 14;
4588 break;
4589 case 0x16 ... 0x17: /* 0b1011x : r14_und, r13_und */
4590 *tgtmode = ARM_CPU_MODE_UND;
4591 *regno = sysm & 1 ? 13 : 14;
4592 break;
4593 case 0x1c ... 0x1d: /* 0b1110x : r14_mon, r13_mon */
4594 *tgtmode = ARM_CPU_MODE_MON;
4595 *regno = sysm & 1 ? 13 : 14;
4596 break;
4597 case 0x1e ... 0x1f: /* 0b1111x : elr_hyp, r13_hyp */
4598 *tgtmode = ARM_CPU_MODE_HYP;
4599 /* Arbitrarily pick 17 for ELR_Hyp (which is not a banked LR!) */
4600 *regno = sysm & 1 ? 13 : 17;
4601 break;
4602 default: /* unallocated */
4603 goto undef;
4607 /* Catch the 'accessing inaccessible register' cases we can detect
4608 * at translate time.
4610 switch (*tgtmode) {
4611 case ARM_CPU_MODE_MON:
4612 if (!arm_dc_feature(s, ARM_FEATURE_EL3) || s->ns) {
4613 goto undef;
4615 if (s->current_el == 1) {
4616 /* If we're in Secure EL1 (which implies that EL3 is AArch64)
4617 * then accesses to Mon registers trap to EL3
4619 exc_target = 3;
4620 goto undef;
4622 break;
4623 case ARM_CPU_MODE_HYP:
4625 * SPSR_hyp and r13_hyp can only be accessed from Monitor mode
4626 * (and so we can forbid accesses from EL2 or below). elr_hyp
4627 * can be accessed also from Hyp mode, so forbid accesses from
4628 * EL0 or EL1.
4630 if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el < 2 ||
4631 (s->current_el < 3 && *regno != 17)) {
4632 goto undef;
4634 break;
4635 default:
4636 break;
4639 return true;
4641 undef:
4642 /* If we get here then some access check did not pass */
4643 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), exc_target);
4644 return false;
4647 static void gen_msr_banked(DisasContext *s, int r, int sysm, int rn)
4649 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
4650 int tgtmode = 0, regno = 0;
4652 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
4653 return;
4656 /* Sync state because msr_banked() can raise exceptions */
4657 gen_set_condexec(s);
4658 gen_set_pc_im(s, s->pc - 4);
4659 tcg_reg = load_reg(s, rn);
4660 tcg_tgtmode = tcg_const_i32(tgtmode);
4661 tcg_regno = tcg_const_i32(regno);
4662 gen_helper_msr_banked(cpu_env, tcg_reg, tcg_tgtmode, tcg_regno);
4663 tcg_temp_free_i32(tcg_tgtmode);
4664 tcg_temp_free_i32(tcg_regno);
4665 tcg_temp_free_i32(tcg_reg);
4666 s->base.is_jmp = DISAS_UPDATE;
4669 static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn)
4671 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
4672 int tgtmode = 0, regno = 0;
4674 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
4675 return;
4678 /* Sync state because mrs_banked() can raise exceptions */
4679 gen_set_condexec(s);
4680 gen_set_pc_im(s, s->pc - 4);
4681 tcg_reg = tcg_temp_new_i32();
4682 tcg_tgtmode = tcg_const_i32(tgtmode);
4683 tcg_regno = tcg_const_i32(regno);
4684 gen_helper_mrs_banked(tcg_reg, cpu_env, tcg_tgtmode, tcg_regno);
4685 tcg_temp_free_i32(tcg_tgtmode);
4686 tcg_temp_free_i32(tcg_regno);
4687 store_reg(s, rn, tcg_reg);
4688 s->base.is_jmp = DISAS_UPDATE;
4691 /* Store value to PC as for an exception return (ie don't
4692 * mask bits). The subsequent call to gen_helper_cpsr_write_eret()
4693 * will do the masking based on the new value of the Thumb bit.
4695 static void store_pc_exc_ret(DisasContext *s, TCGv_i32 pc)
4697 tcg_gen_mov_i32(cpu_R[15], pc);
4698 tcg_temp_free_i32(pc);
4701 /* Generate a v6 exception return. Marks both values as dead. */
4702 static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
4704 store_pc_exc_ret(s, pc);
4705 /* The cpsr_write_eret helper will mask the low bits of PC
4706 * appropriately depending on the new Thumb bit, so it must
4707 * be called after storing the new PC.
4709 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
4710 gen_io_start();
4712 gen_helper_cpsr_write_eret(cpu_env, cpsr);
4713 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
4714 gen_io_end();
4716 tcg_temp_free_i32(cpsr);
4717 /* Must exit loop to check un-masked IRQs */
4718 s->base.is_jmp = DISAS_EXIT;
4721 /* Generate an old-style exception return. Marks pc as dead. */
4722 static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
4724 gen_rfe(s, pc, load_cpu_field(spsr));
4728 * For WFI we will halt the vCPU until an IRQ. For WFE and YIELD we
4729 * only call the helper when running single threaded TCG code to ensure
4730 * the next round-robin scheduled vCPU gets a crack. In MTTCG mode we
4731 * just skip this instruction. Currently the SEV/SEVL instructions
4732 * which are *one* of many ways to wake the CPU from WFE are not
4733 * implemented so we can't sleep like WFI does.
4735 static void gen_nop_hint(DisasContext *s, int val)
4737 switch (val) {
4738 /* When running in MTTCG we don't generate jumps to the yield and
4739 * WFE helpers as it won't affect the scheduling of other vCPUs.
4740 * If we wanted to more completely model WFE/SEV so we don't busy
4741 * spin unnecessarily we would need to do something more involved.
4743 case 1: /* yield */
4744 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
4745 gen_set_pc_im(s, s->pc);
4746 s->base.is_jmp = DISAS_YIELD;
4748 break;
4749 case 3: /* wfi */
4750 gen_set_pc_im(s, s->pc);
4751 s->base.is_jmp = DISAS_WFI;
4752 break;
4753 case 2: /* wfe */
4754 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
4755 gen_set_pc_im(s, s->pc);
4756 s->base.is_jmp = DISAS_WFE;
4758 break;
4759 case 4: /* sev */
4760 case 5: /* sevl */
4761 /* TODO: Implement SEV, SEVL and WFE. May help SMP performance. */
4762 default: /* nop */
4763 break;
4767 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
4769 static inline void gen_neon_add(int size, TCGv_i32 t0, TCGv_i32 t1)
4771 switch (size) {
4772 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
4773 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
4774 case 2: tcg_gen_add_i32(t0, t0, t1); break;
4775 default: abort();
4779 static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
4781 switch (size) {
4782 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
4783 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
4784 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
4785 default: return;
4789 /* 32-bit pairwise ops end up the same as the elementwise versions. */
4790 #define gen_helper_neon_pmax_s32 tcg_gen_smax_i32
4791 #define gen_helper_neon_pmax_u32 tcg_gen_umax_i32
4792 #define gen_helper_neon_pmin_s32 tcg_gen_smin_i32
4793 #define gen_helper_neon_pmin_u32 tcg_gen_umin_i32
4795 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
4796 switch ((size << 1) | u) { \
4797 case 0: \
4798 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
4799 break; \
4800 case 1: \
4801 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
4802 break; \
4803 case 2: \
4804 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
4805 break; \
4806 case 3: \
4807 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
4808 break; \
4809 case 4: \
4810 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
4811 break; \
4812 case 5: \
4813 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
4814 break; \
4815 default: return 1; \
4816 }} while (0)
4818 #define GEN_NEON_INTEGER_OP(name) do { \
4819 switch ((size << 1) | u) { \
4820 case 0: \
4821 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
4822 break; \
4823 case 1: \
4824 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
4825 break; \
4826 case 2: \
4827 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
4828 break; \
4829 case 3: \
4830 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
4831 break; \
4832 case 4: \
4833 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
4834 break; \
4835 case 5: \
4836 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
4837 break; \
4838 default: return 1; \
4839 }} while (0)
4841 static TCGv_i32 neon_load_scratch(int scratch)
4843 TCGv_i32 tmp = tcg_temp_new_i32();
4844 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
4845 return tmp;
4848 static void neon_store_scratch(int scratch, TCGv_i32 var)
4850 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
4851 tcg_temp_free_i32(var);
4854 static inline TCGv_i32 neon_get_scalar(int size, int reg)
4856 TCGv_i32 tmp;
4857 if (size == 1) {
4858 tmp = neon_load_reg(reg & 7, reg >> 4);
4859 if (reg & 8) {
4860 gen_neon_dup_high16(tmp);
4861 } else {
4862 gen_neon_dup_low16(tmp);
4864 } else {
4865 tmp = neon_load_reg(reg & 15, reg >> 4);
4867 return tmp;
4870 static int gen_neon_unzip(int rd, int rm, int size, int q)
4872 TCGv_ptr pd, pm;
4874 if (!q && size == 2) {
4875 return 1;
4877 pd = vfp_reg_ptr(true, rd);
4878 pm = vfp_reg_ptr(true, rm);
4879 if (q) {
4880 switch (size) {
4881 case 0:
4882 gen_helper_neon_qunzip8(pd, pm);
4883 break;
4884 case 1:
4885 gen_helper_neon_qunzip16(pd, pm);
4886 break;
4887 case 2:
4888 gen_helper_neon_qunzip32(pd, pm);
4889 break;
4890 default:
4891 abort();
4893 } else {
4894 switch (size) {
4895 case 0:
4896 gen_helper_neon_unzip8(pd, pm);
4897 break;
4898 case 1:
4899 gen_helper_neon_unzip16(pd, pm);
4900 break;
4901 default:
4902 abort();
4905 tcg_temp_free_ptr(pd);
4906 tcg_temp_free_ptr(pm);
4907 return 0;
4910 static int gen_neon_zip(int rd, int rm, int size, int q)
4912 TCGv_ptr pd, pm;
4914 if (!q && size == 2) {
4915 return 1;
4917 pd = vfp_reg_ptr(true, rd);
4918 pm = vfp_reg_ptr(true, rm);
4919 if (q) {
4920 switch (size) {
4921 case 0:
4922 gen_helper_neon_qzip8(pd, pm);
4923 break;
4924 case 1:
4925 gen_helper_neon_qzip16(pd, pm);
4926 break;
4927 case 2:
4928 gen_helper_neon_qzip32(pd, pm);
4929 break;
4930 default:
4931 abort();
4933 } else {
4934 switch (size) {
4935 case 0:
4936 gen_helper_neon_zip8(pd, pm);
4937 break;
4938 case 1:
4939 gen_helper_neon_zip16(pd, pm);
4940 break;
4941 default:
4942 abort();
4945 tcg_temp_free_ptr(pd);
4946 tcg_temp_free_ptr(pm);
4947 return 0;
4950 static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
4952 TCGv_i32 rd, tmp;
4954 rd = tcg_temp_new_i32();
4955 tmp = tcg_temp_new_i32();
4957 tcg_gen_shli_i32(rd, t0, 8);
4958 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
4959 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
4960 tcg_gen_or_i32(rd, rd, tmp);
4962 tcg_gen_shri_i32(t1, t1, 8);
4963 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
4964 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
4965 tcg_gen_or_i32(t1, t1, tmp);
4966 tcg_gen_mov_i32(t0, rd);
4968 tcg_temp_free_i32(tmp);
4969 tcg_temp_free_i32(rd);
4972 static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
4974 TCGv_i32 rd, tmp;
4976 rd = tcg_temp_new_i32();
4977 tmp = tcg_temp_new_i32();
4979 tcg_gen_shli_i32(rd, t0, 16);
4980 tcg_gen_andi_i32(tmp, t1, 0xffff);
4981 tcg_gen_or_i32(rd, rd, tmp);
4982 tcg_gen_shri_i32(t1, t1, 16);
4983 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
4984 tcg_gen_or_i32(t1, t1, tmp);
4985 tcg_gen_mov_i32(t0, rd);
4987 tcg_temp_free_i32(tmp);
4988 tcg_temp_free_i32(rd);
4992 static struct {
4993 int nregs;
4994 int interleave;
4995 int spacing;
4996 } const neon_ls_element_type[11] = {
4997 {1, 4, 1},
4998 {1, 4, 2},
4999 {4, 1, 1},
5000 {2, 2, 2},
5001 {1, 3, 1},
5002 {1, 3, 2},
5003 {3, 1, 1},
5004 {1, 1, 1},
5005 {1, 2, 1},
5006 {1, 2, 2},
5007 {2, 1, 1}
5010 /* Translate a NEON load/store element instruction. Return nonzero if the
5011 instruction is invalid. */
5012 static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
5014 int rd, rn, rm;
5015 int op;
5016 int nregs;
5017 int interleave;
5018 int spacing;
5019 int stride;
5020 int size;
5021 int reg;
5022 int load;
5023 int n;
5024 int vec_size;
5025 int mmu_idx;
5026 TCGMemOp endian;
5027 TCGv_i32 addr;
5028 TCGv_i32 tmp;
5029 TCGv_i32 tmp2;
5030 TCGv_i64 tmp64;
5032 /* FIXME: this access check should not take precedence over UNDEF
5033 * for invalid encodings; we will generate incorrect syndrome information
5034 * for attempts to execute invalid vfp/neon encodings with FP disabled.
5036 if (s->fp_excp_el) {
5037 gen_exception_insn(s, 4, EXCP_UDEF,
5038 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
5039 return 0;
5042 if (!s->vfp_enabled)
5043 return 1;
5044 VFP_DREG_D(rd, insn);
5045 rn = (insn >> 16) & 0xf;
5046 rm = insn & 0xf;
5047 load = (insn & (1 << 21)) != 0;
5048 endian = s->be_data;
5049 mmu_idx = get_mem_index(s);
5050 if ((insn & (1 << 23)) == 0) {
5051 /* Load store all elements. */
5052 op = (insn >> 8) & 0xf;
5053 size = (insn >> 6) & 3;
5054 if (op > 10)
5055 return 1;
5056 /* Catch UNDEF cases for bad values of align field */
5057 switch (op & 0xc) {
5058 case 4:
5059 if (((insn >> 5) & 1) == 1) {
5060 return 1;
5062 break;
5063 case 8:
5064 if (((insn >> 4) & 3) == 3) {
5065 return 1;
5067 break;
5068 default:
5069 break;
5071 nregs = neon_ls_element_type[op].nregs;
5072 interleave = neon_ls_element_type[op].interleave;
5073 spacing = neon_ls_element_type[op].spacing;
5074 if (size == 3 && (interleave | spacing) != 1) {
5075 return 1;
5077 /* For our purposes, bytes are always little-endian. */
5078 if (size == 0) {
5079 endian = MO_LE;
5081 /* Consecutive little-endian elements from a single register
5082 * can be promoted to a larger little-endian operation.
5084 if (interleave == 1 && endian == MO_LE) {
5085 size = 3;
5087 tmp64 = tcg_temp_new_i64();
5088 addr = tcg_temp_new_i32();
5089 tmp2 = tcg_const_i32(1 << size);
5090 load_reg_var(s, addr, rn);
5091 for (reg = 0; reg < nregs; reg++) {
5092 for (n = 0; n < 8 >> size; n++) {
5093 int xs;
5094 for (xs = 0; xs < interleave; xs++) {
5095 int tt = rd + reg + spacing * xs;
5097 if (load) {
5098 gen_aa32_ld_i64(s, tmp64, addr, mmu_idx, endian | size);
5099 neon_store_element64(tt, n, size, tmp64);
5100 } else {
5101 neon_load_element64(tmp64, tt, n, size);
5102 gen_aa32_st_i64(s, tmp64, addr, mmu_idx, endian | size);
5104 tcg_gen_add_i32(addr, addr, tmp2);
5108 tcg_temp_free_i32(addr);
5109 tcg_temp_free_i32(tmp2);
5110 tcg_temp_free_i64(tmp64);
5111 stride = nregs * interleave * 8;
5112 } else {
5113 size = (insn >> 10) & 3;
5114 if (size == 3) {
5115 /* Load single element to all lanes. */
5116 int a = (insn >> 4) & 1;
5117 if (!load) {
5118 return 1;
5120 size = (insn >> 6) & 3;
5121 nregs = ((insn >> 8) & 3) + 1;
5123 if (size == 3) {
5124 if (nregs != 4 || a == 0) {
5125 return 1;
5127 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
5128 size = 2;
5130 if (nregs == 1 && a == 1 && size == 0) {
5131 return 1;
5133 if (nregs == 3 && a == 1) {
5134 return 1;
5136 addr = tcg_temp_new_i32();
5137 load_reg_var(s, addr, rn);
5139 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write.
5140 * VLD2/3/4 to all lanes: bit 5 indicates register stride.
5142 stride = (insn & (1 << 5)) ? 2 : 1;
5143 vec_size = nregs == 1 ? stride * 8 : 8;
5145 tmp = tcg_temp_new_i32();
5146 for (reg = 0; reg < nregs; reg++) {
5147 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
5148 s->be_data | size);
5149 if ((rd & 1) && vec_size == 16) {
5150 /* We cannot write 16 bytes at once because the
5151 * destination is unaligned.
5153 tcg_gen_gvec_dup_i32(size, neon_reg_offset(rd, 0),
5154 8, 8, tmp);
5155 tcg_gen_gvec_mov(0, neon_reg_offset(rd + 1, 0),
5156 neon_reg_offset(rd, 0), 8, 8);
5157 } else {
5158 tcg_gen_gvec_dup_i32(size, neon_reg_offset(rd, 0),
5159 vec_size, vec_size, tmp);
5161 tcg_gen_addi_i32(addr, addr, 1 << size);
5162 rd += stride;
5164 tcg_temp_free_i32(tmp);
5165 tcg_temp_free_i32(addr);
5166 stride = (1 << size) * nregs;
5167 } else {
5168 /* Single element. */
5169 int idx = (insn >> 4) & 0xf;
5170 int reg_idx;
5171 switch (size) {
5172 case 0:
5173 reg_idx = (insn >> 5) & 7;
5174 stride = 1;
5175 break;
5176 case 1:
5177 reg_idx = (insn >> 6) & 3;
5178 stride = (insn & (1 << 5)) ? 2 : 1;
5179 break;
5180 case 2:
5181 reg_idx = (insn >> 7) & 1;
5182 stride = (insn & (1 << 6)) ? 2 : 1;
5183 break;
5184 default:
5185 abort();
5187 nregs = ((insn >> 8) & 3) + 1;
5188 /* Catch the UNDEF cases. This is unavoidably a bit messy. */
5189 switch (nregs) {
5190 case 1:
5191 if (((idx & (1 << size)) != 0) ||
5192 (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
5193 return 1;
5195 break;
5196 case 3:
5197 if ((idx & 1) != 0) {
5198 return 1;
5200 /* fall through */
5201 case 2:
5202 if (size == 2 && (idx & 2) != 0) {
5203 return 1;
5205 break;
5206 case 4:
5207 if ((size == 2) && ((idx & 3) == 3)) {
5208 return 1;
5210 break;
5211 default:
5212 abort();
5214 if ((rd + stride * (nregs - 1)) > 31) {
5215 /* Attempts to write off the end of the register file
5216 * are UNPREDICTABLE; we choose to UNDEF because otherwise
5217 * the neon_load_reg() would write off the end of the array.
5219 return 1;
5221 tmp = tcg_temp_new_i32();
5222 addr = tcg_temp_new_i32();
5223 load_reg_var(s, addr, rn);
5224 for (reg = 0; reg < nregs; reg++) {
5225 if (load) {
5226 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
5227 s->be_data | size);
5228 neon_store_element(rd, reg_idx, size, tmp);
5229 } else { /* Store */
5230 neon_load_element(tmp, rd, reg_idx, size);
5231 gen_aa32_st_i32(s, tmp, addr, get_mem_index(s),
5232 s->be_data | size);
5234 rd += stride;
5235 tcg_gen_addi_i32(addr, addr, 1 << size);
5237 tcg_temp_free_i32(addr);
5238 tcg_temp_free_i32(tmp);
5239 stride = nregs * (1 << size);
5242 if (rm != 15) {
5243 TCGv_i32 base;
5245 base = load_reg(s, rn);
5246 if (rm == 13) {
5247 tcg_gen_addi_i32(base, base, stride);
5248 } else {
5249 TCGv_i32 index;
5250 index = load_reg(s, rm);
5251 tcg_gen_add_i32(base, base, index);
5252 tcg_temp_free_i32(index);
5254 store_reg(s, rn, base);
5256 return 0;
5259 static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src)
5261 switch (size) {
5262 case 0: gen_helper_neon_narrow_u8(dest, src); break;
5263 case 1: gen_helper_neon_narrow_u16(dest, src); break;
5264 case 2: tcg_gen_extrl_i64_i32(dest, src); break;
5265 default: abort();
5269 static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
5271 switch (size) {
5272 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
5273 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
5274 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
5275 default: abort();
5279 static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src)
5281 switch (size) {
5282 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
5283 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
5284 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
5285 default: abort();
5289 static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
5291 switch (size) {
5292 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
5293 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
5294 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
5295 default: abort();
5299 static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift,
5300 int q, int u)
5302 if (q) {
5303 if (u) {
5304 switch (size) {
5305 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
5306 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
5307 default: abort();
5309 } else {
5310 switch (size) {
5311 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
5312 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
5313 default: abort();
5316 } else {
5317 if (u) {
5318 switch (size) {
5319 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
5320 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
5321 default: abort();
5323 } else {
5324 switch (size) {
5325 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
5326 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
5327 default: abort();
5333 static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
5335 if (u) {
5336 switch (size) {
5337 case 0: gen_helper_neon_widen_u8(dest, src); break;
5338 case 1: gen_helper_neon_widen_u16(dest, src); break;
5339 case 2: tcg_gen_extu_i32_i64(dest, src); break;
5340 default: abort();
5342 } else {
5343 switch (size) {
5344 case 0: gen_helper_neon_widen_s8(dest, src); break;
5345 case 1: gen_helper_neon_widen_s16(dest, src); break;
5346 case 2: tcg_gen_ext_i32_i64(dest, src); break;
5347 default: abort();
5350 tcg_temp_free_i32(src);
5353 static inline void gen_neon_addl(int size)
5355 switch (size) {
5356 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
5357 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
5358 case 2: tcg_gen_add_i64(CPU_V001); break;
5359 default: abort();
5363 static inline void gen_neon_subl(int size)
5365 switch (size) {
5366 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
5367 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
5368 case 2: tcg_gen_sub_i64(CPU_V001); break;
5369 default: abort();
5373 static inline void gen_neon_negl(TCGv_i64 var, int size)
5375 switch (size) {
5376 case 0: gen_helper_neon_negl_u16(var, var); break;
5377 case 1: gen_helper_neon_negl_u32(var, var); break;
5378 case 2:
5379 tcg_gen_neg_i64(var, var);
5380 break;
5381 default: abort();
5385 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
5387 switch (size) {
5388 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
5389 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
5390 default: abort();
5394 static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b,
5395 int size, int u)
5397 TCGv_i64 tmp;
5399 switch ((size << 1) | u) {
5400 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
5401 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
5402 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
5403 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
5404 case 4:
5405 tmp = gen_muls_i64_i32(a, b);
5406 tcg_gen_mov_i64(dest, tmp);
5407 tcg_temp_free_i64(tmp);
5408 break;
5409 case 5:
5410 tmp = gen_mulu_i64_i32(a, b);
5411 tcg_gen_mov_i64(dest, tmp);
5412 tcg_temp_free_i64(tmp);
5413 break;
5414 default: abort();
5417 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
5418 Don't forget to clean them now. */
5419 if (size < 2) {
5420 tcg_temp_free_i32(a);
5421 tcg_temp_free_i32(b);
5425 static void gen_neon_narrow_op(int op, int u, int size,
5426 TCGv_i32 dest, TCGv_i64 src)
5428 if (op) {
5429 if (u) {
5430 gen_neon_unarrow_sats(size, dest, src);
5431 } else {
5432 gen_neon_narrow(size, dest, src);
5434 } else {
5435 if (u) {
5436 gen_neon_narrow_satu(size, dest, src);
5437 } else {
5438 gen_neon_narrow_sats(size, dest, src);
5443 /* Symbolic constants for op fields for Neon 3-register same-length.
5444 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
5445 * table A7-9.
5447 #define NEON_3R_VHADD 0
5448 #define NEON_3R_VQADD 1
5449 #define NEON_3R_VRHADD 2
5450 #define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
5451 #define NEON_3R_VHSUB 4
5452 #define NEON_3R_VQSUB 5
5453 #define NEON_3R_VCGT 6
5454 #define NEON_3R_VCGE 7
5455 #define NEON_3R_VSHL 8
5456 #define NEON_3R_VQSHL 9
5457 #define NEON_3R_VRSHL 10
5458 #define NEON_3R_VQRSHL 11
5459 #define NEON_3R_VMAX 12
5460 #define NEON_3R_VMIN 13
5461 #define NEON_3R_VABD 14
5462 #define NEON_3R_VABA 15
5463 #define NEON_3R_VADD_VSUB 16
5464 #define NEON_3R_VTST_VCEQ 17
5465 #define NEON_3R_VML 18 /* VMLA, VMLS */
5466 #define NEON_3R_VMUL 19
5467 #define NEON_3R_VPMAX 20
5468 #define NEON_3R_VPMIN 21
5469 #define NEON_3R_VQDMULH_VQRDMULH 22
5470 #define NEON_3R_VPADD_VQRDMLAH 23
5471 #define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */
5472 #define NEON_3R_VFM_VQRDMLSH 25 /* VFMA, VFMS, VQRDMLSH */
5473 #define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
5474 #define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
5475 #define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
5476 #define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
5477 #define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
5478 #define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */
5480 static const uint8_t neon_3r_sizes[] = {
5481 [NEON_3R_VHADD] = 0x7,
5482 [NEON_3R_VQADD] = 0xf,
5483 [NEON_3R_VRHADD] = 0x7,
5484 [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
5485 [NEON_3R_VHSUB] = 0x7,
5486 [NEON_3R_VQSUB] = 0xf,
5487 [NEON_3R_VCGT] = 0x7,
5488 [NEON_3R_VCGE] = 0x7,
5489 [NEON_3R_VSHL] = 0xf,
5490 [NEON_3R_VQSHL] = 0xf,
5491 [NEON_3R_VRSHL] = 0xf,
5492 [NEON_3R_VQRSHL] = 0xf,
5493 [NEON_3R_VMAX] = 0x7,
5494 [NEON_3R_VMIN] = 0x7,
5495 [NEON_3R_VABD] = 0x7,
5496 [NEON_3R_VABA] = 0x7,
5497 [NEON_3R_VADD_VSUB] = 0xf,
5498 [NEON_3R_VTST_VCEQ] = 0x7,
5499 [NEON_3R_VML] = 0x7,
5500 [NEON_3R_VMUL] = 0x7,
5501 [NEON_3R_VPMAX] = 0x7,
5502 [NEON_3R_VPMIN] = 0x7,
5503 [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
5504 [NEON_3R_VPADD_VQRDMLAH] = 0x7,
5505 [NEON_3R_SHA] = 0xf, /* size field encodes op type */
5506 [NEON_3R_VFM_VQRDMLSH] = 0x7, /* For VFM, size bit 1 encodes op */
5507 [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
5508 [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
5509 [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
5510 [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
5511 [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
5512 [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */
5515 /* Symbolic constants for op fields for Neon 2-register miscellaneous.
5516 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
5517 * table A7-13.
5519 #define NEON_2RM_VREV64 0
5520 #define NEON_2RM_VREV32 1
5521 #define NEON_2RM_VREV16 2
5522 #define NEON_2RM_VPADDL 4
5523 #define NEON_2RM_VPADDL_U 5
5524 #define NEON_2RM_AESE 6 /* Includes AESD */
5525 #define NEON_2RM_AESMC 7 /* Includes AESIMC */
5526 #define NEON_2RM_VCLS 8
5527 #define NEON_2RM_VCLZ 9
5528 #define NEON_2RM_VCNT 10
5529 #define NEON_2RM_VMVN 11
5530 #define NEON_2RM_VPADAL 12
5531 #define NEON_2RM_VPADAL_U 13
5532 #define NEON_2RM_VQABS 14
5533 #define NEON_2RM_VQNEG 15
5534 #define NEON_2RM_VCGT0 16
5535 #define NEON_2RM_VCGE0 17
5536 #define NEON_2RM_VCEQ0 18
5537 #define NEON_2RM_VCLE0 19
5538 #define NEON_2RM_VCLT0 20
5539 #define NEON_2RM_SHA1H 21
5540 #define NEON_2RM_VABS 22
5541 #define NEON_2RM_VNEG 23
5542 #define NEON_2RM_VCGT0_F 24
5543 #define NEON_2RM_VCGE0_F 25
5544 #define NEON_2RM_VCEQ0_F 26
5545 #define NEON_2RM_VCLE0_F 27
5546 #define NEON_2RM_VCLT0_F 28
5547 #define NEON_2RM_VABS_F 30
5548 #define NEON_2RM_VNEG_F 31
5549 #define NEON_2RM_VSWP 32
5550 #define NEON_2RM_VTRN 33
5551 #define NEON_2RM_VUZP 34
5552 #define NEON_2RM_VZIP 35
5553 #define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
5554 #define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
5555 #define NEON_2RM_VSHLL 38
5556 #define NEON_2RM_SHA1SU1 39 /* Includes SHA256SU0 */
5557 #define NEON_2RM_VRINTN 40
5558 #define NEON_2RM_VRINTX 41
5559 #define NEON_2RM_VRINTA 42
5560 #define NEON_2RM_VRINTZ 43
5561 #define NEON_2RM_VCVT_F16_F32 44
5562 #define NEON_2RM_VRINTM 45
5563 #define NEON_2RM_VCVT_F32_F16 46
5564 #define NEON_2RM_VRINTP 47
5565 #define NEON_2RM_VCVTAU 48
5566 #define NEON_2RM_VCVTAS 49
5567 #define NEON_2RM_VCVTNU 50
5568 #define NEON_2RM_VCVTNS 51
5569 #define NEON_2RM_VCVTPU 52
5570 #define NEON_2RM_VCVTPS 53
5571 #define NEON_2RM_VCVTMU 54
5572 #define NEON_2RM_VCVTMS 55
5573 #define NEON_2RM_VRECPE 56
5574 #define NEON_2RM_VRSQRTE 57
5575 #define NEON_2RM_VRECPE_F 58
5576 #define NEON_2RM_VRSQRTE_F 59
5577 #define NEON_2RM_VCVT_FS 60
5578 #define NEON_2RM_VCVT_FU 61
5579 #define NEON_2RM_VCVT_SF 62
5580 #define NEON_2RM_VCVT_UF 63
5582 static int neon_2rm_is_float_op(int op)
5584 /* Return true if this neon 2reg-misc op is float-to-float */
5585 return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
5586 (op >= NEON_2RM_VRINTN && op <= NEON_2RM_VRINTZ) ||
5587 op == NEON_2RM_VRINTM ||
5588 (op >= NEON_2RM_VRINTP && op <= NEON_2RM_VCVTMS) ||
5589 op >= NEON_2RM_VRECPE_F);
5592 static bool neon_2rm_is_v8_op(int op)
5594 /* Return true if this neon 2reg-misc op is ARMv8 and up */
5595 switch (op) {
5596 case NEON_2RM_VRINTN:
5597 case NEON_2RM_VRINTA:
5598 case NEON_2RM_VRINTM:
5599 case NEON_2RM_VRINTP:
5600 case NEON_2RM_VRINTZ:
5601 case NEON_2RM_VRINTX:
5602 case NEON_2RM_VCVTAU:
5603 case NEON_2RM_VCVTAS:
5604 case NEON_2RM_VCVTNU:
5605 case NEON_2RM_VCVTNS:
5606 case NEON_2RM_VCVTPU:
5607 case NEON_2RM_VCVTPS:
5608 case NEON_2RM_VCVTMU:
5609 case NEON_2RM_VCVTMS:
5610 return true;
5611 default:
5612 return false;
5616 /* Each entry in this array has bit n set if the insn allows
5617 * size value n (otherwise it will UNDEF). Since unallocated
5618 * op values will have no bits set they always UNDEF.
5620 static const uint8_t neon_2rm_sizes[] = {
5621 [NEON_2RM_VREV64] = 0x7,
5622 [NEON_2RM_VREV32] = 0x3,
5623 [NEON_2RM_VREV16] = 0x1,
5624 [NEON_2RM_VPADDL] = 0x7,
5625 [NEON_2RM_VPADDL_U] = 0x7,
5626 [NEON_2RM_AESE] = 0x1,
5627 [NEON_2RM_AESMC] = 0x1,
5628 [NEON_2RM_VCLS] = 0x7,
5629 [NEON_2RM_VCLZ] = 0x7,
5630 [NEON_2RM_VCNT] = 0x1,
5631 [NEON_2RM_VMVN] = 0x1,
5632 [NEON_2RM_VPADAL] = 0x7,
5633 [NEON_2RM_VPADAL_U] = 0x7,
5634 [NEON_2RM_VQABS] = 0x7,
5635 [NEON_2RM_VQNEG] = 0x7,
5636 [NEON_2RM_VCGT0] = 0x7,
5637 [NEON_2RM_VCGE0] = 0x7,
5638 [NEON_2RM_VCEQ0] = 0x7,
5639 [NEON_2RM_VCLE0] = 0x7,
5640 [NEON_2RM_VCLT0] = 0x7,
5641 [NEON_2RM_SHA1H] = 0x4,
5642 [NEON_2RM_VABS] = 0x7,
5643 [NEON_2RM_VNEG] = 0x7,
5644 [NEON_2RM_VCGT0_F] = 0x4,
5645 [NEON_2RM_VCGE0_F] = 0x4,
5646 [NEON_2RM_VCEQ0_F] = 0x4,
5647 [NEON_2RM_VCLE0_F] = 0x4,
5648 [NEON_2RM_VCLT0_F] = 0x4,
5649 [NEON_2RM_VABS_F] = 0x4,
5650 [NEON_2RM_VNEG_F] = 0x4,
5651 [NEON_2RM_VSWP] = 0x1,
5652 [NEON_2RM_VTRN] = 0x7,
5653 [NEON_2RM_VUZP] = 0x7,
5654 [NEON_2RM_VZIP] = 0x7,
5655 [NEON_2RM_VMOVN] = 0x7,
5656 [NEON_2RM_VQMOVN] = 0x7,
5657 [NEON_2RM_VSHLL] = 0x7,
5658 [NEON_2RM_SHA1SU1] = 0x4,
5659 [NEON_2RM_VRINTN] = 0x4,
5660 [NEON_2RM_VRINTX] = 0x4,
5661 [NEON_2RM_VRINTA] = 0x4,
5662 [NEON_2RM_VRINTZ] = 0x4,
5663 [NEON_2RM_VCVT_F16_F32] = 0x2,
5664 [NEON_2RM_VRINTM] = 0x4,
5665 [NEON_2RM_VCVT_F32_F16] = 0x2,
5666 [NEON_2RM_VRINTP] = 0x4,
5667 [NEON_2RM_VCVTAU] = 0x4,
5668 [NEON_2RM_VCVTAS] = 0x4,
5669 [NEON_2RM_VCVTNU] = 0x4,
5670 [NEON_2RM_VCVTNS] = 0x4,
5671 [NEON_2RM_VCVTPU] = 0x4,
5672 [NEON_2RM_VCVTPS] = 0x4,
5673 [NEON_2RM_VCVTMU] = 0x4,
5674 [NEON_2RM_VCVTMS] = 0x4,
5675 [NEON_2RM_VRECPE] = 0x4,
5676 [NEON_2RM_VRSQRTE] = 0x4,
5677 [NEON_2RM_VRECPE_F] = 0x4,
5678 [NEON_2RM_VRSQRTE_F] = 0x4,
5679 [NEON_2RM_VCVT_FS] = 0x4,
5680 [NEON_2RM_VCVT_FU] = 0x4,
5681 [NEON_2RM_VCVT_SF] = 0x4,
5682 [NEON_2RM_VCVT_UF] = 0x4,
5686 /* Expand v8.1 simd helper. */
5687 static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
5688 int q, int rd, int rn, int rm)
5690 if (dc_isar_feature(aa32_rdm, s)) {
5691 int opr_sz = (1 + q) * 8;
5692 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
5693 vfp_reg_offset(1, rn),
5694 vfp_reg_offset(1, rm), cpu_env,
5695 opr_sz, opr_sz, 0, fn);
5696 return 0;
5698 return 1;
5702 * Expanders for VBitOps_VBIF, VBIT, VBSL.
5704 static void gen_bsl_i64(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
5706 tcg_gen_xor_i64(rn, rn, rm);
5707 tcg_gen_and_i64(rn, rn, rd);
5708 tcg_gen_xor_i64(rd, rm, rn);
5711 static void gen_bit_i64(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
5713 tcg_gen_xor_i64(rn, rn, rd);
5714 tcg_gen_and_i64(rn, rn, rm);
5715 tcg_gen_xor_i64(rd, rd, rn);
5718 static void gen_bif_i64(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
5720 tcg_gen_xor_i64(rn, rn, rd);
5721 tcg_gen_andc_i64(rn, rn, rm);
5722 tcg_gen_xor_i64(rd, rd, rn);
5725 static void gen_bsl_vec(unsigned vece, TCGv_vec rd, TCGv_vec rn, TCGv_vec rm)
5727 tcg_gen_xor_vec(vece, rn, rn, rm);
5728 tcg_gen_and_vec(vece, rn, rn, rd);
5729 tcg_gen_xor_vec(vece, rd, rm, rn);
5732 static void gen_bit_vec(unsigned vece, TCGv_vec rd, TCGv_vec rn, TCGv_vec rm)
5734 tcg_gen_xor_vec(vece, rn, rn, rd);
5735 tcg_gen_and_vec(vece, rn, rn, rm);
5736 tcg_gen_xor_vec(vece, rd, rd, rn);
5739 static void gen_bif_vec(unsigned vece, TCGv_vec rd, TCGv_vec rn, TCGv_vec rm)
5741 tcg_gen_xor_vec(vece, rn, rn, rd);
5742 tcg_gen_andc_vec(vece, rn, rn, rm);
5743 tcg_gen_xor_vec(vece, rd, rd, rn);
5746 const GVecGen3 bsl_op = {
5747 .fni8 = gen_bsl_i64,
5748 .fniv = gen_bsl_vec,
5749 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5750 .load_dest = true
5753 const GVecGen3 bit_op = {
5754 .fni8 = gen_bit_i64,
5755 .fniv = gen_bit_vec,
5756 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5757 .load_dest = true
5760 const GVecGen3 bif_op = {
5761 .fni8 = gen_bif_i64,
5762 .fniv = gen_bif_vec,
5763 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5764 .load_dest = true
5767 static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5769 tcg_gen_vec_sar8i_i64(a, a, shift);
5770 tcg_gen_vec_add8_i64(d, d, a);
5773 static void gen_ssra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5775 tcg_gen_vec_sar16i_i64(a, a, shift);
5776 tcg_gen_vec_add16_i64(d, d, a);
5779 static void gen_ssra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
5781 tcg_gen_sari_i32(a, a, shift);
5782 tcg_gen_add_i32(d, d, a);
5785 static void gen_ssra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5787 tcg_gen_sari_i64(a, a, shift);
5788 tcg_gen_add_i64(d, d, a);
5791 static void gen_ssra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
5793 tcg_gen_sari_vec(vece, a, a, sh);
5794 tcg_gen_add_vec(vece, d, d, a);
5797 const GVecGen2i ssra_op[4] = {
5798 { .fni8 = gen_ssra8_i64,
5799 .fniv = gen_ssra_vec,
5800 .load_dest = true,
5801 .opc = INDEX_op_sari_vec,
5802 .vece = MO_8 },
5803 { .fni8 = gen_ssra16_i64,
5804 .fniv = gen_ssra_vec,
5805 .load_dest = true,
5806 .opc = INDEX_op_sari_vec,
5807 .vece = MO_16 },
5808 { .fni4 = gen_ssra32_i32,
5809 .fniv = gen_ssra_vec,
5810 .load_dest = true,
5811 .opc = INDEX_op_sari_vec,
5812 .vece = MO_32 },
5813 { .fni8 = gen_ssra64_i64,
5814 .fniv = gen_ssra_vec,
5815 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5816 .load_dest = true,
5817 .opc = INDEX_op_sari_vec,
5818 .vece = MO_64 },
5821 static void gen_usra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5823 tcg_gen_vec_shr8i_i64(a, a, shift);
5824 tcg_gen_vec_add8_i64(d, d, a);
5827 static void gen_usra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5829 tcg_gen_vec_shr16i_i64(a, a, shift);
5830 tcg_gen_vec_add16_i64(d, d, a);
5833 static void gen_usra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
5835 tcg_gen_shri_i32(a, a, shift);
5836 tcg_gen_add_i32(d, d, a);
5839 static void gen_usra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5841 tcg_gen_shri_i64(a, a, shift);
5842 tcg_gen_add_i64(d, d, a);
5845 static void gen_usra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
5847 tcg_gen_shri_vec(vece, a, a, sh);
5848 tcg_gen_add_vec(vece, d, d, a);
5851 const GVecGen2i usra_op[4] = {
5852 { .fni8 = gen_usra8_i64,
5853 .fniv = gen_usra_vec,
5854 .load_dest = true,
5855 .opc = INDEX_op_shri_vec,
5856 .vece = MO_8, },
5857 { .fni8 = gen_usra16_i64,
5858 .fniv = gen_usra_vec,
5859 .load_dest = true,
5860 .opc = INDEX_op_shri_vec,
5861 .vece = MO_16, },
5862 { .fni4 = gen_usra32_i32,
5863 .fniv = gen_usra_vec,
5864 .load_dest = true,
5865 .opc = INDEX_op_shri_vec,
5866 .vece = MO_32, },
5867 { .fni8 = gen_usra64_i64,
5868 .fniv = gen_usra_vec,
5869 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5870 .load_dest = true,
5871 .opc = INDEX_op_shri_vec,
5872 .vece = MO_64, },
5875 static void gen_shr8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5877 uint64_t mask = dup_const(MO_8, 0xff >> shift);
5878 TCGv_i64 t = tcg_temp_new_i64();
5880 tcg_gen_shri_i64(t, a, shift);
5881 tcg_gen_andi_i64(t, t, mask);
5882 tcg_gen_andi_i64(d, d, ~mask);
5883 tcg_gen_or_i64(d, d, t);
5884 tcg_temp_free_i64(t);
5887 static void gen_shr16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5889 uint64_t mask = dup_const(MO_16, 0xffff >> shift);
5890 TCGv_i64 t = tcg_temp_new_i64();
5892 tcg_gen_shri_i64(t, a, shift);
5893 tcg_gen_andi_i64(t, t, mask);
5894 tcg_gen_andi_i64(d, d, ~mask);
5895 tcg_gen_or_i64(d, d, t);
5896 tcg_temp_free_i64(t);
5899 static void gen_shr32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
5901 tcg_gen_shri_i32(a, a, shift);
5902 tcg_gen_deposit_i32(d, d, a, 0, 32 - shift);
5905 static void gen_shr64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5907 tcg_gen_shri_i64(a, a, shift);
5908 tcg_gen_deposit_i64(d, d, a, 0, 64 - shift);
5911 static void gen_shr_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
5913 if (sh == 0) {
5914 tcg_gen_mov_vec(d, a);
5915 } else {
5916 TCGv_vec t = tcg_temp_new_vec_matching(d);
5917 TCGv_vec m = tcg_temp_new_vec_matching(d);
5919 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK((8 << vece) - sh, sh));
5920 tcg_gen_shri_vec(vece, t, a, sh);
5921 tcg_gen_and_vec(vece, d, d, m);
5922 tcg_gen_or_vec(vece, d, d, t);
5924 tcg_temp_free_vec(t);
5925 tcg_temp_free_vec(m);
5929 const GVecGen2i sri_op[4] = {
5930 { .fni8 = gen_shr8_ins_i64,
5931 .fniv = gen_shr_ins_vec,
5932 .load_dest = true,
5933 .opc = INDEX_op_shri_vec,
5934 .vece = MO_8 },
5935 { .fni8 = gen_shr16_ins_i64,
5936 .fniv = gen_shr_ins_vec,
5937 .load_dest = true,
5938 .opc = INDEX_op_shri_vec,
5939 .vece = MO_16 },
5940 { .fni4 = gen_shr32_ins_i32,
5941 .fniv = gen_shr_ins_vec,
5942 .load_dest = true,
5943 .opc = INDEX_op_shri_vec,
5944 .vece = MO_32 },
5945 { .fni8 = gen_shr64_ins_i64,
5946 .fniv = gen_shr_ins_vec,
5947 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5948 .load_dest = true,
5949 .opc = INDEX_op_shri_vec,
5950 .vece = MO_64 },
5953 static void gen_shl8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5955 uint64_t mask = dup_const(MO_8, 0xff << shift);
5956 TCGv_i64 t = tcg_temp_new_i64();
5958 tcg_gen_shli_i64(t, a, shift);
5959 tcg_gen_andi_i64(t, t, mask);
5960 tcg_gen_andi_i64(d, d, ~mask);
5961 tcg_gen_or_i64(d, d, t);
5962 tcg_temp_free_i64(t);
5965 static void gen_shl16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5967 uint64_t mask = dup_const(MO_16, 0xffff << shift);
5968 TCGv_i64 t = tcg_temp_new_i64();
5970 tcg_gen_shli_i64(t, a, shift);
5971 tcg_gen_andi_i64(t, t, mask);
5972 tcg_gen_andi_i64(d, d, ~mask);
5973 tcg_gen_or_i64(d, d, t);
5974 tcg_temp_free_i64(t);
5977 static void gen_shl32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
5979 tcg_gen_deposit_i32(d, d, a, shift, 32 - shift);
5982 static void gen_shl64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5984 tcg_gen_deposit_i64(d, d, a, shift, 64 - shift);
5987 static void gen_shl_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
5989 if (sh == 0) {
5990 tcg_gen_mov_vec(d, a);
5991 } else {
5992 TCGv_vec t = tcg_temp_new_vec_matching(d);
5993 TCGv_vec m = tcg_temp_new_vec_matching(d);
5995 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK(0, sh));
5996 tcg_gen_shli_vec(vece, t, a, sh);
5997 tcg_gen_and_vec(vece, d, d, m);
5998 tcg_gen_or_vec(vece, d, d, t);
6000 tcg_temp_free_vec(t);
6001 tcg_temp_free_vec(m);
6005 const GVecGen2i sli_op[4] = {
6006 { .fni8 = gen_shl8_ins_i64,
6007 .fniv = gen_shl_ins_vec,
6008 .load_dest = true,
6009 .opc = INDEX_op_shli_vec,
6010 .vece = MO_8 },
6011 { .fni8 = gen_shl16_ins_i64,
6012 .fniv = gen_shl_ins_vec,
6013 .load_dest = true,
6014 .opc = INDEX_op_shli_vec,
6015 .vece = MO_16 },
6016 { .fni4 = gen_shl32_ins_i32,
6017 .fniv = gen_shl_ins_vec,
6018 .load_dest = true,
6019 .opc = INDEX_op_shli_vec,
6020 .vece = MO_32 },
6021 { .fni8 = gen_shl64_ins_i64,
6022 .fniv = gen_shl_ins_vec,
6023 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
6024 .load_dest = true,
6025 .opc = INDEX_op_shli_vec,
6026 .vece = MO_64 },
6029 static void gen_mla8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
6031 gen_helper_neon_mul_u8(a, a, b);
6032 gen_helper_neon_add_u8(d, d, a);
6035 static void gen_mls8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
6037 gen_helper_neon_mul_u8(a, a, b);
6038 gen_helper_neon_sub_u8(d, d, a);
6041 static void gen_mla16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
6043 gen_helper_neon_mul_u16(a, a, b);
6044 gen_helper_neon_add_u16(d, d, a);
6047 static void gen_mls16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
6049 gen_helper_neon_mul_u16(a, a, b);
6050 gen_helper_neon_sub_u16(d, d, a);
6053 static void gen_mla32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
6055 tcg_gen_mul_i32(a, a, b);
6056 tcg_gen_add_i32(d, d, a);
6059 static void gen_mls32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
6061 tcg_gen_mul_i32(a, a, b);
6062 tcg_gen_sub_i32(d, d, a);
6065 static void gen_mla64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
6067 tcg_gen_mul_i64(a, a, b);
6068 tcg_gen_add_i64(d, d, a);
6071 static void gen_mls64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
6073 tcg_gen_mul_i64(a, a, b);
6074 tcg_gen_sub_i64(d, d, a);
6077 static void gen_mla_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
6079 tcg_gen_mul_vec(vece, a, a, b);
6080 tcg_gen_add_vec(vece, d, d, a);
6083 static void gen_mls_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
6085 tcg_gen_mul_vec(vece, a, a, b);
6086 tcg_gen_sub_vec(vece, d, d, a);
6089 /* Note that while NEON does not support VMLA and VMLS as 64-bit ops,
6090 * these tables are shared with AArch64 which does support them.
6092 const GVecGen3 mla_op[4] = {
6093 { .fni4 = gen_mla8_i32,
6094 .fniv = gen_mla_vec,
6095 .opc = INDEX_op_mul_vec,
6096 .load_dest = true,
6097 .vece = MO_8 },
6098 { .fni4 = gen_mla16_i32,
6099 .fniv = gen_mla_vec,
6100 .opc = INDEX_op_mul_vec,
6101 .load_dest = true,
6102 .vece = MO_16 },
6103 { .fni4 = gen_mla32_i32,
6104 .fniv = gen_mla_vec,
6105 .opc = INDEX_op_mul_vec,
6106 .load_dest = true,
6107 .vece = MO_32 },
6108 { .fni8 = gen_mla64_i64,
6109 .fniv = gen_mla_vec,
6110 .opc = INDEX_op_mul_vec,
6111 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
6112 .load_dest = true,
6113 .vece = MO_64 },
6116 const GVecGen3 mls_op[4] = {
6117 { .fni4 = gen_mls8_i32,
6118 .fniv = gen_mls_vec,
6119 .opc = INDEX_op_mul_vec,
6120 .load_dest = true,
6121 .vece = MO_8 },
6122 { .fni4 = gen_mls16_i32,
6123 .fniv = gen_mls_vec,
6124 .opc = INDEX_op_mul_vec,
6125 .load_dest = true,
6126 .vece = MO_16 },
6127 { .fni4 = gen_mls32_i32,
6128 .fniv = gen_mls_vec,
6129 .opc = INDEX_op_mul_vec,
6130 .load_dest = true,
6131 .vece = MO_32 },
6132 { .fni8 = gen_mls64_i64,
6133 .fniv = gen_mls_vec,
6134 .opc = INDEX_op_mul_vec,
6135 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
6136 .load_dest = true,
6137 .vece = MO_64 },
6140 /* CMTST : test is "if (X & Y != 0)". */
6141 static void gen_cmtst_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
6143 tcg_gen_and_i32(d, a, b);
6144 tcg_gen_setcondi_i32(TCG_COND_NE, d, d, 0);
6145 tcg_gen_neg_i32(d, d);
6148 void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
6150 tcg_gen_and_i64(d, a, b);
6151 tcg_gen_setcondi_i64(TCG_COND_NE, d, d, 0);
6152 tcg_gen_neg_i64(d, d);
6155 static void gen_cmtst_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
6157 tcg_gen_and_vec(vece, d, a, b);
6158 tcg_gen_dupi_vec(vece, a, 0);
6159 tcg_gen_cmp_vec(TCG_COND_NE, vece, d, d, a);
6162 const GVecGen3 cmtst_op[4] = {
6163 { .fni4 = gen_helper_neon_tst_u8,
6164 .fniv = gen_cmtst_vec,
6165 .vece = MO_8 },
6166 { .fni4 = gen_helper_neon_tst_u16,
6167 .fniv = gen_cmtst_vec,
6168 .vece = MO_16 },
6169 { .fni4 = gen_cmtst_i32,
6170 .fniv = gen_cmtst_vec,
6171 .vece = MO_32 },
6172 { .fni8 = gen_cmtst_i64,
6173 .fniv = gen_cmtst_vec,
6174 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
6175 .vece = MO_64 },
6178 static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
6179 TCGv_vec a, TCGv_vec b)
6181 TCGv_vec x = tcg_temp_new_vec_matching(t);
6182 tcg_gen_add_vec(vece, x, a, b);
6183 tcg_gen_usadd_vec(vece, t, a, b);
6184 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
6185 tcg_gen_or_vec(vece, sat, sat, x);
6186 tcg_temp_free_vec(x);
6189 const GVecGen4 uqadd_op[4] = {
6190 { .fniv = gen_uqadd_vec,
6191 .fno = gen_helper_gvec_uqadd_b,
6192 .opc = INDEX_op_usadd_vec,
6193 .write_aofs = true,
6194 .vece = MO_8 },
6195 { .fniv = gen_uqadd_vec,
6196 .fno = gen_helper_gvec_uqadd_h,
6197 .opc = INDEX_op_usadd_vec,
6198 .write_aofs = true,
6199 .vece = MO_16 },
6200 { .fniv = gen_uqadd_vec,
6201 .fno = gen_helper_gvec_uqadd_s,
6202 .opc = INDEX_op_usadd_vec,
6203 .write_aofs = true,
6204 .vece = MO_32 },
6205 { .fniv = gen_uqadd_vec,
6206 .fno = gen_helper_gvec_uqadd_d,
6207 .opc = INDEX_op_usadd_vec,
6208 .write_aofs = true,
6209 .vece = MO_64 },
6212 static void gen_sqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
6213 TCGv_vec a, TCGv_vec b)
6215 TCGv_vec x = tcg_temp_new_vec_matching(t);
6216 tcg_gen_add_vec(vece, x, a, b);
6217 tcg_gen_ssadd_vec(vece, t, a, b);
6218 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
6219 tcg_gen_or_vec(vece, sat, sat, x);
6220 tcg_temp_free_vec(x);
6223 const GVecGen4 sqadd_op[4] = {
6224 { .fniv = gen_sqadd_vec,
6225 .fno = gen_helper_gvec_sqadd_b,
6226 .opc = INDEX_op_ssadd_vec,
6227 .write_aofs = true,
6228 .vece = MO_8 },
6229 { .fniv = gen_sqadd_vec,
6230 .fno = gen_helper_gvec_sqadd_h,
6231 .opc = INDEX_op_ssadd_vec,
6232 .write_aofs = true,
6233 .vece = MO_16 },
6234 { .fniv = gen_sqadd_vec,
6235 .fno = gen_helper_gvec_sqadd_s,
6236 .opc = INDEX_op_ssadd_vec,
6237 .write_aofs = true,
6238 .vece = MO_32 },
6239 { .fniv = gen_sqadd_vec,
6240 .fno = gen_helper_gvec_sqadd_d,
6241 .opc = INDEX_op_ssadd_vec,
6242 .write_aofs = true,
6243 .vece = MO_64 },
6246 static void gen_uqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
6247 TCGv_vec a, TCGv_vec b)
6249 TCGv_vec x = tcg_temp_new_vec_matching(t);
6250 tcg_gen_sub_vec(vece, x, a, b);
6251 tcg_gen_ussub_vec(vece, t, a, b);
6252 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
6253 tcg_gen_or_vec(vece, sat, sat, x);
6254 tcg_temp_free_vec(x);
6257 const GVecGen4 uqsub_op[4] = {
6258 { .fniv = gen_uqsub_vec,
6259 .fno = gen_helper_gvec_uqsub_b,
6260 .opc = INDEX_op_ussub_vec,
6261 .write_aofs = true,
6262 .vece = MO_8 },
6263 { .fniv = gen_uqsub_vec,
6264 .fno = gen_helper_gvec_uqsub_h,
6265 .opc = INDEX_op_ussub_vec,
6266 .write_aofs = true,
6267 .vece = MO_16 },
6268 { .fniv = gen_uqsub_vec,
6269 .fno = gen_helper_gvec_uqsub_s,
6270 .opc = INDEX_op_ussub_vec,
6271 .write_aofs = true,
6272 .vece = MO_32 },
6273 { .fniv = gen_uqsub_vec,
6274 .fno = gen_helper_gvec_uqsub_d,
6275 .opc = INDEX_op_ussub_vec,
6276 .write_aofs = true,
6277 .vece = MO_64 },
6280 static void gen_sqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
6281 TCGv_vec a, TCGv_vec b)
6283 TCGv_vec x = tcg_temp_new_vec_matching(t);
6284 tcg_gen_sub_vec(vece, x, a, b);
6285 tcg_gen_sssub_vec(vece, t, a, b);
6286 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
6287 tcg_gen_or_vec(vece, sat, sat, x);
6288 tcg_temp_free_vec(x);
6291 const GVecGen4 sqsub_op[4] = {
6292 { .fniv = gen_sqsub_vec,
6293 .fno = gen_helper_gvec_sqsub_b,
6294 .opc = INDEX_op_sssub_vec,
6295 .write_aofs = true,
6296 .vece = MO_8 },
6297 { .fniv = gen_sqsub_vec,
6298 .fno = gen_helper_gvec_sqsub_h,
6299 .opc = INDEX_op_sssub_vec,
6300 .write_aofs = true,
6301 .vece = MO_16 },
6302 { .fniv = gen_sqsub_vec,
6303 .fno = gen_helper_gvec_sqsub_s,
6304 .opc = INDEX_op_sssub_vec,
6305 .write_aofs = true,
6306 .vece = MO_32 },
6307 { .fniv = gen_sqsub_vec,
6308 .fno = gen_helper_gvec_sqsub_d,
6309 .opc = INDEX_op_sssub_vec,
6310 .write_aofs = true,
6311 .vece = MO_64 },
6314 /* Translate a NEON data processing instruction. Return nonzero if the
6315 instruction is invalid.
6316 We process data in a mixture of 32-bit and 64-bit chunks.
6317 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
6319 static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
6321 int op;
6322 int q;
6323 int rd, rn, rm, rd_ofs, rn_ofs, rm_ofs;
6324 int size;
6325 int shift;
6326 int pass;
6327 int count;
6328 int pairwise;
6329 int u;
6330 int vec_size;
6331 uint32_t imm;
6332 TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
6333 TCGv_ptr ptr1, ptr2, ptr3;
6334 TCGv_i64 tmp64;
6336 /* FIXME: this access check should not take precedence over UNDEF
6337 * for invalid encodings; we will generate incorrect syndrome information
6338 * for attempts to execute invalid vfp/neon encodings with FP disabled.
6340 if (s->fp_excp_el) {
6341 gen_exception_insn(s, 4, EXCP_UDEF,
6342 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
6343 return 0;
6346 if (!s->vfp_enabled)
6347 return 1;
6348 q = (insn & (1 << 6)) != 0;
6349 u = (insn >> 24) & 1;
6350 VFP_DREG_D(rd, insn);
6351 VFP_DREG_N(rn, insn);
6352 VFP_DREG_M(rm, insn);
6353 size = (insn >> 20) & 3;
6354 vec_size = q ? 16 : 8;
6355 rd_ofs = neon_reg_offset(rd, 0);
6356 rn_ofs = neon_reg_offset(rn, 0);
6357 rm_ofs = neon_reg_offset(rm, 0);
6359 if ((insn & (1 << 23)) == 0) {
6360 /* Three register same length. */
6361 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
6362 /* Catch invalid op and bad size combinations: UNDEF */
6363 if ((neon_3r_sizes[op] & (1 << size)) == 0) {
6364 return 1;
6366 /* All insns of this form UNDEF for either this condition or the
6367 * superset of cases "Q==1"; we catch the latter later.
6369 if (q && ((rd | rn | rm) & 1)) {
6370 return 1;
6372 switch (op) {
6373 case NEON_3R_SHA:
6374 /* The SHA-1/SHA-256 3-register instructions require special
6375 * treatment here, as their size field is overloaded as an
6376 * op type selector, and they all consume their input in a
6377 * single pass.
6379 if (!q) {
6380 return 1;
6382 if (!u) { /* SHA-1 */
6383 if (!dc_isar_feature(aa32_sha1, s)) {
6384 return 1;
6386 ptr1 = vfp_reg_ptr(true, rd);
6387 ptr2 = vfp_reg_ptr(true, rn);
6388 ptr3 = vfp_reg_ptr(true, rm);
6389 tmp4 = tcg_const_i32(size);
6390 gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp4);
6391 tcg_temp_free_i32(tmp4);
6392 } else { /* SHA-256 */
6393 if (!dc_isar_feature(aa32_sha2, s) || size == 3) {
6394 return 1;
6396 ptr1 = vfp_reg_ptr(true, rd);
6397 ptr2 = vfp_reg_ptr(true, rn);
6398 ptr3 = vfp_reg_ptr(true, rm);
6399 switch (size) {
6400 case 0:
6401 gen_helper_crypto_sha256h(ptr1, ptr2, ptr3);
6402 break;
6403 case 1:
6404 gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3);
6405 break;
6406 case 2:
6407 gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3);
6408 break;
6411 tcg_temp_free_ptr(ptr1);
6412 tcg_temp_free_ptr(ptr2);
6413 tcg_temp_free_ptr(ptr3);
6414 return 0;
6416 case NEON_3R_VPADD_VQRDMLAH:
6417 if (!u) {
6418 break; /* VPADD */
6420 /* VQRDMLAH */
6421 switch (size) {
6422 case 1:
6423 return do_v81_helper(s, gen_helper_gvec_qrdmlah_s16,
6424 q, rd, rn, rm);
6425 case 2:
6426 return do_v81_helper(s, gen_helper_gvec_qrdmlah_s32,
6427 q, rd, rn, rm);
6429 return 1;
6431 case NEON_3R_VFM_VQRDMLSH:
6432 if (!u) {
6433 /* VFM, VFMS */
6434 if (size == 1) {
6435 return 1;
6437 break;
6439 /* VQRDMLSH */
6440 switch (size) {
6441 case 1:
6442 return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s16,
6443 q, rd, rn, rm);
6444 case 2:
6445 return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s32,
6446 q, rd, rn, rm);
6448 return 1;
6450 case NEON_3R_LOGIC: /* Logic ops. */
6451 switch ((u << 2) | size) {
6452 case 0: /* VAND */
6453 tcg_gen_gvec_and(0, rd_ofs, rn_ofs, rm_ofs,
6454 vec_size, vec_size);
6455 break;
6456 case 1: /* VBIC */
6457 tcg_gen_gvec_andc(0, rd_ofs, rn_ofs, rm_ofs,
6458 vec_size, vec_size);
6459 break;
6460 case 2: /* VORR */
6461 tcg_gen_gvec_or(0, rd_ofs, rn_ofs, rm_ofs,
6462 vec_size, vec_size);
6463 break;
6464 case 3: /* VORN */
6465 tcg_gen_gvec_orc(0, rd_ofs, rn_ofs, rm_ofs,
6466 vec_size, vec_size);
6467 break;
6468 case 4: /* VEOR */
6469 tcg_gen_gvec_xor(0, rd_ofs, rn_ofs, rm_ofs,
6470 vec_size, vec_size);
6471 break;
6472 case 5: /* VBSL */
6473 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
6474 vec_size, vec_size, &bsl_op);
6475 break;
6476 case 6: /* VBIT */
6477 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
6478 vec_size, vec_size, &bit_op);
6479 break;
6480 case 7: /* VBIF */
6481 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
6482 vec_size, vec_size, &bif_op);
6483 break;
6485 return 0;
6487 case NEON_3R_VADD_VSUB:
6488 if (u) {
6489 tcg_gen_gvec_sub(size, rd_ofs, rn_ofs, rm_ofs,
6490 vec_size, vec_size);
6491 } else {
6492 tcg_gen_gvec_add(size, rd_ofs, rn_ofs, rm_ofs,
6493 vec_size, vec_size);
6495 return 0;
6497 case NEON_3R_VQADD:
6498 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
6499 rn_ofs, rm_ofs, vec_size, vec_size,
6500 (u ? uqadd_op : sqadd_op) + size);
6501 break;
6503 case NEON_3R_VQSUB:
6504 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
6505 rn_ofs, rm_ofs, vec_size, vec_size,
6506 (u ? uqsub_op : sqsub_op) + size);
6507 break;
6509 case NEON_3R_VMUL: /* VMUL */
6510 if (u) {
6511 /* Polynomial case allows only P8 and is handled below. */
6512 if (size != 0) {
6513 return 1;
6515 } else {
6516 tcg_gen_gvec_mul(size, rd_ofs, rn_ofs, rm_ofs,
6517 vec_size, vec_size);
6518 return 0;
6520 break;
6522 case NEON_3R_VML: /* VMLA, VMLS */
6523 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size,
6524 u ? &mls_op[size] : &mla_op[size]);
6525 return 0;
6527 case NEON_3R_VTST_VCEQ:
6528 if (u) { /* VCEQ */
6529 tcg_gen_gvec_cmp(TCG_COND_EQ, size, rd_ofs, rn_ofs, rm_ofs,
6530 vec_size, vec_size);
6531 } else { /* VTST */
6532 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
6533 vec_size, vec_size, &cmtst_op[size]);
6535 return 0;
6537 case NEON_3R_VCGT:
6538 tcg_gen_gvec_cmp(u ? TCG_COND_GTU : TCG_COND_GT, size,
6539 rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
6540 return 0;
6542 case NEON_3R_VCGE:
6543 tcg_gen_gvec_cmp(u ? TCG_COND_GEU : TCG_COND_GE, size,
6544 rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
6545 return 0;
6547 case NEON_3R_VMAX:
6548 if (u) {
6549 tcg_gen_gvec_umax(size, rd_ofs, rn_ofs, rm_ofs,
6550 vec_size, vec_size);
6551 } else {
6552 tcg_gen_gvec_smax(size, rd_ofs, rn_ofs, rm_ofs,
6553 vec_size, vec_size);
6555 return 0;
6556 case NEON_3R_VMIN:
6557 if (u) {
6558 tcg_gen_gvec_umin(size, rd_ofs, rn_ofs, rm_ofs,
6559 vec_size, vec_size);
6560 } else {
6561 tcg_gen_gvec_smin(size, rd_ofs, rn_ofs, rm_ofs,
6562 vec_size, vec_size);
6564 return 0;
6567 if (size == 3) {
6568 /* 64-bit element instructions. */
6569 for (pass = 0; pass < (q ? 2 : 1); pass++) {
6570 neon_load_reg64(cpu_V0, rn + pass);
6571 neon_load_reg64(cpu_V1, rm + pass);
6572 switch (op) {
6573 case NEON_3R_VSHL:
6574 if (u) {
6575 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
6576 } else {
6577 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
6579 break;
6580 case NEON_3R_VQSHL:
6581 if (u) {
6582 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
6583 cpu_V1, cpu_V0);
6584 } else {
6585 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
6586 cpu_V1, cpu_V0);
6588 break;
6589 case NEON_3R_VRSHL:
6590 if (u) {
6591 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
6592 } else {
6593 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
6595 break;
6596 case NEON_3R_VQRSHL:
6597 if (u) {
6598 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
6599 cpu_V1, cpu_V0);
6600 } else {
6601 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
6602 cpu_V1, cpu_V0);
6604 break;
6605 default:
6606 abort();
6608 neon_store_reg64(cpu_V0, rd + pass);
6610 return 0;
6612 pairwise = 0;
6613 switch (op) {
6614 case NEON_3R_VSHL:
6615 case NEON_3R_VQSHL:
6616 case NEON_3R_VRSHL:
6617 case NEON_3R_VQRSHL:
6619 int rtmp;
6620 /* Shift instruction operands are reversed. */
6621 rtmp = rn;
6622 rn = rm;
6623 rm = rtmp;
6625 break;
6626 case NEON_3R_VPADD_VQRDMLAH:
6627 case NEON_3R_VPMAX:
6628 case NEON_3R_VPMIN:
6629 pairwise = 1;
6630 break;
6631 case NEON_3R_FLOAT_ARITH:
6632 pairwise = (u && size < 2); /* if VPADD (float) */
6633 break;
6634 case NEON_3R_FLOAT_MINMAX:
6635 pairwise = u; /* if VPMIN/VPMAX (float) */
6636 break;
6637 case NEON_3R_FLOAT_CMP:
6638 if (!u && size) {
6639 /* no encoding for U=0 C=1x */
6640 return 1;
6642 break;
6643 case NEON_3R_FLOAT_ACMP:
6644 if (!u) {
6645 return 1;
6647 break;
6648 case NEON_3R_FLOAT_MISC:
6649 /* VMAXNM/VMINNM in ARMv8 */
6650 if (u && !arm_dc_feature(s, ARM_FEATURE_V8)) {
6651 return 1;
6653 break;
6654 case NEON_3R_VFM_VQRDMLSH:
6655 if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
6656 return 1;
6658 break;
6659 default:
6660 break;
6663 if (pairwise && q) {
6664 /* All the pairwise insns UNDEF if Q is set */
6665 return 1;
6668 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6670 if (pairwise) {
6671 /* Pairwise. */
6672 if (pass < 1) {
6673 tmp = neon_load_reg(rn, 0);
6674 tmp2 = neon_load_reg(rn, 1);
6675 } else {
6676 tmp = neon_load_reg(rm, 0);
6677 tmp2 = neon_load_reg(rm, 1);
6679 } else {
6680 /* Elementwise. */
6681 tmp = neon_load_reg(rn, pass);
6682 tmp2 = neon_load_reg(rm, pass);
6684 switch (op) {
6685 case NEON_3R_VHADD:
6686 GEN_NEON_INTEGER_OP(hadd);
6687 break;
6688 case NEON_3R_VRHADD:
6689 GEN_NEON_INTEGER_OP(rhadd);
6690 break;
6691 case NEON_3R_VHSUB:
6692 GEN_NEON_INTEGER_OP(hsub);
6693 break;
6694 case NEON_3R_VSHL:
6695 GEN_NEON_INTEGER_OP(shl);
6696 break;
6697 case NEON_3R_VQSHL:
6698 GEN_NEON_INTEGER_OP_ENV(qshl);
6699 break;
6700 case NEON_3R_VRSHL:
6701 GEN_NEON_INTEGER_OP(rshl);
6702 break;
6703 case NEON_3R_VQRSHL:
6704 GEN_NEON_INTEGER_OP_ENV(qrshl);
6705 break;
6706 case NEON_3R_VABD:
6707 GEN_NEON_INTEGER_OP(abd);
6708 break;
6709 case NEON_3R_VABA:
6710 GEN_NEON_INTEGER_OP(abd);
6711 tcg_temp_free_i32(tmp2);
6712 tmp2 = neon_load_reg(rd, pass);
6713 gen_neon_add(size, tmp, tmp2);
6714 break;
6715 case NEON_3R_VMUL:
6716 /* VMUL.P8; other cases already eliminated. */
6717 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
6718 break;
6719 case NEON_3R_VPMAX:
6720 GEN_NEON_INTEGER_OP(pmax);
6721 break;
6722 case NEON_3R_VPMIN:
6723 GEN_NEON_INTEGER_OP(pmin);
6724 break;
6725 case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
6726 if (!u) { /* VQDMULH */
6727 switch (size) {
6728 case 1:
6729 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
6730 break;
6731 case 2:
6732 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
6733 break;
6734 default: abort();
6736 } else { /* VQRDMULH */
6737 switch (size) {
6738 case 1:
6739 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
6740 break;
6741 case 2:
6742 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
6743 break;
6744 default: abort();
6747 break;
6748 case NEON_3R_VPADD_VQRDMLAH:
6749 switch (size) {
6750 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
6751 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
6752 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
6753 default: abort();
6755 break;
6756 case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
6758 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6759 switch ((u << 2) | size) {
6760 case 0: /* VADD */
6761 case 4: /* VPADD */
6762 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
6763 break;
6764 case 2: /* VSUB */
6765 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
6766 break;
6767 case 6: /* VABD */
6768 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
6769 break;
6770 default:
6771 abort();
6773 tcg_temp_free_ptr(fpstatus);
6774 break;
6776 case NEON_3R_FLOAT_MULTIPLY:
6778 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6779 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
6780 if (!u) {
6781 tcg_temp_free_i32(tmp2);
6782 tmp2 = neon_load_reg(rd, pass);
6783 if (size == 0) {
6784 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
6785 } else {
6786 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
6789 tcg_temp_free_ptr(fpstatus);
6790 break;
6792 case NEON_3R_FLOAT_CMP:
6794 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6795 if (!u) {
6796 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
6797 } else {
6798 if (size == 0) {
6799 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
6800 } else {
6801 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
6804 tcg_temp_free_ptr(fpstatus);
6805 break;
6807 case NEON_3R_FLOAT_ACMP:
6809 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6810 if (size == 0) {
6811 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
6812 } else {
6813 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
6815 tcg_temp_free_ptr(fpstatus);
6816 break;
6818 case NEON_3R_FLOAT_MINMAX:
6820 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6821 if (size == 0) {
6822 gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus);
6823 } else {
6824 gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus);
6826 tcg_temp_free_ptr(fpstatus);
6827 break;
6829 case NEON_3R_FLOAT_MISC:
6830 if (u) {
6831 /* VMAXNM/VMINNM */
6832 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6833 if (size == 0) {
6834 gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus);
6835 } else {
6836 gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus);
6838 tcg_temp_free_ptr(fpstatus);
6839 } else {
6840 if (size == 0) {
6841 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
6842 } else {
6843 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
6846 break;
6847 case NEON_3R_VFM_VQRDMLSH:
6849 /* VFMA, VFMS: fused multiply-add */
6850 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6851 TCGv_i32 tmp3 = neon_load_reg(rd, pass);
6852 if (size) {
6853 /* VFMS */
6854 gen_helper_vfp_negs(tmp, tmp);
6856 gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus);
6857 tcg_temp_free_i32(tmp3);
6858 tcg_temp_free_ptr(fpstatus);
6859 break;
6861 default:
6862 abort();
6864 tcg_temp_free_i32(tmp2);
6866 /* Save the result. For elementwise operations we can put it
6867 straight into the destination register. For pairwise operations
6868 we have to be careful to avoid clobbering the source operands. */
6869 if (pairwise && rd == rm) {
6870 neon_store_scratch(pass, tmp);
6871 } else {
6872 neon_store_reg(rd, pass, tmp);
6875 } /* for pass */
6876 if (pairwise && rd == rm) {
6877 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6878 tmp = neon_load_scratch(pass);
6879 neon_store_reg(rd, pass, tmp);
6882 /* End of 3 register same size operations. */
6883 } else if (insn & (1 << 4)) {
6884 if ((insn & 0x00380080) != 0) {
6885 /* Two registers and shift. */
6886 op = (insn >> 8) & 0xf;
6887 if (insn & (1 << 7)) {
6888 /* 64-bit shift. */
6889 if (op > 7) {
6890 return 1;
6892 size = 3;
6893 } else {
6894 size = 2;
6895 while ((insn & (1 << (size + 19))) == 0)
6896 size--;
6898 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
6899 if (op < 8) {
6900 /* Shift by immediate:
6901 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
6902 if (q && ((rd | rm) & 1)) {
6903 return 1;
6905 if (!u && (op == 4 || op == 6)) {
6906 return 1;
6908 /* Right shifts are encoded as N - shift, where N is the
6909 element size in bits. */
6910 if (op <= 4) {
6911 shift = shift - (1 << (size + 3));
6914 switch (op) {
6915 case 0: /* VSHR */
6916 /* Right shift comes here negative. */
6917 shift = -shift;
6918 /* Shifts larger than the element size are architecturally
6919 * valid. Unsigned results in all zeros; signed results
6920 * in all sign bits.
6922 if (!u) {
6923 tcg_gen_gvec_sari(size, rd_ofs, rm_ofs,
6924 MIN(shift, (8 << size) - 1),
6925 vec_size, vec_size);
6926 } else if (shift >= 8 << size) {
6927 tcg_gen_gvec_dup8i(rd_ofs, vec_size, vec_size, 0);
6928 } else {
6929 tcg_gen_gvec_shri(size, rd_ofs, rm_ofs, shift,
6930 vec_size, vec_size);
6932 return 0;
6934 case 1: /* VSRA */
6935 /* Right shift comes here negative. */
6936 shift = -shift;
6937 /* Shifts larger than the element size are architecturally
6938 * valid. Unsigned results in all zeros; signed results
6939 * in all sign bits.
6941 if (!u) {
6942 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
6943 MIN(shift, (8 << size) - 1),
6944 &ssra_op[size]);
6945 } else if (shift >= 8 << size) {
6946 /* rd += 0 */
6947 } else {
6948 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
6949 shift, &usra_op[size]);
6951 return 0;
6953 case 4: /* VSRI */
6954 if (!u) {
6955 return 1;
6957 /* Right shift comes here negative. */
6958 shift = -shift;
6959 /* Shift out of range leaves destination unchanged. */
6960 if (shift < 8 << size) {
6961 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
6962 shift, &sri_op[size]);
6964 return 0;
6966 case 5: /* VSHL, VSLI */
6967 if (u) { /* VSLI */
6968 /* Shift out of range leaves destination unchanged. */
6969 if (shift < 8 << size) {
6970 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size,
6971 vec_size, shift, &sli_op[size]);
6973 } else { /* VSHL */
6974 /* Shifts larger than the element size are
6975 * architecturally valid and results in zero.
6977 if (shift >= 8 << size) {
6978 tcg_gen_gvec_dup8i(rd_ofs, vec_size, vec_size, 0);
6979 } else {
6980 tcg_gen_gvec_shli(size, rd_ofs, rm_ofs, shift,
6981 vec_size, vec_size);
6984 return 0;
6987 if (size == 3) {
6988 count = q + 1;
6989 } else {
6990 count = q ? 4: 2;
6993 /* To avoid excessive duplication of ops we implement shift
6994 * by immediate using the variable shift operations.
6996 imm = dup_const(size, shift);
6998 for (pass = 0; pass < count; pass++) {
6999 if (size == 3) {
7000 neon_load_reg64(cpu_V0, rm + pass);
7001 tcg_gen_movi_i64(cpu_V1, imm);
7002 switch (op) {
7003 case 2: /* VRSHR */
7004 case 3: /* VRSRA */
7005 if (u)
7006 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
7007 else
7008 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
7009 break;
7010 case 6: /* VQSHLU */
7011 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
7012 cpu_V0, cpu_V1);
7013 break;
7014 case 7: /* VQSHL */
7015 if (u) {
7016 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
7017 cpu_V0, cpu_V1);
7018 } else {
7019 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
7020 cpu_V0, cpu_V1);
7022 break;
7023 default:
7024 g_assert_not_reached();
7026 if (op == 3) {
7027 /* Accumulate. */
7028 neon_load_reg64(cpu_V1, rd + pass);
7029 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
7031 neon_store_reg64(cpu_V0, rd + pass);
7032 } else { /* size < 3 */
7033 /* Operands in T0 and T1. */
7034 tmp = neon_load_reg(rm, pass);
7035 tmp2 = tcg_temp_new_i32();
7036 tcg_gen_movi_i32(tmp2, imm);
7037 switch (op) {
7038 case 2: /* VRSHR */
7039 case 3: /* VRSRA */
7040 GEN_NEON_INTEGER_OP(rshl);
7041 break;
7042 case 6: /* VQSHLU */
7043 switch (size) {
7044 case 0:
7045 gen_helper_neon_qshlu_s8(tmp, cpu_env,
7046 tmp, tmp2);
7047 break;
7048 case 1:
7049 gen_helper_neon_qshlu_s16(tmp, cpu_env,
7050 tmp, tmp2);
7051 break;
7052 case 2:
7053 gen_helper_neon_qshlu_s32(tmp, cpu_env,
7054 tmp, tmp2);
7055 break;
7056 default:
7057 abort();
7059 break;
7060 case 7: /* VQSHL */
7061 GEN_NEON_INTEGER_OP_ENV(qshl);
7062 break;
7063 default:
7064 g_assert_not_reached();
7066 tcg_temp_free_i32(tmp2);
7068 if (op == 3) {
7069 /* Accumulate. */
7070 tmp2 = neon_load_reg(rd, pass);
7071 gen_neon_add(size, tmp, tmp2);
7072 tcg_temp_free_i32(tmp2);
7074 neon_store_reg(rd, pass, tmp);
7076 } /* for pass */
7077 } else if (op < 10) {
7078 /* Shift by immediate and narrow:
7079 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
7080 int input_unsigned = (op == 8) ? !u : u;
7081 if (rm & 1) {
7082 return 1;
7084 shift = shift - (1 << (size + 3));
7085 size++;
7086 if (size == 3) {
7087 tmp64 = tcg_const_i64(shift);
7088 neon_load_reg64(cpu_V0, rm);
7089 neon_load_reg64(cpu_V1, rm + 1);
7090 for (pass = 0; pass < 2; pass++) {
7091 TCGv_i64 in;
7092 if (pass == 0) {
7093 in = cpu_V0;
7094 } else {
7095 in = cpu_V1;
7097 if (q) {
7098 if (input_unsigned) {
7099 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
7100 } else {
7101 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
7103 } else {
7104 if (input_unsigned) {
7105 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
7106 } else {
7107 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
7110 tmp = tcg_temp_new_i32();
7111 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
7112 neon_store_reg(rd, pass, tmp);
7113 } /* for pass */
7114 tcg_temp_free_i64(tmp64);
7115 } else {
7116 if (size == 1) {
7117 imm = (uint16_t)shift;
7118 imm |= imm << 16;
7119 } else {
7120 /* size == 2 */
7121 imm = (uint32_t)shift;
7123 tmp2 = tcg_const_i32(imm);
7124 tmp4 = neon_load_reg(rm + 1, 0);
7125 tmp5 = neon_load_reg(rm + 1, 1);
7126 for (pass = 0; pass < 2; pass++) {
7127 if (pass == 0) {
7128 tmp = neon_load_reg(rm, 0);
7129 } else {
7130 tmp = tmp4;
7132 gen_neon_shift_narrow(size, tmp, tmp2, q,
7133 input_unsigned);
7134 if (pass == 0) {
7135 tmp3 = neon_load_reg(rm, 1);
7136 } else {
7137 tmp3 = tmp5;
7139 gen_neon_shift_narrow(size, tmp3, tmp2, q,
7140 input_unsigned);
7141 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
7142 tcg_temp_free_i32(tmp);
7143 tcg_temp_free_i32(tmp3);
7144 tmp = tcg_temp_new_i32();
7145 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
7146 neon_store_reg(rd, pass, tmp);
7147 } /* for pass */
7148 tcg_temp_free_i32(tmp2);
7150 } else if (op == 10) {
7151 /* VSHLL, VMOVL */
7152 if (q || (rd & 1)) {
7153 return 1;
7155 tmp = neon_load_reg(rm, 0);
7156 tmp2 = neon_load_reg(rm, 1);
7157 for (pass = 0; pass < 2; pass++) {
7158 if (pass == 1)
7159 tmp = tmp2;
7161 gen_neon_widen(cpu_V0, tmp, size, u);
7163 if (shift != 0) {
7164 /* The shift is less than the width of the source
7165 type, so we can just shift the whole register. */
7166 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
7167 /* Widen the result of shift: we need to clear
7168 * the potential overflow bits resulting from
7169 * left bits of the narrow input appearing as
7170 * right bits of left the neighbour narrow
7171 * input. */
7172 if (size < 2 || !u) {
7173 uint64_t imm64;
7174 if (size == 0) {
7175 imm = (0xffu >> (8 - shift));
7176 imm |= imm << 16;
7177 } else if (size == 1) {
7178 imm = 0xffff >> (16 - shift);
7179 } else {
7180 /* size == 2 */
7181 imm = 0xffffffff >> (32 - shift);
7183 if (size < 2) {
7184 imm64 = imm | (((uint64_t)imm) << 32);
7185 } else {
7186 imm64 = imm;
7188 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
7191 neon_store_reg64(cpu_V0, rd + pass);
7193 } else if (op >= 14) {
7194 /* VCVT fixed-point. */
7195 if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
7196 return 1;
7198 /* We have already masked out the must-be-1 top bit of imm6,
7199 * hence this 32-shift where the ARM ARM has 64-imm6.
7201 shift = 32 - shift;
7202 for (pass = 0; pass < (q ? 4 : 2); pass++) {
7203 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
7204 if (!(op & 1)) {
7205 if (u)
7206 gen_vfp_ulto(0, shift, 1);
7207 else
7208 gen_vfp_slto(0, shift, 1);
7209 } else {
7210 if (u)
7211 gen_vfp_toul(0, shift, 1);
7212 else
7213 gen_vfp_tosl(0, shift, 1);
7215 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
7217 } else {
7218 return 1;
7220 } else { /* (insn & 0x00380080) == 0 */
7221 int invert, reg_ofs, vec_size;
7223 if (q && (rd & 1)) {
7224 return 1;
7227 op = (insn >> 8) & 0xf;
7228 /* One register and immediate. */
7229 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
7230 invert = (insn & (1 << 5)) != 0;
7231 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
7232 * We choose to not special-case this and will behave as if a
7233 * valid constant encoding of 0 had been given.
7235 switch (op) {
7236 case 0: case 1:
7237 /* no-op */
7238 break;
7239 case 2: case 3:
7240 imm <<= 8;
7241 break;
7242 case 4: case 5:
7243 imm <<= 16;
7244 break;
7245 case 6: case 7:
7246 imm <<= 24;
7247 break;
7248 case 8: case 9:
7249 imm |= imm << 16;
7250 break;
7251 case 10: case 11:
7252 imm = (imm << 8) | (imm << 24);
7253 break;
7254 case 12:
7255 imm = (imm << 8) | 0xff;
7256 break;
7257 case 13:
7258 imm = (imm << 16) | 0xffff;
7259 break;
7260 case 14:
7261 imm |= (imm << 8) | (imm << 16) | (imm << 24);
7262 if (invert) {
7263 imm = ~imm;
7265 break;
7266 case 15:
7267 if (invert) {
7268 return 1;
7270 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
7271 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
7272 break;
7274 if (invert) {
7275 imm = ~imm;
7278 reg_ofs = neon_reg_offset(rd, 0);
7279 vec_size = q ? 16 : 8;
7281 if (op & 1 && op < 12) {
7282 if (invert) {
7283 /* The immediate value has already been inverted,
7284 * so BIC becomes AND.
7286 tcg_gen_gvec_andi(MO_32, reg_ofs, reg_ofs, imm,
7287 vec_size, vec_size);
7288 } else {
7289 tcg_gen_gvec_ori(MO_32, reg_ofs, reg_ofs, imm,
7290 vec_size, vec_size);
7292 } else {
7293 /* VMOV, VMVN. */
7294 if (op == 14 && invert) {
7295 TCGv_i64 t64 = tcg_temp_new_i64();
7297 for (pass = 0; pass <= q; ++pass) {
7298 uint64_t val = 0;
7299 int n;
7301 for (n = 0; n < 8; n++) {
7302 if (imm & (1 << (n + pass * 8))) {
7303 val |= 0xffull << (n * 8);
7306 tcg_gen_movi_i64(t64, val);
7307 neon_store_reg64(t64, rd + pass);
7309 tcg_temp_free_i64(t64);
7310 } else {
7311 tcg_gen_gvec_dup32i(reg_ofs, vec_size, vec_size, imm);
7315 } else { /* (insn & 0x00800010 == 0x00800000) */
7316 if (size != 3) {
7317 op = (insn >> 8) & 0xf;
7318 if ((insn & (1 << 6)) == 0) {
7319 /* Three registers of different lengths. */
7320 int src1_wide;
7321 int src2_wide;
7322 int prewiden;
7323 /* undefreq: bit 0 : UNDEF if size == 0
7324 * bit 1 : UNDEF if size == 1
7325 * bit 2 : UNDEF if size == 2
7326 * bit 3 : UNDEF if U == 1
7327 * Note that [2:0] set implies 'always UNDEF'
7329 int undefreq;
7330 /* prewiden, src1_wide, src2_wide, undefreq */
7331 static const int neon_3reg_wide[16][4] = {
7332 {1, 0, 0, 0}, /* VADDL */
7333 {1, 1, 0, 0}, /* VADDW */
7334 {1, 0, 0, 0}, /* VSUBL */
7335 {1, 1, 0, 0}, /* VSUBW */
7336 {0, 1, 1, 0}, /* VADDHN */
7337 {0, 0, 0, 0}, /* VABAL */
7338 {0, 1, 1, 0}, /* VSUBHN */
7339 {0, 0, 0, 0}, /* VABDL */
7340 {0, 0, 0, 0}, /* VMLAL */
7341 {0, 0, 0, 9}, /* VQDMLAL */
7342 {0, 0, 0, 0}, /* VMLSL */
7343 {0, 0, 0, 9}, /* VQDMLSL */
7344 {0, 0, 0, 0}, /* Integer VMULL */
7345 {0, 0, 0, 1}, /* VQDMULL */
7346 {0, 0, 0, 0xa}, /* Polynomial VMULL */
7347 {0, 0, 0, 7}, /* Reserved: always UNDEF */
7350 prewiden = neon_3reg_wide[op][0];
7351 src1_wide = neon_3reg_wide[op][1];
7352 src2_wide = neon_3reg_wide[op][2];
7353 undefreq = neon_3reg_wide[op][3];
7355 if ((undefreq & (1 << size)) ||
7356 ((undefreq & 8) && u)) {
7357 return 1;
7359 if ((src1_wide && (rn & 1)) ||
7360 (src2_wide && (rm & 1)) ||
7361 (!src2_wide && (rd & 1))) {
7362 return 1;
7365 /* Handle VMULL.P64 (Polynomial 64x64 to 128 bit multiply)
7366 * outside the loop below as it only performs a single pass.
7368 if (op == 14 && size == 2) {
7369 TCGv_i64 tcg_rn, tcg_rm, tcg_rd;
7371 if (!dc_isar_feature(aa32_pmull, s)) {
7372 return 1;
7374 tcg_rn = tcg_temp_new_i64();
7375 tcg_rm = tcg_temp_new_i64();
7376 tcg_rd = tcg_temp_new_i64();
7377 neon_load_reg64(tcg_rn, rn);
7378 neon_load_reg64(tcg_rm, rm);
7379 gen_helper_neon_pmull_64_lo(tcg_rd, tcg_rn, tcg_rm);
7380 neon_store_reg64(tcg_rd, rd);
7381 gen_helper_neon_pmull_64_hi(tcg_rd, tcg_rn, tcg_rm);
7382 neon_store_reg64(tcg_rd, rd + 1);
7383 tcg_temp_free_i64(tcg_rn);
7384 tcg_temp_free_i64(tcg_rm);
7385 tcg_temp_free_i64(tcg_rd);
7386 return 0;
7389 /* Avoid overlapping operands. Wide source operands are
7390 always aligned so will never overlap with wide
7391 destinations in problematic ways. */
7392 if (rd == rm && !src2_wide) {
7393 tmp = neon_load_reg(rm, 1);
7394 neon_store_scratch(2, tmp);
7395 } else if (rd == rn && !src1_wide) {
7396 tmp = neon_load_reg(rn, 1);
7397 neon_store_scratch(2, tmp);
7399 tmp3 = NULL;
7400 for (pass = 0; pass < 2; pass++) {
7401 if (src1_wide) {
7402 neon_load_reg64(cpu_V0, rn + pass);
7403 tmp = NULL;
7404 } else {
7405 if (pass == 1 && rd == rn) {
7406 tmp = neon_load_scratch(2);
7407 } else {
7408 tmp = neon_load_reg(rn, pass);
7410 if (prewiden) {
7411 gen_neon_widen(cpu_V0, tmp, size, u);
7414 if (src2_wide) {
7415 neon_load_reg64(cpu_V1, rm + pass);
7416 tmp2 = NULL;
7417 } else {
7418 if (pass == 1 && rd == rm) {
7419 tmp2 = neon_load_scratch(2);
7420 } else {
7421 tmp2 = neon_load_reg(rm, pass);
7423 if (prewiden) {
7424 gen_neon_widen(cpu_V1, tmp2, size, u);
7427 switch (op) {
7428 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
7429 gen_neon_addl(size);
7430 break;
7431 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
7432 gen_neon_subl(size);
7433 break;
7434 case 5: case 7: /* VABAL, VABDL */
7435 switch ((size << 1) | u) {
7436 case 0:
7437 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
7438 break;
7439 case 1:
7440 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
7441 break;
7442 case 2:
7443 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
7444 break;
7445 case 3:
7446 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
7447 break;
7448 case 4:
7449 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
7450 break;
7451 case 5:
7452 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
7453 break;
7454 default: abort();
7456 tcg_temp_free_i32(tmp2);
7457 tcg_temp_free_i32(tmp);
7458 break;
7459 case 8: case 9: case 10: case 11: case 12: case 13:
7460 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
7461 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
7462 break;
7463 case 14: /* Polynomial VMULL */
7464 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
7465 tcg_temp_free_i32(tmp2);
7466 tcg_temp_free_i32(tmp);
7467 break;
7468 default: /* 15 is RESERVED: caught earlier */
7469 abort();
7471 if (op == 13) {
7472 /* VQDMULL */
7473 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
7474 neon_store_reg64(cpu_V0, rd + pass);
7475 } else if (op == 5 || (op >= 8 && op <= 11)) {
7476 /* Accumulate. */
7477 neon_load_reg64(cpu_V1, rd + pass);
7478 switch (op) {
7479 case 10: /* VMLSL */
7480 gen_neon_negl(cpu_V0, size);
7481 /* Fall through */
7482 case 5: case 8: /* VABAL, VMLAL */
7483 gen_neon_addl(size);
7484 break;
7485 case 9: case 11: /* VQDMLAL, VQDMLSL */
7486 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
7487 if (op == 11) {
7488 gen_neon_negl(cpu_V0, size);
7490 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
7491 break;
7492 default:
7493 abort();
7495 neon_store_reg64(cpu_V0, rd + pass);
7496 } else if (op == 4 || op == 6) {
7497 /* Narrowing operation. */
7498 tmp = tcg_temp_new_i32();
7499 if (!u) {
7500 switch (size) {
7501 case 0:
7502 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
7503 break;
7504 case 1:
7505 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
7506 break;
7507 case 2:
7508 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
7509 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
7510 break;
7511 default: abort();
7513 } else {
7514 switch (size) {
7515 case 0:
7516 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
7517 break;
7518 case 1:
7519 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
7520 break;
7521 case 2:
7522 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
7523 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
7524 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
7525 break;
7526 default: abort();
7529 if (pass == 0) {
7530 tmp3 = tmp;
7531 } else {
7532 neon_store_reg(rd, 0, tmp3);
7533 neon_store_reg(rd, 1, tmp);
7535 } else {
7536 /* Write back the result. */
7537 neon_store_reg64(cpu_V0, rd + pass);
7540 } else {
7541 /* Two registers and a scalar. NB that for ops of this form
7542 * the ARM ARM labels bit 24 as Q, but it is in our variable
7543 * 'u', not 'q'.
7545 if (size == 0) {
7546 return 1;
7548 switch (op) {
7549 case 1: /* Float VMLA scalar */
7550 case 5: /* Floating point VMLS scalar */
7551 case 9: /* Floating point VMUL scalar */
7552 if (size == 1) {
7553 return 1;
7555 /* fall through */
7556 case 0: /* Integer VMLA scalar */
7557 case 4: /* Integer VMLS scalar */
7558 case 8: /* Integer VMUL scalar */
7559 case 12: /* VQDMULH scalar */
7560 case 13: /* VQRDMULH scalar */
7561 if (u && ((rd | rn) & 1)) {
7562 return 1;
7564 tmp = neon_get_scalar(size, rm);
7565 neon_store_scratch(0, tmp);
7566 for (pass = 0; pass < (u ? 4 : 2); pass++) {
7567 tmp = neon_load_scratch(0);
7568 tmp2 = neon_load_reg(rn, pass);
7569 if (op == 12) {
7570 if (size == 1) {
7571 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
7572 } else {
7573 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
7575 } else if (op == 13) {
7576 if (size == 1) {
7577 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
7578 } else {
7579 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
7581 } else if (op & 1) {
7582 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7583 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
7584 tcg_temp_free_ptr(fpstatus);
7585 } else {
7586 switch (size) {
7587 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
7588 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
7589 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
7590 default: abort();
7593 tcg_temp_free_i32(tmp2);
7594 if (op < 8) {
7595 /* Accumulate. */
7596 tmp2 = neon_load_reg(rd, pass);
7597 switch (op) {
7598 case 0:
7599 gen_neon_add(size, tmp, tmp2);
7600 break;
7601 case 1:
7603 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7604 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
7605 tcg_temp_free_ptr(fpstatus);
7606 break;
7608 case 4:
7609 gen_neon_rsb(size, tmp, tmp2);
7610 break;
7611 case 5:
7613 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7614 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
7615 tcg_temp_free_ptr(fpstatus);
7616 break;
7618 default:
7619 abort();
7621 tcg_temp_free_i32(tmp2);
7623 neon_store_reg(rd, pass, tmp);
7625 break;
7626 case 3: /* VQDMLAL scalar */
7627 case 7: /* VQDMLSL scalar */
7628 case 11: /* VQDMULL scalar */
7629 if (u == 1) {
7630 return 1;
7632 /* fall through */
7633 case 2: /* VMLAL sclar */
7634 case 6: /* VMLSL scalar */
7635 case 10: /* VMULL scalar */
7636 if (rd & 1) {
7637 return 1;
7639 tmp2 = neon_get_scalar(size, rm);
7640 /* We need a copy of tmp2 because gen_neon_mull
7641 * deletes it during pass 0. */
7642 tmp4 = tcg_temp_new_i32();
7643 tcg_gen_mov_i32(tmp4, tmp2);
7644 tmp3 = neon_load_reg(rn, 1);
7646 for (pass = 0; pass < 2; pass++) {
7647 if (pass == 0) {
7648 tmp = neon_load_reg(rn, 0);
7649 } else {
7650 tmp = tmp3;
7651 tmp2 = tmp4;
7653 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
7654 if (op != 11) {
7655 neon_load_reg64(cpu_V1, rd + pass);
7657 switch (op) {
7658 case 6:
7659 gen_neon_negl(cpu_V0, size);
7660 /* Fall through */
7661 case 2:
7662 gen_neon_addl(size);
7663 break;
7664 case 3: case 7:
7665 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
7666 if (op == 7) {
7667 gen_neon_negl(cpu_V0, size);
7669 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
7670 break;
7671 case 10:
7672 /* no-op */
7673 break;
7674 case 11:
7675 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
7676 break;
7677 default:
7678 abort();
7680 neon_store_reg64(cpu_V0, rd + pass);
7682 break;
7683 case 14: /* VQRDMLAH scalar */
7684 case 15: /* VQRDMLSH scalar */
7686 NeonGenThreeOpEnvFn *fn;
7688 if (!dc_isar_feature(aa32_rdm, s)) {
7689 return 1;
7691 if (u && ((rd | rn) & 1)) {
7692 return 1;
7694 if (op == 14) {
7695 if (size == 1) {
7696 fn = gen_helper_neon_qrdmlah_s16;
7697 } else {
7698 fn = gen_helper_neon_qrdmlah_s32;
7700 } else {
7701 if (size == 1) {
7702 fn = gen_helper_neon_qrdmlsh_s16;
7703 } else {
7704 fn = gen_helper_neon_qrdmlsh_s32;
7708 tmp2 = neon_get_scalar(size, rm);
7709 for (pass = 0; pass < (u ? 4 : 2); pass++) {
7710 tmp = neon_load_reg(rn, pass);
7711 tmp3 = neon_load_reg(rd, pass);
7712 fn(tmp, cpu_env, tmp, tmp2, tmp3);
7713 tcg_temp_free_i32(tmp3);
7714 neon_store_reg(rd, pass, tmp);
7716 tcg_temp_free_i32(tmp2);
7718 break;
7719 default:
7720 g_assert_not_reached();
7723 } else { /* size == 3 */
7724 if (!u) {
7725 /* Extract. */
7726 imm = (insn >> 8) & 0xf;
7728 if (imm > 7 && !q)
7729 return 1;
7731 if (q && ((rd | rn | rm) & 1)) {
7732 return 1;
7735 if (imm == 0) {
7736 neon_load_reg64(cpu_V0, rn);
7737 if (q) {
7738 neon_load_reg64(cpu_V1, rn + 1);
7740 } else if (imm == 8) {
7741 neon_load_reg64(cpu_V0, rn + 1);
7742 if (q) {
7743 neon_load_reg64(cpu_V1, rm);
7745 } else if (q) {
7746 tmp64 = tcg_temp_new_i64();
7747 if (imm < 8) {
7748 neon_load_reg64(cpu_V0, rn);
7749 neon_load_reg64(tmp64, rn + 1);
7750 } else {
7751 neon_load_reg64(cpu_V0, rn + 1);
7752 neon_load_reg64(tmp64, rm);
7754 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
7755 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
7756 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
7757 if (imm < 8) {
7758 neon_load_reg64(cpu_V1, rm);
7759 } else {
7760 neon_load_reg64(cpu_V1, rm + 1);
7761 imm -= 8;
7763 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
7764 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
7765 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
7766 tcg_temp_free_i64(tmp64);
7767 } else {
7768 /* BUGFIX */
7769 neon_load_reg64(cpu_V0, rn);
7770 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
7771 neon_load_reg64(cpu_V1, rm);
7772 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
7773 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
7775 neon_store_reg64(cpu_V0, rd);
7776 if (q) {
7777 neon_store_reg64(cpu_V1, rd + 1);
7779 } else if ((insn & (1 << 11)) == 0) {
7780 /* Two register misc. */
7781 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
7782 size = (insn >> 18) & 3;
7783 /* UNDEF for unknown op values and bad op-size combinations */
7784 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
7785 return 1;
7787 if (neon_2rm_is_v8_op(op) &&
7788 !arm_dc_feature(s, ARM_FEATURE_V8)) {
7789 return 1;
7791 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
7792 q && ((rm | rd) & 1)) {
7793 return 1;
7795 switch (op) {
7796 case NEON_2RM_VREV64:
7797 for (pass = 0; pass < (q ? 2 : 1); pass++) {
7798 tmp = neon_load_reg(rm, pass * 2);
7799 tmp2 = neon_load_reg(rm, pass * 2 + 1);
7800 switch (size) {
7801 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
7802 case 1: gen_swap_half(tmp); break;
7803 case 2: /* no-op */ break;
7804 default: abort();
7806 neon_store_reg(rd, pass * 2 + 1, tmp);
7807 if (size == 2) {
7808 neon_store_reg(rd, pass * 2, tmp2);
7809 } else {
7810 switch (size) {
7811 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
7812 case 1: gen_swap_half(tmp2); break;
7813 default: abort();
7815 neon_store_reg(rd, pass * 2, tmp2);
7818 break;
7819 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
7820 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
7821 for (pass = 0; pass < q + 1; pass++) {
7822 tmp = neon_load_reg(rm, pass * 2);
7823 gen_neon_widen(cpu_V0, tmp, size, op & 1);
7824 tmp = neon_load_reg(rm, pass * 2 + 1);
7825 gen_neon_widen(cpu_V1, tmp, size, op & 1);
7826 switch (size) {
7827 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
7828 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
7829 case 2: tcg_gen_add_i64(CPU_V001); break;
7830 default: abort();
7832 if (op >= NEON_2RM_VPADAL) {
7833 /* Accumulate. */
7834 neon_load_reg64(cpu_V1, rd + pass);
7835 gen_neon_addl(size);
7837 neon_store_reg64(cpu_V0, rd + pass);
7839 break;
7840 case NEON_2RM_VTRN:
7841 if (size == 2) {
7842 int n;
7843 for (n = 0; n < (q ? 4 : 2); n += 2) {
7844 tmp = neon_load_reg(rm, n);
7845 tmp2 = neon_load_reg(rd, n + 1);
7846 neon_store_reg(rm, n, tmp2);
7847 neon_store_reg(rd, n + 1, tmp);
7849 } else {
7850 goto elementwise;
7852 break;
7853 case NEON_2RM_VUZP:
7854 if (gen_neon_unzip(rd, rm, size, q)) {
7855 return 1;
7857 break;
7858 case NEON_2RM_VZIP:
7859 if (gen_neon_zip(rd, rm, size, q)) {
7860 return 1;
7862 break;
7863 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
7864 /* also VQMOVUN; op field and mnemonics don't line up */
7865 if (rm & 1) {
7866 return 1;
7868 tmp2 = NULL;
7869 for (pass = 0; pass < 2; pass++) {
7870 neon_load_reg64(cpu_V0, rm + pass);
7871 tmp = tcg_temp_new_i32();
7872 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
7873 tmp, cpu_V0);
7874 if (pass == 0) {
7875 tmp2 = tmp;
7876 } else {
7877 neon_store_reg(rd, 0, tmp2);
7878 neon_store_reg(rd, 1, tmp);
7881 break;
7882 case NEON_2RM_VSHLL:
7883 if (q || (rd & 1)) {
7884 return 1;
7886 tmp = neon_load_reg(rm, 0);
7887 tmp2 = neon_load_reg(rm, 1);
7888 for (pass = 0; pass < 2; pass++) {
7889 if (pass == 1)
7890 tmp = tmp2;
7891 gen_neon_widen(cpu_V0, tmp, size, 1);
7892 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
7893 neon_store_reg64(cpu_V0, rd + pass);
7895 break;
7896 case NEON_2RM_VCVT_F16_F32:
7898 TCGv_ptr fpst;
7899 TCGv_i32 ahp;
7901 if (!dc_isar_feature(aa32_fp16_spconv, s) ||
7902 q || (rm & 1)) {
7903 return 1;
7905 tmp = tcg_temp_new_i32();
7906 tmp2 = tcg_temp_new_i32();
7907 fpst = get_fpstatus_ptr(true);
7908 ahp = get_ahp_flag();
7909 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
7910 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, fpst, ahp);
7911 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
7912 gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, fpst, ahp);
7913 tcg_gen_shli_i32(tmp2, tmp2, 16);
7914 tcg_gen_or_i32(tmp2, tmp2, tmp);
7915 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
7916 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, fpst, ahp);
7917 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
7918 neon_store_reg(rd, 0, tmp2);
7919 tmp2 = tcg_temp_new_i32();
7920 gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, fpst, ahp);
7921 tcg_gen_shli_i32(tmp2, tmp2, 16);
7922 tcg_gen_or_i32(tmp2, tmp2, tmp);
7923 neon_store_reg(rd, 1, tmp2);
7924 tcg_temp_free_i32(tmp);
7925 tcg_temp_free_i32(ahp);
7926 tcg_temp_free_ptr(fpst);
7927 break;
7929 case NEON_2RM_VCVT_F32_F16:
7931 TCGv_ptr fpst;
7932 TCGv_i32 ahp;
7933 if (!dc_isar_feature(aa32_fp16_spconv, s) ||
7934 q || (rd & 1)) {
7935 return 1;
7937 fpst = get_fpstatus_ptr(true);
7938 ahp = get_ahp_flag();
7939 tmp3 = tcg_temp_new_i32();
7940 tmp = neon_load_reg(rm, 0);
7941 tmp2 = neon_load_reg(rm, 1);
7942 tcg_gen_ext16u_i32(tmp3, tmp);
7943 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
7944 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
7945 tcg_gen_shri_i32(tmp3, tmp, 16);
7946 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
7947 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
7948 tcg_temp_free_i32(tmp);
7949 tcg_gen_ext16u_i32(tmp3, tmp2);
7950 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
7951 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
7952 tcg_gen_shri_i32(tmp3, tmp2, 16);
7953 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
7954 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
7955 tcg_temp_free_i32(tmp2);
7956 tcg_temp_free_i32(tmp3);
7957 tcg_temp_free_i32(ahp);
7958 tcg_temp_free_ptr(fpst);
7959 break;
7961 case NEON_2RM_AESE: case NEON_2RM_AESMC:
7962 if (!dc_isar_feature(aa32_aes, s) || ((rm | rd) & 1)) {
7963 return 1;
7965 ptr1 = vfp_reg_ptr(true, rd);
7966 ptr2 = vfp_reg_ptr(true, rm);
7968 /* Bit 6 is the lowest opcode bit; it distinguishes between
7969 * encryption (AESE/AESMC) and decryption (AESD/AESIMC)
7971 tmp3 = tcg_const_i32(extract32(insn, 6, 1));
7973 if (op == NEON_2RM_AESE) {
7974 gen_helper_crypto_aese(ptr1, ptr2, tmp3);
7975 } else {
7976 gen_helper_crypto_aesmc(ptr1, ptr2, tmp3);
7978 tcg_temp_free_ptr(ptr1);
7979 tcg_temp_free_ptr(ptr2);
7980 tcg_temp_free_i32(tmp3);
7981 break;
7982 case NEON_2RM_SHA1H:
7983 if (!dc_isar_feature(aa32_sha1, s) || ((rm | rd) & 1)) {
7984 return 1;
7986 ptr1 = vfp_reg_ptr(true, rd);
7987 ptr2 = vfp_reg_ptr(true, rm);
7989 gen_helper_crypto_sha1h(ptr1, ptr2);
7991 tcg_temp_free_ptr(ptr1);
7992 tcg_temp_free_ptr(ptr2);
7993 break;
7994 case NEON_2RM_SHA1SU1:
7995 if ((rm | rd) & 1) {
7996 return 1;
7998 /* bit 6 (q): set -> SHA256SU0, cleared -> SHA1SU1 */
7999 if (q) {
8000 if (!dc_isar_feature(aa32_sha2, s)) {
8001 return 1;
8003 } else if (!dc_isar_feature(aa32_sha1, s)) {
8004 return 1;
8006 ptr1 = vfp_reg_ptr(true, rd);
8007 ptr2 = vfp_reg_ptr(true, rm);
8008 if (q) {
8009 gen_helper_crypto_sha256su0(ptr1, ptr2);
8010 } else {
8011 gen_helper_crypto_sha1su1(ptr1, ptr2);
8013 tcg_temp_free_ptr(ptr1);
8014 tcg_temp_free_ptr(ptr2);
8015 break;
8017 case NEON_2RM_VMVN:
8018 tcg_gen_gvec_not(0, rd_ofs, rm_ofs, vec_size, vec_size);
8019 break;
8020 case NEON_2RM_VNEG:
8021 tcg_gen_gvec_neg(size, rd_ofs, rm_ofs, vec_size, vec_size);
8022 break;
8024 default:
8025 elementwise:
8026 for (pass = 0; pass < (q ? 4 : 2); pass++) {
8027 if (neon_2rm_is_float_op(op)) {
8028 tcg_gen_ld_f32(cpu_F0s, cpu_env,
8029 neon_reg_offset(rm, pass));
8030 tmp = NULL;
8031 } else {
8032 tmp = neon_load_reg(rm, pass);
8034 switch (op) {
8035 case NEON_2RM_VREV32:
8036 switch (size) {
8037 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
8038 case 1: gen_swap_half(tmp); break;
8039 default: abort();
8041 break;
8042 case NEON_2RM_VREV16:
8043 gen_rev16(tmp);
8044 break;
8045 case NEON_2RM_VCLS:
8046 switch (size) {
8047 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
8048 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
8049 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
8050 default: abort();
8052 break;
8053 case NEON_2RM_VCLZ:
8054 switch (size) {
8055 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
8056 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
8057 case 2: tcg_gen_clzi_i32(tmp, tmp, 32); break;
8058 default: abort();
8060 break;
8061 case NEON_2RM_VCNT:
8062 gen_helper_neon_cnt_u8(tmp, tmp);
8063 break;
8064 case NEON_2RM_VQABS:
8065 switch (size) {
8066 case 0:
8067 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
8068 break;
8069 case 1:
8070 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
8071 break;
8072 case 2:
8073 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
8074 break;
8075 default: abort();
8077 break;
8078 case NEON_2RM_VQNEG:
8079 switch (size) {
8080 case 0:
8081 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
8082 break;
8083 case 1:
8084 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
8085 break;
8086 case 2:
8087 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
8088 break;
8089 default: abort();
8091 break;
8092 case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
8093 tmp2 = tcg_const_i32(0);
8094 switch(size) {
8095 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
8096 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
8097 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
8098 default: abort();
8100 tcg_temp_free_i32(tmp2);
8101 if (op == NEON_2RM_VCLE0) {
8102 tcg_gen_not_i32(tmp, tmp);
8104 break;
8105 case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
8106 tmp2 = tcg_const_i32(0);
8107 switch(size) {
8108 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
8109 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
8110 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
8111 default: abort();
8113 tcg_temp_free_i32(tmp2);
8114 if (op == NEON_2RM_VCLT0) {
8115 tcg_gen_not_i32(tmp, tmp);
8117 break;
8118 case NEON_2RM_VCEQ0:
8119 tmp2 = tcg_const_i32(0);
8120 switch(size) {
8121 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
8122 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
8123 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
8124 default: abort();
8126 tcg_temp_free_i32(tmp2);
8127 break;
8128 case NEON_2RM_VABS:
8129 switch(size) {
8130 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
8131 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
8132 case 2: tcg_gen_abs_i32(tmp, tmp); break;
8133 default: abort();
8135 break;
8136 case NEON_2RM_VCGT0_F:
8138 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8139 tmp2 = tcg_const_i32(0);
8140 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
8141 tcg_temp_free_i32(tmp2);
8142 tcg_temp_free_ptr(fpstatus);
8143 break;
8145 case NEON_2RM_VCGE0_F:
8147 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8148 tmp2 = tcg_const_i32(0);
8149 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
8150 tcg_temp_free_i32(tmp2);
8151 tcg_temp_free_ptr(fpstatus);
8152 break;
8154 case NEON_2RM_VCEQ0_F:
8156 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8157 tmp2 = tcg_const_i32(0);
8158 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
8159 tcg_temp_free_i32(tmp2);
8160 tcg_temp_free_ptr(fpstatus);
8161 break;
8163 case NEON_2RM_VCLE0_F:
8165 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8166 tmp2 = tcg_const_i32(0);
8167 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
8168 tcg_temp_free_i32(tmp2);
8169 tcg_temp_free_ptr(fpstatus);
8170 break;
8172 case NEON_2RM_VCLT0_F:
8174 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8175 tmp2 = tcg_const_i32(0);
8176 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
8177 tcg_temp_free_i32(tmp2);
8178 tcg_temp_free_ptr(fpstatus);
8179 break;
8181 case NEON_2RM_VABS_F:
8182 gen_vfp_abs(0);
8183 break;
8184 case NEON_2RM_VNEG_F:
8185 gen_vfp_neg(0);
8186 break;
8187 case NEON_2RM_VSWP:
8188 tmp2 = neon_load_reg(rd, pass);
8189 neon_store_reg(rm, pass, tmp2);
8190 break;
8191 case NEON_2RM_VTRN:
8192 tmp2 = neon_load_reg(rd, pass);
8193 switch (size) {
8194 case 0: gen_neon_trn_u8(tmp, tmp2); break;
8195 case 1: gen_neon_trn_u16(tmp, tmp2); break;
8196 default: abort();
8198 neon_store_reg(rm, pass, tmp2);
8199 break;
8200 case NEON_2RM_VRINTN:
8201 case NEON_2RM_VRINTA:
8202 case NEON_2RM_VRINTM:
8203 case NEON_2RM_VRINTP:
8204 case NEON_2RM_VRINTZ:
8206 TCGv_i32 tcg_rmode;
8207 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8208 int rmode;
8210 if (op == NEON_2RM_VRINTZ) {
8211 rmode = FPROUNDING_ZERO;
8212 } else {
8213 rmode = fp_decode_rm[((op & 0x6) >> 1) ^ 1];
8216 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
8217 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
8218 cpu_env);
8219 gen_helper_rints(cpu_F0s, cpu_F0s, fpstatus);
8220 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
8221 cpu_env);
8222 tcg_temp_free_ptr(fpstatus);
8223 tcg_temp_free_i32(tcg_rmode);
8224 break;
8226 case NEON_2RM_VRINTX:
8228 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8229 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpstatus);
8230 tcg_temp_free_ptr(fpstatus);
8231 break;
8233 case NEON_2RM_VCVTAU:
8234 case NEON_2RM_VCVTAS:
8235 case NEON_2RM_VCVTNU:
8236 case NEON_2RM_VCVTNS:
8237 case NEON_2RM_VCVTPU:
8238 case NEON_2RM_VCVTPS:
8239 case NEON_2RM_VCVTMU:
8240 case NEON_2RM_VCVTMS:
8242 bool is_signed = !extract32(insn, 7, 1);
8243 TCGv_ptr fpst = get_fpstatus_ptr(1);
8244 TCGv_i32 tcg_rmode, tcg_shift;
8245 int rmode = fp_decode_rm[extract32(insn, 8, 2)];
8247 tcg_shift = tcg_const_i32(0);
8248 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
8249 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
8250 cpu_env);
8252 if (is_signed) {
8253 gen_helper_vfp_tosls(cpu_F0s, cpu_F0s,
8254 tcg_shift, fpst);
8255 } else {
8256 gen_helper_vfp_touls(cpu_F0s, cpu_F0s,
8257 tcg_shift, fpst);
8260 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
8261 cpu_env);
8262 tcg_temp_free_i32(tcg_rmode);
8263 tcg_temp_free_i32(tcg_shift);
8264 tcg_temp_free_ptr(fpst);
8265 break;
8267 case NEON_2RM_VRECPE:
8269 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8270 gen_helper_recpe_u32(tmp, tmp, fpstatus);
8271 tcg_temp_free_ptr(fpstatus);
8272 break;
8274 case NEON_2RM_VRSQRTE:
8276 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8277 gen_helper_rsqrte_u32(tmp, tmp, fpstatus);
8278 tcg_temp_free_ptr(fpstatus);
8279 break;
8281 case NEON_2RM_VRECPE_F:
8283 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8284 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, fpstatus);
8285 tcg_temp_free_ptr(fpstatus);
8286 break;
8288 case NEON_2RM_VRSQRTE_F:
8290 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8291 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, fpstatus);
8292 tcg_temp_free_ptr(fpstatus);
8293 break;
8295 case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
8296 gen_vfp_sito(0, 1);
8297 break;
8298 case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
8299 gen_vfp_uito(0, 1);
8300 break;
8301 case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
8302 gen_vfp_tosiz(0, 1);
8303 break;
8304 case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
8305 gen_vfp_touiz(0, 1);
8306 break;
8307 default:
8308 /* Reserved op values were caught by the
8309 * neon_2rm_sizes[] check earlier.
8311 abort();
8313 if (neon_2rm_is_float_op(op)) {
8314 tcg_gen_st_f32(cpu_F0s, cpu_env,
8315 neon_reg_offset(rd, pass));
8316 } else {
8317 neon_store_reg(rd, pass, tmp);
8320 break;
8322 } else if ((insn & (1 << 10)) == 0) {
8323 /* VTBL, VTBX. */
8324 int n = ((insn >> 8) & 3) + 1;
8325 if ((rn + n) > 32) {
8326 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
8327 * helper function running off the end of the register file.
8329 return 1;
8331 n <<= 3;
8332 if (insn & (1 << 6)) {
8333 tmp = neon_load_reg(rd, 0);
8334 } else {
8335 tmp = tcg_temp_new_i32();
8336 tcg_gen_movi_i32(tmp, 0);
8338 tmp2 = neon_load_reg(rm, 0);
8339 ptr1 = vfp_reg_ptr(true, rn);
8340 tmp5 = tcg_const_i32(n);
8341 gen_helper_neon_tbl(tmp2, tmp2, tmp, ptr1, tmp5);
8342 tcg_temp_free_i32(tmp);
8343 if (insn & (1 << 6)) {
8344 tmp = neon_load_reg(rd, 1);
8345 } else {
8346 tmp = tcg_temp_new_i32();
8347 tcg_gen_movi_i32(tmp, 0);
8349 tmp3 = neon_load_reg(rm, 1);
8350 gen_helper_neon_tbl(tmp3, tmp3, tmp, ptr1, tmp5);
8351 tcg_temp_free_i32(tmp5);
8352 tcg_temp_free_ptr(ptr1);
8353 neon_store_reg(rd, 0, tmp2);
8354 neon_store_reg(rd, 1, tmp3);
8355 tcg_temp_free_i32(tmp);
8356 } else if ((insn & 0x380) == 0) {
8357 /* VDUP */
8358 int element;
8359 TCGMemOp size;
8361 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
8362 return 1;
8364 if (insn & (1 << 16)) {
8365 size = MO_8;
8366 element = (insn >> 17) & 7;
8367 } else if (insn & (1 << 17)) {
8368 size = MO_16;
8369 element = (insn >> 18) & 3;
8370 } else {
8371 size = MO_32;
8372 element = (insn >> 19) & 1;
8374 tcg_gen_gvec_dup_mem(size, neon_reg_offset(rd, 0),
8375 neon_element_offset(rm, element, size),
8376 q ? 16 : 8, q ? 16 : 8);
8377 } else {
8378 return 1;
8382 return 0;
8385 /* Advanced SIMD three registers of the same length extension.
8386 * 31 25 23 22 20 16 12 11 10 9 8 3 0
8387 * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
8388 * | 1 1 1 1 1 1 0 | op1 | D | op2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
8389 * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
8391 static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
8393 gen_helper_gvec_3 *fn_gvec = NULL;
8394 gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
8395 int rd, rn, rm, opr_sz;
8396 int data = 0;
8397 int off_rn, off_rm;
8398 bool is_long = false, q = extract32(insn, 6, 1);
8399 bool ptr_is_env = false;
8401 if ((insn & 0xfe200f10) == 0xfc200800) {
8402 /* VCMLA -- 1111 110R R.1S .... .... 1000 ...0 .... */
8403 int size = extract32(insn, 20, 1);
8404 data = extract32(insn, 23, 2); /* rot */
8405 if (!dc_isar_feature(aa32_vcma, s)
8406 || (!size && !dc_isar_feature(aa32_fp16_arith, s))) {
8407 return 1;
8409 fn_gvec_ptr = size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
8410 } else if ((insn & 0xfea00f10) == 0xfc800800) {
8411 /* VCADD -- 1111 110R 1.0S .... .... 1000 ...0 .... */
8412 int size = extract32(insn, 20, 1);
8413 data = extract32(insn, 24, 1); /* rot */
8414 if (!dc_isar_feature(aa32_vcma, s)
8415 || (!size && !dc_isar_feature(aa32_fp16_arith, s))) {
8416 return 1;
8418 fn_gvec_ptr = size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
8419 } else if ((insn & 0xfeb00f00) == 0xfc200d00) {
8420 /* V[US]DOT -- 1111 1100 0.10 .... .... 1101 .Q.U .... */
8421 bool u = extract32(insn, 4, 1);
8422 if (!dc_isar_feature(aa32_dp, s)) {
8423 return 1;
8425 fn_gvec = u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b;
8426 } else if ((insn & 0xff300f10) == 0xfc200810) {
8427 /* VFM[AS]L -- 1111 1100 S.10 .... .... 1000 .Q.1 .... */
8428 int is_s = extract32(insn, 23, 1);
8429 if (!dc_isar_feature(aa32_fhm, s)) {
8430 return 1;
8432 is_long = true;
8433 data = is_s; /* is_2 == 0 */
8434 fn_gvec_ptr = gen_helper_gvec_fmlal_a32;
8435 ptr_is_env = true;
8436 } else {
8437 return 1;
8440 VFP_DREG_D(rd, insn);
8441 if (rd & q) {
8442 return 1;
8444 if (q || !is_long) {
8445 VFP_DREG_N(rn, insn);
8446 VFP_DREG_M(rm, insn);
8447 if ((rn | rm) & q & !is_long) {
8448 return 1;
8450 off_rn = vfp_reg_offset(1, rn);
8451 off_rm = vfp_reg_offset(1, rm);
8452 } else {
8453 rn = VFP_SREG_N(insn);
8454 rm = VFP_SREG_M(insn);
8455 off_rn = vfp_reg_offset(0, rn);
8456 off_rm = vfp_reg_offset(0, rm);
8459 if (s->fp_excp_el) {
8460 gen_exception_insn(s, 4, EXCP_UDEF,
8461 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
8462 return 0;
8464 if (!s->vfp_enabled) {
8465 return 1;
8468 opr_sz = (1 + q) * 8;
8469 if (fn_gvec_ptr) {
8470 TCGv_ptr ptr;
8471 if (ptr_is_env) {
8472 ptr = cpu_env;
8473 } else {
8474 ptr = get_fpstatus_ptr(1);
8476 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
8477 opr_sz, opr_sz, data, fn_gvec_ptr);
8478 if (!ptr_is_env) {
8479 tcg_temp_free_ptr(ptr);
8481 } else {
8482 tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
8483 opr_sz, opr_sz, data, fn_gvec);
8485 return 0;
8488 /* Advanced SIMD two registers and a scalar extension.
8489 * 31 24 23 22 20 16 12 11 10 9 8 3 0
8490 * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
8491 * | 1 1 1 1 1 1 1 0 | o1 | D | o2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
8492 * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
8496 static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
8498 gen_helper_gvec_3 *fn_gvec = NULL;
8499 gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
8500 int rd, rn, rm, opr_sz, data;
8501 int off_rn, off_rm;
8502 bool is_long = false, q = extract32(insn, 6, 1);
8503 bool ptr_is_env = false;
8505 if ((insn & 0xff000f10) == 0xfe000800) {
8506 /* VCMLA (indexed) -- 1111 1110 S.RR .... .... 1000 ...0 .... */
8507 int rot = extract32(insn, 20, 2);
8508 int size = extract32(insn, 23, 1);
8509 int index;
8511 if (!dc_isar_feature(aa32_vcma, s)) {
8512 return 1;
8514 if (size == 0) {
8515 if (!dc_isar_feature(aa32_fp16_arith, s)) {
8516 return 1;
8518 /* For fp16, rm is just Vm, and index is M. */
8519 rm = extract32(insn, 0, 4);
8520 index = extract32(insn, 5, 1);
8521 } else {
8522 /* For fp32, rm is the usual M:Vm, and index is 0. */
8523 VFP_DREG_M(rm, insn);
8524 index = 0;
8526 data = (index << 2) | rot;
8527 fn_gvec_ptr = (size ? gen_helper_gvec_fcmlas_idx
8528 : gen_helper_gvec_fcmlah_idx);
8529 } else if ((insn & 0xffb00f00) == 0xfe200d00) {
8530 /* V[US]DOT -- 1111 1110 0.10 .... .... 1101 .Q.U .... */
8531 int u = extract32(insn, 4, 1);
8533 if (!dc_isar_feature(aa32_dp, s)) {
8534 return 1;
8536 fn_gvec = u ? gen_helper_gvec_udot_idx_b : gen_helper_gvec_sdot_idx_b;
8537 /* rm is just Vm, and index is M. */
8538 data = extract32(insn, 5, 1); /* index */
8539 rm = extract32(insn, 0, 4);
8540 } else if ((insn & 0xffa00f10) == 0xfe000810) {
8541 /* VFM[AS]L -- 1111 1110 0.0S .... .... 1000 .Q.1 .... */
8542 int is_s = extract32(insn, 20, 1);
8543 int vm20 = extract32(insn, 0, 3);
8544 int vm3 = extract32(insn, 3, 1);
8545 int m = extract32(insn, 5, 1);
8546 int index;
8548 if (!dc_isar_feature(aa32_fhm, s)) {
8549 return 1;
8551 if (q) {
8552 rm = vm20;
8553 index = m * 2 + vm3;
8554 } else {
8555 rm = vm20 * 2 + m;
8556 index = vm3;
8558 is_long = true;
8559 data = (index << 2) | is_s; /* is_2 == 0 */
8560 fn_gvec_ptr = gen_helper_gvec_fmlal_idx_a32;
8561 ptr_is_env = true;
8562 } else {
8563 return 1;
8566 VFP_DREG_D(rd, insn);
8567 if (rd & q) {
8568 return 1;
8570 if (q || !is_long) {
8571 VFP_DREG_N(rn, insn);
8572 if (rn & q & !is_long) {
8573 return 1;
8575 off_rn = vfp_reg_offset(1, rn);
8576 off_rm = vfp_reg_offset(1, rm);
8577 } else {
8578 rn = VFP_SREG_N(insn);
8579 off_rn = vfp_reg_offset(0, rn);
8580 off_rm = vfp_reg_offset(0, rm);
8582 if (s->fp_excp_el) {
8583 gen_exception_insn(s, 4, EXCP_UDEF,
8584 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
8585 return 0;
8587 if (!s->vfp_enabled) {
8588 return 1;
8591 opr_sz = (1 + q) * 8;
8592 if (fn_gvec_ptr) {
8593 TCGv_ptr ptr;
8594 if (ptr_is_env) {
8595 ptr = cpu_env;
8596 } else {
8597 ptr = get_fpstatus_ptr(1);
8599 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
8600 opr_sz, opr_sz, data, fn_gvec_ptr);
8601 if (!ptr_is_env) {
8602 tcg_temp_free_ptr(ptr);
8604 } else {
8605 tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
8606 opr_sz, opr_sz, data, fn_gvec);
8608 return 0;
8611 static int disas_coproc_insn(DisasContext *s, uint32_t insn)
8613 int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
8614 const ARMCPRegInfo *ri;
8616 cpnum = (insn >> 8) & 0xf;
8618 /* First check for coprocessor space used for XScale/iwMMXt insns */
8619 if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cpnum < 2)) {
8620 if (extract32(s->c15_cpar, cpnum, 1) == 0) {
8621 return 1;
8623 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
8624 return disas_iwmmxt_insn(s, insn);
8625 } else if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
8626 return disas_dsp_insn(s, insn);
8628 return 1;
8631 /* Otherwise treat as a generic register access */
8632 is64 = (insn & (1 << 25)) == 0;
8633 if (!is64 && ((insn & (1 << 4)) == 0)) {
8634 /* cdp */
8635 return 1;
8638 crm = insn & 0xf;
8639 if (is64) {
8640 crn = 0;
8641 opc1 = (insn >> 4) & 0xf;
8642 opc2 = 0;
8643 rt2 = (insn >> 16) & 0xf;
8644 } else {
8645 crn = (insn >> 16) & 0xf;
8646 opc1 = (insn >> 21) & 7;
8647 opc2 = (insn >> 5) & 7;
8648 rt2 = 0;
8650 isread = (insn >> 20) & 1;
8651 rt = (insn >> 12) & 0xf;
8653 ri = get_arm_cp_reginfo(s->cp_regs,
8654 ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
8655 if (ri) {
8656 /* Check access permissions */
8657 if (!cp_access_ok(s->current_el, ri, isread)) {
8658 return 1;
8661 if (ri->accessfn ||
8662 (arm_dc_feature(s, ARM_FEATURE_XSCALE) && cpnum < 14)) {
8663 /* Emit code to perform further access permissions checks at
8664 * runtime; this may result in an exception.
8665 * Note that on XScale all cp0..c13 registers do an access check
8666 * call in order to handle c15_cpar.
8668 TCGv_ptr tmpptr;
8669 TCGv_i32 tcg_syn, tcg_isread;
8670 uint32_t syndrome;
8672 /* Note that since we are an implementation which takes an
8673 * exception on a trapped conditional instruction only if the
8674 * instruction passes its condition code check, we can take
8675 * advantage of the clause in the ARM ARM that allows us to set
8676 * the COND field in the instruction to 0xE in all cases.
8677 * We could fish the actual condition out of the insn (ARM)
8678 * or the condexec bits (Thumb) but it isn't necessary.
8680 switch (cpnum) {
8681 case 14:
8682 if (is64) {
8683 syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
8684 isread, false);
8685 } else {
8686 syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
8687 rt, isread, false);
8689 break;
8690 case 15:
8691 if (is64) {
8692 syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
8693 isread, false);
8694 } else {
8695 syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
8696 rt, isread, false);
8698 break;
8699 default:
8700 /* ARMv8 defines that only coprocessors 14 and 15 exist,
8701 * so this can only happen if this is an ARMv7 or earlier CPU,
8702 * in which case the syndrome information won't actually be
8703 * guest visible.
8705 assert(!arm_dc_feature(s, ARM_FEATURE_V8));
8706 syndrome = syn_uncategorized();
8707 break;
8710 gen_set_condexec(s);
8711 gen_set_pc_im(s, s->pc - 4);
8712 tmpptr = tcg_const_ptr(ri);
8713 tcg_syn = tcg_const_i32(syndrome);
8714 tcg_isread = tcg_const_i32(isread);
8715 gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn,
8716 tcg_isread);
8717 tcg_temp_free_ptr(tmpptr);
8718 tcg_temp_free_i32(tcg_syn);
8719 tcg_temp_free_i32(tcg_isread);
8722 /* Handle special cases first */
8723 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
8724 case ARM_CP_NOP:
8725 return 0;
8726 case ARM_CP_WFI:
8727 if (isread) {
8728 return 1;
8730 gen_set_pc_im(s, s->pc);
8731 s->base.is_jmp = DISAS_WFI;
8732 return 0;
8733 default:
8734 break;
8737 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
8738 gen_io_start();
8741 if (isread) {
8742 /* Read */
8743 if (is64) {
8744 TCGv_i64 tmp64;
8745 TCGv_i32 tmp;
8746 if (ri->type & ARM_CP_CONST) {
8747 tmp64 = tcg_const_i64(ri->resetvalue);
8748 } else if (ri->readfn) {
8749 TCGv_ptr tmpptr;
8750 tmp64 = tcg_temp_new_i64();
8751 tmpptr = tcg_const_ptr(ri);
8752 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
8753 tcg_temp_free_ptr(tmpptr);
8754 } else {
8755 tmp64 = tcg_temp_new_i64();
8756 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
8758 tmp = tcg_temp_new_i32();
8759 tcg_gen_extrl_i64_i32(tmp, tmp64);
8760 store_reg(s, rt, tmp);
8761 tcg_gen_shri_i64(tmp64, tmp64, 32);
8762 tmp = tcg_temp_new_i32();
8763 tcg_gen_extrl_i64_i32(tmp, tmp64);
8764 tcg_temp_free_i64(tmp64);
8765 store_reg(s, rt2, tmp);
8766 } else {
8767 TCGv_i32 tmp;
8768 if (ri->type & ARM_CP_CONST) {
8769 tmp = tcg_const_i32(ri->resetvalue);
8770 } else if (ri->readfn) {
8771 TCGv_ptr tmpptr;
8772 tmp = tcg_temp_new_i32();
8773 tmpptr = tcg_const_ptr(ri);
8774 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
8775 tcg_temp_free_ptr(tmpptr);
8776 } else {
8777 tmp = load_cpu_offset(ri->fieldoffset);
8779 if (rt == 15) {
8780 /* Destination register of r15 for 32 bit loads sets
8781 * the condition codes from the high 4 bits of the value
8783 gen_set_nzcv(tmp);
8784 tcg_temp_free_i32(tmp);
8785 } else {
8786 store_reg(s, rt, tmp);
8789 } else {
8790 /* Write */
8791 if (ri->type & ARM_CP_CONST) {
8792 /* If not forbidden by access permissions, treat as WI */
8793 return 0;
8796 if (is64) {
8797 TCGv_i32 tmplo, tmphi;
8798 TCGv_i64 tmp64 = tcg_temp_new_i64();
8799 tmplo = load_reg(s, rt);
8800 tmphi = load_reg(s, rt2);
8801 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
8802 tcg_temp_free_i32(tmplo);
8803 tcg_temp_free_i32(tmphi);
8804 if (ri->writefn) {
8805 TCGv_ptr tmpptr = tcg_const_ptr(ri);
8806 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
8807 tcg_temp_free_ptr(tmpptr);
8808 } else {
8809 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
8811 tcg_temp_free_i64(tmp64);
8812 } else {
8813 if (ri->writefn) {
8814 TCGv_i32 tmp;
8815 TCGv_ptr tmpptr;
8816 tmp = load_reg(s, rt);
8817 tmpptr = tcg_const_ptr(ri);
8818 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
8819 tcg_temp_free_ptr(tmpptr);
8820 tcg_temp_free_i32(tmp);
8821 } else {
8822 TCGv_i32 tmp = load_reg(s, rt);
8823 store_cpu_offset(tmp, ri->fieldoffset);
8828 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
8829 /* I/O operations must end the TB here (whether read or write) */
8830 gen_io_end();
8831 gen_lookup_tb(s);
8832 } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
8833 /* We default to ending the TB on a coprocessor register write,
8834 * but allow this to be suppressed by the register definition
8835 * (usually only necessary to work around guest bugs).
8837 gen_lookup_tb(s);
8840 return 0;
8843 /* Unknown register; this might be a guest error or a QEMU
8844 * unimplemented feature.
8846 if (is64) {
8847 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
8848 "64 bit system register cp:%d opc1: %d crm:%d "
8849 "(%s)\n",
8850 isread ? "read" : "write", cpnum, opc1, crm,
8851 s->ns ? "non-secure" : "secure");
8852 } else {
8853 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
8854 "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d "
8855 "(%s)\n",
8856 isread ? "read" : "write", cpnum, opc1, crn, crm, opc2,
8857 s->ns ? "non-secure" : "secure");
8860 return 1;
8864 /* Store a 64-bit value to a register pair. Clobbers val. */
8865 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
8867 TCGv_i32 tmp;
8868 tmp = tcg_temp_new_i32();
8869 tcg_gen_extrl_i64_i32(tmp, val);
8870 store_reg(s, rlow, tmp);
8871 tmp = tcg_temp_new_i32();
8872 tcg_gen_shri_i64(val, val, 32);
8873 tcg_gen_extrl_i64_i32(tmp, val);
8874 store_reg(s, rhigh, tmp);
8877 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
8878 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
8880 TCGv_i64 tmp;
8881 TCGv_i32 tmp2;
8883 /* Load value and extend to 64 bits. */
8884 tmp = tcg_temp_new_i64();
8885 tmp2 = load_reg(s, rlow);
8886 tcg_gen_extu_i32_i64(tmp, tmp2);
8887 tcg_temp_free_i32(tmp2);
8888 tcg_gen_add_i64(val, val, tmp);
8889 tcg_temp_free_i64(tmp);
8892 /* load and add a 64-bit value from a register pair. */
8893 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
8895 TCGv_i64 tmp;
8896 TCGv_i32 tmpl;
8897 TCGv_i32 tmph;
8899 /* Load 64-bit value rd:rn. */
8900 tmpl = load_reg(s, rlow);
8901 tmph = load_reg(s, rhigh);
8902 tmp = tcg_temp_new_i64();
8903 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
8904 tcg_temp_free_i32(tmpl);
8905 tcg_temp_free_i32(tmph);
8906 tcg_gen_add_i64(val, val, tmp);
8907 tcg_temp_free_i64(tmp);
8910 /* Set N and Z flags from hi|lo. */
8911 static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
8913 tcg_gen_mov_i32(cpu_NF, hi);
8914 tcg_gen_or_i32(cpu_ZF, lo, hi);
8917 /* Load/Store exclusive instructions are implemented by remembering
8918 the value/address loaded, and seeing if these are the same
8919 when the store is performed. This should be sufficient to implement
8920 the architecturally mandated semantics, and avoids having to monitor
8921 regular stores. The compare vs the remembered value is done during
8922 the cmpxchg operation, but we must compare the addresses manually. */
8923 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
8924 TCGv_i32 addr, int size)
8926 TCGv_i32 tmp = tcg_temp_new_i32();
8927 TCGMemOp opc = size | MO_ALIGN | s->be_data;
8929 s->is_ldex = true;
8931 if (size == 3) {
8932 TCGv_i32 tmp2 = tcg_temp_new_i32();
8933 TCGv_i64 t64 = tcg_temp_new_i64();
8935 /* For AArch32, architecturally the 32-bit word at the lowest
8936 * address is always Rt and the one at addr+4 is Rt2, even if
8937 * the CPU is big-endian. That means we don't want to do a
8938 * gen_aa32_ld_i64(), which invokes gen_aa32_frob64() as if
8939 * for an architecturally 64-bit access, but instead do a
8940 * 64-bit access using MO_BE if appropriate and then split
8941 * the two halves.
8942 * This only makes a difference for BE32 user-mode, where
8943 * frob64() must not flip the two halves of the 64-bit data
8944 * but this code must treat BE32 user-mode like BE32 system.
8946 TCGv taddr = gen_aa32_addr(s, addr, opc);
8948 tcg_gen_qemu_ld_i64(t64, taddr, get_mem_index(s), opc);
8949 tcg_temp_free(taddr);
8950 tcg_gen_mov_i64(cpu_exclusive_val, t64);
8951 if (s->be_data == MO_BE) {
8952 tcg_gen_extr_i64_i32(tmp2, tmp, t64);
8953 } else {
8954 tcg_gen_extr_i64_i32(tmp, tmp2, t64);
8956 tcg_temp_free_i64(t64);
8958 store_reg(s, rt2, tmp2);
8959 } else {
8960 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), opc);
8961 tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
8964 store_reg(s, rt, tmp);
8965 tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
8968 static void gen_clrex(DisasContext *s)
8970 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
8973 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
8974 TCGv_i32 addr, int size)
8976 TCGv_i32 t0, t1, t2;
8977 TCGv_i64 extaddr;
8978 TCGv taddr;
8979 TCGLabel *done_label;
8980 TCGLabel *fail_label;
8981 TCGMemOp opc = size | MO_ALIGN | s->be_data;
8983 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
8984 [addr] = {Rt};
8985 {Rd} = 0;
8986 } else {
8987 {Rd} = 1;
8988 } */
8989 fail_label = gen_new_label();
8990 done_label = gen_new_label();
8991 extaddr = tcg_temp_new_i64();
8992 tcg_gen_extu_i32_i64(extaddr, addr);
8993 tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
8994 tcg_temp_free_i64(extaddr);
8996 taddr = gen_aa32_addr(s, addr, opc);
8997 t0 = tcg_temp_new_i32();
8998 t1 = load_reg(s, rt);
8999 if (size == 3) {
9000 TCGv_i64 o64 = tcg_temp_new_i64();
9001 TCGv_i64 n64 = tcg_temp_new_i64();
9003 t2 = load_reg(s, rt2);
9004 /* For AArch32, architecturally the 32-bit word at the lowest
9005 * address is always Rt and the one at addr+4 is Rt2, even if
9006 * the CPU is big-endian. Since we're going to treat this as a
9007 * single 64-bit BE store, we need to put the two halves in the
9008 * opposite order for BE to LE, so that they end up in the right
9009 * places.
9010 * We don't want gen_aa32_frob64() because that does the wrong
9011 * thing for BE32 usermode.
9013 if (s->be_data == MO_BE) {
9014 tcg_gen_concat_i32_i64(n64, t2, t1);
9015 } else {
9016 tcg_gen_concat_i32_i64(n64, t1, t2);
9018 tcg_temp_free_i32(t2);
9020 tcg_gen_atomic_cmpxchg_i64(o64, taddr, cpu_exclusive_val, n64,
9021 get_mem_index(s), opc);
9022 tcg_temp_free_i64(n64);
9024 tcg_gen_setcond_i64(TCG_COND_NE, o64, o64, cpu_exclusive_val);
9025 tcg_gen_extrl_i64_i32(t0, o64);
9027 tcg_temp_free_i64(o64);
9028 } else {
9029 t2 = tcg_temp_new_i32();
9030 tcg_gen_extrl_i64_i32(t2, cpu_exclusive_val);
9031 tcg_gen_atomic_cmpxchg_i32(t0, taddr, t2, t1, get_mem_index(s), opc);
9032 tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t2);
9033 tcg_temp_free_i32(t2);
9035 tcg_temp_free_i32(t1);
9036 tcg_temp_free(taddr);
9037 tcg_gen_mov_i32(cpu_R[rd], t0);
9038 tcg_temp_free_i32(t0);
9039 tcg_gen_br(done_label);
9041 gen_set_label(fail_label);
9042 tcg_gen_movi_i32(cpu_R[rd], 1);
9043 gen_set_label(done_label);
9044 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
9047 /* gen_srs:
9048 * @env: CPUARMState
9049 * @s: DisasContext
9050 * @mode: mode field from insn (which stack to store to)
9051 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
9052 * @writeback: true if writeback bit set
9054 * Generate code for the SRS (Store Return State) insn.
9056 static void gen_srs(DisasContext *s,
9057 uint32_t mode, uint32_t amode, bool writeback)
9059 int32_t offset;
9060 TCGv_i32 addr, tmp;
9061 bool undef = false;
9063 /* SRS is:
9064 * - trapped to EL3 if EL3 is AArch64 and we are at Secure EL1
9065 * and specified mode is monitor mode
9066 * - UNDEFINED in Hyp mode
9067 * - UNPREDICTABLE in User or System mode
9068 * - UNPREDICTABLE if the specified mode is:
9069 * -- not implemented
9070 * -- not a valid mode number
9071 * -- a mode that's at a higher exception level
9072 * -- Monitor, if we are Non-secure
9073 * For the UNPREDICTABLE cases we choose to UNDEF.
9075 if (s->current_el == 1 && !s->ns && mode == ARM_CPU_MODE_MON) {
9076 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), 3);
9077 return;
9080 if (s->current_el == 0 || s->current_el == 2) {
9081 undef = true;
9084 switch (mode) {
9085 case ARM_CPU_MODE_USR:
9086 case ARM_CPU_MODE_FIQ:
9087 case ARM_CPU_MODE_IRQ:
9088 case ARM_CPU_MODE_SVC:
9089 case ARM_CPU_MODE_ABT:
9090 case ARM_CPU_MODE_UND:
9091 case ARM_CPU_MODE_SYS:
9092 break;
9093 case ARM_CPU_MODE_HYP:
9094 if (s->current_el == 1 || !arm_dc_feature(s, ARM_FEATURE_EL2)) {
9095 undef = true;
9097 break;
9098 case ARM_CPU_MODE_MON:
9099 /* No need to check specifically for "are we non-secure" because
9100 * we've already made EL0 UNDEF and handled the trap for S-EL1;
9101 * so if this isn't EL3 then we must be non-secure.
9103 if (s->current_el != 3) {
9104 undef = true;
9106 break;
9107 default:
9108 undef = true;
9111 if (undef) {
9112 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
9113 default_exception_el(s));
9114 return;
9117 addr = tcg_temp_new_i32();
9118 tmp = tcg_const_i32(mode);
9119 /* get_r13_banked() will raise an exception if called from System mode */
9120 gen_set_condexec(s);
9121 gen_set_pc_im(s, s->pc - 4);
9122 gen_helper_get_r13_banked(addr, cpu_env, tmp);
9123 tcg_temp_free_i32(tmp);
9124 switch (amode) {
9125 case 0: /* DA */
9126 offset = -4;
9127 break;
9128 case 1: /* IA */
9129 offset = 0;
9130 break;
9131 case 2: /* DB */
9132 offset = -8;
9133 break;
9134 case 3: /* IB */
9135 offset = 4;
9136 break;
9137 default:
9138 abort();
9140 tcg_gen_addi_i32(addr, addr, offset);
9141 tmp = load_reg(s, 14);
9142 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
9143 tcg_temp_free_i32(tmp);
9144 tmp = load_cpu_field(spsr);
9145 tcg_gen_addi_i32(addr, addr, 4);
9146 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
9147 tcg_temp_free_i32(tmp);
9148 if (writeback) {
9149 switch (amode) {
9150 case 0:
9151 offset = -8;
9152 break;
9153 case 1:
9154 offset = 4;
9155 break;
9156 case 2:
9157 offset = -4;
9158 break;
9159 case 3:
9160 offset = 0;
9161 break;
9162 default:
9163 abort();
9165 tcg_gen_addi_i32(addr, addr, offset);
9166 tmp = tcg_const_i32(mode);
9167 gen_helper_set_r13_banked(cpu_env, tmp, addr);
9168 tcg_temp_free_i32(tmp);
9170 tcg_temp_free_i32(addr);
9171 s->base.is_jmp = DISAS_UPDATE;
9174 /* Generate a label used for skipping this instruction */
9175 static void arm_gen_condlabel(DisasContext *s)
9177 if (!s->condjmp) {
9178 s->condlabel = gen_new_label();
9179 s->condjmp = 1;
9183 /* Skip this instruction if the ARM condition is false */
9184 static void arm_skip_unless(DisasContext *s, uint32_t cond)
9186 arm_gen_condlabel(s);
9187 arm_gen_test_cc(cond ^ 1, s->condlabel);
9190 static void disas_arm_insn(DisasContext *s, unsigned int insn)
9192 unsigned int cond, val, op1, i, shift, rm, rs, rn, rd, sh;
9193 TCGv_i32 tmp;
9194 TCGv_i32 tmp2;
9195 TCGv_i32 tmp3;
9196 TCGv_i32 addr;
9197 TCGv_i64 tmp64;
9199 /* M variants do not implement ARM mode; this must raise the INVSTATE
9200 * UsageFault exception.
9202 if (arm_dc_feature(s, ARM_FEATURE_M)) {
9203 gen_exception_insn(s, 4, EXCP_INVSTATE, syn_uncategorized(),
9204 default_exception_el(s));
9205 return;
9207 cond = insn >> 28;
9208 if (cond == 0xf){
9209 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
9210 * choose to UNDEF. In ARMv5 and above the space is used
9211 * for miscellaneous unconditional instructions.
9213 ARCH(5);
9215 /* Unconditional instructions. */
9216 if (((insn >> 25) & 7) == 1) {
9217 /* NEON Data processing. */
9218 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
9219 goto illegal_op;
9222 if (disas_neon_data_insn(s, insn)) {
9223 goto illegal_op;
9225 return;
9227 if ((insn & 0x0f100000) == 0x04000000) {
9228 /* NEON load/store. */
9229 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
9230 goto illegal_op;
9233 if (disas_neon_ls_insn(s, insn)) {
9234 goto illegal_op;
9236 return;
9238 if ((insn & 0x0f000e10) == 0x0e000a00) {
9239 /* VFP. */
9240 if (disas_vfp_insn(s, insn)) {
9241 goto illegal_op;
9243 return;
9245 if (((insn & 0x0f30f000) == 0x0510f000) ||
9246 ((insn & 0x0f30f010) == 0x0710f000)) {
9247 if ((insn & (1 << 22)) == 0) {
9248 /* PLDW; v7MP */
9249 if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
9250 goto illegal_op;
9253 /* Otherwise PLD; v5TE+ */
9254 ARCH(5TE);
9255 return;
9257 if (((insn & 0x0f70f000) == 0x0450f000) ||
9258 ((insn & 0x0f70f010) == 0x0650f000)) {
9259 ARCH(7);
9260 return; /* PLI; V7 */
9262 if (((insn & 0x0f700000) == 0x04100000) ||
9263 ((insn & 0x0f700010) == 0x06100000)) {
9264 if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
9265 goto illegal_op;
9267 return; /* v7MP: Unallocated memory hint: must NOP */
9270 if ((insn & 0x0ffffdff) == 0x01010000) {
9271 ARCH(6);
9272 /* setend */
9273 if (((insn >> 9) & 1) != !!(s->be_data == MO_BE)) {
9274 gen_helper_setend(cpu_env);
9275 s->base.is_jmp = DISAS_UPDATE;
9277 return;
9278 } else if ((insn & 0x0fffff00) == 0x057ff000) {
9279 switch ((insn >> 4) & 0xf) {
9280 case 1: /* clrex */
9281 ARCH(6K);
9282 gen_clrex(s);
9283 return;
9284 case 4: /* dsb */
9285 case 5: /* dmb */
9286 ARCH(7);
9287 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
9288 return;
9289 case 6: /* isb */
9290 /* We need to break the TB after this insn to execute
9291 * self-modifying code correctly and also to take
9292 * any pending interrupts immediately.
9294 gen_goto_tb(s, 0, s->pc & ~1);
9295 return;
9296 case 7: /* sb */
9297 if ((insn & 0xf) || !dc_isar_feature(aa32_sb, s)) {
9298 goto illegal_op;
9301 * TODO: There is no speculation barrier opcode
9302 * for TCG; MB and end the TB instead.
9304 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
9305 gen_goto_tb(s, 0, s->pc & ~1);
9306 return;
9307 default:
9308 goto illegal_op;
9310 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
9311 /* srs */
9312 ARCH(6);
9313 gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21));
9314 return;
9315 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
9316 /* rfe */
9317 int32_t offset;
9318 if (IS_USER(s))
9319 goto illegal_op;
9320 ARCH(6);
9321 rn = (insn >> 16) & 0xf;
9322 addr = load_reg(s, rn);
9323 i = (insn >> 23) & 3;
9324 switch (i) {
9325 case 0: offset = -4; break; /* DA */
9326 case 1: offset = 0; break; /* IA */
9327 case 2: offset = -8; break; /* DB */
9328 case 3: offset = 4; break; /* IB */
9329 default: abort();
9331 if (offset)
9332 tcg_gen_addi_i32(addr, addr, offset);
9333 /* Load PC into tmp and CPSR into tmp2. */
9334 tmp = tcg_temp_new_i32();
9335 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9336 tcg_gen_addi_i32(addr, addr, 4);
9337 tmp2 = tcg_temp_new_i32();
9338 gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
9339 if (insn & (1 << 21)) {
9340 /* Base writeback. */
9341 switch (i) {
9342 case 0: offset = -8; break;
9343 case 1: offset = 4; break;
9344 case 2: offset = -4; break;
9345 case 3: offset = 0; break;
9346 default: abort();
9348 if (offset)
9349 tcg_gen_addi_i32(addr, addr, offset);
9350 store_reg(s, rn, addr);
9351 } else {
9352 tcg_temp_free_i32(addr);
9354 gen_rfe(s, tmp, tmp2);
9355 return;
9356 } else if ((insn & 0x0e000000) == 0x0a000000) {
9357 /* branch link and change to thumb (blx <offset>) */
9358 int32_t offset;
9360 val = (uint32_t)s->pc;
9361 tmp = tcg_temp_new_i32();
9362 tcg_gen_movi_i32(tmp, val);
9363 store_reg(s, 14, tmp);
9364 /* Sign-extend the 24-bit offset */
9365 offset = (((int32_t)insn) << 8) >> 8;
9366 /* offset * 4 + bit24 * 2 + (thumb bit) */
9367 val += (offset << 2) | ((insn >> 23) & 2) | 1;
9368 /* pipeline offset */
9369 val += 4;
9370 /* protected by ARCH(5); above, near the start of uncond block */
9371 gen_bx_im(s, val);
9372 return;
9373 } else if ((insn & 0x0e000f00) == 0x0c000100) {
9374 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
9375 /* iWMMXt register transfer. */
9376 if (extract32(s->c15_cpar, 1, 1)) {
9377 if (!disas_iwmmxt_insn(s, insn)) {
9378 return;
9382 } else if ((insn & 0x0e000a00) == 0x0c000800
9383 && arm_dc_feature(s, ARM_FEATURE_V8)) {
9384 if (disas_neon_insn_3same_ext(s, insn)) {
9385 goto illegal_op;
9387 return;
9388 } else if ((insn & 0x0f000a00) == 0x0e000800
9389 && arm_dc_feature(s, ARM_FEATURE_V8)) {
9390 if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
9391 goto illegal_op;
9393 return;
9394 } else if ((insn & 0x0fe00000) == 0x0c400000) {
9395 /* Coprocessor double register transfer. */
9396 ARCH(5TE);
9397 } else if ((insn & 0x0f000010) == 0x0e000010) {
9398 /* Additional coprocessor register transfer. */
9399 } else if ((insn & 0x0ff10020) == 0x01000000) {
9400 uint32_t mask;
9401 uint32_t val;
9402 /* cps (privileged) */
9403 if (IS_USER(s))
9404 return;
9405 mask = val = 0;
9406 if (insn & (1 << 19)) {
9407 if (insn & (1 << 8))
9408 mask |= CPSR_A;
9409 if (insn & (1 << 7))
9410 mask |= CPSR_I;
9411 if (insn & (1 << 6))
9412 mask |= CPSR_F;
9413 if (insn & (1 << 18))
9414 val |= mask;
9416 if (insn & (1 << 17)) {
9417 mask |= CPSR_M;
9418 val |= (insn & 0x1f);
9420 if (mask) {
9421 gen_set_psr_im(s, mask, 0, val);
9423 return;
9425 goto illegal_op;
9427 if (cond != 0xe) {
9428 /* if not always execute, we generate a conditional jump to
9429 next instruction */
9430 arm_skip_unless(s, cond);
9432 if ((insn & 0x0f900000) == 0x03000000) {
9433 if ((insn & (1 << 21)) == 0) {
9434 ARCH(6T2);
9435 rd = (insn >> 12) & 0xf;
9436 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
9437 if ((insn & (1 << 22)) == 0) {
9438 /* MOVW */
9439 tmp = tcg_temp_new_i32();
9440 tcg_gen_movi_i32(tmp, val);
9441 } else {
9442 /* MOVT */
9443 tmp = load_reg(s, rd);
9444 tcg_gen_ext16u_i32(tmp, tmp);
9445 tcg_gen_ori_i32(tmp, tmp, val << 16);
9447 store_reg(s, rd, tmp);
9448 } else {
9449 if (((insn >> 12) & 0xf) != 0xf)
9450 goto illegal_op;
9451 if (((insn >> 16) & 0xf) == 0) {
9452 gen_nop_hint(s, insn & 0xff);
9453 } else {
9454 /* CPSR = immediate */
9455 val = insn & 0xff;
9456 shift = ((insn >> 8) & 0xf) * 2;
9457 if (shift)
9458 val = (val >> shift) | (val << (32 - shift));
9459 i = ((insn & (1 << 22)) != 0);
9460 if (gen_set_psr_im(s, msr_mask(s, (insn >> 16) & 0xf, i),
9461 i, val)) {
9462 goto illegal_op;
9466 } else if ((insn & 0x0f900000) == 0x01000000
9467 && (insn & 0x00000090) != 0x00000090) {
9468 /* miscellaneous instructions */
9469 op1 = (insn >> 21) & 3;
9470 sh = (insn >> 4) & 0xf;
9471 rm = insn & 0xf;
9472 switch (sh) {
9473 case 0x0: /* MSR, MRS */
9474 if (insn & (1 << 9)) {
9475 /* MSR (banked) and MRS (banked) */
9476 int sysm = extract32(insn, 16, 4) |
9477 (extract32(insn, 8, 1) << 4);
9478 int r = extract32(insn, 22, 1);
9480 if (op1 & 1) {
9481 /* MSR (banked) */
9482 gen_msr_banked(s, r, sysm, rm);
9483 } else {
9484 /* MRS (banked) */
9485 int rd = extract32(insn, 12, 4);
9487 gen_mrs_banked(s, r, sysm, rd);
9489 break;
9492 /* MSR, MRS (for PSRs) */
9493 if (op1 & 1) {
9494 /* PSR = reg */
9495 tmp = load_reg(s, rm);
9496 i = ((op1 & 2) != 0);
9497 if (gen_set_psr(s, msr_mask(s, (insn >> 16) & 0xf, i), i, tmp))
9498 goto illegal_op;
9499 } else {
9500 /* reg = PSR */
9501 rd = (insn >> 12) & 0xf;
9502 if (op1 & 2) {
9503 if (IS_USER(s))
9504 goto illegal_op;
9505 tmp = load_cpu_field(spsr);
9506 } else {
9507 tmp = tcg_temp_new_i32();
9508 gen_helper_cpsr_read(tmp, cpu_env);
9510 store_reg(s, rd, tmp);
9512 break;
9513 case 0x1:
9514 if (op1 == 1) {
9515 /* branch/exchange thumb (bx). */
9516 ARCH(4T);
9517 tmp = load_reg(s, rm);
9518 gen_bx(s, tmp);
9519 } else if (op1 == 3) {
9520 /* clz */
9521 ARCH(5);
9522 rd = (insn >> 12) & 0xf;
9523 tmp = load_reg(s, rm);
9524 tcg_gen_clzi_i32(tmp, tmp, 32);
9525 store_reg(s, rd, tmp);
9526 } else {
9527 goto illegal_op;
9529 break;
9530 case 0x2:
9531 if (op1 == 1) {
9532 ARCH(5J); /* bxj */
9533 /* Trivial implementation equivalent to bx. */
9534 tmp = load_reg(s, rm);
9535 gen_bx(s, tmp);
9536 } else {
9537 goto illegal_op;
9539 break;
9540 case 0x3:
9541 if (op1 != 1)
9542 goto illegal_op;
9544 ARCH(5);
9545 /* branch link/exchange thumb (blx) */
9546 tmp = load_reg(s, rm);
9547 tmp2 = tcg_temp_new_i32();
9548 tcg_gen_movi_i32(tmp2, s->pc);
9549 store_reg(s, 14, tmp2);
9550 gen_bx(s, tmp);
9551 break;
9552 case 0x4:
9554 /* crc32/crc32c */
9555 uint32_t c = extract32(insn, 8, 4);
9557 /* Check this CPU supports ARMv8 CRC instructions.
9558 * op1 == 3 is UNPREDICTABLE but handle as UNDEFINED.
9559 * Bits 8, 10 and 11 should be zero.
9561 if (!dc_isar_feature(aa32_crc32, s) || op1 == 0x3 || (c & 0xd) != 0) {
9562 goto illegal_op;
9565 rn = extract32(insn, 16, 4);
9566 rd = extract32(insn, 12, 4);
9568 tmp = load_reg(s, rn);
9569 tmp2 = load_reg(s, rm);
9570 if (op1 == 0) {
9571 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
9572 } else if (op1 == 1) {
9573 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
9575 tmp3 = tcg_const_i32(1 << op1);
9576 if (c & 0x2) {
9577 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
9578 } else {
9579 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
9581 tcg_temp_free_i32(tmp2);
9582 tcg_temp_free_i32(tmp3);
9583 store_reg(s, rd, tmp);
9584 break;
9586 case 0x5: /* saturating add/subtract */
9587 ARCH(5TE);
9588 rd = (insn >> 12) & 0xf;
9589 rn = (insn >> 16) & 0xf;
9590 tmp = load_reg(s, rm);
9591 tmp2 = load_reg(s, rn);
9592 if (op1 & 2)
9593 gen_helper_double_saturate(tmp2, cpu_env, tmp2);
9594 if (op1 & 1)
9595 gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2);
9596 else
9597 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
9598 tcg_temp_free_i32(tmp2);
9599 store_reg(s, rd, tmp);
9600 break;
9601 case 0x6: /* ERET */
9602 if (op1 != 3) {
9603 goto illegal_op;
9605 if (!arm_dc_feature(s, ARM_FEATURE_V7VE)) {
9606 goto illegal_op;
9608 if ((insn & 0x000fff0f) != 0x0000000e) {
9609 /* UNPREDICTABLE; we choose to UNDEF */
9610 goto illegal_op;
9613 if (s->current_el == 2) {
9614 tmp = load_cpu_field(elr_el[2]);
9615 } else {
9616 tmp = load_reg(s, 14);
9618 gen_exception_return(s, tmp);
9619 break;
9620 case 7:
9622 int imm16 = extract32(insn, 0, 4) | (extract32(insn, 8, 12) << 4);
9623 switch (op1) {
9624 case 0:
9625 /* HLT */
9626 gen_hlt(s, imm16);
9627 break;
9628 case 1:
9629 /* bkpt */
9630 ARCH(5);
9631 gen_exception_bkpt_insn(s, 4, syn_aa32_bkpt(imm16, false));
9632 break;
9633 case 2:
9634 /* Hypervisor call (v7) */
9635 ARCH(7);
9636 if (IS_USER(s)) {
9637 goto illegal_op;
9639 gen_hvc(s, imm16);
9640 break;
9641 case 3:
9642 /* Secure monitor call (v6+) */
9643 ARCH(6K);
9644 if (IS_USER(s)) {
9645 goto illegal_op;
9647 gen_smc(s);
9648 break;
9649 default:
9650 g_assert_not_reached();
9652 break;
9654 case 0x8: /* signed multiply */
9655 case 0xa:
9656 case 0xc:
9657 case 0xe:
9658 ARCH(5TE);
9659 rs = (insn >> 8) & 0xf;
9660 rn = (insn >> 12) & 0xf;
9661 rd = (insn >> 16) & 0xf;
9662 if (op1 == 1) {
9663 /* (32 * 16) >> 16 */
9664 tmp = load_reg(s, rm);
9665 tmp2 = load_reg(s, rs);
9666 if (sh & 4)
9667 tcg_gen_sari_i32(tmp2, tmp2, 16);
9668 else
9669 gen_sxth(tmp2);
9670 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9671 tcg_gen_shri_i64(tmp64, tmp64, 16);
9672 tmp = tcg_temp_new_i32();
9673 tcg_gen_extrl_i64_i32(tmp, tmp64);
9674 tcg_temp_free_i64(tmp64);
9675 if ((sh & 2) == 0) {
9676 tmp2 = load_reg(s, rn);
9677 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9678 tcg_temp_free_i32(tmp2);
9680 store_reg(s, rd, tmp);
9681 } else {
9682 /* 16 * 16 */
9683 tmp = load_reg(s, rm);
9684 tmp2 = load_reg(s, rs);
9685 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
9686 tcg_temp_free_i32(tmp2);
9687 if (op1 == 2) {
9688 tmp64 = tcg_temp_new_i64();
9689 tcg_gen_ext_i32_i64(tmp64, tmp);
9690 tcg_temp_free_i32(tmp);
9691 gen_addq(s, tmp64, rn, rd);
9692 gen_storeq_reg(s, rn, rd, tmp64);
9693 tcg_temp_free_i64(tmp64);
9694 } else {
9695 if (op1 == 0) {
9696 tmp2 = load_reg(s, rn);
9697 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9698 tcg_temp_free_i32(tmp2);
9700 store_reg(s, rd, tmp);
9703 break;
9704 default:
9705 goto illegal_op;
9707 } else if (((insn & 0x0e000000) == 0 &&
9708 (insn & 0x00000090) != 0x90) ||
9709 ((insn & 0x0e000000) == (1 << 25))) {
9710 int set_cc, logic_cc, shiftop;
9712 op1 = (insn >> 21) & 0xf;
9713 set_cc = (insn >> 20) & 1;
9714 logic_cc = table_logic_cc[op1] & set_cc;
9716 /* data processing instruction */
9717 if (insn & (1 << 25)) {
9718 /* immediate operand */
9719 val = insn & 0xff;
9720 shift = ((insn >> 8) & 0xf) * 2;
9721 if (shift) {
9722 val = (val >> shift) | (val << (32 - shift));
9724 tmp2 = tcg_temp_new_i32();
9725 tcg_gen_movi_i32(tmp2, val);
9726 if (logic_cc && shift) {
9727 gen_set_CF_bit31(tmp2);
9729 } else {
9730 /* register */
9731 rm = (insn) & 0xf;
9732 tmp2 = load_reg(s, rm);
9733 shiftop = (insn >> 5) & 3;
9734 if (!(insn & (1 << 4))) {
9735 shift = (insn >> 7) & 0x1f;
9736 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
9737 } else {
9738 rs = (insn >> 8) & 0xf;
9739 tmp = load_reg(s, rs);
9740 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
9743 if (op1 != 0x0f && op1 != 0x0d) {
9744 rn = (insn >> 16) & 0xf;
9745 tmp = load_reg(s, rn);
9746 } else {
9747 tmp = NULL;
9749 rd = (insn >> 12) & 0xf;
9750 switch(op1) {
9751 case 0x00:
9752 tcg_gen_and_i32(tmp, tmp, tmp2);
9753 if (logic_cc) {
9754 gen_logic_CC(tmp);
9756 store_reg_bx(s, rd, tmp);
9757 break;
9758 case 0x01:
9759 tcg_gen_xor_i32(tmp, tmp, tmp2);
9760 if (logic_cc) {
9761 gen_logic_CC(tmp);
9763 store_reg_bx(s, rd, tmp);
9764 break;
9765 case 0x02:
9766 if (set_cc && rd == 15) {
9767 /* SUBS r15, ... is used for exception return. */
9768 if (IS_USER(s)) {
9769 goto illegal_op;
9771 gen_sub_CC(tmp, tmp, tmp2);
9772 gen_exception_return(s, tmp);
9773 } else {
9774 if (set_cc) {
9775 gen_sub_CC(tmp, tmp, tmp2);
9776 } else {
9777 tcg_gen_sub_i32(tmp, tmp, tmp2);
9779 store_reg_bx(s, rd, tmp);
9781 break;
9782 case 0x03:
9783 if (set_cc) {
9784 gen_sub_CC(tmp, tmp2, tmp);
9785 } else {
9786 tcg_gen_sub_i32(tmp, tmp2, tmp);
9788 store_reg_bx(s, rd, tmp);
9789 break;
9790 case 0x04:
9791 if (set_cc) {
9792 gen_add_CC(tmp, tmp, tmp2);
9793 } else {
9794 tcg_gen_add_i32(tmp, tmp, tmp2);
9796 store_reg_bx(s, rd, tmp);
9797 break;
9798 case 0x05:
9799 if (set_cc) {
9800 gen_adc_CC(tmp, tmp, tmp2);
9801 } else {
9802 gen_add_carry(tmp, tmp, tmp2);
9804 store_reg_bx(s, rd, tmp);
9805 break;
9806 case 0x06:
9807 if (set_cc) {
9808 gen_sbc_CC(tmp, tmp, tmp2);
9809 } else {
9810 gen_sub_carry(tmp, tmp, tmp2);
9812 store_reg_bx(s, rd, tmp);
9813 break;
9814 case 0x07:
9815 if (set_cc) {
9816 gen_sbc_CC(tmp, tmp2, tmp);
9817 } else {
9818 gen_sub_carry(tmp, tmp2, tmp);
9820 store_reg_bx(s, rd, tmp);
9821 break;
9822 case 0x08:
9823 if (set_cc) {
9824 tcg_gen_and_i32(tmp, tmp, tmp2);
9825 gen_logic_CC(tmp);
9827 tcg_temp_free_i32(tmp);
9828 break;
9829 case 0x09:
9830 if (set_cc) {
9831 tcg_gen_xor_i32(tmp, tmp, tmp2);
9832 gen_logic_CC(tmp);
9834 tcg_temp_free_i32(tmp);
9835 break;
9836 case 0x0a:
9837 if (set_cc) {
9838 gen_sub_CC(tmp, tmp, tmp2);
9840 tcg_temp_free_i32(tmp);
9841 break;
9842 case 0x0b:
9843 if (set_cc) {
9844 gen_add_CC(tmp, tmp, tmp2);
9846 tcg_temp_free_i32(tmp);
9847 break;
9848 case 0x0c:
9849 tcg_gen_or_i32(tmp, tmp, tmp2);
9850 if (logic_cc) {
9851 gen_logic_CC(tmp);
9853 store_reg_bx(s, rd, tmp);
9854 break;
9855 case 0x0d:
9856 if (logic_cc && rd == 15) {
9857 /* MOVS r15, ... is used for exception return. */
9858 if (IS_USER(s)) {
9859 goto illegal_op;
9861 gen_exception_return(s, tmp2);
9862 } else {
9863 if (logic_cc) {
9864 gen_logic_CC(tmp2);
9866 store_reg_bx(s, rd, tmp2);
9868 break;
9869 case 0x0e:
9870 tcg_gen_andc_i32(tmp, tmp, tmp2);
9871 if (logic_cc) {
9872 gen_logic_CC(tmp);
9874 store_reg_bx(s, rd, tmp);
9875 break;
9876 default:
9877 case 0x0f:
9878 tcg_gen_not_i32(tmp2, tmp2);
9879 if (logic_cc) {
9880 gen_logic_CC(tmp2);
9882 store_reg_bx(s, rd, tmp2);
9883 break;
9885 if (op1 != 0x0f && op1 != 0x0d) {
9886 tcg_temp_free_i32(tmp2);
9888 } else {
9889 /* other instructions */
9890 op1 = (insn >> 24) & 0xf;
9891 switch(op1) {
9892 case 0x0:
9893 case 0x1:
9894 /* multiplies, extra load/stores */
9895 sh = (insn >> 5) & 3;
9896 if (sh == 0) {
9897 if (op1 == 0x0) {
9898 rd = (insn >> 16) & 0xf;
9899 rn = (insn >> 12) & 0xf;
9900 rs = (insn >> 8) & 0xf;
9901 rm = (insn) & 0xf;
9902 op1 = (insn >> 20) & 0xf;
9903 switch (op1) {
9904 case 0: case 1: case 2: case 3: case 6:
9905 /* 32 bit mul */
9906 tmp = load_reg(s, rs);
9907 tmp2 = load_reg(s, rm);
9908 tcg_gen_mul_i32(tmp, tmp, tmp2);
9909 tcg_temp_free_i32(tmp2);
9910 if (insn & (1 << 22)) {
9911 /* Subtract (mls) */
9912 ARCH(6T2);
9913 tmp2 = load_reg(s, rn);
9914 tcg_gen_sub_i32(tmp, tmp2, tmp);
9915 tcg_temp_free_i32(tmp2);
9916 } else if (insn & (1 << 21)) {
9917 /* Add */
9918 tmp2 = load_reg(s, rn);
9919 tcg_gen_add_i32(tmp, tmp, tmp2);
9920 tcg_temp_free_i32(tmp2);
9922 if (insn & (1 << 20))
9923 gen_logic_CC(tmp);
9924 store_reg(s, rd, tmp);
9925 break;
9926 case 4:
9927 /* 64 bit mul double accumulate (UMAAL) */
9928 ARCH(6);
9929 tmp = load_reg(s, rs);
9930 tmp2 = load_reg(s, rm);
9931 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
9932 gen_addq_lo(s, tmp64, rn);
9933 gen_addq_lo(s, tmp64, rd);
9934 gen_storeq_reg(s, rn, rd, tmp64);
9935 tcg_temp_free_i64(tmp64);
9936 break;
9937 case 8: case 9: case 10: case 11:
9938 case 12: case 13: case 14: case 15:
9939 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
9940 tmp = load_reg(s, rs);
9941 tmp2 = load_reg(s, rm);
9942 if (insn & (1 << 22)) {
9943 tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2);
9944 } else {
9945 tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2);
9947 if (insn & (1 << 21)) { /* mult accumulate */
9948 TCGv_i32 al = load_reg(s, rn);
9949 TCGv_i32 ah = load_reg(s, rd);
9950 tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, al, ah);
9951 tcg_temp_free_i32(al);
9952 tcg_temp_free_i32(ah);
9954 if (insn & (1 << 20)) {
9955 gen_logicq_cc(tmp, tmp2);
9957 store_reg(s, rn, tmp);
9958 store_reg(s, rd, tmp2);
9959 break;
9960 default:
9961 goto illegal_op;
9963 } else {
9964 rn = (insn >> 16) & 0xf;
9965 rd = (insn >> 12) & 0xf;
9966 if (insn & (1 << 23)) {
9967 /* load/store exclusive */
9968 bool is_ld = extract32(insn, 20, 1);
9969 bool is_lasr = !extract32(insn, 8, 1);
9970 int op2 = (insn >> 8) & 3;
9971 op1 = (insn >> 21) & 0x3;
9973 switch (op2) {
9974 case 0: /* lda/stl */
9975 if (op1 == 1) {
9976 goto illegal_op;
9978 ARCH(8);
9979 break;
9980 case 1: /* reserved */
9981 goto illegal_op;
9982 case 2: /* ldaex/stlex */
9983 ARCH(8);
9984 break;
9985 case 3: /* ldrex/strex */
9986 if (op1) {
9987 ARCH(6K);
9988 } else {
9989 ARCH(6);
9991 break;
9994 addr = tcg_temp_local_new_i32();
9995 load_reg_var(s, addr, rn);
9997 if (is_lasr && !is_ld) {
9998 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
10001 if (op2 == 0) {
10002 if (is_ld) {
10003 tmp = tcg_temp_new_i32();
10004 switch (op1) {
10005 case 0: /* lda */
10006 gen_aa32_ld32u_iss(s, tmp, addr,
10007 get_mem_index(s),
10008 rd | ISSIsAcqRel);
10009 break;
10010 case 2: /* ldab */
10011 gen_aa32_ld8u_iss(s, tmp, addr,
10012 get_mem_index(s),
10013 rd | ISSIsAcqRel);
10014 break;
10015 case 3: /* ldah */
10016 gen_aa32_ld16u_iss(s, tmp, addr,
10017 get_mem_index(s),
10018 rd | ISSIsAcqRel);
10019 break;
10020 default:
10021 abort();
10023 store_reg(s, rd, tmp);
10024 } else {
10025 rm = insn & 0xf;
10026 tmp = load_reg(s, rm);
10027 switch (op1) {
10028 case 0: /* stl */
10029 gen_aa32_st32_iss(s, tmp, addr,
10030 get_mem_index(s),
10031 rm | ISSIsAcqRel);
10032 break;
10033 case 2: /* stlb */
10034 gen_aa32_st8_iss(s, tmp, addr,
10035 get_mem_index(s),
10036 rm | ISSIsAcqRel);
10037 break;
10038 case 3: /* stlh */
10039 gen_aa32_st16_iss(s, tmp, addr,
10040 get_mem_index(s),
10041 rm | ISSIsAcqRel);
10042 break;
10043 default:
10044 abort();
10046 tcg_temp_free_i32(tmp);
10048 } else if (is_ld) {
10049 switch (op1) {
10050 case 0: /* ldrex */
10051 gen_load_exclusive(s, rd, 15, addr, 2);
10052 break;
10053 case 1: /* ldrexd */
10054 gen_load_exclusive(s, rd, rd + 1, addr, 3);
10055 break;
10056 case 2: /* ldrexb */
10057 gen_load_exclusive(s, rd, 15, addr, 0);
10058 break;
10059 case 3: /* ldrexh */
10060 gen_load_exclusive(s, rd, 15, addr, 1);
10061 break;
10062 default:
10063 abort();
10065 } else {
10066 rm = insn & 0xf;
10067 switch (op1) {
10068 case 0: /* strex */
10069 gen_store_exclusive(s, rd, rm, 15, addr, 2);
10070 break;
10071 case 1: /* strexd */
10072 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
10073 break;
10074 case 2: /* strexb */
10075 gen_store_exclusive(s, rd, rm, 15, addr, 0);
10076 break;
10077 case 3: /* strexh */
10078 gen_store_exclusive(s, rd, rm, 15, addr, 1);
10079 break;
10080 default:
10081 abort();
10084 tcg_temp_free_i32(addr);
10086 if (is_lasr && is_ld) {
10087 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
10089 } else if ((insn & 0x00300f00) == 0) {
10090 /* 0bcccc_0001_0x00_xxxx_xxxx_0000_1001_xxxx
10091 * - SWP, SWPB
10094 TCGv taddr;
10095 TCGMemOp opc = s->be_data;
10097 rm = (insn) & 0xf;
10099 if (insn & (1 << 22)) {
10100 opc |= MO_UB;
10101 } else {
10102 opc |= MO_UL | MO_ALIGN;
10105 addr = load_reg(s, rn);
10106 taddr = gen_aa32_addr(s, addr, opc);
10107 tcg_temp_free_i32(addr);
10109 tmp = load_reg(s, rm);
10110 tcg_gen_atomic_xchg_i32(tmp, taddr, tmp,
10111 get_mem_index(s), opc);
10112 tcg_temp_free(taddr);
10113 store_reg(s, rd, tmp);
10114 } else {
10115 goto illegal_op;
10118 } else {
10119 int address_offset;
10120 bool load = insn & (1 << 20);
10121 bool wbit = insn & (1 << 21);
10122 bool pbit = insn & (1 << 24);
10123 bool doubleword = false;
10124 ISSInfo issinfo;
10126 /* Misc load/store */
10127 rn = (insn >> 16) & 0xf;
10128 rd = (insn >> 12) & 0xf;
10130 /* ISS not valid if writeback */
10131 issinfo = (pbit & !wbit) ? rd : ISSInvalid;
10133 if (!load && (sh & 2)) {
10134 /* doubleword */
10135 ARCH(5TE);
10136 if (rd & 1) {
10137 /* UNPREDICTABLE; we choose to UNDEF */
10138 goto illegal_op;
10140 load = (sh & 1) == 0;
10141 doubleword = true;
10144 addr = load_reg(s, rn);
10145 if (pbit) {
10146 gen_add_datah_offset(s, insn, 0, addr);
10148 address_offset = 0;
10150 if (doubleword) {
10151 if (!load) {
10152 /* store */
10153 tmp = load_reg(s, rd);
10154 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
10155 tcg_temp_free_i32(tmp);
10156 tcg_gen_addi_i32(addr, addr, 4);
10157 tmp = load_reg(s, rd + 1);
10158 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
10159 tcg_temp_free_i32(tmp);
10160 } else {
10161 /* load */
10162 tmp = tcg_temp_new_i32();
10163 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
10164 store_reg(s, rd, tmp);
10165 tcg_gen_addi_i32(addr, addr, 4);
10166 tmp = tcg_temp_new_i32();
10167 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
10168 rd++;
10170 address_offset = -4;
10171 } else if (load) {
10172 /* load */
10173 tmp = tcg_temp_new_i32();
10174 switch (sh) {
10175 case 1:
10176 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s),
10177 issinfo);
10178 break;
10179 case 2:
10180 gen_aa32_ld8s_iss(s, tmp, addr, get_mem_index(s),
10181 issinfo);
10182 break;
10183 default:
10184 case 3:
10185 gen_aa32_ld16s_iss(s, tmp, addr, get_mem_index(s),
10186 issinfo);
10187 break;
10189 } else {
10190 /* store */
10191 tmp = load_reg(s, rd);
10192 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), issinfo);
10193 tcg_temp_free_i32(tmp);
10195 /* Perform base writeback before the loaded value to
10196 ensure correct behavior with overlapping index registers.
10197 ldrd with base writeback is undefined if the
10198 destination and index registers overlap. */
10199 if (!pbit) {
10200 gen_add_datah_offset(s, insn, address_offset, addr);
10201 store_reg(s, rn, addr);
10202 } else if (wbit) {
10203 if (address_offset)
10204 tcg_gen_addi_i32(addr, addr, address_offset);
10205 store_reg(s, rn, addr);
10206 } else {
10207 tcg_temp_free_i32(addr);
10209 if (load) {
10210 /* Complete the load. */
10211 store_reg(s, rd, tmp);
10214 break;
10215 case 0x4:
10216 case 0x5:
10217 goto do_ldst;
10218 case 0x6:
10219 case 0x7:
10220 if (insn & (1 << 4)) {
10221 ARCH(6);
10222 /* Armv6 Media instructions. */
10223 rm = insn & 0xf;
10224 rn = (insn >> 16) & 0xf;
10225 rd = (insn >> 12) & 0xf;
10226 rs = (insn >> 8) & 0xf;
10227 switch ((insn >> 23) & 3) {
10228 case 0: /* Parallel add/subtract. */
10229 op1 = (insn >> 20) & 7;
10230 tmp = load_reg(s, rn);
10231 tmp2 = load_reg(s, rm);
10232 sh = (insn >> 5) & 7;
10233 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
10234 goto illegal_op;
10235 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
10236 tcg_temp_free_i32(tmp2);
10237 store_reg(s, rd, tmp);
10238 break;
10239 case 1:
10240 if ((insn & 0x00700020) == 0) {
10241 /* Halfword pack. */
10242 tmp = load_reg(s, rn);
10243 tmp2 = load_reg(s, rm);
10244 shift = (insn >> 7) & 0x1f;
10245 if (insn & (1 << 6)) {
10246 /* pkhtb */
10247 if (shift == 0)
10248 shift = 31;
10249 tcg_gen_sari_i32(tmp2, tmp2, shift);
10250 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
10251 tcg_gen_ext16u_i32(tmp2, tmp2);
10252 } else {
10253 /* pkhbt */
10254 if (shift)
10255 tcg_gen_shli_i32(tmp2, tmp2, shift);
10256 tcg_gen_ext16u_i32(tmp, tmp);
10257 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
10259 tcg_gen_or_i32(tmp, tmp, tmp2);
10260 tcg_temp_free_i32(tmp2);
10261 store_reg(s, rd, tmp);
10262 } else if ((insn & 0x00200020) == 0x00200000) {
10263 /* [us]sat */
10264 tmp = load_reg(s, rm);
10265 shift = (insn >> 7) & 0x1f;
10266 if (insn & (1 << 6)) {
10267 if (shift == 0)
10268 shift = 31;
10269 tcg_gen_sari_i32(tmp, tmp, shift);
10270 } else {
10271 tcg_gen_shli_i32(tmp, tmp, shift);
10273 sh = (insn >> 16) & 0x1f;
10274 tmp2 = tcg_const_i32(sh);
10275 if (insn & (1 << 22))
10276 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
10277 else
10278 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
10279 tcg_temp_free_i32(tmp2);
10280 store_reg(s, rd, tmp);
10281 } else if ((insn & 0x00300fe0) == 0x00200f20) {
10282 /* [us]sat16 */
10283 tmp = load_reg(s, rm);
10284 sh = (insn >> 16) & 0x1f;
10285 tmp2 = tcg_const_i32(sh);
10286 if (insn & (1 << 22))
10287 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
10288 else
10289 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
10290 tcg_temp_free_i32(tmp2);
10291 store_reg(s, rd, tmp);
10292 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
10293 /* Select bytes. */
10294 tmp = load_reg(s, rn);
10295 tmp2 = load_reg(s, rm);
10296 tmp3 = tcg_temp_new_i32();
10297 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
10298 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
10299 tcg_temp_free_i32(tmp3);
10300 tcg_temp_free_i32(tmp2);
10301 store_reg(s, rd, tmp);
10302 } else if ((insn & 0x000003e0) == 0x00000060) {
10303 tmp = load_reg(s, rm);
10304 shift = (insn >> 10) & 3;
10305 /* ??? In many cases it's not necessary to do a
10306 rotate, a shift is sufficient. */
10307 if (shift != 0)
10308 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
10309 op1 = (insn >> 20) & 7;
10310 switch (op1) {
10311 case 0: gen_sxtb16(tmp); break;
10312 case 2: gen_sxtb(tmp); break;
10313 case 3: gen_sxth(tmp); break;
10314 case 4: gen_uxtb16(tmp); break;
10315 case 6: gen_uxtb(tmp); break;
10316 case 7: gen_uxth(tmp); break;
10317 default: goto illegal_op;
10319 if (rn != 15) {
10320 tmp2 = load_reg(s, rn);
10321 if ((op1 & 3) == 0) {
10322 gen_add16(tmp, tmp2);
10323 } else {
10324 tcg_gen_add_i32(tmp, tmp, tmp2);
10325 tcg_temp_free_i32(tmp2);
10328 store_reg(s, rd, tmp);
10329 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
10330 /* rev */
10331 tmp = load_reg(s, rm);
10332 if (insn & (1 << 22)) {
10333 if (insn & (1 << 7)) {
10334 gen_revsh(tmp);
10335 } else {
10336 ARCH(6T2);
10337 gen_helper_rbit(tmp, tmp);
10339 } else {
10340 if (insn & (1 << 7))
10341 gen_rev16(tmp);
10342 else
10343 tcg_gen_bswap32_i32(tmp, tmp);
10345 store_reg(s, rd, tmp);
10346 } else {
10347 goto illegal_op;
10349 break;
10350 case 2: /* Multiplies (Type 3). */
10351 switch ((insn >> 20) & 0x7) {
10352 case 5:
10353 if (((insn >> 6) ^ (insn >> 7)) & 1) {
10354 /* op2 not 00x or 11x : UNDEF */
10355 goto illegal_op;
10357 /* Signed multiply most significant [accumulate].
10358 (SMMUL, SMMLA, SMMLS) */
10359 tmp = load_reg(s, rm);
10360 tmp2 = load_reg(s, rs);
10361 tmp64 = gen_muls_i64_i32(tmp, tmp2);
10363 if (rd != 15) {
10364 tmp = load_reg(s, rd);
10365 if (insn & (1 << 6)) {
10366 tmp64 = gen_subq_msw(tmp64, tmp);
10367 } else {
10368 tmp64 = gen_addq_msw(tmp64, tmp);
10371 if (insn & (1 << 5)) {
10372 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
10374 tcg_gen_shri_i64(tmp64, tmp64, 32);
10375 tmp = tcg_temp_new_i32();
10376 tcg_gen_extrl_i64_i32(tmp, tmp64);
10377 tcg_temp_free_i64(tmp64);
10378 store_reg(s, rn, tmp);
10379 break;
10380 case 0:
10381 case 4:
10382 /* SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD */
10383 if (insn & (1 << 7)) {
10384 goto illegal_op;
10386 tmp = load_reg(s, rm);
10387 tmp2 = load_reg(s, rs);
10388 if (insn & (1 << 5))
10389 gen_swap_half(tmp2);
10390 gen_smul_dual(tmp, tmp2);
10391 if (insn & (1 << 22)) {
10392 /* smlald, smlsld */
10393 TCGv_i64 tmp64_2;
10395 tmp64 = tcg_temp_new_i64();
10396 tmp64_2 = tcg_temp_new_i64();
10397 tcg_gen_ext_i32_i64(tmp64, tmp);
10398 tcg_gen_ext_i32_i64(tmp64_2, tmp2);
10399 tcg_temp_free_i32(tmp);
10400 tcg_temp_free_i32(tmp2);
10401 if (insn & (1 << 6)) {
10402 tcg_gen_sub_i64(tmp64, tmp64, tmp64_2);
10403 } else {
10404 tcg_gen_add_i64(tmp64, tmp64, tmp64_2);
10406 tcg_temp_free_i64(tmp64_2);
10407 gen_addq(s, tmp64, rd, rn);
10408 gen_storeq_reg(s, rd, rn, tmp64);
10409 tcg_temp_free_i64(tmp64);
10410 } else {
10411 /* smuad, smusd, smlad, smlsd */
10412 if (insn & (1 << 6)) {
10413 /* This subtraction cannot overflow. */
10414 tcg_gen_sub_i32(tmp, tmp, tmp2);
10415 } else {
10416 /* This addition cannot overflow 32 bits;
10417 * however it may overflow considered as a
10418 * signed operation, in which case we must set
10419 * the Q flag.
10421 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
10423 tcg_temp_free_i32(tmp2);
10424 if (rd != 15)
10426 tmp2 = load_reg(s, rd);
10427 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
10428 tcg_temp_free_i32(tmp2);
10430 store_reg(s, rn, tmp);
10432 break;
10433 case 1:
10434 case 3:
10435 /* SDIV, UDIV */
10436 if (!dc_isar_feature(arm_div, s)) {
10437 goto illegal_op;
10439 if (((insn >> 5) & 7) || (rd != 15)) {
10440 goto illegal_op;
10442 tmp = load_reg(s, rm);
10443 tmp2 = load_reg(s, rs);
10444 if (insn & (1 << 21)) {
10445 gen_helper_udiv(tmp, tmp, tmp2);
10446 } else {
10447 gen_helper_sdiv(tmp, tmp, tmp2);
10449 tcg_temp_free_i32(tmp2);
10450 store_reg(s, rn, tmp);
10451 break;
10452 default:
10453 goto illegal_op;
10455 break;
10456 case 3:
10457 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
10458 switch (op1) {
10459 case 0: /* Unsigned sum of absolute differences. */
10460 ARCH(6);
10461 tmp = load_reg(s, rm);
10462 tmp2 = load_reg(s, rs);
10463 gen_helper_usad8(tmp, tmp, tmp2);
10464 tcg_temp_free_i32(tmp2);
10465 if (rd != 15) {
10466 tmp2 = load_reg(s, rd);
10467 tcg_gen_add_i32(tmp, tmp, tmp2);
10468 tcg_temp_free_i32(tmp2);
10470 store_reg(s, rn, tmp);
10471 break;
10472 case 0x20: case 0x24: case 0x28: case 0x2c:
10473 /* Bitfield insert/clear. */
10474 ARCH(6T2);
10475 shift = (insn >> 7) & 0x1f;
10476 i = (insn >> 16) & 0x1f;
10477 if (i < shift) {
10478 /* UNPREDICTABLE; we choose to UNDEF */
10479 goto illegal_op;
10481 i = i + 1 - shift;
10482 if (rm == 15) {
10483 tmp = tcg_temp_new_i32();
10484 tcg_gen_movi_i32(tmp, 0);
10485 } else {
10486 tmp = load_reg(s, rm);
10488 if (i != 32) {
10489 tmp2 = load_reg(s, rd);
10490 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, i);
10491 tcg_temp_free_i32(tmp2);
10493 store_reg(s, rd, tmp);
10494 break;
10495 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
10496 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
10497 ARCH(6T2);
10498 tmp = load_reg(s, rm);
10499 shift = (insn >> 7) & 0x1f;
10500 i = ((insn >> 16) & 0x1f) + 1;
10501 if (shift + i > 32)
10502 goto illegal_op;
10503 if (i < 32) {
10504 if (op1 & 0x20) {
10505 tcg_gen_extract_i32(tmp, tmp, shift, i);
10506 } else {
10507 tcg_gen_sextract_i32(tmp, tmp, shift, i);
10510 store_reg(s, rd, tmp);
10511 break;
10512 default:
10513 goto illegal_op;
10515 break;
10517 break;
10519 do_ldst:
10520 /* Check for undefined extension instructions
10521 * per the ARM Bible IE:
10522 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
10524 sh = (0xf << 20) | (0xf << 4);
10525 if (op1 == 0x7 && ((insn & sh) == sh))
10527 goto illegal_op;
10529 /* load/store byte/word */
10530 rn = (insn >> 16) & 0xf;
10531 rd = (insn >> 12) & 0xf;
10532 tmp2 = load_reg(s, rn);
10533 if ((insn & 0x01200000) == 0x00200000) {
10534 /* ldrt/strt */
10535 i = get_a32_user_mem_index(s);
10536 } else {
10537 i = get_mem_index(s);
10539 if (insn & (1 << 24))
10540 gen_add_data_offset(s, insn, tmp2);
10541 if (insn & (1 << 20)) {
10542 /* load */
10543 tmp = tcg_temp_new_i32();
10544 if (insn & (1 << 22)) {
10545 gen_aa32_ld8u_iss(s, tmp, tmp2, i, rd);
10546 } else {
10547 gen_aa32_ld32u_iss(s, tmp, tmp2, i, rd);
10549 } else {
10550 /* store */
10551 tmp = load_reg(s, rd);
10552 if (insn & (1 << 22)) {
10553 gen_aa32_st8_iss(s, tmp, tmp2, i, rd);
10554 } else {
10555 gen_aa32_st32_iss(s, tmp, tmp2, i, rd);
10557 tcg_temp_free_i32(tmp);
10559 if (!(insn & (1 << 24))) {
10560 gen_add_data_offset(s, insn, tmp2);
10561 store_reg(s, rn, tmp2);
10562 } else if (insn & (1 << 21)) {
10563 store_reg(s, rn, tmp2);
10564 } else {
10565 tcg_temp_free_i32(tmp2);
10567 if (insn & (1 << 20)) {
10568 /* Complete the load. */
10569 store_reg_from_load(s, rd, tmp);
10571 break;
10572 case 0x08:
10573 case 0x09:
10575 int j, n, loaded_base;
10576 bool exc_return = false;
10577 bool is_load = extract32(insn, 20, 1);
10578 bool user = false;
10579 TCGv_i32 loaded_var;
10580 /* load/store multiple words */
10581 /* XXX: store correct base if write back */
10582 if (insn & (1 << 22)) {
10583 /* LDM (user), LDM (exception return) and STM (user) */
10584 if (IS_USER(s))
10585 goto illegal_op; /* only usable in supervisor mode */
10587 if (is_load && extract32(insn, 15, 1)) {
10588 exc_return = true;
10589 } else {
10590 user = true;
10593 rn = (insn >> 16) & 0xf;
10594 addr = load_reg(s, rn);
10596 /* compute total size */
10597 loaded_base = 0;
10598 loaded_var = NULL;
10599 n = 0;
10600 for(i=0;i<16;i++) {
10601 if (insn & (1 << i))
10602 n++;
10604 /* XXX: test invalid n == 0 case ? */
10605 if (insn & (1 << 23)) {
10606 if (insn & (1 << 24)) {
10607 /* pre increment */
10608 tcg_gen_addi_i32(addr, addr, 4);
10609 } else {
10610 /* post increment */
10612 } else {
10613 if (insn & (1 << 24)) {
10614 /* pre decrement */
10615 tcg_gen_addi_i32(addr, addr, -(n * 4));
10616 } else {
10617 /* post decrement */
10618 if (n != 1)
10619 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
10622 j = 0;
10623 for(i=0;i<16;i++) {
10624 if (insn & (1 << i)) {
10625 if (is_load) {
10626 /* load */
10627 tmp = tcg_temp_new_i32();
10628 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
10629 if (user) {
10630 tmp2 = tcg_const_i32(i);
10631 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
10632 tcg_temp_free_i32(tmp2);
10633 tcg_temp_free_i32(tmp);
10634 } else if (i == rn) {
10635 loaded_var = tmp;
10636 loaded_base = 1;
10637 } else if (i == 15 && exc_return) {
10638 store_pc_exc_ret(s, tmp);
10639 } else {
10640 store_reg_from_load(s, i, tmp);
10642 } else {
10643 /* store */
10644 if (i == 15) {
10645 /* special case: r15 = PC + 8 */
10646 val = (long)s->pc + 4;
10647 tmp = tcg_temp_new_i32();
10648 tcg_gen_movi_i32(tmp, val);
10649 } else if (user) {
10650 tmp = tcg_temp_new_i32();
10651 tmp2 = tcg_const_i32(i);
10652 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
10653 tcg_temp_free_i32(tmp2);
10654 } else {
10655 tmp = load_reg(s, i);
10657 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
10658 tcg_temp_free_i32(tmp);
10660 j++;
10661 /* no need to add after the last transfer */
10662 if (j != n)
10663 tcg_gen_addi_i32(addr, addr, 4);
10666 if (insn & (1 << 21)) {
10667 /* write back */
10668 if (insn & (1 << 23)) {
10669 if (insn & (1 << 24)) {
10670 /* pre increment */
10671 } else {
10672 /* post increment */
10673 tcg_gen_addi_i32(addr, addr, 4);
10675 } else {
10676 if (insn & (1 << 24)) {
10677 /* pre decrement */
10678 if (n != 1)
10679 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
10680 } else {
10681 /* post decrement */
10682 tcg_gen_addi_i32(addr, addr, -(n * 4));
10685 store_reg(s, rn, addr);
10686 } else {
10687 tcg_temp_free_i32(addr);
10689 if (loaded_base) {
10690 store_reg(s, rn, loaded_var);
10692 if (exc_return) {
10693 /* Restore CPSR from SPSR. */
10694 tmp = load_cpu_field(spsr);
10695 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
10696 gen_io_start();
10698 gen_helper_cpsr_write_eret(cpu_env, tmp);
10699 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
10700 gen_io_end();
10702 tcg_temp_free_i32(tmp);
10703 /* Must exit loop to check un-masked IRQs */
10704 s->base.is_jmp = DISAS_EXIT;
10707 break;
10708 case 0xa:
10709 case 0xb:
10711 int32_t offset;
10713 /* branch (and link) */
10714 val = (int32_t)s->pc;
10715 if (insn & (1 << 24)) {
10716 tmp = tcg_temp_new_i32();
10717 tcg_gen_movi_i32(tmp, val);
10718 store_reg(s, 14, tmp);
10720 offset = sextract32(insn << 2, 0, 26);
10721 val += offset + 4;
10722 gen_jmp(s, val);
10724 break;
10725 case 0xc:
10726 case 0xd:
10727 case 0xe:
10728 if (((insn >> 8) & 0xe) == 10) {
10729 /* VFP. */
10730 if (disas_vfp_insn(s, insn)) {
10731 goto illegal_op;
10733 } else if (disas_coproc_insn(s, insn)) {
10734 /* Coprocessor. */
10735 goto illegal_op;
10737 break;
10738 case 0xf:
10739 /* swi */
10740 gen_set_pc_im(s, s->pc);
10741 s->svc_imm = extract32(insn, 0, 24);
10742 s->base.is_jmp = DISAS_SWI;
10743 break;
10744 default:
10745 illegal_op:
10746 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
10747 default_exception_el(s));
10748 break;
10753 static bool thumb_insn_is_16bit(DisasContext *s, uint32_t insn)
10755 /* Return true if this is a 16 bit instruction. We must be precise
10756 * about this (matching the decode). We assume that s->pc still
10757 * points to the first 16 bits of the insn.
10759 if ((insn >> 11) < 0x1d) {
10760 /* Definitely a 16-bit instruction */
10761 return true;
10764 /* Top five bits 0b11101 / 0b11110 / 0b11111 : this is the
10765 * first half of a 32-bit Thumb insn. Thumb-1 cores might
10766 * end up actually treating this as two 16-bit insns, though,
10767 * if it's half of a bl/blx pair that might span a page boundary.
10769 if (arm_dc_feature(s, ARM_FEATURE_THUMB2) ||
10770 arm_dc_feature(s, ARM_FEATURE_M)) {
10771 /* Thumb2 cores (including all M profile ones) always treat
10772 * 32-bit insns as 32-bit.
10774 return false;
10777 if ((insn >> 11) == 0x1e && s->pc - s->page_start < TARGET_PAGE_SIZE - 3) {
10778 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix, and the suffix
10779 * is not on the next page; we merge this into a 32-bit
10780 * insn.
10782 return false;
10784 /* 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF);
10785 * 0b1111_1xxx_xxxx_xxxx : BL suffix;
10786 * 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix on the end of a page
10787 * -- handle as single 16 bit insn
10789 return true;
10792 /* Return true if this is a Thumb-2 logical op. */
10793 static int
10794 thumb2_logic_op(int op)
10796 return (op < 8);
10799 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
10800 then set condition code flags based on the result of the operation.
10801 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
10802 to the high bit of T1.
10803 Returns zero if the opcode is valid. */
10805 static int
10806 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out,
10807 TCGv_i32 t0, TCGv_i32 t1)
10809 int logic_cc;
10811 logic_cc = 0;
10812 switch (op) {
10813 case 0: /* and */
10814 tcg_gen_and_i32(t0, t0, t1);
10815 logic_cc = conds;
10816 break;
10817 case 1: /* bic */
10818 tcg_gen_andc_i32(t0, t0, t1);
10819 logic_cc = conds;
10820 break;
10821 case 2: /* orr */
10822 tcg_gen_or_i32(t0, t0, t1);
10823 logic_cc = conds;
10824 break;
10825 case 3: /* orn */
10826 tcg_gen_orc_i32(t0, t0, t1);
10827 logic_cc = conds;
10828 break;
10829 case 4: /* eor */
10830 tcg_gen_xor_i32(t0, t0, t1);
10831 logic_cc = conds;
10832 break;
10833 case 8: /* add */
10834 if (conds)
10835 gen_add_CC(t0, t0, t1);
10836 else
10837 tcg_gen_add_i32(t0, t0, t1);
10838 break;
10839 case 10: /* adc */
10840 if (conds)
10841 gen_adc_CC(t0, t0, t1);
10842 else
10843 gen_adc(t0, t1);
10844 break;
10845 case 11: /* sbc */
10846 if (conds) {
10847 gen_sbc_CC(t0, t0, t1);
10848 } else {
10849 gen_sub_carry(t0, t0, t1);
10851 break;
10852 case 13: /* sub */
10853 if (conds)
10854 gen_sub_CC(t0, t0, t1);
10855 else
10856 tcg_gen_sub_i32(t0, t0, t1);
10857 break;
10858 case 14: /* rsb */
10859 if (conds)
10860 gen_sub_CC(t0, t1, t0);
10861 else
10862 tcg_gen_sub_i32(t0, t1, t0);
10863 break;
10864 default: /* 5, 6, 7, 9, 12, 15. */
10865 return 1;
10867 if (logic_cc) {
10868 gen_logic_CC(t0);
10869 if (shifter_out)
10870 gen_set_CF_bit31(t1);
10872 return 0;
10875 /* Translate a 32-bit thumb instruction. */
10876 static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
10878 uint32_t imm, shift, offset;
10879 uint32_t rd, rn, rm, rs;
10880 TCGv_i32 tmp;
10881 TCGv_i32 tmp2;
10882 TCGv_i32 tmp3;
10883 TCGv_i32 addr;
10884 TCGv_i64 tmp64;
10885 int op;
10886 int shiftop;
10887 int conds;
10888 int logic_cc;
10891 * ARMv6-M supports a limited subset of Thumb2 instructions.
10892 * Other Thumb1 architectures allow only 32-bit
10893 * combined BL/BLX prefix and suffix.
10895 if (arm_dc_feature(s, ARM_FEATURE_M) &&
10896 !arm_dc_feature(s, ARM_FEATURE_V7)) {
10897 int i;
10898 bool found = false;
10899 static const uint32_t armv6m_insn[] = {0xf3808000 /* msr */,
10900 0xf3b08040 /* dsb */,
10901 0xf3b08050 /* dmb */,
10902 0xf3b08060 /* isb */,
10903 0xf3e08000 /* mrs */,
10904 0xf000d000 /* bl */};
10905 static const uint32_t armv6m_mask[] = {0xffe0d000,
10906 0xfff0d0f0,
10907 0xfff0d0f0,
10908 0xfff0d0f0,
10909 0xffe0d000,
10910 0xf800d000};
10912 for (i = 0; i < ARRAY_SIZE(armv6m_insn); i++) {
10913 if ((insn & armv6m_mask[i]) == armv6m_insn[i]) {
10914 found = true;
10915 break;
10918 if (!found) {
10919 goto illegal_op;
10921 } else if ((insn & 0xf800e800) != 0xf000e800) {
10922 ARCH(6T2);
10925 rn = (insn >> 16) & 0xf;
10926 rs = (insn >> 12) & 0xf;
10927 rd = (insn >> 8) & 0xf;
10928 rm = insn & 0xf;
10929 switch ((insn >> 25) & 0xf) {
10930 case 0: case 1: case 2: case 3:
10931 /* 16-bit instructions. Should never happen. */
10932 abort();
10933 case 4:
10934 if (insn & (1 << 22)) {
10935 /* 0b1110_100x_x1xx_xxxx_xxxx_xxxx_xxxx_xxxx
10936 * - load/store doubleword, load/store exclusive, ldacq/strel,
10937 * table branch, TT.
10939 if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_M) &&
10940 arm_dc_feature(s, ARM_FEATURE_V8)) {
10941 /* 0b1110_1001_0111_1111_1110_1001_0111_111
10942 * - SG (v8M only)
10943 * The bulk of the behaviour for this instruction is implemented
10944 * in v7m_handle_execute_nsc(), which deals with the insn when
10945 * it is executed by a CPU in non-secure state from memory
10946 * which is Secure & NonSecure-Callable.
10947 * Here we only need to handle the remaining cases:
10948 * * in NS memory (including the "security extension not
10949 * implemented" case) : NOP
10950 * * in S memory but CPU already secure (clear IT bits)
10951 * We know that the attribute for the memory this insn is
10952 * in must match the current CPU state, because otherwise
10953 * get_phys_addr_pmsav8 would have generated an exception.
10955 if (s->v8m_secure) {
10956 /* Like the IT insn, we don't need to generate any code */
10957 s->condexec_cond = 0;
10958 s->condexec_mask = 0;
10960 } else if (insn & 0x01200000) {
10961 /* 0b1110_1000_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
10962 * - load/store dual (post-indexed)
10963 * 0b1111_1001_x10x_xxxx_xxxx_xxxx_xxxx_xxxx
10964 * - load/store dual (literal and immediate)
10965 * 0b1111_1001_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
10966 * - load/store dual (pre-indexed)
10968 bool wback = extract32(insn, 21, 1);
10970 if (rn == 15) {
10971 if (insn & (1 << 21)) {
10972 /* UNPREDICTABLE */
10973 goto illegal_op;
10975 addr = tcg_temp_new_i32();
10976 tcg_gen_movi_i32(addr, s->pc & ~3);
10977 } else {
10978 addr = load_reg(s, rn);
10980 offset = (insn & 0xff) * 4;
10981 if ((insn & (1 << 23)) == 0) {
10982 offset = -offset;
10985 if (s->v8m_stackcheck && rn == 13 && wback) {
10987 * Here 'addr' is the current SP; if offset is +ve we're
10988 * moving SP up, else down. It is UNKNOWN whether the limit
10989 * check triggers when SP starts below the limit and ends
10990 * up above it; check whichever of the current and final
10991 * SP is lower, so QEMU will trigger in that situation.
10993 if ((int32_t)offset < 0) {
10994 TCGv_i32 newsp = tcg_temp_new_i32();
10996 tcg_gen_addi_i32(newsp, addr, offset);
10997 gen_helper_v8m_stackcheck(cpu_env, newsp);
10998 tcg_temp_free_i32(newsp);
10999 } else {
11000 gen_helper_v8m_stackcheck(cpu_env, addr);
11004 if (insn & (1 << 24)) {
11005 tcg_gen_addi_i32(addr, addr, offset);
11006 offset = 0;
11008 if (insn & (1 << 20)) {
11009 /* ldrd */
11010 tmp = tcg_temp_new_i32();
11011 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
11012 store_reg(s, rs, tmp);
11013 tcg_gen_addi_i32(addr, addr, 4);
11014 tmp = tcg_temp_new_i32();
11015 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
11016 store_reg(s, rd, tmp);
11017 } else {
11018 /* strd */
11019 tmp = load_reg(s, rs);
11020 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
11021 tcg_temp_free_i32(tmp);
11022 tcg_gen_addi_i32(addr, addr, 4);
11023 tmp = load_reg(s, rd);
11024 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
11025 tcg_temp_free_i32(tmp);
11027 if (wback) {
11028 /* Base writeback. */
11029 tcg_gen_addi_i32(addr, addr, offset - 4);
11030 store_reg(s, rn, addr);
11031 } else {
11032 tcg_temp_free_i32(addr);
11034 } else if ((insn & (1 << 23)) == 0) {
11035 /* 0b1110_1000_010x_xxxx_xxxx_xxxx_xxxx_xxxx
11036 * - load/store exclusive word
11037 * - TT (v8M only)
11039 if (rs == 15) {
11040 if (!(insn & (1 << 20)) &&
11041 arm_dc_feature(s, ARM_FEATURE_M) &&
11042 arm_dc_feature(s, ARM_FEATURE_V8)) {
11043 /* 0b1110_1000_0100_xxxx_1111_xxxx_xxxx_xxxx
11044 * - TT (v8M only)
11046 bool alt = insn & (1 << 7);
11047 TCGv_i32 addr, op, ttresp;
11049 if ((insn & 0x3f) || rd == 13 || rd == 15 || rn == 15) {
11050 /* we UNDEF for these UNPREDICTABLE cases */
11051 goto illegal_op;
11054 if (alt && !s->v8m_secure) {
11055 goto illegal_op;
11058 addr = load_reg(s, rn);
11059 op = tcg_const_i32(extract32(insn, 6, 2));
11060 ttresp = tcg_temp_new_i32();
11061 gen_helper_v7m_tt(ttresp, cpu_env, addr, op);
11062 tcg_temp_free_i32(addr);
11063 tcg_temp_free_i32(op);
11064 store_reg(s, rd, ttresp);
11065 break;
11067 goto illegal_op;
11069 addr = tcg_temp_local_new_i32();
11070 load_reg_var(s, addr, rn);
11071 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
11072 if (insn & (1 << 20)) {
11073 gen_load_exclusive(s, rs, 15, addr, 2);
11074 } else {
11075 gen_store_exclusive(s, rd, rs, 15, addr, 2);
11077 tcg_temp_free_i32(addr);
11078 } else if ((insn & (7 << 5)) == 0) {
11079 /* Table Branch. */
11080 if (rn == 15) {
11081 addr = tcg_temp_new_i32();
11082 tcg_gen_movi_i32(addr, s->pc);
11083 } else {
11084 addr = load_reg(s, rn);
11086 tmp = load_reg(s, rm);
11087 tcg_gen_add_i32(addr, addr, tmp);
11088 if (insn & (1 << 4)) {
11089 /* tbh */
11090 tcg_gen_add_i32(addr, addr, tmp);
11091 tcg_temp_free_i32(tmp);
11092 tmp = tcg_temp_new_i32();
11093 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
11094 } else { /* tbb */
11095 tcg_temp_free_i32(tmp);
11096 tmp = tcg_temp_new_i32();
11097 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
11099 tcg_temp_free_i32(addr);
11100 tcg_gen_shli_i32(tmp, tmp, 1);
11101 tcg_gen_addi_i32(tmp, tmp, s->pc);
11102 store_reg(s, 15, tmp);
11103 } else {
11104 bool is_lasr = false;
11105 bool is_ld = extract32(insn, 20, 1);
11106 int op2 = (insn >> 6) & 0x3;
11107 op = (insn >> 4) & 0x3;
11108 switch (op2) {
11109 case 0:
11110 goto illegal_op;
11111 case 1:
11112 /* Load/store exclusive byte/halfword/doubleword */
11113 if (op == 2) {
11114 goto illegal_op;
11116 ARCH(7);
11117 break;
11118 case 2:
11119 /* Load-acquire/store-release */
11120 if (op == 3) {
11121 goto illegal_op;
11123 /* Fall through */
11124 case 3:
11125 /* Load-acquire/store-release exclusive */
11126 ARCH(8);
11127 is_lasr = true;
11128 break;
11131 if (is_lasr && !is_ld) {
11132 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
11135 addr = tcg_temp_local_new_i32();
11136 load_reg_var(s, addr, rn);
11137 if (!(op2 & 1)) {
11138 if (is_ld) {
11139 tmp = tcg_temp_new_i32();
11140 switch (op) {
11141 case 0: /* ldab */
11142 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s),
11143 rs | ISSIsAcqRel);
11144 break;
11145 case 1: /* ldah */
11146 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s),
11147 rs | ISSIsAcqRel);
11148 break;
11149 case 2: /* lda */
11150 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s),
11151 rs | ISSIsAcqRel);
11152 break;
11153 default:
11154 abort();
11156 store_reg(s, rs, tmp);
11157 } else {
11158 tmp = load_reg(s, rs);
11159 switch (op) {
11160 case 0: /* stlb */
11161 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s),
11162 rs | ISSIsAcqRel);
11163 break;
11164 case 1: /* stlh */
11165 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s),
11166 rs | ISSIsAcqRel);
11167 break;
11168 case 2: /* stl */
11169 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s),
11170 rs | ISSIsAcqRel);
11171 break;
11172 default:
11173 abort();
11175 tcg_temp_free_i32(tmp);
11177 } else if (is_ld) {
11178 gen_load_exclusive(s, rs, rd, addr, op);
11179 } else {
11180 gen_store_exclusive(s, rm, rs, rd, addr, op);
11182 tcg_temp_free_i32(addr);
11184 if (is_lasr && is_ld) {
11185 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
11188 } else {
11189 /* Load/store multiple, RFE, SRS. */
11190 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
11191 /* RFE, SRS: not available in user mode or on M profile */
11192 if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
11193 goto illegal_op;
11195 if (insn & (1 << 20)) {
11196 /* rfe */
11197 addr = load_reg(s, rn);
11198 if ((insn & (1 << 24)) == 0)
11199 tcg_gen_addi_i32(addr, addr, -8);
11200 /* Load PC into tmp and CPSR into tmp2. */
11201 tmp = tcg_temp_new_i32();
11202 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
11203 tcg_gen_addi_i32(addr, addr, 4);
11204 tmp2 = tcg_temp_new_i32();
11205 gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
11206 if (insn & (1 << 21)) {
11207 /* Base writeback. */
11208 if (insn & (1 << 24)) {
11209 tcg_gen_addi_i32(addr, addr, 4);
11210 } else {
11211 tcg_gen_addi_i32(addr, addr, -4);
11213 store_reg(s, rn, addr);
11214 } else {
11215 tcg_temp_free_i32(addr);
11217 gen_rfe(s, tmp, tmp2);
11218 } else {
11219 /* srs */
11220 gen_srs(s, (insn & 0x1f), (insn & (1 << 24)) ? 1 : 2,
11221 insn & (1 << 21));
11223 } else {
11224 int i, loaded_base = 0;
11225 TCGv_i32 loaded_var;
11226 bool wback = extract32(insn, 21, 1);
11227 /* Load/store multiple. */
11228 addr = load_reg(s, rn);
11229 offset = 0;
11230 for (i = 0; i < 16; i++) {
11231 if (insn & (1 << i))
11232 offset += 4;
11235 if (insn & (1 << 24)) {
11236 tcg_gen_addi_i32(addr, addr, -offset);
11239 if (s->v8m_stackcheck && rn == 13 && wback) {
11241 * If the writeback is incrementing SP rather than
11242 * decrementing it, and the initial SP is below the
11243 * stack limit but the final written-back SP would
11244 * be above, then then we must not perform any memory
11245 * accesses, but it is IMPDEF whether we generate
11246 * an exception. We choose to do so in this case.
11247 * At this point 'addr' is the lowest address, so
11248 * either the original SP (if incrementing) or our
11249 * final SP (if decrementing), so that's what we check.
11251 gen_helper_v8m_stackcheck(cpu_env, addr);
11254 loaded_var = NULL;
11255 for (i = 0; i < 16; i++) {
11256 if ((insn & (1 << i)) == 0)
11257 continue;
11258 if (insn & (1 << 20)) {
11259 /* Load. */
11260 tmp = tcg_temp_new_i32();
11261 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
11262 if (i == 15) {
11263 gen_bx_excret(s, tmp);
11264 } else if (i == rn) {
11265 loaded_var = tmp;
11266 loaded_base = 1;
11267 } else {
11268 store_reg(s, i, tmp);
11270 } else {
11271 /* Store. */
11272 tmp = load_reg(s, i);
11273 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
11274 tcg_temp_free_i32(tmp);
11276 tcg_gen_addi_i32(addr, addr, 4);
11278 if (loaded_base) {
11279 store_reg(s, rn, loaded_var);
11281 if (wback) {
11282 /* Base register writeback. */
11283 if (insn & (1 << 24)) {
11284 tcg_gen_addi_i32(addr, addr, -offset);
11286 /* Fault if writeback register is in register list. */
11287 if (insn & (1 << rn))
11288 goto illegal_op;
11289 store_reg(s, rn, addr);
11290 } else {
11291 tcg_temp_free_i32(addr);
11295 break;
11296 case 5:
11298 op = (insn >> 21) & 0xf;
11299 if (op == 6) {
11300 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11301 goto illegal_op;
11303 /* Halfword pack. */
11304 tmp = load_reg(s, rn);
11305 tmp2 = load_reg(s, rm);
11306 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
11307 if (insn & (1 << 5)) {
11308 /* pkhtb */
11309 if (shift == 0)
11310 shift = 31;
11311 tcg_gen_sari_i32(tmp2, tmp2, shift);
11312 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
11313 tcg_gen_ext16u_i32(tmp2, tmp2);
11314 } else {
11315 /* pkhbt */
11316 if (shift)
11317 tcg_gen_shli_i32(tmp2, tmp2, shift);
11318 tcg_gen_ext16u_i32(tmp, tmp);
11319 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
11321 tcg_gen_or_i32(tmp, tmp, tmp2);
11322 tcg_temp_free_i32(tmp2);
11323 store_reg(s, rd, tmp);
11324 } else {
11325 /* Data processing register constant shift. */
11326 if (rn == 15) {
11327 tmp = tcg_temp_new_i32();
11328 tcg_gen_movi_i32(tmp, 0);
11329 } else {
11330 tmp = load_reg(s, rn);
11332 tmp2 = load_reg(s, rm);
11334 shiftop = (insn >> 4) & 3;
11335 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
11336 conds = (insn & (1 << 20)) != 0;
11337 logic_cc = (conds && thumb2_logic_op(op));
11338 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
11339 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
11340 goto illegal_op;
11341 tcg_temp_free_i32(tmp2);
11342 if (rd == 13 &&
11343 ((op == 2 && rn == 15) ||
11344 (op == 8 && rn == 13) ||
11345 (op == 13 && rn == 13))) {
11346 /* MOV SP, ... or ADD SP, SP, ... or SUB SP, SP, ... */
11347 store_sp_checked(s, tmp);
11348 } else if (rd != 15) {
11349 store_reg(s, rd, tmp);
11350 } else {
11351 tcg_temp_free_i32(tmp);
11354 break;
11355 case 13: /* Misc data processing. */
11356 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
11357 if (op < 4 && (insn & 0xf000) != 0xf000)
11358 goto illegal_op;
11359 switch (op) {
11360 case 0: /* Register controlled shift. */
11361 tmp = load_reg(s, rn);
11362 tmp2 = load_reg(s, rm);
11363 if ((insn & 0x70) != 0)
11364 goto illegal_op;
11366 * 0b1111_1010_0xxx_xxxx_1111_xxxx_0000_xxxx:
11367 * - MOV, MOVS (register-shifted register), flagsetting
11369 op = (insn >> 21) & 3;
11370 logic_cc = (insn & (1 << 20)) != 0;
11371 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
11372 if (logic_cc)
11373 gen_logic_CC(tmp);
11374 store_reg(s, rd, tmp);
11375 break;
11376 case 1: /* Sign/zero extend. */
11377 op = (insn >> 20) & 7;
11378 switch (op) {
11379 case 0: /* SXTAH, SXTH */
11380 case 1: /* UXTAH, UXTH */
11381 case 4: /* SXTAB, SXTB */
11382 case 5: /* UXTAB, UXTB */
11383 break;
11384 case 2: /* SXTAB16, SXTB16 */
11385 case 3: /* UXTAB16, UXTB16 */
11386 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11387 goto illegal_op;
11389 break;
11390 default:
11391 goto illegal_op;
11393 if (rn != 15) {
11394 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11395 goto illegal_op;
11398 tmp = load_reg(s, rm);
11399 shift = (insn >> 4) & 3;
11400 /* ??? In many cases it's not necessary to do a
11401 rotate, a shift is sufficient. */
11402 if (shift != 0)
11403 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
11404 op = (insn >> 20) & 7;
11405 switch (op) {
11406 case 0: gen_sxth(tmp); break;
11407 case 1: gen_uxth(tmp); break;
11408 case 2: gen_sxtb16(tmp); break;
11409 case 3: gen_uxtb16(tmp); break;
11410 case 4: gen_sxtb(tmp); break;
11411 case 5: gen_uxtb(tmp); break;
11412 default:
11413 g_assert_not_reached();
11415 if (rn != 15) {
11416 tmp2 = load_reg(s, rn);
11417 if ((op >> 1) == 1) {
11418 gen_add16(tmp, tmp2);
11419 } else {
11420 tcg_gen_add_i32(tmp, tmp, tmp2);
11421 tcg_temp_free_i32(tmp2);
11424 store_reg(s, rd, tmp);
11425 break;
11426 case 2: /* SIMD add/subtract. */
11427 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11428 goto illegal_op;
11430 op = (insn >> 20) & 7;
11431 shift = (insn >> 4) & 7;
11432 if ((op & 3) == 3 || (shift & 3) == 3)
11433 goto illegal_op;
11434 tmp = load_reg(s, rn);
11435 tmp2 = load_reg(s, rm);
11436 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
11437 tcg_temp_free_i32(tmp2);
11438 store_reg(s, rd, tmp);
11439 break;
11440 case 3: /* Other data processing. */
11441 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
11442 if (op < 4) {
11443 /* Saturating add/subtract. */
11444 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11445 goto illegal_op;
11447 tmp = load_reg(s, rn);
11448 tmp2 = load_reg(s, rm);
11449 if (op & 1)
11450 gen_helper_double_saturate(tmp, cpu_env, tmp);
11451 if (op & 2)
11452 gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);
11453 else
11454 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
11455 tcg_temp_free_i32(tmp2);
11456 } else {
11457 switch (op) {
11458 case 0x0a: /* rbit */
11459 case 0x08: /* rev */
11460 case 0x09: /* rev16 */
11461 case 0x0b: /* revsh */
11462 case 0x18: /* clz */
11463 break;
11464 case 0x10: /* sel */
11465 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11466 goto illegal_op;
11468 break;
11469 case 0x20: /* crc32/crc32c */
11470 case 0x21:
11471 case 0x22:
11472 case 0x28:
11473 case 0x29:
11474 case 0x2a:
11475 if (!dc_isar_feature(aa32_crc32, s)) {
11476 goto illegal_op;
11478 break;
11479 default:
11480 goto illegal_op;
11482 tmp = load_reg(s, rn);
11483 switch (op) {
11484 case 0x0a: /* rbit */
11485 gen_helper_rbit(tmp, tmp);
11486 break;
11487 case 0x08: /* rev */
11488 tcg_gen_bswap32_i32(tmp, tmp);
11489 break;
11490 case 0x09: /* rev16 */
11491 gen_rev16(tmp);
11492 break;
11493 case 0x0b: /* revsh */
11494 gen_revsh(tmp);
11495 break;
11496 case 0x10: /* sel */
11497 tmp2 = load_reg(s, rm);
11498 tmp3 = tcg_temp_new_i32();
11499 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
11500 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
11501 tcg_temp_free_i32(tmp3);
11502 tcg_temp_free_i32(tmp2);
11503 break;
11504 case 0x18: /* clz */
11505 tcg_gen_clzi_i32(tmp, tmp, 32);
11506 break;
11507 case 0x20:
11508 case 0x21:
11509 case 0x22:
11510 case 0x28:
11511 case 0x29:
11512 case 0x2a:
11514 /* crc32/crc32c */
11515 uint32_t sz = op & 0x3;
11516 uint32_t c = op & 0x8;
11518 tmp2 = load_reg(s, rm);
11519 if (sz == 0) {
11520 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
11521 } else if (sz == 1) {
11522 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
11524 tmp3 = tcg_const_i32(1 << sz);
11525 if (c) {
11526 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
11527 } else {
11528 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
11530 tcg_temp_free_i32(tmp2);
11531 tcg_temp_free_i32(tmp3);
11532 break;
11534 default:
11535 g_assert_not_reached();
11538 store_reg(s, rd, tmp);
11539 break;
11540 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
11541 switch ((insn >> 20) & 7) {
11542 case 0: /* 32 x 32 -> 32 */
11543 case 7: /* Unsigned sum of absolute differences. */
11544 break;
11545 case 1: /* 16 x 16 -> 32 */
11546 case 2: /* Dual multiply add. */
11547 case 3: /* 32 * 16 -> 32msb */
11548 case 4: /* Dual multiply subtract. */
11549 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
11550 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11551 goto illegal_op;
11553 break;
11555 op = (insn >> 4) & 0xf;
11556 tmp = load_reg(s, rn);
11557 tmp2 = load_reg(s, rm);
11558 switch ((insn >> 20) & 7) {
11559 case 0: /* 32 x 32 -> 32 */
11560 tcg_gen_mul_i32(tmp, tmp, tmp2);
11561 tcg_temp_free_i32(tmp2);
11562 if (rs != 15) {
11563 tmp2 = load_reg(s, rs);
11564 if (op)
11565 tcg_gen_sub_i32(tmp, tmp2, tmp);
11566 else
11567 tcg_gen_add_i32(tmp, tmp, tmp2);
11568 tcg_temp_free_i32(tmp2);
11570 break;
11571 case 1: /* 16 x 16 -> 32 */
11572 gen_mulxy(tmp, tmp2, op & 2, op & 1);
11573 tcg_temp_free_i32(tmp2);
11574 if (rs != 15) {
11575 tmp2 = load_reg(s, rs);
11576 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
11577 tcg_temp_free_i32(tmp2);
11579 break;
11580 case 2: /* Dual multiply add. */
11581 case 4: /* Dual multiply subtract. */
11582 if (op)
11583 gen_swap_half(tmp2);
11584 gen_smul_dual(tmp, tmp2);
11585 if (insn & (1 << 22)) {
11586 /* This subtraction cannot overflow. */
11587 tcg_gen_sub_i32(tmp, tmp, tmp2);
11588 } else {
11589 /* This addition cannot overflow 32 bits;
11590 * however it may overflow considered as a signed
11591 * operation, in which case we must set the Q flag.
11593 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
11595 tcg_temp_free_i32(tmp2);
11596 if (rs != 15)
11598 tmp2 = load_reg(s, rs);
11599 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
11600 tcg_temp_free_i32(tmp2);
11602 break;
11603 case 3: /* 32 * 16 -> 32msb */
11604 if (op)
11605 tcg_gen_sari_i32(tmp2, tmp2, 16);
11606 else
11607 gen_sxth(tmp2);
11608 tmp64 = gen_muls_i64_i32(tmp, tmp2);
11609 tcg_gen_shri_i64(tmp64, tmp64, 16);
11610 tmp = tcg_temp_new_i32();
11611 tcg_gen_extrl_i64_i32(tmp, tmp64);
11612 tcg_temp_free_i64(tmp64);
11613 if (rs != 15)
11615 tmp2 = load_reg(s, rs);
11616 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
11617 tcg_temp_free_i32(tmp2);
11619 break;
11620 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
11621 tmp64 = gen_muls_i64_i32(tmp, tmp2);
11622 if (rs != 15) {
11623 tmp = load_reg(s, rs);
11624 if (insn & (1 << 20)) {
11625 tmp64 = gen_addq_msw(tmp64, tmp);
11626 } else {
11627 tmp64 = gen_subq_msw(tmp64, tmp);
11630 if (insn & (1 << 4)) {
11631 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
11633 tcg_gen_shri_i64(tmp64, tmp64, 32);
11634 tmp = tcg_temp_new_i32();
11635 tcg_gen_extrl_i64_i32(tmp, tmp64);
11636 tcg_temp_free_i64(tmp64);
11637 break;
11638 case 7: /* Unsigned sum of absolute differences. */
11639 gen_helper_usad8(tmp, tmp, tmp2);
11640 tcg_temp_free_i32(tmp2);
11641 if (rs != 15) {
11642 tmp2 = load_reg(s, rs);
11643 tcg_gen_add_i32(tmp, tmp, tmp2);
11644 tcg_temp_free_i32(tmp2);
11646 break;
11648 store_reg(s, rd, tmp);
11649 break;
11650 case 6: case 7: /* 64-bit multiply, Divide. */
11651 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
11652 tmp = load_reg(s, rn);
11653 tmp2 = load_reg(s, rm);
11654 if ((op & 0x50) == 0x10) {
11655 /* sdiv, udiv */
11656 if (!dc_isar_feature(thumb_div, s)) {
11657 goto illegal_op;
11659 if (op & 0x20)
11660 gen_helper_udiv(tmp, tmp, tmp2);
11661 else
11662 gen_helper_sdiv(tmp, tmp, tmp2);
11663 tcg_temp_free_i32(tmp2);
11664 store_reg(s, rd, tmp);
11665 } else if ((op & 0xe) == 0xc) {
11666 /* Dual multiply accumulate long. */
11667 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11668 tcg_temp_free_i32(tmp);
11669 tcg_temp_free_i32(tmp2);
11670 goto illegal_op;
11672 if (op & 1)
11673 gen_swap_half(tmp2);
11674 gen_smul_dual(tmp, tmp2);
11675 if (op & 0x10) {
11676 tcg_gen_sub_i32(tmp, tmp, tmp2);
11677 } else {
11678 tcg_gen_add_i32(tmp, tmp, tmp2);
11680 tcg_temp_free_i32(tmp2);
11681 /* BUGFIX */
11682 tmp64 = tcg_temp_new_i64();
11683 tcg_gen_ext_i32_i64(tmp64, tmp);
11684 tcg_temp_free_i32(tmp);
11685 gen_addq(s, tmp64, rs, rd);
11686 gen_storeq_reg(s, rs, rd, tmp64);
11687 tcg_temp_free_i64(tmp64);
11688 } else {
11689 if (op & 0x20) {
11690 /* Unsigned 64-bit multiply */
11691 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
11692 } else {
11693 if (op & 8) {
11694 /* smlalxy */
11695 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11696 tcg_temp_free_i32(tmp2);
11697 tcg_temp_free_i32(tmp);
11698 goto illegal_op;
11700 gen_mulxy(tmp, tmp2, op & 2, op & 1);
11701 tcg_temp_free_i32(tmp2);
11702 tmp64 = tcg_temp_new_i64();
11703 tcg_gen_ext_i32_i64(tmp64, tmp);
11704 tcg_temp_free_i32(tmp);
11705 } else {
11706 /* Signed 64-bit multiply */
11707 tmp64 = gen_muls_i64_i32(tmp, tmp2);
11710 if (op & 4) {
11711 /* umaal */
11712 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11713 tcg_temp_free_i64(tmp64);
11714 goto illegal_op;
11716 gen_addq_lo(s, tmp64, rs);
11717 gen_addq_lo(s, tmp64, rd);
11718 } else if (op & 0x40) {
11719 /* 64-bit accumulate. */
11720 gen_addq(s, tmp64, rs, rd);
11722 gen_storeq_reg(s, rs, rd, tmp64);
11723 tcg_temp_free_i64(tmp64);
11725 break;
11727 break;
11728 case 6: case 7: case 14: case 15:
11729 /* Coprocessor. */
11730 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11731 /* 0b111x_11xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx */
11732 if (extract32(insn, 24, 2) == 3) {
11733 goto illegal_op; /* op0 = 0b11 : unallocated */
11737 * Decode VLLDM and VLSTM first: these are nonstandard because:
11738 * * if there is no FPU then these insns must NOP in
11739 * Secure state and UNDEF in Nonsecure state
11740 * * if there is an FPU then these insns do not have
11741 * the usual behaviour that disas_vfp_insn() provides of
11742 * being controlled by CPACR/NSACR enable bits or the
11743 * lazy-stacking logic.
11745 if (arm_dc_feature(s, ARM_FEATURE_V8) &&
11746 (insn & 0xffa00f00) == 0xec200a00) {
11747 /* 0b1110_1100_0x1x_xxxx_xxxx_1010_xxxx_xxxx
11748 * - VLLDM, VLSTM
11749 * We choose to UNDEF if the RAZ bits are non-zero.
11751 if (!s->v8m_secure || (insn & 0x0040f0ff)) {
11752 goto illegal_op;
11754 /* Just NOP since FP support is not implemented */
11755 break;
11757 if (arm_dc_feature(s, ARM_FEATURE_VFP) &&
11758 ((insn >> 8) & 0xe) == 10) {
11759 /* FP, and the CPU supports it */
11760 if (disas_vfp_insn(s, insn)) {
11761 goto illegal_op;
11763 break;
11766 /* All other insns: NOCP */
11767 gen_exception_insn(s, 4, EXCP_NOCP, syn_uncategorized(),
11768 default_exception_el(s));
11769 break;
11771 if ((insn & 0xfe000a00) == 0xfc000800
11772 && arm_dc_feature(s, ARM_FEATURE_V8)) {
11773 /* The Thumb2 and ARM encodings are identical. */
11774 if (disas_neon_insn_3same_ext(s, insn)) {
11775 goto illegal_op;
11777 } else if ((insn & 0xff000a00) == 0xfe000800
11778 && arm_dc_feature(s, ARM_FEATURE_V8)) {
11779 /* The Thumb2 and ARM encodings are identical. */
11780 if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
11781 goto illegal_op;
11783 } else if (((insn >> 24) & 3) == 3) {
11784 /* Translate into the equivalent ARM encoding. */
11785 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
11786 if (disas_neon_data_insn(s, insn)) {
11787 goto illegal_op;
11789 } else if (((insn >> 8) & 0xe) == 10) {
11790 if (disas_vfp_insn(s, insn)) {
11791 goto illegal_op;
11793 } else {
11794 if (insn & (1 << 28))
11795 goto illegal_op;
11796 if (disas_coproc_insn(s, insn)) {
11797 goto illegal_op;
11800 break;
11801 case 8: case 9: case 10: case 11:
11802 if (insn & (1 << 15)) {
11803 /* Branches, misc control. */
11804 if (insn & 0x5000) {
11805 /* Unconditional branch. */
11806 /* signextend(hw1[10:0]) -> offset[:12]. */
11807 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
11808 /* hw1[10:0] -> offset[11:1]. */
11809 offset |= (insn & 0x7ff) << 1;
11810 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
11811 offset[24:22] already have the same value because of the
11812 sign extension above. */
11813 offset ^= ((~insn) & (1 << 13)) << 10;
11814 offset ^= ((~insn) & (1 << 11)) << 11;
11816 if (insn & (1 << 14)) {
11817 /* Branch and link. */
11818 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
11821 offset += s->pc;
11822 if (insn & (1 << 12)) {
11823 /* b/bl */
11824 gen_jmp(s, offset);
11825 } else {
11826 /* blx */
11827 offset &= ~(uint32_t)2;
11828 /* thumb2 bx, no need to check */
11829 gen_bx_im(s, offset);
11831 } else if (((insn >> 23) & 7) == 7) {
11832 /* Misc control */
11833 if (insn & (1 << 13))
11834 goto illegal_op;
11836 if (insn & (1 << 26)) {
11837 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11838 goto illegal_op;
11840 if (!(insn & (1 << 20))) {
11841 /* Hypervisor call (v7) */
11842 int imm16 = extract32(insn, 16, 4) << 12
11843 | extract32(insn, 0, 12);
11844 ARCH(7);
11845 if (IS_USER(s)) {
11846 goto illegal_op;
11848 gen_hvc(s, imm16);
11849 } else {
11850 /* Secure monitor call (v6+) */
11851 ARCH(6K);
11852 if (IS_USER(s)) {
11853 goto illegal_op;
11855 gen_smc(s);
11857 } else {
11858 op = (insn >> 20) & 7;
11859 switch (op) {
11860 case 0: /* msr cpsr. */
11861 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11862 tmp = load_reg(s, rn);
11863 /* the constant is the mask and SYSm fields */
11864 addr = tcg_const_i32(insn & 0xfff);
11865 gen_helper_v7m_msr(cpu_env, addr, tmp);
11866 tcg_temp_free_i32(addr);
11867 tcg_temp_free_i32(tmp);
11868 gen_lookup_tb(s);
11869 break;
11871 /* fall through */
11872 case 1: /* msr spsr. */
11873 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11874 goto illegal_op;
11877 if (extract32(insn, 5, 1)) {
11878 /* MSR (banked) */
11879 int sysm = extract32(insn, 8, 4) |
11880 (extract32(insn, 4, 1) << 4);
11881 int r = op & 1;
11883 gen_msr_banked(s, r, sysm, rm);
11884 break;
11887 /* MSR (for PSRs) */
11888 tmp = load_reg(s, rn);
11889 if (gen_set_psr(s,
11890 msr_mask(s, (insn >> 8) & 0xf, op == 1),
11891 op == 1, tmp))
11892 goto illegal_op;
11893 break;
11894 case 2: /* cps, nop-hint. */
11895 if (((insn >> 8) & 7) == 0) {
11896 gen_nop_hint(s, insn & 0xff);
11898 /* Implemented as NOP in user mode. */
11899 if (IS_USER(s))
11900 break;
11901 offset = 0;
11902 imm = 0;
11903 if (insn & (1 << 10)) {
11904 if (insn & (1 << 7))
11905 offset |= CPSR_A;
11906 if (insn & (1 << 6))
11907 offset |= CPSR_I;
11908 if (insn & (1 << 5))
11909 offset |= CPSR_F;
11910 if (insn & (1 << 9))
11911 imm = CPSR_A | CPSR_I | CPSR_F;
11913 if (insn & (1 << 8)) {
11914 offset |= 0x1f;
11915 imm |= (insn & 0x1f);
11917 if (offset) {
11918 gen_set_psr_im(s, offset, 0, imm);
11920 break;
11921 case 3: /* Special control operations. */
11922 if (!arm_dc_feature(s, ARM_FEATURE_V7) &&
11923 !arm_dc_feature(s, ARM_FEATURE_M)) {
11924 goto illegal_op;
11926 op = (insn >> 4) & 0xf;
11927 switch (op) {
11928 case 2: /* clrex */
11929 gen_clrex(s);
11930 break;
11931 case 4: /* dsb */
11932 case 5: /* dmb */
11933 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
11934 break;
11935 case 6: /* isb */
11936 /* We need to break the TB after this insn
11937 * to execute self-modifying code correctly
11938 * and also to take any pending interrupts
11939 * immediately.
11941 gen_goto_tb(s, 0, s->pc & ~1);
11942 break;
11943 case 7: /* sb */
11944 if ((insn & 0xf) || !dc_isar_feature(aa32_sb, s)) {
11945 goto illegal_op;
11948 * TODO: There is no speculation barrier opcode
11949 * for TCG; MB and end the TB instead.
11951 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
11952 gen_goto_tb(s, 0, s->pc & ~1);
11953 break;
11954 default:
11955 goto illegal_op;
11957 break;
11958 case 4: /* bxj */
11959 /* Trivial implementation equivalent to bx.
11960 * This instruction doesn't exist at all for M-profile.
11962 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11963 goto illegal_op;
11965 tmp = load_reg(s, rn);
11966 gen_bx(s, tmp);
11967 break;
11968 case 5: /* Exception return. */
11969 if (IS_USER(s)) {
11970 goto illegal_op;
11972 if (rn != 14 || rd != 15) {
11973 goto illegal_op;
11975 if (s->current_el == 2) {
11976 /* ERET from Hyp uses ELR_Hyp, not LR */
11977 if (insn & 0xff) {
11978 goto illegal_op;
11980 tmp = load_cpu_field(elr_el[2]);
11981 } else {
11982 tmp = load_reg(s, rn);
11983 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
11985 gen_exception_return(s, tmp);
11986 break;
11987 case 6: /* MRS */
11988 if (extract32(insn, 5, 1) &&
11989 !arm_dc_feature(s, ARM_FEATURE_M)) {
11990 /* MRS (banked) */
11991 int sysm = extract32(insn, 16, 4) |
11992 (extract32(insn, 4, 1) << 4);
11994 gen_mrs_banked(s, 0, sysm, rd);
11995 break;
11998 if (extract32(insn, 16, 4) != 0xf) {
11999 goto illegal_op;
12001 if (!arm_dc_feature(s, ARM_FEATURE_M) &&
12002 extract32(insn, 0, 8) != 0) {
12003 goto illegal_op;
12006 /* mrs cpsr */
12007 tmp = tcg_temp_new_i32();
12008 if (arm_dc_feature(s, ARM_FEATURE_M)) {
12009 addr = tcg_const_i32(insn & 0xff);
12010 gen_helper_v7m_mrs(tmp, cpu_env, addr);
12011 tcg_temp_free_i32(addr);
12012 } else {
12013 gen_helper_cpsr_read(tmp, cpu_env);
12015 store_reg(s, rd, tmp);
12016 break;
12017 case 7: /* MRS */
12018 if (extract32(insn, 5, 1) &&
12019 !arm_dc_feature(s, ARM_FEATURE_M)) {
12020 /* MRS (banked) */
12021 int sysm = extract32(insn, 16, 4) |
12022 (extract32(insn, 4, 1) << 4);
12024 gen_mrs_banked(s, 1, sysm, rd);
12025 break;
12028 /* mrs spsr. */
12029 /* Not accessible in user mode. */
12030 if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
12031 goto illegal_op;
12034 if (extract32(insn, 16, 4) != 0xf ||
12035 extract32(insn, 0, 8) != 0) {
12036 goto illegal_op;
12039 tmp = load_cpu_field(spsr);
12040 store_reg(s, rd, tmp);
12041 break;
12044 } else {
12045 /* Conditional branch. */
12046 op = (insn >> 22) & 0xf;
12047 /* Generate a conditional jump to next instruction. */
12048 arm_skip_unless(s, op);
12050 /* offset[11:1] = insn[10:0] */
12051 offset = (insn & 0x7ff) << 1;
12052 /* offset[17:12] = insn[21:16]. */
12053 offset |= (insn & 0x003f0000) >> 4;
12054 /* offset[31:20] = insn[26]. */
12055 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
12056 /* offset[18] = insn[13]. */
12057 offset |= (insn & (1 << 13)) << 5;
12058 /* offset[19] = insn[11]. */
12059 offset |= (insn & (1 << 11)) << 8;
12061 /* jump to the offset */
12062 gen_jmp(s, s->pc + offset);
12064 } else {
12066 * 0b1111_0xxx_xxxx_0xxx_xxxx_xxxx
12067 * - Data-processing (modified immediate, plain binary immediate)
12069 if (insn & (1 << 25)) {
12071 * 0b1111_0x1x_xxxx_0xxx_xxxx_xxxx
12072 * - Data-processing (plain binary immediate)
12074 if (insn & (1 << 24)) {
12075 if (insn & (1 << 20))
12076 goto illegal_op;
12077 /* Bitfield/Saturate. */
12078 op = (insn >> 21) & 7;
12079 imm = insn & 0x1f;
12080 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
12081 if (rn == 15) {
12082 tmp = tcg_temp_new_i32();
12083 tcg_gen_movi_i32(tmp, 0);
12084 } else {
12085 tmp = load_reg(s, rn);
12087 switch (op) {
12088 case 2: /* Signed bitfield extract. */
12089 imm++;
12090 if (shift + imm > 32)
12091 goto illegal_op;
12092 if (imm < 32) {
12093 tcg_gen_sextract_i32(tmp, tmp, shift, imm);
12095 break;
12096 case 6: /* Unsigned bitfield extract. */
12097 imm++;
12098 if (shift + imm > 32)
12099 goto illegal_op;
12100 if (imm < 32) {
12101 tcg_gen_extract_i32(tmp, tmp, shift, imm);
12103 break;
12104 case 3: /* Bitfield insert/clear. */
12105 if (imm < shift)
12106 goto illegal_op;
12107 imm = imm + 1 - shift;
12108 if (imm != 32) {
12109 tmp2 = load_reg(s, rd);
12110 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, imm);
12111 tcg_temp_free_i32(tmp2);
12113 break;
12114 case 7:
12115 goto illegal_op;
12116 default: /* Saturate. */
12117 if (shift) {
12118 if (op & 1)
12119 tcg_gen_sari_i32(tmp, tmp, shift);
12120 else
12121 tcg_gen_shli_i32(tmp, tmp, shift);
12123 tmp2 = tcg_const_i32(imm);
12124 if (op & 4) {
12125 /* Unsigned. */
12126 if ((op & 1) && shift == 0) {
12127 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
12128 tcg_temp_free_i32(tmp);
12129 tcg_temp_free_i32(tmp2);
12130 goto illegal_op;
12132 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
12133 } else {
12134 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
12136 } else {
12137 /* Signed. */
12138 if ((op & 1) && shift == 0) {
12139 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
12140 tcg_temp_free_i32(tmp);
12141 tcg_temp_free_i32(tmp2);
12142 goto illegal_op;
12144 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
12145 } else {
12146 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
12149 tcg_temp_free_i32(tmp2);
12150 break;
12152 store_reg(s, rd, tmp);
12153 } else {
12154 imm = ((insn & 0x04000000) >> 15)
12155 | ((insn & 0x7000) >> 4) | (insn & 0xff);
12156 if (insn & (1 << 22)) {
12157 /* 16-bit immediate. */
12158 imm |= (insn >> 4) & 0xf000;
12159 if (insn & (1 << 23)) {
12160 /* movt */
12161 tmp = load_reg(s, rd);
12162 tcg_gen_ext16u_i32(tmp, tmp);
12163 tcg_gen_ori_i32(tmp, tmp, imm << 16);
12164 } else {
12165 /* movw */
12166 tmp = tcg_temp_new_i32();
12167 tcg_gen_movi_i32(tmp, imm);
12169 store_reg(s, rd, tmp);
12170 } else {
12171 /* Add/sub 12-bit immediate. */
12172 if (rn == 15) {
12173 offset = s->pc & ~(uint32_t)3;
12174 if (insn & (1 << 23))
12175 offset -= imm;
12176 else
12177 offset += imm;
12178 tmp = tcg_temp_new_i32();
12179 tcg_gen_movi_i32(tmp, offset);
12180 store_reg(s, rd, tmp);
12181 } else {
12182 tmp = load_reg(s, rn);
12183 if (insn & (1 << 23))
12184 tcg_gen_subi_i32(tmp, tmp, imm);
12185 else
12186 tcg_gen_addi_i32(tmp, tmp, imm);
12187 if (rn == 13 && rd == 13) {
12188 /* ADD SP, SP, imm or SUB SP, SP, imm */
12189 store_sp_checked(s, tmp);
12190 } else {
12191 store_reg(s, rd, tmp);
12196 } else {
12198 * 0b1111_0x0x_xxxx_0xxx_xxxx_xxxx
12199 * - Data-processing (modified immediate)
12201 int shifter_out = 0;
12202 /* modified 12-bit immediate. */
12203 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
12204 imm = (insn & 0xff);
12205 switch (shift) {
12206 case 0: /* XY */
12207 /* Nothing to do. */
12208 break;
12209 case 1: /* 00XY00XY */
12210 imm |= imm << 16;
12211 break;
12212 case 2: /* XY00XY00 */
12213 imm |= imm << 16;
12214 imm <<= 8;
12215 break;
12216 case 3: /* XYXYXYXY */
12217 imm |= imm << 16;
12218 imm |= imm << 8;
12219 break;
12220 default: /* Rotated constant. */
12221 shift = (shift << 1) | (imm >> 7);
12222 imm |= 0x80;
12223 imm = imm << (32 - shift);
12224 shifter_out = 1;
12225 break;
12227 tmp2 = tcg_temp_new_i32();
12228 tcg_gen_movi_i32(tmp2, imm);
12229 rn = (insn >> 16) & 0xf;
12230 if (rn == 15) {
12231 tmp = tcg_temp_new_i32();
12232 tcg_gen_movi_i32(tmp, 0);
12233 } else {
12234 tmp = load_reg(s, rn);
12236 op = (insn >> 21) & 0xf;
12237 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
12238 shifter_out, tmp, tmp2))
12239 goto illegal_op;
12240 tcg_temp_free_i32(tmp2);
12241 rd = (insn >> 8) & 0xf;
12242 if (rd == 13 && rn == 13
12243 && (op == 8 || op == 13)) {
12244 /* ADD(S) SP, SP, imm or SUB(S) SP, SP, imm */
12245 store_sp_checked(s, tmp);
12246 } else if (rd != 15) {
12247 store_reg(s, rd, tmp);
12248 } else {
12249 tcg_temp_free_i32(tmp);
12253 break;
12254 case 12: /* Load/store single data item. */
12256 int postinc = 0;
12257 int writeback = 0;
12258 int memidx;
12259 ISSInfo issinfo;
12261 if ((insn & 0x01100000) == 0x01000000) {
12262 if (disas_neon_ls_insn(s, insn)) {
12263 goto illegal_op;
12265 break;
12267 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
12268 if (rs == 15) {
12269 if (!(insn & (1 << 20))) {
12270 goto illegal_op;
12272 if (op != 2) {
12273 /* Byte or halfword load space with dest == r15 : memory hints.
12274 * Catch them early so we don't emit pointless addressing code.
12275 * This space is a mix of:
12276 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
12277 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
12278 * cores)
12279 * unallocated hints, which must be treated as NOPs
12280 * UNPREDICTABLE space, which we NOP or UNDEF depending on
12281 * which is easiest for the decoding logic
12282 * Some space which must UNDEF
12284 int op1 = (insn >> 23) & 3;
12285 int op2 = (insn >> 6) & 0x3f;
12286 if (op & 2) {
12287 goto illegal_op;
12289 if (rn == 15) {
12290 /* UNPREDICTABLE, unallocated hint or
12291 * PLD/PLDW/PLI (literal)
12293 return;
12295 if (op1 & 1) {
12296 return; /* PLD/PLDW/PLI or unallocated hint */
12298 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
12299 return; /* PLD/PLDW/PLI or unallocated hint */
12301 /* UNDEF space, or an UNPREDICTABLE */
12302 goto illegal_op;
12305 memidx = get_mem_index(s);
12306 if (rn == 15) {
12307 addr = tcg_temp_new_i32();
12308 /* PC relative. */
12309 /* s->pc has already been incremented by 4. */
12310 imm = s->pc & 0xfffffffc;
12311 if (insn & (1 << 23))
12312 imm += insn & 0xfff;
12313 else
12314 imm -= insn & 0xfff;
12315 tcg_gen_movi_i32(addr, imm);
12316 } else {
12317 addr = load_reg(s, rn);
12318 if (insn & (1 << 23)) {
12319 /* Positive offset. */
12320 imm = insn & 0xfff;
12321 tcg_gen_addi_i32(addr, addr, imm);
12322 } else {
12323 imm = insn & 0xff;
12324 switch ((insn >> 8) & 0xf) {
12325 case 0x0: /* Shifted Register. */
12326 shift = (insn >> 4) & 0xf;
12327 if (shift > 3) {
12328 tcg_temp_free_i32(addr);
12329 goto illegal_op;
12331 tmp = load_reg(s, rm);
12332 if (shift)
12333 tcg_gen_shli_i32(tmp, tmp, shift);
12334 tcg_gen_add_i32(addr, addr, tmp);
12335 tcg_temp_free_i32(tmp);
12336 break;
12337 case 0xc: /* Negative offset. */
12338 tcg_gen_addi_i32(addr, addr, -imm);
12339 break;
12340 case 0xe: /* User privilege. */
12341 tcg_gen_addi_i32(addr, addr, imm);
12342 memidx = get_a32_user_mem_index(s);
12343 break;
12344 case 0x9: /* Post-decrement. */
12345 imm = -imm;
12346 /* Fall through. */
12347 case 0xb: /* Post-increment. */
12348 postinc = 1;
12349 writeback = 1;
12350 break;
12351 case 0xd: /* Pre-decrement. */
12352 imm = -imm;
12353 /* Fall through. */
12354 case 0xf: /* Pre-increment. */
12355 writeback = 1;
12356 break;
12357 default:
12358 tcg_temp_free_i32(addr);
12359 goto illegal_op;
12364 issinfo = writeback ? ISSInvalid : rs;
12366 if (s->v8m_stackcheck && rn == 13 && writeback) {
12368 * Stackcheck. Here we know 'addr' is the current SP;
12369 * if imm is +ve we're moving SP up, else down. It is
12370 * UNKNOWN whether the limit check triggers when SP starts
12371 * below the limit and ends up above it; we chose to do so.
12373 if ((int32_t)imm < 0) {
12374 TCGv_i32 newsp = tcg_temp_new_i32();
12376 tcg_gen_addi_i32(newsp, addr, imm);
12377 gen_helper_v8m_stackcheck(cpu_env, newsp);
12378 tcg_temp_free_i32(newsp);
12379 } else {
12380 gen_helper_v8m_stackcheck(cpu_env, addr);
12384 if (writeback && !postinc) {
12385 tcg_gen_addi_i32(addr, addr, imm);
12388 if (insn & (1 << 20)) {
12389 /* Load. */
12390 tmp = tcg_temp_new_i32();
12391 switch (op) {
12392 case 0:
12393 gen_aa32_ld8u_iss(s, tmp, addr, memidx, issinfo);
12394 break;
12395 case 4:
12396 gen_aa32_ld8s_iss(s, tmp, addr, memidx, issinfo);
12397 break;
12398 case 1:
12399 gen_aa32_ld16u_iss(s, tmp, addr, memidx, issinfo);
12400 break;
12401 case 5:
12402 gen_aa32_ld16s_iss(s, tmp, addr, memidx, issinfo);
12403 break;
12404 case 2:
12405 gen_aa32_ld32u_iss(s, tmp, addr, memidx, issinfo);
12406 break;
12407 default:
12408 tcg_temp_free_i32(tmp);
12409 tcg_temp_free_i32(addr);
12410 goto illegal_op;
12412 if (rs == 15) {
12413 gen_bx_excret(s, tmp);
12414 } else {
12415 store_reg(s, rs, tmp);
12417 } else {
12418 /* Store. */
12419 tmp = load_reg(s, rs);
12420 switch (op) {
12421 case 0:
12422 gen_aa32_st8_iss(s, tmp, addr, memidx, issinfo);
12423 break;
12424 case 1:
12425 gen_aa32_st16_iss(s, tmp, addr, memidx, issinfo);
12426 break;
12427 case 2:
12428 gen_aa32_st32_iss(s, tmp, addr, memidx, issinfo);
12429 break;
12430 default:
12431 tcg_temp_free_i32(tmp);
12432 tcg_temp_free_i32(addr);
12433 goto illegal_op;
12435 tcg_temp_free_i32(tmp);
12437 if (postinc)
12438 tcg_gen_addi_i32(addr, addr, imm);
12439 if (writeback) {
12440 store_reg(s, rn, addr);
12441 } else {
12442 tcg_temp_free_i32(addr);
12445 break;
12446 default:
12447 goto illegal_op;
12449 return;
12450 illegal_op:
12451 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
12452 default_exception_el(s));
12455 static void disas_thumb_insn(DisasContext *s, uint32_t insn)
12457 uint32_t val, op, rm, rn, rd, shift, cond;
12458 int32_t offset;
12459 int i;
12460 TCGv_i32 tmp;
12461 TCGv_i32 tmp2;
12462 TCGv_i32 addr;
12464 switch (insn >> 12) {
12465 case 0: case 1:
12467 rd = insn & 7;
12468 op = (insn >> 11) & 3;
12469 if (op == 3) {
12471 * 0b0001_1xxx_xxxx_xxxx
12472 * - Add, subtract (three low registers)
12473 * - Add, subtract (two low registers and immediate)
12475 rn = (insn >> 3) & 7;
12476 tmp = load_reg(s, rn);
12477 if (insn & (1 << 10)) {
12478 /* immediate */
12479 tmp2 = tcg_temp_new_i32();
12480 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
12481 } else {
12482 /* reg */
12483 rm = (insn >> 6) & 7;
12484 tmp2 = load_reg(s, rm);
12486 if (insn & (1 << 9)) {
12487 if (s->condexec_mask)
12488 tcg_gen_sub_i32(tmp, tmp, tmp2);
12489 else
12490 gen_sub_CC(tmp, tmp, tmp2);
12491 } else {
12492 if (s->condexec_mask)
12493 tcg_gen_add_i32(tmp, tmp, tmp2);
12494 else
12495 gen_add_CC(tmp, tmp, tmp2);
12497 tcg_temp_free_i32(tmp2);
12498 store_reg(s, rd, tmp);
12499 } else {
12500 /* shift immediate */
12501 rm = (insn >> 3) & 7;
12502 shift = (insn >> 6) & 0x1f;
12503 tmp = load_reg(s, rm);
12504 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
12505 if (!s->condexec_mask)
12506 gen_logic_CC(tmp);
12507 store_reg(s, rd, tmp);
12509 break;
12510 case 2: case 3:
12512 * 0b001x_xxxx_xxxx_xxxx
12513 * - Add, subtract, compare, move (one low register and immediate)
12515 op = (insn >> 11) & 3;
12516 rd = (insn >> 8) & 0x7;
12517 if (op == 0) { /* mov */
12518 tmp = tcg_temp_new_i32();
12519 tcg_gen_movi_i32(tmp, insn & 0xff);
12520 if (!s->condexec_mask)
12521 gen_logic_CC(tmp);
12522 store_reg(s, rd, tmp);
12523 } else {
12524 tmp = load_reg(s, rd);
12525 tmp2 = tcg_temp_new_i32();
12526 tcg_gen_movi_i32(tmp2, insn & 0xff);
12527 switch (op) {
12528 case 1: /* cmp */
12529 gen_sub_CC(tmp, tmp, tmp2);
12530 tcg_temp_free_i32(tmp);
12531 tcg_temp_free_i32(tmp2);
12532 break;
12533 case 2: /* add */
12534 if (s->condexec_mask)
12535 tcg_gen_add_i32(tmp, tmp, tmp2);
12536 else
12537 gen_add_CC(tmp, tmp, tmp2);
12538 tcg_temp_free_i32(tmp2);
12539 store_reg(s, rd, tmp);
12540 break;
12541 case 3: /* sub */
12542 if (s->condexec_mask)
12543 tcg_gen_sub_i32(tmp, tmp, tmp2);
12544 else
12545 gen_sub_CC(tmp, tmp, tmp2);
12546 tcg_temp_free_i32(tmp2);
12547 store_reg(s, rd, tmp);
12548 break;
12551 break;
12552 case 4:
12553 if (insn & (1 << 11)) {
12554 rd = (insn >> 8) & 7;
12555 /* load pc-relative. Bit 1 of PC is ignored. */
12556 val = s->pc + 2 + ((insn & 0xff) * 4);
12557 val &= ~(uint32_t)2;
12558 addr = tcg_temp_new_i32();
12559 tcg_gen_movi_i32(addr, val);
12560 tmp = tcg_temp_new_i32();
12561 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s),
12562 rd | ISSIs16Bit);
12563 tcg_temp_free_i32(addr);
12564 store_reg(s, rd, tmp);
12565 break;
12567 if (insn & (1 << 10)) {
12568 /* 0b0100_01xx_xxxx_xxxx
12569 * - data processing extended, branch and exchange
12571 rd = (insn & 7) | ((insn >> 4) & 8);
12572 rm = (insn >> 3) & 0xf;
12573 op = (insn >> 8) & 3;
12574 switch (op) {
12575 case 0: /* add */
12576 tmp = load_reg(s, rd);
12577 tmp2 = load_reg(s, rm);
12578 tcg_gen_add_i32(tmp, tmp, tmp2);
12579 tcg_temp_free_i32(tmp2);
12580 if (rd == 13) {
12581 /* ADD SP, SP, reg */
12582 store_sp_checked(s, tmp);
12583 } else {
12584 store_reg(s, rd, tmp);
12586 break;
12587 case 1: /* cmp */
12588 tmp = load_reg(s, rd);
12589 tmp2 = load_reg(s, rm);
12590 gen_sub_CC(tmp, tmp, tmp2);
12591 tcg_temp_free_i32(tmp2);
12592 tcg_temp_free_i32(tmp);
12593 break;
12594 case 2: /* mov/cpy */
12595 tmp = load_reg(s, rm);
12596 if (rd == 13) {
12597 /* MOV SP, reg */
12598 store_sp_checked(s, tmp);
12599 } else {
12600 store_reg(s, rd, tmp);
12602 break;
12603 case 3:
12605 /* 0b0100_0111_xxxx_xxxx
12606 * - branch [and link] exchange thumb register
12608 bool link = insn & (1 << 7);
12610 if (insn & 3) {
12611 goto undef;
12613 if (link) {
12614 ARCH(5);
12616 if ((insn & 4)) {
12617 /* BXNS/BLXNS: only exists for v8M with the
12618 * security extensions, and always UNDEF if NonSecure.
12619 * We don't implement these in the user-only mode
12620 * either (in theory you can use them from Secure User
12621 * mode but they are too tied in to system emulation.)
12623 if (!s->v8m_secure || IS_USER_ONLY) {
12624 goto undef;
12626 if (link) {
12627 gen_blxns(s, rm);
12628 } else {
12629 gen_bxns(s, rm);
12631 break;
12633 /* BLX/BX */
12634 tmp = load_reg(s, rm);
12635 if (link) {
12636 val = (uint32_t)s->pc | 1;
12637 tmp2 = tcg_temp_new_i32();
12638 tcg_gen_movi_i32(tmp2, val);
12639 store_reg(s, 14, tmp2);
12640 gen_bx(s, tmp);
12641 } else {
12642 /* Only BX works as exception-return, not BLX */
12643 gen_bx_excret(s, tmp);
12645 break;
12648 break;
12652 * 0b0100_00xx_xxxx_xxxx
12653 * - Data-processing (two low registers)
12655 rd = insn & 7;
12656 rm = (insn >> 3) & 7;
12657 op = (insn >> 6) & 0xf;
12658 if (op == 2 || op == 3 || op == 4 || op == 7) {
12659 /* the shift/rotate ops want the operands backwards */
12660 val = rm;
12661 rm = rd;
12662 rd = val;
12663 val = 1;
12664 } else {
12665 val = 0;
12668 if (op == 9) { /* neg */
12669 tmp = tcg_temp_new_i32();
12670 tcg_gen_movi_i32(tmp, 0);
12671 } else if (op != 0xf) { /* mvn doesn't read its first operand */
12672 tmp = load_reg(s, rd);
12673 } else {
12674 tmp = NULL;
12677 tmp2 = load_reg(s, rm);
12678 switch (op) {
12679 case 0x0: /* and */
12680 tcg_gen_and_i32(tmp, tmp, tmp2);
12681 if (!s->condexec_mask)
12682 gen_logic_CC(tmp);
12683 break;
12684 case 0x1: /* eor */
12685 tcg_gen_xor_i32(tmp, tmp, tmp2);
12686 if (!s->condexec_mask)
12687 gen_logic_CC(tmp);
12688 break;
12689 case 0x2: /* lsl */
12690 if (s->condexec_mask) {
12691 gen_shl(tmp2, tmp2, tmp);
12692 } else {
12693 gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
12694 gen_logic_CC(tmp2);
12696 break;
12697 case 0x3: /* lsr */
12698 if (s->condexec_mask) {
12699 gen_shr(tmp2, tmp2, tmp);
12700 } else {
12701 gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
12702 gen_logic_CC(tmp2);
12704 break;
12705 case 0x4: /* asr */
12706 if (s->condexec_mask) {
12707 gen_sar(tmp2, tmp2, tmp);
12708 } else {
12709 gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
12710 gen_logic_CC(tmp2);
12712 break;
12713 case 0x5: /* adc */
12714 if (s->condexec_mask) {
12715 gen_adc(tmp, tmp2);
12716 } else {
12717 gen_adc_CC(tmp, tmp, tmp2);
12719 break;
12720 case 0x6: /* sbc */
12721 if (s->condexec_mask) {
12722 gen_sub_carry(tmp, tmp, tmp2);
12723 } else {
12724 gen_sbc_CC(tmp, tmp, tmp2);
12726 break;
12727 case 0x7: /* ror */
12728 if (s->condexec_mask) {
12729 tcg_gen_andi_i32(tmp, tmp, 0x1f);
12730 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
12731 } else {
12732 gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);
12733 gen_logic_CC(tmp2);
12735 break;
12736 case 0x8: /* tst */
12737 tcg_gen_and_i32(tmp, tmp, tmp2);
12738 gen_logic_CC(tmp);
12739 rd = 16;
12740 break;
12741 case 0x9: /* neg */
12742 if (s->condexec_mask)
12743 tcg_gen_neg_i32(tmp, tmp2);
12744 else
12745 gen_sub_CC(tmp, tmp, tmp2);
12746 break;
12747 case 0xa: /* cmp */
12748 gen_sub_CC(tmp, tmp, tmp2);
12749 rd = 16;
12750 break;
12751 case 0xb: /* cmn */
12752 gen_add_CC(tmp, tmp, tmp2);
12753 rd = 16;
12754 break;
12755 case 0xc: /* orr */
12756 tcg_gen_or_i32(tmp, tmp, tmp2);
12757 if (!s->condexec_mask)
12758 gen_logic_CC(tmp);
12759 break;
12760 case 0xd: /* mul */
12761 tcg_gen_mul_i32(tmp, tmp, tmp2);
12762 if (!s->condexec_mask)
12763 gen_logic_CC(tmp);
12764 break;
12765 case 0xe: /* bic */
12766 tcg_gen_andc_i32(tmp, tmp, tmp2);
12767 if (!s->condexec_mask)
12768 gen_logic_CC(tmp);
12769 break;
12770 case 0xf: /* mvn */
12771 tcg_gen_not_i32(tmp2, tmp2);
12772 if (!s->condexec_mask)
12773 gen_logic_CC(tmp2);
12774 val = 1;
12775 rm = rd;
12776 break;
12778 if (rd != 16) {
12779 if (val) {
12780 store_reg(s, rm, tmp2);
12781 if (op != 0xf)
12782 tcg_temp_free_i32(tmp);
12783 } else {
12784 store_reg(s, rd, tmp);
12785 tcg_temp_free_i32(tmp2);
12787 } else {
12788 tcg_temp_free_i32(tmp);
12789 tcg_temp_free_i32(tmp2);
12791 break;
12793 case 5:
12794 /* load/store register offset. */
12795 rd = insn & 7;
12796 rn = (insn >> 3) & 7;
12797 rm = (insn >> 6) & 7;
12798 op = (insn >> 9) & 7;
12799 addr = load_reg(s, rn);
12800 tmp = load_reg(s, rm);
12801 tcg_gen_add_i32(addr, addr, tmp);
12802 tcg_temp_free_i32(tmp);
12804 if (op < 3) { /* store */
12805 tmp = load_reg(s, rd);
12806 } else {
12807 tmp = tcg_temp_new_i32();
12810 switch (op) {
12811 case 0: /* str */
12812 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12813 break;
12814 case 1: /* strh */
12815 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12816 break;
12817 case 2: /* strb */
12818 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12819 break;
12820 case 3: /* ldrsb */
12821 gen_aa32_ld8s_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12822 break;
12823 case 4: /* ldr */
12824 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12825 break;
12826 case 5: /* ldrh */
12827 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12828 break;
12829 case 6: /* ldrb */
12830 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12831 break;
12832 case 7: /* ldrsh */
12833 gen_aa32_ld16s_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12834 break;
12836 if (op >= 3) { /* load */
12837 store_reg(s, rd, tmp);
12838 } else {
12839 tcg_temp_free_i32(tmp);
12841 tcg_temp_free_i32(addr);
12842 break;
12844 case 6:
12845 /* load/store word immediate offset */
12846 rd = insn & 7;
12847 rn = (insn >> 3) & 7;
12848 addr = load_reg(s, rn);
12849 val = (insn >> 4) & 0x7c;
12850 tcg_gen_addi_i32(addr, addr, val);
12852 if (insn & (1 << 11)) {
12853 /* load */
12854 tmp = tcg_temp_new_i32();
12855 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
12856 store_reg(s, rd, tmp);
12857 } else {
12858 /* store */
12859 tmp = load_reg(s, rd);
12860 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
12861 tcg_temp_free_i32(tmp);
12863 tcg_temp_free_i32(addr);
12864 break;
12866 case 7:
12867 /* load/store byte immediate offset */
12868 rd = insn & 7;
12869 rn = (insn >> 3) & 7;
12870 addr = load_reg(s, rn);
12871 val = (insn >> 6) & 0x1f;
12872 tcg_gen_addi_i32(addr, addr, val);
12874 if (insn & (1 << 11)) {
12875 /* load */
12876 tmp = tcg_temp_new_i32();
12877 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12878 store_reg(s, rd, tmp);
12879 } else {
12880 /* store */
12881 tmp = load_reg(s, rd);
12882 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12883 tcg_temp_free_i32(tmp);
12885 tcg_temp_free_i32(addr);
12886 break;
12888 case 8:
12889 /* load/store halfword immediate offset */
12890 rd = insn & 7;
12891 rn = (insn >> 3) & 7;
12892 addr = load_reg(s, rn);
12893 val = (insn >> 5) & 0x3e;
12894 tcg_gen_addi_i32(addr, addr, val);
12896 if (insn & (1 << 11)) {
12897 /* load */
12898 tmp = tcg_temp_new_i32();
12899 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12900 store_reg(s, rd, tmp);
12901 } else {
12902 /* store */
12903 tmp = load_reg(s, rd);
12904 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12905 tcg_temp_free_i32(tmp);
12907 tcg_temp_free_i32(addr);
12908 break;
12910 case 9:
12911 /* load/store from stack */
12912 rd = (insn >> 8) & 7;
12913 addr = load_reg(s, 13);
12914 val = (insn & 0xff) * 4;
12915 tcg_gen_addi_i32(addr, addr, val);
12917 if (insn & (1 << 11)) {
12918 /* load */
12919 tmp = tcg_temp_new_i32();
12920 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12921 store_reg(s, rd, tmp);
12922 } else {
12923 /* store */
12924 tmp = load_reg(s, rd);
12925 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12926 tcg_temp_free_i32(tmp);
12928 tcg_temp_free_i32(addr);
12929 break;
12931 case 10:
12933 * 0b1010_xxxx_xxxx_xxxx
12934 * - Add PC/SP (immediate)
12936 rd = (insn >> 8) & 7;
12937 if (insn & (1 << 11)) {
12938 /* SP */
12939 tmp = load_reg(s, 13);
12940 } else {
12941 /* PC. bit 1 is ignored. */
12942 tmp = tcg_temp_new_i32();
12943 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
12945 val = (insn & 0xff) * 4;
12946 tcg_gen_addi_i32(tmp, tmp, val);
12947 store_reg(s, rd, tmp);
12948 break;
12950 case 11:
12951 /* misc */
12952 op = (insn >> 8) & 0xf;
12953 switch (op) {
12954 case 0:
12956 * 0b1011_0000_xxxx_xxxx
12957 * - ADD (SP plus immediate)
12958 * - SUB (SP minus immediate)
12960 tmp = load_reg(s, 13);
12961 val = (insn & 0x7f) * 4;
12962 if (insn & (1 << 7))
12963 val = -(int32_t)val;
12964 tcg_gen_addi_i32(tmp, tmp, val);
12965 store_sp_checked(s, tmp);
12966 break;
12968 case 2: /* sign/zero extend. */
12969 ARCH(6);
12970 rd = insn & 7;
12971 rm = (insn >> 3) & 7;
12972 tmp = load_reg(s, rm);
12973 switch ((insn >> 6) & 3) {
12974 case 0: gen_sxth(tmp); break;
12975 case 1: gen_sxtb(tmp); break;
12976 case 2: gen_uxth(tmp); break;
12977 case 3: gen_uxtb(tmp); break;
12979 store_reg(s, rd, tmp);
12980 break;
12981 case 4: case 5: case 0xc: case 0xd:
12983 * 0b1011_x10x_xxxx_xxxx
12984 * - push/pop
12986 addr = load_reg(s, 13);
12987 if (insn & (1 << 8))
12988 offset = 4;
12989 else
12990 offset = 0;
12991 for (i = 0; i < 8; i++) {
12992 if (insn & (1 << i))
12993 offset += 4;
12995 if ((insn & (1 << 11)) == 0) {
12996 tcg_gen_addi_i32(addr, addr, -offset);
12999 if (s->v8m_stackcheck) {
13001 * Here 'addr' is the lower of "old SP" and "new SP";
13002 * if this is a pop that starts below the limit and ends
13003 * above it, it is UNKNOWN whether the limit check triggers;
13004 * we choose to trigger.
13006 gen_helper_v8m_stackcheck(cpu_env, addr);
13009 for (i = 0; i < 8; i++) {
13010 if (insn & (1 << i)) {
13011 if (insn & (1 << 11)) {
13012 /* pop */
13013 tmp = tcg_temp_new_i32();
13014 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
13015 store_reg(s, i, tmp);
13016 } else {
13017 /* push */
13018 tmp = load_reg(s, i);
13019 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
13020 tcg_temp_free_i32(tmp);
13022 /* advance to the next address. */
13023 tcg_gen_addi_i32(addr, addr, 4);
13026 tmp = NULL;
13027 if (insn & (1 << 8)) {
13028 if (insn & (1 << 11)) {
13029 /* pop pc */
13030 tmp = tcg_temp_new_i32();
13031 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
13032 /* don't set the pc until the rest of the instruction
13033 has completed */
13034 } else {
13035 /* push lr */
13036 tmp = load_reg(s, 14);
13037 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
13038 tcg_temp_free_i32(tmp);
13040 tcg_gen_addi_i32(addr, addr, 4);
13042 if ((insn & (1 << 11)) == 0) {
13043 tcg_gen_addi_i32(addr, addr, -offset);
13045 /* write back the new stack pointer */
13046 store_reg(s, 13, addr);
13047 /* set the new PC value */
13048 if ((insn & 0x0900) == 0x0900) {
13049 store_reg_from_load(s, 15, tmp);
13051 break;
13053 case 1: case 3: case 9: case 11: /* czb */
13054 rm = insn & 7;
13055 tmp = load_reg(s, rm);
13056 arm_gen_condlabel(s);
13057 if (insn & (1 << 11))
13058 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
13059 else
13060 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
13061 tcg_temp_free_i32(tmp);
13062 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
13063 val = (uint32_t)s->pc + 2;
13064 val += offset;
13065 gen_jmp(s, val);
13066 break;
13068 case 15: /* IT, nop-hint. */
13069 if ((insn & 0xf) == 0) {
13070 gen_nop_hint(s, (insn >> 4) & 0xf);
13071 break;
13073 /* If Then. */
13074 s->condexec_cond = (insn >> 4) & 0xe;
13075 s->condexec_mask = insn & 0x1f;
13076 /* No actual code generated for this insn, just setup state. */
13077 break;
13079 case 0xe: /* bkpt */
13081 int imm8 = extract32(insn, 0, 8);
13082 ARCH(5);
13083 gen_exception_bkpt_insn(s, 2, syn_aa32_bkpt(imm8, true));
13084 break;
13087 case 0xa: /* rev, and hlt */
13089 int op1 = extract32(insn, 6, 2);
13091 if (op1 == 2) {
13092 /* HLT */
13093 int imm6 = extract32(insn, 0, 6);
13095 gen_hlt(s, imm6);
13096 break;
13099 /* Otherwise this is rev */
13100 ARCH(6);
13101 rn = (insn >> 3) & 0x7;
13102 rd = insn & 0x7;
13103 tmp = load_reg(s, rn);
13104 switch (op1) {
13105 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
13106 case 1: gen_rev16(tmp); break;
13107 case 3: gen_revsh(tmp); break;
13108 default:
13109 g_assert_not_reached();
13111 store_reg(s, rd, tmp);
13112 break;
13115 case 6:
13116 switch ((insn >> 5) & 7) {
13117 case 2:
13118 /* setend */
13119 ARCH(6);
13120 if (((insn >> 3) & 1) != !!(s->be_data == MO_BE)) {
13121 gen_helper_setend(cpu_env);
13122 s->base.is_jmp = DISAS_UPDATE;
13124 break;
13125 case 3:
13126 /* cps */
13127 ARCH(6);
13128 if (IS_USER(s)) {
13129 break;
13131 if (arm_dc_feature(s, ARM_FEATURE_M)) {
13132 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
13133 /* FAULTMASK */
13134 if (insn & 1) {
13135 addr = tcg_const_i32(19);
13136 gen_helper_v7m_msr(cpu_env, addr, tmp);
13137 tcg_temp_free_i32(addr);
13139 /* PRIMASK */
13140 if (insn & 2) {
13141 addr = tcg_const_i32(16);
13142 gen_helper_v7m_msr(cpu_env, addr, tmp);
13143 tcg_temp_free_i32(addr);
13145 tcg_temp_free_i32(tmp);
13146 gen_lookup_tb(s);
13147 } else {
13148 if (insn & (1 << 4)) {
13149 shift = CPSR_A | CPSR_I | CPSR_F;
13150 } else {
13151 shift = 0;
13153 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
13155 break;
13156 default:
13157 goto undef;
13159 break;
13161 default:
13162 goto undef;
13164 break;
13166 case 12:
13168 /* load/store multiple */
13169 TCGv_i32 loaded_var = NULL;
13170 rn = (insn >> 8) & 0x7;
13171 addr = load_reg(s, rn);
13172 for (i = 0; i < 8; i++) {
13173 if (insn & (1 << i)) {
13174 if (insn & (1 << 11)) {
13175 /* load */
13176 tmp = tcg_temp_new_i32();
13177 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
13178 if (i == rn) {
13179 loaded_var = tmp;
13180 } else {
13181 store_reg(s, i, tmp);
13183 } else {
13184 /* store */
13185 tmp = load_reg(s, i);
13186 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
13187 tcg_temp_free_i32(tmp);
13189 /* advance to the next address */
13190 tcg_gen_addi_i32(addr, addr, 4);
13193 if ((insn & (1 << rn)) == 0) {
13194 /* base reg not in list: base register writeback */
13195 store_reg(s, rn, addr);
13196 } else {
13197 /* base reg in list: if load, complete it now */
13198 if (insn & (1 << 11)) {
13199 store_reg(s, rn, loaded_var);
13201 tcg_temp_free_i32(addr);
13203 break;
13205 case 13:
13206 /* conditional branch or swi */
13207 cond = (insn >> 8) & 0xf;
13208 if (cond == 0xe)
13209 goto undef;
13211 if (cond == 0xf) {
13212 /* swi */
13213 gen_set_pc_im(s, s->pc);
13214 s->svc_imm = extract32(insn, 0, 8);
13215 s->base.is_jmp = DISAS_SWI;
13216 break;
13218 /* generate a conditional jump to next instruction */
13219 arm_skip_unless(s, cond);
13221 /* jump to the offset */
13222 val = (uint32_t)s->pc + 2;
13223 offset = ((int32_t)insn << 24) >> 24;
13224 val += offset << 1;
13225 gen_jmp(s, val);
13226 break;
13228 case 14:
13229 if (insn & (1 << 11)) {
13230 /* thumb_insn_is_16bit() ensures we can't get here for
13231 * a Thumb2 CPU, so this must be a thumb1 split BL/BLX:
13232 * 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF)
13234 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
13235 ARCH(5);
13236 offset = ((insn & 0x7ff) << 1);
13237 tmp = load_reg(s, 14);
13238 tcg_gen_addi_i32(tmp, tmp, offset);
13239 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
13241 tmp2 = tcg_temp_new_i32();
13242 tcg_gen_movi_i32(tmp2, s->pc | 1);
13243 store_reg(s, 14, tmp2);
13244 gen_bx(s, tmp);
13245 break;
13247 /* unconditional branch */
13248 val = (uint32_t)s->pc;
13249 offset = ((int32_t)insn << 21) >> 21;
13250 val += (offset << 1) + 2;
13251 gen_jmp(s, val);
13252 break;
13254 case 15:
13255 /* thumb_insn_is_16bit() ensures we can't get here for
13256 * a Thumb2 CPU, so this must be a thumb1 split BL/BLX.
13258 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
13260 if (insn & (1 << 11)) {
13261 /* 0b1111_1xxx_xxxx_xxxx : BL suffix */
13262 offset = ((insn & 0x7ff) << 1) | 1;
13263 tmp = load_reg(s, 14);
13264 tcg_gen_addi_i32(tmp, tmp, offset);
13266 tmp2 = tcg_temp_new_i32();
13267 tcg_gen_movi_i32(tmp2, s->pc | 1);
13268 store_reg(s, 14, tmp2);
13269 gen_bx(s, tmp);
13270 } else {
13271 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix */
13272 uint32_t uoffset = ((int32_t)insn << 21) >> 9;
13274 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + uoffset);
13276 break;
13278 return;
13279 illegal_op:
13280 undef:
13281 gen_exception_insn(s, 2, EXCP_UDEF, syn_uncategorized(),
13282 default_exception_el(s));
13285 static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
13287 /* Return true if the insn at dc->pc might cross a page boundary.
13288 * (False positives are OK, false negatives are not.)
13289 * We know this is a Thumb insn, and our caller ensures we are
13290 * only called if dc->pc is less than 4 bytes from the page
13291 * boundary, so we cross the page if the first 16 bits indicate
13292 * that this is a 32 bit insn.
13294 uint16_t insn = arm_lduw_code(env, s->pc, s->sctlr_b);
13296 return !thumb_insn_is_16bit(s, insn);
13299 static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
13301 DisasContext *dc = container_of(dcbase, DisasContext, base);
13302 CPUARMState *env = cs->env_ptr;
13303 ARMCPU *cpu = arm_env_get_cpu(env);
13304 uint32_t tb_flags = dc->base.tb->flags;
13305 uint32_t condexec, core_mmu_idx;
13307 dc->isar = &cpu->isar;
13308 dc->pc = dc->base.pc_first;
13309 dc->condjmp = 0;
13311 dc->aarch64 = 0;
13312 /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
13313 * there is no secure EL1, so we route exceptions to EL3.
13315 dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
13316 !arm_el_is_aa64(env, 3);
13317 dc->thumb = FIELD_EX32(tb_flags, TBFLAG_A32, THUMB);
13318 dc->sctlr_b = FIELD_EX32(tb_flags, TBFLAG_A32, SCTLR_B);
13319 dc->be_data = FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
13320 condexec = FIELD_EX32(tb_flags, TBFLAG_A32, CONDEXEC);
13321 dc->condexec_mask = (condexec & 0xf) << 1;
13322 dc->condexec_cond = condexec >> 4;
13323 core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX);
13324 dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
13325 dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
13326 #if !defined(CONFIG_USER_ONLY)
13327 dc->user = (dc->current_el == 0);
13328 #endif
13329 dc->ns = FIELD_EX32(tb_flags, TBFLAG_A32, NS);
13330 dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL);
13331 dc->vfp_enabled = FIELD_EX32(tb_flags, TBFLAG_A32, VFPEN);
13332 dc->vec_len = FIELD_EX32(tb_flags, TBFLAG_A32, VECLEN);
13333 dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
13334 dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
13335 dc->v7m_handler_mode = FIELD_EX32(tb_flags, TBFLAG_A32, HANDLER);
13336 dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
13337 regime_is_secure(env, dc->mmu_idx);
13338 dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_A32, STACKCHECK);
13339 dc->cp_regs = cpu->cp_regs;
13340 dc->features = env->features;
13342 /* Single step state. The code-generation logic here is:
13343 * SS_ACTIVE == 0:
13344 * generate code with no special handling for single-stepping (except
13345 * that anything that can make us go to SS_ACTIVE == 1 must end the TB;
13346 * this happens anyway because those changes are all system register or
13347 * PSTATE writes).
13348 * SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
13349 * emit code for one insn
13350 * emit code to clear PSTATE.SS
13351 * emit code to generate software step exception for completed step
13352 * end TB (as usual for having generated an exception)
13353 * SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
13354 * emit code to generate a software step exception
13355 * end the TB
13357 dc->ss_active = FIELD_EX32(tb_flags, TBFLAG_ANY, SS_ACTIVE);
13358 dc->pstate_ss = FIELD_EX32(tb_flags, TBFLAG_ANY, PSTATE_SS);
13359 dc->is_ldex = false;
13360 dc->ss_same_el = false; /* Can't be true since EL_d must be AArch64 */
13362 dc->page_start = dc->base.pc_first & TARGET_PAGE_MASK;
13364 /* If architectural single step active, limit to 1. */
13365 if (is_singlestepping(dc)) {
13366 dc->base.max_insns = 1;
13369 /* ARM is a fixed-length ISA. Bound the number of insns to execute
13370 to those left on the page. */
13371 if (!dc->thumb) {
13372 int bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
13373 dc->base.max_insns = MIN(dc->base.max_insns, bound);
13376 cpu_F0s = tcg_temp_new_i32();
13377 cpu_F1s = tcg_temp_new_i32();
13378 cpu_F0d = tcg_temp_new_i64();
13379 cpu_F1d = tcg_temp_new_i64();
13380 cpu_V0 = cpu_F0d;
13381 cpu_V1 = cpu_F1d;
13382 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
13383 cpu_M0 = tcg_temp_new_i64();
13386 static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
13388 DisasContext *dc = container_of(dcbase, DisasContext, base);
13390 /* A note on handling of the condexec (IT) bits:
13392 * We want to avoid the overhead of having to write the updated condexec
13393 * bits back to the CPUARMState for every instruction in an IT block. So:
13394 * (1) if the condexec bits are not already zero then we write
13395 * zero back into the CPUARMState now. This avoids complications trying
13396 * to do it at the end of the block. (For example if we don't do this
13397 * it's hard to identify whether we can safely skip writing condexec
13398 * at the end of the TB, which we definitely want to do for the case
13399 * where a TB doesn't do anything with the IT state at all.)
13400 * (2) if we are going to leave the TB then we call gen_set_condexec()
13401 * which will write the correct value into CPUARMState if zero is wrong.
13402 * This is done both for leaving the TB at the end, and for leaving
13403 * it because of an exception we know will happen, which is done in
13404 * gen_exception_insn(). The latter is necessary because we need to
13405 * leave the TB with the PC/IT state just prior to execution of the
13406 * instruction which caused the exception.
13407 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
13408 * then the CPUARMState will be wrong and we need to reset it.
13409 * This is handled in the same way as restoration of the
13410 * PC in these situations; we save the value of the condexec bits
13411 * for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
13412 * then uses this to restore them after an exception.
13414 * Note that there are no instructions which can read the condexec
13415 * bits, and none which can write non-static values to them, so
13416 * we don't need to care about whether CPUARMState is correct in the
13417 * middle of a TB.
13420 /* Reset the conditional execution bits immediately. This avoids
13421 complications trying to do it at the end of the block. */
13422 if (dc->condexec_mask || dc->condexec_cond) {
13423 TCGv_i32 tmp = tcg_temp_new_i32();
13424 tcg_gen_movi_i32(tmp, 0);
13425 store_cpu_field(tmp, condexec_bits);
13429 static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
13431 DisasContext *dc = container_of(dcbase, DisasContext, base);
13433 tcg_gen_insn_start(dc->pc,
13434 (dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
13436 dc->insn_start = tcg_last_op();
13439 static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
13440 const CPUBreakpoint *bp)
13442 DisasContext *dc = container_of(dcbase, DisasContext, base);
13444 if (bp->flags & BP_CPU) {
13445 gen_set_condexec(dc);
13446 gen_set_pc_im(dc, dc->pc);
13447 gen_helper_check_breakpoints(cpu_env);
13448 /* End the TB early; it's likely not going to be executed */
13449 dc->base.is_jmp = DISAS_TOO_MANY;
13450 } else {
13451 gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
13452 /* The address covered by the breakpoint must be
13453 included in [tb->pc, tb->pc + tb->size) in order
13454 to for it to be properly cleared -- thus we
13455 increment the PC here so that the logic setting
13456 tb->size below does the right thing. */
13457 /* TODO: Advance PC by correct instruction length to
13458 * avoid disassembler error messages */
13459 dc->pc += 2;
13460 dc->base.is_jmp = DISAS_NORETURN;
13463 return true;
13466 static bool arm_pre_translate_insn(DisasContext *dc)
13468 #ifdef CONFIG_USER_ONLY
13469 /* Intercept jump to the magic kernel page. */
13470 if (dc->pc >= 0xffff0000) {
13471 /* We always get here via a jump, so know we are not in a
13472 conditional execution block. */
13473 gen_exception_internal(EXCP_KERNEL_TRAP);
13474 dc->base.is_jmp = DISAS_NORETURN;
13475 return true;
13477 #endif
13479 if (dc->ss_active && !dc->pstate_ss) {
13480 /* Singlestep state is Active-pending.
13481 * If we're in this state at the start of a TB then either
13482 * a) we just took an exception to an EL which is being debugged
13483 * and this is the first insn in the exception handler
13484 * b) debug exceptions were masked and we just unmasked them
13485 * without changing EL (eg by clearing PSTATE.D)
13486 * In either case we're going to take a swstep exception in the
13487 * "did not step an insn" case, and so the syndrome ISV and EX
13488 * bits should be zero.
13490 assert(dc->base.num_insns == 1);
13491 gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
13492 default_exception_el(dc));
13493 dc->base.is_jmp = DISAS_NORETURN;
13494 return true;
13497 return false;
13500 static void arm_post_translate_insn(DisasContext *dc)
13502 if (dc->condjmp && !dc->base.is_jmp) {
13503 gen_set_label(dc->condlabel);
13504 dc->condjmp = 0;
13506 dc->base.pc_next = dc->pc;
13507 translator_loop_temp_check(&dc->base);
13510 static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
13512 DisasContext *dc = container_of(dcbase, DisasContext, base);
13513 CPUARMState *env = cpu->env_ptr;
13514 unsigned int insn;
13516 if (arm_pre_translate_insn(dc)) {
13517 return;
13520 insn = arm_ldl_code(env, dc->pc, dc->sctlr_b);
13521 dc->insn = insn;
13522 dc->pc += 4;
13523 disas_arm_insn(dc, insn);
13525 arm_post_translate_insn(dc);
13527 /* ARM is a fixed-length ISA. We performed the cross-page check
13528 in init_disas_context by adjusting max_insns. */
13531 static bool thumb_insn_is_unconditional(DisasContext *s, uint32_t insn)
13533 /* Return true if this Thumb insn is always unconditional,
13534 * even inside an IT block. This is true of only a very few
13535 * instructions: BKPT, HLT, and SG.
13537 * A larger class of instructions are UNPREDICTABLE if used
13538 * inside an IT block; we do not need to detect those here, because
13539 * what we do by default (perform the cc check and update the IT
13540 * bits state machine) is a permitted CONSTRAINED UNPREDICTABLE
13541 * choice for those situations.
13543 * insn is either a 16-bit or a 32-bit instruction; the two are
13544 * distinguishable because for the 16-bit case the top 16 bits
13545 * are zeroes, and that isn't a valid 32-bit encoding.
13547 if ((insn & 0xffffff00) == 0xbe00) {
13548 /* BKPT */
13549 return true;
13552 if ((insn & 0xffffffc0) == 0xba80 && arm_dc_feature(s, ARM_FEATURE_V8) &&
13553 !arm_dc_feature(s, ARM_FEATURE_M)) {
13554 /* HLT: v8A only. This is unconditional even when it is going to
13555 * UNDEF; see the v8A ARM ARM DDI0487B.a H3.3.
13556 * For v7 cores this was a plain old undefined encoding and so
13557 * honours its cc check. (We might be using the encoding as
13558 * a semihosting trap, but we don't change the cc check behaviour
13559 * on that account, because a debugger connected to a real v7A
13560 * core and emulating semihosting traps by catching the UNDEF
13561 * exception would also only see cases where the cc check passed.
13562 * No guest code should be trying to do a HLT semihosting trap
13563 * in an IT block anyway.
13565 return true;
13568 if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_V8) &&
13569 arm_dc_feature(s, ARM_FEATURE_M)) {
13570 /* SG: v8M only */
13571 return true;
13574 return false;
13577 static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
13579 DisasContext *dc = container_of(dcbase, DisasContext, base);
13580 CPUARMState *env = cpu->env_ptr;
13581 uint32_t insn;
13582 bool is_16bit;
13584 if (arm_pre_translate_insn(dc)) {
13585 return;
13588 insn = arm_lduw_code(env, dc->pc, dc->sctlr_b);
13589 is_16bit = thumb_insn_is_16bit(dc, insn);
13590 dc->pc += 2;
13591 if (!is_16bit) {
13592 uint32_t insn2 = arm_lduw_code(env, dc->pc, dc->sctlr_b);
13594 insn = insn << 16 | insn2;
13595 dc->pc += 2;
13597 dc->insn = insn;
13599 if (dc->condexec_mask && !thumb_insn_is_unconditional(dc, insn)) {
13600 uint32_t cond = dc->condexec_cond;
13602 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
13603 arm_skip_unless(dc, cond);
13607 if (is_16bit) {
13608 disas_thumb_insn(dc, insn);
13609 } else {
13610 disas_thumb2_insn(dc, insn);
13613 /* Advance the Thumb condexec condition. */
13614 if (dc->condexec_mask) {
13615 dc->condexec_cond = ((dc->condexec_cond & 0xe) |
13616 ((dc->condexec_mask >> 4) & 1));
13617 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
13618 if (dc->condexec_mask == 0) {
13619 dc->condexec_cond = 0;
13623 arm_post_translate_insn(dc);
13625 /* Thumb is a variable-length ISA. Stop translation when the next insn
13626 * will touch a new page. This ensures that prefetch aborts occur at
13627 * the right place.
13629 * We want to stop the TB if the next insn starts in a new page,
13630 * or if it spans between this page and the next. This means that
13631 * if we're looking at the last halfword in the page we need to
13632 * see if it's a 16-bit Thumb insn (which will fit in this TB)
13633 * or a 32-bit Thumb insn (which won't).
13634 * This is to avoid generating a silly TB with a single 16-bit insn
13635 * in it at the end of this page (which would execute correctly
13636 * but isn't very efficient).
13638 if (dc->base.is_jmp == DISAS_NEXT
13639 && (dc->pc - dc->page_start >= TARGET_PAGE_SIZE
13640 || (dc->pc - dc->page_start >= TARGET_PAGE_SIZE - 3
13641 && insn_crosses_page(env, dc)))) {
13642 dc->base.is_jmp = DISAS_TOO_MANY;
13646 static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
13648 DisasContext *dc = container_of(dcbase, DisasContext, base);
13650 if (tb_cflags(dc->base.tb) & CF_LAST_IO && dc->condjmp) {
13651 /* FIXME: This can theoretically happen with self-modifying code. */
13652 cpu_abort(cpu, "IO on conditional branch instruction");
13655 /* At this stage dc->condjmp will only be set when the skipped
13656 instruction was a conditional branch or trap, and the PC has
13657 already been written. */
13658 gen_set_condexec(dc);
13659 if (dc->base.is_jmp == DISAS_BX_EXCRET) {
13660 /* Exception return branches need some special case code at the
13661 * end of the TB, which is complex enough that it has to
13662 * handle the single-step vs not and the condition-failed
13663 * insn codepath itself.
13665 gen_bx_excret_final_code(dc);
13666 } else if (unlikely(is_singlestepping(dc))) {
13667 /* Unconditional and "condition passed" instruction codepath. */
13668 switch (dc->base.is_jmp) {
13669 case DISAS_SWI:
13670 gen_ss_advance(dc);
13671 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
13672 default_exception_el(dc));
13673 break;
13674 case DISAS_HVC:
13675 gen_ss_advance(dc);
13676 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
13677 break;
13678 case DISAS_SMC:
13679 gen_ss_advance(dc);
13680 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
13681 break;
13682 case DISAS_NEXT:
13683 case DISAS_TOO_MANY:
13684 case DISAS_UPDATE:
13685 gen_set_pc_im(dc, dc->pc);
13686 /* fall through */
13687 default:
13688 /* FIXME: Single stepping a WFI insn will not halt the CPU. */
13689 gen_singlestep_exception(dc);
13690 break;
13691 case DISAS_NORETURN:
13692 break;
13694 } else {
13695 /* While branches must always occur at the end of an IT block,
13696 there are a few other things that can cause us to terminate
13697 the TB in the middle of an IT block:
13698 - Exception generating instructions (bkpt, swi, undefined).
13699 - Page boundaries.
13700 - Hardware watchpoints.
13701 Hardware breakpoints have already been handled and skip this code.
13703 switch(dc->base.is_jmp) {
13704 case DISAS_NEXT:
13705 case DISAS_TOO_MANY:
13706 gen_goto_tb(dc, 1, dc->pc);
13707 break;
13708 case DISAS_JUMP:
13709 gen_goto_ptr();
13710 break;
13711 case DISAS_UPDATE:
13712 gen_set_pc_im(dc, dc->pc);
13713 /* fall through */
13714 default:
13715 /* indicate that the hash table must be used to find the next TB */
13716 tcg_gen_exit_tb(NULL, 0);
13717 break;
13718 case DISAS_NORETURN:
13719 /* nothing more to generate */
13720 break;
13721 case DISAS_WFI:
13723 TCGv_i32 tmp = tcg_const_i32((dc->thumb &&
13724 !(dc->insn & (1U << 31))) ? 2 : 4);
13726 gen_helper_wfi(cpu_env, tmp);
13727 tcg_temp_free_i32(tmp);
13728 /* The helper doesn't necessarily throw an exception, but we
13729 * must go back to the main loop to check for interrupts anyway.
13731 tcg_gen_exit_tb(NULL, 0);
13732 break;
13734 case DISAS_WFE:
13735 gen_helper_wfe(cpu_env);
13736 break;
13737 case DISAS_YIELD:
13738 gen_helper_yield(cpu_env);
13739 break;
13740 case DISAS_SWI:
13741 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
13742 default_exception_el(dc));
13743 break;
13744 case DISAS_HVC:
13745 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
13746 break;
13747 case DISAS_SMC:
13748 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
13749 break;
13753 if (dc->condjmp) {
13754 /* "Condition failed" instruction codepath for the branch/trap insn */
13755 gen_set_label(dc->condlabel);
13756 gen_set_condexec(dc);
13757 if (unlikely(is_singlestepping(dc))) {
13758 gen_set_pc_im(dc, dc->pc);
13759 gen_singlestep_exception(dc);
13760 } else {
13761 gen_goto_tb(dc, 1, dc->pc);
13765 /* Functions above can change dc->pc, so re-align db->pc_next */
13766 dc->base.pc_next = dc->pc;
13769 static void arm_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
13771 DisasContext *dc = container_of(dcbase, DisasContext, base);
13773 qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
13774 log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
13777 static const TranslatorOps arm_translator_ops = {
13778 .init_disas_context = arm_tr_init_disas_context,
13779 .tb_start = arm_tr_tb_start,
13780 .insn_start = arm_tr_insn_start,
13781 .breakpoint_check = arm_tr_breakpoint_check,
13782 .translate_insn = arm_tr_translate_insn,
13783 .tb_stop = arm_tr_tb_stop,
13784 .disas_log = arm_tr_disas_log,
13787 static const TranslatorOps thumb_translator_ops = {
13788 .init_disas_context = arm_tr_init_disas_context,
13789 .tb_start = arm_tr_tb_start,
13790 .insn_start = arm_tr_insn_start,
13791 .breakpoint_check = arm_tr_breakpoint_check,
13792 .translate_insn = thumb_tr_translate_insn,
13793 .tb_stop = arm_tr_tb_stop,
13794 .disas_log = arm_tr_disas_log,
13797 /* generate intermediate code for basic block 'tb'. */
13798 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
13800 DisasContext dc;
13801 const TranslatorOps *ops = &arm_translator_ops;
13803 if (FIELD_EX32(tb->flags, TBFLAG_A32, THUMB)) {
13804 ops = &thumb_translator_ops;
13806 #ifdef TARGET_AARCH64
13807 if (FIELD_EX32(tb->flags, TBFLAG_ANY, AARCH64_STATE)) {
13808 ops = &aarch64_translator_ops;
13810 #endif
13812 translator_loop(ops, &dc.base, cpu, tb, max_insns);
13815 void arm_cpu_dump_state(CPUState *cs, FILE *f, int flags)
13817 ARMCPU *cpu = ARM_CPU(cs);
13818 CPUARMState *env = &cpu->env;
13819 int i;
13821 if (is_a64(env)) {
13822 aarch64_cpu_dump_state(cs, f, flags);
13823 return;
13826 for(i=0;i<16;i++) {
13827 qemu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
13828 if ((i % 4) == 3)
13829 qemu_fprintf(f, "\n");
13830 else
13831 qemu_fprintf(f, " ");
13834 if (arm_feature(env, ARM_FEATURE_M)) {
13835 uint32_t xpsr = xpsr_read(env);
13836 const char *mode;
13837 const char *ns_status = "";
13839 if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
13840 ns_status = env->v7m.secure ? "S " : "NS ";
13843 if (xpsr & XPSR_EXCP) {
13844 mode = "handler";
13845 } else {
13846 if (env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_NPRIV_MASK) {
13847 mode = "unpriv-thread";
13848 } else {
13849 mode = "priv-thread";
13853 qemu_fprintf(f, "XPSR=%08x %c%c%c%c %c %s%s\n",
13854 xpsr,
13855 xpsr & XPSR_N ? 'N' : '-',
13856 xpsr & XPSR_Z ? 'Z' : '-',
13857 xpsr & XPSR_C ? 'C' : '-',
13858 xpsr & XPSR_V ? 'V' : '-',
13859 xpsr & XPSR_T ? 'T' : 'A',
13860 ns_status,
13861 mode);
13862 } else {
13863 uint32_t psr = cpsr_read(env);
13864 const char *ns_status = "";
13866 if (arm_feature(env, ARM_FEATURE_EL3) &&
13867 (psr & CPSR_M) != ARM_CPU_MODE_MON) {
13868 ns_status = env->cp15.scr_el3 & SCR_NS ? "NS " : "S ";
13871 qemu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%s%d\n",
13872 psr,
13873 psr & CPSR_N ? 'N' : '-',
13874 psr & CPSR_Z ? 'Z' : '-',
13875 psr & CPSR_C ? 'C' : '-',
13876 psr & CPSR_V ? 'V' : '-',
13877 psr & CPSR_T ? 'T' : 'A',
13878 ns_status,
13879 aarch32_mode_name(psr), (psr & 0x10) ? 32 : 26);
13882 if (flags & CPU_DUMP_FPU) {
13883 int numvfpregs = 0;
13884 if (arm_feature(env, ARM_FEATURE_VFP)) {
13885 numvfpregs += 16;
13887 if (arm_feature(env, ARM_FEATURE_VFP3)) {
13888 numvfpregs += 16;
13890 for (i = 0; i < numvfpregs; i++) {
13891 uint64_t v = *aa32_vfp_dreg(env, i);
13892 qemu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
13893 i * 2, (uint32_t)v,
13894 i * 2 + 1, (uint32_t)(v >> 32),
13895 i, v);
13897 qemu_fprintf(f, "FPSCR: %08x\n", vfp_get_fpscr(env));
13901 void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
13902 target_ulong *data)
13904 if (is_a64(env)) {
13905 env->pc = data[0];
13906 env->condexec_bits = 0;
13907 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
13908 } else {
13909 env->regs[15] = data[0];
13910 env->condexec_bits = data[1];
13911 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;