target/arm: Remove VLDR/VSTR/VLDM/VSTM use of cpu_F0s and cpu_F0d
[qemu/ar7.git] / target / arm / translate.c
blob4a462fe09443bf1e7684a4a48c52714f741d8974
1 /*
2 * ARM translation
4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2005-2007 CodeSourcery
6 * Copyright (c) 2007 OpenedHand, Ltd.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include "qemu/osdep.h"
23 #include "cpu.h"
24 #include "internals.h"
25 #include "disas/disas.h"
26 #include "exec/exec-all.h"
27 #include "tcg-op.h"
28 #include "tcg-op-gvec.h"
29 #include "qemu/log.h"
30 #include "qemu/bitops.h"
31 #include "qemu/qemu-print.h"
32 #include "arm_ldst.h"
33 #include "hw/semihosting/semihost.h"
35 #include "exec/helper-proto.h"
36 #include "exec/helper-gen.h"
38 #include "trace-tcg.h"
39 #include "exec/log.h"
42 #define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T)
43 #define ENABLE_ARCH_5 arm_dc_feature(s, ARM_FEATURE_V5)
44 /* currently all emulated v5 cores are also v5TE, so don't bother */
45 #define ENABLE_ARCH_5TE arm_dc_feature(s, ARM_FEATURE_V5)
46 #define ENABLE_ARCH_5J dc_isar_feature(jazelle, s)
47 #define ENABLE_ARCH_6 arm_dc_feature(s, ARM_FEATURE_V6)
48 #define ENABLE_ARCH_6K arm_dc_feature(s, ARM_FEATURE_V6K)
49 #define ENABLE_ARCH_6T2 arm_dc_feature(s, ARM_FEATURE_THUMB2)
50 #define ENABLE_ARCH_7 arm_dc_feature(s, ARM_FEATURE_V7)
51 #define ENABLE_ARCH_8 arm_dc_feature(s, ARM_FEATURE_V8)
53 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
55 #include "translate.h"
57 #if defined(CONFIG_USER_ONLY)
58 #define IS_USER(s) 1
59 #else
60 #define IS_USER(s) (s->user)
61 #endif
63 /* We reuse the same 64-bit temporaries for efficiency. */
64 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
65 static TCGv_i32 cpu_R[16];
66 TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
67 TCGv_i64 cpu_exclusive_addr;
68 TCGv_i64 cpu_exclusive_val;
70 /* FIXME: These should be removed. */
71 static TCGv_i32 cpu_F0s, cpu_F1s;
72 static TCGv_i64 cpu_F0d, cpu_F1d;
74 #include "exec/gen-icount.h"
76 static const char * const regnames[] =
77 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
78 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
80 /* Function prototypes for gen_ functions calling Neon helpers. */
81 typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32,
82 TCGv_i32, TCGv_i32);
84 /* initialize TCG globals. */
85 void arm_translate_init(void)
87 int i;
89 for (i = 0; i < 16; i++) {
90 cpu_R[i] = tcg_global_mem_new_i32(cpu_env,
91 offsetof(CPUARMState, regs[i]),
92 regnames[i]);
94 cpu_CF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, CF), "CF");
95 cpu_NF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, NF), "NF");
96 cpu_VF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, VF), "VF");
97 cpu_ZF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, ZF), "ZF");
99 cpu_exclusive_addr = tcg_global_mem_new_i64(cpu_env,
100 offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
101 cpu_exclusive_val = tcg_global_mem_new_i64(cpu_env,
102 offsetof(CPUARMState, exclusive_val), "exclusive_val");
104 a64_translate_init();
107 /* Flags for the disas_set_da_iss info argument:
108 * lower bits hold the Rt register number, higher bits are flags.
110 typedef enum ISSInfo {
111 ISSNone = 0,
112 ISSRegMask = 0x1f,
113 ISSInvalid = (1 << 5),
114 ISSIsAcqRel = (1 << 6),
115 ISSIsWrite = (1 << 7),
116 ISSIs16Bit = (1 << 8),
117 } ISSInfo;
119 /* Save the syndrome information for a Data Abort */
120 static void disas_set_da_iss(DisasContext *s, TCGMemOp memop, ISSInfo issinfo)
122 uint32_t syn;
123 int sas = memop & MO_SIZE;
124 bool sse = memop & MO_SIGN;
125 bool is_acqrel = issinfo & ISSIsAcqRel;
126 bool is_write = issinfo & ISSIsWrite;
127 bool is_16bit = issinfo & ISSIs16Bit;
128 int srt = issinfo & ISSRegMask;
130 if (issinfo & ISSInvalid) {
131 /* Some callsites want to conditionally provide ISS info,
132 * eg "only if this was not a writeback"
134 return;
137 if (srt == 15) {
138 /* For AArch32, insns where the src/dest is R15 never generate
139 * ISS information. Catching that here saves checking at all
140 * the call sites.
142 return;
145 syn = syn_data_abort_with_iss(0, sas, sse, srt, 0, is_acqrel,
146 0, 0, 0, is_write, 0, is_16bit);
147 disas_set_insn_syndrome(s, syn);
150 static inline int get_a32_user_mem_index(DisasContext *s)
152 /* Return the core mmu_idx to use for A32/T32 "unprivileged load/store"
153 * insns:
154 * if PL2, UNPREDICTABLE (we choose to implement as if PL0)
155 * otherwise, access as if at PL0.
157 switch (s->mmu_idx) {
158 case ARMMMUIdx_S1E2: /* this one is UNPREDICTABLE */
159 case ARMMMUIdx_S12NSE0:
160 case ARMMMUIdx_S12NSE1:
161 return arm_to_core_mmu_idx(ARMMMUIdx_S12NSE0);
162 case ARMMMUIdx_S1E3:
163 case ARMMMUIdx_S1SE0:
164 case ARMMMUIdx_S1SE1:
165 return arm_to_core_mmu_idx(ARMMMUIdx_S1SE0);
166 case ARMMMUIdx_MUser:
167 case ARMMMUIdx_MPriv:
168 return arm_to_core_mmu_idx(ARMMMUIdx_MUser);
169 case ARMMMUIdx_MUserNegPri:
170 case ARMMMUIdx_MPrivNegPri:
171 return arm_to_core_mmu_idx(ARMMMUIdx_MUserNegPri);
172 case ARMMMUIdx_MSUser:
173 case ARMMMUIdx_MSPriv:
174 return arm_to_core_mmu_idx(ARMMMUIdx_MSUser);
175 case ARMMMUIdx_MSUserNegPri:
176 case ARMMMUIdx_MSPrivNegPri:
177 return arm_to_core_mmu_idx(ARMMMUIdx_MSUserNegPri);
178 case ARMMMUIdx_S2NS:
179 default:
180 g_assert_not_reached();
184 static inline TCGv_i32 load_cpu_offset(int offset)
186 TCGv_i32 tmp = tcg_temp_new_i32();
187 tcg_gen_ld_i32(tmp, cpu_env, offset);
188 return tmp;
191 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
193 static inline void store_cpu_offset(TCGv_i32 var, int offset)
195 tcg_gen_st_i32(var, cpu_env, offset);
196 tcg_temp_free_i32(var);
199 #define store_cpu_field(var, name) \
200 store_cpu_offset(var, offsetof(CPUARMState, name))
202 /* Set a variable to the value of a CPU register. */
203 static void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
205 if (reg == 15) {
206 uint32_t addr;
207 /* normally, since we updated PC, we need only to add one insn */
208 if (s->thumb)
209 addr = (long)s->pc + 2;
210 else
211 addr = (long)s->pc + 4;
212 tcg_gen_movi_i32(var, addr);
213 } else {
214 tcg_gen_mov_i32(var, cpu_R[reg]);
218 /* Create a new temporary and set it to the value of a CPU register. */
219 static inline TCGv_i32 load_reg(DisasContext *s, int reg)
221 TCGv_i32 tmp = tcg_temp_new_i32();
222 load_reg_var(s, tmp, reg);
223 return tmp;
226 /* Set a CPU register. The source must be a temporary and will be
227 marked as dead. */
228 static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
230 if (reg == 15) {
231 /* In Thumb mode, we must ignore bit 0.
232 * In ARM mode, for ARMv4 and ARMv5, it is UNPREDICTABLE if bits [1:0]
233 * are not 0b00, but for ARMv6 and above, we must ignore bits [1:0].
234 * We choose to ignore [1:0] in ARM mode for all architecture versions.
236 tcg_gen_andi_i32(var, var, s->thumb ? ~1 : ~3);
237 s->base.is_jmp = DISAS_JUMP;
239 tcg_gen_mov_i32(cpu_R[reg], var);
240 tcg_temp_free_i32(var);
244 * Variant of store_reg which applies v8M stack-limit checks before updating
245 * SP. If the check fails this will result in an exception being taken.
246 * We disable the stack checks for CONFIG_USER_ONLY because we have
247 * no idea what the stack limits should be in that case.
248 * If stack checking is not being done this just acts like store_reg().
250 static void store_sp_checked(DisasContext *s, TCGv_i32 var)
252 #ifndef CONFIG_USER_ONLY
253 if (s->v8m_stackcheck) {
254 gen_helper_v8m_stackcheck(cpu_env, var);
256 #endif
257 store_reg(s, 13, var);
260 /* Value extensions. */
261 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
262 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
263 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
264 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
266 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
267 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
270 static inline void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
272 TCGv_i32 tmp_mask = tcg_const_i32(mask);
273 gen_helper_cpsr_write(cpu_env, var, tmp_mask);
274 tcg_temp_free_i32(tmp_mask);
276 /* Set NZCV flags from the high 4 bits of var. */
277 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
279 static void gen_exception_internal(int excp)
281 TCGv_i32 tcg_excp = tcg_const_i32(excp);
283 assert(excp_is_internal(excp));
284 gen_helper_exception_internal(cpu_env, tcg_excp);
285 tcg_temp_free_i32(tcg_excp);
288 static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el)
290 TCGv_i32 tcg_excp = tcg_const_i32(excp);
291 TCGv_i32 tcg_syn = tcg_const_i32(syndrome);
292 TCGv_i32 tcg_el = tcg_const_i32(target_el);
294 gen_helper_exception_with_syndrome(cpu_env, tcg_excp,
295 tcg_syn, tcg_el);
297 tcg_temp_free_i32(tcg_el);
298 tcg_temp_free_i32(tcg_syn);
299 tcg_temp_free_i32(tcg_excp);
302 static void gen_step_complete_exception(DisasContext *s)
304 /* We just completed step of an insn. Move from Active-not-pending
305 * to Active-pending, and then also take the swstep exception.
306 * This corresponds to making the (IMPDEF) choice to prioritize
307 * swstep exceptions over asynchronous exceptions taken to an exception
308 * level where debug is disabled. This choice has the advantage that
309 * we do not need to maintain internal state corresponding to the
310 * ISV/EX syndrome bits between completion of the step and generation
311 * of the exception, and our syndrome information is always correct.
313 gen_ss_advance(s);
314 gen_exception(EXCP_UDEF, syn_swstep(s->ss_same_el, 1, s->is_ldex),
315 default_exception_el(s));
316 s->base.is_jmp = DISAS_NORETURN;
319 static void gen_singlestep_exception(DisasContext *s)
321 /* Generate the right kind of exception for singlestep, which is
322 * either the architectural singlestep or EXCP_DEBUG for QEMU's
323 * gdb singlestepping.
325 if (s->ss_active) {
326 gen_step_complete_exception(s);
327 } else {
328 gen_exception_internal(EXCP_DEBUG);
332 static inline bool is_singlestepping(DisasContext *s)
334 /* Return true if we are singlestepping either because of
335 * architectural singlestep or QEMU gdbstub singlestep. This does
336 * not include the command line '-singlestep' mode which is rather
337 * misnamed as it only means "one instruction per TB" and doesn't
338 * affect the code we generate.
340 return s->base.singlestep_enabled || s->ss_active;
343 static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
345 TCGv_i32 tmp1 = tcg_temp_new_i32();
346 TCGv_i32 tmp2 = tcg_temp_new_i32();
347 tcg_gen_ext16s_i32(tmp1, a);
348 tcg_gen_ext16s_i32(tmp2, b);
349 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
350 tcg_temp_free_i32(tmp2);
351 tcg_gen_sari_i32(a, a, 16);
352 tcg_gen_sari_i32(b, b, 16);
353 tcg_gen_mul_i32(b, b, a);
354 tcg_gen_mov_i32(a, tmp1);
355 tcg_temp_free_i32(tmp1);
358 /* Byteswap each halfword. */
359 static void gen_rev16(TCGv_i32 var)
361 TCGv_i32 tmp = tcg_temp_new_i32();
362 TCGv_i32 mask = tcg_const_i32(0x00ff00ff);
363 tcg_gen_shri_i32(tmp, var, 8);
364 tcg_gen_and_i32(tmp, tmp, mask);
365 tcg_gen_and_i32(var, var, mask);
366 tcg_gen_shli_i32(var, var, 8);
367 tcg_gen_or_i32(var, var, tmp);
368 tcg_temp_free_i32(mask);
369 tcg_temp_free_i32(tmp);
372 /* Byteswap low halfword and sign extend. */
373 static void gen_revsh(TCGv_i32 var)
375 tcg_gen_ext16u_i32(var, var);
376 tcg_gen_bswap16_i32(var, var);
377 tcg_gen_ext16s_i32(var, var);
380 /* Return (b << 32) + a. Mark inputs as dead */
381 static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv_i32 b)
383 TCGv_i64 tmp64 = tcg_temp_new_i64();
385 tcg_gen_extu_i32_i64(tmp64, b);
386 tcg_temp_free_i32(b);
387 tcg_gen_shli_i64(tmp64, tmp64, 32);
388 tcg_gen_add_i64(a, tmp64, a);
390 tcg_temp_free_i64(tmp64);
391 return a;
394 /* Return (b << 32) - a. Mark inputs as dead. */
395 static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv_i32 b)
397 TCGv_i64 tmp64 = tcg_temp_new_i64();
399 tcg_gen_extu_i32_i64(tmp64, b);
400 tcg_temp_free_i32(b);
401 tcg_gen_shli_i64(tmp64, tmp64, 32);
402 tcg_gen_sub_i64(a, tmp64, a);
404 tcg_temp_free_i64(tmp64);
405 return a;
408 /* 32x32->64 multiply. Marks inputs as dead. */
409 static TCGv_i64 gen_mulu_i64_i32(TCGv_i32 a, TCGv_i32 b)
411 TCGv_i32 lo = tcg_temp_new_i32();
412 TCGv_i32 hi = tcg_temp_new_i32();
413 TCGv_i64 ret;
415 tcg_gen_mulu2_i32(lo, hi, a, b);
416 tcg_temp_free_i32(a);
417 tcg_temp_free_i32(b);
419 ret = tcg_temp_new_i64();
420 tcg_gen_concat_i32_i64(ret, lo, hi);
421 tcg_temp_free_i32(lo);
422 tcg_temp_free_i32(hi);
424 return ret;
427 static TCGv_i64 gen_muls_i64_i32(TCGv_i32 a, TCGv_i32 b)
429 TCGv_i32 lo = tcg_temp_new_i32();
430 TCGv_i32 hi = tcg_temp_new_i32();
431 TCGv_i64 ret;
433 tcg_gen_muls2_i32(lo, hi, a, b);
434 tcg_temp_free_i32(a);
435 tcg_temp_free_i32(b);
437 ret = tcg_temp_new_i64();
438 tcg_gen_concat_i32_i64(ret, lo, hi);
439 tcg_temp_free_i32(lo);
440 tcg_temp_free_i32(hi);
442 return ret;
445 /* Swap low and high halfwords. */
446 static void gen_swap_half(TCGv_i32 var)
448 TCGv_i32 tmp = tcg_temp_new_i32();
449 tcg_gen_shri_i32(tmp, var, 16);
450 tcg_gen_shli_i32(var, var, 16);
451 tcg_gen_or_i32(var, var, tmp);
452 tcg_temp_free_i32(tmp);
455 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
456 tmp = (t0 ^ t1) & 0x8000;
457 t0 &= ~0x8000;
458 t1 &= ~0x8000;
459 t0 = (t0 + t1) ^ tmp;
462 static void gen_add16(TCGv_i32 t0, TCGv_i32 t1)
464 TCGv_i32 tmp = tcg_temp_new_i32();
465 tcg_gen_xor_i32(tmp, t0, t1);
466 tcg_gen_andi_i32(tmp, tmp, 0x8000);
467 tcg_gen_andi_i32(t0, t0, ~0x8000);
468 tcg_gen_andi_i32(t1, t1, ~0x8000);
469 tcg_gen_add_i32(t0, t0, t1);
470 tcg_gen_xor_i32(t0, t0, tmp);
471 tcg_temp_free_i32(tmp);
472 tcg_temp_free_i32(t1);
475 /* Set CF to the top bit of var. */
476 static void gen_set_CF_bit31(TCGv_i32 var)
478 tcg_gen_shri_i32(cpu_CF, var, 31);
481 /* Set N and Z flags from var. */
482 static inline void gen_logic_CC(TCGv_i32 var)
484 tcg_gen_mov_i32(cpu_NF, var);
485 tcg_gen_mov_i32(cpu_ZF, var);
488 /* T0 += T1 + CF. */
489 static void gen_adc(TCGv_i32 t0, TCGv_i32 t1)
491 tcg_gen_add_i32(t0, t0, t1);
492 tcg_gen_add_i32(t0, t0, cpu_CF);
495 /* dest = T0 + T1 + CF. */
496 static void gen_add_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
498 tcg_gen_add_i32(dest, t0, t1);
499 tcg_gen_add_i32(dest, dest, cpu_CF);
502 /* dest = T0 - T1 + CF - 1. */
503 static void gen_sub_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
505 tcg_gen_sub_i32(dest, t0, t1);
506 tcg_gen_add_i32(dest, dest, cpu_CF);
507 tcg_gen_subi_i32(dest, dest, 1);
510 /* dest = T0 + T1. Compute C, N, V and Z flags */
511 static void gen_add_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
513 TCGv_i32 tmp = tcg_temp_new_i32();
514 tcg_gen_movi_i32(tmp, 0);
515 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, t1, tmp);
516 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
517 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
518 tcg_gen_xor_i32(tmp, t0, t1);
519 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
520 tcg_temp_free_i32(tmp);
521 tcg_gen_mov_i32(dest, cpu_NF);
524 /* dest = T0 + T1 + CF. Compute C, N, V and Z flags */
525 static void gen_adc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
527 TCGv_i32 tmp = tcg_temp_new_i32();
528 if (TCG_TARGET_HAS_add2_i32) {
529 tcg_gen_movi_i32(tmp, 0);
530 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp);
531 tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1, tmp);
532 } else {
533 TCGv_i64 q0 = tcg_temp_new_i64();
534 TCGv_i64 q1 = tcg_temp_new_i64();
535 tcg_gen_extu_i32_i64(q0, t0);
536 tcg_gen_extu_i32_i64(q1, t1);
537 tcg_gen_add_i64(q0, q0, q1);
538 tcg_gen_extu_i32_i64(q1, cpu_CF);
539 tcg_gen_add_i64(q0, q0, q1);
540 tcg_gen_extr_i64_i32(cpu_NF, cpu_CF, q0);
541 tcg_temp_free_i64(q0);
542 tcg_temp_free_i64(q1);
544 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
545 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
546 tcg_gen_xor_i32(tmp, t0, t1);
547 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
548 tcg_temp_free_i32(tmp);
549 tcg_gen_mov_i32(dest, cpu_NF);
552 /* dest = T0 - T1. Compute C, N, V and Z flags */
553 static void gen_sub_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
555 TCGv_i32 tmp;
556 tcg_gen_sub_i32(cpu_NF, t0, t1);
557 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
558 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0, t1);
559 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
560 tmp = tcg_temp_new_i32();
561 tcg_gen_xor_i32(tmp, t0, t1);
562 tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
563 tcg_temp_free_i32(tmp);
564 tcg_gen_mov_i32(dest, cpu_NF);
567 /* dest = T0 + ~T1 + CF. Compute C, N, V and Z flags */
568 static void gen_sbc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
570 TCGv_i32 tmp = tcg_temp_new_i32();
571 tcg_gen_not_i32(tmp, t1);
572 gen_adc_CC(dest, t0, tmp);
573 tcg_temp_free_i32(tmp);
576 #define GEN_SHIFT(name) \
577 static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \
579 TCGv_i32 tmp1, tmp2, tmp3; \
580 tmp1 = tcg_temp_new_i32(); \
581 tcg_gen_andi_i32(tmp1, t1, 0xff); \
582 tmp2 = tcg_const_i32(0); \
583 tmp3 = tcg_const_i32(0x1f); \
584 tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
585 tcg_temp_free_i32(tmp3); \
586 tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
587 tcg_gen_##name##_i32(dest, tmp2, tmp1); \
588 tcg_temp_free_i32(tmp2); \
589 tcg_temp_free_i32(tmp1); \
591 GEN_SHIFT(shl)
592 GEN_SHIFT(shr)
593 #undef GEN_SHIFT
595 static void gen_sar(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
597 TCGv_i32 tmp1, tmp2;
598 tmp1 = tcg_temp_new_i32();
599 tcg_gen_andi_i32(tmp1, t1, 0xff);
600 tmp2 = tcg_const_i32(0x1f);
601 tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1);
602 tcg_temp_free_i32(tmp2);
603 tcg_gen_sar_i32(dest, t0, tmp1);
604 tcg_temp_free_i32(tmp1);
607 static void shifter_out_im(TCGv_i32 var, int shift)
609 if (shift == 0) {
610 tcg_gen_andi_i32(cpu_CF, var, 1);
611 } else {
612 tcg_gen_shri_i32(cpu_CF, var, shift);
613 if (shift != 31) {
614 tcg_gen_andi_i32(cpu_CF, cpu_CF, 1);
619 /* Shift by immediate. Includes special handling for shift == 0. */
620 static inline void gen_arm_shift_im(TCGv_i32 var, int shiftop,
621 int shift, int flags)
623 switch (shiftop) {
624 case 0: /* LSL */
625 if (shift != 0) {
626 if (flags)
627 shifter_out_im(var, 32 - shift);
628 tcg_gen_shli_i32(var, var, shift);
630 break;
631 case 1: /* LSR */
632 if (shift == 0) {
633 if (flags) {
634 tcg_gen_shri_i32(cpu_CF, var, 31);
636 tcg_gen_movi_i32(var, 0);
637 } else {
638 if (flags)
639 shifter_out_im(var, shift - 1);
640 tcg_gen_shri_i32(var, var, shift);
642 break;
643 case 2: /* ASR */
644 if (shift == 0)
645 shift = 32;
646 if (flags)
647 shifter_out_im(var, shift - 1);
648 if (shift == 32)
649 shift = 31;
650 tcg_gen_sari_i32(var, var, shift);
651 break;
652 case 3: /* ROR/RRX */
653 if (shift != 0) {
654 if (flags)
655 shifter_out_im(var, shift - 1);
656 tcg_gen_rotri_i32(var, var, shift); break;
657 } else {
658 TCGv_i32 tmp = tcg_temp_new_i32();
659 tcg_gen_shli_i32(tmp, cpu_CF, 31);
660 if (flags)
661 shifter_out_im(var, 0);
662 tcg_gen_shri_i32(var, var, 1);
663 tcg_gen_or_i32(var, var, tmp);
664 tcg_temp_free_i32(tmp);
669 static inline void gen_arm_shift_reg(TCGv_i32 var, int shiftop,
670 TCGv_i32 shift, int flags)
672 if (flags) {
673 switch (shiftop) {
674 case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break;
675 case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break;
676 case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break;
677 case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break;
679 } else {
680 switch (shiftop) {
681 case 0:
682 gen_shl(var, var, shift);
683 break;
684 case 1:
685 gen_shr(var, var, shift);
686 break;
687 case 2:
688 gen_sar(var, var, shift);
689 break;
690 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
691 tcg_gen_rotr_i32(var, var, shift); break;
694 tcg_temp_free_i32(shift);
697 #define PAS_OP(pfx) \
698 switch (op2) { \
699 case 0: gen_pas_helper(glue(pfx,add16)); break; \
700 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
701 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
702 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
703 case 4: gen_pas_helper(glue(pfx,add8)); break; \
704 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
706 static void gen_arm_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
708 TCGv_ptr tmp;
710 switch (op1) {
711 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
712 case 1:
713 tmp = tcg_temp_new_ptr();
714 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
715 PAS_OP(s)
716 tcg_temp_free_ptr(tmp);
717 break;
718 case 5:
719 tmp = tcg_temp_new_ptr();
720 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
721 PAS_OP(u)
722 tcg_temp_free_ptr(tmp);
723 break;
724 #undef gen_pas_helper
725 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
726 case 2:
727 PAS_OP(q);
728 break;
729 case 3:
730 PAS_OP(sh);
731 break;
732 case 6:
733 PAS_OP(uq);
734 break;
735 case 7:
736 PAS_OP(uh);
737 break;
738 #undef gen_pas_helper
741 #undef PAS_OP
743 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
744 #define PAS_OP(pfx) \
745 switch (op1) { \
746 case 0: gen_pas_helper(glue(pfx,add8)); break; \
747 case 1: gen_pas_helper(glue(pfx,add16)); break; \
748 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
749 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
750 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
751 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
753 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
755 TCGv_ptr tmp;
757 switch (op2) {
758 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
759 case 0:
760 tmp = tcg_temp_new_ptr();
761 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
762 PAS_OP(s)
763 tcg_temp_free_ptr(tmp);
764 break;
765 case 4:
766 tmp = tcg_temp_new_ptr();
767 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
768 PAS_OP(u)
769 tcg_temp_free_ptr(tmp);
770 break;
771 #undef gen_pas_helper
772 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
773 case 1:
774 PAS_OP(q);
775 break;
776 case 2:
777 PAS_OP(sh);
778 break;
779 case 5:
780 PAS_OP(uq);
781 break;
782 case 6:
783 PAS_OP(uh);
784 break;
785 #undef gen_pas_helper
788 #undef PAS_OP
791 * Generate a conditional based on ARM condition code cc.
792 * This is common between ARM and Aarch64 targets.
794 void arm_test_cc(DisasCompare *cmp, int cc)
796 TCGv_i32 value;
797 TCGCond cond;
798 bool global = true;
800 switch (cc) {
801 case 0: /* eq: Z */
802 case 1: /* ne: !Z */
803 cond = TCG_COND_EQ;
804 value = cpu_ZF;
805 break;
807 case 2: /* cs: C */
808 case 3: /* cc: !C */
809 cond = TCG_COND_NE;
810 value = cpu_CF;
811 break;
813 case 4: /* mi: N */
814 case 5: /* pl: !N */
815 cond = TCG_COND_LT;
816 value = cpu_NF;
817 break;
819 case 6: /* vs: V */
820 case 7: /* vc: !V */
821 cond = TCG_COND_LT;
822 value = cpu_VF;
823 break;
825 case 8: /* hi: C && !Z */
826 case 9: /* ls: !C || Z -> !(C && !Z) */
827 cond = TCG_COND_NE;
828 value = tcg_temp_new_i32();
829 global = false;
830 /* CF is 1 for C, so -CF is an all-bits-set mask for C;
831 ZF is non-zero for !Z; so AND the two subexpressions. */
832 tcg_gen_neg_i32(value, cpu_CF);
833 tcg_gen_and_i32(value, value, cpu_ZF);
834 break;
836 case 10: /* ge: N == V -> N ^ V == 0 */
837 case 11: /* lt: N != V -> N ^ V != 0 */
838 /* Since we're only interested in the sign bit, == 0 is >= 0. */
839 cond = TCG_COND_GE;
840 value = tcg_temp_new_i32();
841 global = false;
842 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
843 break;
845 case 12: /* gt: !Z && N == V */
846 case 13: /* le: Z || N != V */
847 cond = TCG_COND_NE;
848 value = tcg_temp_new_i32();
849 global = false;
850 /* (N == V) is equal to the sign bit of ~(NF ^ VF). Propagate
851 * the sign bit then AND with ZF to yield the result. */
852 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
853 tcg_gen_sari_i32(value, value, 31);
854 tcg_gen_andc_i32(value, cpu_ZF, value);
855 break;
857 case 14: /* always */
858 case 15: /* always */
859 /* Use the ALWAYS condition, which will fold early.
860 * It doesn't matter what we use for the value. */
861 cond = TCG_COND_ALWAYS;
862 value = cpu_ZF;
863 goto no_invert;
865 default:
866 fprintf(stderr, "Bad condition code 0x%x\n", cc);
867 abort();
870 if (cc & 1) {
871 cond = tcg_invert_cond(cond);
874 no_invert:
875 cmp->cond = cond;
876 cmp->value = value;
877 cmp->value_global = global;
880 void arm_free_cc(DisasCompare *cmp)
882 if (!cmp->value_global) {
883 tcg_temp_free_i32(cmp->value);
887 void arm_jump_cc(DisasCompare *cmp, TCGLabel *label)
889 tcg_gen_brcondi_i32(cmp->cond, cmp->value, 0, label);
892 void arm_gen_test_cc(int cc, TCGLabel *label)
894 DisasCompare cmp;
895 arm_test_cc(&cmp, cc);
896 arm_jump_cc(&cmp, label);
897 arm_free_cc(&cmp);
900 static const uint8_t table_logic_cc[16] = {
901 1, /* and */
902 1, /* xor */
903 0, /* sub */
904 0, /* rsb */
905 0, /* add */
906 0, /* adc */
907 0, /* sbc */
908 0, /* rsc */
909 1, /* andl */
910 1, /* xorl */
911 0, /* cmp */
912 0, /* cmn */
913 1, /* orr */
914 1, /* mov */
915 1, /* bic */
916 1, /* mvn */
919 static inline void gen_set_condexec(DisasContext *s)
921 if (s->condexec_mask) {
922 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
923 TCGv_i32 tmp = tcg_temp_new_i32();
924 tcg_gen_movi_i32(tmp, val);
925 store_cpu_field(tmp, condexec_bits);
929 static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
931 tcg_gen_movi_i32(cpu_R[15], val);
934 /* Set PC and Thumb state from an immediate address. */
935 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
937 TCGv_i32 tmp;
939 s->base.is_jmp = DISAS_JUMP;
940 if (s->thumb != (addr & 1)) {
941 tmp = tcg_temp_new_i32();
942 tcg_gen_movi_i32(tmp, addr & 1);
943 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, thumb));
944 tcg_temp_free_i32(tmp);
946 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
949 /* Set PC and Thumb state from var. var is marked as dead. */
950 static inline void gen_bx(DisasContext *s, TCGv_i32 var)
952 s->base.is_jmp = DISAS_JUMP;
953 tcg_gen_andi_i32(cpu_R[15], var, ~1);
954 tcg_gen_andi_i32(var, var, 1);
955 store_cpu_field(var, thumb);
958 /* Set PC and Thumb state from var. var is marked as dead.
959 * For M-profile CPUs, include logic to detect exception-return
960 * branches and handle them. This is needed for Thumb POP/LDM to PC, LDR to PC,
961 * and BX reg, and no others, and happens only for code in Handler mode.
963 static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var)
965 /* Generate the same code here as for a simple bx, but flag via
966 * s->base.is_jmp that we need to do the rest of the work later.
968 gen_bx(s, var);
969 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY) ||
970 (s->v7m_handler_mode && arm_dc_feature(s, ARM_FEATURE_M))) {
971 s->base.is_jmp = DISAS_BX_EXCRET;
975 static inline void gen_bx_excret_final_code(DisasContext *s)
977 /* Generate the code to finish possible exception return and end the TB */
978 TCGLabel *excret_label = gen_new_label();
979 uint32_t min_magic;
981 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY)) {
982 /* Covers FNC_RETURN and EXC_RETURN magic */
983 min_magic = FNC_RETURN_MIN_MAGIC;
984 } else {
985 /* EXC_RETURN magic only */
986 min_magic = EXC_RETURN_MIN_MAGIC;
989 /* Is the new PC value in the magic range indicating exception return? */
990 tcg_gen_brcondi_i32(TCG_COND_GEU, cpu_R[15], min_magic, excret_label);
991 /* No: end the TB as we would for a DISAS_JMP */
992 if (is_singlestepping(s)) {
993 gen_singlestep_exception(s);
994 } else {
995 tcg_gen_exit_tb(NULL, 0);
997 gen_set_label(excret_label);
998 /* Yes: this is an exception return.
999 * At this point in runtime env->regs[15] and env->thumb will hold
1000 * the exception-return magic number, which do_v7m_exception_exit()
1001 * will read. Nothing else will be able to see those values because
1002 * the cpu-exec main loop guarantees that we will always go straight
1003 * from raising the exception to the exception-handling code.
1005 * gen_ss_advance(s) does nothing on M profile currently but
1006 * calling it is conceptually the right thing as we have executed
1007 * this instruction (compare SWI, HVC, SMC handling).
1009 gen_ss_advance(s);
1010 gen_exception_internal(EXCP_EXCEPTION_EXIT);
1013 static inline void gen_bxns(DisasContext *s, int rm)
1015 TCGv_i32 var = load_reg(s, rm);
1017 /* The bxns helper may raise an EXCEPTION_EXIT exception, so in theory
1018 * we need to sync state before calling it, but:
1019 * - we don't need to do gen_set_pc_im() because the bxns helper will
1020 * always set the PC itself
1021 * - we don't need to do gen_set_condexec() because BXNS is UNPREDICTABLE
1022 * unless it's outside an IT block or the last insn in an IT block,
1023 * so we know that condexec == 0 (already set at the top of the TB)
1024 * is correct in the non-UNPREDICTABLE cases, and we can choose
1025 * "zeroes the IT bits" as our UNPREDICTABLE behaviour otherwise.
1027 gen_helper_v7m_bxns(cpu_env, var);
1028 tcg_temp_free_i32(var);
1029 s->base.is_jmp = DISAS_EXIT;
1032 static inline void gen_blxns(DisasContext *s, int rm)
1034 TCGv_i32 var = load_reg(s, rm);
1036 /* We don't need to sync condexec state, for the same reason as bxns.
1037 * We do however need to set the PC, because the blxns helper reads it.
1038 * The blxns helper may throw an exception.
1040 gen_set_pc_im(s, s->pc);
1041 gen_helper_v7m_blxns(cpu_env, var);
1042 tcg_temp_free_i32(var);
1043 s->base.is_jmp = DISAS_EXIT;
1046 /* Variant of store_reg which uses branch&exchange logic when storing
1047 to r15 in ARM architecture v7 and above. The source must be a temporary
1048 and will be marked as dead. */
1049 static inline void store_reg_bx(DisasContext *s, int reg, TCGv_i32 var)
1051 if (reg == 15 && ENABLE_ARCH_7) {
1052 gen_bx(s, var);
1053 } else {
1054 store_reg(s, reg, var);
1058 /* Variant of store_reg which uses branch&exchange logic when storing
1059 * to r15 in ARM architecture v5T and above. This is used for storing
1060 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
1061 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
1062 static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
1064 if (reg == 15 && ENABLE_ARCH_5) {
1065 gen_bx_excret(s, var);
1066 } else {
1067 store_reg(s, reg, var);
1071 #ifdef CONFIG_USER_ONLY
1072 #define IS_USER_ONLY 1
1073 #else
1074 #define IS_USER_ONLY 0
1075 #endif
1077 /* Abstractions of "generate code to do a guest load/store for
1078 * AArch32", where a vaddr is always 32 bits (and is zero
1079 * extended if we're a 64 bit core) and data is also
1080 * 32 bits unless specifically doing a 64 bit access.
1081 * These functions work like tcg_gen_qemu_{ld,st}* except
1082 * that the address argument is TCGv_i32 rather than TCGv.
1085 static inline TCGv gen_aa32_addr(DisasContext *s, TCGv_i32 a32, TCGMemOp op)
1087 TCGv addr = tcg_temp_new();
1088 tcg_gen_extu_i32_tl(addr, a32);
1090 /* Not needed for user-mode BE32, where we use MO_BE instead. */
1091 if (!IS_USER_ONLY && s->sctlr_b && (op & MO_SIZE) < MO_32) {
1092 tcg_gen_xori_tl(addr, addr, 4 - (1 << (op & MO_SIZE)));
1094 return addr;
1097 static void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
1098 int index, TCGMemOp opc)
1100 TCGv addr;
1102 if (arm_dc_feature(s, ARM_FEATURE_M) &&
1103 !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
1104 opc |= MO_ALIGN;
1107 addr = gen_aa32_addr(s, a32, opc);
1108 tcg_gen_qemu_ld_i32(val, addr, index, opc);
1109 tcg_temp_free(addr);
1112 static void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
1113 int index, TCGMemOp opc)
1115 TCGv addr;
1117 if (arm_dc_feature(s, ARM_FEATURE_M) &&
1118 !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
1119 opc |= MO_ALIGN;
1122 addr = gen_aa32_addr(s, a32, opc);
1123 tcg_gen_qemu_st_i32(val, addr, index, opc);
1124 tcg_temp_free(addr);
1127 #define DO_GEN_LD(SUFF, OPC) \
1128 static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
1129 TCGv_i32 a32, int index) \
1131 gen_aa32_ld_i32(s, val, a32, index, OPC | s->be_data); \
1133 static inline void gen_aa32_ld##SUFF##_iss(DisasContext *s, \
1134 TCGv_i32 val, \
1135 TCGv_i32 a32, int index, \
1136 ISSInfo issinfo) \
1138 gen_aa32_ld##SUFF(s, val, a32, index); \
1139 disas_set_da_iss(s, OPC, issinfo); \
1142 #define DO_GEN_ST(SUFF, OPC) \
1143 static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
1144 TCGv_i32 a32, int index) \
1146 gen_aa32_st_i32(s, val, a32, index, OPC | s->be_data); \
1148 static inline void gen_aa32_st##SUFF##_iss(DisasContext *s, \
1149 TCGv_i32 val, \
1150 TCGv_i32 a32, int index, \
1151 ISSInfo issinfo) \
1153 gen_aa32_st##SUFF(s, val, a32, index); \
1154 disas_set_da_iss(s, OPC, issinfo | ISSIsWrite); \
1157 static inline void gen_aa32_frob64(DisasContext *s, TCGv_i64 val)
1159 /* Not needed for user-mode BE32, where we use MO_BE instead. */
1160 if (!IS_USER_ONLY && s->sctlr_b) {
1161 tcg_gen_rotri_i64(val, val, 32);
1165 static void gen_aa32_ld_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
1166 int index, TCGMemOp opc)
1168 TCGv addr = gen_aa32_addr(s, a32, opc);
1169 tcg_gen_qemu_ld_i64(val, addr, index, opc);
1170 gen_aa32_frob64(s, val);
1171 tcg_temp_free(addr);
1174 static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
1175 TCGv_i32 a32, int index)
1177 gen_aa32_ld_i64(s, val, a32, index, MO_Q | s->be_data);
1180 static void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
1181 int index, TCGMemOp opc)
1183 TCGv addr = gen_aa32_addr(s, a32, opc);
1185 /* Not needed for user-mode BE32, where we use MO_BE instead. */
1186 if (!IS_USER_ONLY && s->sctlr_b) {
1187 TCGv_i64 tmp = tcg_temp_new_i64();
1188 tcg_gen_rotri_i64(tmp, val, 32);
1189 tcg_gen_qemu_st_i64(tmp, addr, index, opc);
1190 tcg_temp_free_i64(tmp);
1191 } else {
1192 tcg_gen_qemu_st_i64(val, addr, index, opc);
1194 tcg_temp_free(addr);
1197 static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
1198 TCGv_i32 a32, int index)
1200 gen_aa32_st_i64(s, val, a32, index, MO_Q | s->be_data);
1203 DO_GEN_LD(8s, MO_SB)
1204 DO_GEN_LD(8u, MO_UB)
1205 DO_GEN_LD(16s, MO_SW)
1206 DO_GEN_LD(16u, MO_UW)
1207 DO_GEN_LD(32u, MO_UL)
1208 DO_GEN_ST(8, MO_UB)
1209 DO_GEN_ST(16, MO_UW)
1210 DO_GEN_ST(32, MO_UL)
1212 static inline void gen_hvc(DisasContext *s, int imm16)
1214 /* The pre HVC helper handles cases when HVC gets trapped
1215 * as an undefined insn by runtime configuration (ie before
1216 * the insn really executes).
1218 gen_set_pc_im(s, s->pc - 4);
1219 gen_helper_pre_hvc(cpu_env);
1220 /* Otherwise we will treat this as a real exception which
1221 * happens after execution of the insn. (The distinction matters
1222 * for the PC value reported to the exception handler and also
1223 * for single stepping.)
1225 s->svc_imm = imm16;
1226 gen_set_pc_im(s, s->pc);
1227 s->base.is_jmp = DISAS_HVC;
1230 static inline void gen_smc(DisasContext *s)
1232 /* As with HVC, we may take an exception either before or after
1233 * the insn executes.
1235 TCGv_i32 tmp;
1237 gen_set_pc_im(s, s->pc - 4);
1238 tmp = tcg_const_i32(syn_aa32_smc());
1239 gen_helper_pre_smc(cpu_env, tmp);
1240 tcg_temp_free_i32(tmp);
1241 gen_set_pc_im(s, s->pc);
1242 s->base.is_jmp = DISAS_SMC;
1245 static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
1247 gen_set_condexec(s);
1248 gen_set_pc_im(s, s->pc - offset);
1249 gen_exception_internal(excp);
1250 s->base.is_jmp = DISAS_NORETURN;
1253 static void gen_exception_insn(DisasContext *s, int offset, int excp,
1254 int syn, uint32_t target_el)
1256 gen_set_condexec(s);
1257 gen_set_pc_im(s, s->pc - offset);
1258 gen_exception(excp, syn, target_el);
1259 s->base.is_jmp = DISAS_NORETURN;
1262 static void gen_exception_bkpt_insn(DisasContext *s, int offset, uint32_t syn)
1264 TCGv_i32 tcg_syn;
1266 gen_set_condexec(s);
1267 gen_set_pc_im(s, s->pc - offset);
1268 tcg_syn = tcg_const_i32(syn);
1269 gen_helper_exception_bkpt_insn(cpu_env, tcg_syn);
1270 tcg_temp_free_i32(tcg_syn);
1271 s->base.is_jmp = DISAS_NORETURN;
1274 /* Force a TB lookup after an instruction that changes the CPU state. */
1275 static inline void gen_lookup_tb(DisasContext *s)
1277 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
1278 s->base.is_jmp = DISAS_EXIT;
1281 static inline void gen_hlt(DisasContext *s, int imm)
1283 /* HLT. This has two purposes.
1284 * Architecturally, it is an external halting debug instruction.
1285 * Since QEMU doesn't implement external debug, we treat this as
1286 * it is required for halting debug disabled: it will UNDEF.
1287 * Secondly, "HLT 0x3C" is a T32 semihosting trap instruction,
1288 * and "HLT 0xF000" is an A32 semihosting syscall. These traps
1289 * must trigger semihosting even for ARMv7 and earlier, where
1290 * HLT was an undefined encoding.
1291 * In system mode, we don't allow userspace access to
1292 * semihosting, to provide some semblance of security
1293 * (and for consistency with our 32-bit semihosting).
1295 if (semihosting_enabled() &&
1296 #ifndef CONFIG_USER_ONLY
1297 s->current_el != 0 &&
1298 #endif
1299 (imm == (s->thumb ? 0x3c : 0xf000))) {
1300 gen_exception_internal_insn(s, 0, EXCP_SEMIHOST);
1301 return;
1304 gen_exception_insn(s, s->thumb ? 2 : 4, EXCP_UDEF, syn_uncategorized(),
1305 default_exception_el(s));
1308 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
1309 TCGv_i32 var)
1311 int val, rm, shift, shiftop;
1312 TCGv_i32 offset;
1314 if (!(insn & (1 << 25))) {
1315 /* immediate */
1316 val = insn & 0xfff;
1317 if (!(insn & (1 << 23)))
1318 val = -val;
1319 if (val != 0)
1320 tcg_gen_addi_i32(var, var, val);
1321 } else {
1322 /* shift/register */
1323 rm = (insn) & 0xf;
1324 shift = (insn >> 7) & 0x1f;
1325 shiftop = (insn >> 5) & 3;
1326 offset = load_reg(s, rm);
1327 gen_arm_shift_im(offset, shiftop, shift, 0);
1328 if (!(insn & (1 << 23)))
1329 tcg_gen_sub_i32(var, var, offset);
1330 else
1331 tcg_gen_add_i32(var, var, offset);
1332 tcg_temp_free_i32(offset);
1336 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
1337 int extra, TCGv_i32 var)
1339 int val, rm;
1340 TCGv_i32 offset;
1342 if (insn & (1 << 22)) {
1343 /* immediate */
1344 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
1345 if (!(insn & (1 << 23)))
1346 val = -val;
1347 val += extra;
1348 if (val != 0)
1349 tcg_gen_addi_i32(var, var, val);
1350 } else {
1351 /* register */
1352 if (extra)
1353 tcg_gen_addi_i32(var, var, extra);
1354 rm = (insn) & 0xf;
1355 offset = load_reg(s, rm);
1356 if (!(insn & (1 << 23)))
1357 tcg_gen_sub_i32(var, var, offset);
1358 else
1359 tcg_gen_add_i32(var, var, offset);
1360 tcg_temp_free_i32(offset);
1364 static TCGv_ptr get_fpstatus_ptr(int neon)
1366 TCGv_ptr statusptr = tcg_temp_new_ptr();
1367 int offset;
1368 if (neon) {
1369 offset = offsetof(CPUARMState, vfp.standard_fp_status);
1370 } else {
1371 offset = offsetof(CPUARMState, vfp.fp_status);
1373 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
1374 return statusptr;
1377 #define VFP_OP2(name) \
1378 static inline void gen_vfp_##name(int dp) \
1380 TCGv_ptr fpst = get_fpstatus_ptr(0); \
1381 if (dp) { \
1382 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, fpst); \
1383 } else { \
1384 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, fpst); \
1386 tcg_temp_free_ptr(fpst); \
1389 VFP_OP2(add)
1390 VFP_OP2(sub)
1391 VFP_OP2(mul)
1392 VFP_OP2(div)
1394 #undef VFP_OP2
1396 static inline void gen_vfp_F1_mul(int dp)
1398 /* Like gen_vfp_mul() but put result in F1 */
1399 TCGv_ptr fpst = get_fpstatus_ptr(0);
1400 if (dp) {
1401 gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, fpst);
1402 } else {
1403 gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, fpst);
1405 tcg_temp_free_ptr(fpst);
1408 static inline void gen_vfp_F1_neg(int dp)
1410 /* Like gen_vfp_neg() but put result in F1 */
1411 if (dp) {
1412 gen_helper_vfp_negd(cpu_F1d, cpu_F0d);
1413 } else {
1414 gen_helper_vfp_negs(cpu_F1s, cpu_F0s);
1418 static inline void gen_vfp_abs(int dp)
1420 if (dp)
1421 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1422 else
1423 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1426 static inline void gen_vfp_neg(int dp)
1428 if (dp)
1429 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1430 else
1431 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1434 static inline void gen_vfp_sqrt(int dp)
1436 if (dp)
1437 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1438 else
1439 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1442 static inline void gen_vfp_cmp(int dp)
1444 if (dp)
1445 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1446 else
1447 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1450 static inline void gen_vfp_cmpe(int dp)
1452 if (dp)
1453 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1454 else
1455 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1458 static inline void gen_vfp_F1_ld0(int dp)
1460 if (dp)
1461 tcg_gen_movi_i64(cpu_F1d, 0);
1462 else
1463 tcg_gen_movi_i32(cpu_F1s, 0);
1466 #define VFP_GEN_ITOF(name) \
1467 static inline void gen_vfp_##name(int dp, int neon) \
1469 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1470 if (dp) { \
1471 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
1472 } else { \
1473 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1475 tcg_temp_free_ptr(statusptr); \
1478 VFP_GEN_ITOF(uito)
1479 VFP_GEN_ITOF(sito)
1480 #undef VFP_GEN_ITOF
1482 #define VFP_GEN_FTOI(name) \
1483 static inline void gen_vfp_##name(int dp, int neon) \
1485 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1486 if (dp) { \
1487 gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
1488 } else { \
1489 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1491 tcg_temp_free_ptr(statusptr); \
1494 VFP_GEN_FTOI(toui)
1495 VFP_GEN_FTOI(touiz)
1496 VFP_GEN_FTOI(tosi)
1497 VFP_GEN_FTOI(tosiz)
1498 #undef VFP_GEN_FTOI
1500 #define VFP_GEN_FIX(name, round) \
1501 static inline void gen_vfp_##name(int dp, int shift, int neon) \
1503 TCGv_i32 tmp_shift = tcg_const_i32(shift); \
1504 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1505 if (dp) { \
1506 gen_helper_vfp_##name##d##round(cpu_F0d, cpu_F0d, tmp_shift, \
1507 statusptr); \
1508 } else { \
1509 gen_helper_vfp_##name##s##round(cpu_F0s, cpu_F0s, tmp_shift, \
1510 statusptr); \
1512 tcg_temp_free_i32(tmp_shift); \
1513 tcg_temp_free_ptr(statusptr); \
1515 VFP_GEN_FIX(tosh, _round_to_zero)
1516 VFP_GEN_FIX(tosl, _round_to_zero)
1517 VFP_GEN_FIX(touh, _round_to_zero)
1518 VFP_GEN_FIX(toul, _round_to_zero)
1519 VFP_GEN_FIX(shto, )
1520 VFP_GEN_FIX(slto, )
1521 VFP_GEN_FIX(uhto, )
1522 VFP_GEN_FIX(ulto, )
1523 #undef VFP_GEN_FIX
1525 static inline long vfp_reg_offset(bool dp, unsigned reg)
1527 if (dp) {
1528 return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]);
1529 } else {
1530 long ofs = offsetof(CPUARMState, vfp.zregs[reg >> 2].d[(reg >> 1) & 1]);
1531 if (reg & 1) {
1532 ofs += offsetof(CPU_DoubleU, l.upper);
1533 } else {
1534 ofs += offsetof(CPU_DoubleU, l.lower);
1536 return ofs;
1540 /* Return the offset of a 32-bit piece of a NEON register.
1541 zero is the least significant end of the register. */
1542 static inline long
1543 neon_reg_offset (int reg, int n)
1545 int sreg;
1546 sreg = reg * 2 + n;
1547 return vfp_reg_offset(0, sreg);
1550 /* Return the offset of a 2**SIZE piece of a NEON register, at index ELE,
1551 * where 0 is the least significant end of the register.
1553 static inline long
1554 neon_element_offset(int reg, int element, TCGMemOp size)
1556 int element_size = 1 << size;
1557 int ofs = element * element_size;
1558 #ifdef HOST_WORDS_BIGENDIAN
1559 /* Calculate the offset assuming fully little-endian,
1560 * then XOR to account for the order of the 8-byte units.
1562 if (element_size < 8) {
1563 ofs ^= 8 - element_size;
1565 #endif
1566 return neon_reg_offset(reg, 0) + ofs;
1569 static TCGv_i32 neon_load_reg(int reg, int pass)
1571 TCGv_i32 tmp = tcg_temp_new_i32();
1572 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1573 return tmp;
1576 static void neon_load_element(TCGv_i32 var, int reg, int ele, TCGMemOp mop)
1578 long offset = neon_element_offset(reg, ele, mop & MO_SIZE);
1580 switch (mop) {
1581 case MO_UB:
1582 tcg_gen_ld8u_i32(var, cpu_env, offset);
1583 break;
1584 case MO_UW:
1585 tcg_gen_ld16u_i32(var, cpu_env, offset);
1586 break;
1587 case MO_UL:
1588 tcg_gen_ld_i32(var, cpu_env, offset);
1589 break;
1590 default:
1591 g_assert_not_reached();
1595 static void neon_load_element64(TCGv_i64 var, int reg, int ele, TCGMemOp mop)
1597 long offset = neon_element_offset(reg, ele, mop & MO_SIZE);
1599 switch (mop) {
1600 case MO_UB:
1601 tcg_gen_ld8u_i64(var, cpu_env, offset);
1602 break;
1603 case MO_UW:
1604 tcg_gen_ld16u_i64(var, cpu_env, offset);
1605 break;
1606 case MO_UL:
1607 tcg_gen_ld32u_i64(var, cpu_env, offset);
1608 break;
1609 case MO_Q:
1610 tcg_gen_ld_i64(var, cpu_env, offset);
1611 break;
1612 default:
1613 g_assert_not_reached();
1617 static void neon_store_reg(int reg, int pass, TCGv_i32 var)
1619 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1620 tcg_temp_free_i32(var);
1623 static void neon_store_element(int reg, int ele, TCGMemOp size, TCGv_i32 var)
1625 long offset = neon_element_offset(reg, ele, size);
1627 switch (size) {
1628 case MO_8:
1629 tcg_gen_st8_i32(var, cpu_env, offset);
1630 break;
1631 case MO_16:
1632 tcg_gen_st16_i32(var, cpu_env, offset);
1633 break;
1634 case MO_32:
1635 tcg_gen_st_i32(var, cpu_env, offset);
1636 break;
1637 default:
1638 g_assert_not_reached();
1642 static void neon_store_element64(int reg, int ele, TCGMemOp size, TCGv_i64 var)
1644 long offset = neon_element_offset(reg, ele, size);
1646 switch (size) {
1647 case MO_8:
1648 tcg_gen_st8_i64(var, cpu_env, offset);
1649 break;
1650 case MO_16:
1651 tcg_gen_st16_i64(var, cpu_env, offset);
1652 break;
1653 case MO_32:
1654 tcg_gen_st32_i64(var, cpu_env, offset);
1655 break;
1656 case MO_64:
1657 tcg_gen_st_i64(var, cpu_env, offset);
1658 break;
1659 default:
1660 g_assert_not_reached();
1664 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1666 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1669 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1671 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1674 static inline void neon_load_reg32(TCGv_i32 var, int reg)
1676 tcg_gen_ld_i32(var, cpu_env, vfp_reg_offset(false, reg));
1679 static inline void neon_store_reg32(TCGv_i32 var, int reg)
1681 tcg_gen_st_i32(var, cpu_env, vfp_reg_offset(false, reg));
1684 static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
1686 TCGv_ptr ret = tcg_temp_new_ptr();
1687 tcg_gen_addi_ptr(ret, cpu_env, vfp_reg_offset(dp, reg));
1688 return ret;
1691 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1692 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1693 #define tcg_gen_st_f32 tcg_gen_st_i32
1694 #define tcg_gen_st_f64 tcg_gen_st_i64
1696 static inline void gen_mov_F0_vreg(int dp, int reg)
1698 if (dp)
1699 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1700 else
1701 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1704 static inline void gen_mov_F1_vreg(int dp, int reg)
1706 if (dp)
1707 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1708 else
1709 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1712 static inline void gen_mov_vreg_F0(int dp, int reg)
1714 if (dp)
1715 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1716 else
1717 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1720 #define ARM_CP_RW_BIT (1 << 20)
1722 /* Include the VFP decoder */
1723 #include "translate-vfp.inc.c"
1725 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1727 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1730 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1732 tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1735 static inline TCGv_i32 iwmmxt_load_creg(int reg)
1737 TCGv_i32 var = tcg_temp_new_i32();
1738 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1739 return var;
1742 static inline void iwmmxt_store_creg(int reg, TCGv_i32 var)
1744 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1745 tcg_temp_free_i32(var);
1748 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1750 iwmmxt_store_reg(cpu_M0, rn);
1753 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1755 iwmmxt_load_reg(cpu_M0, rn);
1758 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1760 iwmmxt_load_reg(cpu_V1, rn);
1761 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1764 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1766 iwmmxt_load_reg(cpu_V1, rn);
1767 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1770 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1772 iwmmxt_load_reg(cpu_V1, rn);
1773 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1776 #define IWMMXT_OP(name) \
1777 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1779 iwmmxt_load_reg(cpu_V1, rn); \
1780 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1783 #define IWMMXT_OP_ENV(name) \
1784 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1786 iwmmxt_load_reg(cpu_V1, rn); \
1787 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1790 #define IWMMXT_OP_ENV_SIZE(name) \
1791 IWMMXT_OP_ENV(name##b) \
1792 IWMMXT_OP_ENV(name##w) \
1793 IWMMXT_OP_ENV(name##l)
1795 #define IWMMXT_OP_ENV1(name) \
1796 static inline void gen_op_iwmmxt_##name##_M0(void) \
1798 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1801 IWMMXT_OP(maddsq)
1802 IWMMXT_OP(madduq)
1803 IWMMXT_OP(sadb)
1804 IWMMXT_OP(sadw)
1805 IWMMXT_OP(mulslw)
1806 IWMMXT_OP(mulshw)
1807 IWMMXT_OP(mululw)
1808 IWMMXT_OP(muluhw)
1809 IWMMXT_OP(macsw)
1810 IWMMXT_OP(macuw)
1812 IWMMXT_OP_ENV_SIZE(unpackl)
1813 IWMMXT_OP_ENV_SIZE(unpackh)
1815 IWMMXT_OP_ENV1(unpacklub)
1816 IWMMXT_OP_ENV1(unpackluw)
1817 IWMMXT_OP_ENV1(unpacklul)
1818 IWMMXT_OP_ENV1(unpackhub)
1819 IWMMXT_OP_ENV1(unpackhuw)
1820 IWMMXT_OP_ENV1(unpackhul)
1821 IWMMXT_OP_ENV1(unpacklsb)
1822 IWMMXT_OP_ENV1(unpacklsw)
1823 IWMMXT_OP_ENV1(unpacklsl)
1824 IWMMXT_OP_ENV1(unpackhsb)
1825 IWMMXT_OP_ENV1(unpackhsw)
1826 IWMMXT_OP_ENV1(unpackhsl)
1828 IWMMXT_OP_ENV_SIZE(cmpeq)
1829 IWMMXT_OP_ENV_SIZE(cmpgtu)
1830 IWMMXT_OP_ENV_SIZE(cmpgts)
1832 IWMMXT_OP_ENV_SIZE(mins)
1833 IWMMXT_OP_ENV_SIZE(minu)
1834 IWMMXT_OP_ENV_SIZE(maxs)
1835 IWMMXT_OP_ENV_SIZE(maxu)
1837 IWMMXT_OP_ENV_SIZE(subn)
1838 IWMMXT_OP_ENV_SIZE(addn)
1839 IWMMXT_OP_ENV_SIZE(subu)
1840 IWMMXT_OP_ENV_SIZE(addu)
1841 IWMMXT_OP_ENV_SIZE(subs)
1842 IWMMXT_OP_ENV_SIZE(adds)
1844 IWMMXT_OP_ENV(avgb0)
1845 IWMMXT_OP_ENV(avgb1)
1846 IWMMXT_OP_ENV(avgw0)
1847 IWMMXT_OP_ENV(avgw1)
1849 IWMMXT_OP_ENV(packuw)
1850 IWMMXT_OP_ENV(packul)
1851 IWMMXT_OP_ENV(packuq)
1852 IWMMXT_OP_ENV(packsw)
1853 IWMMXT_OP_ENV(packsl)
1854 IWMMXT_OP_ENV(packsq)
1856 static void gen_op_iwmmxt_set_mup(void)
1858 TCGv_i32 tmp;
1859 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1860 tcg_gen_ori_i32(tmp, tmp, 2);
1861 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1864 static void gen_op_iwmmxt_set_cup(void)
1866 TCGv_i32 tmp;
1867 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1868 tcg_gen_ori_i32(tmp, tmp, 1);
1869 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1872 static void gen_op_iwmmxt_setpsr_nz(void)
1874 TCGv_i32 tmp = tcg_temp_new_i32();
1875 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1876 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1879 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1881 iwmmxt_load_reg(cpu_V1, rn);
1882 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1883 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1886 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn,
1887 TCGv_i32 dest)
1889 int rd;
1890 uint32_t offset;
1891 TCGv_i32 tmp;
1893 rd = (insn >> 16) & 0xf;
1894 tmp = load_reg(s, rd);
1896 offset = (insn & 0xff) << ((insn >> 7) & 2);
1897 if (insn & (1 << 24)) {
1898 /* Pre indexed */
1899 if (insn & (1 << 23))
1900 tcg_gen_addi_i32(tmp, tmp, offset);
1901 else
1902 tcg_gen_addi_i32(tmp, tmp, -offset);
1903 tcg_gen_mov_i32(dest, tmp);
1904 if (insn & (1 << 21))
1905 store_reg(s, rd, tmp);
1906 else
1907 tcg_temp_free_i32(tmp);
1908 } else if (insn & (1 << 21)) {
1909 /* Post indexed */
1910 tcg_gen_mov_i32(dest, tmp);
1911 if (insn & (1 << 23))
1912 tcg_gen_addi_i32(tmp, tmp, offset);
1913 else
1914 tcg_gen_addi_i32(tmp, tmp, -offset);
1915 store_reg(s, rd, tmp);
1916 } else if (!(insn & (1 << 23)))
1917 return 1;
1918 return 0;
1921 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest)
1923 int rd = (insn >> 0) & 0xf;
1924 TCGv_i32 tmp;
1926 if (insn & (1 << 8)) {
1927 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1928 return 1;
1929 } else {
1930 tmp = iwmmxt_load_creg(rd);
1932 } else {
1933 tmp = tcg_temp_new_i32();
1934 iwmmxt_load_reg(cpu_V0, rd);
1935 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
1937 tcg_gen_andi_i32(tmp, tmp, mask);
1938 tcg_gen_mov_i32(dest, tmp);
1939 tcg_temp_free_i32(tmp);
1940 return 0;
1943 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
1944 (ie. an undefined instruction). */
1945 static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
1947 int rd, wrd;
1948 int rdhi, rdlo, rd0, rd1, i;
1949 TCGv_i32 addr;
1950 TCGv_i32 tmp, tmp2, tmp3;
1952 if ((insn & 0x0e000e00) == 0x0c000000) {
1953 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1954 wrd = insn & 0xf;
1955 rdlo = (insn >> 12) & 0xf;
1956 rdhi = (insn >> 16) & 0xf;
1957 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1958 iwmmxt_load_reg(cpu_V0, wrd);
1959 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
1960 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1961 tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
1962 } else { /* TMCRR */
1963 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1964 iwmmxt_store_reg(cpu_V0, wrd);
1965 gen_op_iwmmxt_set_mup();
1967 return 0;
1970 wrd = (insn >> 12) & 0xf;
1971 addr = tcg_temp_new_i32();
1972 if (gen_iwmmxt_address(s, insn, addr)) {
1973 tcg_temp_free_i32(addr);
1974 return 1;
1976 if (insn & ARM_CP_RW_BIT) {
1977 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1978 tmp = tcg_temp_new_i32();
1979 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
1980 iwmmxt_store_creg(wrd, tmp);
1981 } else {
1982 i = 1;
1983 if (insn & (1 << 8)) {
1984 if (insn & (1 << 22)) { /* WLDRD */
1985 gen_aa32_ld64(s, cpu_M0, addr, get_mem_index(s));
1986 i = 0;
1987 } else { /* WLDRW wRd */
1988 tmp = tcg_temp_new_i32();
1989 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
1991 } else {
1992 tmp = tcg_temp_new_i32();
1993 if (insn & (1 << 22)) { /* WLDRH */
1994 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
1995 } else { /* WLDRB */
1996 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
1999 if (i) {
2000 tcg_gen_extu_i32_i64(cpu_M0, tmp);
2001 tcg_temp_free_i32(tmp);
2003 gen_op_iwmmxt_movq_wRn_M0(wrd);
2005 } else {
2006 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
2007 tmp = iwmmxt_load_creg(wrd);
2008 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
2009 } else {
2010 gen_op_iwmmxt_movq_M0_wRn(wrd);
2011 tmp = tcg_temp_new_i32();
2012 if (insn & (1 << 8)) {
2013 if (insn & (1 << 22)) { /* WSTRD */
2014 gen_aa32_st64(s, cpu_M0, addr, get_mem_index(s));
2015 } else { /* WSTRW wRd */
2016 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2017 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
2019 } else {
2020 if (insn & (1 << 22)) { /* WSTRH */
2021 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2022 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
2023 } else { /* WSTRB */
2024 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2025 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
2029 tcg_temp_free_i32(tmp);
2031 tcg_temp_free_i32(addr);
2032 return 0;
2035 if ((insn & 0x0f000000) != 0x0e000000)
2036 return 1;
2038 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
2039 case 0x000: /* WOR */
2040 wrd = (insn >> 12) & 0xf;
2041 rd0 = (insn >> 0) & 0xf;
2042 rd1 = (insn >> 16) & 0xf;
2043 gen_op_iwmmxt_movq_M0_wRn(rd0);
2044 gen_op_iwmmxt_orq_M0_wRn(rd1);
2045 gen_op_iwmmxt_setpsr_nz();
2046 gen_op_iwmmxt_movq_wRn_M0(wrd);
2047 gen_op_iwmmxt_set_mup();
2048 gen_op_iwmmxt_set_cup();
2049 break;
2050 case 0x011: /* TMCR */
2051 if (insn & 0xf)
2052 return 1;
2053 rd = (insn >> 12) & 0xf;
2054 wrd = (insn >> 16) & 0xf;
2055 switch (wrd) {
2056 case ARM_IWMMXT_wCID:
2057 case ARM_IWMMXT_wCASF:
2058 break;
2059 case ARM_IWMMXT_wCon:
2060 gen_op_iwmmxt_set_cup();
2061 /* Fall through. */
2062 case ARM_IWMMXT_wCSSF:
2063 tmp = iwmmxt_load_creg(wrd);
2064 tmp2 = load_reg(s, rd);
2065 tcg_gen_andc_i32(tmp, tmp, tmp2);
2066 tcg_temp_free_i32(tmp2);
2067 iwmmxt_store_creg(wrd, tmp);
2068 break;
2069 case ARM_IWMMXT_wCGR0:
2070 case ARM_IWMMXT_wCGR1:
2071 case ARM_IWMMXT_wCGR2:
2072 case ARM_IWMMXT_wCGR3:
2073 gen_op_iwmmxt_set_cup();
2074 tmp = load_reg(s, rd);
2075 iwmmxt_store_creg(wrd, tmp);
2076 break;
2077 default:
2078 return 1;
2080 break;
2081 case 0x100: /* WXOR */
2082 wrd = (insn >> 12) & 0xf;
2083 rd0 = (insn >> 0) & 0xf;
2084 rd1 = (insn >> 16) & 0xf;
2085 gen_op_iwmmxt_movq_M0_wRn(rd0);
2086 gen_op_iwmmxt_xorq_M0_wRn(rd1);
2087 gen_op_iwmmxt_setpsr_nz();
2088 gen_op_iwmmxt_movq_wRn_M0(wrd);
2089 gen_op_iwmmxt_set_mup();
2090 gen_op_iwmmxt_set_cup();
2091 break;
2092 case 0x111: /* TMRC */
2093 if (insn & 0xf)
2094 return 1;
2095 rd = (insn >> 12) & 0xf;
2096 wrd = (insn >> 16) & 0xf;
2097 tmp = iwmmxt_load_creg(wrd);
2098 store_reg(s, rd, tmp);
2099 break;
2100 case 0x300: /* WANDN */
2101 wrd = (insn >> 12) & 0xf;
2102 rd0 = (insn >> 0) & 0xf;
2103 rd1 = (insn >> 16) & 0xf;
2104 gen_op_iwmmxt_movq_M0_wRn(rd0);
2105 tcg_gen_neg_i64(cpu_M0, cpu_M0);
2106 gen_op_iwmmxt_andq_M0_wRn(rd1);
2107 gen_op_iwmmxt_setpsr_nz();
2108 gen_op_iwmmxt_movq_wRn_M0(wrd);
2109 gen_op_iwmmxt_set_mup();
2110 gen_op_iwmmxt_set_cup();
2111 break;
2112 case 0x200: /* WAND */
2113 wrd = (insn >> 12) & 0xf;
2114 rd0 = (insn >> 0) & 0xf;
2115 rd1 = (insn >> 16) & 0xf;
2116 gen_op_iwmmxt_movq_M0_wRn(rd0);
2117 gen_op_iwmmxt_andq_M0_wRn(rd1);
2118 gen_op_iwmmxt_setpsr_nz();
2119 gen_op_iwmmxt_movq_wRn_M0(wrd);
2120 gen_op_iwmmxt_set_mup();
2121 gen_op_iwmmxt_set_cup();
2122 break;
2123 case 0x810: case 0xa10: /* WMADD */
2124 wrd = (insn >> 12) & 0xf;
2125 rd0 = (insn >> 0) & 0xf;
2126 rd1 = (insn >> 16) & 0xf;
2127 gen_op_iwmmxt_movq_M0_wRn(rd0);
2128 if (insn & (1 << 21))
2129 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
2130 else
2131 gen_op_iwmmxt_madduq_M0_wRn(rd1);
2132 gen_op_iwmmxt_movq_wRn_M0(wrd);
2133 gen_op_iwmmxt_set_mup();
2134 break;
2135 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
2136 wrd = (insn >> 12) & 0xf;
2137 rd0 = (insn >> 16) & 0xf;
2138 rd1 = (insn >> 0) & 0xf;
2139 gen_op_iwmmxt_movq_M0_wRn(rd0);
2140 switch ((insn >> 22) & 3) {
2141 case 0:
2142 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
2143 break;
2144 case 1:
2145 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
2146 break;
2147 case 2:
2148 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
2149 break;
2150 case 3:
2151 return 1;
2153 gen_op_iwmmxt_movq_wRn_M0(wrd);
2154 gen_op_iwmmxt_set_mup();
2155 gen_op_iwmmxt_set_cup();
2156 break;
2157 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
2158 wrd = (insn >> 12) & 0xf;
2159 rd0 = (insn >> 16) & 0xf;
2160 rd1 = (insn >> 0) & 0xf;
2161 gen_op_iwmmxt_movq_M0_wRn(rd0);
2162 switch ((insn >> 22) & 3) {
2163 case 0:
2164 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
2165 break;
2166 case 1:
2167 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
2168 break;
2169 case 2:
2170 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
2171 break;
2172 case 3:
2173 return 1;
2175 gen_op_iwmmxt_movq_wRn_M0(wrd);
2176 gen_op_iwmmxt_set_mup();
2177 gen_op_iwmmxt_set_cup();
2178 break;
2179 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
2180 wrd = (insn >> 12) & 0xf;
2181 rd0 = (insn >> 16) & 0xf;
2182 rd1 = (insn >> 0) & 0xf;
2183 gen_op_iwmmxt_movq_M0_wRn(rd0);
2184 if (insn & (1 << 22))
2185 gen_op_iwmmxt_sadw_M0_wRn(rd1);
2186 else
2187 gen_op_iwmmxt_sadb_M0_wRn(rd1);
2188 if (!(insn & (1 << 20)))
2189 gen_op_iwmmxt_addl_M0_wRn(wrd);
2190 gen_op_iwmmxt_movq_wRn_M0(wrd);
2191 gen_op_iwmmxt_set_mup();
2192 break;
2193 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
2194 wrd = (insn >> 12) & 0xf;
2195 rd0 = (insn >> 16) & 0xf;
2196 rd1 = (insn >> 0) & 0xf;
2197 gen_op_iwmmxt_movq_M0_wRn(rd0);
2198 if (insn & (1 << 21)) {
2199 if (insn & (1 << 20))
2200 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
2201 else
2202 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
2203 } else {
2204 if (insn & (1 << 20))
2205 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
2206 else
2207 gen_op_iwmmxt_mululw_M0_wRn(rd1);
2209 gen_op_iwmmxt_movq_wRn_M0(wrd);
2210 gen_op_iwmmxt_set_mup();
2211 break;
2212 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
2213 wrd = (insn >> 12) & 0xf;
2214 rd0 = (insn >> 16) & 0xf;
2215 rd1 = (insn >> 0) & 0xf;
2216 gen_op_iwmmxt_movq_M0_wRn(rd0);
2217 if (insn & (1 << 21))
2218 gen_op_iwmmxt_macsw_M0_wRn(rd1);
2219 else
2220 gen_op_iwmmxt_macuw_M0_wRn(rd1);
2221 if (!(insn & (1 << 20))) {
2222 iwmmxt_load_reg(cpu_V1, wrd);
2223 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
2225 gen_op_iwmmxt_movq_wRn_M0(wrd);
2226 gen_op_iwmmxt_set_mup();
2227 break;
2228 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
2229 wrd = (insn >> 12) & 0xf;
2230 rd0 = (insn >> 16) & 0xf;
2231 rd1 = (insn >> 0) & 0xf;
2232 gen_op_iwmmxt_movq_M0_wRn(rd0);
2233 switch ((insn >> 22) & 3) {
2234 case 0:
2235 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
2236 break;
2237 case 1:
2238 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
2239 break;
2240 case 2:
2241 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
2242 break;
2243 case 3:
2244 return 1;
2246 gen_op_iwmmxt_movq_wRn_M0(wrd);
2247 gen_op_iwmmxt_set_mup();
2248 gen_op_iwmmxt_set_cup();
2249 break;
2250 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
2251 wrd = (insn >> 12) & 0xf;
2252 rd0 = (insn >> 16) & 0xf;
2253 rd1 = (insn >> 0) & 0xf;
2254 gen_op_iwmmxt_movq_M0_wRn(rd0);
2255 if (insn & (1 << 22)) {
2256 if (insn & (1 << 20))
2257 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
2258 else
2259 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
2260 } else {
2261 if (insn & (1 << 20))
2262 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
2263 else
2264 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
2266 gen_op_iwmmxt_movq_wRn_M0(wrd);
2267 gen_op_iwmmxt_set_mup();
2268 gen_op_iwmmxt_set_cup();
2269 break;
2270 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
2271 wrd = (insn >> 12) & 0xf;
2272 rd0 = (insn >> 16) & 0xf;
2273 rd1 = (insn >> 0) & 0xf;
2274 gen_op_iwmmxt_movq_M0_wRn(rd0);
2275 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
2276 tcg_gen_andi_i32(tmp, tmp, 7);
2277 iwmmxt_load_reg(cpu_V1, rd1);
2278 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2279 tcg_temp_free_i32(tmp);
2280 gen_op_iwmmxt_movq_wRn_M0(wrd);
2281 gen_op_iwmmxt_set_mup();
2282 break;
2283 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
2284 if (((insn >> 6) & 3) == 3)
2285 return 1;
2286 rd = (insn >> 12) & 0xf;
2287 wrd = (insn >> 16) & 0xf;
2288 tmp = load_reg(s, rd);
2289 gen_op_iwmmxt_movq_M0_wRn(wrd);
2290 switch ((insn >> 6) & 3) {
2291 case 0:
2292 tmp2 = tcg_const_i32(0xff);
2293 tmp3 = tcg_const_i32((insn & 7) << 3);
2294 break;
2295 case 1:
2296 tmp2 = tcg_const_i32(0xffff);
2297 tmp3 = tcg_const_i32((insn & 3) << 4);
2298 break;
2299 case 2:
2300 tmp2 = tcg_const_i32(0xffffffff);
2301 tmp3 = tcg_const_i32((insn & 1) << 5);
2302 break;
2303 default:
2304 tmp2 = NULL;
2305 tmp3 = NULL;
2307 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
2308 tcg_temp_free_i32(tmp3);
2309 tcg_temp_free_i32(tmp2);
2310 tcg_temp_free_i32(tmp);
2311 gen_op_iwmmxt_movq_wRn_M0(wrd);
2312 gen_op_iwmmxt_set_mup();
2313 break;
2314 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
2315 rd = (insn >> 12) & 0xf;
2316 wrd = (insn >> 16) & 0xf;
2317 if (rd == 15 || ((insn >> 22) & 3) == 3)
2318 return 1;
2319 gen_op_iwmmxt_movq_M0_wRn(wrd);
2320 tmp = tcg_temp_new_i32();
2321 switch ((insn >> 22) & 3) {
2322 case 0:
2323 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
2324 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2325 if (insn & 8) {
2326 tcg_gen_ext8s_i32(tmp, tmp);
2327 } else {
2328 tcg_gen_andi_i32(tmp, tmp, 0xff);
2330 break;
2331 case 1:
2332 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
2333 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2334 if (insn & 8) {
2335 tcg_gen_ext16s_i32(tmp, tmp);
2336 } else {
2337 tcg_gen_andi_i32(tmp, tmp, 0xffff);
2339 break;
2340 case 2:
2341 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
2342 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2343 break;
2345 store_reg(s, rd, tmp);
2346 break;
2347 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
2348 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
2349 return 1;
2350 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
2351 switch ((insn >> 22) & 3) {
2352 case 0:
2353 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
2354 break;
2355 case 1:
2356 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
2357 break;
2358 case 2:
2359 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
2360 break;
2362 tcg_gen_shli_i32(tmp, tmp, 28);
2363 gen_set_nzcv(tmp);
2364 tcg_temp_free_i32(tmp);
2365 break;
2366 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
2367 if (((insn >> 6) & 3) == 3)
2368 return 1;
2369 rd = (insn >> 12) & 0xf;
2370 wrd = (insn >> 16) & 0xf;
2371 tmp = load_reg(s, rd);
2372 switch ((insn >> 6) & 3) {
2373 case 0:
2374 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
2375 break;
2376 case 1:
2377 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
2378 break;
2379 case 2:
2380 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
2381 break;
2383 tcg_temp_free_i32(tmp);
2384 gen_op_iwmmxt_movq_wRn_M0(wrd);
2385 gen_op_iwmmxt_set_mup();
2386 break;
2387 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
2388 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
2389 return 1;
2390 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
2391 tmp2 = tcg_temp_new_i32();
2392 tcg_gen_mov_i32(tmp2, tmp);
2393 switch ((insn >> 22) & 3) {
2394 case 0:
2395 for (i = 0; i < 7; i ++) {
2396 tcg_gen_shli_i32(tmp2, tmp2, 4);
2397 tcg_gen_and_i32(tmp, tmp, tmp2);
2399 break;
2400 case 1:
2401 for (i = 0; i < 3; i ++) {
2402 tcg_gen_shli_i32(tmp2, tmp2, 8);
2403 tcg_gen_and_i32(tmp, tmp, tmp2);
2405 break;
2406 case 2:
2407 tcg_gen_shli_i32(tmp2, tmp2, 16);
2408 tcg_gen_and_i32(tmp, tmp, tmp2);
2409 break;
2411 gen_set_nzcv(tmp);
2412 tcg_temp_free_i32(tmp2);
2413 tcg_temp_free_i32(tmp);
2414 break;
2415 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
2416 wrd = (insn >> 12) & 0xf;
2417 rd0 = (insn >> 16) & 0xf;
2418 gen_op_iwmmxt_movq_M0_wRn(rd0);
2419 switch ((insn >> 22) & 3) {
2420 case 0:
2421 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
2422 break;
2423 case 1:
2424 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
2425 break;
2426 case 2:
2427 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
2428 break;
2429 case 3:
2430 return 1;
2432 gen_op_iwmmxt_movq_wRn_M0(wrd);
2433 gen_op_iwmmxt_set_mup();
2434 break;
2435 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
2436 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
2437 return 1;
2438 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
2439 tmp2 = tcg_temp_new_i32();
2440 tcg_gen_mov_i32(tmp2, tmp);
2441 switch ((insn >> 22) & 3) {
2442 case 0:
2443 for (i = 0; i < 7; i ++) {
2444 tcg_gen_shli_i32(tmp2, tmp2, 4);
2445 tcg_gen_or_i32(tmp, tmp, tmp2);
2447 break;
2448 case 1:
2449 for (i = 0; i < 3; i ++) {
2450 tcg_gen_shli_i32(tmp2, tmp2, 8);
2451 tcg_gen_or_i32(tmp, tmp, tmp2);
2453 break;
2454 case 2:
2455 tcg_gen_shli_i32(tmp2, tmp2, 16);
2456 tcg_gen_or_i32(tmp, tmp, tmp2);
2457 break;
2459 gen_set_nzcv(tmp);
2460 tcg_temp_free_i32(tmp2);
2461 tcg_temp_free_i32(tmp);
2462 break;
2463 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
2464 rd = (insn >> 12) & 0xf;
2465 rd0 = (insn >> 16) & 0xf;
2466 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
2467 return 1;
2468 gen_op_iwmmxt_movq_M0_wRn(rd0);
2469 tmp = tcg_temp_new_i32();
2470 switch ((insn >> 22) & 3) {
2471 case 0:
2472 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
2473 break;
2474 case 1:
2475 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
2476 break;
2477 case 2:
2478 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
2479 break;
2481 store_reg(s, rd, tmp);
2482 break;
2483 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
2484 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2485 wrd = (insn >> 12) & 0xf;
2486 rd0 = (insn >> 16) & 0xf;
2487 rd1 = (insn >> 0) & 0xf;
2488 gen_op_iwmmxt_movq_M0_wRn(rd0);
2489 switch ((insn >> 22) & 3) {
2490 case 0:
2491 if (insn & (1 << 21))
2492 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2493 else
2494 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2495 break;
2496 case 1:
2497 if (insn & (1 << 21))
2498 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2499 else
2500 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2501 break;
2502 case 2:
2503 if (insn & (1 << 21))
2504 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2505 else
2506 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2507 break;
2508 case 3:
2509 return 1;
2511 gen_op_iwmmxt_movq_wRn_M0(wrd);
2512 gen_op_iwmmxt_set_mup();
2513 gen_op_iwmmxt_set_cup();
2514 break;
2515 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2516 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2517 wrd = (insn >> 12) & 0xf;
2518 rd0 = (insn >> 16) & 0xf;
2519 gen_op_iwmmxt_movq_M0_wRn(rd0);
2520 switch ((insn >> 22) & 3) {
2521 case 0:
2522 if (insn & (1 << 21))
2523 gen_op_iwmmxt_unpacklsb_M0();
2524 else
2525 gen_op_iwmmxt_unpacklub_M0();
2526 break;
2527 case 1:
2528 if (insn & (1 << 21))
2529 gen_op_iwmmxt_unpacklsw_M0();
2530 else
2531 gen_op_iwmmxt_unpackluw_M0();
2532 break;
2533 case 2:
2534 if (insn & (1 << 21))
2535 gen_op_iwmmxt_unpacklsl_M0();
2536 else
2537 gen_op_iwmmxt_unpacklul_M0();
2538 break;
2539 case 3:
2540 return 1;
2542 gen_op_iwmmxt_movq_wRn_M0(wrd);
2543 gen_op_iwmmxt_set_mup();
2544 gen_op_iwmmxt_set_cup();
2545 break;
2546 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2547 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2548 wrd = (insn >> 12) & 0xf;
2549 rd0 = (insn >> 16) & 0xf;
2550 gen_op_iwmmxt_movq_M0_wRn(rd0);
2551 switch ((insn >> 22) & 3) {
2552 case 0:
2553 if (insn & (1 << 21))
2554 gen_op_iwmmxt_unpackhsb_M0();
2555 else
2556 gen_op_iwmmxt_unpackhub_M0();
2557 break;
2558 case 1:
2559 if (insn & (1 << 21))
2560 gen_op_iwmmxt_unpackhsw_M0();
2561 else
2562 gen_op_iwmmxt_unpackhuw_M0();
2563 break;
2564 case 2:
2565 if (insn & (1 << 21))
2566 gen_op_iwmmxt_unpackhsl_M0();
2567 else
2568 gen_op_iwmmxt_unpackhul_M0();
2569 break;
2570 case 3:
2571 return 1;
2573 gen_op_iwmmxt_movq_wRn_M0(wrd);
2574 gen_op_iwmmxt_set_mup();
2575 gen_op_iwmmxt_set_cup();
2576 break;
2577 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2578 case 0x214: case 0x614: case 0xa14: case 0xe14:
2579 if (((insn >> 22) & 3) == 0)
2580 return 1;
2581 wrd = (insn >> 12) & 0xf;
2582 rd0 = (insn >> 16) & 0xf;
2583 gen_op_iwmmxt_movq_M0_wRn(rd0);
2584 tmp = tcg_temp_new_i32();
2585 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2586 tcg_temp_free_i32(tmp);
2587 return 1;
2589 switch ((insn >> 22) & 3) {
2590 case 1:
2591 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
2592 break;
2593 case 2:
2594 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
2595 break;
2596 case 3:
2597 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
2598 break;
2600 tcg_temp_free_i32(tmp);
2601 gen_op_iwmmxt_movq_wRn_M0(wrd);
2602 gen_op_iwmmxt_set_mup();
2603 gen_op_iwmmxt_set_cup();
2604 break;
2605 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2606 case 0x014: case 0x414: case 0x814: case 0xc14:
2607 if (((insn >> 22) & 3) == 0)
2608 return 1;
2609 wrd = (insn >> 12) & 0xf;
2610 rd0 = (insn >> 16) & 0xf;
2611 gen_op_iwmmxt_movq_M0_wRn(rd0);
2612 tmp = tcg_temp_new_i32();
2613 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2614 tcg_temp_free_i32(tmp);
2615 return 1;
2617 switch ((insn >> 22) & 3) {
2618 case 1:
2619 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2620 break;
2621 case 2:
2622 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2623 break;
2624 case 3:
2625 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2626 break;
2628 tcg_temp_free_i32(tmp);
2629 gen_op_iwmmxt_movq_wRn_M0(wrd);
2630 gen_op_iwmmxt_set_mup();
2631 gen_op_iwmmxt_set_cup();
2632 break;
2633 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2634 case 0x114: case 0x514: case 0x914: case 0xd14:
2635 if (((insn >> 22) & 3) == 0)
2636 return 1;
2637 wrd = (insn >> 12) & 0xf;
2638 rd0 = (insn >> 16) & 0xf;
2639 gen_op_iwmmxt_movq_M0_wRn(rd0);
2640 tmp = tcg_temp_new_i32();
2641 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2642 tcg_temp_free_i32(tmp);
2643 return 1;
2645 switch ((insn >> 22) & 3) {
2646 case 1:
2647 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2648 break;
2649 case 2:
2650 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2651 break;
2652 case 3:
2653 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2654 break;
2656 tcg_temp_free_i32(tmp);
2657 gen_op_iwmmxt_movq_wRn_M0(wrd);
2658 gen_op_iwmmxt_set_mup();
2659 gen_op_iwmmxt_set_cup();
2660 break;
2661 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2662 case 0x314: case 0x714: case 0xb14: case 0xf14:
2663 if (((insn >> 22) & 3) == 0)
2664 return 1;
2665 wrd = (insn >> 12) & 0xf;
2666 rd0 = (insn >> 16) & 0xf;
2667 gen_op_iwmmxt_movq_M0_wRn(rd0);
2668 tmp = tcg_temp_new_i32();
2669 switch ((insn >> 22) & 3) {
2670 case 1:
2671 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2672 tcg_temp_free_i32(tmp);
2673 return 1;
2675 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2676 break;
2677 case 2:
2678 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2679 tcg_temp_free_i32(tmp);
2680 return 1;
2682 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2683 break;
2684 case 3:
2685 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2686 tcg_temp_free_i32(tmp);
2687 return 1;
2689 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2690 break;
2692 tcg_temp_free_i32(tmp);
2693 gen_op_iwmmxt_movq_wRn_M0(wrd);
2694 gen_op_iwmmxt_set_mup();
2695 gen_op_iwmmxt_set_cup();
2696 break;
2697 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2698 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2699 wrd = (insn >> 12) & 0xf;
2700 rd0 = (insn >> 16) & 0xf;
2701 rd1 = (insn >> 0) & 0xf;
2702 gen_op_iwmmxt_movq_M0_wRn(rd0);
2703 switch ((insn >> 22) & 3) {
2704 case 0:
2705 if (insn & (1 << 21))
2706 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2707 else
2708 gen_op_iwmmxt_minub_M0_wRn(rd1);
2709 break;
2710 case 1:
2711 if (insn & (1 << 21))
2712 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2713 else
2714 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2715 break;
2716 case 2:
2717 if (insn & (1 << 21))
2718 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2719 else
2720 gen_op_iwmmxt_minul_M0_wRn(rd1);
2721 break;
2722 case 3:
2723 return 1;
2725 gen_op_iwmmxt_movq_wRn_M0(wrd);
2726 gen_op_iwmmxt_set_mup();
2727 break;
2728 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2729 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2730 wrd = (insn >> 12) & 0xf;
2731 rd0 = (insn >> 16) & 0xf;
2732 rd1 = (insn >> 0) & 0xf;
2733 gen_op_iwmmxt_movq_M0_wRn(rd0);
2734 switch ((insn >> 22) & 3) {
2735 case 0:
2736 if (insn & (1 << 21))
2737 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2738 else
2739 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2740 break;
2741 case 1:
2742 if (insn & (1 << 21))
2743 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2744 else
2745 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2746 break;
2747 case 2:
2748 if (insn & (1 << 21))
2749 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2750 else
2751 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2752 break;
2753 case 3:
2754 return 1;
2756 gen_op_iwmmxt_movq_wRn_M0(wrd);
2757 gen_op_iwmmxt_set_mup();
2758 break;
2759 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2760 case 0x402: case 0x502: case 0x602: case 0x702:
2761 wrd = (insn >> 12) & 0xf;
2762 rd0 = (insn >> 16) & 0xf;
2763 rd1 = (insn >> 0) & 0xf;
2764 gen_op_iwmmxt_movq_M0_wRn(rd0);
2765 tmp = tcg_const_i32((insn >> 20) & 3);
2766 iwmmxt_load_reg(cpu_V1, rd1);
2767 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2768 tcg_temp_free_i32(tmp);
2769 gen_op_iwmmxt_movq_wRn_M0(wrd);
2770 gen_op_iwmmxt_set_mup();
2771 break;
2772 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2773 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2774 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2775 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2776 wrd = (insn >> 12) & 0xf;
2777 rd0 = (insn >> 16) & 0xf;
2778 rd1 = (insn >> 0) & 0xf;
2779 gen_op_iwmmxt_movq_M0_wRn(rd0);
2780 switch ((insn >> 20) & 0xf) {
2781 case 0x0:
2782 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2783 break;
2784 case 0x1:
2785 gen_op_iwmmxt_subub_M0_wRn(rd1);
2786 break;
2787 case 0x3:
2788 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2789 break;
2790 case 0x4:
2791 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2792 break;
2793 case 0x5:
2794 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2795 break;
2796 case 0x7:
2797 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2798 break;
2799 case 0x8:
2800 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2801 break;
2802 case 0x9:
2803 gen_op_iwmmxt_subul_M0_wRn(rd1);
2804 break;
2805 case 0xb:
2806 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2807 break;
2808 default:
2809 return 1;
2811 gen_op_iwmmxt_movq_wRn_M0(wrd);
2812 gen_op_iwmmxt_set_mup();
2813 gen_op_iwmmxt_set_cup();
2814 break;
2815 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2816 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2817 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2818 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2819 wrd = (insn >> 12) & 0xf;
2820 rd0 = (insn >> 16) & 0xf;
2821 gen_op_iwmmxt_movq_M0_wRn(rd0);
2822 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2823 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2824 tcg_temp_free_i32(tmp);
2825 gen_op_iwmmxt_movq_wRn_M0(wrd);
2826 gen_op_iwmmxt_set_mup();
2827 gen_op_iwmmxt_set_cup();
2828 break;
2829 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2830 case 0x418: case 0x518: case 0x618: case 0x718:
2831 case 0x818: case 0x918: case 0xa18: case 0xb18:
2832 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2833 wrd = (insn >> 12) & 0xf;
2834 rd0 = (insn >> 16) & 0xf;
2835 rd1 = (insn >> 0) & 0xf;
2836 gen_op_iwmmxt_movq_M0_wRn(rd0);
2837 switch ((insn >> 20) & 0xf) {
2838 case 0x0:
2839 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2840 break;
2841 case 0x1:
2842 gen_op_iwmmxt_addub_M0_wRn(rd1);
2843 break;
2844 case 0x3:
2845 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2846 break;
2847 case 0x4:
2848 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2849 break;
2850 case 0x5:
2851 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2852 break;
2853 case 0x7:
2854 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2855 break;
2856 case 0x8:
2857 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2858 break;
2859 case 0x9:
2860 gen_op_iwmmxt_addul_M0_wRn(rd1);
2861 break;
2862 case 0xb:
2863 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2864 break;
2865 default:
2866 return 1;
2868 gen_op_iwmmxt_movq_wRn_M0(wrd);
2869 gen_op_iwmmxt_set_mup();
2870 gen_op_iwmmxt_set_cup();
2871 break;
2872 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2873 case 0x408: case 0x508: case 0x608: case 0x708:
2874 case 0x808: case 0x908: case 0xa08: case 0xb08:
2875 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2876 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2877 return 1;
2878 wrd = (insn >> 12) & 0xf;
2879 rd0 = (insn >> 16) & 0xf;
2880 rd1 = (insn >> 0) & 0xf;
2881 gen_op_iwmmxt_movq_M0_wRn(rd0);
2882 switch ((insn >> 22) & 3) {
2883 case 1:
2884 if (insn & (1 << 21))
2885 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2886 else
2887 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2888 break;
2889 case 2:
2890 if (insn & (1 << 21))
2891 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2892 else
2893 gen_op_iwmmxt_packul_M0_wRn(rd1);
2894 break;
2895 case 3:
2896 if (insn & (1 << 21))
2897 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2898 else
2899 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2900 break;
2902 gen_op_iwmmxt_movq_wRn_M0(wrd);
2903 gen_op_iwmmxt_set_mup();
2904 gen_op_iwmmxt_set_cup();
2905 break;
2906 case 0x201: case 0x203: case 0x205: case 0x207:
2907 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2908 case 0x211: case 0x213: case 0x215: case 0x217:
2909 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2910 wrd = (insn >> 5) & 0xf;
2911 rd0 = (insn >> 12) & 0xf;
2912 rd1 = (insn >> 0) & 0xf;
2913 if (rd0 == 0xf || rd1 == 0xf)
2914 return 1;
2915 gen_op_iwmmxt_movq_M0_wRn(wrd);
2916 tmp = load_reg(s, rd0);
2917 tmp2 = load_reg(s, rd1);
2918 switch ((insn >> 16) & 0xf) {
2919 case 0x0: /* TMIA */
2920 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2921 break;
2922 case 0x8: /* TMIAPH */
2923 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2924 break;
2925 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2926 if (insn & (1 << 16))
2927 tcg_gen_shri_i32(tmp, tmp, 16);
2928 if (insn & (1 << 17))
2929 tcg_gen_shri_i32(tmp2, tmp2, 16);
2930 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2931 break;
2932 default:
2933 tcg_temp_free_i32(tmp2);
2934 tcg_temp_free_i32(tmp);
2935 return 1;
2937 tcg_temp_free_i32(tmp2);
2938 tcg_temp_free_i32(tmp);
2939 gen_op_iwmmxt_movq_wRn_M0(wrd);
2940 gen_op_iwmmxt_set_mup();
2941 break;
2942 default:
2943 return 1;
2946 return 0;
2949 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
2950 (ie. an undefined instruction). */
2951 static int disas_dsp_insn(DisasContext *s, uint32_t insn)
2953 int acc, rd0, rd1, rdhi, rdlo;
2954 TCGv_i32 tmp, tmp2;
2956 if ((insn & 0x0ff00f10) == 0x0e200010) {
2957 /* Multiply with Internal Accumulate Format */
2958 rd0 = (insn >> 12) & 0xf;
2959 rd1 = insn & 0xf;
2960 acc = (insn >> 5) & 7;
2962 if (acc != 0)
2963 return 1;
2965 tmp = load_reg(s, rd0);
2966 tmp2 = load_reg(s, rd1);
2967 switch ((insn >> 16) & 0xf) {
2968 case 0x0: /* MIA */
2969 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2970 break;
2971 case 0x8: /* MIAPH */
2972 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2973 break;
2974 case 0xc: /* MIABB */
2975 case 0xd: /* MIABT */
2976 case 0xe: /* MIATB */
2977 case 0xf: /* MIATT */
2978 if (insn & (1 << 16))
2979 tcg_gen_shri_i32(tmp, tmp, 16);
2980 if (insn & (1 << 17))
2981 tcg_gen_shri_i32(tmp2, tmp2, 16);
2982 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2983 break;
2984 default:
2985 return 1;
2987 tcg_temp_free_i32(tmp2);
2988 tcg_temp_free_i32(tmp);
2990 gen_op_iwmmxt_movq_wRn_M0(acc);
2991 return 0;
2994 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2995 /* Internal Accumulator Access Format */
2996 rdhi = (insn >> 16) & 0xf;
2997 rdlo = (insn >> 12) & 0xf;
2998 acc = insn & 7;
3000 if (acc != 0)
3001 return 1;
3003 if (insn & ARM_CP_RW_BIT) { /* MRA */
3004 iwmmxt_load_reg(cpu_V0, acc);
3005 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
3006 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
3007 tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
3008 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
3009 } else { /* MAR */
3010 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
3011 iwmmxt_store_reg(cpu_V0, acc);
3013 return 0;
3016 return 1;
3019 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
3020 #define VFP_SREG(insn, bigbit, smallbit) \
3021 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
3022 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
3023 if (arm_dc_feature(s, ARM_FEATURE_VFP3)) { \
3024 reg = (((insn) >> (bigbit)) & 0x0f) \
3025 | (((insn) >> ((smallbit) - 4)) & 0x10); \
3026 } else { \
3027 if (insn & (1 << (smallbit))) \
3028 return 1; \
3029 reg = ((insn) >> (bigbit)) & 0x0f; \
3030 }} while (0)
3032 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
3033 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
3034 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
3035 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
3036 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
3037 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
3039 /* Move between integer and VFP cores. */
3040 static TCGv_i32 gen_vfp_mrs(void)
3042 TCGv_i32 tmp = tcg_temp_new_i32();
3043 tcg_gen_mov_i32(tmp, cpu_F0s);
3044 return tmp;
3047 static void gen_vfp_msr(TCGv_i32 tmp)
3049 tcg_gen_mov_i32(cpu_F0s, tmp);
3050 tcg_temp_free_i32(tmp);
3053 static void gen_neon_dup_low16(TCGv_i32 var)
3055 TCGv_i32 tmp = tcg_temp_new_i32();
3056 tcg_gen_ext16u_i32(var, var);
3057 tcg_gen_shli_i32(tmp, var, 16);
3058 tcg_gen_or_i32(var, var, tmp);
3059 tcg_temp_free_i32(tmp);
3062 static void gen_neon_dup_high16(TCGv_i32 var)
3064 TCGv_i32 tmp = tcg_temp_new_i32();
3065 tcg_gen_andi_i32(var, var, 0xffff0000);
3066 tcg_gen_shri_i32(tmp, var, 16);
3067 tcg_gen_or_i32(var, var, tmp);
3068 tcg_temp_free_i32(tmp);
3072 * Disassemble a VFP instruction. Returns nonzero if an error occurred
3073 * (ie. an undefined instruction).
3075 static int disas_vfp_insn(DisasContext *s, uint32_t insn)
3077 uint32_t rd, rn, rm, op, i, n, delta_d, delta_m, bank_mask;
3078 int dp, veclen;
3079 TCGv_i32 tmp;
3080 TCGv_i32 tmp2;
3082 if (!arm_dc_feature(s, ARM_FEATURE_VFP)) {
3083 return 1;
3087 * If the decodetree decoder handles this insn it will always
3088 * emit code to either execute the insn or generate an appropriate
3089 * exception; so we don't need to ever return non-zero to tell
3090 * the calling code to emit an UNDEF exception.
3092 if (extract32(insn, 28, 4) == 0xf) {
3093 if (disas_vfp_uncond(s, insn)) {
3094 return 0;
3096 } else {
3097 if (disas_vfp(s, insn)) {
3098 return 0;
3102 if (extract32(insn, 28, 4) == 0xf) {
3104 * Encodings with T=1 (Thumb) or unconditional (ARM): these
3105 * were all handled by the decodetree decoder, so any insn
3106 * patterns which get here must be UNDEF.
3108 return 1;
3112 * FIXME: this access check should not take precedence over UNDEF
3113 * for invalid encodings; we will generate incorrect syndrome information
3114 * for attempts to execute invalid vfp/neon encodings with FP disabled.
3116 if (!vfp_access_check(s)) {
3117 return 0;
3120 dp = ((insn & 0xf00) == 0xb00);
3121 switch ((insn >> 24) & 0xf) {
3122 case 0xe:
3123 if (insn & (1 << 4)) {
3124 /* already handled by decodetree */
3125 return 1;
3126 } else {
3127 /* data processing */
3128 bool rd_is_dp = dp;
3129 bool rm_is_dp = dp;
3130 bool no_output = false;
3132 /* The opcode is in bits 23, 21, 20 and 6. */
3133 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
3134 rn = VFP_SREG_N(insn);
3136 if (op == 15) {
3137 /* rn is opcode, encoded as per VFP_SREG_N. */
3138 switch (rn) {
3139 case 0x00: /* vmov */
3140 case 0x01: /* vabs */
3141 case 0x02: /* vneg */
3142 case 0x03: /* vsqrt */
3143 break;
3145 case 0x04: /* vcvtb.f64.f16, vcvtb.f32.f16 */
3146 case 0x05: /* vcvtt.f64.f16, vcvtt.f32.f16 */
3148 * VCVTB, VCVTT: only present with the halfprec extension
3149 * UNPREDICTABLE if bit 8 is set prior to ARMv8
3150 * (we choose to UNDEF)
3152 if (dp) {
3153 if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
3154 return 1;
3156 } else {
3157 if (!dc_isar_feature(aa32_fp16_spconv, s)) {
3158 return 1;
3161 rm_is_dp = false;
3162 break;
3163 case 0x06: /* vcvtb.f16.f32, vcvtb.f16.f64 */
3164 case 0x07: /* vcvtt.f16.f32, vcvtt.f16.f64 */
3165 if (dp) {
3166 if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
3167 return 1;
3169 } else {
3170 if (!dc_isar_feature(aa32_fp16_spconv, s)) {
3171 return 1;
3174 rd_is_dp = false;
3175 break;
3177 case 0x08: case 0x0a: /* vcmp, vcmpz */
3178 case 0x09: case 0x0b: /* vcmpe, vcmpez */
3179 no_output = true;
3180 break;
3182 case 0x0c: /* vrintr */
3183 case 0x0d: /* vrintz */
3184 case 0x0e: /* vrintx */
3185 break;
3187 case 0x0f: /* vcvt double<->single */
3188 rd_is_dp = !dp;
3189 break;
3191 case 0x10: /* vcvt.fxx.u32 */
3192 case 0x11: /* vcvt.fxx.s32 */
3193 rm_is_dp = false;
3194 break;
3195 case 0x18: /* vcvtr.u32.fxx */
3196 case 0x19: /* vcvtz.u32.fxx */
3197 case 0x1a: /* vcvtr.s32.fxx */
3198 case 0x1b: /* vcvtz.s32.fxx */
3199 rd_is_dp = false;
3200 break;
3202 case 0x14: /* vcvt fp <-> fixed */
3203 case 0x15:
3204 case 0x16:
3205 case 0x17:
3206 case 0x1c:
3207 case 0x1d:
3208 case 0x1e:
3209 case 0x1f:
3210 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3211 return 1;
3213 /* Immediate frac_bits has same format as SREG_M. */
3214 rm_is_dp = false;
3215 break;
3217 case 0x13: /* vjcvt */
3218 if (!dp || !dc_isar_feature(aa32_jscvt, s)) {
3219 return 1;
3221 rd_is_dp = false;
3222 break;
3224 default:
3225 return 1;
3227 } else if (dp) {
3228 /* rn is register number */
3229 VFP_DREG_N(rn, insn);
3232 if (rd_is_dp) {
3233 VFP_DREG_D(rd, insn);
3234 } else {
3235 rd = VFP_SREG_D(insn);
3237 if (rm_is_dp) {
3238 VFP_DREG_M(rm, insn);
3239 } else {
3240 rm = VFP_SREG_M(insn);
3243 veclen = s->vec_len;
3244 if (op == 15 && rn > 3) {
3245 veclen = 0;
3248 /* Shut up compiler warnings. */
3249 delta_m = 0;
3250 delta_d = 0;
3251 bank_mask = 0;
3253 if (veclen > 0) {
3254 if (dp)
3255 bank_mask = 0xc;
3256 else
3257 bank_mask = 0x18;
3259 /* Figure out what type of vector operation this is. */
3260 if ((rd & bank_mask) == 0) {
3261 /* scalar */
3262 veclen = 0;
3263 } else {
3264 if (dp)
3265 delta_d = (s->vec_stride >> 1) + 1;
3266 else
3267 delta_d = s->vec_stride + 1;
3269 if ((rm & bank_mask) == 0) {
3270 /* mixed scalar/vector */
3271 delta_m = 0;
3272 } else {
3273 /* vector */
3274 delta_m = delta_d;
3279 /* Load the initial operands. */
3280 if (op == 15) {
3281 switch (rn) {
3282 case 0x08: case 0x09: /* Compare */
3283 gen_mov_F0_vreg(dp, rd);
3284 gen_mov_F1_vreg(dp, rm);
3285 break;
3286 case 0x0a: case 0x0b: /* Compare with zero */
3287 gen_mov_F0_vreg(dp, rd);
3288 gen_vfp_F1_ld0(dp);
3289 break;
3290 case 0x14: /* vcvt fp <-> fixed */
3291 case 0x15:
3292 case 0x16:
3293 case 0x17:
3294 case 0x1c:
3295 case 0x1d:
3296 case 0x1e:
3297 case 0x1f:
3298 /* Source and destination the same. */
3299 gen_mov_F0_vreg(dp, rd);
3300 break;
3301 default:
3302 /* One source operand. */
3303 gen_mov_F0_vreg(rm_is_dp, rm);
3304 break;
3306 } else {
3307 /* Two source operands. */
3308 gen_mov_F0_vreg(dp, rn);
3309 gen_mov_F1_vreg(dp, rm);
3312 for (;;) {
3313 /* Perform the calculation. */
3314 switch (op) {
3315 case 0: /* VMLA: fd + (fn * fm) */
3316 /* Note that order of inputs to the add matters for NaNs */
3317 gen_vfp_F1_mul(dp);
3318 gen_mov_F0_vreg(dp, rd);
3319 gen_vfp_add(dp);
3320 break;
3321 case 1: /* VMLS: fd + -(fn * fm) */
3322 gen_vfp_mul(dp);
3323 gen_vfp_F1_neg(dp);
3324 gen_mov_F0_vreg(dp, rd);
3325 gen_vfp_add(dp);
3326 break;
3327 case 2: /* VNMLS: -fd + (fn * fm) */
3328 /* Note that it isn't valid to replace (-A + B) with (B - A)
3329 * or similar plausible looking simplifications
3330 * because this will give wrong results for NaNs.
3332 gen_vfp_F1_mul(dp);
3333 gen_mov_F0_vreg(dp, rd);
3334 gen_vfp_neg(dp);
3335 gen_vfp_add(dp);
3336 break;
3337 case 3: /* VNMLA: -fd + -(fn * fm) */
3338 gen_vfp_mul(dp);
3339 gen_vfp_F1_neg(dp);
3340 gen_mov_F0_vreg(dp, rd);
3341 gen_vfp_neg(dp);
3342 gen_vfp_add(dp);
3343 break;
3344 case 4: /* mul: fn * fm */
3345 gen_vfp_mul(dp);
3346 break;
3347 case 5: /* nmul: -(fn * fm) */
3348 gen_vfp_mul(dp);
3349 gen_vfp_neg(dp);
3350 break;
3351 case 6: /* add: fn + fm */
3352 gen_vfp_add(dp);
3353 break;
3354 case 7: /* sub: fn - fm */
3355 gen_vfp_sub(dp);
3356 break;
3357 case 8: /* div: fn / fm */
3358 gen_vfp_div(dp);
3359 break;
3360 case 10: /* VFNMA : fd = muladd(-fd, fn, fm) */
3361 case 11: /* VFNMS : fd = muladd(-fd, -fn, fm) */
3362 case 12: /* VFMA : fd = muladd( fd, fn, fm) */
3363 case 13: /* VFMS : fd = muladd( fd, -fn, fm) */
3364 /* These are fused multiply-add, and must be done as one
3365 * floating point operation with no rounding between the
3366 * multiplication and addition steps.
3367 * NB that doing the negations here as separate steps is
3368 * correct : an input NaN should come out with its sign bit
3369 * flipped if it is a negated-input.
3371 if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
3372 return 1;
3374 if (dp) {
3375 TCGv_ptr fpst;
3376 TCGv_i64 frd;
3377 if (op & 1) {
3378 /* VFNMS, VFMS */
3379 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
3381 frd = tcg_temp_new_i64();
3382 tcg_gen_ld_f64(frd, cpu_env, vfp_reg_offset(dp, rd));
3383 if (op & 2) {
3384 /* VFNMA, VFNMS */
3385 gen_helper_vfp_negd(frd, frd);
3387 fpst = get_fpstatus_ptr(0);
3388 gen_helper_vfp_muladdd(cpu_F0d, cpu_F0d,
3389 cpu_F1d, frd, fpst);
3390 tcg_temp_free_ptr(fpst);
3391 tcg_temp_free_i64(frd);
3392 } else {
3393 TCGv_ptr fpst;
3394 TCGv_i32 frd;
3395 if (op & 1) {
3396 /* VFNMS, VFMS */
3397 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
3399 frd = tcg_temp_new_i32();
3400 tcg_gen_ld_f32(frd, cpu_env, vfp_reg_offset(dp, rd));
3401 if (op & 2) {
3402 gen_helper_vfp_negs(frd, frd);
3404 fpst = get_fpstatus_ptr(0);
3405 gen_helper_vfp_muladds(cpu_F0s, cpu_F0s,
3406 cpu_F1s, frd, fpst);
3407 tcg_temp_free_ptr(fpst);
3408 tcg_temp_free_i32(frd);
3410 break;
3411 case 14: /* fconst */
3412 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3413 return 1;
3416 n = (insn << 12) & 0x80000000;
3417 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3418 if (dp) {
3419 if (i & 0x40)
3420 i |= 0x3f80;
3421 else
3422 i |= 0x4000;
3423 n |= i << 16;
3424 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3425 } else {
3426 if (i & 0x40)
3427 i |= 0x780;
3428 else
3429 i |= 0x800;
3430 n |= i << 19;
3431 tcg_gen_movi_i32(cpu_F0s, n);
3433 break;
3434 case 15: /* extension space */
3435 switch (rn) {
3436 case 0: /* cpy */
3437 /* no-op */
3438 break;
3439 case 1: /* abs */
3440 gen_vfp_abs(dp);
3441 break;
3442 case 2: /* neg */
3443 gen_vfp_neg(dp);
3444 break;
3445 case 3: /* sqrt */
3446 gen_vfp_sqrt(dp);
3447 break;
3448 case 4: /* vcvtb.f32.f16, vcvtb.f64.f16 */
3450 TCGv_ptr fpst = get_fpstatus_ptr(false);
3451 TCGv_i32 ahp_mode = get_ahp_flag();
3452 tmp = gen_vfp_mrs();
3453 tcg_gen_ext16u_i32(tmp, tmp);
3454 if (dp) {
3455 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
3456 fpst, ahp_mode);
3457 } else {
3458 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
3459 fpst, ahp_mode);
3461 tcg_temp_free_i32(ahp_mode);
3462 tcg_temp_free_ptr(fpst);
3463 tcg_temp_free_i32(tmp);
3464 break;
3466 case 5: /* vcvtt.f32.f16, vcvtt.f64.f16 */
3468 TCGv_ptr fpst = get_fpstatus_ptr(false);
3469 TCGv_i32 ahp = get_ahp_flag();
3470 tmp = gen_vfp_mrs();
3471 tcg_gen_shri_i32(tmp, tmp, 16);
3472 if (dp) {
3473 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
3474 fpst, ahp);
3475 } else {
3476 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
3477 fpst, ahp);
3479 tcg_temp_free_i32(tmp);
3480 tcg_temp_free_i32(ahp);
3481 tcg_temp_free_ptr(fpst);
3482 break;
3484 case 6: /* vcvtb.f16.f32, vcvtb.f16.f64 */
3486 TCGv_ptr fpst = get_fpstatus_ptr(false);
3487 TCGv_i32 ahp = get_ahp_flag();
3488 tmp = tcg_temp_new_i32();
3490 if (dp) {
3491 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
3492 fpst, ahp);
3493 } else {
3494 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
3495 fpst, ahp);
3497 tcg_temp_free_i32(ahp);
3498 tcg_temp_free_ptr(fpst);
3499 gen_mov_F0_vreg(0, rd);
3500 tmp2 = gen_vfp_mrs();
3501 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3502 tcg_gen_or_i32(tmp, tmp, tmp2);
3503 tcg_temp_free_i32(tmp2);
3504 gen_vfp_msr(tmp);
3505 break;
3507 case 7: /* vcvtt.f16.f32, vcvtt.f16.f64 */
3509 TCGv_ptr fpst = get_fpstatus_ptr(false);
3510 TCGv_i32 ahp = get_ahp_flag();
3511 tmp = tcg_temp_new_i32();
3512 if (dp) {
3513 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
3514 fpst, ahp);
3515 } else {
3516 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
3517 fpst, ahp);
3519 tcg_temp_free_i32(ahp);
3520 tcg_temp_free_ptr(fpst);
3521 tcg_gen_shli_i32(tmp, tmp, 16);
3522 gen_mov_F0_vreg(0, rd);
3523 tmp2 = gen_vfp_mrs();
3524 tcg_gen_ext16u_i32(tmp2, tmp2);
3525 tcg_gen_or_i32(tmp, tmp, tmp2);
3526 tcg_temp_free_i32(tmp2);
3527 gen_vfp_msr(tmp);
3528 break;
3530 case 8: /* cmp */
3531 gen_vfp_cmp(dp);
3532 break;
3533 case 9: /* cmpe */
3534 gen_vfp_cmpe(dp);
3535 break;
3536 case 10: /* cmpz */
3537 gen_vfp_cmp(dp);
3538 break;
3539 case 11: /* cmpez */
3540 gen_vfp_F1_ld0(dp);
3541 gen_vfp_cmpe(dp);
3542 break;
3543 case 12: /* vrintr */
3545 TCGv_ptr fpst = get_fpstatus_ptr(0);
3546 if (dp) {
3547 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
3548 } else {
3549 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
3551 tcg_temp_free_ptr(fpst);
3552 break;
3554 case 13: /* vrintz */
3556 TCGv_ptr fpst = get_fpstatus_ptr(0);
3557 TCGv_i32 tcg_rmode;
3558 tcg_rmode = tcg_const_i32(float_round_to_zero);
3559 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
3560 if (dp) {
3561 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
3562 } else {
3563 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
3565 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
3566 tcg_temp_free_i32(tcg_rmode);
3567 tcg_temp_free_ptr(fpst);
3568 break;
3570 case 14: /* vrintx */
3572 TCGv_ptr fpst = get_fpstatus_ptr(0);
3573 if (dp) {
3574 gen_helper_rintd_exact(cpu_F0d, cpu_F0d, fpst);
3575 } else {
3576 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpst);
3578 tcg_temp_free_ptr(fpst);
3579 break;
3581 case 15: /* single<->double conversion */
3582 if (dp) {
3583 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3584 } else {
3585 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3587 break;
3588 case 16: /* fuito */
3589 gen_vfp_uito(dp, 0);
3590 break;
3591 case 17: /* fsito */
3592 gen_vfp_sito(dp, 0);
3593 break;
3594 case 19: /* vjcvt */
3595 gen_helper_vjcvt(cpu_F0s, cpu_F0d, cpu_env);
3596 break;
3597 case 20: /* fshto */
3598 gen_vfp_shto(dp, 16 - rm, 0);
3599 break;
3600 case 21: /* fslto */
3601 gen_vfp_slto(dp, 32 - rm, 0);
3602 break;
3603 case 22: /* fuhto */
3604 gen_vfp_uhto(dp, 16 - rm, 0);
3605 break;
3606 case 23: /* fulto */
3607 gen_vfp_ulto(dp, 32 - rm, 0);
3608 break;
3609 case 24: /* ftoui */
3610 gen_vfp_toui(dp, 0);
3611 break;
3612 case 25: /* ftouiz */
3613 gen_vfp_touiz(dp, 0);
3614 break;
3615 case 26: /* ftosi */
3616 gen_vfp_tosi(dp, 0);
3617 break;
3618 case 27: /* ftosiz */
3619 gen_vfp_tosiz(dp, 0);
3620 break;
3621 case 28: /* ftosh */
3622 gen_vfp_tosh(dp, 16 - rm, 0);
3623 break;
3624 case 29: /* ftosl */
3625 gen_vfp_tosl(dp, 32 - rm, 0);
3626 break;
3627 case 30: /* ftouh */
3628 gen_vfp_touh(dp, 16 - rm, 0);
3629 break;
3630 case 31: /* ftoul */
3631 gen_vfp_toul(dp, 32 - rm, 0);
3632 break;
3633 default: /* undefined */
3634 g_assert_not_reached();
3636 break;
3637 default: /* undefined */
3638 return 1;
3641 /* Write back the result, if any. */
3642 if (!no_output) {
3643 gen_mov_vreg_F0(rd_is_dp, rd);
3646 /* break out of the loop if we have finished */
3647 if (veclen == 0) {
3648 break;
3651 if (op == 15 && delta_m == 0) {
3652 /* single source one-many */
3653 while (veclen--) {
3654 rd = ((rd + delta_d) & (bank_mask - 1))
3655 | (rd & bank_mask);
3656 gen_mov_vreg_F0(dp, rd);
3658 break;
3660 /* Setup the next operands. */
3661 veclen--;
3662 rd = ((rd + delta_d) & (bank_mask - 1))
3663 | (rd & bank_mask);
3665 if (op == 15) {
3666 /* One source operand. */
3667 rm = ((rm + delta_m) & (bank_mask - 1))
3668 | (rm & bank_mask);
3669 gen_mov_F0_vreg(dp, rm);
3670 } else {
3671 /* Two source operands. */
3672 rn = ((rn + delta_d) & (bank_mask - 1))
3673 | (rn & bank_mask);
3674 gen_mov_F0_vreg(dp, rn);
3675 if (delta_m) {
3676 rm = ((rm + delta_m) & (bank_mask - 1))
3677 | (rm & bank_mask);
3678 gen_mov_F1_vreg(dp, rm);
3683 break;
3684 case 0xc:
3685 case 0xd:
3686 /* Already handled by decodetree */
3687 return 1;
3688 default:
3689 /* Should never happen. */
3690 return 1;
3692 return 0;
3695 static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
3697 #ifndef CONFIG_USER_ONLY
3698 return (s->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
3699 ((s->pc - 1) & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
3700 #else
3701 return true;
3702 #endif
3705 static void gen_goto_ptr(void)
3707 tcg_gen_lookup_and_goto_ptr();
3710 /* This will end the TB but doesn't guarantee we'll return to
3711 * cpu_loop_exec. Any live exit_requests will be processed as we
3712 * enter the next TB.
3714 static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
3716 if (use_goto_tb(s, dest)) {
3717 tcg_gen_goto_tb(n);
3718 gen_set_pc_im(s, dest);
3719 tcg_gen_exit_tb(s->base.tb, n);
3720 } else {
3721 gen_set_pc_im(s, dest);
3722 gen_goto_ptr();
3724 s->base.is_jmp = DISAS_NORETURN;
3727 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3729 if (unlikely(is_singlestepping(s))) {
3730 /* An indirect jump so that we still trigger the debug exception. */
3731 if (s->thumb)
3732 dest |= 1;
3733 gen_bx_im(s, dest);
3734 } else {
3735 gen_goto_tb(s, 0, dest);
3739 static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
3741 if (x)
3742 tcg_gen_sari_i32(t0, t0, 16);
3743 else
3744 gen_sxth(t0);
3745 if (y)
3746 tcg_gen_sari_i32(t1, t1, 16);
3747 else
3748 gen_sxth(t1);
3749 tcg_gen_mul_i32(t0, t0, t1);
3752 /* Return the mask of PSR bits set by a MSR instruction. */
3753 static uint32_t msr_mask(DisasContext *s, int flags, int spsr)
3755 uint32_t mask;
3757 mask = 0;
3758 if (flags & (1 << 0))
3759 mask |= 0xff;
3760 if (flags & (1 << 1))
3761 mask |= 0xff00;
3762 if (flags & (1 << 2))
3763 mask |= 0xff0000;
3764 if (flags & (1 << 3))
3765 mask |= 0xff000000;
3767 /* Mask out undefined bits. */
3768 mask &= ~CPSR_RESERVED;
3769 if (!arm_dc_feature(s, ARM_FEATURE_V4T)) {
3770 mask &= ~CPSR_T;
3772 if (!arm_dc_feature(s, ARM_FEATURE_V5)) {
3773 mask &= ~CPSR_Q; /* V5TE in reality*/
3775 if (!arm_dc_feature(s, ARM_FEATURE_V6)) {
3776 mask &= ~(CPSR_E | CPSR_GE);
3778 if (!arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
3779 mask &= ~CPSR_IT;
3781 /* Mask out execution state and reserved bits. */
3782 if (!spsr) {
3783 mask &= ~(CPSR_EXEC | CPSR_RESERVED);
3785 /* Mask out privileged bits. */
3786 if (IS_USER(s))
3787 mask &= CPSR_USER;
3788 return mask;
3791 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3792 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
3794 TCGv_i32 tmp;
3795 if (spsr) {
3796 /* ??? This is also undefined in system mode. */
3797 if (IS_USER(s))
3798 return 1;
3800 tmp = load_cpu_field(spsr);
3801 tcg_gen_andi_i32(tmp, tmp, ~mask);
3802 tcg_gen_andi_i32(t0, t0, mask);
3803 tcg_gen_or_i32(tmp, tmp, t0);
3804 store_cpu_field(tmp, spsr);
3805 } else {
3806 gen_set_cpsr(t0, mask);
3808 tcg_temp_free_i32(t0);
3809 gen_lookup_tb(s);
3810 return 0;
3813 /* Returns nonzero if access to the PSR is not permitted. */
3814 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3816 TCGv_i32 tmp;
3817 tmp = tcg_temp_new_i32();
3818 tcg_gen_movi_i32(tmp, val);
3819 return gen_set_psr(s, mask, spsr, tmp);
3822 static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
3823 int *tgtmode, int *regno)
3825 /* Decode the r and sysm fields of MSR/MRS banked accesses into
3826 * the target mode and register number, and identify the various
3827 * unpredictable cases.
3828 * MSR (banked) and MRS (banked) are CONSTRAINED UNPREDICTABLE if:
3829 * + executed in user mode
3830 * + using R15 as the src/dest register
3831 * + accessing an unimplemented register
3832 * + accessing a register that's inaccessible at current PL/security state*
3833 * + accessing a register that you could access with a different insn
3834 * We choose to UNDEF in all these cases.
3835 * Since we don't know which of the various AArch32 modes we are in
3836 * we have to defer some checks to runtime.
3837 * Accesses to Monitor mode registers from Secure EL1 (which implies
3838 * that EL3 is AArch64) must trap to EL3.
3840 * If the access checks fail this function will emit code to take
3841 * an exception and return false. Otherwise it will return true,
3842 * and set *tgtmode and *regno appropriately.
3844 int exc_target = default_exception_el(s);
3846 /* These instructions are present only in ARMv8, or in ARMv7 with the
3847 * Virtualization Extensions.
3849 if (!arm_dc_feature(s, ARM_FEATURE_V8) &&
3850 !arm_dc_feature(s, ARM_FEATURE_EL2)) {
3851 goto undef;
3854 if (IS_USER(s) || rn == 15) {
3855 goto undef;
3858 /* The table in the v8 ARM ARM section F5.2.3 describes the encoding
3859 * of registers into (r, sysm).
3861 if (r) {
3862 /* SPSRs for other modes */
3863 switch (sysm) {
3864 case 0xe: /* SPSR_fiq */
3865 *tgtmode = ARM_CPU_MODE_FIQ;
3866 break;
3867 case 0x10: /* SPSR_irq */
3868 *tgtmode = ARM_CPU_MODE_IRQ;
3869 break;
3870 case 0x12: /* SPSR_svc */
3871 *tgtmode = ARM_CPU_MODE_SVC;
3872 break;
3873 case 0x14: /* SPSR_abt */
3874 *tgtmode = ARM_CPU_MODE_ABT;
3875 break;
3876 case 0x16: /* SPSR_und */
3877 *tgtmode = ARM_CPU_MODE_UND;
3878 break;
3879 case 0x1c: /* SPSR_mon */
3880 *tgtmode = ARM_CPU_MODE_MON;
3881 break;
3882 case 0x1e: /* SPSR_hyp */
3883 *tgtmode = ARM_CPU_MODE_HYP;
3884 break;
3885 default: /* unallocated */
3886 goto undef;
3888 /* We arbitrarily assign SPSR a register number of 16. */
3889 *regno = 16;
3890 } else {
3891 /* general purpose registers for other modes */
3892 switch (sysm) {
3893 case 0x0 ... 0x6: /* 0b00xxx : r8_usr ... r14_usr */
3894 *tgtmode = ARM_CPU_MODE_USR;
3895 *regno = sysm + 8;
3896 break;
3897 case 0x8 ... 0xe: /* 0b01xxx : r8_fiq ... r14_fiq */
3898 *tgtmode = ARM_CPU_MODE_FIQ;
3899 *regno = sysm;
3900 break;
3901 case 0x10 ... 0x11: /* 0b1000x : r14_irq, r13_irq */
3902 *tgtmode = ARM_CPU_MODE_IRQ;
3903 *regno = sysm & 1 ? 13 : 14;
3904 break;
3905 case 0x12 ... 0x13: /* 0b1001x : r14_svc, r13_svc */
3906 *tgtmode = ARM_CPU_MODE_SVC;
3907 *regno = sysm & 1 ? 13 : 14;
3908 break;
3909 case 0x14 ... 0x15: /* 0b1010x : r14_abt, r13_abt */
3910 *tgtmode = ARM_CPU_MODE_ABT;
3911 *regno = sysm & 1 ? 13 : 14;
3912 break;
3913 case 0x16 ... 0x17: /* 0b1011x : r14_und, r13_und */
3914 *tgtmode = ARM_CPU_MODE_UND;
3915 *regno = sysm & 1 ? 13 : 14;
3916 break;
3917 case 0x1c ... 0x1d: /* 0b1110x : r14_mon, r13_mon */
3918 *tgtmode = ARM_CPU_MODE_MON;
3919 *regno = sysm & 1 ? 13 : 14;
3920 break;
3921 case 0x1e ... 0x1f: /* 0b1111x : elr_hyp, r13_hyp */
3922 *tgtmode = ARM_CPU_MODE_HYP;
3923 /* Arbitrarily pick 17 for ELR_Hyp (which is not a banked LR!) */
3924 *regno = sysm & 1 ? 13 : 17;
3925 break;
3926 default: /* unallocated */
3927 goto undef;
3931 /* Catch the 'accessing inaccessible register' cases we can detect
3932 * at translate time.
3934 switch (*tgtmode) {
3935 case ARM_CPU_MODE_MON:
3936 if (!arm_dc_feature(s, ARM_FEATURE_EL3) || s->ns) {
3937 goto undef;
3939 if (s->current_el == 1) {
3940 /* If we're in Secure EL1 (which implies that EL3 is AArch64)
3941 * then accesses to Mon registers trap to EL3
3943 exc_target = 3;
3944 goto undef;
3946 break;
3947 case ARM_CPU_MODE_HYP:
3949 * SPSR_hyp and r13_hyp can only be accessed from Monitor mode
3950 * (and so we can forbid accesses from EL2 or below). elr_hyp
3951 * can be accessed also from Hyp mode, so forbid accesses from
3952 * EL0 or EL1.
3954 if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el < 2 ||
3955 (s->current_el < 3 && *regno != 17)) {
3956 goto undef;
3958 break;
3959 default:
3960 break;
3963 return true;
3965 undef:
3966 /* If we get here then some access check did not pass */
3967 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), exc_target);
3968 return false;
3971 static void gen_msr_banked(DisasContext *s, int r, int sysm, int rn)
3973 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
3974 int tgtmode = 0, regno = 0;
3976 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
3977 return;
3980 /* Sync state because msr_banked() can raise exceptions */
3981 gen_set_condexec(s);
3982 gen_set_pc_im(s, s->pc - 4);
3983 tcg_reg = load_reg(s, rn);
3984 tcg_tgtmode = tcg_const_i32(tgtmode);
3985 tcg_regno = tcg_const_i32(regno);
3986 gen_helper_msr_banked(cpu_env, tcg_reg, tcg_tgtmode, tcg_regno);
3987 tcg_temp_free_i32(tcg_tgtmode);
3988 tcg_temp_free_i32(tcg_regno);
3989 tcg_temp_free_i32(tcg_reg);
3990 s->base.is_jmp = DISAS_UPDATE;
3993 static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn)
3995 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
3996 int tgtmode = 0, regno = 0;
3998 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
3999 return;
4002 /* Sync state because mrs_banked() can raise exceptions */
4003 gen_set_condexec(s);
4004 gen_set_pc_im(s, s->pc - 4);
4005 tcg_reg = tcg_temp_new_i32();
4006 tcg_tgtmode = tcg_const_i32(tgtmode);
4007 tcg_regno = tcg_const_i32(regno);
4008 gen_helper_mrs_banked(tcg_reg, cpu_env, tcg_tgtmode, tcg_regno);
4009 tcg_temp_free_i32(tcg_tgtmode);
4010 tcg_temp_free_i32(tcg_regno);
4011 store_reg(s, rn, tcg_reg);
4012 s->base.is_jmp = DISAS_UPDATE;
4015 /* Store value to PC as for an exception return (ie don't
4016 * mask bits). The subsequent call to gen_helper_cpsr_write_eret()
4017 * will do the masking based on the new value of the Thumb bit.
4019 static void store_pc_exc_ret(DisasContext *s, TCGv_i32 pc)
4021 tcg_gen_mov_i32(cpu_R[15], pc);
4022 tcg_temp_free_i32(pc);
4025 /* Generate a v6 exception return. Marks both values as dead. */
4026 static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
4028 store_pc_exc_ret(s, pc);
4029 /* The cpsr_write_eret helper will mask the low bits of PC
4030 * appropriately depending on the new Thumb bit, so it must
4031 * be called after storing the new PC.
4033 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
4034 gen_io_start();
4036 gen_helper_cpsr_write_eret(cpu_env, cpsr);
4037 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
4038 gen_io_end();
4040 tcg_temp_free_i32(cpsr);
4041 /* Must exit loop to check un-masked IRQs */
4042 s->base.is_jmp = DISAS_EXIT;
4045 /* Generate an old-style exception return. Marks pc as dead. */
4046 static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
4048 gen_rfe(s, pc, load_cpu_field(spsr));
4052 * For WFI we will halt the vCPU until an IRQ. For WFE and YIELD we
4053 * only call the helper when running single threaded TCG code to ensure
4054 * the next round-robin scheduled vCPU gets a crack. In MTTCG mode we
4055 * just skip this instruction. Currently the SEV/SEVL instructions
4056 * which are *one* of many ways to wake the CPU from WFE are not
4057 * implemented so we can't sleep like WFI does.
4059 static void gen_nop_hint(DisasContext *s, int val)
4061 switch (val) {
4062 /* When running in MTTCG we don't generate jumps to the yield and
4063 * WFE helpers as it won't affect the scheduling of other vCPUs.
4064 * If we wanted to more completely model WFE/SEV so we don't busy
4065 * spin unnecessarily we would need to do something more involved.
4067 case 1: /* yield */
4068 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
4069 gen_set_pc_im(s, s->pc);
4070 s->base.is_jmp = DISAS_YIELD;
4072 break;
4073 case 3: /* wfi */
4074 gen_set_pc_im(s, s->pc);
4075 s->base.is_jmp = DISAS_WFI;
4076 break;
4077 case 2: /* wfe */
4078 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
4079 gen_set_pc_im(s, s->pc);
4080 s->base.is_jmp = DISAS_WFE;
4082 break;
4083 case 4: /* sev */
4084 case 5: /* sevl */
4085 /* TODO: Implement SEV, SEVL and WFE. May help SMP performance. */
4086 default: /* nop */
4087 break;
4091 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
4093 static inline void gen_neon_add(int size, TCGv_i32 t0, TCGv_i32 t1)
4095 switch (size) {
4096 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
4097 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
4098 case 2: tcg_gen_add_i32(t0, t0, t1); break;
4099 default: abort();
4103 static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
4105 switch (size) {
4106 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
4107 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
4108 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
4109 default: return;
4113 /* 32-bit pairwise ops end up the same as the elementwise versions. */
4114 #define gen_helper_neon_pmax_s32 tcg_gen_smax_i32
4115 #define gen_helper_neon_pmax_u32 tcg_gen_umax_i32
4116 #define gen_helper_neon_pmin_s32 tcg_gen_smin_i32
4117 #define gen_helper_neon_pmin_u32 tcg_gen_umin_i32
4119 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
4120 switch ((size << 1) | u) { \
4121 case 0: \
4122 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
4123 break; \
4124 case 1: \
4125 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
4126 break; \
4127 case 2: \
4128 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
4129 break; \
4130 case 3: \
4131 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
4132 break; \
4133 case 4: \
4134 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
4135 break; \
4136 case 5: \
4137 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
4138 break; \
4139 default: return 1; \
4140 }} while (0)
4142 #define GEN_NEON_INTEGER_OP(name) do { \
4143 switch ((size << 1) | u) { \
4144 case 0: \
4145 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
4146 break; \
4147 case 1: \
4148 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
4149 break; \
4150 case 2: \
4151 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
4152 break; \
4153 case 3: \
4154 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
4155 break; \
4156 case 4: \
4157 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
4158 break; \
4159 case 5: \
4160 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
4161 break; \
4162 default: return 1; \
4163 }} while (0)
4165 static TCGv_i32 neon_load_scratch(int scratch)
4167 TCGv_i32 tmp = tcg_temp_new_i32();
4168 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
4169 return tmp;
4172 static void neon_store_scratch(int scratch, TCGv_i32 var)
4174 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
4175 tcg_temp_free_i32(var);
4178 static inline TCGv_i32 neon_get_scalar(int size, int reg)
4180 TCGv_i32 tmp;
4181 if (size == 1) {
4182 tmp = neon_load_reg(reg & 7, reg >> 4);
4183 if (reg & 8) {
4184 gen_neon_dup_high16(tmp);
4185 } else {
4186 gen_neon_dup_low16(tmp);
4188 } else {
4189 tmp = neon_load_reg(reg & 15, reg >> 4);
4191 return tmp;
4194 static int gen_neon_unzip(int rd, int rm, int size, int q)
4196 TCGv_ptr pd, pm;
4198 if (!q && size == 2) {
4199 return 1;
4201 pd = vfp_reg_ptr(true, rd);
4202 pm = vfp_reg_ptr(true, rm);
4203 if (q) {
4204 switch (size) {
4205 case 0:
4206 gen_helper_neon_qunzip8(pd, pm);
4207 break;
4208 case 1:
4209 gen_helper_neon_qunzip16(pd, pm);
4210 break;
4211 case 2:
4212 gen_helper_neon_qunzip32(pd, pm);
4213 break;
4214 default:
4215 abort();
4217 } else {
4218 switch (size) {
4219 case 0:
4220 gen_helper_neon_unzip8(pd, pm);
4221 break;
4222 case 1:
4223 gen_helper_neon_unzip16(pd, pm);
4224 break;
4225 default:
4226 abort();
4229 tcg_temp_free_ptr(pd);
4230 tcg_temp_free_ptr(pm);
4231 return 0;
4234 static int gen_neon_zip(int rd, int rm, int size, int q)
4236 TCGv_ptr pd, pm;
4238 if (!q && size == 2) {
4239 return 1;
4241 pd = vfp_reg_ptr(true, rd);
4242 pm = vfp_reg_ptr(true, rm);
4243 if (q) {
4244 switch (size) {
4245 case 0:
4246 gen_helper_neon_qzip8(pd, pm);
4247 break;
4248 case 1:
4249 gen_helper_neon_qzip16(pd, pm);
4250 break;
4251 case 2:
4252 gen_helper_neon_qzip32(pd, pm);
4253 break;
4254 default:
4255 abort();
4257 } else {
4258 switch (size) {
4259 case 0:
4260 gen_helper_neon_zip8(pd, pm);
4261 break;
4262 case 1:
4263 gen_helper_neon_zip16(pd, pm);
4264 break;
4265 default:
4266 abort();
4269 tcg_temp_free_ptr(pd);
4270 tcg_temp_free_ptr(pm);
4271 return 0;
4274 static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
4276 TCGv_i32 rd, tmp;
4278 rd = tcg_temp_new_i32();
4279 tmp = tcg_temp_new_i32();
4281 tcg_gen_shli_i32(rd, t0, 8);
4282 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
4283 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
4284 tcg_gen_or_i32(rd, rd, tmp);
4286 tcg_gen_shri_i32(t1, t1, 8);
4287 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
4288 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
4289 tcg_gen_or_i32(t1, t1, tmp);
4290 tcg_gen_mov_i32(t0, rd);
4292 tcg_temp_free_i32(tmp);
4293 tcg_temp_free_i32(rd);
4296 static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
4298 TCGv_i32 rd, tmp;
4300 rd = tcg_temp_new_i32();
4301 tmp = tcg_temp_new_i32();
4303 tcg_gen_shli_i32(rd, t0, 16);
4304 tcg_gen_andi_i32(tmp, t1, 0xffff);
4305 tcg_gen_or_i32(rd, rd, tmp);
4306 tcg_gen_shri_i32(t1, t1, 16);
4307 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
4308 tcg_gen_or_i32(t1, t1, tmp);
4309 tcg_gen_mov_i32(t0, rd);
4311 tcg_temp_free_i32(tmp);
4312 tcg_temp_free_i32(rd);
4316 static struct {
4317 int nregs;
4318 int interleave;
4319 int spacing;
4320 } const neon_ls_element_type[11] = {
4321 {1, 4, 1},
4322 {1, 4, 2},
4323 {4, 1, 1},
4324 {2, 2, 2},
4325 {1, 3, 1},
4326 {1, 3, 2},
4327 {3, 1, 1},
4328 {1, 1, 1},
4329 {1, 2, 1},
4330 {1, 2, 2},
4331 {2, 1, 1}
4334 /* Translate a NEON load/store element instruction. Return nonzero if the
4335 instruction is invalid. */
4336 static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
4338 int rd, rn, rm;
4339 int op;
4340 int nregs;
4341 int interleave;
4342 int spacing;
4343 int stride;
4344 int size;
4345 int reg;
4346 int load;
4347 int n;
4348 int vec_size;
4349 int mmu_idx;
4350 TCGMemOp endian;
4351 TCGv_i32 addr;
4352 TCGv_i32 tmp;
4353 TCGv_i32 tmp2;
4354 TCGv_i64 tmp64;
4356 /* FIXME: this access check should not take precedence over UNDEF
4357 * for invalid encodings; we will generate incorrect syndrome information
4358 * for attempts to execute invalid vfp/neon encodings with FP disabled.
4360 if (s->fp_excp_el) {
4361 gen_exception_insn(s, 4, EXCP_UDEF,
4362 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
4363 return 0;
4366 if (!s->vfp_enabled)
4367 return 1;
4368 VFP_DREG_D(rd, insn);
4369 rn = (insn >> 16) & 0xf;
4370 rm = insn & 0xf;
4371 load = (insn & (1 << 21)) != 0;
4372 endian = s->be_data;
4373 mmu_idx = get_mem_index(s);
4374 if ((insn & (1 << 23)) == 0) {
4375 /* Load store all elements. */
4376 op = (insn >> 8) & 0xf;
4377 size = (insn >> 6) & 3;
4378 if (op > 10)
4379 return 1;
4380 /* Catch UNDEF cases for bad values of align field */
4381 switch (op & 0xc) {
4382 case 4:
4383 if (((insn >> 5) & 1) == 1) {
4384 return 1;
4386 break;
4387 case 8:
4388 if (((insn >> 4) & 3) == 3) {
4389 return 1;
4391 break;
4392 default:
4393 break;
4395 nregs = neon_ls_element_type[op].nregs;
4396 interleave = neon_ls_element_type[op].interleave;
4397 spacing = neon_ls_element_type[op].spacing;
4398 if (size == 3 && (interleave | spacing) != 1) {
4399 return 1;
4401 /* For our purposes, bytes are always little-endian. */
4402 if (size == 0) {
4403 endian = MO_LE;
4405 /* Consecutive little-endian elements from a single register
4406 * can be promoted to a larger little-endian operation.
4408 if (interleave == 1 && endian == MO_LE) {
4409 size = 3;
4411 tmp64 = tcg_temp_new_i64();
4412 addr = tcg_temp_new_i32();
4413 tmp2 = tcg_const_i32(1 << size);
4414 load_reg_var(s, addr, rn);
4415 for (reg = 0; reg < nregs; reg++) {
4416 for (n = 0; n < 8 >> size; n++) {
4417 int xs;
4418 for (xs = 0; xs < interleave; xs++) {
4419 int tt = rd + reg + spacing * xs;
4421 if (load) {
4422 gen_aa32_ld_i64(s, tmp64, addr, mmu_idx, endian | size);
4423 neon_store_element64(tt, n, size, tmp64);
4424 } else {
4425 neon_load_element64(tmp64, tt, n, size);
4426 gen_aa32_st_i64(s, tmp64, addr, mmu_idx, endian | size);
4428 tcg_gen_add_i32(addr, addr, tmp2);
4432 tcg_temp_free_i32(addr);
4433 tcg_temp_free_i32(tmp2);
4434 tcg_temp_free_i64(tmp64);
4435 stride = nregs * interleave * 8;
4436 } else {
4437 size = (insn >> 10) & 3;
4438 if (size == 3) {
4439 /* Load single element to all lanes. */
4440 int a = (insn >> 4) & 1;
4441 if (!load) {
4442 return 1;
4444 size = (insn >> 6) & 3;
4445 nregs = ((insn >> 8) & 3) + 1;
4447 if (size == 3) {
4448 if (nregs != 4 || a == 0) {
4449 return 1;
4451 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
4452 size = 2;
4454 if (nregs == 1 && a == 1 && size == 0) {
4455 return 1;
4457 if (nregs == 3 && a == 1) {
4458 return 1;
4460 addr = tcg_temp_new_i32();
4461 load_reg_var(s, addr, rn);
4463 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write.
4464 * VLD2/3/4 to all lanes: bit 5 indicates register stride.
4466 stride = (insn & (1 << 5)) ? 2 : 1;
4467 vec_size = nregs == 1 ? stride * 8 : 8;
4469 tmp = tcg_temp_new_i32();
4470 for (reg = 0; reg < nregs; reg++) {
4471 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
4472 s->be_data | size);
4473 if ((rd & 1) && vec_size == 16) {
4474 /* We cannot write 16 bytes at once because the
4475 * destination is unaligned.
4477 tcg_gen_gvec_dup_i32(size, neon_reg_offset(rd, 0),
4478 8, 8, tmp);
4479 tcg_gen_gvec_mov(0, neon_reg_offset(rd + 1, 0),
4480 neon_reg_offset(rd, 0), 8, 8);
4481 } else {
4482 tcg_gen_gvec_dup_i32(size, neon_reg_offset(rd, 0),
4483 vec_size, vec_size, tmp);
4485 tcg_gen_addi_i32(addr, addr, 1 << size);
4486 rd += stride;
4488 tcg_temp_free_i32(tmp);
4489 tcg_temp_free_i32(addr);
4490 stride = (1 << size) * nregs;
4491 } else {
4492 /* Single element. */
4493 int idx = (insn >> 4) & 0xf;
4494 int reg_idx;
4495 switch (size) {
4496 case 0:
4497 reg_idx = (insn >> 5) & 7;
4498 stride = 1;
4499 break;
4500 case 1:
4501 reg_idx = (insn >> 6) & 3;
4502 stride = (insn & (1 << 5)) ? 2 : 1;
4503 break;
4504 case 2:
4505 reg_idx = (insn >> 7) & 1;
4506 stride = (insn & (1 << 6)) ? 2 : 1;
4507 break;
4508 default:
4509 abort();
4511 nregs = ((insn >> 8) & 3) + 1;
4512 /* Catch the UNDEF cases. This is unavoidably a bit messy. */
4513 switch (nregs) {
4514 case 1:
4515 if (((idx & (1 << size)) != 0) ||
4516 (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
4517 return 1;
4519 break;
4520 case 3:
4521 if ((idx & 1) != 0) {
4522 return 1;
4524 /* fall through */
4525 case 2:
4526 if (size == 2 && (idx & 2) != 0) {
4527 return 1;
4529 break;
4530 case 4:
4531 if ((size == 2) && ((idx & 3) == 3)) {
4532 return 1;
4534 break;
4535 default:
4536 abort();
4538 if ((rd + stride * (nregs - 1)) > 31) {
4539 /* Attempts to write off the end of the register file
4540 * are UNPREDICTABLE; we choose to UNDEF because otherwise
4541 * the neon_load_reg() would write off the end of the array.
4543 return 1;
4545 tmp = tcg_temp_new_i32();
4546 addr = tcg_temp_new_i32();
4547 load_reg_var(s, addr, rn);
4548 for (reg = 0; reg < nregs; reg++) {
4549 if (load) {
4550 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
4551 s->be_data | size);
4552 neon_store_element(rd, reg_idx, size, tmp);
4553 } else { /* Store */
4554 neon_load_element(tmp, rd, reg_idx, size);
4555 gen_aa32_st_i32(s, tmp, addr, get_mem_index(s),
4556 s->be_data | size);
4558 rd += stride;
4559 tcg_gen_addi_i32(addr, addr, 1 << size);
4561 tcg_temp_free_i32(addr);
4562 tcg_temp_free_i32(tmp);
4563 stride = nregs * (1 << size);
4566 if (rm != 15) {
4567 TCGv_i32 base;
4569 base = load_reg(s, rn);
4570 if (rm == 13) {
4571 tcg_gen_addi_i32(base, base, stride);
4572 } else {
4573 TCGv_i32 index;
4574 index = load_reg(s, rm);
4575 tcg_gen_add_i32(base, base, index);
4576 tcg_temp_free_i32(index);
4578 store_reg(s, rn, base);
4580 return 0;
4583 static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src)
4585 switch (size) {
4586 case 0: gen_helper_neon_narrow_u8(dest, src); break;
4587 case 1: gen_helper_neon_narrow_u16(dest, src); break;
4588 case 2: tcg_gen_extrl_i64_i32(dest, src); break;
4589 default: abort();
4593 static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
4595 switch (size) {
4596 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
4597 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
4598 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
4599 default: abort();
4603 static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src)
4605 switch (size) {
4606 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
4607 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
4608 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
4609 default: abort();
4613 static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
4615 switch (size) {
4616 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
4617 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
4618 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
4619 default: abort();
4623 static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift,
4624 int q, int u)
4626 if (q) {
4627 if (u) {
4628 switch (size) {
4629 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4630 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4631 default: abort();
4633 } else {
4634 switch (size) {
4635 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
4636 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
4637 default: abort();
4640 } else {
4641 if (u) {
4642 switch (size) {
4643 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
4644 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
4645 default: abort();
4647 } else {
4648 switch (size) {
4649 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
4650 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
4651 default: abort();
4657 static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
4659 if (u) {
4660 switch (size) {
4661 case 0: gen_helper_neon_widen_u8(dest, src); break;
4662 case 1: gen_helper_neon_widen_u16(dest, src); break;
4663 case 2: tcg_gen_extu_i32_i64(dest, src); break;
4664 default: abort();
4666 } else {
4667 switch (size) {
4668 case 0: gen_helper_neon_widen_s8(dest, src); break;
4669 case 1: gen_helper_neon_widen_s16(dest, src); break;
4670 case 2: tcg_gen_ext_i32_i64(dest, src); break;
4671 default: abort();
4674 tcg_temp_free_i32(src);
4677 static inline void gen_neon_addl(int size)
4679 switch (size) {
4680 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4681 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4682 case 2: tcg_gen_add_i64(CPU_V001); break;
4683 default: abort();
4687 static inline void gen_neon_subl(int size)
4689 switch (size) {
4690 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4691 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4692 case 2: tcg_gen_sub_i64(CPU_V001); break;
4693 default: abort();
4697 static inline void gen_neon_negl(TCGv_i64 var, int size)
4699 switch (size) {
4700 case 0: gen_helper_neon_negl_u16(var, var); break;
4701 case 1: gen_helper_neon_negl_u32(var, var); break;
4702 case 2:
4703 tcg_gen_neg_i64(var, var);
4704 break;
4705 default: abort();
4709 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4711 switch (size) {
4712 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4713 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4714 default: abort();
4718 static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b,
4719 int size, int u)
4721 TCGv_i64 tmp;
4723 switch ((size << 1) | u) {
4724 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4725 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4726 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4727 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4728 case 4:
4729 tmp = gen_muls_i64_i32(a, b);
4730 tcg_gen_mov_i64(dest, tmp);
4731 tcg_temp_free_i64(tmp);
4732 break;
4733 case 5:
4734 tmp = gen_mulu_i64_i32(a, b);
4735 tcg_gen_mov_i64(dest, tmp);
4736 tcg_temp_free_i64(tmp);
4737 break;
4738 default: abort();
4741 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
4742 Don't forget to clean them now. */
4743 if (size < 2) {
4744 tcg_temp_free_i32(a);
4745 tcg_temp_free_i32(b);
4749 static void gen_neon_narrow_op(int op, int u, int size,
4750 TCGv_i32 dest, TCGv_i64 src)
4752 if (op) {
4753 if (u) {
4754 gen_neon_unarrow_sats(size, dest, src);
4755 } else {
4756 gen_neon_narrow(size, dest, src);
4758 } else {
4759 if (u) {
4760 gen_neon_narrow_satu(size, dest, src);
4761 } else {
4762 gen_neon_narrow_sats(size, dest, src);
4767 /* Symbolic constants for op fields for Neon 3-register same-length.
4768 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
4769 * table A7-9.
4771 #define NEON_3R_VHADD 0
4772 #define NEON_3R_VQADD 1
4773 #define NEON_3R_VRHADD 2
4774 #define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
4775 #define NEON_3R_VHSUB 4
4776 #define NEON_3R_VQSUB 5
4777 #define NEON_3R_VCGT 6
4778 #define NEON_3R_VCGE 7
4779 #define NEON_3R_VSHL 8
4780 #define NEON_3R_VQSHL 9
4781 #define NEON_3R_VRSHL 10
4782 #define NEON_3R_VQRSHL 11
4783 #define NEON_3R_VMAX 12
4784 #define NEON_3R_VMIN 13
4785 #define NEON_3R_VABD 14
4786 #define NEON_3R_VABA 15
4787 #define NEON_3R_VADD_VSUB 16
4788 #define NEON_3R_VTST_VCEQ 17
4789 #define NEON_3R_VML 18 /* VMLA, VMLS */
4790 #define NEON_3R_VMUL 19
4791 #define NEON_3R_VPMAX 20
4792 #define NEON_3R_VPMIN 21
4793 #define NEON_3R_VQDMULH_VQRDMULH 22
4794 #define NEON_3R_VPADD_VQRDMLAH 23
4795 #define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */
4796 #define NEON_3R_VFM_VQRDMLSH 25 /* VFMA, VFMS, VQRDMLSH */
4797 #define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
4798 #define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
4799 #define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
4800 #define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
4801 #define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
4802 #define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */
4804 static const uint8_t neon_3r_sizes[] = {
4805 [NEON_3R_VHADD] = 0x7,
4806 [NEON_3R_VQADD] = 0xf,
4807 [NEON_3R_VRHADD] = 0x7,
4808 [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
4809 [NEON_3R_VHSUB] = 0x7,
4810 [NEON_3R_VQSUB] = 0xf,
4811 [NEON_3R_VCGT] = 0x7,
4812 [NEON_3R_VCGE] = 0x7,
4813 [NEON_3R_VSHL] = 0xf,
4814 [NEON_3R_VQSHL] = 0xf,
4815 [NEON_3R_VRSHL] = 0xf,
4816 [NEON_3R_VQRSHL] = 0xf,
4817 [NEON_3R_VMAX] = 0x7,
4818 [NEON_3R_VMIN] = 0x7,
4819 [NEON_3R_VABD] = 0x7,
4820 [NEON_3R_VABA] = 0x7,
4821 [NEON_3R_VADD_VSUB] = 0xf,
4822 [NEON_3R_VTST_VCEQ] = 0x7,
4823 [NEON_3R_VML] = 0x7,
4824 [NEON_3R_VMUL] = 0x7,
4825 [NEON_3R_VPMAX] = 0x7,
4826 [NEON_3R_VPMIN] = 0x7,
4827 [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
4828 [NEON_3R_VPADD_VQRDMLAH] = 0x7,
4829 [NEON_3R_SHA] = 0xf, /* size field encodes op type */
4830 [NEON_3R_VFM_VQRDMLSH] = 0x7, /* For VFM, size bit 1 encodes op */
4831 [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
4832 [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
4833 [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
4834 [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
4835 [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
4836 [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */
4839 /* Symbolic constants for op fields for Neon 2-register miscellaneous.
4840 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
4841 * table A7-13.
4843 #define NEON_2RM_VREV64 0
4844 #define NEON_2RM_VREV32 1
4845 #define NEON_2RM_VREV16 2
4846 #define NEON_2RM_VPADDL 4
4847 #define NEON_2RM_VPADDL_U 5
4848 #define NEON_2RM_AESE 6 /* Includes AESD */
4849 #define NEON_2RM_AESMC 7 /* Includes AESIMC */
4850 #define NEON_2RM_VCLS 8
4851 #define NEON_2RM_VCLZ 9
4852 #define NEON_2RM_VCNT 10
4853 #define NEON_2RM_VMVN 11
4854 #define NEON_2RM_VPADAL 12
4855 #define NEON_2RM_VPADAL_U 13
4856 #define NEON_2RM_VQABS 14
4857 #define NEON_2RM_VQNEG 15
4858 #define NEON_2RM_VCGT0 16
4859 #define NEON_2RM_VCGE0 17
4860 #define NEON_2RM_VCEQ0 18
4861 #define NEON_2RM_VCLE0 19
4862 #define NEON_2RM_VCLT0 20
4863 #define NEON_2RM_SHA1H 21
4864 #define NEON_2RM_VABS 22
4865 #define NEON_2RM_VNEG 23
4866 #define NEON_2RM_VCGT0_F 24
4867 #define NEON_2RM_VCGE0_F 25
4868 #define NEON_2RM_VCEQ0_F 26
4869 #define NEON_2RM_VCLE0_F 27
4870 #define NEON_2RM_VCLT0_F 28
4871 #define NEON_2RM_VABS_F 30
4872 #define NEON_2RM_VNEG_F 31
4873 #define NEON_2RM_VSWP 32
4874 #define NEON_2RM_VTRN 33
4875 #define NEON_2RM_VUZP 34
4876 #define NEON_2RM_VZIP 35
4877 #define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
4878 #define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
4879 #define NEON_2RM_VSHLL 38
4880 #define NEON_2RM_SHA1SU1 39 /* Includes SHA256SU0 */
4881 #define NEON_2RM_VRINTN 40
4882 #define NEON_2RM_VRINTX 41
4883 #define NEON_2RM_VRINTA 42
4884 #define NEON_2RM_VRINTZ 43
4885 #define NEON_2RM_VCVT_F16_F32 44
4886 #define NEON_2RM_VRINTM 45
4887 #define NEON_2RM_VCVT_F32_F16 46
4888 #define NEON_2RM_VRINTP 47
4889 #define NEON_2RM_VCVTAU 48
4890 #define NEON_2RM_VCVTAS 49
4891 #define NEON_2RM_VCVTNU 50
4892 #define NEON_2RM_VCVTNS 51
4893 #define NEON_2RM_VCVTPU 52
4894 #define NEON_2RM_VCVTPS 53
4895 #define NEON_2RM_VCVTMU 54
4896 #define NEON_2RM_VCVTMS 55
4897 #define NEON_2RM_VRECPE 56
4898 #define NEON_2RM_VRSQRTE 57
4899 #define NEON_2RM_VRECPE_F 58
4900 #define NEON_2RM_VRSQRTE_F 59
4901 #define NEON_2RM_VCVT_FS 60
4902 #define NEON_2RM_VCVT_FU 61
4903 #define NEON_2RM_VCVT_SF 62
4904 #define NEON_2RM_VCVT_UF 63
4906 static int neon_2rm_is_float_op(int op)
4908 /* Return true if this neon 2reg-misc op is float-to-float */
4909 return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
4910 (op >= NEON_2RM_VRINTN && op <= NEON_2RM_VRINTZ) ||
4911 op == NEON_2RM_VRINTM ||
4912 (op >= NEON_2RM_VRINTP && op <= NEON_2RM_VCVTMS) ||
4913 op >= NEON_2RM_VRECPE_F);
4916 static bool neon_2rm_is_v8_op(int op)
4918 /* Return true if this neon 2reg-misc op is ARMv8 and up */
4919 switch (op) {
4920 case NEON_2RM_VRINTN:
4921 case NEON_2RM_VRINTA:
4922 case NEON_2RM_VRINTM:
4923 case NEON_2RM_VRINTP:
4924 case NEON_2RM_VRINTZ:
4925 case NEON_2RM_VRINTX:
4926 case NEON_2RM_VCVTAU:
4927 case NEON_2RM_VCVTAS:
4928 case NEON_2RM_VCVTNU:
4929 case NEON_2RM_VCVTNS:
4930 case NEON_2RM_VCVTPU:
4931 case NEON_2RM_VCVTPS:
4932 case NEON_2RM_VCVTMU:
4933 case NEON_2RM_VCVTMS:
4934 return true;
4935 default:
4936 return false;
4940 /* Each entry in this array has bit n set if the insn allows
4941 * size value n (otherwise it will UNDEF). Since unallocated
4942 * op values will have no bits set they always UNDEF.
4944 static const uint8_t neon_2rm_sizes[] = {
4945 [NEON_2RM_VREV64] = 0x7,
4946 [NEON_2RM_VREV32] = 0x3,
4947 [NEON_2RM_VREV16] = 0x1,
4948 [NEON_2RM_VPADDL] = 0x7,
4949 [NEON_2RM_VPADDL_U] = 0x7,
4950 [NEON_2RM_AESE] = 0x1,
4951 [NEON_2RM_AESMC] = 0x1,
4952 [NEON_2RM_VCLS] = 0x7,
4953 [NEON_2RM_VCLZ] = 0x7,
4954 [NEON_2RM_VCNT] = 0x1,
4955 [NEON_2RM_VMVN] = 0x1,
4956 [NEON_2RM_VPADAL] = 0x7,
4957 [NEON_2RM_VPADAL_U] = 0x7,
4958 [NEON_2RM_VQABS] = 0x7,
4959 [NEON_2RM_VQNEG] = 0x7,
4960 [NEON_2RM_VCGT0] = 0x7,
4961 [NEON_2RM_VCGE0] = 0x7,
4962 [NEON_2RM_VCEQ0] = 0x7,
4963 [NEON_2RM_VCLE0] = 0x7,
4964 [NEON_2RM_VCLT0] = 0x7,
4965 [NEON_2RM_SHA1H] = 0x4,
4966 [NEON_2RM_VABS] = 0x7,
4967 [NEON_2RM_VNEG] = 0x7,
4968 [NEON_2RM_VCGT0_F] = 0x4,
4969 [NEON_2RM_VCGE0_F] = 0x4,
4970 [NEON_2RM_VCEQ0_F] = 0x4,
4971 [NEON_2RM_VCLE0_F] = 0x4,
4972 [NEON_2RM_VCLT0_F] = 0x4,
4973 [NEON_2RM_VABS_F] = 0x4,
4974 [NEON_2RM_VNEG_F] = 0x4,
4975 [NEON_2RM_VSWP] = 0x1,
4976 [NEON_2RM_VTRN] = 0x7,
4977 [NEON_2RM_VUZP] = 0x7,
4978 [NEON_2RM_VZIP] = 0x7,
4979 [NEON_2RM_VMOVN] = 0x7,
4980 [NEON_2RM_VQMOVN] = 0x7,
4981 [NEON_2RM_VSHLL] = 0x7,
4982 [NEON_2RM_SHA1SU1] = 0x4,
4983 [NEON_2RM_VRINTN] = 0x4,
4984 [NEON_2RM_VRINTX] = 0x4,
4985 [NEON_2RM_VRINTA] = 0x4,
4986 [NEON_2RM_VRINTZ] = 0x4,
4987 [NEON_2RM_VCVT_F16_F32] = 0x2,
4988 [NEON_2RM_VRINTM] = 0x4,
4989 [NEON_2RM_VCVT_F32_F16] = 0x2,
4990 [NEON_2RM_VRINTP] = 0x4,
4991 [NEON_2RM_VCVTAU] = 0x4,
4992 [NEON_2RM_VCVTAS] = 0x4,
4993 [NEON_2RM_VCVTNU] = 0x4,
4994 [NEON_2RM_VCVTNS] = 0x4,
4995 [NEON_2RM_VCVTPU] = 0x4,
4996 [NEON_2RM_VCVTPS] = 0x4,
4997 [NEON_2RM_VCVTMU] = 0x4,
4998 [NEON_2RM_VCVTMS] = 0x4,
4999 [NEON_2RM_VRECPE] = 0x4,
5000 [NEON_2RM_VRSQRTE] = 0x4,
5001 [NEON_2RM_VRECPE_F] = 0x4,
5002 [NEON_2RM_VRSQRTE_F] = 0x4,
5003 [NEON_2RM_VCVT_FS] = 0x4,
5004 [NEON_2RM_VCVT_FU] = 0x4,
5005 [NEON_2RM_VCVT_SF] = 0x4,
5006 [NEON_2RM_VCVT_UF] = 0x4,
5010 /* Expand v8.1 simd helper. */
5011 static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
5012 int q, int rd, int rn, int rm)
5014 if (dc_isar_feature(aa32_rdm, s)) {
5015 int opr_sz = (1 + q) * 8;
5016 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
5017 vfp_reg_offset(1, rn),
5018 vfp_reg_offset(1, rm), cpu_env,
5019 opr_sz, opr_sz, 0, fn);
5020 return 0;
5022 return 1;
5025 static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5027 tcg_gen_vec_sar8i_i64(a, a, shift);
5028 tcg_gen_vec_add8_i64(d, d, a);
5031 static void gen_ssra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5033 tcg_gen_vec_sar16i_i64(a, a, shift);
5034 tcg_gen_vec_add16_i64(d, d, a);
5037 static void gen_ssra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
5039 tcg_gen_sari_i32(a, a, shift);
5040 tcg_gen_add_i32(d, d, a);
5043 static void gen_ssra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5045 tcg_gen_sari_i64(a, a, shift);
5046 tcg_gen_add_i64(d, d, a);
5049 static void gen_ssra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
5051 tcg_gen_sari_vec(vece, a, a, sh);
5052 tcg_gen_add_vec(vece, d, d, a);
5055 static const TCGOpcode vecop_list_ssra[] = {
5056 INDEX_op_sari_vec, INDEX_op_add_vec, 0
5059 const GVecGen2i ssra_op[4] = {
5060 { .fni8 = gen_ssra8_i64,
5061 .fniv = gen_ssra_vec,
5062 .load_dest = true,
5063 .opt_opc = vecop_list_ssra,
5064 .vece = MO_8 },
5065 { .fni8 = gen_ssra16_i64,
5066 .fniv = gen_ssra_vec,
5067 .load_dest = true,
5068 .opt_opc = vecop_list_ssra,
5069 .vece = MO_16 },
5070 { .fni4 = gen_ssra32_i32,
5071 .fniv = gen_ssra_vec,
5072 .load_dest = true,
5073 .opt_opc = vecop_list_ssra,
5074 .vece = MO_32 },
5075 { .fni8 = gen_ssra64_i64,
5076 .fniv = gen_ssra_vec,
5077 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5078 .opt_opc = vecop_list_ssra,
5079 .load_dest = true,
5080 .vece = MO_64 },
5083 static void gen_usra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5085 tcg_gen_vec_shr8i_i64(a, a, shift);
5086 tcg_gen_vec_add8_i64(d, d, a);
5089 static void gen_usra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5091 tcg_gen_vec_shr16i_i64(a, a, shift);
5092 tcg_gen_vec_add16_i64(d, d, a);
5095 static void gen_usra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
5097 tcg_gen_shri_i32(a, a, shift);
5098 tcg_gen_add_i32(d, d, a);
5101 static void gen_usra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5103 tcg_gen_shri_i64(a, a, shift);
5104 tcg_gen_add_i64(d, d, a);
5107 static void gen_usra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
5109 tcg_gen_shri_vec(vece, a, a, sh);
5110 tcg_gen_add_vec(vece, d, d, a);
5113 static const TCGOpcode vecop_list_usra[] = {
5114 INDEX_op_shri_vec, INDEX_op_add_vec, 0
5117 const GVecGen2i usra_op[4] = {
5118 { .fni8 = gen_usra8_i64,
5119 .fniv = gen_usra_vec,
5120 .load_dest = true,
5121 .opt_opc = vecop_list_usra,
5122 .vece = MO_8, },
5123 { .fni8 = gen_usra16_i64,
5124 .fniv = gen_usra_vec,
5125 .load_dest = true,
5126 .opt_opc = vecop_list_usra,
5127 .vece = MO_16, },
5128 { .fni4 = gen_usra32_i32,
5129 .fniv = gen_usra_vec,
5130 .load_dest = true,
5131 .opt_opc = vecop_list_usra,
5132 .vece = MO_32, },
5133 { .fni8 = gen_usra64_i64,
5134 .fniv = gen_usra_vec,
5135 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5136 .load_dest = true,
5137 .opt_opc = vecop_list_usra,
5138 .vece = MO_64, },
5141 static void gen_shr8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5143 uint64_t mask = dup_const(MO_8, 0xff >> shift);
5144 TCGv_i64 t = tcg_temp_new_i64();
5146 tcg_gen_shri_i64(t, a, shift);
5147 tcg_gen_andi_i64(t, t, mask);
5148 tcg_gen_andi_i64(d, d, ~mask);
5149 tcg_gen_or_i64(d, d, t);
5150 tcg_temp_free_i64(t);
5153 static void gen_shr16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5155 uint64_t mask = dup_const(MO_16, 0xffff >> shift);
5156 TCGv_i64 t = tcg_temp_new_i64();
5158 tcg_gen_shri_i64(t, a, shift);
5159 tcg_gen_andi_i64(t, t, mask);
5160 tcg_gen_andi_i64(d, d, ~mask);
5161 tcg_gen_or_i64(d, d, t);
5162 tcg_temp_free_i64(t);
5165 static void gen_shr32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
5167 tcg_gen_shri_i32(a, a, shift);
5168 tcg_gen_deposit_i32(d, d, a, 0, 32 - shift);
5171 static void gen_shr64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5173 tcg_gen_shri_i64(a, a, shift);
5174 tcg_gen_deposit_i64(d, d, a, 0, 64 - shift);
5177 static void gen_shr_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
5179 if (sh == 0) {
5180 tcg_gen_mov_vec(d, a);
5181 } else {
5182 TCGv_vec t = tcg_temp_new_vec_matching(d);
5183 TCGv_vec m = tcg_temp_new_vec_matching(d);
5185 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK((8 << vece) - sh, sh));
5186 tcg_gen_shri_vec(vece, t, a, sh);
5187 tcg_gen_and_vec(vece, d, d, m);
5188 tcg_gen_or_vec(vece, d, d, t);
5190 tcg_temp_free_vec(t);
5191 tcg_temp_free_vec(m);
5195 static const TCGOpcode vecop_list_sri[] = { INDEX_op_shri_vec, 0 };
5197 const GVecGen2i sri_op[4] = {
5198 { .fni8 = gen_shr8_ins_i64,
5199 .fniv = gen_shr_ins_vec,
5200 .load_dest = true,
5201 .opt_opc = vecop_list_sri,
5202 .vece = MO_8 },
5203 { .fni8 = gen_shr16_ins_i64,
5204 .fniv = gen_shr_ins_vec,
5205 .load_dest = true,
5206 .opt_opc = vecop_list_sri,
5207 .vece = MO_16 },
5208 { .fni4 = gen_shr32_ins_i32,
5209 .fniv = gen_shr_ins_vec,
5210 .load_dest = true,
5211 .opt_opc = vecop_list_sri,
5212 .vece = MO_32 },
5213 { .fni8 = gen_shr64_ins_i64,
5214 .fniv = gen_shr_ins_vec,
5215 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5216 .load_dest = true,
5217 .opt_opc = vecop_list_sri,
5218 .vece = MO_64 },
5221 static void gen_shl8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5223 uint64_t mask = dup_const(MO_8, 0xff << shift);
5224 TCGv_i64 t = tcg_temp_new_i64();
5226 tcg_gen_shli_i64(t, a, shift);
5227 tcg_gen_andi_i64(t, t, mask);
5228 tcg_gen_andi_i64(d, d, ~mask);
5229 tcg_gen_or_i64(d, d, t);
5230 tcg_temp_free_i64(t);
5233 static void gen_shl16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5235 uint64_t mask = dup_const(MO_16, 0xffff << shift);
5236 TCGv_i64 t = tcg_temp_new_i64();
5238 tcg_gen_shli_i64(t, a, shift);
5239 tcg_gen_andi_i64(t, t, mask);
5240 tcg_gen_andi_i64(d, d, ~mask);
5241 tcg_gen_or_i64(d, d, t);
5242 tcg_temp_free_i64(t);
5245 static void gen_shl32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
5247 tcg_gen_deposit_i32(d, d, a, shift, 32 - shift);
5250 static void gen_shl64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5252 tcg_gen_deposit_i64(d, d, a, shift, 64 - shift);
5255 static void gen_shl_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
5257 if (sh == 0) {
5258 tcg_gen_mov_vec(d, a);
5259 } else {
5260 TCGv_vec t = tcg_temp_new_vec_matching(d);
5261 TCGv_vec m = tcg_temp_new_vec_matching(d);
5263 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK(0, sh));
5264 tcg_gen_shli_vec(vece, t, a, sh);
5265 tcg_gen_and_vec(vece, d, d, m);
5266 tcg_gen_or_vec(vece, d, d, t);
5268 tcg_temp_free_vec(t);
5269 tcg_temp_free_vec(m);
5273 static const TCGOpcode vecop_list_sli[] = { INDEX_op_shli_vec, 0 };
5275 const GVecGen2i sli_op[4] = {
5276 { .fni8 = gen_shl8_ins_i64,
5277 .fniv = gen_shl_ins_vec,
5278 .load_dest = true,
5279 .opt_opc = vecop_list_sli,
5280 .vece = MO_8 },
5281 { .fni8 = gen_shl16_ins_i64,
5282 .fniv = gen_shl_ins_vec,
5283 .load_dest = true,
5284 .opt_opc = vecop_list_sli,
5285 .vece = MO_16 },
5286 { .fni4 = gen_shl32_ins_i32,
5287 .fniv = gen_shl_ins_vec,
5288 .load_dest = true,
5289 .opt_opc = vecop_list_sli,
5290 .vece = MO_32 },
5291 { .fni8 = gen_shl64_ins_i64,
5292 .fniv = gen_shl_ins_vec,
5293 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5294 .load_dest = true,
5295 .opt_opc = vecop_list_sli,
5296 .vece = MO_64 },
5299 static void gen_mla8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
5301 gen_helper_neon_mul_u8(a, a, b);
5302 gen_helper_neon_add_u8(d, d, a);
5305 static void gen_mls8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
5307 gen_helper_neon_mul_u8(a, a, b);
5308 gen_helper_neon_sub_u8(d, d, a);
5311 static void gen_mla16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
5313 gen_helper_neon_mul_u16(a, a, b);
5314 gen_helper_neon_add_u16(d, d, a);
5317 static void gen_mls16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
5319 gen_helper_neon_mul_u16(a, a, b);
5320 gen_helper_neon_sub_u16(d, d, a);
5323 static void gen_mla32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
5325 tcg_gen_mul_i32(a, a, b);
5326 tcg_gen_add_i32(d, d, a);
5329 static void gen_mls32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
5331 tcg_gen_mul_i32(a, a, b);
5332 tcg_gen_sub_i32(d, d, a);
5335 static void gen_mla64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
5337 tcg_gen_mul_i64(a, a, b);
5338 tcg_gen_add_i64(d, d, a);
5341 static void gen_mls64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
5343 tcg_gen_mul_i64(a, a, b);
5344 tcg_gen_sub_i64(d, d, a);
5347 static void gen_mla_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
5349 tcg_gen_mul_vec(vece, a, a, b);
5350 tcg_gen_add_vec(vece, d, d, a);
5353 static void gen_mls_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
5355 tcg_gen_mul_vec(vece, a, a, b);
5356 tcg_gen_sub_vec(vece, d, d, a);
5359 /* Note that while NEON does not support VMLA and VMLS as 64-bit ops,
5360 * these tables are shared with AArch64 which does support them.
5363 static const TCGOpcode vecop_list_mla[] = {
5364 INDEX_op_mul_vec, INDEX_op_add_vec, 0
5367 static const TCGOpcode vecop_list_mls[] = {
5368 INDEX_op_mul_vec, INDEX_op_sub_vec, 0
5371 const GVecGen3 mla_op[4] = {
5372 { .fni4 = gen_mla8_i32,
5373 .fniv = gen_mla_vec,
5374 .load_dest = true,
5375 .opt_opc = vecop_list_mla,
5376 .vece = MO_8 },
5377 { .fni4 = gen_mla16_i32,
5378 .fniv = gen_mla_vec,
5379 .load_dest = true,
5380 .opt_opc = vecop_list_mla,
5381 .vece = MO_16 },
5382 { .fni4 = gen_mla32_i32,
5383 .fniv = gen_mla_vec,
5384 .load_dest = true,
5385 .opt_opc = vecop_list_mla,
5386 .vece = MO_32 },
5387 { .fni8 = gen_mla64_i64,
5388 .fniv = gen_mla_vec,
5389 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5390 .load_dest = true,
5391 .opt_opc = vecop_list_mla,
5392 .vece = MO_64 },
5395 const GVecGen3 mls_op[4] = {
5396 { .fni4 = gen_mls8_i32,
5397 .fniv = gen_mls_vec,
5398 .load_dest = true,
5399 .opt_opc = vecop_list_mls,
5400 .vece = MO_8 },
5401 { .fni4 = gen_mls16_i32,
5402 .fniv = gen_mls_vec,
5403 .load_dest = true,
5404 .opt_opc = vecop_list_mls,
5405 .vece = MO_16 },
5406 { .fni4 = gen_mls32_i32,
5407 .fniv = gen_mls_vec,
5408 .load_dest = true,
5409 .opt_opc = vecop_list_mls,
5410 .vece = MO_32 },
5411 { .fni8 = gen_mls64_i64,
5412 .fniv = gen_mls_vec,
5413 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5414 .load_dest = true,
5415 .opt_opc = vecop_list_mls,
5416 .vece = MO_64 },
5419 /* CMTST : test is "if (X & Y != 0)". */
5420 static void gen_cmtst_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
5422 tcg_gen_and_i32(d, a, b);
5423 tcg_gen_setcondi_i32(TCG_COND_NE, d, d, 0);
5424 tcg_gen_neg_i32(d, d);
5427 void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
5429 tcg_gen_and_i64(d, a, b);
5430 tcg_gen_setcondi_i64(TCG_COND_NE, d, d, 0);
5431 tcg_gen_neg_i64(d, d);
5434 static void gen_cmtst_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
5436 tcg_gen_and_vec(vece, d, a, b);
5437 tcg_gen_dupi_vec(vece, a, 0);
5438 tcg_gen_cmp_vec(TCG_COND_NE, vece, d, d, a);
5441 static const TCGOpcode vecop_list_cmtst[] = { INDEX_op_cmp_vec, 0 };
5443 const GVecGen3 cmtst_op[4] = {
5444 { .fni4 = gen_helper_neon_tst_u8,
5445 .fniv = gen_cmtst_vec,
5446 .opt_opc = vecop_list_cmtst,
5447 .vece = MO_8 },
5448 { .fni4 = gen_helper_neon_tst_u16,
5449 .fniv = gen_cmtst_vec,
5450 .opt_opc = vecop_list_cmtst,
5451 .vece = MO_16 },
5452 { .fni4 = gen_cmtst_i32,
5453 .fniv = gen_cmtst_vec,
5454 .opt_opc = vecop_list_cmtst,
5455 .vece = MO_32 },
5456 { .fni8 = gen_cmtst_i64,
5457 .fniv = gen_cmtst_vec,
5458 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5459 .opt_opc = vecop_list_cmtst,
5460 .vece = MO_64 },
5463 static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
5464 TCGv_vec a, TCGv_vec b)
5466 TCGv_vec x = tcg_temp_new_vec_matching(t);
5467 tcg_gen_add_vec(vece, x, a, b);
5468 tcg_gen_usadd_vec(vece, t, a, b);
5469 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
5470 tcg_gen_or_vec(vece, sat, sat, x);
5471 tcg_temp_free_vec(x);
5474 static const TCGOpcode vecop_list_uqadd[] = {
5475 INDEX_op_usadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
5478 const GVecGen4 uqadd_op[4] = {
5479 { .fniv = gen_uqadd_vec,
5480 .fno = gen_helper_gvec_uqadd_b,
5481 .write_aofs = true,
5482 .opt_opc = vecop_list_uqadd,
5483 .vece = MO_8 },
5484 { .fniv = gen_uqadd_vec,
5485 .fno = gen_helper_gvec_uqadd_h,
5486 .write_aofs = true,
5487 .opt_opc = vecop_list_uqadd,
5488 .vece = MO_16 },
5489 { .fniv = gen_uqadd_vec,
5490 .fno = gen_helper_gvec_uqadd_s,
5491 .write_aofs = true,
5492 .opt_opc = vecop_list_uqadd,
5493 .vece = MO_32 },
5494 { .fniv = gen_uqadd_vec,
5495 .fno = gen_helper_gvec_uqadd_d,
5496 .write_aofs = true,
5497 .opt_opc = vecop_list_uqadd,
5498 .vece = MO_64 },
5501 static void gen_sqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
5502 TCGv_vec a, TCGv_vec b)
5504 TCGv_vec x = tcg_temp_new_vec_matching(t);
5505 tcg_gen_add_vec(vece, x, a, b);
5506 tcg_gen_ssadd_vec(vece, t, a, b);
5507 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
5508 tcg_gen_or_vec(vece, sat, sat, x);
5509 tcg_temp_free_vec(x);
5512 static const TCGOpcode vecop_list_sqadd[] = {
5513 INDEX_op_ssadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
5516 const GVecGen4 sqadd_op[4] = {
5517 { .fniv = gen_sqadd_vec,
5518 .fno = gen_helper_gvec_sqadd_b,
5519 .opt_opc = vecop_list_sqadd,
5520 .write_aofs = true,
5521 .vece = MO_8 },
5522 { .fniv = gen_sqadd_vec,
5523 .fno = gen_helper_gvec_sqadd_h,
5524 .opt_opc = vecop_list_sqadd,
5525 .write_aofs = true,
5526 .vece = MO_16 },
5527 { .fniv = gen_sqadd_vec,
5528 .fno = gen_helper_gvec_sqadd_s,
5529 .opt_opc = vecop_list_sqadd,
5530 .write_aofs = true,
5531 .vece = MO_32 },
5532 { .fniv = gen_sqadd_vec,
5533 .fno = gen_helper_gvec_sqadd_d,
5534 .opt_opc = vecop_list_sqadd,
5535 .write_aofs = true,
5536 .vece = MO_64 },
5539 static void gen_uqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
5540 TCGv_vec a, TCGv_vec b)
5542 TCGv_vec x = tcg_temp_new_vec_matching(t);
5543 tcg_gen_sub_vec(vece, x, a, b);
5544 tcg_gen_ussub_vec(vece, t, a, b);
5545 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
5546 tcg_gen_or_vec(vece, sat, sat, x);
5547 tcg_temp_free_vec(x);
5550 static const TCGOpcode vecop_list_uqsub[] = {
5551 INDEX_op_ussub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
5554 const GVecGen4 uqsub_op[4] = {
5555 { .fniv = gen_uqsub_vec,
5556 .fno = gen_helper_gvec_uqsub_b,
5557 .opt_opc = vecop_list_uqsub,
5558 .write_aofs = true,
5559 .vece = MO_8 },
5560 { .fniv = gen_uqsub_vec,
5561 .fno = gen_helper_gvec_uqsub_h,
5562 .opt_opc = vecop_list_uqsub,
5563 .write_aofs = true,
5564 .vece = MO_16 },
5565 { .fniv = gen_uqsub_vec,
5566 .fno = gen_helper_gvec_uqsub_s,
5567 .opt_opc = vecop_list_uqsub,
5568 .write_aofs = true,
5569 .vece = MO_32 },
5570 { .fniv = gen_uqsub_vec,
5571 .fno = gen_helper_gvec_uqsub_d,
5572 .opt_opc = vecop_list_uqsub,
5573 .write_aofs = true,
5574 .vece = MO_64 },
5577 static void gen_sqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
5578 TCGv_vec a, TCGv_vec b)
5580 TCGv_vec x = tcg_temp_new_vec_matching(t);
5581 tcg_gen_sub_vec(vece, x, a, b);
5582 tcg_gen_sssub_vec(vece, t, a, b);
5583 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
5584 tcg_gen_or_vec(vece, sat, sat, x);
5585 tcg_temp_free_vec(x);
5588 static const TCGOpcode vecop_list_sqsub[] = {
5589 INDEX_op_sssub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
5592 const GVecGen4 sqsub_op[4] = {
5593 { .fniv = gen_sqsub_vec,
5594 .fno = gen_helper_gvec_sqsub_b,
5595 .opt_opc = vecop_list_sqsub,
5596 .write_aofs = true,
5597 .vece = MO_8 },
5598 { .fniv = gen_sqsub_vec,
5599 .fno = gen_helper_gvec_sqsub_h,
5600 .opt_opc = vecop_list_sqsub,
5601 .write_aofs = true,
5602 .vece = MO_16 },
5603 { .fniv = gen_sqsub_vec,
5604 .fno = gen_helper_gvec_sqsub_s,
5605 .opt_opc = vecop_list_sqsub,
5606 .write_aofs = true,
5607 .vece = MO_32 },
5608 { .fniv = gen_sqsub_vec,
5609 .fno = gen_helper_gvec_sqsub_d,
5610 .opt_opc = vecop_list_sqsub,
5611 .write_aofs = true,
5612 .vece = MO_64 },
5615 /* Translate a NEON data processing instruction. Return nonzero if the
5616 instruction is invalid.
5617 We process data in a mixture of 32-bit and 64-bit chunks.
5618 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
5620 static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
5622 int op;
5623 int q;
5624 int rd, rn, rm, rd_ofs, rn_ofs, rm_ofs;
5625 int size;
5626 int shift;
5627 int pass;
5628 int count;
5629 int pairwise;
5630 int u;
5631 int vec_size;
5632 uint32_t imm;
5633 TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
5634 TCGv_ptr ptr1, ptr2, ptr3;
5635 TCGv_i64 tmp64;
5637 /* FIXME: this access check should not take precedence over UNDEF
5638 * for invalid encodings; we will generate incorrect syndrome information
5639 * for attempts to execute invalid vfp/neon encodings with FP disabled.
5641 if (s->fp_excp_el) {
5642 gen_exception_insn(s, 4, EXCP_UDEF,
5643 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
5644 return 0;
5647 if (!s->vfp_enabled)
5648 return 1;
5649 q = (insn & (1 << 6)) != 0;
5650 u = (insn >> 24) & 1;
5651 VFP_DREG_D(rd, insn);
5652 VFP_DREG_N(rn, insn);
5653 VFP_DREG_M(rm, insn);
5654 size = (insn >> 20) & 3;
5655 vec_size = q ? 16 : 8;
5656 rd_ofs = neon_reg_offset(rd, 0);
5657 rn_ofs = neon_reg_offset(rn, 0);
5658 rm_ofs = neon_reg_offset(rm, 0);
5660 if ((insn & (1 << 23)) == 0) {
5661 /* Three register same length. */
5662 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
5663 /* Catch invalid op and bad size combinations: UNDEF */
5664 if ((neon_3r_sizes[op] & (1 << size)) == 0) {
5665 return 1;
5667 /* All insns of this form UNDEF for either this condition or the
5668 * superset of cases "Q==1"; we catch the latter later.
5670 if (q && ((rd | rn | rm) & 1)) {
5671 return 1;
5673 switch (op) {
5674 case NEON_3R_SHA:
5675 /* The SHA-1/SHA-256 3-register instructions require special
5676 * treatment here, as their size field is overloaded as an
5677 * op type selector, and they all consume their input in a
5678 * single pass.
5680 if (!q) {
5681 return 1;
5683 if (!u) { /* SHA-1 */
5684 if (!dc_isar_feature(aa32_sha1, s)) {
5685 return 1;
5687 ptr1 = vfp_reg_ptr(true, rd);
5688 ptr2 = vfp_reg_ptr(true, rn);
5689 ptr3 = vfp_reg_ptr(true, rm);
5690 tmp4 = tcg_const_i32(size);
5691 gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp4);
5692 tcg_temp_free_i32(tmp4);
5693 } else { /* SHA-256 */
5694 if (!dc_isar_feature(aa32_sha2, s) || size == 3) {
5695 return 1;
5697 ptr1 = vfp_reg_ptr(true, rd);
5698 ptr2 = vfp_reg_ptr(true, rn);
5699 ptr3 = vfp_reg_ptr(true, rm);
5700 switch (size) {
5701 case 0:
5702 gen_helper_crypto_sha256h(ptr1, ptr2, ptr3);
5703 break;
5704 case 1:
5705 gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3);
5706 break;
5707 case 2:
5708 gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3);
5709 break;
5712 tcg_temp_free_ptr(ptr1);
5713 tcg_temp_free_ptr(ptr2);
5714 tcg_temp_free_ptr(ptr3);
5715 return 0;
5717 case NEON_3R_VPADD_VQRDMLAH:
5718 if (!u) {
5719 break; /* VPADD */
5721 /* VQRDMLAH */
5722 switch (size) {
5723 case 1:
5724 return do_v81_helper(s, gen_helper_gvec_qrdmlah_s16,
5725 q, rd, rn, rm);
5726 case 2:
5727 return do_v81_helper(s, gen_helper_gvec_qrdmlah_s32,
5728 q, rd, rn, rm);
5730 return 1;
5732 case NEON_3R_VFM_VQRDMLSH:
5733 if (!u) {
5734 /* VFM, VFMS */
5735 if (size == 1) {
5736 return 1;
5738 break;
5740 /* VQRDMLSH */
5741 switch (size) {
5742 case 1:
5743 return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s16,
5744 q, rd, rn, rm);
5745 case 2:
5746 return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s32,
5747 q, rd, rn, rm);
5749 return 1;
5751 case NEON_3R_LOGIC: /* Logic ops. */
5752 switch ((u << 2) | size) {
5753 case 0: /* VAND */
5754 tcg_gen_gvec_and(0, rd_ofs, rn_ofs, rm_ofs,
5755 vec_size, vec_size);
5756 break;
5757 case 1: /* VBIC */
5758 tcg_gen_gvec_andc(0, rd_ofs, rn_ofs, rm_ofs,
5759 vec_size, vec_size);
5760 break;
5761 case 2: /* VORR */
5762 tcg_gen_gvec_or(0, rd_ofs, rn_ofs, rm_ofs,
5763 vec_size, vec_size);
5764 break;
5765 case 3: /* VORN */
5766 tcg_gen_gvec_orc(0, rd_ofs, rn_ofs, rm_ofs,
5767 vec_size, vec_size);
5768 break;
5769 case 4: /* VEOR */
5770 tcg_gen_gvec_xor(0, rd_ofs, rn_ofs, rm_ofs,
5771 vec_size, vec_size);
5772 break;
5773 case 5: /* VBSL */
5774 tcg_gen_gvec_bitsel(MO_8, rd_ofs, rd_ofs, rn_ofs, rm_ofs,
5775 vec_size, vec_size);
5776 break;
5777 case 6: /* VBIT */
5778 tcg_gen_gvec_bitsel(MO_8, rd_ofs, rm_ofs, rn_ofs, rd_ofs,
5779 vec_size, vec_size);
5780 break;
5781 case 7: /* VBIF */
5782 tcg_gen_gvec_bitsel(MO_8, rd_ofs, rm_ofs, rd_ofs, rn_ofs,
5783 vec_size, vec_size);
5784 break;
5786 return 0;
5788 case NEON_3R_VADD_VSUB:
5789 if (u) {
5790 tcg_gen_gvec_sub(size, rd_ofs, rn_ofs, rm_ofs,
5791 vec_size, vec_size);
5792 } else {
5793 tcg_gen_gvec_add(size, rd_ofs, rn_ofs, rm_ofs,
5794 vec_size, vec_size);
5796 return 0;
5798 case NEON_3R_VQADD:
5799 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
5800 rn_ofs, rm_ofs, vec_size, vec_size,
5801 (u ? uqadd_op : sqadd_op) + size);
5802 return 0;
5804 case NEON_3R_VQSUB:
5805 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
5806 rn_ofs, rm_ofs, vec_size, vec_size,
5807 (u ? uqsub_op : sqsub_op) + size);
5808 return 0;
5810 case NEON_3R_VMUL: /* VMUL */
5811 if (u) {
5812 /* Polynomial case allows only P8 and is handled below. */
5813 if (size != 0) {
5814 return 1;
5816 } else {
5817 tcg_gen_gvec_mul(size, rd_ofs, rn_ofs, rm_ofs,
5818 vec_size, vec_size);
5819 return 0;
5821 break;
5823 case NEON_3R_VML: /* VMLA, VMLS */
5824 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size,
5825 u ? &mls_op[size] : &mla_op[size]);
5826 return 0;
5828 case NEON_3R_VTST_VCEQ:
5829 if (u) { /* VCEQ */
5830 tcg_gen_gvec_cmp(TCG_COND_EQ, size, rd_ofs, rn_ofs, rm_ofs,
5831 vec_size, vec_size);
5832 } else { /* VTST */
5833 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
5834 vec_size, vec_size, &cmtst_op[size]);
5836 return 0;
5838 case NEON_3R_VCGT:
5839 tcg_gen_gvec_cmp(u ? TCG_COND_GTU : TCG_COND_GT, size,
5840 rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
5841 return 0;
5843 case NEON_3R_VCGE:
5844 tcg_gen_gvec_cmp(u ? TCG_COND_GEU : TCG_COND_GE, size,
5845 rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
5846 return 0;
5848 case NEON_3R_VMAX:
5849 if (u) {
5850 tcg_gen_gvec_umax(size, rd_ofs, rn_ofs, rm_ofs,
5851 vec_size, vec_size);
5852 } else {
5853 tcg_gen_gvec_smax(size, rd_ofs, rn_ofs, rm_ofs,
5854 vec_size, vec_size);
5856 return 0;
5857 case NEON_3R_VMIN:
5858 if (u) {
5859 tcg_gen_gvec_umin(size, rd_ofs, rn_ofs, rm_ofs,
5860 vec_size, vec_size);
5861 } else {
5862 tcg_gen_gvec_smin(size, rd_ofs, rn_ofs, rm_ofs,
5863 vec_size, vec_size);
5865 return 0;
5868 if (size == 3) {
5869 /* 64-bit element instructions. */
5870 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5871 neon_load_reg64(cpu_V0, rn + pass);
5872 neon_load_reg64(cpu_V1, rm + pass);
5873 switch (op) {
5874 case NEON_3R_VSHL:
5875 if (u) {
5876 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
5877 } else {
5878 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
5880 break;
5881 case NEON_3R_VQSHL:
5882 if (u) {
5883 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
5884 cpu_V1, cpu_V0);
5885 } else {
5886 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
5887 cpu_V1, cpu_V0);
5889 break;
5890 case NEON_3R_VRSHL:
5891 if (u) {
5892 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
5893 } else {
5894 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
5896 break;
5897 case NEON_3R_VQRSHL:
5898 if (u) {
5899 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
5900 cpu_V1, cpu_V0);
5901 } else {
5902 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
5903 cpu_V1, cpu_V0);
5905 break;
5906 default:
5907 abort();
5909 neon_store_reg64(cpu_V0, rd + pass);
5911 return 0;
5913 pairwise = 0;
5914 switch (op) {
5915 case NEON_3R_VSHL:
5916 case NEON_3R_VQSHL:
5917 case NEON_3R_VRSHL:
5918 case NEON_3R_VQRSHL:
5920 int rtmp;
5921 /* Shift instruction operands are reversed. */
5922 rtmp = rn;
5923 rn = rm;
5924 rm = rtmp;
5926 break;
5927 case NEON_3R_VPADD_VQRDMLAH:
5928 case NEON_3R_VPMAX:
5929 case NEON_3R_VPMIN:
5930 pairwise = 1;
5931 break;
5932 case NEON_3R_FLOAT_ARITH:
5933 pairwise = (u && size < 2); /* if VPADD (float) */
5934 break;
5935 case NEON_3R_FLOAT_MINMAX:
5936 pairwise = u; /* if VPMIN/VPMAX (float) */
5937 break;
5938 case NEON_3R_FLOAT_CMP:
5939 if (!u && size) {
5940 /* no encoding for U=0 C=1x */
5941 return 1;
5943 break;
5944 case NEON_3R_FLOAT_ACMP:
5945 if (!u) {
5946 return 1;
5948 break;
5949 case NEON_3R_FLOAT_MISC:
5950 /* VMAXNM/VMINNM in ARMv8 */
5951 if (u && !arm_dc_feature(s, ARM_FEATURE_V8)) {
5952 return 1;
5954 break;
5955 case NEON_3R_VFM_VQRDMLSH:
5956 if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
5957 return 1;
5959 break;
5960 default:
5961 break;
5964 if (pairwise && q) {
5965 /* All the pairwise insns UNDEF if Q is set */
5966 return 1;
5969 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5971 if (pairwise) {
5972 /* Pairwise. */
5973 if (pass < 1) {
5974 tmp = neon_load_reg(rn, 0);
5975 tmp2 = neon_load_reg(rn, 1);
5976 } else {
5977 tmp = neon_load_reg(rm, 0);
5978 tmp2 = neon_load_reg(rm, 1);
5980 } else {
5981 /* Elementwise. */
5982 tmp = neon_load_reg(rn, pass);
5983 tmp2 = neon_load_reg(rm, pass);
5985 switch (op) {
5986 case NEON_3R_VHADD:
5987 GEN_NEON_INTEGER_OP(hadd);
5988 break;
5989 case NEON_3R_VRHADD:
5990 GEN_NEON_INTEGER_OP(rhadd);
5991 break;
5992 case NEON_3R_VHSUB:
5993 GEN_NEON_INTEGER_OP(hsub);
5994 break;
5995 case NEON_3R_VSHL:
5996 GEN_NEON_INTEGER_OP(shl);
5997 break;
5998 case NEON_3R_VQSHL:
5999 GEN_NEON_INTEGER_OP_ENV(qshl);
6000 break;
6001 case NEON_3R_VRSHL:
6002 GEN_NEON_INTEGER_OP(rshl);
6003 break;
6004 case NEON_3R_VQRSHL:
6005 GEN_NEON_INTEGER_OP_ENV(qrshl);
6006 break;
6007 case NEON_3R_VABD:
6008 GEN_NEON_INTEGER_OP(abd);
6009 break;
6010 case NEON_3R_VABA:
6011 GEN_NEON_INTEGER_OP(abd);
6012 tcg_temp_free_i32(tmp2);
6013 tmp2 = neon_load_reg(rd, pass);
6014 gen_neon_add(size, tmp, tmp2);
6015 break;
6016 case NEON_3R_VMUL:
6017 /* VMUL.P8; other cases already eliminated. */
6018 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
6019 break;
6020 case NEON_3R_VPMAX:
6021 GEN_NEON_INTEGER_OP(pmax);
6022 break;
6023 case NEON_3R_VPMIN:
6024 GEN_NEON_INTEGER_OP(pmin);
6025 break;
6026 case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
6027 if (!u) { /* VQDMULH */
6028 switch (size) {
6029 case 1:
6030 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
6031 break;
6032 case 2:
6033 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
6034 break;
6035 default: abort();
6037 } else { /* VQRDMULH */
6038 switch (size) {
6039 case 1:
6040 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
6041 break;
6042 case 2:
6043 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
6044 break;
6045 default: abort();
6048 break;
6049 case NEON_3R_VPADD_VQRDMLAH:
6050 switch (size) {
6051 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
6052 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
6053 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
6054 default: abort();
6056 break;
6057 case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
6059 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6060 switch ((u << 2) | size) {
6061 case 0: /* VADD */
6062 case 4: /* VPADD */
6063 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
6064 break;
6065 case 2: /* VSUB */
6066 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
6067 break;
6068 case 6: /* VABD */
6069 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
6070 break;
6071 default:
6072 abort();
6074 tcg_temp_free_ptr(fpstatus);
6075 break;
6077 case NEON_3R_FLOAT_MULTIPLY:
6079 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6080 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
6081 if (!u) {
6082 tcg_temp_free_i32(tmp2);
6083 tmp2 = neon_load_reg(rd, pass);
6084 if (size == 0) {
6085 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
6086 } else {
6087 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
6090 tcg_temp_free_ptr(fpstatus);
6091 break;
6093 case NEON_3R_FLOAT_CMP:
6095 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6096 if (!u) {
6097 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
6098 } else {
6099 if (size == 0) {
6100 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
6101 } else {
6102 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
6105 tcg_temp_free_ptr(fpstatus);
6106 break;
6108 case NEON_3R_FLOAT_ACMP:
6110 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6111 if (size == 0) {
6112 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
6113 } else {
6114 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
6116 tcg_temp_free_ptr(fpstatus);
6117 break;
6119 case NEON_3R_FLOAT_MINMAX:
6121 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6122 if (size == 0) {
6123 gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus);
6124 } else {
6125 gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus);
6127 tcg_temp_free_ptr(fpstatus);
6128 break;
6130 case NEON_3R_FLOAT_MISC:
6131 if (u) {
6132 /* VMAXNM/VMINNM */
6133 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6134 if (size == 0) {
6135 gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus);
6136 } else {
6137 gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus);
6139 tcg_temp_free_ptr(fpstatus);
6140 } else {
6141 if (size == 0) {
6142 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
6143 } else {
6144 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
6147 break;
6148 case NEON_3R_VFM_VQRDMLSH:
6150 /* VFMA, VFMS: fused multiply-add */
6151 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6152 TCGv_i32 tmp3 = neon_load_reg(rd, pass);
6153 if (size) {
6154 /* VFMS */
6155 gen_helper_vfp_negs(tmp, tmp);
6157 gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus);
6158 tcg_temp_free_i32(tmp3);
6159 tcg_temp_free_ptr(fpstatus);
6160 break;
6162 default:
6163 abort();
6165 tcg_temp_free_i32(tmp2);
6167 /* Save the result. For elementwise operations we can put it
6168 straight into the destination register. For pairwise operations
6169 we have to be careful to avoid clobbering the source operands. */
6170 if (pairwise && rd == rm) {
6171 neon_store_scratch(pass, tmp);
6172 } else {
6173 neon_store_reg(rd, pass, tmp);
6176 } /* for pass */
6177 if (pairwise && rd == rm) {
6178 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6179 tmp = neon_load_scratch(pass);
6180 neon_store_reg(rd, pass, tmp);
6183 /* End of 3 register same size operations. */
6184 } else if (insn & (1 << 4)) {
6185 if ((insn & 0x00380080) != 0) {
6186 /* Two registers and shift. */
6187 op = (insn >> 8) & 0xf;
6188 if (insn & (1 << 7)) {
6189 /* 64-bit shift. */
6190 if (op > 7) {
6191 return 1;
6193 size = 3;
6194 } else {
6195 size = 2;
6196 while ((insn & (1 << (size + 19))) == 0)
6197 size--;
6199 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
6200 if (op < 8) {
6201 /* Shift by immediate:
6202 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
6203 if (q && ((rd | rm) & 1)) {
6204 return 1;
6206 if (!u && (op == 4 || op == 6)) {
6207 return 1;
6209 /* Right shifts are encoded as N - shift, where N is the
6210 element size in bits. */
6211 if (op <= 4) {
6212 shift = shift - (1 << (size + 3));
6215 switch (op) {
6216 case 0: /* VSHR */
6217 /* Right shift comes here negative. */
6218 shift = -shift;
6219 /* Shifts larger than the element size are architecturally
6220 * valid. Unsigned results in all zeros; signed results
6221 * in all sign bits.
6223 if (!u) {
6224 tcg_gen_gvec_sari(size, rd_ofs, rm_ofs,
6225 MIN(shift, (8 << size) - 1),
6226 vec_size, vec_size);
6227 } else if (shift >= 8 << size) {
6228 tcg_gen_gvec_dup8i(rd_ofs, vec_size, vec_size, 0);
6229 } else {
6230 tcg_gen_gvec_shri(size, rd_ofs, rm_ofs, shift,
6231 vec_size, vec_size);
6233 return 0;
6235 case 1: /* VSRA */
6236 /* Right shift comes here negative. */
6237 shift = -shift;
6238 /* Shifts larger than the element size are architecturally
6239 * valid. Unsigned results in all zeros; signed results
6240 * in all sign bits.
6242 if (!u) {
6243 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
6244 MIN(shift, (8 << size) - 1),
6245 &ssra_op[size]);
6246 } else if (shift >= 8 << size) {
6247 /* rd += 0 */
6248 } else {
6249 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
6250 shift, &usra_op[size]);
6252 return 0;
6254 case 4: /* VSRI */
6255 if (!u) {
6256 return 1;
6258 /* Right shift comes here negative. */
6259 shift = -shift;
6260 /* Shift out of range leaves destination unchanged. */
6261 if (shift < 8 << size) {
6262 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
6263 shift, &sri_op[size]);
6265 return 0;
6267 case 5: /* VSHL, VSLI */
6268 if (u) { /* VSLI */
6269 /* Shift out of range leaves destination unchanged. */
6270 if (shift < 8 << size) {
6271 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size,
6272 vec_size, shift, &sli_op[size]);
6274 } else { /* VSHL */
6275 /* Shifts larger than the element size are
6276 * architecturally valid and results in zero.
6278 if (shift >= 8 << size) {
6279 tcg_gen_gvec_dup8i(rd_ofs, vec_size, vec_size, 0);
6280 } else {
6281 tcg_gen_gvec_shli(size, rd_ofs, rm_ofs, shift,
6282 vec_size, vec_size);
6285 return 0;
6288 if (size == 3) {
6289 count = q + 1;
6290 } else {
6291 count = q ? 4: 2;
6294 /* To avoid excessive duplication of ops we implement shift
6295 * by immediate using the variable shift operations.
6297 imm = dup_const(size, shift);
6299 for (pass = 0; pass < count; pass++) {
6300 if (size == 3) {
6301 neon_load_reg64(cpu_V0, rm + pass);
6302 tcg_gen_movi_i64(cpu_V1, imm);
6303 switch (op) {
6304 case 2: /* VRSHR */
6305 case 3: /* VRSRA */
6306 if (u)
6307 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
6308 else
6309 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
6310 break;
6311 case 6: /* VQSHLU */
6312 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
6313 cpu_V0, cpu_V1);
6314 break;
6315 case 7: /* VQSHL */
6316 if (u) {
6317 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
6318 cpu_V0, cpu_V1);
6319 } else {
6320 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
6321 cpu_V0, cpu_V1);
6323 break;
6324 default:
6325 g_assert_not_reached();
6327 if (op == 3) {
6328 /* Accumulate. */
6329 neon_load_reg64(cpu_V1, rd + pass);
6330 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
6332 neon_store_reg64(cpu_V0, rd + pass);
6333 } else { /* size < 3 */
6334 /* Operands in T0 and T1. */
6335 tmp = neon_load_reg(rm, pass);
6336 tmp2 = tcg_temp_new_i32();
6337 tcg_gen_movi_i32(tmp2, imm);
6338 switch (op) {
6339 case 2: /* VRSHR */
6340 case 3: /* VRSRA */
6341 GEN_NEON_INTEGER_OP(rshl);
6342 break;
6343 case 6: /* VQSHLU */
6344 switch (size) {
6345 case 0:
6346 gen_helper_neon_qshlu_s8(tmp, cpu_env,
6347 tmp, tmp2);
6348 break;
6349 case 1:
6350 gen_helper_neon_qshlu_s16(tmp, cpu_env,
6351 tmp, tmp2);
6352 break;
6353 case 2:
6354 gen_helper_neon_qshlu_s32(tmp, cpu_env,
6355 tmp, tmp2);
6356 break;
6357 default:
6358 abort();
6360 break;
6361 case 7: /* VQSHL */
6362 GEN_NEON_INTEGER_OP_ENV(qshl);
6363 break;
6364 default:
6365 g_assert_not_reached();
6367 tcg_temp_free_i32(tmp2);
6369 if (op == 3) {
6370 /* Accumulate. */
6371 tmp2 = neon_load_reg(rd, pass);
6372 gen_neon_add(size, tmp, tmp2);
6373 tcg_temp_free_i32(tmp2);
6375 neon_store_reg(rd, pass, tmp);
6377 } /* for pass */
6378 } else if (op < 10) {
6379 /* Shift by immediate and narrow:
6380 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
6381 int input_unsigned = (op == 8) ? !u : u;
6382 if (rm & 1) {
6383 return 1;
6385 shift = shift - (1 << (size + 3));
6386 size++;
6387 if (size == 3) {
6388 tmp64 = tcg_const_i64(shift);
6389 neon_load_reg64(cpu_V0, rm);
6390 neon_load_reg64(cpu_V1, rm + 1);
6391 for (pass = 0; pass < 2; pass++) {
6392 TCGv_i64 in;
6393 if (pass == 0) {
6394 in = cpu_V0;
6395 } else {
6396 in = cpu_V1;
6398 if (q) {
6399 if (input_unsigned) {
6400 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
6401 } else {
6402 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
6404 } else {
6405 if (input_unsigned) {
6406 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
6407 } else {
6408 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
6411 tmp = tcg_temp_new_i32();
6412 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
6413 neon_store_reg(rd, pass, tmp);
6414 } /* for pass */
6415 tcg_temp_free_i64(tmp64);
6416 } else {
6417 if (size == 1) {
6418 imm = (uint16_t)shift;
6419 imm |= imm << 16;
6420 } else {
6421 /* size == 2 */
6422 imm = (uint32_t)shift;
6424 tmp2 = tcg_const_i32(imm);
6425 tmp4 = neon_load_reg(rm + 1, 0);
6426 tmp5 = neon_load_reg(rm + 1, 1);
6427 for (pass = 0; pass < 2; pass++) {
6428 if (pass == 0) {
6429 tmp = neon_load_reg(rm, 0);
6430 } else {
6431 tmp = tmp4;
6433 gen_neon_shift_narrow(size, tmp, tmp2, q,
6434 input_unsigned);
6435 if (pass == 0) {
6436 tmp3 = neon_load_reg(rm, 1);
6437 } else {
6438 tmp3 = tmp5;
6440 gen_neon_shift_narrow(size, tmp3, tmp2, q,
6441 input_unsigned);
6442 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
6443 tcg_temp_free_i32(tmp);
6444 tcg_temp_free_i32(tmp3);
6445 tmp = tcg_temp_new_i32();
6446 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
6447 neon_store_reg(rd, pass, tmp);
6448 } /* for pass */
6449 tcg_temp_free_i32(tmp2);
6451 } else if (op == 10) {
6452 /* VSHLL, VMOVL */
6453 if (q || (rd & 1)) {
6454 return 1;
6456 tmp = neon_load_reg(rm, 0);
6457 tmp2 = neon_load_reg(rm, 1);
6458 for (pass = 0; pass < 2; pass++) {
6459 if (pass == 1)
6460 tmp = tmp2;
6462 gen_neon_widen(cpu_V0, tmp, size, u);
6464 if (shift != 0) {
6465 /* The shift is less than the width of the source
6466 type, so we can just shift the whole register. */
6467 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
6468 /* Widen the result of shift: we need to clear
6469 * the potential overflow bits resulting from
6470 * left bits of the narrow input appearing as
6471 * right bits of left the neighbour narrow
6472 * input. */
6473 if (size < 2 || !u) {
6474 uint64_t imm64;
6475 if (size == 0) {
6476 imm = (0xffu >> (8 - shift));
6477 imm |= imm << 16;
6478 } else if (size == 1) {
6479 imm = 0xffff >> (16 - shift);
6480 } else {
6481 /* size == 2 */
6482 imm = 0xffffffff >> (32 - shift);
6484 if (size < 2) {
6485 imm64 = imm | (((uint64_t)imm) << 32);
6486 } else {
6487 imm64 = imm;
6489 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
6492 neon_store_reg64(cpu_V0, rd + pass);
6494 } else if (op >= 14) {
6495 /* VCVT fixed-point. */
6496 if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
6497 return 1;
6499 /* We have already masked out the must-be-1 top bit of imm6,
6500 * hence this 32-shift where the ARM ARM has 64-imm6.
6502 shift = 32 - shift;
6503 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6504 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
6505 if (!(op & 1)) {
6506 if (u)
6507 gen_vfp_ulto(0, shift, 1);
6508 else
6509 gen_vfp_slto(0, shift, 1);
6510 } else {
6511 if (u)
6512 gen_vfp_toul(0, shift, 1);
6513 else
6514 gen_vfp_tosl(0, shift, 1);
6516 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
6518 } else {
6519 return 1;
6521 } else { /* (insn & 0x00380080) == 0 */
6522 int invert, reg_ofs, vec_size;
6524 if (q && (rd & 1)) {
6525 return 1;
6528 op = (insn >> 8) & 0xf;
6529 /* One register and immediate. */
6530 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
6531 invert = (insn & (1 << 5)) != 0;
6532 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
6533 * We choose to not special-case this and will behave as if a
6534 * valid constant encoding of 0 had been given.
6536 switch (op) {
6537 case 0: case 1:
6538 /* no-op */
6539 break;
6540 case 2: case 3:
6541 imm <<= 8;
6542 break;
6543 case 4: case 5:
6544 imm <<= 16;
6545 break;
6546 case 6: case 7:
6547 imm <<= 24;
6548 break;
6549 case 8: case 9:
6550 imm |= imm << 16;
6551 break;
6552 case 10: case 11:
6553 imm = (imm << 8) | (imm << 24);
6554 break;
6555 case 12:
6556 imm = (imm << 8) | 0xff;
6557 break;
6558 case 13:
6559 imm = (imm << 16) | 0xffff;
6560 break;
6561 case 14:
6562 imm |= (imm << 8) | (imm << 16) | (imm << 24);
6563 if (invert) {
6564 imm = ~imm;
6566 break;
6567 case 15:
6568 if (invert) {
6569 return 1;
6571 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
6572 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
6573 break;
6575 if (invert) {
6576 imm = ~imm;
6579 reg_ofs = neon_reg_offset(rd, 0);
6580 vec_size = q ? 16 : 8;
6582 if (op & 1 && op < 12) {
6583 if (invert) {
6584 /* The immediate value has already been inverted,
6585 * so BIC becomes AND.
6587 tcg_gen_gvec_andi(MO_32, reg_ofs, reg_ofs, imm,
6588 vec_size, vec_size);
6589 } else {
6590 tcg_gen_gvec_ori(MO_32, reg_ofs, reg_ofs, imm,
6591 vec_size, vec_size);
6593 } else {
6594 /* VMOV, VMVN. */
6595 if (op == 14 && invert) {
6596 TCGv_i64 t64 = tcg_temp_new_i64();
6598 for (pass = 0; pass <= q; ++pass) {
6599 uint64_t val = 0;
6600 int n;
6602 for (n = 0; n < 8; n++) {
6603 if (imm & (1 << (n + pass * 8))) {
6604 val |= 0xffull << (n * 8);
6607 tcg_gen_movi_i64(t64, val);
6608 neon_store_reg64(t64, rd + pass);
6610 tcg_temp_free_i64(t64);
6611 } else {
6612 tcg_gen_gvec_dup32i(reg_ofs, vec_size, vec_size, imm);
6616 } else { /* (insn & 0x00800010 == 0x00800000) */
6617 if (size != 3) {
6618 op = (insn >> 8) & 0xf;
6619 if ((insn & (1 << 6)) == 0) {
6620 /* Three registers of different lengths. */
6621 int src1_wide;
6622 int src2_wide;
6623 int prewiden;
6624 /* undefreq: bit 0 : UNDEF if size == 0
6625 * bit 1 : UNDEF if size == 1
6626 * bit 2 : UNDEF if size == 2
6627 * bit 3 : UNDEF if U == 1
6628 * Note that [2:0] set implies 'always UNDEF'
6630 int undefreq;
6631 /* prewiden, src1_wide, src2_wide, undefreq */
6632 static const int neon_3reg_wide[16][4] = {
6633 {1, 0, 0, 0}, /* VADDL */
6634 {1, 1, 0, 0}, /* VADDW */
6635 {1, 0, 0, 0}, /* VSUBL */
6636 {1, 1, 0, 0}, /* VSUBW */
6637 {0, 1, 1, 0}, /* VADDHN */
6638 {0, 0, 0, 0}, /* VABAL */
6639 {0, 1, 1, 0}, /* VSUBHN */
6640 {0, 0, 0, 0}, /* VABDL */
6641 {0, 0, 0, 0}, /* VMLAL */
6642 {0, 0, 0, 9}, /* VQDMLAL */
6643 {0, 0, 0, 0}, /* VMLSL */
6644 {0, 0, 0, 9}, /* VQDMLSL */
6645 {0, 0, 0, 0}, /* Integer VMULL */
6646 {0, 0, 0, 1}, /* VQDMULL */
6647 {0, 0, 0, 0xa}, /* Polynomial VMULL */
6648 {0, 0, 0, 7}, /* Reserved: always UNDEF */
6651 prewiden = neon_3reg_wide[op][0];
6652 src1_wide = neon_3reg_wide[op][1];
6653 src2_wide = neon_3reg_wide[op][2];
6654 undefreq = neon_3reg_wide[op][3];
6656 if ((undefreq & (1 << size)) ||
6657 ((undefreq & 8) && u)) {
6658 return 1;
6660 if ((src1_wide && (rn & 1)) ||
6661 (src2_wide && (rm & 1)) ||
6662 (!src2_wide && (rd & 1))) {
6663 return 1;
6666 /* Handle VMULL.P64 (Polynomial 64x64 to 128 bit multiply)
6667 * outside the loop below as it only performs a single pass.
6669 if (op == 14 && size == 2) {
6670 TCGv_i64 tcg_rn, tcg_rm, tcg_rd;
6672 if (!dc_isar_feature(aa32_pmull, s)) {
6673 return 1;
6675 tcg_rn = tcg_temp_new_i64();
6676 tcg_rm = tcg_temp_new_i64();
6677 tcg_rd = tcg_temp_new_i64();
6678 neon_load_reg64(tcg_rn, rn);
6679 neon_load_reg64(tcg_rm, rm);
6680 gen_helper_neon_pmull_64_lo(tcg_rd, tcg_rn, tcg_rm);
6681 neon_store_reg64(tcg_rd, rd);
6682 gen_helper_neon_pmull_64_hi(tcg_rd, tcg_rn, tcg_rm);
6683 neon_store_reg64(tcg_rd, rd + 1);
6684 tcg_temp_free_i64(tcg_rn);
6685 tcg_temp_free_i64(tcg_rm);
6686 tcg_temp_free_i64(tcg_rd);
6687 return 0;
6690 /* Avoid overlapping operands. Wide source operands are
6691 always aligned so will never overlap with wide
6692 destinations in problematic ways. */
6693 if (rd == rm && !src2_wide) {
6694 tmp = neon_load_reg(rm, 1);
6695 neon_store_scratch(2, tmp);
6696 } else if (rd == rn && !src1_wide) {
6697 tmp = neon_load_reg(rn, 1);
6698 neon_store_scratch(2, tmp);
6700 tmp3 = NULL;
6701 for (pass = 0; pass < 2; pass++) {
6702 if (src1_wide) {
6703 neon_load_reg64(cpu_V0, rn + pass);
6704 tmp = NULL;
6705 } else {
6706 if (pass == 1 && rd == rn) {
6707 tmp = neon_load_scratch(2);
6708 } else {
6709 tmp = neon_load_reg(rn, pass);
6711 if (prewiden) {
6712 gen_neon_widen(cpu_V0, tmp, size, u);
6715 if (src2_wide) {
6716 neon_load_reg64(cpu_V1, rm + pass);
6717 tmp2 = NULL;
6718 } else {
6719 if (pass == 1 && rd == rm) {
6720 tmp2 = neon_load_scratch(2);
6721 } else {
6722 tmp2 = neon_load_reg(rm, pass);
6724 if (prewiden) {
6725 gen_neon_widen(cpu_V1, tmp2, size, u);
6728 switch (op) {
6729 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
6730 gen_neon_addl(size);
6731 break;
6732 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
6733 gen_neon_subl(size);
6734 break;
6735 case 5: case 7: /* VABAL, VABDL */
6736 switch ((size << 1) | u) {
6737 case 0:
6738 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
6739 break;
6740 case 1:
6741 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
6742 break;
6743 case 2:
6744 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
6745 break;
6746 case 3:
6747 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
6748 break;
6749 case 4:
6750 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
6751 break;
6752 case 5:
6753 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
6754 break;
6755 default: abort();
6757 tcg_temp_free_i32(tmp2);
6758 tcg_temp_free_i32(tmp);
6759 break;
6760 case 8: case 9: case 10: case 11: case 12: case 13:
6761 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
6762 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
6763 break;
6764 case 14: /* Polynomial VMULL */
6765 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
6766 tcg_temp_free_i32(tmp2);
6767 tcg_temp_free_i32(tmp);
6768 break;
6769 default: /* 15 is RESERVED: caught earlier */
6770 abort();
6772 if (op == 13) {
6773 /* VQDMULL */
6774 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6775 neon_store_reg64(cpu_V0, rd + pass);
6776 } else if (op == 5 || (op >= 8 && op <= 11)) {
6777 /* Accumulate. */
6778 neon_load_reg64(cpu_V1, rd + pass);
6779 switch (op) {
6780 case 10: /* VMLSL */
6781 gen_neon_negl(cpu_V0, size);
6782 /* Fall through */
6783 case 5: case 8: /* VABAL, VMLAL */
6784 gen_neon_addl(size);
6785 break;
6786 case 9: case 11: /* VQDMLAL, VQDMLSL */
6787 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6788 if (op == 11) {
6789 gen_neon_negl(cpu_V0, size);
6791 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
6792 break;
6793 default:
6794 abort();
6796 neon_store_reg64(cpu_V0, rd + pass);
6797 } else if (op == 4 || op == 6) {
6798 /* Narrowing operation. */
6799 tmp = tcg_temp_new_i32();
6800 if (!u) {
6801 switch (size) {
6802 case 0:
6803 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
6804 break;
6805 case 1:
6806 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
6807 break;
6808 case 2:
6809 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
6810 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
6811 break;
6812 default: abort();
6814 } else {
6815 switch (size) {
6816 case 0:
6817 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
6818 break;
6819 case 1:
6820 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
6821 break;
6822 case 2:
6823 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
6824 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
6825 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
6826 break;
6827 default: abort();
6830 if (pass == 0) {
6831 tmp3 = tmp;
6832 } else {
6833 neon_store_reg(rd, 0, tmp3);
6834 neon_store_reg(rd, 1, tmp);
6836 } else {
6837 /* Write back the result. */
6838 neon_store_reg64(cpu_V0, rd + pass);
6841 } else {
6842 /* Two registers and a scalar. NB that for ops of this form
6843 * the ARM ARM labels bit 24 as Q, but it is in our variable
6844 * 'u', not 'q'.
6846 if (size == 0) {
6847 return 1;
6849 switch (op) {
6850 case 1: /* Float VMLA scalar */
6851 case 5: /* Floating point VMLS scalar */
6852 case 9: /* Floating point VMUL scalar */
6853 if (size == 1) {
6854 return 1;
6856 /* fall through */
6857 case 0: /* Integer VMLA scalar */
6858 case 4: /* Integer VMLS scalar */
6859 case 8: /* Integer VMUL scalar */
6860 case 12: /* VQDMULH scalar */
6861 case 13: /* VQRDMULH scalar */
6862 if (u && ((rd | rn) & 1)) {
6863 return 1;
6865 tmp = neon_get_scalar(size, rm);
6866 neon_store_scratch(0, tmp);
6867 for (pass = 0; pass < (u ? 4 : 2); pass++) {
6868 tmp = neon_load_scratch(0);
6869 tmp2 = neon_load_reg(rn, pass);
6870 if (op == 12) {
6871 if (size == 1) {
6872 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
6873 } else {
6874 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
6876 } else if (op == 13) {
6877 if (size == 1) {
6878 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
6879 } else {
6880 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
6882 } else if (op & 1) {
6883 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6884 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
6885 tcg_temp_free_ptr(fpstatus);
6886 } else {
6887 switch (size) {
6888 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
6889 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
6890 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
6891 default: abort();
6894 tcg_temp_free_i32(tmp2);
6895 if (op < 8) {
6896 /* Accumulate. */
6897 tmp2 = neon_load_reg(rd, pass);
6898 switch (op) {
6899 case 0:
6900 gen_neon_add(size, tmp, tmp2);
6901 break;
6902 case 1:
6904 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6905 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
6906 tcg_temp_free_ptr(fpstatus);
6907 break;
6909 case 4:
6910 gen_neon_rsb(size, tmp, tmp2);
6911 break;
6912 case 5:
6914 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6915 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
6916 tcg_temp_free_ptr(fpstatus);
6917 break;
6919 default:
6920 abort();
6922 tcg_temp_free_i32(tmp2);
6924 neon_store_reg(rd, pass, tmp);
6926 break;
6927 case 3: /* VQDMLAL scalar */
6928 case 7: /* VQDMLSL scalar */
6929 case 11: /* VQDMULL scalar */
6930 if (u == 1) {
6931 return 1;
6933 /* fall through */
6934 case 2: /* VMLAL sclar */
6935 case 6: /* VMLSL scalar */
6936 case 10: /* VMULL scalar */
6937 if (rd & 1) {
6938 return 1;
6940 tmp2 = neon_get_scalar(size, rm);
6941 /* We need a copy of tmp2 because gen_neon_mull
6942 * deletes it during pass 0. */
6943 tmp4 = tcg_temp_new_i32();
6944 tcg_gen_mov_i32(tmp4, tmp2);
6945 tmp3 = neon_load_reg(rn, 1);
6947 for (pass = 0; pass < 2; pass++) {
6948 if (pass == 0) {
6949 tmp = neon_load_reg(rn, 0);
6950 } else {
6951 tmp = tmp3;
6952 tmp2 = tmp4;
6954 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
6955 if (op != 11) {
6956 neon_load_reg64(cpu_V1, rd + pass);
6958 switch (op) {
6959 case 6:
6960 gen_neon_negl(cpu_V0, size);
6961 /* Fall through */
6962 case 2:
6963 gen_neon_addl(size);
6964 break;
6965 case 3: case 7:
6966 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6967 if (op == 7) {
6968 gen_neon_negl(cpu_V0, size);
6970 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
6971 break;
6972 case 10:
6973 /* no-op */
6974 break;
6975 case 11:
6976 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6977 break;
6978 default:
6979 abort();
6981 neon_store_reg64(cpu_V0, rd + pass);
6983 break;
6984 case 14: /* VQRDMLAH scalar */
6985 case 15: /* VQRDMLSH scalar */
6987 NeonGenThreeOpEnvFn *fn;
6989 if (!dc_isar_feature(aa32_rdm, s)) {
6990 return 1;
6992 if (u && ((rd | rn) & 1)) {
6993 return 1;
6995 if (op == 14) {
6996 if (size == 1) {
6997 fn = gen_helper_neon_qrdmlah_s16;
6998 } else {
6999 fn = gen_helper_neon_qrdmlah_s32;
7001 } else {
7002 if (size == 1) {
7003 fn = gen_helper_neon_qrdmlsh_s16;
7004 } else {
7005 fn = gen_helper_neon_qrdmlsh_s32;
7009 tmp2 = neon_get_scalar(size, rm);
7010 for (pass = 0; pass < (u ? 4 : 2); pass++) {
7011 tmp = neon_load_reg(rn, pass);
7012 tmp3 = neon_load_reg(rd, pass);
7013 fn(tmp, cpu_env, tmp, tmp2, tmp3);
7014 tcg_temp_free_i32(tmp3);
7015 neon_store_reg(rd, pass, tmp);
7017 tcg_temp_free_i32(tmp2);
7019 break;
7020 default:
7021 g_assert_not_reached();
7024 } else { /* size == 3 */
7025 if (!u) {
7026 /* Extract. */
7027 imm = (insn >> 8) & 0xf;
7029 if (imm > 7 && !q)
7030 return 1;
7032 if (q && ((rd | rn | rm) & 1)) {
7033 return 1;
7036 if (imm == 0) {
7037 neon_load_reg64(cpu_V0, rn);
7038 if (q) {
7039 neon_load_reg64(cpu_V1, rn + 1);
7041 } else if (imm == 8) {
7042 neon_load_reg64(cpu_V0, rn + 1);
7043 if (q) {
7044 neon_load_reg64(cpu_V1, rm);
7046 } else if (q) {
7047 tmp64 = tcg_temp_new_i64();
7048 if (imm < 8) {
7049 neon_load_reg64(cpu_V0, rn);
7050 neon_load_reg64(tmp64, rn + 1);
7051 } else {
7052 neon_load_reg64(cpu_V0, rn + 1);
7053 neon_load_reg64(tmp64, rm);
7055 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
7056 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
7057 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
7058 if (imm < 8) {
7059 neon_load_reg64(cpu_V1, rm);
7060 } else {
7061 neon_load_reg64(cpu_V1, rm + 1);
7062 imm -= 8;
7064 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
7065 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
7066 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
7067 tcg_temp_free_i64(tmp64);
7068 } else {
7069 /* BUGFIX */
7070 neon_load_reg64(cpu_V0, rn);
7071 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
7072 neon_load_reg64(cpu_V1, rm);
7073 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
7074 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
7076 neon_store_reg64(cpu_V0, rd);
7077 if (q) {
7078 neon_store_reg64(cpu_V1, rd + 1);
7080 } else if ((insn & (1 << 11)) == 0) {
7081 /* Two register misc. */
7082 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
7083 size = (insn >> 18) & 3;
7084 /* UNDEF for unknown op values and bad op-size combinations */
7085 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
7086 return 1;
7088 if (neon_2rm_is_v8_op(op) &&
7089 !arm_dc_feature(s, ARM_FEATURE_V8)) {
7090 return 1;
7092 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
7093 q && ((rm | rd) & 1)) {
7094 return 1;
7096 switch (op) {
7097 case NEON_2RM_VREV64:
7098 for (pass = 0; pass < (q ? 2 : 1); pass++) {
7099 tmp = neon_load_reg(rm, pass * 2);
7100 tmp2 = neon_load_reg(rm, pass * 2 + 1);
7101 switch (size) {
7102 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
7103 case 1: gen_swap_half(tmp); break;
7104 case 2: /* no-op */ break;
7105 default: abort();
7107 neon_store_reg(rd, pass * 2 + 1, tmp);
7108 if (size == 2) {
7109 neon_store_reg(rd, pass * 2, tmp2);
7110 } else {
7111 switch (size) {
7112 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
7113 case 1: gen_swap_half(tmp2); break;
7114 default: abort();
7116 neon_store_reg(rd, pass * 2, tmp2);
7119 break;
7120 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
7121 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
7122 for (pass = 0; pass < q + 1; pass++) {
7123 tmp = neon_load_reg(rm, pass * 2);
7124 gen_neon_widen(cpu_V0, tmp, size, op & 1);
7125 tmp = neon_load_reg(rm, pass * 2 + 1);
7126 gen_neon_widen(cpu_V1, tmp, size, op & 1);
7127 switch (size) {
7128 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
7129 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
7130 case 2: tcg_gen_add_i64(CPU_V001); break;
7131 default: abort();
7133 if (op >= NEON_2RM_VPADAL) {
7134 /* Accumulate. */
7135 neon_load_reg64(cpu_V1, rd + pass);
7136 gen_neon_addl(size);
7138 neon_store_reg64(cpu_V0, rd + pass);
7140 break;
7141 case NEON_2RM_VTRN:
7142 if (size == 2) {
7143 int n;
7144 for (n = 0; n < (q ? 4 : 2); n += 2) {
7145 tmp = neon_load_reg(rm, n);
7146 tmp2 = neon_load_reg(rd, n + 1);
7147 neon_store_reg(rm, n, tmp2);
7148 neon_store_reg(rd, n + 1, tmp);
7150 } else {
7151 goto elementwise;
7153 break;
7154 case NEON_2RM_VUZP:
7155 if (gen_neon_unzip(rd, rm, size, q)) {
7156 return 1;
7158 break;
7159 case NEON_2RM_VZIP:
7160 if (gen_neon_zip(rd, rm, size, q)) {
7161 return 1;
7163 break;
7164 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
7165 /* also VQMOVUN; op field and mnemonics don't line up */
7166 if (rm & 1) {
7167 return 1;
7169 tmp2 = NULL;
7170 for (pass = 0; pass < 2; pass++) {
7171 neon_load_reg64(cpu_V0, rm + pass);
7172 tmp = tcg_temp_new_i32();
7173 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
7174 tmp, cpu_V0);
7175 if (pass == 0) {
7176 tmp2 = tmp;
7177 } else {
7178 neon_store_reg(rd, 0, tmp2);
7179 neon_store_reg(rd, 1, tmp);
7182 break;
7183 case NEON_2RM_VSHLL:
7184 if (q || (rd & 1)) {
7185 return 1;
7187 tmp = neon_load_reg(rm, 0);
7188 tmp2 = neon_load_reg(rm, 1);
7189 for (pass = 0; pass < 2; pass++) {
7190 if (pass == 1)
7191 tmp = tmp2;
7192 gen_neon_widen(cpu_V0, tmp, size, 1);
7193 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
7194 neon_store_reg64(cpu_V0, rd + pass);
7196 break;
7197 case NEON_2RM_VCVT_F16_F32:
7199 TCGv_ptr fpst;
7200 TCGv_i32 ahp;
7202 if (!dc_isar_feature(aa32_fp16_spconv, s) ||
7203 q || (rm & 1)) {
7204 return 1;
7206 tmp = tcg_temp_new_i32();
7207 tmp2 = tcg_temp_new_i32();
7208 fpst = get_fpstatus_ptr(true);
7209 ahp = get_ahp_flag();
7210 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
7211 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, fpst, ahp);
7212 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
7213 gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, fpst, ahp);
7214 tcg_gen_shli_i32(tmp2, tmp2, 16);
7215 tcg_gen_or_i32(tmp2, tmp2, tmp);
7216 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
7217 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, fpst, ahp);
7218 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
7219 neon_store_reg(rd, 0, tmp2);
7220 tmp2 = tcg_temp_new_i32();
7221 gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, fpst, ahp);
7222 tcg_gen_shli_i32(tmp2, tmp2, 16);
7223 tcg_gen_or_i32(tmp2, tmp2, tmp);
7224 neon_store_reg(rd, 1, tmp2);
7225 tcg_temp_free_i32(tmp);
7226 tcg_temp_free_i32(ahp);
7227 tcg_temp_free_ptr(fpst);
7228 break;
7230 case NEON_2RM_VCVT_F32_F16:
7232 TCGv_ptr fpst;
7233 TCGv_i32 ahp;
7234 if (!dc_isar_feature(aa32_fp16_spconv, s) ||
7235 q || (rd & 1)) {
7236 return 1;
7238 fpst = get_fpstatus_ptr(true);
7239 ahp = get_ahp_flag();
7240 tmp3 = tcg_temp_new_i32();
7241 tmp = neon_load_reg(rm, 0);
7242 tmp2 = neon_load_reg(rm, 1);
7243 tcg_gen_ext16u_i32(tmp3, tmp);
7244 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
7245 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
7246 tcg_gen_shri_i32(tmp3, tmp, 16);
7247 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
7248 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
7249 tcg_temp_free_i32(tmp);
7250 tcg_gen_ext16u_i32(tmp3, tmp2);
7251 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
7252 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
7253 tcg_gen_shri_i32(tmp3, tmp2, 16);
7254 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
7255 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
7256 tcg_temp_free_i32(tmp2);
7257 tcg_temp_free_i32(tmp3);
7258 tcg_temp_free_i32(ahp);
7259 tcg_temp_free_ptr(fpst);
7260 break;
7262 case NEON_2RM_AESE: case NEON_2RM_AESMC:
7263 if (!dc_isar_feature(aa32_aes, s) || ((rm | rd) & 1)) {
7264 return 1;
7266 ptr1 = vfp_reg_ptr(true, rd);
7267 ptr2 = vfp_reg_ptr(true, rm);
7269 /* Bit 6 is the lowest opcode bit; it distinguishes between
7270 * encryption (AESE/AESMC) and decryption (AESD/AESIMC)
7272 tmp3 = tcg_const_i32(extract32(insn, 6, 1));
7274 if (op == NEON_2RM_AESE) {
7275 gen_helper_crypto_aese(ptr1, ptr2, tmp3);
7276 } else {
7277 gen_helper_crypto_aesmc(ptr1, ptr2, tmp3);
7279 tcg_temp_free_ptr(ptr1);
7280 tcg_temp_free_ptr(ptr2);
7281 tcg_temp_free_i32(tmp3);
7282 break;
7283 case NEON_2RM_SHA1H:
7284 if (!dc_isar_feature(aa32_sha1, s) || ((rm | rd) & 1)) {
7285 return 1;
7287 ptr1 = vfp_reg_ptr(true, rd);
7288 ptr2 = vfp_reg_ptr(true, rm);
7290 gen_helper_crypto_sha1h(ptr1, ptr2);
7292 tcg_temp_free_ptr(ptr1);
7293 tcg_temp_free_ptr(ptr2);
7294 break;
7295 case NEON_2RM_SHA1SU1:
7296 if ((rm | rd) & 1) {
7297 return 1;
7299 /* bit 6 (q): set -> SHA256SU0, cleared -> SHA1SU1 */
7300 if (q) {
7301 if (!dc_isar_feature(aa32_sha2, s)) {
7302 return 1;
7304 } else if (!dc_isar_feature(aa32_sha1, s)) {
7305 return 1;
7307 ptr1 = vfp_reg_ptr(true, rd);
7308 ptr2 = vfp_reg_ptr(true, rm);
7309 if (q) {
7310 gen_helper_crypto_sha256su0(ptr1, ptr2);
7311 } else {
7312 gen_helper_crypto_sha1su1(ptr1, ptr2);
7314 tcg_temp_free_ptr(ptr1);
7315 tcg_temp_free_ptr(ptr2);
7316 break;
7318 case NEON_2RM_VMVN:
7319 tcg_gen_gvec_not(0, rd_ofs, rm_ofs, vec_size, vec_size);
7320 break;
7321 case NEON_2RM_VNEG:
7322 tcg_gen_gvec_neg(size, rd_ofs, rm_ofs, vec_size, vec_size);
7323 break;
7324 case NEON_2RM_VABS:
7325 tcg_gen_gvec_abs(size, rd_ofs, rm_ofs, vec_size, vec_size);
7326 break;
7328 default:
7329 elementwise:
7330 for (pass = 0; pass < (q ? 4 : 2); pass++) {
7331 if (neon_2rm_is_float_op(op)) {
7332 tcg_gen_ld_f32(cpu_F0s, cpu_env,
7333 neon_reg_offset(rm, pass));
7334 tmp = NULL;
7335 } else {
7336 tmp = neon_load_reg(rm, pass);
7338 switch (op) {
7339 case NEON_2RM_VREV32:
7340 switch (size) {
7341 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
7342 case 1: gen_swap_half(tmp); break;
7343 default: abort();
7345 break;
7346 case NEON_2RM_VREV16:
7347 gen_rev16(tmp);
7348 break;
7349 case NEON_2RM_VCLS:
7350 switch (size) {
7351 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
7352 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
7353 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
7354 default: abort();
7356 break;
7357 case NEON_2RM_VCLZ:
7358 switch (size) {
7359 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
7360 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
7361 case 2: tcg_gen_clzi_i32(tmp, tmp, 32); break;
7362 default: abort();
7364 break;
7365 case NEON_2RM_VCNT:
7366 gen_helper_neon_cnt_u8(tmp, tmp);
7367 break;
7368 case NEON_2RM_VQABS:
7369 switch (size) {
7370 case 0:
7371 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
7372 break;
7373 case 1:
7374 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
7375 break;
7376 case 2:
7377 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
7378 break;
7379 default: abort();
7381 break;
7382 case NEON_2RM_VQNEG:
7383 switch (size) {
7384 case 0:
7385 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
7386 break;
7387 case 1:
7388 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
7389 break;
7390 case 2:
7391 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
7392 break;
7393 default: abort();
7395 break;
7396 case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
7397 tmp2 = tcg_const_i32(0);
7398 switch(size) {
7399 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
7400 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
7401 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
7402 default: abort();
7404 tcg_temp_free_i32(tmp2);
7405 if (op == NEON_2RM_VCLE0) {
7406 tcg_gen_not_i32(tmp, tmp);
7408 break;
7409 case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
7410 tmp2 = tcg_const_i32(0);
7411 switch(size) {
7412 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
7413 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
7414 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
7415 default: abort();
7417 tcg_temp_free_i32(tmp2);
7418 if (op == NEON_2RM_VCLT0) {
7419 tcg_gen_not_i32(tmp, tmp);
7421 break;
7422 case NEON_2RM_VCEQ0:
7423 tmp2 = tcg_const_i32(0);
7424 switch(size) {
7425 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
7426 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
7427 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
7428 default: abort();
7430 tcg_temp_free_i32(tmp2);
7431 break;
7432 case NEON_2RM_VCGT0_F:
7434 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7435 tmp2 = tcg_const_i32(0);
7436 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
7437 tcg_temp_free_i32(tmp2);
7438 tcg_temp_free_ptr(fpstatus);
7439 break;
7441 case NEON_2RM_VCGE0_F:
7443 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7444 tmp2 = tcg_const_i32(0);
7445 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
7446 tcg_temp_free_i32(tmp2);
7447 tcg_temp_free_ptr(fpstatus);
7448 break;
7450 case NEON_2RM_VCEQ0_F:
7452 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7453 tmp2 = tcg_const_i32(0);
7454 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
7455 tcg_temp_free_i32(tmp2);
7456 tcg_temp_free_ptr(fpstatus);
7457 break;
7459 case NEON_2RM_VCLE0_F:
7461 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7462 tmp2 = tcg_const_i32(0);
7463 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
7464 tcg_temp_free_i32(tmp2);
7465 tcg_temp_free_ptr(fpstatus);
7466 break;
7468 case NEON_2RM_VCLT0_F:
7470 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7471 tmp2 = tcg_const_i32(0);
7472 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
7473 tcg_temp_free_i32(tmp2);
7474 tcg_temp_free_ptr(fpstatus);
7475 break;
7477 case NEON_2RM_VABS_F:
7478 gen_vfp_abs(0);
7479 break;
7480 case NEON_2RM_VNEG_F:
7481 gen_vfp_neg(0);
7482 break;
7483 case NEON_2RM_VSWP:
7484 tmp2 = neon_load_reg(rd, pass);
7485 neon_store_reg(rm, pass, tmp2);
7486 break;
7487 case NEON_2RM_VTRN:
7488 tmp2 = neon_load_reg(rd, pass);
7489 switch (size) {
7490 case 0: gen_neon_trn_u8(tmp, tmp2); break;
7491 case 1: gen_neon_trn_u16(tmp, tmp2); break;
7492 default: abort();
7494 neon_store_reg(rm, pass, tmp2);
7495 break;
7496 case NEON_2RM_VRINTN:
7497 case NEON_2RM_VRINTA:
7498 case NEON_2RM_VRINTM:
7499 case NEON_2RM_VRINTP:
7500 case NEON_2RM_VRINTZ:
7502 TCGv_i32 tcg_rmode;
7503 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7504 int rmode;
7506 if (op == NEON_2RM_VRINTZ) {
7507 rmode = FPROUNDING_ZERO;
7508 } else {
7509 rmode = fp_decode_rm[((op & 0x6) >> 1) ^ 1];
7512 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
7513 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
7514 cpu_env);
7515 gen_helper_rints(cpu_F0s, cpu_F0s, fpstatus);
7516 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
7517 cpu_env);
7518 tcg_temp_free_ptr(fpstatus);
7519 tcg_temp_free_i32(tcg_rmode);
7520 break;
7522 case NEON_2RM_VRINTX:
7524 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7525 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpstatus);
7526 tcg_temp_free_ptr(fpstatus);
7527 break;
7529 case NEON_2RM_VCVTAU:
7530 case NEON_2RM_VCVTAS:
7531 case NEON_2RM_VCVTNU:
7532 case NEON_2RM_VCVTNS:
7533 case NEON_2RM_VCVTPU:
7534 case NEON_2RM_VCVTPS:
7535 case NEON_2RM_VCVTMU:
7536 case NEON_2RM_VCVTMS:
7538 bool is_signed = !extract32(insn, 7, 1);
7539 TCGv_ptr fpst = get_fpstatus_ptr(1);
7540 TCGv_i32 tcg_rmode, tcg_shift;
7541 int rmode = fp_decode_rm[extract32(insn, 8, 2)];
7543 tcg_shift = tcg_const_i32(0);
7544 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
7545 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
7546 cpu_env);
7548 if (is_signed) {
7549 gen_helper_vfp_tosls(cpu_F0s, cpu_F0s,
7550 tcg_shift, fpst);
7551 } else {
7552 gen_helper_vfp_touls(cpu_F0s, cpu_F0s,
7553 tcg_shift, fpst);
7556 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
7557 cpu_env);
7558 tcg_temp_free_i32(tcg_rmode);
7559 tcg_temp_free_i32(tcg_shift);
7560 tcg_temp_free_ptr(fpst);
7561 break;
7563 case NEON_2RM_VRECPE:
7565 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7566 gen_helper_recpe_u32(tmp, tmp, fpstatus);
7567 tcg_temp_free_ptr(fpstatus);
7568 break;
7570 case NEON_2RM_VRSQRTE:
7572 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7573 gen_helper_rsqrte_u32(tmp, tmp, fpstatus);
7574 tcg_temp_free_ptr(fpstatus);
7575 break;
7577 case NEON_2RM_VRECPE_F:
7579 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7580 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, fpstatus);
7581 tcg_temp_free_ptr(fpstatus);
7582 break;
7584 case NEON_2RM_VRSQRTE_F:
7586 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7587 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, fpstatus);
7588 tcg_temp_free_ptr(fpstatus);
7589 break;
7591 case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
7592 gen_vfp_sito(0, 1);
7593 break;
7594 case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
7595 gen_vfp_uito(0, 1);
7596 break;
7597 case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
7598 gen_vfp_tosiz(0, 1);
7599 break;
7600 case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
7601 gen_vfp_touiz(0, 1);
7602 break;
7603 default:
7604 /* Reserved op values were caught by the
7605 * neon_2rm_sizes[] check earlier.
7607 abort();
7609 if (neon_2rm_is_float_op(op)) {
7610 tcg_gen_st_f32(cpu_F0s, cpu_env,
7611 neon_reg_offset(rd, pass));
7612 } else {
7613 neon_store_reg(rd, pass, tmp);
7616 break;
7618 } else if ((insn & (1 << 10)) == 0) {
7619 /* VTBL, VTBX. */
7620 int n = ((insn >> 8) & 3) + 1;
7621 if ((rn + n) > 32) {
7622 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
7623 * helper function running off the end of the register file.
7625 return 1;
7627 n <<= 3;
7628 if (insn & (1 << 6)) {
7629 tmp = neon_load_reg(rd, 0);
7630 } else {
7631 tmp = tcg_temp_new_i32();
7632 tcg_gen_movi_i32(tmp, 0);
7634 tmp2 = neon_load_reg(rm, 0);
7635 ptr1 = vfp_reg_ptr(true, rn);
7636 tmp5 = tcg_const_i32(n);
7637 gen_helper_neon_tbl(tmp2, tmp2, tmp, ptr1, tmp5);
7638 tcg_temp_free_i32(tmp);
7639 if (insn & (1 << 6)) {
7640 tmp = neon_load_reg(rd, 1);
7641 } else {
7642 tmp = tcg_temp_new_i32();
7643 tcg_gen_movi_i32(tmp, 0);
7645 tmp3 = neon_load_reg(rm, 1);
7646 gen_helper_neon_tbl(tmp3, tmp3, tmp, ptr1, tmp5);
7647 tcg_temp_free_i32(tmp5);
7648 tcg_temp_free_ptr(ptr1);
7649 neon_store_reg(rd, 0, tmp2);
7650 neon_store_reg(rd, 1, tmp3);
7651 tcg_temp_free_i32(tmp);
7652 } else if ((insn & 0x380) == 0) {
7653 /* VDUP */
7654 int element;
7655 TCGMemOp size;
7657 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
7658 return 1;
7660 if (insn & (1 << 16)) {
7661 size = MO_8;
7662 element = (insn >> 17) & 7;
7663 } else if (insn & (1 << 17)) {
7664 size = MO_16;
7665 element = (insn >> 18) & 3;
7666 } else {
7667 size = MO_32;
7668 element = (insn >> 19) & 1;
7670 tcg_gen_gvec_dup_mem(size, neon_reg_offset(rd, 0),
7671 neon_element_offset(rm, element, size),
7672 q ? 16 : 8, q ? 16 : 8);
7673 } else {
7674 return 1;
7678 return 0;
7681 /* Advanced SIMD three registers of the same length extension.
7682 * 31 25 23 22 20 16 12 11 10 9 8 3 0
7683 * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
7684 * | 1 1 1 1 1 1 0 | op1 | D | op2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
7685 * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
7687 static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
7689 gen_helper_gvec_3 *fn_gvec = NULL;
7690 gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
7691 int rd, rn, rm, opr_sz;
7692 int data = 0;
7693 int off_rn, off_rm;
7694 bool is_long = false, q = extract32(insn, 6, 1);
7695 bool ptr_is_env = false;
7697 if ((insn & 0xfe200f10) == 0xfc200800) {
7698 /* VCMLA -- 1111 110R R.1S .... .... 1000 ...0 .... */
7699 int size = extract32(insn, 20, 1);
7700 data = extract32(insn, 23, 2); /* rot */
7701 if (!dc_isar_feature(aa32_vcma, s)
7702 || (!size && !dc_isar_feature(aa32_fp16_arith, s))) {
7703 return 1;
7705 fn_gvec_ptr = size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
7706 } else if ((insn & 0xfea00f10) == 0xfc800800) {
7707 /* VCADD -- 1111 110R 1.0S .... .... 1000 ...0 .... */
7708 int size = extract32(insn, 20, 1);
7709 data = extract32(insn, 24, 1); /* rot */
7710 if (!dc_isar_feature(aa32_vcma, s)
7711 || (!size && !dc_isar_feature(aa32_fp16_arith, s))) {
7712 return 1;
7714 fn_gvec_ptr = size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
7715 } else if ((insn & 0xfeb00f00) == 0xfc200d00) {
7716 /* V[US]DOT -- 1111 1100 0.10 .... .... 1101 .Q.U .... */
7717 bool u = extract32(insn, 4, 1);
7718 if (!dc_isar_feature(aa32_dp, s)) {
7719 return 1;
7721 fn_gvec = u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b;
7722 } else if ((insn & 0xff300f10) == 0xfc200810) {
7723 /* VFM[AS]L -- 1111 1100 S.10 .... .... 1000 .Q.1 .... */
7724 int is_s = extract32(insn, 23, 1);
7725 if (!dc_isar_feature(aa32_fhm, s)) {
7726 return 1;
7728 is_long = true;
7729 data = is_s; /* is_2 == 0 */
7730 fn_gvec_ptr = gen_helper_gvec_fmlal_a32;
7731 ptr_is_env = true;
7732 } else {
7733 return 1;
7736 VFP_DREG_D(rd, insn);
7737 if (rd & q) {
7738 return 1;
7740 if (q || !is_long) {
7741 VFP_DREG_N(rn, insn);
7742 VFP_DREG_M(rm, insn);
7743 if ((rn | rm) & q & !is_long) {
7744 return 1;
7746 off_rn = vfp_reg_offset(1, rn);
7747 off_rm = vfp_reg_offset(1, rm);
7748 } else {
7749 rn = VFP_SREG_N(insn);
7750 rm = VFP_SREG_M(insn);
7751 off_rn = vfp_reg_offset(0, rn);
7752 off_rm = vfp_reg_offset(0, rm);
7755 if (s->fp_excp_el) {
7756 gen_exception_insn(s, 4, EXCP_UDEF,
7757 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
7758 return 0;
7760 if (!s->vfp_enabled) {
7761 return 1;
7764 opr_sz = (1 + q) * 8;
7765 if (fn_gvec_ptr) {
7766 TCGv_ptr ptr;
7767 if (ptr_is_env) {
7768 ptr = cpu_env;
7769 } else {
7770 ptr = get_fpstatus_ptr(1);
7772 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
7773 opr_sz, opr_sz, data, fn_gvec_ptr);
7774 if (!ptr_is_env) {
7775 tcg_temp_free_ptr(ptr);
7777 } else {
7778 tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
7779 opr_sz, opr_sz, data, fn_gvec);
7781 return 0;
7784 /* Advanced SIMD two registers and a scalar extension.
7785 * 31 24 23 22 20 16 12 11 10 9 8 3 0
7786 * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
7787 * | 1 1 1 1 1 1 1 0 | o1 | D | o2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
7788 * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
7792 static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
7794 gen_helper_gvec_3 *fn_gvec = NULL;
7795 gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
7796 int rd, rn, rm, opr_sz, data;
7797 int off_rn, off_rm;
7798 bool is_long = false, q = extract32(insn, 6, 1);
7799 bool ptr_is_env = false;
7801 if ((insn & 0xff000f10) == 0xfe000800) {
7802 /* VCMLA (indexed) -- 1111 1110 S.RR .... .... 1000 ...0 .... */
7803 int rot = extract32(insn, 20, 2);
7804 int size = extract32(insn, 23, 1);
7805 int index;
7807 if (!dc_isar_feature(aa32_vcma, s)) {
7808 return 1;
7810 if (size == 0) {
7811 if (!dc_isar_feature(aa32_fp16_arith, s)) {
7812 return 1;
7814 /* For fp16, rm is just Vm, and index is M. */
7815 rm = extract32(insn, 0, 4);
7816 index = extract32(insn, 5, 1);
7817 } else {
7818 /* For fp32, rm is the usual M:Vm, and index is 0. */
7819 VFP_DREG_M(rm, insn);
7820 index = 0;
7822 data = (index << 2) | rot;
7823 fn_gvec_ptr = (size ? gen_helper_gvec_fcmlas_idx
7824 : gen_helper_gvec_fcmlah_idx);
7825 } else if ((insn & 0xffb00f00) == 0xfe200d00) {
7826 /* V[US]DOT -- 1111 1110 0.10 .... .... 1101 .Q.U .... */
7827 int u = extract32(insn, 4, 1);
7829 if (!dc_isar_feature(aa32_dp, s)) {
7830 return 1;
7832 fn_gvec = u ? gen_helper_gvec_udot_idx_b : gen_helper_gvec_sdot_idx_b;
7833 /* rm is just Vm, and index is M. */
7834 data = extract32(insn, 5, 1); /* index */
7835 rm = extract32(insn, 0, 4);
7836 } else if ((insn & 0xffa00f10) == 0xfe000810) {
7837 /* VFM[AS]L -- 1111 1110 0.0S .... .... 1000 .Q.1 .... */
7838 int is_s = extract32(insn, 20, 1);
7839 int vm20 = extract32(insn, 0, 3);
7840 int vm3 = extract32(insn, 3, 1);
7841 int m = extract32(insn, 5, 1);
7842 int index;
7844 if (!dc_isar_feature(aa32_fhm, s)) {
7845 return 1;
7847 if (q) {
7848 rm = vm20;
7849 index = m * 2 + vm3;
7850 } else {
7851 rm = vm20 * 2 + m;
7852 index = vm3;
7854 is_long = true;
7855 data = (index << 2) | is_s; /* is_2 == 0 */
7856 fn_gvec_ptr = gen_helper_gvec_fmlal_idx_a32;
7857 ptr_is_env = true;
7858 } else {
7859 return 1;
7862 VFP_DREG_D(rd, insn);
7863 if (rd & q) {
7864 return 1;
7866 if (q || !is_long) {
7867 VFP_DREG_N(rn, insn);
7868 if (rn & q & !is_long) {
7869 return 1;
7871 off_rn = vfp_reg_offset(1, rn);
7872 off_rm = vfp_reg_offset(1, rm);
7873 } else {
7874 rn = VFP_SREG_N(insn);
7875 off_rn = vfp_reg_offset(0, rn);
7876 off_rm = vfp_reg_offset(0, rm);
7878 if (s->fp_excp_el) {
7879 gen_exception_insn(s, 4, EXCP_UDEF,
7880 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
7881 return 0;
7883 if (!s->vfp_enabled) {
7884 return 1;
7887 opr_sz = (1 + q) * 8;
7888 if (fn_gvec_ptr) {
7889 TCGv_ptr ptr;
7890 if (ptr_is_env) {
7891 ptr = cpu_env;
7892 } else {
7893 ptr = get_fpstatus_ptr(1);
7895 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
7896 opr_sz, opr_sz, data, fn_gvec_ptr);
7897 if (!ptr_is_env) {
7898 tcg_temp_free_ptr(ptr);
7900 } else {
7901 tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
7902 opr_sz, opr_sz, data, fn_gvec);
7904 return 0;
7907 static int disas_coproc_insn(DisasContext *s, uint32_t insn)
7909 int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
7910 const ARMCPRegInfo *ri;
7912 cpnum = (insn >> 8) & 0xf;
7914 /* First check for coprocessor space used for XScale/iwMMXt insns */
7915 if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cpnum < 2)) {
7916 if (extract32(s->c15_cpar, cpnum, 1) == 0) {
7917 return 1;
7919 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
7920 return disas_iwmmxt_insn(s, insn);
7921 } else if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
7922 return disas_dsp_insn(s, insn);
7924 return 1;
7927 /* Otherwise treat as a generic register access */
7928 is64 = (insn & (1 << 25)) == 0;
7929 if (!is64 && ((insn & (1 << 4)) == 0)) {
7930 /* cdp */
7931 return 1;
7934 crm = insn & 0xf;
7935 if (is64) {
7936 crn = 0;
7937 opc1 = (insn >> 4) & 0xf;
7938 opc2 = 0;
7939 rt2 = (insn >> 16) & 0xf;
7940 } else {
7941 crn = (insn >> 16) & 0xf;
7942 opc1 = (insn >> 21) & 7;
7943 opc2 = (insn >> 5) & 7;
7944 rt2 = 0;
7946 isread = (insn >> 20) & 1;
7947 rt = (insn >> 12) & 0xf;
7949 ri = get_arm_cp_reginfo(s->cp_regs,
7950 ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
7951 if (ri) {
7952 /* Check access permissions */
7953 if (!cp_access_ok(s->current_el, ri, isread)) {
7954 return 1;
7957 if (ri->accessfn ||
7958 (arm_dc_feature(s, ARM_FEATURE_XSCALE) && cpnum < 14)) {
7959 /* Emit code to perform further access permissions checks at
7960 * runtime; this may result in an exception.
7961 * Note that on XScale all cp0..c13 registers do an access check
7962 * call in order to handle c15_cpar.
7964 TCGv_ptr tmpptr;
7965 TCGv_i32 tcg_syn, tcg_isread;
7966 uint32_t syndrome;
7968 /* Note that since we are an implementation which takes an
7969 * exception on a trapped conditional instruction only if the
7970 * instruction passes its condition code check, we can take
7971 * advantage of the clause in the ARM ARM that allows us to set
7972 * the COND field in the instruction to 0xE in all cases.
7973 * We could fish the actual condition out of the insn (ARM)
7974 * or the condexec bits (Thumb) but it isn't necessary.
7976 switch (cpnum) {
7977 case 14:
7978 if (is64) {
7979 syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
7980 isread, false);
7981 } else {
7982 syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
7983 rt, isread, false);
7985 break;
7986 case 15:
7987 if (is64) {
7988 syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
7989 isread, false);
7990 } else {
7991 syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
7992 rt, isread, false);
7994 break;
7995 default:
7996 /* ARMv8 defines that only coprocessors 14 and 15 exist,
7997 * so this can only happen if this is an ARMv7 or earlier CPU,
7998 * in which case the syndrome information won't actually be
7999 * guest visible.
8001 assert(!arm_dc_feature(s, ARM_FEATURE_V8));
8002 syndrome = syn_uncategorized();
8003 break;
8006 gen_set_condexec(s);
8007 gen_set_pc_im(s, s->pc - 4);
8008 tmpptr = tcg_const_ptr(ri);
8009 tcg_syn = tcg_const_i32(syndrome);
8010 tcg_isread = tcg_const_i32(isread);
8011 gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn,
8012 tcg_isread);
8013 tcg_temp_free_ptr(tmpptr);
8014 tcg_temp_free_i32(tcg_syn);
8015 tcg_temp_free_i32(tcg_isread);
8018 /* Handle special cases first */
8019 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
8020 case ARM_CP_NOP:
8021 return 0;
8022 case ARM_CP_WFI:
8023 if (isread) {
8024 return 1;
8026 gen_set_pc_im(s, s->pc);
8027 s->base.is_jmp = DISAS_WFI;
8028 return 0;
8029 default:
8030 break;
8033 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
8034 gen_io_start();
8037 if (isread) {
8038 /* Read */
8039 if (is64) {
8040 TCGv_i64 tmp64;
8041 TCGv_i32 tmp;
8042 if (ri->type & ARM_CP_CONST) {
8043 tmp64 = tcg_const_i64(ri->resetvalue);
8044 } else if (ri->readfn) {
8045 TCGv_ptr tmpptr;
8046 tmp64 = tcg_temp_new_i64();
8047 tmpptr = tcg_const_ptr(ri);
8048 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
8049 tcg_temp_free_ptr(tmpptr);
8050 } else {
8051 tmp64 = tcg_temp_new_i64();
8052 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
8054 tmp = tcg_temp_new_i32();
8055 tcg_gen_extrl_i64_i32(tmp, tmp64);
8056 store_reg(s, rt, tmp);
8057 tcg_gen_shri_i64(tmp64, tmp64, 32);
8058 tmp = tcg_temp_new_i32();
8059 tcg_gen_extrl_i64_i32(tmp, tmp64);
8060 tcg_temp_free_i64(tmp64);
8061 store_reg(s, rt2, tmp);
8062 } else {
8063 TCGv_i32 tmp;
8064 if (ri->type & ARM_CP_CONST) {
8065 tmp = tcg_const_i32(ri->resetvalue);
8066 } else if (ri->readfn) {
8067 TCGv_ptr tmpptr;
8068 tmp = tcg_temp_new_i32();
8069 tmpptr = tcg_const_ptr(ri);
8070 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
8071 tcg_temp_free_ptr(tmpptr);
8072 } else {
8073 tmp = load_cpu_offset(ri->fieldoffset);
8075 if (rt == 15) {
8076 /* Destination register of r15 for 32 bit loads sets
8077 * the condition codes from the high 4 bits of the value
8079 gen_set_nzcv(tmp);
8080 tcg_temp_free_i32(tmp);
8081 } else {
8082 store_reg(s, rt, tmp);
8085 } else {
8086 /* Write */
8087 if (ri->type & ARM_CP_CONST) {
8088 /* If not forbidden by access permissions, treat as WI */
8089 return 0;
8092 if (is64) {
8093 TCGv_i32 tmplo, tmphi;
8094 TCGv_i64 tmp64 = tcg_temp_new_i64();
8095 tmplo = load_reg(s, rt);
8096 tmphi = load_reg(s, rt2);
8097 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
8098 tcg_temp_free_i32(tmplo);
8099 tcg_temp_free_i32(tmphi);
8100 if (ri->writefn) {
8101 TCGv_ptr tmpptr = tcg_const_ptr(ri);
8102 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
8103 tcg_temp_free_ptr(tmpptr);
8104 } else {
8105 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
8107 tcg_temp_free_i64(tmp64);
8108 } else {
8109 if (ri->writefn) {
8110 TCGv_i32 tmp;
8111 TCGv_ptr tmpptr;
8112 tmp = load_reg(s, rt);
8113 tmpptr = tcg_const_ptr(ri);
8114 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
8115 tcg_temp_free_ptr(tmpptr);
8116 tcg_temp_free_i32(tmp);
8117 } else {
8118 TCGv_i32 tmp = load_reg(s, rt);
8119 store_cpu_offset(tmp, ri->fieldoffset);
8124 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
8125 /* I/O operations must end the TB here (whether read or write) */
8126 gen_io_end();
8127 gen_lookup_tb(s);
8128 } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
8129 /* We default to ending the TB on a coprocessor register write,
8130 * but allow this to be suppressed by the register definition
8131 * (usually only necessary to work around guest bugs).
8133 gen_lookup_tb(s);
8136 return 0;
8139 /* Unknown register; this might be a guest error or a QEMU
8140 * unimplemented feature.
8142 if (is64) {
8143 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
8144 "64 bit system register cp:%d opc1: %d crm:%d "
8145 "(%s)\n",
8146 isread ? "read" : "write", cpnum, opc1, crm,
8147 s->ns ? "non-secure" : "secure");
8148 } else {
8149 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
8150 "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d "
8151 "(%s)\n",
8152 isread ? "read" : "write", cpnum, opc1, crn, crm, opc2,
8153 s->ns ? "non-secure" : "secure");
8156 return 1;
8160 /* Store a 64-bit value to a register pair. Clobbers val. */
8161 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
8163 TCGv_i32 tmp;
8164 tmp = tcg_temp_new_i32();
8165 tcg_gen_extrl_i64_i32(tmp, val);
8166 store_reg(s, rlow, tmp);
8167 tmp = tcg_temp_new_i32();
8168 tcg_gen_shri_i64(val, val, 32);
8169 tcg_gen_extrl_i64_i32(tmp, val);
8170 store_reg(s, rhigh, tmp);
8173 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
8174 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
8176 TCGv_i64 tmp;
8177 TCGv_i32 tmp2;
8179 /* Load value and extend to 64 bits. */
8180 tmp = tcg_temp_new_i64();
8181 tmp2 = load_reg(s, rlow);
8182 tcg_gen_extu_i32_i64(tmp, tmp2);
8183 tcg_temp_free_i32(tmp2);
8184 tcg_gen_add_i64(val, val, tmp);
8185 tcg_temp_free_i64(tmp);
8188 /* load and add a 64-bit value from a register pair. */
8189 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
8191 TCGv_i64 tmp;
8192 TCGv_i32 tmpl;
8193 TCGv_i32 tmph;
8195 /* Load 64-bit value rd:rn. */
8196 tmpl = load_reg(s, rlow);
8197 tmph = load_reg(s, rhigh);
8198 tmp = tcg_temp_new_i64();
8199 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
8200 tcg_temp_free_i32(tmpl);
8201 tcg_temp_free_i32(tmph);
8202 tcg_gen_add_i64(val, val, tmp);
8203 tcg_temp_free_i64(tmp);
8206 /* Set N and Z flags from hi|lo. */
8207 static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
8209 tcg_gen_mov_i32(cpu_NF, hi);
8210 tcg_gen_or_i32(cpu_ZF, lo, hi);
8213 /* Load/Store exclusive instructions are implemented by remembering
8214 the value/address loaded, and seeing if these are the same
8215 when the store is performed. This should be sufficient to implement
8216 the architecturally mandated semantics, and avoids having to monitor
8217 regular stores. The compare vs the remembered value is done during
8218 the cmpxchg operation, but we must compare the addresses manually. */
8219 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
8220 TCGv_i32 addr, int size)
8222 TCGv_i32 tmp = tcg_temp_new_i32();
8223 TCGMemOp opc = size | MO_ALIGN | s->be_data;
8225 s->is_ldex = true;
8227 if (size == 3) {
8228 TCGv_i32 tmp2 = tcg_temp_new_i32();
8229 TCGv_i64 t64 = tcg_temp_new_i64();
8231 /* For AArch32, architecturally the 32-bit word at the lowest
8232 * address is always Rt and the one at addr+4 is Rt2, even if
8233 * the CPU is big-endian. That means we don't want to do a
8234 * gen_aa32_ld_i64(), which invokes gen_aa32_frob64() as if
8235 * for an architecturally 64-bit access, but instead do a
8236 * 64-bit access using MO_BE if appropriate and then split
8237 * the two halves.
8238 * This only makes a difference for BE32 user-mode, where
8239 * frob64() must not flip the two halves of the 64-bit data
8240 * but this code must treat BE32 user-mode like BE32 system.
8242 TCGv taddr = gen_aa32_addr(s, addr, opc);
8244 tcg_gen_qemu_ld_i64(t64, taddr, get_mem_index(s), opc);
8245 tcg_temp_free(taddr);
8246 tcg_gen_mov_i64(cpu_exclusive_val, t64);
8247 if (s->be_data == MO_BE) {
8248 tcg_gen_extr_i64_i32(tmp2, tmp, t64);
8249 } else {
8250 tcg_gen_extr_i64_i32(tmp, tmp2, t64);
8252 tcg_temp_free_i64(t64);
8254 store_reg(s, rt2, tmp2);
8255 } else {
8256 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), opc);
8257 tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
8260 store_reg(s, rt, tmp);
8261 tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
8264 static void gen_clrex(DisasContext *s)
8266 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
8269 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
8270 TCGv_i32 addr, int size)
8272 TCGv_i32 t0, t1, t2;
8273 TCGv_i64 extaddr;
8274 TCGv taddr;
8275 TCGLabel *done_label;
8276 TCGLabel *fail_label;
8277 TCGMemOp opc = size | MO_ALIGN | s->be_data;
8279 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
8280 [addr] = {Rt};
8281 {Rd} = 0;
8282 } else {
8283 {Rd} = 1;
8284 } */
8285 fail_label = gen_new_label();
8286 done_label = gen_new_label();
8287 extaddr = tcg_temp_new_i64();
8288 tcg_gen_extu_i32_i64(extaddr, addr);
8289 tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
8290 tcg_temp_free_i64(extaddr);
8292 taddr = gen_aa32_addr(s, addr, opc);
8293 t0 = tcg_temp_new_i32();
8294 t1 = load_reg(s, rt);
8295 if (size == 3) {
8296 TCGv_i64 o64 = tcg_temp_new_i64();
8297 TCGv_i64 n64 = tcg_temp_new_i64();
8299 t2 = load_reg(s, rt2);
8300 /* For AArch32, architecturally the 32-bit word at the lowest
8301 * address is always Rt and the one at addr+4 is Rt2, even if
8302 * the CPU is big-endian. Since we're going to treat this as a
8303 * single 64-bit BE store, we need to put the two halves in the
8304 * opposite order for BE to LE, so that they end up in the right
8305 * places.
8306 * We don't want gen_aa32_frob64() because that does the wrong
8307 * thing for BE32 usermode.
8309 if (s->be_data == MO_BE) {
8310 tcg_gen_concat_i32_i64(n64, t2, t1);
8311 } else {
8312 tcg_gen_concat_i32_i64(n64, t1, t2);
8314 tcg_temp_free_i32(t2);
8316 tcg_gen_atomic_cmpxchg_i64(o64, taddr, cpu_exclusive_val, n64,
8317 get_mem_index(s), opc);
8318 tcg_temp_free_i64(n64);
8320 tcg_gen_setcond_i64(TCG_COND_NE, o64, o64, cpu_exclusive_val);
8321 tcg_gen_extrl_i64_i32(t0, o64);
8323 tcg_temp_free_i64(o64);
8324 } else {
8325 t2 = tcg_temp_new_i32();
8326 tcg_gen_extrl_i64_i32(t2, cpu_exclusive_val);
8327 tcg_gen_atomic_cmpxchg_i32(t0, taddr, t2, t1, get_mem_index(s), opc);
8328 tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t2);
8329 tcg_temp_free_i32(t2);
8331 tcg_temp_free_i32(t1);
8332 tcg_temp_free(taddr);
8333 tcg_gen_mov_i32(cpu_R[rd], t0);
8334 tcg_temp_free_i32(t0);
8335 tcg_gen_br(done_label);
8337 gen_set_label(fail_label);
8338 tcg_gen_movi_i32(cpu_R[rd], 1);
8339 gen_set_label(done_label);
8340 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
8343 /* gen_srs:
8344 * @env: CPUARMState
8345 * @s: DisasContext
8346 * @mode: mode field from insn (which stack to store to)
8347 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
8348 * @writeback: true if writeback bit set
8350 * Generate code for the SRS (Store Return State) insn.
8352 static void gen_srs(DisasContext *s,
8353 uint32_t mode, uint32_t amode, bool writeback)
8355 int32_t offset;
8356 TCGv_i32 addr, tmp;
8357 bool undef = false;
8359 /* SRS is:
8360 * - trapped to EL3 if EL3 is AArch64 and we are at Secure EL1
8361 * and specified mode is monitor mode
8362 * - UNDEFINED in Hyp mode
8363 * - UNPREDICTABLE in User or System mode
8364 * - UNPREDICTABLE if the specified mode is:
8365 * -- not implemented
8366 * -- not a valid mode number
8367 * -- a mode that's at a higher exception level
8368 * -- Monitor, if we are Non-secure
8369 * For the UNPREDICTABLE cases we choose to UNDEF.
8371 if (s->current_el == 1 && !s->ns && mode == ARM_CPU_MODE_MON) {
8372 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), 3);
8373 return;
8376 if (s->current_el == 0 || s->current_el == 2) {
8377 undef = true;
8380 switch (mode) {
8381 case ARM_CPU_MODE_USR:
8382 case ARM_CPU_MODE_FIQ:
8383 case ARM_CPU_MODE_IRQ:
8384 case ARM_CPU_MODE_SVC:
8385 case ARM_CPU_MODE_ABT:
8386 case ARM_CPU_MODE_UND:
8387 case ARM_CPU_MODE_SYS:
8388 break;
8389 case ARM_CPU_MODE_HYP:
8390 if (s->current_el == 1 || !arm_dc_feature(s, ARM_FEATURE_EL2)) {
8391 undef = true;
8393 break;
8394 case ARM_CPU_MODE_MON:
8395 /* No need to check specifically for "are we non-secure" because
8396 * we've already made EL0 UNDEF and handled the trap for S-EL1;
8397 * so if this isn't EL3 then we must be non-secure.
8399 if (s->current_el != 3) {
8400 undef = true;
8402 break;
8403 default:
8404 undef = true;
8407 if (undef) {
8408 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
8409 default_exception_el(s));
8410 return;
8413 addr = tcg_temp_new_i32();
8414 tmp = tcg_const_i32(mode);
8415 /* get_r13_banked() will raise an exception if called from System mode */
8416 gen_set_condexec(s);
8417 gen_set_pc_im(s, s->pc - 4);
8418 gen_helper_get_r13_banked(addr, cpu_env, tmp);
8419 tcg_temp_free_i32(tmp);
8420 switch (amode) {
8421 case 0: /* DA */
8422 offset = -4;
8423 break;
8424 case 1: /* IA */
8425 offset = 0;
8426 break;
8427 case 2: /* DB */
8428 offset = -8;
8429 break;
8430 case 3: /* IB */
8431 offset = 4;
8432 break;
8433 default:
8434 abort();
8436 tcg_gen_addi_i32(addr, addr, offset);
8437 tmp = load_reg(s, 14);
8438 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
8439 tcg_temp_free_i32(tmp);
8440 tmp = load_cpu_field(spsr);
8441 tcg_gen_addi_i32(addr, addr, 4);
8442 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
8443 tcg_temp_free_i32(tmp);
8444 if (writeback) {
8445 switch (amode) {
8446 case 0:
8447 offset = -8;
8448 break;
8449 case 1:
8450 offset = 4;
8451 break;
8452 case 2:
8453 offset = -4;
8454 break;
8455 case 3:
8456 offset = 0;
8457 break;
8458 default:
8459 abort();
8461 tcg_gen_addi_i32(addr, addr, offset);
8462 tmp = tcg_const_i32(mode);
8463 gen_helper_set_r13_banked(cpu_env, tmp, addr);
8464 tcg_temp_free_i32(tmp);
8466 tcg_temp_free_i32(addr);
8467 s->base.is_jmp = DISAS_UPDATE;
8470 /* Generate a label used for skipping this instruction */
8471 static void arm_gen_condlabel(DisasContext *s)
8473 if (!s->condjmp) {
8474 s->condlabel = gen_new_label();
8475 s->condjmp = 1;
8479 /* Skip this instruction if the ARM condition is false */
8480 static void arm_skip_unless(DisasContext *s, uint32_t cond)
8482 arm_gen_condlabel(s);
8483 arm_gen_test_cc(cond ^ 1, s->condlabel);
8486 static void disas_arm_insn(DisasContext *s, unsigned int insn)
8488 unsigned int cond, val, op1, i, shift, rm, rs, rn, rd, sh;
8489 TCGv_i32 tmp;
8490 TCGv_i32 tmp2;
8491 TCGv_i32 tmp3;
8492 TCGv_i32 addr;
8493 TCGv_i64 tmp64;
8495 /* M variants do not implement ARM mode; this must raise the INVSTATE
8496 * UsageFault exception.
8498 if (arm_dc_feature(s, ARM_FEATURE_M)) {
8499 gen_exception_insn(s, 4, EXCP_INVSTATE, syn_uncategorized(),
8500 default_exception_el(s));
8501 return;
8503 cond = insn >> 28;
8504 if (cond == 0xf){
8505 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
8506 * choose to UNDEF. In ARMv5 and above the space is used
8507 * for miscellaneous unconditional instructions.
8509 ARCH(5);
8511 /* Unconditional instructions. */
8512 if (((insn >> 25) & 7) == 1) {
8513 /* NEON Data processing. */
8514 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
8515 goto illegal_op;
8518 if (disas_neon_data_insn(s, insn)) {
8519 goto illegal_op;
8521 return;
8523 if ((insn & 0x0f100000) == 0x04000000) {
8524 /* NEON load/store. */
8525 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
8526 goto illegal_op;
8529 if (disas_neon_ls_insn(s, insn)) {
8530 goto illegal_op;
8532 return;
8534 if ((insn & 0x0f000e10) == 0x0e000a00) {
8535 /* VFP. */
8536 if (disas_vfp_insn(s, insn)) {
8537 goto illegal_op;
8539 return;
8541 if (((insn & 0x0f30f000) == 0x0510f000) ||
8542 ((insn & 0x0f30f010) == 0x0710f000)) {
8543 if ((insn & (1 << 22)) == 0) {
8544 /* PLDW; v7MP */
8545 if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
8546 goto illegal_op;
8549 /* Otherwise PLD; v5TE+ */
8550 ARCH(5TE);
8551 return;
8553 if (((insn & 0x0f70f000) == 0x0450f000) ||
8554 ((insn & 0x0f70f010) == 0x0650f000)) {
8555 ARCH(7);
8556 return; /* PLI; V7 */
8558 if (((insn & 0x0f700000) == 0x04100000) ||
8559 ((insn & 0x0f700010) == 0x06100000)) {
8560 if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
8561 goto illegal_op;
8563 return; /* v7MP: Unallocated memory hint: must NOP */
8566 if ((insn & 0x0ffffdff) == 0x01010000) {
8567 ARCH(6);
8568 /* setend */
8569 if (((insn >> 9) & 1) != !!(s->be_data == MO_BE)) {
8570 gen_helper_setend(cpu_env);
8571 s->base.is_jmp = DISAS_UPDATE;
8573 return;
8574 } else if ((insn & 0x0fffff00) == 0x057ff000) {
8575 switch ((insn >> 4) & 0xf) {
8576 case 1: /* clrex */
8577 ARCH(6K);
8578 gen_clrex(s);
8579 return;
8580 case 4: /* dsb */
8581 case 5: /* dmb */
8582 ARCH(7);
8583 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
8584 return;
8585 case 6: /* isb */
8586 /* We need to break the TB after this insn to execute
8587 * self-modifying code correctly and also to take
8588 * any pending interrupts immediately.
8590 gen_goto_tb(s, 0, s->pc & ~1);
8591 return;
8592 case 7: /* sb */
8593 if ((insn & 0xf) || !dc_isar_feature(aa32_sb, s)) {
8594 goto illegal_op;
8597 * TODO: There is no speculation barrier opcode
8598 * for TCG; MB and end the TB instead.
8600 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
8601 gen_goto_tb(s, 0, s->pc & ~1);
8602 return;
8603 default:
8604 goto illegal_op;
8606 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
8607 /* srs */
8608 ARCH(6);
8609 gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21));
8610 return;
8611 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
8612 /* rfe */
8613 int32_t offset;
8614 if (IS_USER(s))
8615 goto illegal_op;
8616 ARCH(6);
8617 rn = (insn >> 16) & 0xf;
8618 addr = load_reg(s, rn);
8619 i = (insn >> 23) & 3;
8620 switch (i) {
8621 case 0: offset = -4; break; /* DA */
8622 case 1: offset = 0; break; /* IA */
8623 case 2: offset = -8; break; /* DB */
8624 case 3: offset = 4; break; /* IB */
8625 default: abort();
8627 if (offset)
8628 tcg_gen_addi_i32(addr, addr, offset);
8629 /* Load PC into tmp and CPSR into tmp2. */
8630 tmp = tcg_temp_new_i32();
8631 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
8632 tcg_gen_addi_i32(addr, addr, 4);
8633 tmp2 = tcg_temp_new_i32();
8634 gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
8635 if (insn & (1 << 21)) {
8636 /* Base writeback. */
8637 switch (i) {
8638 case 0: offset = -8; break;
8639 case 1: offset = 4; break;
8640 case 2: offset = -4; break;
8641 case 3: offset = 0; break;
8642 default: abort();
8644 if (offset)
8645 tcg_gen_addi_i32(addr, addr, offset);
8646 store_reg(s, rn, addr);
8647 } else {
8648 tcg_temp_free_i32(addr);
8650 gen_rfe(s, tmp, tmp2);
8651 return;
8652 } else if ((insn & 0x0e000000) == 0x0a000000) {
8653 /* branch link and change to thumb (blx <offset>) */
8654 int32_t offset;
8656 val = (uint32_t)s->pc;
8657 tmp = tcg_temp_new_i32();
8658 tcg_gen_movi_i32(tmp, val);
8659 store_reg(s, 14, tmp);
8660 /* Sign-extend the 24-bit offset */
8661 offset = (((int32_t)insn) << 8) >> 8;
8662 /* offset * 4 + bit24 * 2 + (thumb bit) */
8663 val += (offset << 2) | ((insn >> 23) & 2) | 1;
8664 /* pipeline offset */
8665 val += 4;
8666 /* protected by ARCH(5); above, near the start of uncond block */
8667 gen_bx_im(s, val);
8668 return;
8669 } else if ((insn & 0x0e000f00) == 0x0c000100) {
8670 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
8671 /* iWMMXt register transfer. */
8672 if (extract32(s->c15_cpar, 1, 1)) {
8673 if (!disas_iwmmxt_insn(s, insn)) {
8674 return;
8678 } else if ((insn & 0x0e000a00) == 0x0c000800
8679 && arm_dc_feature(s, ARM_FEATURE_V8)) {
8680 if (disas_neon_insn_3same_ext(s, insn)) {
8681 goto illegal_op;
8683 return;
8684 } else if ((insn & 0x0f000a00) == 0x0e000800
8685 && arm_dc_feature(s, ARM_FEATURE_V8)) {
8686 if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
8687 goto illegal_op;
8689 return;
8690 } else if ((insn & 0x0fe00000) == 0x0c400000) {
8691 /* Coprocessor double register transfer. */
8692 ARCH(5TE);
8693 } else if ((insn & 0x0f000010) == 0x0e000010) {
8694 /* Additional coprocessor register transfer. */
8695 } else if ((insn & 0x0ff10020) == 0x01000000) {
8696 uint32_t mask;
8697 uint32_t val;
8698 /* cps (privileged) */
8699 if (IS_USER(s))
8700 return;
8701 mask = val = 0;
8702 if (insn & (1 << 19)) {
8703 if (insn & (1 << 8))
8704 mask |= CPSR_A;
8705 if (insn & (1 << 7))
8706 mask |= CPSR_I;
8707 if (insn & (1 << 6))
8708 mask |= CPSR_F;
8709 if (insn & (1 << 18))
8710 val |= mask;
8712 if (insn & (1 << 17)) {
8713 mask |= CPSR_M;
8714 val |= (insn & 0x1f);
8716 if (mask) {
8717 gen_set_psr_im(s, mask, 0, val);
8719 return;
8721 goto illegal_op;
8723 if (cond != 0xe) {
8724 /* if not always execute, we generate a conditional jump to
8725 next instruction */
8726 arm_skip_unless(s, cond);
8728 if ((insn & 0x0f900000) == 0x03000000) {
8729 if ((insn & (1 << 21)) == 0) {
8730 ARCH(6T2);
8731 rd = (insn >> 12) & 0xf;
8732 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
8733 if ((insn & (1 << 22)) == 0) {
8734 /* MOVW */
8735 tmp = tcg_temp_new_i32();
8736 tcg_gen_movi_i32(tmp, val);
8737 } else {
8738 /* MOVT */
8739 tmp = load_reg(s, rd);
8740 tcg_gen_ext16u_i32(tmp, tmp);
8741 tcg_gen_ori_i32(tmp, tmp, val << 16);
8743 store_reg(s, rd, tmp);
8744 } else {
8745 if (((insn >> 12) & 0xf) != 0xf)
8746 goto illegal_op;
8747 if (((insn >> 16) & 0xf) == 0) {
8748 gen_nop_hint(s, insn & 0xff);
8749 } else {
8750 /* CPSR = immediate */
8751 val = insn & 0xff;
8752 shift = ((insn >> 8) & 0xf) * 2;
8753 if (shift)
8754 val = (val >> shift) | (val << (32 - shift));
8755 i = ((insn & (1 << 22)) != 0);
8756 if (gen_set_psr_im(s, msr_mask(s, (insn >> 16) & 0xf, i),
8757 i, val)) {
8758 goto illegal_op;
8762 } else if ((insn & 0x0f900000) == 0x01000000
8763 && (insn & 0x00000090) != 0x00000090) {
8764 /* miscellaneous instructions */
8765 op1 = (insn >> 21) & 3;
8766 sh = (insn >> 4) & 0xf;
8767 rm = insn & 0xf;
8768 switch (sh) {
8769 case 0x0: /* MSR, MRS */
8770 if (insn & (1 << 9)) {
8771 /* MSR (banked) and MRS (banked) */
8772 int sysm = extract32(insn, 16, 4) |
8773 (extract32(insn, 8, 1) << 4);
8774 int r = extract32(insn, 22, 1);
8776 if (op1 & 1) {
8777 /* MSR (banked) */
8778 gen_msr_banked(s, r, sysm, rm);
8779 } else {
8780 /* MRS (banked) */
8781 int rd = extract32(insn, 12, 4);
8783 gen_mrs_banked(s, r, sysm, rd);
8785 break;
8788 /* MSR, MRS (for PSRs) */
8789 if (op1 & 1) {
8790 /* PSR = reg */
8791 tmp = load_reg(s, rm);
8792 i = ((op1 & 2) != 0);
8793 if (gen_set_psr(s, msr_mask(s, (insn >> 16) & 0xf, i), i, tmp))
8794 goto illegal_op;
8795 } else {
8796 /* reg = PSR */
8797 rd = (insn >> 12) & 0xf;
8798 if (op1 & 2) {
8799 if (IS_USER(s))
8800 goto illegal_op;
8801 tmp = load_cpu_field(spsr);
8802 } else {
8803 tmp = tcg_temp_new_i32();
8804 gen_helper_cpsr_read(tmp, cpu_env);
8806 store_reg(s, rd, tmp);
8808 break;
8809 case 0x1:
8810 if (op1 == 1) {
8811 /* branch/exchange thumb (bx). */
8812 ARCH(4T);
8813 tmp = load_reg(s, rm);
8814 gen_bx(s, tmp);
8815 } else if (op1 == 3) {
8816 /* clz */
8817 ARCH(5);
8818 rd = (insn >> 12) & 0xf;
8819 tmp = load_reg(s, rm);
8820 tcg_gen_clzi_i32(tmp, tmp, 32);
8821 store_reg(s, rd, tmp);
8822 } else {
8823 goto illegal_op;
8825 break;
8826 case 0x2:
8827 if (op1 == 1) {
8828 ARCH(5J); /* bxj */
8829 /* Trivial implementation equivalent to bx. */
8830 tmp = load_reg(s, rm);
8831 gen_bx(s, tmp);
8832 } else {
8833 goto illegal_op;
8835 break;
8836 case 0x3:
8837 if (op1 != 1)
8838 goto illegal_op;
8840 ARCH(5);
8841 /* branch link/exchange thumb (blx) */
8842 tmp = load_reg(s, rm);
8843 tmp2 = tcg_temp_new_i32();
8844 tcg_gen_movi_i32(tmp2, s->pc);
8845 store_reg(s, 14, tmp2);
8846 gen_bx(s, tmp);
8847 break;
8848 case 0x4:
8850 /* crc32/crc32c */
8851 uint32_t c = extract32(insn, 8, 4);
8853 /* Check this CPU supports ARMv8 CRC instructions.
8854 * op1 == 3 is UNPREDICTABLE but handle as UNDEFINED.
8855 * Bits 8, 10 and 11 should be zero.
8857 if (!dc_isar_feature(aa32_crc32, s) || op1 == 0x3 || (c & 0xd) != 0) {
8858 goto illegal_op;
8861 rn = extract32(insn, 16, 4);
8862 rd = extract32(insn, 12, 4);
8864 tmp = load_reg(s, rn);
8865 tmp2 = load_reg(s, rm);
8866 if (op1 == 0) {
8867 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
8868 } else if (op1 == 1) {
8869 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
8871 tmp3 = tcg_const_i32(1 << op1);
8872 if (c & 0x2) {
8873 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
8874 } else {
8875 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
8877 tcg_temp_free_i32(tmp2);
8878 tcg_temp_free_i32(tmp3);
8879 store_reg(s, rd, tmp);
8880 break;
8882 case 0x5: /* saturating add/subtract */
8883 ARCH(5TE);
8884 rd = (insn >> 12) & 0xf;
8885 rn = (insn >> 16) & 0xf;
8886 tmp = load_reg(s, rm);
8887 tmp2 = load_reg(s, rn);
8888 if (op1 & 2)
8889 gen_helper_double_saturate(tmp2, cpu_env, tmp2);
8890 if (op1 & 1)
8891 gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2);
8892 else
8893 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
8894 tcg_temp_free_i32(tmp2);
8895 store_reg(s, rd, tmp);
8896 break;
8897 case 0x6: /* ERET */
8898 if (op1 != 3) {
8899 goto illegal_op;
8901 if (!arm_dc_feature(s, ARM_FEATURE_V7VE)) {
8902 goto illegal_op;
8904 if ((insn & 0x000fff0f) != 0x0000000e) {
8905 /* UNPREDICTABLE; we choose to UNDEF */
8906 goto illegal_op;
8909 if (s->current_el == 2) {
8910 tmp = load_cpu_field(elr_el[2]);
8911 } else {
8912 tmp = load_reg(s, 14);
8914 gen_exception_return(s, tmp);
8915 break;
8916 case 7:
8918 int imm16 = extract32(insn, 0, 4) | (extract32(insn, 8, 12) << 4);
8919 switch (op1) {
8920 case 0:
8921 /* HLT */
8922 gen_hlt(s, imm16);
8923 break;
8924 case 1:
8925 /* bkpt */
8926 ARCH(5);
8927 gen_exception_bkpt_insn(s, 4, syn_aa32_bkpt(imm16, false));
8928 break;
8929 case 2:
8930 /* Hypervisor call (v7) */
8931 ARCH(7);
8932 if (IS_USER(s)) {
8933 goto illegal_op;
8935 gen_hvc(s, imm16);
8936 break;
8937 case 3:
8938 /* Secure monitor call (v6+) */
8939 ARCH(6K);
8940 if (IS_USER(s)) {
8941 goto illegal_op;
8943 gen_smc(s);
8944 break;
8945 default:
8946 g_assert_not_reached();
8948 break;
8950 case 0x8: /* signed multiply */
8951 case 0xa:
8952 case 0xc:
8953 case 0xe:
8954 ARCH(5TE);
8955 rs = (insn >> 8) & 0xf;
8956 rn = (insn >> 12) & 0xf;
8957 rd = (insn >> 16) & 0xf;
8958 if (op1 == 1) {
8959 /* (32 * 16) >> 16 */
8960 tmp = load_reg(s, rm);
8961 tmp2 = load_reg(s, rs);
8962 if (sh & 4)
8963 tcg_gen_sari_i32(tmp2, tmp2, 16);
8964 else
8965 gen_sxth(tmp2);
8966 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8967 tcg_gen_shri_i64(tmp64, tmp64, 16);
8968 tmp = tcg_temp_new_i32();
8969 tcg_gen_extrl_i64_i32(tmp, tmp64);
8970 tcg_temp_free_i64(tmp64);
8971 if ((sh & 2) == 0) {
8972 tmp2 = load_reg(s, rn);
8973 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8974 tcg_temp_free_i32(tmp2);
8976 store_reg(s, rd, tmp);
8977 } else {
8978 /* 16 * 16 */
8979 tmp = load_reg(s, rm);
8980 tmp2 = load_reg(s, rs);
8981 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
8982 tcg_temp_free_i32(tmp2);
8983 if (op1 == 2) {
8984 tmp64 = tcg_temp_new_i64();
8985 tcg_gen_ext_i32_i64(tmp64, tmp);
8986 tcg_temp_free_i32(tmp);
8987 gen_addq(s, tmp64, rn, rd);
8988 gen_storeq_reg(s, rn, rd, tmp64);
8989 tcg_temp_free_i64(tmp64);
8990 } else {
8991 if (op1 == 0) {
8992 tmp2 = load_reg(s, rn);
8993 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8994 tcg_temp_free_i32(tmp2);
8996 store_reg(s, rd, tmp);
8999 break;
9000 default:
9001 goto illegal_op;
9003 } else if (((insn & 0x0e000000) == 0 &&
9004 (insn & 0x00000090) != 0x90) ||
9005 ((insn & 0x0e000000) == (1 << 25))) {
9006 int set_cc, logic_cc, shiftop;
9008 op1 = (insn >> 21) & 0xf;
9009 set_cc = (insn >> 20) & 1;
9010 logic_cc = table_logic_cc[op1] & set_cc;
9012 /* data processing instruction */
9013 if (insn & (1 << 25)) {
9014 /* immediate operand */
9015 val = insn & 0xff;
9016 shift = ((insn >> 8) & 0xf) * 2;
9017 if (shift) {
9018 val = (val >> shift) | (val << (32 - shift));
9020 tmp2 = tcg_temp_new_i32();
9021 tcg_gen_movi_i32(tmp2, val);
9022 if (logic_cc && shift) {
9023 gen_set_CF_bit31(tmp2);
9025 } else {
9026 /* register */
9027 rm = (insn) & 0xf;
9028 tmp2 = load_reg(s, rm);
9029 shiftop = (insn >> 5) & 3;
9030 if (!(insn & (1 << 4))) {
9031 shift = (insn >> 7) & 0x1f;
9032 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
9033 } else {
9034 rs = (insn >> 8) & 0xf;
9035 tmp = load_reg(s, rs);
9036 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
9039 if (op1 != 0x0f && op1 != 0x0d) {
9040 rn = (insn >> 16) & 0xf;
9041 tmp = load_reg(s, rn);
9042 } else {
9043 tmp = NULL;
9045 rd = (insn >> 12) & 0xf;
9046 switch(op1) {
9047 case 0x00:
9048 tcg_gen_and_i32(tmp, tmp, tmp2);
9049 if (logic_cc) {
9050 gen_logic_CC(tmp);
9052 store_reg_bx(s, rd, tmp);
9053 break;
9054 case 0x01:
9055 tcg_gen_xor_i32(tmp, tmp, tmp2);
9056 if (logic_cc) {
9057 gen_logic_CC(tmp);
9059 store_reg_bx(s, rd, tmp);
9060 break;
9061 case 0x02:
9062 if (set_cc && rd == 15) {
9063 /* SUBS r15, ... is used for exception return. */
9064 if (IS_USER(s)) {
9065 goto illegal_op;
9067 gen_sub_CC(tmp, tmp, tmp2);
9068 gen_exception_return(s, tmp);
9069 } else {
9070 if (set_cc) {
9071 gen_sub_CC(tmp, tmp, tmp2);
9072 } else {
9073 tcg_gen_sub_i32(tmp, tmp, tmp2);
9075 store_reg_bx(s, rd, tmp);
9077 break;
9078 case 0x03:
9079 if (set_cc) {
9080 gen_sub_CC(tmp, tmp2, tmp);
9081 } else {
9082 tcg_gen_sub_i32(tmp, tmp2, tmp);
9084 store_reg_bx(s, rd, tmp);
9085 break;
9086 case 0x04:
9087 if (set_cc) {
9088 gen_add_CC(tmp, tmp, tmp2);
9089 } else {
9090 tcg_gen_add_i32(tmp, tmp, tmp2);
9092 store_reg_bx(s, rd, tmp);
9093 break;
9094 case 0x05:
9095 if (set_cc) {
9096 gen_adc_CC(tmp, tmp, tmp2);
9097 } else {
9098 gen_add_carry(tmp, tmp, tmp2);
9100 store_reg_bx(s, rd, tmp);
9101 break;
9102 case 0x06:
9103 if (set_cc) {
9104 gen_sbc_CC(tmp, tmp, tmp2);
9105 } else {
9106 gen_sub_carry(tmp, tmp, tmp2);
9108 store_reg_bx(s, rd, tmp);
9109 break;
9110 case 0x07:
9111 if (set_cc) {
9112 gen_sbc_CC(tmp, tmp2, tmp);
9113 } else {
9114 gen_sub_carry(tmp, tmp2, tmp);
9116 store_reg_bx(s, rd, tmp);
9117 break;
9118 case 0x08:
9119 if (set_cc) {
9120 tcg_gen_and_i32(tmp, tmp, tmp2);
9121 gen_logic_CC(tmp);
9123 tcg_temp_free_i32(tmp);
9124 break;
9125 case 0x09:
9126 if (set_cc) {
9127 tcg_gen_xor_i32(tmp, tmp, tmp2);
9128 gen_logic_CC(tmp);
9130 tcg_temp_free_i32(tmp);
9131 break;
9132 case 0x0a:
9133 if (set_cc) {
9134 gen_sub_CC(tmp, tmp, tmp2);
9136 tcg_temp_free_i32(tmp);
9137 break;
9138 case 0x0b:
9139 if (set_cc) {
9140 gen_add_CC(tmp, tmp, tmp2);
9142 tcg_temp_free_i32(tmp);
9143 break;
9144 case 0x0c:
9145 tcg_gen_or_i32(tmp, tmp, tmp2);
9146 if (logic_cc) {
9147 gen_logic_CC(tmp);
9149 store_reg_bx(s, rd, tmp);
9150 break;
9151 case 0x0d:
9152 if (logic_cc && rd == 15) {
9153 /* MOVS r15, ... is used for exception return. */
9154 if (IS_USER(s)) {
9155 goto illegal_op;
9157 gen_exception_return(s, tmp2);
9158 } else {
9159 if (logic_cc) {
9160 gen_logic_CC(tmp2);
9162 store_reg_bx(s, rd, tmp2);
9164 break;
9165 case 0x0e:
9166 tcg_gen_andc_i32(tmp, tmp, tmp2);
9167 if (logic_cc) {
9168 gen_logic_CC(tmp);
9170 store_reg_bx(s, rd, tmp);
9171 break;
9172 default:
9173 case 0x0f:
9174 tcg_gen_not_i32(tmp2, tmp2);
9175 if (logic_cc) {
9176 gen_logic_CC(tmp2);
9178 store_reg_bx(s, rd, tmp2);
9179 break;
9181 if (op1 != 0x0f && op1 != 0x0d) {
9182 tcg_temp_free_i32(tmp2);
9184 } else {
9185 /* other instructions */
9186 op1 = (insn >> 24) & 0xf;
9187 switch(op1) {
9188 case 0x0:
9189 case 0x1:
9190 /* multiplies, extra load/stores */
9191 sh = (insn >> 5) & 3;
9192 if (sh == 0) {
9193 if (op1 == 0x0) {
9194 rd = (insn >> 16) & 0xf;
9195 rn = (insn >> 12) & 0xf;
9196 rs = (insn >> 8) & 0xf;
9197 rm = (insn) & 0xf;
9198 op1 = (insn >> 20) & 0xf;
9199 switch (op1) {
9200 case 0: case 1: case 2: case 3: case 6:
9201 /* 32 bit mul */
9202 tmp = load_reg(s, rs);
9203 tmp2 = load_reg(s, rm);
9204 tcg_gen_mul_i32(tmp, tmp, tmp2);
9205 tcg_temp_free_i32(tmp2);
9206 if (insn & (1 << 22)) {
9207 /* Subtract (mls) */
9208 ARCH(6T2);
9209 tmp2 = load_reg(s, rn);
9210 tcg_gen_sub_i32(tmp, tmp2, tmp);
9211 tcg_temp_free_i32(tmp2);
9212 } else if (insn & (1 << 21)) {
9213 /* Add */
9214 tmp2 = load_reg(s, rn);
9215 tcg_gen_add_i32(tmp, tmp, tmp2);
9216 tcg_temp_free_i32(tmp2);
9218 if (insn & (1 << 20))
9219 gen_logic_CC(tmp);
9220 store_reg(s, rd, tmp);
9221 break;
9222 case 4:
9223 /* 64 bit mul double accumulate (UMAAL) */
9224 ARCH(6);
9225 tmp = load_reg(s, rs);
9226 tmp2 = load_reg(s, rm);
9227 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
9228 gen_addq_lo(s, tmp64, rn);
9229 gen_addq_lo(s, tmp64, rd);
9230 gen_storeq_reg(s, rn, rd, tmp64);
9231 tcg_temp_free_i64(tmp64);
9232 break;
9233 case 8: case 9: case 10: case 11:
9234 case 12: case 13: case 14: case 15:
9235 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
9236 tmp = load_reg(s, rs);
9237 tmp2 = load_reg(s, rm);
9238 if (insn & (1 << 22)) {
9239 tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2);
9240 } else {
9241 tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2);
9243 if (insn & (1 << 21)) { /* mult accumulate */
9244 TCGv_i32 al = load_reg(s, rn);
9245 TCGv_i32 ah = load_reg(s, rd);
9246 tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, al, ah);
9247 tcg_temp_free_i32(al);
9248 tcg_temp_free_i32(ah);
9250 if (insn & (1 << 20)) {
9251 gen_logicq_cc(tmp, tmp2);
9253 store_reg(s, rn, tmp);
9254 store_reg(s, rd, tmp2);
9255 break;
9256 default:
9257 goto illegal_op;
9259 } else {
9260 rn = (insn >> 16) & 0xf;
9261 rd = (insn >> 12) & 0xf;
9262 if (insn & (1 << 23)) {
9263 /* load/store exclusive */
9264 bool is_ld = extract32(insn, 20, 1);
9265 bool is_lasr = !extract32(insn, 8, 1);
9266 int op2 = (insn >> 8) & 3;
9267 op1 = (insn >> 21) & 0x3;
9269 switch (op2) {
9270 case 0: /* lda/stl */
9271 if (op1 == 1) {
9272 goto illegal_op;
9274 ARCH(8);
9275 break;
9276 case 1: /* reserved */
9277 goto illegal_op;
9278 case 2: /* ldaex/stlex */
9279 ARCH(8);
9280 break;
9281 case 3: /* ldrex/strex */
9282 if (op1) {
9283 ARCH(6K);
9284 } else {
9285 ARCH(6);
9287 break;
9290 addr = tcg_temp_local_new_i32();
9291 load_reg_var(s, addr, rn);
9293 if (is_lasr && !is_ld) {
9294 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
9297 if (op2 == 0) {
9298 if (is_ld) {
9299 tmp = tcg_temp_new_i32();
9300 switch (op1) {
9301 case 0: /* lda */
9302 gen_aa32_ld32u_iss(s, tmp, addr,
9303 get_mem_index(s),
9304 rd | ISSIsAcqRel);
9305 break;
9306 case 2: /* ldab */
9307 gen_aa32_ld8u_iss(s, tmp, addr,
9308 get_mem_index(s),
9309 rd | ISSIsAcqRel);
9310 break;
9311 case 3: /* ldah */
9312 gen_aa32_ld16u_iss(s, tmp, addr,
9313 get_mem_index(s),
9314 rd | ISSIsAcqRel);
9315 break;
9316 default:
9317 abort();
9319 store_reg(s, rd, tmp);
9320 } else {
9321 rm = insn & 0xf;
9322 tmp = load_reg(s, rm);
9323 switch (op1) {
9324 case 0: /* stl */
9325 gen_aa32_st32_iss(s, tmp, addr,
9326 get_mem_index(s),
9327 rm | ISSIsAcqRel);
9328 break;
9329 case 2: /* stlb */
9330 gen_aa32_st8_iss(s, tmp, addr,
9331 get_mem_index(s),
9332 rm | ISSIsAcqRel);
9333 break;
9334 case 3: /* stlh */
9335 gen_aa32_st16_iss(s, tmp, addr,
9336 get_mem_index(s),
9337 rm | ISSIsAcqRel);
9338 break;
9339 default:
9340 abort();
9342 tcg_temp_free_i32(tmp);
9344 } else if (is_ld) {
9345 switch (op1) {
9346 case 0: /* ldrex */
9347 gen_load_exclusive(s, rd, 15, addr, 2);
9348 break;
9349 case 1: /* ldrexd */
9350 gen_load_exclusive(s, rd, rd + 1, addr, 3);
9351 break;
9352 case 2: /* ldrexb */
9353 gen_load_exclusive(s, rd, 15, addr, 0);
9354 break;
9355 case 3: /* ldrexh */
9356 gen_load_exclusive(s, rd, 15, addr, 1);
9357 break;
9358 default:
9359 abort();
9361 } else {
9362 rm = insn & 0xf;
9363 switch (op1) {
9364 case 0: /* strex */
9365 gen_store_exclusive(s, rd, rm, 15, addr, 2);
9366 break;
9367 case 1: /* strexd */
9368 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
9369 break;
9370 case 2: /* strexb */
9371 gen_store_exclusive(s, rd, rm, 15, addr, 0);
9372 break;
9373 case 3: /* strexh */
9374 gen_store_exclusive(s, rd, rm, 15, addr, 1);
9375 break;
9376 default:
9377 abort();
9380 tcg_temp_free_i32(addr);
9382 if (is_lasr && is_ld) {
9383 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
9385 } else if ((insn & 0x00300f00) == 0) {
9386 /* 0bcccc_0001_0x00_xxxx_xxxx_0000_1001_xxxx
9387 * - SWP, SWPB
9390 TCGv taddr;
9391 TCGMemOp opc = s->be_data;
9393 rm = (insn) & 0xf;
9395 if (insn & (1 << 22)) {
9396 opc |= MO_UB;
9397 } else {
9398 opc |= MO_UL | MO_ALIGN;
9401 addr = load_reg(s, rn);
9402 taddr = gen_aa32_addr(s, addr, opc);
9403 tcg_temp_free_i32(addr);
9405 tmp = load_reg(s, rm);
9406 tcg_gen_atomic_xchg_i32(tmp, taddr, tmp,
9407 get_mem_index(s), opc);
9408 tcg_temp_free(taddr);
9409 store_reg(s, rd, tmp);
9410 } else {
9411 goto illegal_op;
9414 } else {
9415 int address_offset;
9416 bool load = insn & (1 << 20);
9417 bool wbit = insn & (1 << 21);
9418 bool pbit = insn & (1 << 24);
9419 bool doubleword = false;
9420 ISSInfo issinfo;
9422 /* Misc load/store */
9423 rn = (insn >> 16) & 0xf;
9424 rd = (insn >> 12) & 0xf;
9426 /* ISS not valid if writeback */
9427 issinfo = (pbit & !wbit) ? rd : ISSInvalid;
9429 if (!load && (sh & 2)) {
9430 /* doubleword */
9431 ARCH(5TE);
9432 if (rd & 1) {
9433 /* UNPREDICTABLE; we choose to UNDEF */
9434 goto illegal_op;
9436 load = (sh & 1) == 0;
9437 doubleword = true;
9440 addr = load_reg(s, rn);
9441 if (pbit) {
9442 gen_add_datah_offset(s, insn, 0, addr);
9444 address_offset = 0;
9446 if (doubleword) {
9447 if (!load) {
9448 /* store */
9449 tmp = load_reg(s, rd);
9450 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
9451 tcg_temp_free_i32(tmp);
9452 tcg_gen_addi_i32(addr, addr, 4);
9453 tmp = load_reg(s, rd + 1);
9454 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
9455 tcg_temp_free_i32(tmp);
9456 } else {
9457 /* load */
9458 tmp = tcg_temp_new_i32();
9459 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9460 store_reg(s, rd, tmp);
9461 tcg_gen_addi_i32(addr, addr, 4);
9462 tmp = tcg_temp_new_i32();
9463 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9464 rd++;
9466 address_offset = -4;
9467 } else if (load) {
9468 /* load */
9469 tmp = tcg_temp_new_i32();
9470 switch (sh) {
9471 case 1:
9472 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s),
9473 issinfo);
9474 break;
9475 case 2:
9476 gen_aa32_ld8s_iss(s, tmp, addr, get_mem_index(s),
9477 issinfo);
9478 break;
9479 default:
9480 case 3:
9481 gen_aa32_ld16s_iss(s, tmp, addr, get_mem_index(s),
9482 issinfo);
9483 break;
9485 } else {
9486 /* store */
9487 tmp = load_reg(s, rd);
9488 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), issinfo);
9489 tcg_temp_free_i32(tmp);
9491 /* Perform base writeback before the loaded value to
9492 ensure correct behavior with overlapping index registers.
9493 ldrd with base writeback is undefined if the
9494 destination and index registers overlap. */
9495 if (!pbit) {
9496 gen_add_datah_offset(s, insn, address_offset, addr);
9497 store_reg(s, rn, addr);
9498 } else if (wbit) {
9499 if (address_offset)
9500 tcg_gen_addi_i32(addr, addr, address_offset);
9501 store_reg(s, rn, addr);
9502 } else {
9503 tcg_temp_free_i32(addr);
9505 if (load) {
9506 /* Complete the load. */
9507 store_reg(s, rd, tmp);
9510 break;
9511 case 0x4:
9512 case 0x5:
9513 goto do_ldst;
9514 case 0x6:
9515 case 0x7:
9516 if (insn & (1 << 4)) {
9517 ARCH(6);
9518 /* Armv6 Media instructions. */
9519 rm = insn & 0xf;
9520 rn = (insn >> 16) & 0xf;
9521 rd = (insn >> 12) & 0xf;
9522 rs = (insn >> 8) & 0xf;
9523 switch ((insn >> 23) & 3) {
9524 case 0: /* Parallel add/subtract. */
9525 op1 = (insn >> 20) & 7;
9526 tmp = load_reg(s, rn);
9527 tmp2 = load_reg(s, rm);
9528 sh = (insn >> 5) & 7;
9529 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
9530 goto illegal_op;
9531 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
9532 tcg_temp_free_i32(tmp2);
9533 store_reg(s, rd, tmp);
9534 break;
9535 case 1:
9536 if ((insn & 0x00700020) == 0) {
9537 /* Halfword pack. */
9538 tmp = load_reg(s, rn);
9539 tmp2 = load_reg(s, rm);
9540 shift = (insn >> 7) & 0x1f;
9541 if (insn & (1 << 6)) {
9542 /* pkhtb */
9543 if (shift == 0)
9544 shift = 31;
9545 tcg_gen_sari_i32(tmp2, tmp2, shift);
9546 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
9547 tcg_gen_ext16u_i32(tmp2, tmp2);
9548 } else {
9549 /* pkhbt */
9550 if (shift)
9551 tcg_gen_shli_i32(tmp2, tmp2, shift);
9552 tcg_gen_ext16u_i32(tmp, tmp);
9553 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
9555 tcg_gen_or_i32(tmp, tmp, tmp2);
9556 tcg_temp_free_i32(tmp2);
9557 store_reg(s, rd, tmp);
9558 } else if ((insn & 0x00200020) == 0x00200000) {
9559 /* [us]sat */
9560 tmp = load_reg(s, rm);
9561 shift = (insn >> 7) & 0x1f;
9562 if (insn & (1 << 6)) {
9563 if (shift == 0)
9564 shift = 31;
9565 tcg_gen_sari_i32(tmp, tmp, shift);
9566 } else {
9567 tcg_gen_shli_i32(tmp, tmp, shift);
9569 sh = (insn >> 16) & 0x1f;
9570 tmp2 = tcg_const_i32(sh);
9571 if (insn & (1 << 22))
9572 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
9573 else
9574 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
9575 tcg_temp_free_i32(tmp2);
9576 store_reg(s, rd, tmp);
9577 } else if ((insn & 0x00300fe0) == 0x00200f20) {
9578 /* [us]sat16 */
9579 tmp = load_reg(s, rm);
9580 sh = (insn >> 16) & 0x1f;
9581 tmp2 = tcg_const_i32(sh);
9582 if (insn & (1 << 22))
9583 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
9584 else
9585 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
9586 tcg_temp_free_i32(tmp2);
9587 store_reg(s, rd, tmp);
9588 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
9589 /* Select bytes. */
9590 tmp = load_reg(s, rn);
9591 tmp2 = load_reg(s, rm);
9592 tmp3 = tcg_temp_new_i32();
9593 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
9594 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
9595 tcg_temp_free_i32(tmp3);
9596 tcg_temp_free_i32(tmp2);
9597 store_reg(s, rd, tmp);
9598 } else if ((insn & 0x000003e0) == 0x00000060) {
9599 tmp = load_reg(s, rm);
9600 shift = (insn >> 10) & 3;
9601 /* ??? In many cases it's not necessary to do a
9602 rotate, a shift is sufficient. */
9603 if (shift != 0)
9604 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
9605 op1 = (insn >> 20) & 7;
9606 switch (op1) {
9607 case 0: gen_sxtb16(tmp); break;
9608 case 2: gen_sxtb(tmp); break;
9609 case 3: gen_sxth(tmp); break;
9610 case 4: gen_uxtb16(tmp); break;
9611 case 6: gen_uxtb(tmp); break;
9612 case 7: gen_uxth(tmp); break;
9613 default: goto illegal_op;
9615 if (rn != 15) {
9616 tmp2 = load_reg(s, rn);
9617 if ((op1 & 3) == 0) {
9618 gen_add16(tmp, tmp2);
9619 } else {
9620 tcg_gen_add_i32(tmp, tmp, tmp2);
9621 tcg_temp_free_i32(tmp2);
9624 store_reg(s, rd, tmp);
9625 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
9626 /* rev */
9627 tmp = load_reg(s, rm);
9628 if (insn & (1 << 22)) {
9629 if (insn & (1 << 7)) {
9630 gen_revsh(tmp);
9631 } else {
9632 ARCH(6T2);
9633 gen_helper_rbit(tmp, tmp);
9635 } else {
9636 if (insn & (1 << 7))
9637 gen_rev16(tmp);
9638 else
9639 tcg_gen_bswap32_i32(tmp, tmp);
9641 store_reg(s, rd, tmp);
9642 } else {
9643 goto illegal_op;
9645 break;
9646 case 2: /* Multiplies (Type 3). */
9647 switch ((insn >> 20) & 0x7) {
9648 case 5:
9649 if (((insn >> 6) ^ (insn >> 7)) & 1) {
9650 /* op2 not 00x or 11x : UNDEF */
9651 goto illegal_op;
9653 /* Signed multiply most significant [accumulate].
9654 (SMMUL, SMMLA, SMMLS) */
9655 tmp = load_reg(s, rm);
9656 tmp2 = load_reg(s, rs);
9657 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9659 if (rd != 15) {
9660 tmp = load_reg(s, rd);
9661 if (insn & (1 << 6)) {
9662 tmp64 = gen_subq_msw(tmp64, tmp);
9663 } else {
9664 tmp64 = gen_addq_msw(tmp64, tmp);
9667 if (insn & (1 << 5)) {
9668 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
9670 tcg_gen_shri_i64(tmp64, tmp64, 32);
9671 tmp = tcg_temp_new_i32();
9672 tcg_gen_extrl_i64_i32(tmp, tmp64);
9673 tcg_temp_free_i64(tmp64);
9674 store_reg(s, rn, tmp);
9675 break;
9676 case 0:
9677 case 4:
9678 /* SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD */
9679 if (insn & (1 << 7)) {
9680 goto illegal_op;
9682 tmp = load_reg(s, rm);
9683 tmp2 = load_reg(s, rs);
9684 if (insn & (1 << 5))
9685 gen_swap_half(tmp2);
9686 gen_smul_dual(tmp, tmp2);
9687 if (insn & (1 << 22)) {
9688 /* smlald, smlsld */
9689 TCGv_i64 tmp64_2;
9691 tmp64 = tcg_temp_new_i64();
9692 tmp64_2 = tcg_temp_new_i64();
9693 tcg_gen_ext_i32_i64(tmp64, tmp);
9694 tcg_gen_ext_i32_i64(tmp64_2, tmp2);
9695 tcg_temp_free_i32(tmp);
9696 tcg_temp_free_i32(tmp2);
9697 if (insn & (1 << 6)) {
9698 tcg_gen_sub_i64(tmp64, tmp64, tmp64_2);
9699 } else {
9700 tcg_gen_add_i64(tmp64, tmp64, tmp64_2);
9702 tcg_temp_free_i64(tmp64_2);
9703 gen_addq(s, tmp64, rd, rn);
9704 gen_storeq_reg(s, rd, rn, tmp64);
9705 tcg_temp_free_i64(tmp64);
9706 } else {
9707 /* smuad, smusd, smlad, smlsd */
9708 if (insn & (1 << 6)) {
9709 /* This subtraction cannot overflow. */
9710 tcg_gen_sub_i32(tmp, tmp, tmp2);
9711 } else {
9712 /* This addition cannot overflow 32 bits;
9713 * however it may overflow considered as a
9714 * signed operation, in which case we must set
9715 * the Q flag.
9717 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9719 tcg_temp_free_i32(tmp2);
9720 if (rd != 15)
9722 tmp2 = load_reg(s, rd);
9723 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9724 tcg_temp_free_i32(tmp2);
9726 store_reg(s, rn, tmp);
9728 break;
9729 case 1:
9730 case 3:
9731 /* SDIV, UDIV */
9732 if (!dc_isar_feature(arm_div, s)) {
9733 goto illegal_op;
9735 if (((insn >> 5) & 7) || (rd != 15)) {
9736 goto illegal_op;
9738 tmp = load_reg(s, rm);
9739 tmp2 = load_reg(s, rs);
9740 if (insn & (1 << 21)) {
9741 gen_helper_udiv(tmp, tmp, tmp2);
9742 } else {
9743 gen_helper_sdiv(tmp, tmp, tmp2);
9745 tcg_temp_free_i32(tmp2);
9746 store_reg(s, rn, tmp);
9747 break;
9748 default:
9749 goto illegal_op;
9751 break;
9752 case 3:
9753 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
9754 switch (op1) {
9755 case 0: /* Unsigned sum of absolute differences. */
9756 ARCH(6);
9757 tmp = load_reg(s, rm);
9758 tmp2 = load_reg(s, rs);
9759 gen_helper_usad8(tmp, tmp, tmp2);
9760 tcg_temp_free_i32(tmp2);
9761 if (rd != 15) {
9762 tmp2 = load_reg(s, rd);
9763 tcg_gen_add_i32(tmp, tmp, tmp2);
9764 tcg_temp_free_i32(tmp2);
9766 store_reg(s, rn, tmp);
9767 break;
9768 case 0x20: case 0x24: case 0x28: case 0x2c:
9769 /* Bitfield insert/clear. */
9770 ARCH(6T2);
9771 shift = (insn >> 7) & 0x1f;
9772 i = (insn >> 16) & 0x1f;
9773 if (i < shift) {
9774 /* UNPREDICTABLE; we choose to UNDEF */
9775 goto illegal_op;
9777 i = i + 1 - shift;
9778 if (rm == 15) {
9779 tmp = tcg_temp_new_i32();
9780 tcg_gen_movi_i32(tmp, 0);
9781 } else {
9782 tmp = load_reg(s, rm);
9784 if (i != 32) {
9785 tmp2 = load_reg(s, rd);
9786 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, i);
9787 tcg_temp_free_i32(tmp2);
9789 store_reg(s, rd, tmp);
9790 break;
9791 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
9792 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
9793 ARCH(6T2);
9794 tmp = load_reg(s, rm);
9795 shift = (insn >> 7) & 0x1f;
9796 i = ((insn >> 16) & 0x1f) + 1;
9797 if (shift + i > 32)
9798 goto illegal_op;
9799 if (i < 32) {
9800 if (op1 & 0x20) {
9801 tcg_gen_extract_i32(tmp, tmp, shift, i);
9802 } else {
9803 tcg_gen_sextract_i32(tmp, tmp, shift, i);
9806 store_reg(s, rd, tmp);
9807 break;
9808 default:
9809 goto illegal_op;
9811 break;
9813 break;
9815 do_ldst:
9816 /* Check for undefined extension instructions
9817 * per the ARM Bible IE:
9818 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
9820 sh = (0xf << 20) | (0xf << 4);
9821 if (op1 == 0x7 && ((insn & sh) == sh))
9823 goto illegal_op;
9825 /* load/store byte/word */
9826 rn = (insn >> 16) & 0xf;
9827 rd = (insn >> 12) & 0xf;
9828 tmp2 = load_reg(s, rn);
9829 if ((insn & 0x01200000) == 0x00200000) {
9830 /* ldrt/strt */
9831 i = get_a32_user_mem_index(s);
9832 } else {
9833 i = get_mem_index(s);
9835 if (insn & (1 << 24))
9836 gen_add_data_offset(s, insn, tmp2);
9837 if (insn & (1 << 20)) {
9838 /* load */
9839 tmp = tcg_temp_new_i32();
9840 if (insn & (1 << 22)) {
9841 gen_aa32_ld8u_iss(s, tmp, tmp2, i, rd);
9842 } else {
9843 gen_aa32_ld32u_iss(s, tmp, tmp2, i, rd);
9845 } else {
9846 /* store */
9847 tmp = load_reg(s, rd);
9848 if (insn & (1 << 22)) {
9849 gen_aa32_st8_iss(s, tmp, tmp2, i, rd);
9850 } else {
9851 gen_aa32_st32_iss(s, tmp, tmp2, i, rd);
9853 tcg_temp_free_i32(tmp);
9855 if (!(insn & (1 << 24))) {
9856 gen_add_data_offset(s, insn, tmp2);
9857 store_reg(s, rn, tmp2);
9858 } else if (insn & (1 << 21)) {
9859 store_reg(s, rn, tmp2);
9860 } else {
9861 tcg_temp_free_i32(tmp2);
9863 if (insn & (1 << 20)) {
9864 /* Complete the load. */
9865 store_reg_from_load(s, rd, tmp);
9867 break;
9868 case 0x08:
9869 case 0x09:
9871 int j, n, loaded_base;
9872 bool exc_return = false;
9873 bool is_load = extract32(insn, 20, 1);
9874 bool user = false;
9875 TCGv_i32 loaded_var;
9876 /* load/store multiple words */
9877 /* XXX: store correct base if write back */
9878 if (insn & (1 << 22)) {
9879 /* LDM (user), LDM (exception return) and STM (user) */
9880 if (IS_USER(s))
9881 goto illegal_op; /* only usable in supervisor mode */
9883 if (is_load && extract32(insn, 15, 1)) {
9884 exc_return = true;
9885 } else {
9886 user = true;
9889 rn = (insn >> 16) & 0xf;
9890 addr = load_reg(s, rn);
9892 /* compute total size */
9893 loaded_base = 0;
9894 loaded_var = NULL;
9895 n = 0;
9896 for(i=0;i<16;i++) {
9897 if (insn & (1 << i))
9898 n++;
9900 /* XXX: test invalid n == 0 case ? */
9901 if (insn & (1 << 23)) {
9902 if (insn & (1 << 24)) {
9903 /* pre increment */
9904 tcg_gen_addi_i32(addr, addr, 4);
9905 } else {
9906 /* post increment */
9908 } else {
9909 if (insn & (1 << 24)) {
9910 /* pre decrement */
9911 tcg_gen_addi_i32(addr, addr, -(n * 4));
9912 } else {
9913 /* post decrement */
9914 if (n != 1)
9915 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
9918 j = 0;
9919 for(i=0;i<16;i++) {
9920 if (insn & (1 << i)) {
9921 if (is_load) {
9922 /* load */
9923 tmp = tcg_temp_new_i32();
9924 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9925 if (user) {
9926 tmp2 = tcg_const_i32(i);
9927 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
9928 tcg_temp_free_i32(tmp2);
9929 tcg_temp_free_i32(tmp);
9930 } else if (i == rn) {
9931 loaded_var = tmp;
9932 loaded_base = 1;
9933 } else if (i == 15 && exc_return) {
9934 store_pc_exc_ret(s, tmp);
9935 } else {
9936 store_reg_from_load(s, i, tmp);
9938 } else {
9939 /* store */
9940 if (i == 15) {
9941 /* special case: r15 = PC + 8 */
9942 val = (long)s->pc + 4;
9943 tmp = tcg_temp_new_i32();
9944 tcg_gen_movi_i32(tmp, val);
9945 } else if (user) {
9946 tmp = tcg_temp_new_i32();
9947 tmp2 = tcg_const_i32(i);
9948 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
9949 tcg_temp_free_i32(tmp2);
9950 } else {
9951 tmp = load_reg(s, i);
9953 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
9954 tcg_temp_free_i32(tmp);
9956 j++;
9957 /* no need to add after the last transfer */
9958 if (j != n)
9959 tcg_gen_addi_i32(addr, addr, 4);
9962 if (insn & (1 << 21)) {
9963 /* write back */
9964 if (insn & (1 << 23)) {
9965 if (insn & (1 << 24)) {
9966 /* pre increment */
9967 } else {
9968 /* post increment */
9969 tcg_gen_addi_i32(addr, addr, 4);
9971 } else {
9972 if (insn & (1 << 24)) {
9973 /* pre decrement */
9974 if (n != 1)
9975 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
9976 } else {
9977 /* post decrement */
9978 tcg_gen_addi_i32(addr, addr, -(n * 4));
9981 store_reg(s, rn, addr);
9982 } else {
9983 tcg_temp_free_i32(addr);
9985 if (loaded_base) {
9986 store_reg(s, rn, loaded_var);
9988 if (exc_return) {
9989 /* Restore CPSR from SPSR. */
9990 tmp = load_cpu_field(spsr);
9991 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
9992 gen_io_start();
9994 gen_helper_cpsr_write_eret(cpu_env, tmp);
9995 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
9996 gen_io_end();
9998 tcg_temp_free_i32(tmp);
9999 /* Must exit loop to check un-masked IRQs */
10000 s->base.is_jmp = DISAS_EXIT;
10003 break;
10004 case 0xa:
10005 case 0xb:
10007 int32_t offset;
10009 /* branch (and link) */
10010 val = (int32_t)s->pc;
10011 if (insn & (1 << 24)) {
10012 tmp = tcg_temp_new_i32();
10013 tcg_gen_movi_i32(tmp, val);
10014 store_reg(s, 14, tmp);
10016 offset = sextract32(insn << 2, 0, 26);
10017 val += offset + 4;
10018 gen_jmp(s, val);
10020 break;
10021 case 0xc:
10022 case 0xd:
10023 case 0xe:
10024 if (((insn >> 8) & 0xe) == 10) {
10025 /* VFP. */
10026 if (disas_vfp_insn(s, insn)) {
10027 goto illegal_op;
10029 } else if (disas_coproc_insn(s, insn)) {
10030 /* Coprocessor. */
10031 goto illegal_op;
10033 break;
10034 case 0xf:
10035 /* swi */
10036 gen_set_pc_im(s, s->pc);
10037 s->svc_imm = extract32(insn, 0, 24);
10038 s->base.is_jmp = DISAS_SWI;
10039 break;
10040 default:
10041 illegal_op:
10042 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
10043 default_exception_el(s));
10044 break;
10049 static bool thumb_insn_is_16bit(DisasContext *s, uint32_t insn)
10051 /* Return true if this is a 16 bit instruction. We must be precise
10052 * about this (matching the decode). We assume that s->pc still
10053 * points to the first 16 bits of the insn.
10055 if ((insn >> 11) < 0x1d) {
10056 /* Definitely a 16-bit instruction */
10057 return true;
10060 /* Top five bits 0b11101 / 0b11110 / 0b11111 : this is the
10061 * first half of a 32-bit Thumb insn. Thumb-1 cores might
10062 * end up actually treating this as two 16-bit insns, though,
10063 * if it's half of a bl/blx pair that might span a page boundary.
10065 if (arm_dc_feature(s, ARM_FEATURE_THUMB2) ||
10066 arm_dc_feature(s, ARM_FEATURE_M)) {
10067 /* Thumb2 cores (including all M profile ones) always treat
10068 * 32-bit insns as 32-bit.
10070 return false;
10073 if ((insn >> 11) == 0x1e && s->pc - s->page_start < TARGET_PAGE_SIZE - 3) {
10074 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix, and the suffix
10075 * is not on the next page; we merge this into a 32-bit
10076 * insn.
10078 return false;
10080 /* 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF);
10081 * 0b1111_1xxx_xxxx_xxxx : BL suffix;
10082 * 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix on the end of a page
10083 * -- handle as single 16 bit insn
10085 return true;
10088 /* Return true if this is a Thumb-2 logical op. */
10089 static int
10090 thumb2_logic_op(int op)
10092 return (op < 8);
10095 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
10096 then set condition code flags based on the result of the operation.
10097 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
10098 to the high bit of T1.
10099 Returns zero if the opcode is valid. */
10101 static int
10102 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out,
10103 TCGv_i32 t0, TCGv_i32 t1)
10105 int logic_cc;
10107 logic_cc = 0;
10108 switch (op) {
10109 case 0: /* and */
10110 tcg_gen_and_i32(t0, t0, t1);
10111 logic_cc = conds;
10112 break;
10113 case 1: /* bic */
10114 tcg_gen_andc_i32(t0, t0, t1);
10115 logic_cc = conds;
10116 break;
10117 case 2: /* orr */
10118 tcg_gen_or_i32(t0, t0, t1);
10119 logic_cc = conds;
10120 break;
10121 case 3: /* orn */
10122 tcg_gen_orc_i32(t0, t0, t1);
10123 logic_cc = conds;
10124 break;
10125 case 4: /* eor */
10126 tcg_gen_xor_i32(t0, t0, t1);
10127 logic_cc = conds;
10128 break;
10129 case 8: /* add */
10130 if (conds)
10131 gen_add_CC(t0, t0, t1);
10132 else
10133 tcg_gen_add_i32(t0, t0, t1);
10134 break;
10135 case 10: /* adc */
10136 if (conds)
10137 gen_adc_CC(t0, t0, t1);
10138 else
10139 gen_adc(t0, t1);
10140 break;
10141 case 11: /* sbc */
10142 if (conds) {
10143 gen_sbc_CC(t0, t0, t1);
10144 } else {
10145 gen_sub_carry(t0, t0, t1);
10147 break;
10148 case 13: /* sub */
10149 if (conds)
10150 gen_sub_CC(t0, t0, t1);
10151 else
10152 tcg_gen_sub_i32(t0, t0, t1);
10153 break;
10154 case 14: /* rsb */
10155 if (conds)
10156 gen_sub_CC(t0, t1, t0);
10157 else
10158 tcg_gen_sub_i32(t0, t1, t0);
10159 break;
10160 default: /* 5, 6, 7, 9, 12, 15. */
10161 return 1;
10163 if (logic_cc) {
10164 gen_logic_CC(t0);
10165 if (shifter_out)
10166 gen_set_CF_bit31(t1);
10168 return 0;
10171 /* Translate a 32-bit thumb instruction. */
10172 static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
10174 uint32_t imm, shift, offset;
10175 uint32_t rd, rn, rm, rs;
10176 TCGv_i32 tmp;
10177 TCGv_i32 tmp2;
10178 TCGv_i32 tmp3;
10179 TCGv_i32 addr;
10180 TCGv_i64 tmp64;
10181 int op;
10182 int shiftop;
10183 int conds;
10184 int logic_cc;
10187 * ARMv6-M supports a limited subset of Thumb2 instructions.
10188 * Other Thumb1 architectures allow only 32-bit
10189 * combined BL/BLX prefix and suffix.
10191 if (arm_dc_feature(s, ARM_FEATURE_M) &&
10192 !arm_dc_feature(s, ARM_FEATURE_V7)) {
10193 int i;
10194 bool found = false;
10195 static const uint32_t armv6m_insn[] = {0xf3808000 /* msr */,
10196 0xf3b08040 /* dsb */,
10197 0xf3b08050 /* dmb */,
10198 0xf3b08060 /* isb */,
10199 0xf3e08000 /* mrs */,
10200 0xf000d000 /* bl */};
10201 static const uint32_t armv6m_mask[] = {0xffe0d000,
10202 0xfff0d0f0,
10203 0xfff0d0f0,
10204 0xfff0d0f0,
10205 0xffe0d000,
10206 0xf800d000};
10208 for (i = 0; i < ARRAY_SIZE(armv6m_insn); i++) {
10209 if ((insn & armv6m_mask[i]) == armv6m_insn[i]) {
10210 found = true;
10211 break;
10214 if (!found) {
10215 goto illegal_op;
10217 } else if ((insn & 0xf800e800) != 0xf000e800) {
10218 ARCH(6T2);
10221 rn = (insn >> 16) & 0xf;
10222 rs = (insn >> 12) & 0xf;
10223 rd = (insn >> 8) & 0xf;
10224 rm = insn & 0xf;
10225 switch ((insn >> 25) & 0xf) {
10226 case 0: case 1: case 2: case 3:
10227 /* 16-bit instructions. Should never happen. */
10228 abort();
10229 case 4:
10230 if (insn & (1 << 22)) {
10231 /* 0b1110_100x_x1xx_xxxx_xxxx_xxxx_xxxx_xxxx
10232 * - load/store doubleword, load/store exclusive, ldacq/strel,
10233 * table branch, TT.
10235 if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_M) &&
10236 arm_dc_feature(s, ARM_FEATURE_V8)) {
10237 /* 0b1110_1001_0111_1111_1110_1001_0111_111
10238 * - SG (v8M only)
10239 * The bulk of the behaviour for this instruction is implemented
10240 * in v7m_handle_execute_nsc(), which deals with the insn when
10241 * it is executed by a CPU in non-secure state from memory
10242 * which is Secure & NonSecure-Callable.
10243 * Here we only need to handle the remaining cases:
10244 * * in NS memory (including the "security extension not
10245 * implemented" case) : NOP
10246 * * in S memory but CPU already secure (clear IT bits)
10247 * We know that the attribute for the memory this insn is
10248 * in must match the current CPU state, because otherwise
10249 * get_phys_addr_pmsav8 would have generated an exception.
10251 if (s->v8m_secure) {
10252 /* Like the IT insn, we don't need to generate any code */
10253 s->condexec_cond = 0;
10254 s->condexec_mask = 0;
10256 } else if (insn & 0x01200000) {
10257 /* 0b1110_1000_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
10258 * - load/store dual (post-indexed)
10259 * 0b1111_1001_x10x_xxxx_xxxx_xxxx_xxxx_xxxx
10260 * - load/store dual (literal and immediate)
10261 * 0b1111_1001_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
10262 * - load/store dual (pre-indexed)
10264 bool wback = extract32(insn, 21, 1);
10266 if (rn == 15) {
10267 if (insn & (1 << 21)) {
10268 /* UNPREDICTABLE */
10269 goto illegal_op;
10271 addr = tcg_temp_new_i32();
10272 tcg_gen_movi_i32(addr, s->pc & ~3);
10273 } else {
10274 addr = load_reg(s, rn);
10276 offset = (insn & 0xff) * 4;
10277 if ((insn & (1 << 23)) == 0) {
10278 offset = -offset;
10281 if (s->v8m_stackcheck && rn == 13 && wback) {
10283 * Here 'addr' is the current SP; if offset is +ve we're
10284 * moving SP up, else down. It is UNKNOWN whether the limit
10285 * check triggers when SP starts below the limit and ends
10286 * up above it; check whichever of the current and final
10287 * SP is lower, so QEMU will trigger in that situation.
10289 if ((int32_t)offset < 0) {
10290 TCGv_i32 newsp = tcg_temp_new_i32();
10292 tcg_gen_addi_i32(newsp, addr, offset);
10293 gen_helper_v8m_stackcheck(cpu_env, newsp);
10294 tcg_temp_free_i32(newsp);
10295 } else {
10296 gen_helper_v8m_stackcheck(cpu_env, addr);
10300 if (insn & (1 << 24)) {
10301 tcg_gen_addi_i32(addr, addr, offset);
10302 offset = 0;
10304 if (insn & (1 << 20)) {
10305 /* ldrd */
10306 tmp = tcg_temp_new_i32();
10307 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
10308 store_reg(s, rs, tmp);
10309 tcg_gen_addi_i32(addr, addr, 4);
10310 tmp = tcg_temp_new_i32();
10311 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
10312 store_reg(s, rd, tmp);
10313 } else {
10314 /* strd */
10315 tmp = load_reg(s, rs);
10316 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
10317 tcg_temp_free_i32(tmp);
10318 tcg_gen_addi_i32(addr, addr, 4);
10319 tmp = load_reg(s, rd);
10320 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
10321 tcg_temp_free_i32(tmp);
10323 if (wback) {
10324 /* Base writeback. */
10325 tcg_gen_addi_i32(addr, addr, offset - 4);
10326 store_reg(s, rn, addr);
10327 } else {
10328 tcg_temp_free_i32(addr);
10330 } else if ((insn & (1 << 23)) == 0) {
10331 /* 0b1110_1000_010x_xxxx_xxxx_xxxx_xxxx_xxxx
10332 * - load/store exclusive word
10333 * - TT (v8M only)
10335 if (rs == 15) {
10336 if (!(insn & (1 << 20)) &&
10337 arm_dc_feature(s, ARM_FEATURE_M) &&
10338 arm_dc_feature(s, ARM_FEATURE_V8)) {
10339 /* 0b1110_1000_0100_xxxx_1111_xxxx_xxxx_xxxx
10340 * - TT (v8M only)
10342 bool alt = insn & (1 << 7);
10343 TCGv_i32 addr, op, ttresp;
10345 if ((insn & 0x3f) || rd == 13 || rd == 15 || rn == 15) {
10346 /* we UNDEF for these UNPREDICTABLE cases */
10347 goto illegal_op;
10350 if (alt && !s->v8m_secure) {
10351 goto illegal_op;
10354 addr = load_reg(s, rn);
10355 op = tcg_const_i32(extract32(insn, 6, 2));
10356 ttresp = tcg_temp_new_i32();
10357 gen_helper_v7m_tt(ttresp, cpu_env, addr, op);
10358 tcg_temp_free_i32(addr);
10359 tcg_temp_free_i32(op);
10360 store_reg(s, rd, ttresp);
10361 break;
10363 goto illegal_op;
10365 addr = tcg_temp_local_new_i32();
10366 load_reg_var(s, addr, rn);
10367 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
10368 if (insn & (1 << 20)) {
10369 gen_load_exclusive(s, rs, 15, addr, 2);
10370 } else {
10371 gen_store_exclusive(s, rd, rs, 15, addr, 2);
10373 tcg_temp_free_i32(addr);
10374 } else if ((insn & (7 << 5)) == 0) {
10375 /* Table Branch. */
10376 if (rn == 15) {
10377 addr = tcg_temp_new_i32();
10378 tcg_gen_movi_i32(addr, s->pc);
10379 } else {
10380 addr = load_reg(s, rn);
10382 tmp = load_reg(s, rm);
10383 tcg_gen_add_i32(addr, addr, tmp);
10384 if (insn & (1 << 4)) {
10385 /* tbh */
10386 tcg_gen_add_i32(addr, addr, tmp);
10387 tcg_temp_free_i32(tmp);
10388 tmp = tcg_temp_new_i32();
10389 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
10390 } else { /* tbb */
10391 tcg_temp_free_i32(tmp);
10392 tmp = tcg_temp_new_i32();
10393 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
10395 tcg_temp_free_i32(addr);
10396 tcg_gen_shli_i32(tmp, tmp, 1);
10397 tcg_gen_addi_i32(tmp, tmp, s->pc);
10398 store_reg(s, 15, tmp);
10399 } else {
10400 bool is_lasr = false;
10401 bool is_ld = extract32(insn, 20, 1);
10402 int op2 = (insn >> 6) & 0x3;
10403 op = (insn >> 4) & 0x3;
10404 switch (op2) {
10405 case 0:
10406 goto illegal_op;
10407 case 1:
10408 /* Load/store exclusive byte/halfword/doubleword */
10409 if (op == 2) {
10410 goto illegal_op;
10412 ARCH(7);
10413 break;
10414 case 2:
10415 /* Load-acquire/store-release */
10416 if (op == 3) {
10417 goto illegal_op;
10419 /* Fall through */
10420 case 3:
10421 /* Load-acquire/store-release exclusive */
10422 ARCH(8);
10423 is_lasr = true;
10424 break;
10427 if (is_lasr && !is_ld) {
10428 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
10431 addr = tcg_temp_local_new_i32();
10432 load_reg_var(s, addr, rn);
10433 if (!(op2 & 1)) {
10434 if (is_ld) {
10435 tmp = tcg_temp_new_i32();
10436 switch (op) {
10437 case 0: /* ldab */
10438 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s),
10439 rs | ISSIsAcqRel);
10440 break;
10441 case 1: /* ldah */
10442 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s),
10443 rs | ISSIsAcqRel);
10444 break;
10445 case 2: /* lda */
10446 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s),
10447 rs | ISSIsAcqRel);
10448 break;
10449 default:
10450 abort();
10452 store_reg(s, rs, tmp);
10453 } else {
10454 tmp = load_reg(s, rs);
10455 switch (op) {
10456 case 0: /* stlb */
10457 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s),
10458 rs | ISSIsAcqRel);
10459 break;
10460 case 1: /* stlh */
10461 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s),
10462 rs | ISSIsAcqRel);
10463 break;
10464 case 2: /* stl */
10465 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s),
10466 rs | ISSIsAcqRel);
10467 break;
10468 default:
10469 abort();
10471 tcg_temp_free_i32(tmp);
10473 } else if (is_ld) {
10474 gen_load_exclusive(s, rs, rd, addr, op);
10475 } else {
10476 gen_store_exclusive(s, rm, rs, rd, addr, op);
10478 tcg_temp_free_i32(addr);
10480 if (is_lasr && is_ld) {
10481 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
10484 } else {
10485 /* Load/store multiple, RFE, SRS. */
10486 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
10487 /* RFE, SRS: not available in user mode or on M profile */
10488 if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
10489 goto illegal_op;
10491 if (insn & (1 << 20)) {
10492 /* rfe */
10493 addr = load_reg(s, rn);
10494 if ((insn & (1 << 24)) == 0)
10495 tcg_gen_addi_i32(addr, addr, -8);
10496 /* Load PC into tmp and CPSR into tmp2. */
10497 tmp = tcg_temp_new_i32();
10498 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
10499 tcg_gen_addi_i32(addr, addr, 4);
10500 tmp2 = tcg_temp_new_i32();
10501 gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
10502 if (insn & (1 << 21)) {
10503 /* Base writeback. */
10504 if (insn & (1 << 24)) {
10505 tcg_gen_addi_i32(addr, addr, 4);
10506 } else {
10507 tcg_gen_addi_i32(addr, addr, -4);
10509 store_reg(s, rn, addr);
10510 } else {
10511 tcg_temp_free_i32(addr);
10513 gen_rfe(s, tmp, tmp2);
10514 } else {
10515 /* srs */
10516 gen_srs(s, (insn & 0x1f), (insn & (1 << 24)) ? 1 : 2,
10517 insn & (1 << 21));
10519 } else {
10520 int i, loaded_base = 0;
10521 TCGv_i32 loaded_var;
10522 bool wback = extract32(insn, 21, 1);
10523 /* Load/store multiple. */
10524 addr = load_reg(s, rn);
10525 offset = 0;
10526 for (i = 0; i < 16; i++) {
10527 if (insn & (1 << i))
10528 offset += 4;
10531 if (insn & (1 << 24)) {
10532 tcg_gen_addi_i32(addr, addr, -offset);
10535 if (s->v8m_stackcheck && rn == 13 && wback) {
10537 * If the writeback is incrementing SP rather than
10538 * decrementing it, and the initial SP is below the
10539 * stack limit but the final written-back SP would
10540 * be above, then then we must not perform any memory
10541 * accesses, but it is IMPDEF whether we generate
10542 * an exception. We choose to do so in this case.
10543 * At this point 'addr' is the lowest address, so
10544 * either the original SP (if incrementing) or our
10545 * final SP (if decrementing), so that's what we check.
10547 gen_helper_v8m_stackcheck(cpu_env, addr);
10550 loaded_var = NULL;
10551 for (i = 0; i < 16; i++) {
10552 if ((insn & (1 << i)) == 0)
10553 continue;
10554 if (insn & (1 << 20)) {
10555 /* Load. */
10556 tmp = tcg_temp_new_i32();
10557 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
10558 if (i == 15) {
10559 gen_bx_excret(s, tmp);
10560 } else if (i == rn) {
10561 loaded_var = tmp;
10562 loaded_base = 1;
10563 } else {
10564 store_reg(s, i, tmp);
10566 } else {
10567 /* Store. */
10568 tmp = load_reg(s, i);
10569 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
10570 tcg_temp_free_i32(tmp);
10572 tcg_gen_addi_i32(addr, addr, 4);
10574 if (loaded_base) {
10575 store_reg(s, rn, loaded_var);
10577 if (wback) {
10578 /* Base register writeback. */
10579 if (insn & (1 << 24)) {
10580 tcg_gen_addi_i32(addr, addr, -offset);
10582 /* Fault if writeback register is in register list. */
10583 if (insn & (1 << rn))
10584 goto illegal_op;
10585 store_reg(s, rn, addr);
10586 } else {
10587 tcg_temp_free_i32(addr);
10591 break;
10592 case 5:
10594 op = (insn >> 21) & 0xf;
10595 if (op == 6) {
10596 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10597 goto illegal_op;
10599 /* Halfword pack. */
10600 tmp = load_reg(s, rn);
10601 tmp2 = load_reg(s, rm);
10602 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
10603 if (insn & (1 << 5)) {
10604 /* pkhtb */
10605 if (shift == 0)
10606 shift = 31;
10607 tcg_gen_sari_i32(tmp2, tmp2, shift);
10608 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
10609 tcg_gen_ext16u_i32(tmp2, tmp2);
10610 } else {
10611 /* pkhbt */
10612 if (shift)
10613 tcg_gen_shli_i32(tmp2, tmp2, shift);
10614 tcg_gen_ext16u_i32(tmp, tmp);
10615 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
10617 tcg_gen_or_i32(tmp, tmp, tmp2);
10618 tcg_temp_free_i32(tmp2);
10619 store_reg(s, rd, tmp);
10620 } else {
10621 /* Data processing register constant shift. */
10622 if (rn == 15) {
10623 tmp = tcg_temp_new_i32();
10624 tcg_gen_movi_i32(tmp, 0);
10625 } else {
10626 tmp = load_reg(s, rn);
10628 tmp2 = load_reg(s, rm);
10630 shiftop = (insn >> 4) & 3;
10631 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
10632 conds = (insn & (1 << 20)) != 0;
10633 logic_cc = (conds && thumb2_logic_op(op));
10634 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
10635 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
10636 goto illegal_op;
10637 tcg_temp_free_i32(tmp2);
10638 if (rd == 13 &&
10639 ((op == 2 && rn == 15) ||
10640 (op == 8 && rn == 13) ||
10641 (op == 13 && rn == 13))) {
10642 /* MOV SP, ... or ADD SP, SP, ... or SUB SP, SP, ... */
10643 store_sp_checked(s, tmp);
10644 } else if (rd != 15) {
10645 store_reg(s, rd, tmp);
10646 } else {
10647 tcg_temp_free_i32(tmp);
10650 break;
10651 case 13: /* Misc data processing. */
10652 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
10653 if (op < 4 && (insn & 0xf000) != 0xf000)
10654 goto illegal_op;
10655 switch (op) {
10656 case 0: /* Register controlled shift. */
10657 tmp = load_reg(s, rn);
10658 tmp2 = load_reg(s, rm);
10659 if ((insn & 0x70) != 0)
10660 goto illegal_op;
10662 * 0b1111_1010_0xxx_xxxx_1111_xxxx_0000_xxxx:
10663 * - MOV, MOVS (register-shifted register), flagsetting
10665 op = (insn >> 21) & 3;
10666 logic_cc = (insn & (1 << 20)) != 0;
10667 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
10668 if (logic_cc)
10669 gen_logic_CC(tmp);
10670 store_reg(s, rd, tmp);
10671 break;
10672 case 1: /* Sign/zero extend. */
10673 op = (insn >> 20) & 7;
10674 switch (op) {
10675 case 0: /* SXTAH, SXTH */
10676 case 1: /* UXTAH, UXTH */
10677 case 4: /* SXTAB, SXTB */
10678 case 5: /* UXTAB, UXTB */
10679 break;
10680 case 2: /* SXTAB16, SXTB16 */
10681 case 3: /* UXTAB16, UXTB16 */
10682 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10683 goto illegal_op;
10685 break;
10686 default:
10687 goto illegal_op;
10689 if (rn != 15) {
10690 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10691 goto illegal_op;
10694 tmp = load_reg(s, rm);
10695 shift = (insn >> 4) & 3;
10696 /* ??? In many cases it's not necessary to do a
10697 rotate, a shift is sufficient. */
10698 if (shift != 0)
10699 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
10700 op = (insn >> 20) & 7;
10701 switch (op) {
10702 case 0: gen_sxth(tmp); break;
10703 case 1: gen_uxth(tmp); break;
10704 case 2: gen_sxtb16(tmp); break;
10705 case 3: gen_uxtb16(tmp); break;
10706 case 4: gen_sxtb(tmp); break;
10707 case 5: gen_uxtb(tmp); break;
10708 default:
10709 g_assert_not_reached();
10711 if (rn != 15) {
10712 tmp2 = load_reg(s, rn);
10713 if ((op >> 1) == 1) {
10714 gen_add16(tmp, tmp2);
10715 } else {
10716 tcg_gen_add_i32(tmp, tmp, tmp2);
10717 tcg_temp_free_i32(tmp2);
10720 store_reg(s, rd, tmp);
10721 break;
10722 case 2: /* SIMD add/subtract. */
10723 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10724 goto illegal_op;
10726 op = (insn >> 20) & 7;
10727 shift = (insn >> 4) & 7;
10728 if ((op & 3) == 3 || (shift & 3) == 3)
10729 goto illegal_op;
10730 tmp = load_reg(s, rn);
10731 tmp2 = load_reg(s, rm);
10732 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
10733 tcg_temp_free_i32(tmp2);
10734 store_reg(s, rd, tmp);
10735 break;
10736 case 3: /* Other data processing. */
10737 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
10738 if (op < 4) {
10739 /* Saturating add/subtract. */
10740 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10741 goto illegal_op;
10743 tmp = load_reg(s, rn);
10744 tmp2 = load_reg(s, rm);
10745 if (op & 1)
10746 gen_helper_double_saturate(tmp, cpu_env, tmp);
10747 if (op & 2)
10748 gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);
10749 else
10750 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
10751 tcg_temp_free_i32(tmp2);
10752 } else {
10753 switch (op) {
10754 case 0x0a: /* rbit */
10755 case 0x08: /* rev */
10756 case 0x09: /* rev16 */
10757 case 0x0b: /* revsh */
10758 case 0x18: /* clz */
10759 break;
10760 case 0x10: /* sel */
10761 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10762 goto illegal_op;
10764 break;
10765 case 0x20: /* crc32/crc32c */
10766 case 0x21:
10767 case 0x22:
10768 case 0x28:
10769 case 0x29:
10770 case 0x2a:
10771 if (!dc_isar_feature(aa32_crc32, s)) {
10772 goto illegal_op;
10774 break;
10775 default:
10776 goto illegal_op;
10778 tmp = load_reg(s, rn);
10779 switch (op) {
10780 case 0x0a: /* rbit */
10781 gen_helper_rbit(tmp, tmp);
10782 break;
10783 case 0x08: /* rev */
10784 tcg_gen_bswap32_i32(tmp, tmp);
10785 break;
10786 case 0x09: /* rev16 */
10787 gen_rev16(tmp);
10788 break;
10789 case 0x0b: /* revsh */
10790 gen_revsh(tmp);
10791 break;
10792 case 0x10: /* sel */
10793 tmp2 = load_reg(s, rm);
10794 tmp3 = tcg_temp_new_i32();
10795 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
10796 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
10797 tcg_temp_free_i32(tmp3);
10798 tcg_temp_free_i32(tmp2);
10799 break;
10800 case 0x18: /* clz */
10801 tcg_gen_clzi_i32(tmp, tmp, 32);
10802 break;
10803 case 0x20:
10804 case 0x21:
10805 case 0x22:
10806 case 0x28:
10807 case 0x29:
10808 case 0x2a:
10810 /* crc32/crc32c */
10811 uint32_t sz = op & 0x3;
10812 uint32_t c = op & 0x8;
10814 tmp2 = load_reg(s, rm);
10815 if (sz == 0) {
10816 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
10817 } else if (sz == 1) {
10818 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
10820 tmp3 = tcg_const_i32(1 << sz);
10821 if (c) {
10822 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
10823 } else {
10824 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
10826 tcg_temp_free_i32(tmp2);
10827 tcg_temp_free_i32(tmp3);
10828 break;
10830 default:
10831 g_assert_not_reached();
10834 store_reg(s, rd, tmp);
10835 break;
10836 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
10837 switch ((insn >> 20) & 7) {
10838 case 0: /* 32 x 32 -> 32 */
10839 case 7: /* Unsigned sum of absolute differences. */
10840 break;
10841 case 1: /* 16 x 16 -> 32 */
10842 case 2: /* Dual multiply add. */
10843 case 3: /* 32 * 16 -> 32msb */
10844 case 4: /* Dual multiply subtract. */
10845 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
10846 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10847 goto illegal_op;
10849 break;
10851 op = (insn >> 4) & 0xf;
10852 tmp = load_reg(s, rn);
10853 tmp2 = load_reg(s, rm);
10854 switch ((insn >> 20) & 7) {
10855 case 0: /* 32 x 32 -> 32 */
10856 tcg_gen_mul_i32(tmp, tmp, tmp2);
10857 tcg_temp_free_i32(tmp2);
10858 if (rs != 15) {
10859 tmp2 = load_reg(s, rs);
10860 if (op)
10861 tcg_gen_sub_i32(tmp, tmp2, tmp);
10862 else
10863 tcg_gen_add_i32(tmp, tmp, tmp2);
10864 tcg_temp_free_i32(tmp2);
10866 break;
10867 case 1: /* 16 x 16 -> 32 */
10868 gen_mulxy(tmp, tmp2, op & 2, op & 1);
10869 tcg_temp_free_i32(tmp2);
10870 if (rs != 15) {
10871 tmp2 = load_reg(s, rs);
10872 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
10873 tcg_temp_free_i32(tmp2);
10875 break;
10876 case 2: /* Dual multiply add. */
10877 case 4: /* Dual multiply subtract. */
10878 if (op)
10879 gen_swap_half(tmp2);
10880 gen_smul_dual(tmp, tmp2);
10881 if (insn & (1 << 22)) {
10882 /* This subtraction cannot overflow. */
10883 tcg_gen_sub_i32(tmp, tmp, tmp2);
10884 } else {
10885 /* This addition cannot overflow 32 bits;
10886 * however it may overflow considered as a signed
10887 * operation, in which case we must set the Q flag.
10889 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
10891 tcg_temp_free_i32(tmp2);
10892 if (rs != 15)
10894 tmp2 = load_reg(s, rs);
10895 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
10896 tcg_temp_free_i32(tmp2);
10898 break;
10899 case 3: /* 32 * 16 -> 32msb */
10900 if (op)
10901 tcg_gen_sari_i32(tmp2, tmp2, 16);
10902 else
10903 gen_sxth(tmp2);
10904 tmp64 = gen_muls_i64_i32(tmp, tmp2);
10905 tcg_gen_shri_i64(tmp64, tmp64, 16);
10906 tmp = tcg_temp_new_i32();
10907 tcg_gen_extrl_i64_i32(tmp, tmp64);
10908 tcg_temp_free_i64(tmp64);
10909 if (rs != 15)
10911 tmp2 = load_reg(s, rs);
10912 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
10913 tcg_temp_free_i32(tmp2);
10915 break;
10916 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
10917 tmp64 = gen_muls_i64_i32(tmp, tmp2);
10918 if (rs != 15) {
10919 tmp = load_reg(s, rs);
10920 if (insn & (1 << 20)) {
10921 tmp64 = gen_addq_msw(tmp64, tmp);
10922 } else {
10923 tmp64 = gen_subq_msw(tmp64, tmp);
10926 if (insn & (1 << 4)) {
10927 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
10929 tcg_gen_shri_i64(tmp64, tmp64, 32);
10930 tmp = tcg_temp_new_i32();
10931 tcg_gen_extrl_i64_i32(tmp, tmp64);
10932 tcg_temp_free_i64(tmp64);
10933 break;
10934 case 7: /* Unsigned sum of absolute differences. */
10935 gen_helper_usad8(tmp, tmp, tmp2);
10936 tcg_temp_free_i32(tmp2);
10937 if (rs != 15) {
10938 tmp2 = load_reg(s, rs);
10939 tcg_gen_add_i32(tmp, tmp, tmp2);
10940 tcg_temp_free_i32(tmp2);
10942 break;
10944 store_reg(s, rd, tmp);
10945 break;
10946 case 6: case 7: /* 64-bit multiply, Divide. */
10947 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
10948 tmp = load_reg(s, rn);
10949 tmp2 = load_reg(s, rm);
10950 if ((op & 0x50) == 0x10) {
10951 /* sdiv, udiv */
10952 if (!dc_isar_feature(thumb_div, s)) {
10953 goto illegal_op;
10955 if (op & 0x20)
10956 gen_helper_udiv(tmp, tmp, tmp2);
10957 else
10958 gen_helper_sdiv(tmp, tmp, tmp2);
10959 tcg_temp_free_i32(tmp2);
10960 store_reg(s, rd, tmp);
10961 } else if ((op & 0xe) == 0xc) {
10962 /* Dual multiply accumulate long. */
10963 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10964 tcg_temp_free_i32(tmp);
10965 tcg_temp_free_i32(tmp2);
10966 goto illegal_op;
10968 if (op & 1)
10969 gen_swap_half(tmp2);
10970 gen_smul_dual(tmp, tmp2);
10971 if (op & 0x10) {
10972 tcg_gen_sub_i32(tmp, tmp, tmp2);
10973 } else {
10974 tcg_gen_add_i32(tmp, tmp, tmp2);
10976 tcg_temp_free_i32(tmp2);
10977 /* BUGFIX */
10978 tmp64 = tcg_temp_new_i64();
10979 tcg_gen_ext_i32_i64(tmp64, tmp);
10980 tcg_temp_free_i32(tmp);
10981 gen_addq(s, tmp64, rs, rd);
10982 gen_storeq_reg(s, rs, rd, tmp64);
10983 tcg_temp_free_i64(tmp64);
10984 } else {
10985 if (op & 0x20) {
10986 /* Unsigned 64-bit multiply */
10987 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
10988 } else {
10989 if (op & 8) {
10990 /* smlalxy */
10991 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
10992 tcg_temp_free_i32(tmp2);
10993 tcg_temp_free_i32(tmp);
10994 goto illegal_op;
10996 gen_mulxy(tmp, tmp2, op & 2, op & 1);
10997 tcg_temp_free_i32(tmp2);
10998 tmp64 = tcg_temp_new_i64();
10999 tcg_gen_ext_i32_i64(tmp64, tmp);
11000 tcg_temp_free_i32(tmp);
11001 } else {
11002 /* Signed 64-bit multiply */
11003 tmp64 = gen_muls_i64_i32(tmp, tmp2);
11006 if (op & 4) {
11007 /* umaal */
11008 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11009 tcg_temp_free_i64(tmp64);
11010 goto illegal_op;
11012 gen_addq_lo(s, tmp64, rs);
11013 gen_addq_lo(s, tmp64, rd);
11014 } else if (op & 0x40) {
11015 /* 64-bit accumulate. */
11016 gen_addq(s, tmp64, rs, rd);
11018 gen_storeq_reg(s, rs, rd, tmp64);
11019 tcg_temp_free_i64(tmp64);
11021 break;
11023 break;
11024 case 6: case 7: case 14: case 15:
11025 /* Coprocessor. */
11026 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11027 /* 0b111x_11xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx */
11028 if (extract32(insn, 24, 2) == 3) {
11029 goto illegal_op; /* op0 = 0b11 : unallocated */
11033 * Decode VLLDM and VLSTM first: these are nonstandard because:
11034 * * if there is no FPU then these insns must NOP in
11035 * Secure state and UNDEF in Nonsecure state
11036 * * if there is an FPU then these insns do not have
11037 * the usual behaviour that disas_vfp_insn() provides of
11038 * being controlled by CPACR/NSACR enable bits or the
11039 * lazy-stacking logic.
11041 if (arm_dc_feature(s, ARM_FEATURE_V8) &&
11042 (insn & 0xffa00f00) == 0xec200a00) {
11043 /* 0b1110_1100_0x1x_xxxx_xxxx_1010_xxxx_xxxx
11044 * - VLLDM, VLSTM
11045 * We choose to UNDEF if the RAZ bits are non-zero.
11047 if (!s->v8m_secure || (insn & 0x0040f0ff)) {
11048 goto illegal_op;
11051 if (arm_dc_feature(s, ARM_FEATURE_VFP)) {
11052 TCGv_i32 fptr = load_reg(s, rn);
11054 if (extract32(insn, 20, 1)) {
11055 gen_helper_v7m_vlldm(cpu_env, fptr);
11056 } else {
11057 gen_helper_v7m_vlstm(cpu_env, fptr);
11059 tcg_temp_free_i32(fptr);
11061 /* End the TB, because we have updated FP control bits */
11062 s->base.is_jmp = DISAS_UPDATE;
11064 break;
11066 if (arm_dc_feature(s, ARM_FEATURE_VFP) &&
11067 ((insn >> 8) & 0xe) == 10) {
11068 /* FP, and the CPU supports it */
11069 if (disas_vfp_insn(s, insn)) {
11070 goto illegal_op;
11072 break;
11075 /* All other insns: NOCP */
11076 gen_exception_insn(s, 4, EXCP_NOCP, syn_uncategorized(),
11077 default_exception_el(s));
11078 break;
11080 if ((insn & 0xfe000a00) == 0xfc000800
11081 && arm_dc_feature(s, ARM_FEATURE_V8)) {
11082 /* The Thumb2 and ARM encodings are identical. */
11083 if (disas_neon_insn_3same_ext(s, insn)) {
11084 goto illegal_op;
11086 } else if ((insn & 0xff000a00) == 0xfe000800
11087 && arm_dc_feature(s, ARM_FEATURE_V8)) {
11088 /* The Thumb2 and ARM encodings are identical. */
11089 if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
11090 goto illegal_op;
11092 } else if (((insn >> 24) & 3) == 3) {
11093 /* Translate into the equivalent ARM encoding. */
11094 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
11095 if (disas_neon_data_insn(s, insn)) {
11096 goto illegal_op;
11098 } else if (((insn >> 8) & 0xe) == 10) {
11099 if (disas_vfp_insn(s, insn)) {
11100 goto illegal_op;
11102 } else {
11103 if (insn & (1 << 28))
11104 goto illegal_op;
11105 if (disas_coproc_insn(s, insn)) {
11106 goto illegal_op;
11109 break;
11110 case 8: case 9: case 10: case 11:
11111 if (insn & (1 << 15)) {
11112 /* Branches, misc control. */
11113 if (insn & 0x5000) {
11114 /* Unconditional branch. */
11115 /* signextend(hw1[10:0]) -> offset[:12]. */
11116 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
11117 /* hw1[10:0] -> offset[11:1]. */
11118 offset |= (insn & 0x7ff) << 1;
11119 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
11120 offset[24:22] already have the same value because of the
11121 sign extension above. */
11122 offset ^= ((~insn) & (1 << 13)) << 10;
11123 offset ^= ((~insn) & (1 << 11)) << 11;
11125 if (insn & (1 << 14)) {
11126 /* Branch and link. */
11127 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
11130 offset += s->pc;
11131 if (insn & (1 << 12)) {
11132 /* b/bl */
11133 gen_jmp(s, offset);
11134 } else {
11135 /* blx */
11136 offset &= ~(uint32_t)2;
11137 /* thumb2 bx, no need to check */
11138 gen_bx_im(s, offset);
11140 } else if (((insn >> 23) & 7) == 7) {
11141 /* Misc control */
11142 if (insn & (1 << 13))
11143 goto illegal_op;
11145 if (insn & (1 << 26)) {
11146 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11147 goto illegal_op;
11149 if (!(insn & (1 << 20))) {
11150 /* Hypervisor call (v7) */
11151 int imm16 = extract32(insn, 16, 4) << 12
11152 | extract32(insn, 0, 12);
11153 ARCH(7);
11154 if (IS_USER(s)) {
11155 goto illegal_op;
11157 gen_hvc(s, imm16);
11158 } else {
11159 /* Secure monitor call (v6+) */
11160 ARCH(6K);
11161 if (IS_USER(s)) {
11162 goto illegal_op;
11164 gen_smc(s);
11166 } else {
11167 op = (insn >> 20) & 7;
11168 switch (op) {
11169 case 0: /* msr cpsr. */
11170 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11171 tmp = load_reg(s, rn);
11172 /* the constant is the mask and SYSm fields */
11173 addr = tcg_const_i32(insn & 0xfff);
11174 gen_helper_v7m_msr(cpu_env, addr, tmp);
11175 tcg_temp_free_i32(addr);
11176 tcg_temp_free_i32(tmp);
11177 gen_lookup_tb(s);
11178 break;
11180 /* fall through */
11181 case 1: /* msr spsr. */
11182 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11183 goto illegal_op;
11186 if (extract32(insn, 5, 1)) {
11187 /* MSR (banked) */
11188 int sysm = extract32(insn, 8, 4) |
11189 (extract32(insn, 4, 1) << 4);
11190 int r = op & 1;
11192 gen_msr_banked(s, r, sysm, rm);
11193 break;
11196 /* MSR (for PSRs) */
11197 tmp = load_reg(s, rn);
11198 if (gen_set_psr(s,
11199 msr_mask(s, (insn >> 8) & 0xf, op == 1),
11200 op == 1, tmp))
11201 goto illegal_op;
11202 break;
11203 case 2: /* cps, nop-hint. */
11204 if (((insn >> 8) & 7) == 0) {
11205 gen_nop_hint(s, insn & 0xff);
11207 /* Implemented as NOP in user mode. */
11208 if (IS_USER(s))
11209 break;
11210 offset = 0;
11211 imm = 0;
11212 if (insn & (1 << 10)) {
11213 if (insn & (1 << 7))
11214 offset |= CPSR_A;
11215 if (insn & (1 << 6))
11216 offset |= CPSR_I;
11217 if (insn & (1 << 5))
11218 offset |= CPSR_F;
11219 if (insn & (1 << 9))
11220 imm = CPSR_A | CPSR_I | CPSR_F;
11222 if (insn & (1 << 8)) {
11223 offset |= 0x1f;
11224 imm |= (insn & 0x1f);
11226 if (offset) {
11227 gen_set_psr_im(s, offset, 0, imm);
11229 break;
11230 case 3: /* Special control operations. */
11231 if (!arm_dc_feature(s, ARM_FEATURE_V7) &&
11232 !arm_dc_feature(s, ARM_FEATURE_M)) {
11233 goto illegal_op;
11235 op = (insn >> 4) & 0xf;
11236 switch (op) {
11237 case 2: /* clrex */
11238 gen_clrex(s);
11239 break;
11240 case 4: /* dsb */
11241 case 5: /* dmb */
11242 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
11243 break;
11244 case 6: /* isb */
11245 /* We need to break the TB after this insn
11246 * to execute self-modifying code correctly
11247 * and also to take any pending interrupts
11248 * immediately.
11250 gen_goto_tb(s, 0, s->pc & ~1);
11251 break;
11252 case 7: /* sb */
11253 if ((insn & 0xf) || !dc_isar_feature(aa32_sb, s)) {
11254 goto illegal_op;
11257 * TODO: There is no speculation barrier opcode
11258 * for TCG; MB and end the TB instead.
11260 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
11261 gen_goto_tb(s, 0, s->pc & ~1);
11262 break;
11263 default:
11264 goto illegal_op;
11266 break;
11267 case 4: /* bxj */
11268 /* Trivial implementation equivalent to bx.
11269 * This instruction doesn't exist at all for M-profile.
11271 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11272 goto illegal_op;
11274 tmp = load_reg(s, rn);
11275 gen_bx(s, tmp);
11276 break;
11277 case 5: /* Exception return. */
11278 if (IS_USER(s)) {
11279 goto illegal_op;
11281 if (rn != 14 || rd != 15) {
11282 goto illegal_op;
11284 if (s->current_el == 2) {
11285 /* ERET from Hyp uses ELR_Hyp, not LR */
11286 if (insn & 0xff) {
11287 goto illegal_op;
11289 tmp = load_cpu_field(elr_el[2]);
11290 } else {
11291 tmp = load_reg(s, rn);
11292 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
11294 gen_exception_return(s, tmp);
11295 break;
11296 case 6: /* MRS */
11297 if (extract32(insn, 5, 1) &&
11298 !arm_dc_feature(s, ARM_FEATURE_M)) {
11299 /* MRS (banked) */
11300 int sysm = extract32(insn, 16, 4) |
11301 (extract32(insn, 4, 1) << 4);
11303 gen_mrs_banked(s, 0, sysm, rd);
11304 break;
11307 if (extract32(insn, 16, 4) != 0xf) {
11308 goto illegal_op;
11310 if (!arm_dc_feature(s, ARM_FEATURE_M) &&
11311 extract32(insn, 0, 8) != 0) {
11312 goto illegal_op;
11315 /* mrs cpsr */
11316 tmp = tcg_temp_new_i32();
11317 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11318 addr = tcg_const_i32(insn & 0xff);
11319 gen_helper_v7m_mrs(tmp, cpu_env, addr);
11320 tcg_temp_free_i32(addr);
11321 } else {
11322 gen_helper_cpsr_read(tmp, cpu_env);
11324 store_reg(s, rd, tmp);
11325 break;
11326 case 7: /* MRS */
11327 if (extract32(insn, 5, 1) &&
11328 !arm_dc_feature(s, ARM_FEATURE_M)) {
11329 /* MRS (banked) */
11330 int sysm = extract32(insn, 16, 4) |
11331 (extract32(insn, 4, 1) << 4);
11333 gen_mrs_banked(s, 1, sysm, rd);
11334 break;
11337 /* mrs spsr. */
11338 /* Not accessible in user mode. */
11339 if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
11340 goto illegal_op;
11343 if (extract32(insn, 16, 4) != 0xf ||
11344 extract32(insn, 0, 8) != 0) {
11345 goto illegal_op;
11348 tmp = load_cpu_field(spsr);
11349 store_reg(s, rd, tmp);
11350 break;
11353 } else {
11354 /* Conditional branch. */
11355 op = (insn >> 22) & 0xf;
11356 /* Generate a conditional jump to next instruction. */
11357 arm_skip_unless(s, op);
11359 /* offset[11:1] = insn[10:0] */
11360 offset = (insn & 0x7ff) << 1;
11361 /* offset[17:12] = insn[21:16]. */
11362 offset |= (insn & 0x003f0000) >> 4;
11363 /* offset[31:20] = insn[26]. */
11364 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
11365 /* offset[18] = insn[13]. */
11366 offset |= (insn & (1 << 13)) << 5;
11367 /* offset[19] = insn[11]. */
11368 offset |= (insn & (1 << 11)) << 8;
11370 /* jump to the offset */
11371 gen_jmp(s, s->pc + offset);
11373 } else {
11375 * 0b1111_0xxx_xxxx_0xxx_xxxx_xxxx
11376 * - Data-processing (modified immediate, plain binary immediate)
11378 if (insn & (1 << 25)) {
11380 * 0b1111_0x1x_xxxx_0xxx_xxxx_xxxx
11381 * - Data-processing (plain binary immediate)
11383 if (insn & (1 << 24)) {
11384 if (insn & (1 << 20))
11385 goto illegal_op;
11386 /* Bitfield/Saturate. */
11387 op = (insn >> 21) & 7;
11388 imm = insn & 0x1f;
11389 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
11390 if (rn == 15) {
11391 tmp = tcg_temp_new_i32();
11392 tcg_gen_movi_i32(tmp, 0);
11393 } else {
11394 tmp = load_reg(s, rn);
11396 switch (op) {
11397 case 2: /* Signed bitfield extract. */
11398 imm++;
11399 if (shift + imm > 32)
11400 goto illegal_op;
11401 if (imm < 32) {
11402 tcg_gen_sextract_i32(tmp, tmp, shift, imm);
11404 break;
11405 case 6: /* Unsigned bitfield extract. */
11406 imm++;
11407 if (shift + imm > 32)
11408 goto illegal_op;
11409 if (imm < 32) {
11410 tcg_gen_extract_i32(tmp, tmp, shift, imm);
11412 break;
11413 case 3: /* Bitfield insert/clear. */
11414 if (imm < shift)
11415 goto illegal_op;
11416 imm = imm + 1 - shift;
11417 if (imm != 32) {
11418 tmp2 = load_reg(s, rd);
11419 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, imm);
11420 tcg_temp_free_i32(tmp2);
11422 break;
11423 case 7:
11424 goto illegal_op;
11425 default: /* Saturate. */
11426 if (shift) {
11427 if (op & 1)
11428 tcg_gen_sari_i32(tmp, tmp, shift);
11429 else
11430 tcg_gen_shli_i32(tmp, tmp, shift);
11432 tmp2 = tcg_const_i32(imm);
11433 if (op & 4) {
11434 /* Unsigned. */
11435 if ((op & 1) && shift == 0) {
11436 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11437 tcg_temp_free_i32(tmp);
11438 tcg_temp_free_i32(tmp2);
11439 goto illegal_op;
11441 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
11442 } else {
11443 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
11445 } else {
11446 /* Signed. */
11447 if ((op & 1) && shift == 0) {
11448 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11449 tcg_temp_free_i32(tmp);
11450 tcg_temp_free_i32(tmp2);
11451 goto illegal_op;
11453 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
11454 } else {
11455 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
11458 tcg_temp_free_i32(tmp2);
11459 break;
11461 store_reg(s, rd, tmp);
11462 } else {
11463 imm = ((insn & 0x04000000) >> 15)
11464 | ((insn & 0x7000) >> 4) | (insn & 0xff);
11465 if (insn & (1 << 22)) {
11466 /* 16-bit immediate. */
11467 imm |= (insn >> 4) & 0xf000;
11468 if (insn & (1 << 23)) {
11469 /* movt */
11470 tmp = load_reg(s, rd);
11471 tcg_gen_ext16u_i32(tmp, tmp);
11472 tcg_gen_ori_i32(tmp, tmp, imm << 16);
11473 } else {
11474 /* movw */
11475 tmp = tcg_temp_new_i32();
11476 tcg_gen_movi_i32(tmp, imm);
11478 store_reg(s, rd, tmp);
11479 } else {
11480 /* Add/sub 12-bit immediate. */
11481 if (rn == 15) {
11482 offset = s->pc & ~(uint32_t)3;
11483 if (insn & (1 << 23))
11484 offset -= imm;
11485 else
11486 offset += imm;
11487 tmp = tcg_temp_new_i32();
11488 tcg_gen_movi_i32(tmp, offset);
11489 store_reg(s, rd, tmp);
11490 } else {
11491 tmp = load_reg(s, rn);
11492 if (insn & (1 << 23))
11493 tcg_gen_subi_i32(tmp, tmp, imm);
11494 else
11495 tcg_gen_addi_i32(tmp, tmp, imm);
11496 if (rn == 13 && rd == 13) {
11497 /* ADD SP, SP, imm or SUB SP, SP, imm */
11498 store_sp_checked(s, tmp);
11499 } else {
11500 store_reg(s, rd, tmp);
11505 } else {
11507 * 0b1111_0x0x_xxxx_0xxx_xxxx_xxxx
11508 * - Data-processing (modified immediate)
11510 int shifter_out = 0;
11511 /* modified 12-bit immediate. */
11512 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
11513 imm = (insn & 0xff);
11514 switch (shift) {
11515 case 0: /* XY */
11516 /* Nothing to do. */
11517 break;
11518 case 1: /* 00XY00XY */
11519 imm |= imm << 16;
11520 break;
11521 case 2: /* XY00XY00 */
11522 imm |= imm << 16;
11523 imm <<= 8;
11524 break;
11525 case 3: /* XYXYXYXY */
11526 imm |= imm << 16;
11527 imm |= imm << 8;
11528 break;
11529 default: /* Rotated constant. */
11530 shift = (shift << 1) | (imm >> 7);
11531 imm |= 0x80;
11532 imm = imm << (32 - shift);
11533 shifter_out = 1;
11534 break;
11536 tmp2 = tcg_temp_new_i32();
11537 tcg_gen_movi_i32(tmp2, imm);
11538 rn = (insn >> 16) & 0xf;
11539 if (rn == 15) {
11540 tmp = tcg_temp_new_i32();
11541 tcg_gen_movi_i32(tmp, 0);
11542 } else {
11543 tmp = load_reg(s, rn);
11545 op = (insn >> 21) & 0xf;
11546 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
11547 shifter_out, tmp, tmp2))
11548 goto illegal_op;
11549 tcg_temp_free_i32(tmp2);
11550 rd = (insn >> 8) & 0xf;
11551 if (rd == 13 && rn == 13
11552 && (op == 8 || op == 13)) {
11553 /* ADD(S) SP, SP, imm or SUB(S) SP, SP, imm */
11554 store_sp_checked(s, tmp);
11555 } else if (rd != 15) {
11556 store_reg(s, rd, tmp);
11557 } else {
11558 tcg_temp_free_i32(tmp);
11562 break;
11563 case 12: /* Load/store single data item. */
11565 int postinc = 0;
11566 int writeback = 0;
11567 int memidx;
11568 ISSInfo issinfo;
11570 if ((insn & 0x01100000) == 0x01000000) {
11571 if (disas_neon_ls_insn(s, insn)) {
11572 goto illegal_op;
11574 break;
11576 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
11577 if (rs == 15) {
11578 if (!(insn & (1 << 20))) {
11579 goto illegal_op;
11581 if (op != 2) {
11582 /* Byte or halfword load space with dest == r15 : memory hints.
11583 * Catch them early so we don't emit pointless addressing code.
11584 * This space is a mix of:
11585 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
11586 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
11587 * cores)
11588 * unallocated hints, which must be treated as NOPs
11589 * UNPREDICTABLE space, which we NOP or UNDEF depending on
11590 * which is easiest for the decoding logic
11591 * Some space which must UNDEF
11593 int op1 = (insn >> 23) & 3;
11594 int op2 = (insn >> 6) & 0x3f;
11595 if (op & 2) {
11596 goto illegal_op;
11598 if (rn == 15) {
11599 /* UNPREDICTABLE, unallocated hint or
11600 * PLD/PLDW/PLI (literal)
11602 return;
11604 if (op1 & 1) {
11605 return; /* PLD/PLDW/PLI or unallocated hint */
11607 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
11608 return; /* PLD/PLDW/PLI or unallocated hint */
11610 /* UNDEF space, or an UNPREDICTABLE */
11611 goto illegal_op;
11614 memidx = get_mem_index(s);
11615 if (rn == 15) {
11616 addr = tcg_temp_new_i32();
11617 /* PC relative. */
11618 /* s->pc has already been incremented by 4. */
11619 imm = s->pc & 0xfffffffc;
11620 if (insn & (1 << 23))
11621 imm += insn & 0xfff;
11622 else
11623 imm -= insn & 0xfff;
11624 tcg_gen_movi_i32(addr, imm);
11625 } else {
11626 addr = load_reg(s, rn);
11627 if (insn & (1 << 23)) {
11628 /* Positive offset. */
11629 imm = insn & 0xfff;
11630 tcg_gen_addi_i32(addr, addr, imm);
11631 } else {
11632 imm = insn & 0xff;
11633 switch ((insn >> 8) & 0xf) {
11634 case 0x0: /* Shifted Register. */
11635 shift = (insn >> 4) & 0xf;
11636 if (shift > 3) {
11637 tcg_temp_free_i32(addr);
11638 goto illegal_op;
11640 tmp = load_reg(s, rm);
11641 if (shift)
11642 tcg_gen_shli_i32(tmp, tmp, shift);
11643 tcg_gen_add_i32(addr, addr, tmp);
11644 tcg_temp_free_i32(tmp);
11645 break;
11646 case 0xc: /* Negative offset. */
11647 tcg_gen_addi_i32(addr, addr, -imm);
11648 break;
11649 case 0xe: /* User privilege. */
11650 tcg_gen_addi_i32(addr, addr, imm);
11651 memidx = get_a32_user_mem_index(s);
11652 break;
11653 case 0x9: /* Post-decrement. */
11654 imm = -imm;
11655 /* Fall through. */
11656 case 0xb: /* Post-increment. */
11657 postinc = 1;
11658 writeback = 1;
11659 break;
11660 case 0xd: /* Pre-decrement. */
11661 imm = -imm;
11662 /* Fall through. */
11663 case 0xf: /* Pre-increment. */
11664 writeback = 1;
11665 break;
11666 default:
11667 tcg_temp_free_i32(addr);
11668 goto illegal_op;
11673 issinfo = writeback ? ISSInvalid : rs;
11675 if (s->v8m_stackcheck && rn == 13 && writeback) {
11677 * Stackcheck. Here we know 'addr' is the current SP;
11678 * if imm is +ve we're moving SP up, else down. It is
11679 * UNKNOWN whether the limit check triggers when SP starts
11680 * below the limit and ends up above it; we chose to do so.
11682 if ((int32_t)imm < 0) {
11683 TCGv_i32 newsp = tcg_temp_new_i32();
11685 tcg_gen_addi_i32(newsp, addr, imm);
11686 gen_helper_v8m_stackcheck(cpu_env, newsp);
11687 tcg_temp_free_i32(newsp);
11688 } else {
11689 gen_helper_v8m_stackcheck(cpu_env, addr);
11693 if (writeback && !postinc) {
11694 tcg_gen_addi_i32(addr, addr, imm);
11697 if (insn & (1 << 20)) {
11698 /* Load. */
11699 tmp = tcg_temp_new_i32();
11700 switch (op) {
11701 case 0:
11702 gen_aa32_ld8u_iss(s, tmp, addr, memidx, issinfo);
11703 break;
11704 case 4:
11705 gen_aa32_ld8s_iss(s, tmp, addr, memidx, issinfo);
11706 break;
11707 case 1:
11708 gen_aa32_ld16u_iss(s, tmp, addr, memidx, issinfo);
11709 break;
11710 case 5:
11711 gen_aa32_ld16s_iss(s, tmp, addr, memidx, issinfo);
11712 break;
11713 case 2:
11714 gen_aa32_ld32u_iss(s, tmp, addr, memidx, issinfo);
11715 break;
11716 default:
11717 tcg_temp_free_i32(tmp);
11718 tcg_temp_free_i32(addr);
11719 goto illegal_op;
11721 if (rs == 15) {
11722 gen_bx_excret(s, tmp);
11723 } else {
11724 store_reg(s, rs, tmp);
11726 } else {
11727 /* Store. */
11728 tmp = load_reg(s, rs);
11729 switch (op) {
11730 case 0:
11731 gen_aa32_st8_iss(s, tmp, addr, memidx, issinfo);
11732 break;
11733 case 1:
11734 gen_aa32_st16_iss(s, tmp, addr, memidx, issinfo);
11735 break;
11736 case 2:
11737 gen_aa32_st32_iss(s, tmp, addr, memidx, issinfo);
11738 break;
11739 default:
11740 tcg_temp_free_i32(tmp);
11741 tcg_temp_free_i32(addr);
11742 goto illegal_op;
11744 tcg_temp_free_i32(tmp);
11746 if (postinc)
11747 tcg_gen_addi_i32(addr, addr, imm);
11748 if (writeback) {
11749 store_reg(s, rn, addr);
11750 } else {
11751 tcg_temp_free_i32(addr);
11754 break;
11755 default:
11756 goto illegal_op;
11758 return;
11759 illegal_op:
11760 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
11761 default_exception_el(s));
11764 static void disas_thumb_insn(DisasContext *s, uint32_t insn)
11766 uint32_t val, op, rm, rn, rd, shift, cond;
11767 int32_t offset;
11768 int i;
11769 TCGv_i32 tmp;
11770 TCGv_i32 tmp2;
11771 TCGv_i32 addr;
11773 switch (insn >> 12) {
11774 case 0: case 1:
11776 rd = insn & 7;
11777 op = (insn >> 11) & 3;
11778 if (op == 3) {
11780 * 0b0001_1xxx_xxxx_xxxx
11781 * - Add, subtract (three low registers)
11782 * - Add, subtract (two low registers and immediate)
11784 rn = (insn >> 3) & 7;
11785 tmp = load_reg(s, rn);
11786 if (insn & (1 << 10)) {
11787 /* immediate */
11788 tmp2 = tcg_temp_new_i32();
11789 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
11790 } else {
11791 /* reg */
11792 rm = (insn >> 6) & 7;
11793 tmp2 = load_reg(s, rm);
11795 if (insn & (1 << 9)) {
11796 if (s->condexec_mask)
11797 tcg_gen_sub_i32(tmp, tmp, tmp2);
11798 else
11799 gen_sub_CC(tmp, tmp, tmp2);
11800 } else {
11801 if (s->condexec_mask)
11802 tcg_gen_add_i32(tmp, tmp, tmp2);
11803 else
11804 gen_add_CC(tmp, tmp, tmp2);
11806 tcg_temp_free_i32(tmp2);
11807 store_reg(s, rd, tmp);
11808 } else {
11809 /* shift immediate */
11810 rm = (insn >> 3) & 7;
11811 shift = (insn >> 6) & 0x1f;
11812 tmp = load_reg(s, rm);
11813 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
11814 if (!s->condexec_mask)
11815 gen_logic_CC(tmp);
11816 store_reg(s, rd, tmp);
11818 break;
11819 case 2: case 3:
11821 * 0b001x_xxxx_xxxx_xxxx
11822 * - Add, subtract, compare, move (one low register and immediate)
11824 op = (insn >> 11) & 3;
11825 rd = (insn >> 8) & 0x7;
11826 if (op == 0) { /* mov */
11827 tmp = tcg_temp_new_i32();
11828 tcg_gen_movi_i32(tmp, insn & 0xff);
11829 if (!s->condexec_mask)
11830 gen_logic_CC(tmp);
11831 store_reg(s, rd, tmp);
11832 } else {
11833 tmp = load_reg(s, rd);
11834 tmp2 = tcg_temp_new_i32();
11835 tcg_gen_movi_i32(tmp2, insn & 0xff);
11836 switch (op) {
11837 case 1: /* cmp */
11838 gen_sub_CC(tmp, tmp, tmp2);
11839 tcg_temp_free_i32(tmp);
11840 tcg_temp_free_i32(tmp2);
11841 break;
11842 case 2: /* add */
11843 if (s->condexec_mask)
11844 tcg_gen_add_i32(tmp, tmp, tmp2);
11845 else
11846 gen_add_CC(tmp, tmp, tmp2);
11847 tcg_temp_free_i32(tmp2);
11848 store_reg(s, rd, tmp);
11849 break;
11850 case 3: /* sub */
11851 if (s->condexec_mask)
11852 tcg_gen_sub_i32(tmp, tmp, tmp2);
11853 else
11854 gen_sub_CC(tmp, tmp, tmp2);
11855 tcg_temp_free_i32(tmp2);
11856 store_reg(s, rd, tmp);
11857 break;
11860 break;
11861 case 4:
11862 if (insn & (1 << 11)) {
11863 rd = (insn >> 8) & 7;
11864 /* load pc-relative. Bit 1 of PC is ignored. */
11865 val = s->pc + 2 + ((insn & 0xff) * 4);
11866 val &= ~(uint32_t)2;
11867 addr = tcg_temp_new_i32();
11868 tcg_gen_movi_i32(addr, val);
11869 tmp = tcg_temp_new_i32();
11870 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s),
11871 rd | ISSIs16Bit);
11872 tcg_temp_free_i32(addr);
11873 store_reg(s, rd, tmp);
11874 break;
11876 if (insn & (1 << 10)) {
11877 /* 0b0100_01xx_xxxx_xxxx
11878 * - data processing extended, branch and exchange
11880 rd = (insn & 7) | ((insn >> 4) & 8);
11881 rm = (insn >> 3) & 0xf;
11882 op = (insn >> 8) & 3;
11883 switch (op) {
11884 case 0: /* add */
11885 tmp = load_reg(s, rd);
11886 tmp2 = load_reg(s, rm);
11887 tcg_gen_add_i32(tmp, tmp, tmp2);
11888 tcg_temp_free_i32(tmp2);
11889 if (rd == 13) {
11890 /* ADD SP, SP, reg */
11891 store_sp_checked(s, tmp);
11892 } else {
11893 store_reg(s, rd, tmp);
11895 break;
11896 case 1: /* cmp */
11897 tmp = load_reg(s, rd);
11898 tmp2 = load_reg(s, rm);
11899 gen_sub_CC(tmp, tmp, tmp2);
11900 tcg_temp_free_i32(tmp2);
11901 tcg_temp_free_i32(tmp);
11902 break;
11903 case 2: /* mov/cpy */
11904 tmp = load_reg(s, rm);
11905 if (rd == 13) {
11906 /* MOV SP, reg */
11907 store_sp_checked(s, tmp);
11908 } else {
11909 store_reg(s, rd, tmp);
11911 break;
11912 case 3:
11914 /* 0b0100_0111_xxxx_xxxx
11915 * - branch [and link] exchange thumb register
11917 bool link = insn & (1 << 7);
11919 if (insn & 3) {
11920 goto undef;
11922 if (link) {
11923 ARCH(5);
11925 if ((insn & 4)) {
11926 /* BXNS/BLXNS: only exists for v8M with the
11927 * security extensions, and always UNDEF if NonSecure.
11928 * We don't implement these in the user-only mode
11929 * either (in theory you can use them from Secure User
11930 * mode but they are too tied in to system emulation.)
11932 if (!s->v8m_secure || IS_USER_ONLY) {
11933 goto undef;
11935 if (link) {
11936 gen_blxns(s, rm);
11937 } else {
11938 gen_bxns(s, rm);
11940 break;
11942 /* BLX/BX */
11943 tmp = load_reg(s, rm);
11944 if (link) {
11945 val = (uint32_t)s->pc | 1;
11946 tmp2 = tcg_temp_new_i32();
11947 tcg_gen_movi_i32(tmp2, val);
11948 store_reg(s, 14, tmp2);
11949 gen_bx(s, tmp);
11950 } else {
11951 /* Only BX works as exception-return, not BLX */
11952 gen_bx_excret(s, tmp);
11954 break;
11957 break;
11961 * 0b0100_00xx_xxxx_xxxx
11962 * - Data-processing (two low registers)
11964 rd = insn & 7;
11965 rm = (insn >> 3) & 7;
11966 op = (insn >> 6) & 0xf;
11967 if (op == 2 || op == 3 || op == 4 || op == 7) {
11968 /* the shift/rotate ops want the operands backwards */
11969 val = rm;
11970 rm = rd;
11971 rd = val;
11972 val = 1;
11973 } else {
11974 val = 0;
11977 if (op == 9) { /* neg */
11978 tmp = tcg_temp_new_i32();
11979 tcg_gen_movi_i32(tmp, 0);
11980 } else if (op != 0xf) { /* mvn doesn't read its first operand */
11981 tmp = load_reg(s, rd);
11982 } else {
11983 tmp = NULL;
11986 tmp2 = load_reg(s, rm);
11987 switch (op) {
11988 case 0x0: /* and */
11989 tcg_gen_and_i32(tmp, tmp, tmp2);
11990 if (!s->condexec_mask)
11991 gen_logic_CC(tmp);
11992 break;
11993 case 0x1: /* eor */
11994 tcg_gen_xor_i32(tmp, tmp, tmp2);
11995 if (!s->condexec_mask)
11996 gen_logic_CC(tmp);
11997 break;
11998 case 0x2: /* lsl */
11999 if (s->condexec_mask) {
12000 gen_shl(tmp2, tmp2, tmp);
12001 } else {
12002 gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
12003 gen_logic_CC(tmp2);
12005 break;
12006 case 0x3: /* lsr */
12007 if (s->condexec_mask) {
12008 gen_shr(tmp2, tmp2, tmp);
12009 } else {
12010 gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
12011 gen_logic_CC(tmp2);
12013 break;
12014 case 0x4: /* asr */
12015 if (s->condexec_mask) {
12016 gen_sar(tmp2, tmp2, tmp);
12017 } else {
12018 gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
12019 gen_logic_CC(tmp2);
12021 break;
12022 case 0x5: /* adc */
12023 if (s->condexec_mask) {
12024 gen_adc(tmp, tmp2);
12025 } else {
12026 gen_adc_CC(tmp, tmp, tmp2);
12028 break;
12029 case 0x6: /* sbc */
12030 if (s->condexec_mask) {
12031 gen_sub_carry(tmp, tmp, tmp2);
12032 } else {
12033 gen_sbc_CC(tmp, tmp, tmp2);
12035 break;
12036 case 0x7: /* ror */
12037 if (s->condexec_mask) {
12038 tcg_gen_andi_i32(tmp, tmp, 0x1f);
12039 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
12040 } else {
12041 gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);
12042 gen_logic_CC(tmp2);
12044 break;
12045 case 0x8: /* tst */
12046 tcg_gen_and_i32(tmp, tmp, tmp2);
12047 gen_logic_CC(tmp);
12048 rd = 16;
12049 break;
12050 case 0x9: /* neg */
12051 if (s->condexec_mask)
12052 tcg_gen_neg_i32(tmp, tmp2);
12053 else
12054 gen_sub_CC(tmp, tmp, tmp2);
12055 break;
12056 case 0xa: /* cmp */
12057 gen_sub_CC(tmp, tmp, tmp2);
12058 rd = 16;
12059 break;
12060 case 0xb: /* cmn */
12061 gen_add_CC(tmp, tmp, tmp2);
12062 rd = 16;
12063 break;
12064 case 0xc: /* orr */
12065 tcg_gen_or_i32(tmp, tmp, tmp2);
12066 if (!s->condexec_mask)
12067 gen_logic_CC(tmp);
12068 break;
12069 case 0xd: /* mul */
12070 tcg_gen_mul_i32(tmp, tmp, tmp2);
12071 if (!s->condexec_mask)
12072 gen_logic_CC(tmp);
12073 break;
12074 case 0xe: /* bic */
12075 tcg_gen_andc_i32(tmp, tmp, tmp2);
12076 if (!s->condexec_mask)
12077 gen_logic_CC(tmp);
12078 break;
12079 case 0xf: /* mvn */
12080 tcg_gen_not_i32(tmp2, tmp2);
12081 if (!s->condexec_mask)
12082 gen_logic_CC(tmp2);
12083 val = 1;
12084 rm = rd;
12085 break;
12087 if (rd != 16) {
12088 if (val) {
12089 store_reg(s, rm, tmp2);
12090 if (op != 0xf)
12091 tcg_temp_free_i32(tmp);
12092 } else {
12093 store_reg(s, rd, tmp);
12094 tcg_temp_free_i32(tmp2);
12096 } else {
12097 tcg_temp_free_i32(tmp);
12098 tcg_temp_free_i32(tmp2);
12100 break;
12102 case 5:
12103 /* load/store register offset. */
12104 rd = insn & 7;
12105 rn = (insn >> 3) & 7;
12106 rm = (insn >> 6) & 7;
12107 op = (insn >> 9) & 7;
12108 addr = load_reg(s, rn);
12109 tmp = load_reg(s, rm);
12110 tcg_gen_add_i32(addr, addr, tmp);
12111 tcg_temp_free_i32(tmp);
12113 if (op < 3) { /* store */
12114 tmp = load_reg(s, rd);
12115 } else {
12116 tmp = tcg_temp_new_i32();
12119 switch (op) {
12120 case 0: /* str */
12121 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12122 break;
12123 case 1: /* strh */
12124 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12125 break;
12126 case 2: /* strb */
12127 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12128 break;
12129 case 3: /* ldrsb */
12130 gen_aa32_ld8s_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12131 break;
12132 case 4: /* ldr */
12133 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12134 break;
12135 case 5: /* ldrh */
12136 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12137 break;
12138 case 6: /* ldrb */
12139 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12140 break;
12141 case 7: /* ldrsh */
12142 gen_aa32_ld16s_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12143 break;
12145 if (op >= 3) { /* load */
12146 store_reg(s, rd, tmp);
12147 } else {
12148 tcg_temp_free_i32(tmp);
12150 tcg_temp_free_i32(addr);
12151 break;
12153 case 6:
12154 /* load/store word immediate offset */
12155 rd = insn & 7;
12156 rn = (insn >> 3) & 7;
12157 addr = load_reg(s, rn);
12158 val = (insn >> 4) & 0x7c;
12159 tcg_gen_addi_i32(addr, addr, val);
12161 if (insn & (1 << 11)) {
12162 /* load */
12163 tmp = tcg_temp_new_i32();
12164 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
12165 store_reg(s, rd, tmp);
12166 } else {
12167 /* store */
12168 tmp = load_reg(s, rd);
12169 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
12170 tcg_temp_free_i32(tmp);
12172 tcg_temp_free_i32(addr);
12173 break;
12175 case 7:
12176 /* load/store byte immediate offset */
12177 rd = insn & 7;
12178 rn = (insn >> 3) & 7;
12179 addr = load_reg(s, rn);
12180 val = (insn >> 6) & 0x1f;
12181 tcg_gen_addi_i32(addr, addr, val);
12183 if (insn & (1 << 11)) {
12184 /* load */
12185 tmp = tcg_temp_new_i32();
12186 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12187 store_reg(s, rd, tmp);
12188 } else {
12189 /* store */
12190 tmp = load_reg(s, rd);
12191 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12192 tcg_temp_free_i32(tmp);
12194 tcg_temp_free_i32(addr);
12195 break;
12197 case 8:
12198 /* load/store halfword immediate offset */
12199 rd = insn & 7;
12200 rn = (insn >> 3) & 7;
12201 addr = load_reg(s, rn);
12202 val = (insn >> 5) & 0x3e;
12203 tcg_gen_addi_i32(addr, addr, val);
12205 if (insn & (1 << 11)) {
12206 /* load */
12207 tmp = tcg_temp_new_i32();
12208 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12209 store_reg(s, rd, tmp);
12210 } else {
12211 /* store */
12212 tmp = load_reg(s, rd);
12213 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12214 tcg_temp_free_i32(tmp);
12216 tcg_temp_free_i32(addr);
12217 break;
12219 case 9:
12220 /* load/store from stack */
12221 rd = (insn >> 8) & 7;
12222 addr = load_reg(s, 13);
12223 val = (insn & 0xff) * 4;
12224 tcg_gen_addi_i32(addr, addr, val);
12226 if (insn & (1 << 11)) {
12227 /* load */
12228 tmp = tcg_temp_new_i32();
12229 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12230 store_reg(s, rd, tmp);
12231 } else {
12232 /* store */
12233 tmp = load_reg(s, rd);
12234 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12235 tcg_temp_free_i32(tmp);
12237 tcg_temp_free_i32(addr);
12238 break;
12240 case 10:
12242 * 0b1010_xxxx_xxxx_xxxx
12243 * - Add PC/SP (immediate)
12245 rd = (insn >> 8) & 7;
12246 if (insn & (1 << 11)) {
12247 /* SP */
12248 tmp = load_reg(s, 13);
12249 } else {
12250 /* PC. bit 1 is ignored. */
12251 tmp = tcg_temp_new_i32();
12252 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
12254 val = (insn & 0xff) * 4;
12255 tcg_gen_addi_i32(tmp, tmp, val);
12256 store_reg(s, rd, tmp);
12257 break;
12259 case 11:
12260 /* misc */
12261 op = (insn >> 8) & 0xf;
12262 switch (op) {
12263 case 0:
12265 * 0b1011_0000_xxxx_xxxx
12266 * - ADD (SP plus immediate)
12267 * - SUB (SP minus immediate)
12269 tmp = load_reg(s, 13);
12270 val = (insn & 0x7f) * 4;
12271 if (insn & (1 << 7))
12272 val = -(int32_t)val;
12273 tcg_gen_addi_i32(tmp, tmp, val);
12274 store_sp_checked(s, tmp);
12275 break;
12277 case 2: /* sign/zero extend. */
12278 ARCH(6);
12279 rd = insn & 7;
12280 rm = (insn >> 3) & 7;
12281 tmp = load_reg(s, rm);
12282 switch ((insn >> 6) & 3) {
12283 case 0: gen_sxth(tmp); break;
12284 case 1: gen_sxtb(tmp); break;
12285 case 2: gen_uxth(tmp); break;
12286 case 3: gen_uxtb(tmp); break;
12288 store_reg(s, rd, tmp);
12289 break;
12290 case 4: case 5: case 0xc: case 0xd:
12292 * 0b1011_x10x_xxxx_xxxx
12293 * - push/pop
12295 addr = load_reg(s, 13);
12296 if (insn & (1 << 8))
12297 offset = 4;
12298 else
12299 offset = 0;
12300 for (i = 0; i < 8; i++) {
12301 if (insn & (1 << i))
12302 offset += 4;
12304 if ((insn & (1 << 11)) == 0) {
12305 tcg_gen_addi_i32(addr, addr, -offset);
12308 if (s->v8m_stackcheck) {
12310 * Here 'addr' is the lower of "old SP" and "new SP";
12311 * if this is a pop that starts below the limit and ends
12312 * above it, it is UNKNOWN whether the limit check triggers;
12313 * we choose to trigger.
12315 gen_helper_v8m_stackcheck(cpu_env, addr);
12318 for (i = 0; i < 8; i++) {
12319 if (insn & (1 << i)) {
12320 if (insn & (1 << 11)) {
12321 /* pop */
12322 tmp = tcg_temp_new_i32();
12323 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
12324 store_reg(s, i, tmp);
12325 } else {
12326 /* push */
12327 tmp = load_reg(s, i);
12328 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
12329 tcg_temp_free_i32(tmp);
12331 /* advance to the next address. */
12332 tcg_gen_addi_i32(addr, addr, 4);
12335 tmp = NULL;
12336 if (insn & (1 << 8)) {
12337 if (insn & (1 << 11)) {
12338 /* pop pc */
12339 tmp = tcg_temp_new_i32();
12340 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
12341 /* don't set the pc until the rest of the instruction
12342 has completed */
12343 } else {
12344 /* push lr */
12345 tmp = load_reg(s, 14);
12346 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
12347 tcg_temp_free_i32(tmp);
12349 tcg_gen_addi_i32(addr, addr, 4);
12351 if ((insn & (1 << 11)) == 0) {
12352 tcg_gen_addi_i32(addr, addr, -offset);
12354 /* write back the new stack pointer */
12355 store_reg(s, 13, addr);
12356 /* set the new PC value */
12357 if ((insn & 0x0900) == 0x0900) {
12358 store_reg_from_load(s, 15, tmp);
12360 break;
12362 case 1: case 3: case 9: case 11: /* czb */
12363 rm = insn & 7;
12364 tmp = load_reg(s, rm);
12365 arm_gen_condlabel(s);
12366 if (insn & (1 << 11))
12367 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
12368 else
12369 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
12370 tcg_temp_free_i32(tmp);
12371 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
12372 val = (uint32_t)s->pc + 2;
12373 val += offset;
12374 gen_jmp(s, val);
12375 break;
12377 case 15: /* IT, nop-hint. */
12378 if ((insn & 0xf) == 0) {
12379 gen_nop_hint(s, (insn >> 4) & 0xf);
12380 break;
12382 /* If Then. */
12383 s->condexec_cond = (insn >> 4) & 0xe;
12384 s->condexec_mask = insn & 0x1f;
12385 /* No actual code generated for this insn, just setup state. */
12386 break;
12388 case 0xe: /* bkpt */
12390 int imm8 = extract32(insn, 0, 8);
12391 ARCH(5);
12392 gen_exception_bkpt_insn(s, 2, syn_aa32_bkpt(imm8, true));
12393 break;
12396 case 0xa: /* rev, and hlt */
12398 int op1 = extract32(insn, 6, 2);
12400 if (op1 == 2) {
12401 /* HLT */
12402 int imm6 = extract32(insn, 0, 6);
12404 gen_hlt(s, imm6);
12405 break;
12408 /* Otherwise this is rev */
12409 ARCH(6);
12410 rn = (insn >> 3) & 0x7;
12411 rd = insn & 0x7;
12412 tmp = load_reg(s, rn);
12413 switch (op1) {
12414 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
12415 case 1: gen_rev16(tmp); break;
12416 case 3: gen_revsh(tmp); break;
12417 default:
12418 g_assert_not_reached();
12420 store_reg(s, rd, tmp);
12421 break;
12424 case 6:
12425 switch ((insn >> 5) & 7) {
12426 case 2:
12427 /* setend */
12428 ARCH(6);
12429 if (((insn >> 3) & 1) != !!(s->be_data == MO_BE)) {
12430 gen_helper_setend(cpu_env);
12431 s->base.is_jmp = DISAS_UPDATE;
12433 break;
12434 case 3:
12435 /* cps */
12436 ARCH(6);
12437 if (IS_USER(s)) {
12438 break;
12440 if (arm_dc_feature(s, ARM_FEATURE_M)) {
12441 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
12442 /* FAULTMASK */
12443 if (insn & 1) {
12444 addr = tcg_const_i32(19);
12445 gen_helper_v7m_msr(cpu_env, addr, tmp);
12446 tcg_temp_free_i32(addr);
12448 /* PRIMASK */
12449 if (insn & 2) {
12450 addr = tcg_const_i32(16);
12451 gen_helper_v7m_msr(cpu_env, addr, tmp);
12452 tcg_temp_free_i32(addr);
12454 tcg_temp_free_i32(tmp);
12455 gen_lookup_tb(s);
12456 } else {
12457 if (insn & (1 << 4)) {
12458 shift = CPSR_A | CPSR_I | CPSR_F;
12459 } else {
12460 shift = 0;
12462 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
12464 break;
12465 default:
12466 goto undef;
12468 break;
12470 default:
12471 goto undef;
12473 break;
12475 case 12:
12477 /* load/store multiple */
12478 TCGv_i32 loaded_var = NULL;
12479 rn = (insn >> 8) & 0x7;
12480 addr = load_reg(s, rn);
12481 for (i = 0; i < 8; i++) {
12482 if (insn & (1 << i)) {
12483 if (insn & (1 << 11)) {
12484 /* load */
12485 tmp = tcg_temp_new_i32();
12486 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
12487 if (i == rn) {
12488 loaded_var = tmp;
12489 } else {
12490 store_reg(s, i, tmp);
12492 } else {
12493 /* store */
12494 tmp = load_reg(s, i);
12495 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
12496 tcg_temp_free_i32(tmp);
12498 /* advance to the next address */
12499 tcg_gen_addi_i32(addr, addr, 4);
12502 if ((insn & (1 << rn)) == 0) {
12503 /* base reg not in list: base register writeback */
12504 store_reg(s, rn, addr);
12505 } else {
12506 /* base reg in list: if load, complete it now */
12507 if (insn & (1 << 11)) {
12508 store_reg(s, rn, loaded_var);
12510 tcg_temp_free_i32(addr);
12512 break;
12514 case 13:
12515 /* conditional branch or swi */
12516 cond = (insn >> 8) & 0xf;
12517 if (cond == 0xe)
12518 goto undef;
12520 if (cond == 0xf) {
12521 /* swi */
12522 gen_set_pc_im(s, s->pc);
12523 s->svc_imm = extract32(insn, 0, 8);
12524 s->base.is_jmp = DISAS_SWI;
12525 break;
12527 /* generate a conditional jump to next instruction */
12528 arm_skip_unless(s, cond);
12530 /* jump to the offset */
12531 val = (uint32_t)s->pc + 2;
12532 offset = ((int32_t)insn << 24) >> 24;
12533 val += offset << 1;
12534 gen_jmp(s, val);
12535 break;
12537 case 14:
12538 if (insn & (1 << 11)) {
12539 /* thumb_insn_is_16bit() ensures we can't get here for
12540 * a Thumb2 CPU, so this must be a thumb1 split BL/BLX:
12541 * 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF)
12543 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
12544 ARCH(5);
12545 offset = ((insn & 0x7ff) << 1);
12546 tmp = load_reg(s, 14);
12547 tcg_gen_addi_i32(tmp, tmp, offset);
12548 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
12550 tmp2 = tcg_temp_new_i32();
12551 tcg_gen_movi_i32(tmp2, s->pc | 1);
12552 store_reg(s, 14, tmp2);
12553 gen_bx(s, tmp);
12554 break;
12556 /* unconditional branch */
12557 val = (uint32_t)s->pc;
12558 offset = ((int32_t)insn << 21) >> 21;
12559 val += (offset << 1) + 2;
12560 gen_jmp(s, val);
12561 break;
12563 case 15:
12564 /* thumb_insn_is_16bit() ensures we can't get here for
12565 * a Thumb2 CPU, so this must be a thumb1 split BL/BLX.
12567 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
12569 if (insn & (1 << 11)) {
12570 /* 0b1111_1xxx_xxxx_xxxx : BL suffix */
12571 offset = ((insn & 0x7ff) << 1) | 1;
12572 tmp = load_reg(s, 14);
12573 tcg_gen_addi_i32(tmp, tmp, offset);
12575 tmp2 = tcg_temp_new_i32();
12576 tcg_gen_movi_i32(tmp2, s->pc | 1);
12577 store_reg(s, 14, tmp2);
12578 gen_bx(s, tmp);
12579 } else {
12580 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix */
12581 uint32_t uoffset = ((int32_t)insn << 21) >> 9;
12583 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + uoffset);
12585 break;
12587 return;
12588 illegal_op:
12589 undef:
12590 gen_exception_insn(s, 2, EXCP_UDEF, syn_uncategorized(),
12591 default_exception_el(s));
12594 static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
12596 /* Return true if the insn at dc->pc might cross a page boundary.
12597 * (False positives are OK, false negatives are not.)
12598 * We know this is a Thumb insn, and our caller ensures we are
12599 * only called if dc->pc is less than 4 bytes from the page
12600 * boundary, so we cross the page if the first 16 bits indicate
12601 * that this is a 32 bit insn.
12603 uint16_t insn = arm_lduw_code(env, s->pc, s->sctlr_b);
12605 return !thumb_insn_is_16bit(s, insn);
12608 static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
12610 DisasContext *dc = container_of(dcbase, DisasContext, base);
12611 CPUARMState *env = cs->env_ptr;
12612 ARMCPU *cpu = env_archcpu(env);
12613 uint32_t tb_flags = dc->base.tb->flags;
12614 uint32_t condexec, core_mmu_idx;
12616 dc->isar = &cpu->isar;
12617 dc->pc = dc->base.pc_first;
12618 dc->condjmp = 0;
12620 dc->aarch64 = 0;
12621 /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
12622 * there is no secure EL1, so we route exceptions to EL3.
12624 dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
12625 !arm_el_is_aa64(env, 3);
12626 dc->thumb = FIELD_EX32(tb_flags, TBFLAG_A32, THUMB);
12627 dc->sctlr_b = FIELD_EX32(tb_flags, TBFLAG_A32, SCTLR_B);
12628 dc->be_data = FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
12629 condexec = FIELD_EX32(tb_flags, TBFLAG_A32, CONDEXEC);
12630 dc->condexec_mask = (condexec & 0xf) << 1;
12631 dc->condexec_cond = condexec >> 4;
12632 core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX);
12633 dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
12634 dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
12635 #if !defined(CONFIG_USER_ONLY)
12636 dc->user = (dc->current_el == 0);
12637 #endif
12638 dc->ns = FIELD_EX32(tb_flags, TBFLAG_A32, NS);
12639 dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL);
12640 dc->vfp_enabled = FIELD_EX32(tb_flags, TBFLAG_A32, VFPEN);
12641 dc->vec_len = FIELD_EX32(tb_flags, TBFLAG_A32, VECLEN);
12642 if (arm_feature(env, ARM_FEATURE_XSCALE)) {
12643 dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
12644 dc->vec_stride = 0;
12645 } else {
12646 dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
12647 dc->c15_cpar = 0;
12649 dc->v7m_handler_mode = FIELD_EX32(tb_flags, TBFLAG_A32, HANDLER);
12650 dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
12651 regime_is_secure(env, dc->mmu_idx);
12652 dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_A32, STACKCHECK);
12653 dc->v8m_fpccr_s_wrong = FIELD_EX32(tb_flags, TBFLAG_A32, FPCCR_S_WRONG);
12654 dc->v7m_new_fp_ctxt_needed =
12655 FIELD_EX32(tb_flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED);
12656 dc->v7m_lspact = FIELD_EX32(tb_flags, TBFLAG_A32, LSPACT);
12657 dc->cp_regs = cpu->cp_regs;
12658 dc->features = env->features;
12660 /* Single step state. The code-generation logic here is:
12661 * SS_ACTIVE == 0:
12662 * generate code with no special handling for single-stepping (except
12663 * that anything that can make us go to SS_ACTIVE == 1 must end the TB;
12664 * this happens anyway because those changes are all system register or
12665 * PSTATE writes).
12666 * SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
12667 * emit code for one insn
12668 * emit code to clear PSTATE.SS
12669 * emit code to generate software step exception for completed step
12670 * end TB (as usual for having generated an exception)
12671 * SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
12672 * emit code to generate a software step exception
12673 * end the TB
12675 dc->ss_active = FIELD_EX32(tb_flags, TBFLAG_ANY, SS_ACTIVE);
12676 dc->pstate_ss = FIELD_EX32(tb_flags, TBFLAG_ANY, PSTATE_SS);
12677 dc->is_ldex = false;
12678 dc->ss_same_el = false; /* Can't be true since EL_d must be AArch64 */
12680 dc->page_start = dc->base.pc_first & TARGET_PAGE_MASK;
12682 /* If architectural single step active, limit to 1. */
12683 if (is_singlestepping(dc)) {
12684 dc->base.max_insns = 1;
12687 /* ARM is a fixed-length ISA. Bound the number of insns to execute
12688 to those left on the page. */
12689 if (!dc->thumb) {
12690 int bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
12691 dc->base.max_insns = MIN(dc->base.max_insns, bound);
12694 cpu_F0s = tcg_temp_new_i32();
12695 cpu_F1s = tcg_temp_new_i32();
12696 cpu_F0d = tcg_temp_new_i64();
12697 cpu_F1d = tcg_temp_new_i64();
12698 cpu_V0 = cpu_F0d;
12699 cpu_V1 = cpu_F1d;
12700 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
12701 cpu_M0 = tcg_temp_new_i64();
12704 static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
12706 DisasContext *dc = container_of(dcbase, DisasContext, base);
12708 /* A note on handling of the condexec (IT) bits:
12710 * We want to avoid the overhead of having to write the updated condexec
12711 * bits back to the CPUARMState for every instruction in an IT block. So:
12712 * (1) if the condexec bits are not already zero then we write
12713 * zero back into the CPUARMState now. This avoids complications trying
12714 * to do it at the end of the block. (For example if we don't do this
12715 * it's hard to identify whether we can safely skip writing condexec
12716 * at the end of the TB, which we definitely want to do for the case
12717 * where a TB doesn't do anything with the IT state at all.)
12718 * (2) if we are going to leave the TB then we call gen_set_condexec()
12719 * which will write the correct value into CPUARMState if zero is wrong.
12720 * This is done both for leaving the TB at the end, and for leaving
12721 * it because of an exception we know will happen, which is done in
12722 * gen_exception_insn(). The latter is necessary because we need to
12723 * leave the TB with the PC/IT state just prior to execution of the
12724 * instruction which caused the exception.
12725 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
12726 * then the CPUARMState will be wrong and we need to reset it.
12727 * This is handled in the same way as restoration of the
12728 * PC in these situations; we save the value of the condexec bits
12729 * for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
12730 * then uses this to restore them after an exception.
12732 * Note that there are no instructions which can read the condexec
12733 * bits, and none which can write non-static values to them, so
12734 * we don't need to care about whether CPUARMState is correct in the
12735 * middle of a TB.
12738 /* Reset the conditional execution bits immediately. This avoids
12739 complications trying to do it at the end of the block. */
12740 if (dc->condexec_mask || dc->condexec_cond) {
12741 TCGv_i32 tmp = tcg_temp_new_i32();
12742 tcg_gen_movi_i32(tmp, 0);
12743 store_cpu_field(tmp, condexec_bits);
12747 static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
12749 DisasContext *dc = container_of(dcbase, DisasContext, base);
12751 tcg_gen_insn_start(dc->pc,
12752 (dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
12754 dc->insn_start = tcg_last_op();
12757 static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
12758 const CPUBreakpoint *bp)
12760 DisasContext *dc = container_of(dcbase, DisasContext, base);
12762 if (bp->flags & BP_CPU) {
12763 gen_set_condexec(dc);
12764 gen_set_pc_im(dc, dc->pc);
12765 gen_helper_check_breakpoints(cpu_env);
12766 /* End the TB early; it's likely not going to be executed */
12767 dc->base.is_jmp = DISAS_TOO_MANY;
12768 } else {
12769 gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
12770 /* The address covered by the breakpoint must be
12771 included in [tb->pc, tb->pc + tb->size) in order
12772 to for it to be properly cleared -- thus we
12773 increment the PC here so that the logic setting
12774 tb->size below does the right thing. */
12775 /* TODO: Advance PC by correct instruction length to
12776 * avoid disassembler error messages */
12777 dc->pc += 2;
12778 dc->base.is_jmp = DISAS_NORETURN;
12781 return true;
12784 static bool arm_pre_translate_insn(DisasContext *dc)
12786 #ifdef CONFIG_USER_ONLY
12787 /* Intercept jump to the magic kernel page. */
12788 if (dc->pc >= 0xffff0000) {
12789 /* We always get here via a jump, so know we are not in a
12790 conditional execution block. */
12791 gen_exception_internal(EXCP_KERNEL_TRAP);
12792 dc->base.is_jmp = DISAS_NORETURN;
12793 return true;
12795 #endif
12797 if (dc->ss_active && !dc->pstate_ss) {
12798 /* Singlestep state is Active-pending.
12799 * If we're in this state at the start of a TB then either
12800 * a) we just took an exception to an EL which is being debugged
12801 * and this is the first insn in the exception handler
12802 * b) debug exceptions were masked and we just unmasked them
12803 * without changing EL (eg by clearing PSTATE.D)
12804 * In either case we're going to take a swstep exception in the
12805 * "did not step an insn" case, and so the syndrome ISV and EX
12806 * bits should be zero.
12808 assert(dc->base.num_insns == 1);
12809 gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
12810 default_exception_el(dc));
12811 dc->base.is_jmp = DISAS_NORETURN;
12812 return true;
12815 return false;
12818 static void arm_post_translate_insn(DisasContext *dc)
12820 if (dc->condjmp && !dc->base.is_jmp) {
12821 gen_set_label(dc->condlabel);
12822 dc->condjmp = 0;
12824 dc->base.pc_next = dc->pc;
12825 translator_loop_temp_check(&dc->base);
12828 static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
12830 DisasContext *dc = container_of(dcbase, DisasContext, base);
12831 CPUARMState *env = cpu->env_ptr;
12832 unsigned int insn;
12834 if (arm_pre_translate_insn(dc)) {
12835 return;
12838 insn = arm_ldl_code(env, dc->pc, dc->sctlr_b);
12839 dc->insn = insn;
12840 dc->pc += 4;
12841 disas_arm_insn(dc, insn);
12843 arm_post_translate_insn(dc);
12845 /* ARM is a fixed-length ISA. We performed the cross-page check
12846 in init_disas_context by adjusting max_insns. */
12849 static bool thumb_insn_is_unconditional(DisasContext *s, uint32_t insn)
12851 /* Return true if this Thumb insn is always unconditional,
12852 * even inside an IT block. This is true of only a very few
12853 * instructions: BKPT, HLT, and SG.
12855 * A larger class of instructions are UNPREDICTABLE if used
12856 * inside an IT block; we do not need to detect those here, because
12857 * what we do by default (perform the cc check and update the IT
12858 * bits state machine) is a permitted CONSTRAINED UNPREDICTABLE
12859 * choice for those situations.
12861 * insn is either a 16-bit or a 32-bit instruction; the two are
12862 * distinguishable because for the 16-bit case the top 16 bits
12863 * are zeroes, and that isn't a valid 32-bit encoding.
12865 if ((insn & 0xffffff00) == 0xbe00) {
12866 /* BKPT */
12867 return true;
12870 if ((insn & 0xffffffc0) == 0xba80 && arm_dc_feature(s, ARM_FEATURE_V8) &&
12871 !arm_dc_feature(s, ARM_FEATURE_M)) {
12872 /* HLT: v8A only. This is unconditional even when it is going to
12873 * UNDEF; see the v8A ARM ARM DDI0487B.a H3.3.
12874 * For v7 cores this was a plain old undefined encoding and so
12875 * honours its cc check. (We might be using the encoding as
12876 * a semihosting trap, but we don't change the cc check behaviour
12877 * on that account, because a debugger connected to a real v7A
12878 * core and emulating semihosting traps by catching the UNDEF
12879 * exception would also only see cases where the cc check passed.
12880 * No guest code should be trying to do a HLT semihosting trap
12881 * in an IT block anyway.
12883 return true;
12886 if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_V8) &&
12887 arm_dc_feature(s, ARM_FEATURE_M)) {
12888 /* SG: v8M only */
12889 return true;
12892 return false;
12895 static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
12897 DisasContext *dc = container_of(dcbase, DisasContext, base);
12898 CPUARMState *env = cpu->env_ptr;
12899 uint32_t insn;
12900 bool is_16bit;
12902 if (arm_pre_translate_insn(dc)) {
12903 return;
12906 insn = arm_lduw_code(env, dc->pc, dc->sctlr_b);
12907 is_16bit = thumb_insn_is_16bit(dc, insn);
12908 dc->pc += 2;
12909 if (!is_16bit) {
12910 uint32_t insn2 = arm_lduw_code(env, dc->pc, dc->sctlr_b);
12912 insn = insn << 16 | insn2;
12913 dc->pc += 2;
12915 dc->insn = insn;
12917 if (dc->condexec_mask && !thumb_insn_is_unconditional(dc, insn)) {
12918 uint32_t cond = dc->condexec_cond;
12920 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
12921 arm_skip_unless(dc, cond);
12925 if (is_16bit) {
12926 disas_thumb_insn(dc, insn);
12927 } else {
12928 disas_thumb2_insn(dc, insn);
12931 /* Advance the Thumb condexec condition. */
12932 if (dc->condexec_mask) {
12933 dc->condexec_cond = ((dc->condexec_cond & 0xe) |
12934 ((dc->condexec_mask >> 4) & 1));
12935 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
12936 if (dc->condexec_mask == 0) {
12937 dc->condexec_cond = 0;
12941 arm_post_translate_insn(dc);
12943 /* Thumb is a variable-length ISA. Stop translation when the next insn
12944 * will touch a new page. This ensures that prefetch aborts occur at
12945 * the right place.
12947 * We want to stop the TB if the next insn starts in a new page,
12948 * or if it spans between this page and the next. This means that
12949 * if we're looking at the last halfword in the page we need to
12950 * see if it's a 16-bit Thumb insn (which will fit in this TB)
12951 * or a 32-bit Thumb insn (which won't).
12952 * This is to avoid generating a silly TB with a single 16-bit insn
12953 * in it at the end of this page (which would execute correctly
12954 * but isn't very efficient).
12956 if (dc->base.is_jmp == DISAS_NEXT
12957 && (dc->pc - dc->page_start >= TARGET_PAGE_SIZE
12958 || (dc->pc - dc->page_start >= TARGET_PAGE_SIZE - 3
12959 && insn_crosses_page(env, dc)))) {
12960 dc->base.is_jmp = DISAS_TOO_MANY;
12964 static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
12966 DisasContext *dc = container_of(dcbase, DisasContext, base);
12968 if (tb_cflags(dc->base.tb) & CF_LAST_IO && dc->condjmp) {
12969 /* FIXME: This can theoretically happen with self-modifying code. */
12970 cpu_abort(cpu, "IO on conditional branch instruction");
12973 /* At this stage dc->condjmp will only be set when the skipped
12974 instruction was a conditional branch or trap, and the PC has
12975 already been written. */
12976 gen_set_condexec(dc);
12977 if (dc->base.is_jmp == DISAS_BX_EXCRET) {
12978 /* Exception return branches need some special case code at the
12979 * end of the TB, which is complex enough that it has to
12980 * handle the single-step vs not and the condition-failed
12981 * insn codepath itself.
12983 gen_bx_excret_final_code(dc);
12984 } else if (unlikely(is_singlestepping(dc))) {
12985 /* Unconditional and "condition passed" instruction codepath. */
12986 switch (dc->base.is_jmp) {
12987 case DISAS_SWI:
12988 gen_ss_advance(dc);
12989 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
12990 default_exception_el(dc));
12991 break;
12992 case DISAS_HVC:
12993 gen_ss_advance(dc);
12994 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
12995 break;
12996 case DISAS_SMC:
12997 gen_ss_advance(dc);
12998 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
12999 break;
13000 case DISAS_NEXT:
13001 case DISAS_TOO_MANY:
13002 case DISAS_UPDATE:
13003 gen_set_pc_im(dc, dc->pc);
13004 /* fall through */
13005 default:
13006 /* FIXME: Single stepping a WFI insn will not halt the CPU. */
13007 gen_singlestep_exception(dc);
13008 break;
13009 case DISAS_NORETURN:
13010 break;
13012 } else {
13013 /* While branches must always occur at the end of an IT block,
13014 there are a few other things that can cause us to terminate
13015 the TB in the middle of an IT block:
13016 - Exception generating instructions (bkpt, swi, undefined).
13017 - Page boundaries.
13018 - Hardware watchpoints.
13019 Hardware breakpoints have already been handled and skip this code.
13021 switch(dc->base.is_jmp) {
13022 case DISAS_NEXT:
13023 case DISAS_TOO_MANY:
13024 gen_goto_tb(dc, 1, dc->pc);
13025 break;
13026 case DISAS_JUMP:
13027 gen_goto_ptr();
13028 break;
13029 case DISAS_UPDATE:
13030 gen_set_pc_im(dc, dc->pc);
13031 /* fall through */
13032 default:
13033 /* indicate that the hash table must be used to find the next TB */
13034 tcg_gen_exit_tb(NULL, 0);
13035 break;
13036 case DISAS_NORETURN:
13037 /* nothing more to generate */
13038 break;
13039 case DISAS_WFI:
13041 TCGv_i32 tmp = tcg_const_i32((dc->thumb &&
13042 !(dc->insn & (1U << 31))) ? 2 : 4);
13044 gen_helper_wfi(cpu_env, tmp);
13045 tcg_temp_free_i32(tmp);
13046 /* The helper doesn't necessarily throw an exception, but we
13047 * must go back to the main loop to check for interrupts anyway.
13049 tcg_gen_exit_tb(NULL, 0);
13050 break;
13052 case DISAS_WFE:
13053 gen_helper_wfe(cpu_env);
13054 break;
13055 case DISAS_YIELD:
13056 gen_helper_yield(cpu_env);
13057 break;
13058 case DISAS_SWI:
13059 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
13060 default_exception_el(dc));
13061 break;
13062 case DISAS_HVC:
13063 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
13064 break;
13065 case DISAS_SMC:
13066 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
13067 break;
13071 if (dc->condjmp) {
13072 /* "Condition failed" instruction codepath for the branch/trap insn */
13073 gen_set_label(dc->condlabel);
13074 gen_set_condexec(dc);
13075 if (unlikely(is_singlestepping(dc))) {
13076 gen_set_pc_im(dc, dc->pc);
13077 gen_singlestep_exception(dc);
13078 } else {
13079 gen_goto_tb(dc, 1, dc->pc);
13083 /* Functions above can change dc->pc, so re-align db->pc_next */
13084 dc->base.pc_next = dc->pc;
13087 static void arm_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
13089 DisasContext *dc = container_of(dcbase, DisasContext, base);
13091 qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
13092 log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
13095 static const TranslatorOps arm_translator_ops = {
13096 .init_disas_context = arm_tr_init_disas_context,
13097 .tb_start = arm_tr_tb_start,
13098 .insn_start = arm_tr_insn_start,
13099 .breakpoint_check = arm_tr_breakpoint_check,
13100 .translate_insn = arm_tr_translate_insn,
13101 .tb_stop = arm_tr_tb_stop,
13102 .disas_log = arm_tr_disas_log,
13105 static const TranslatorOps thumb_translator_ops = {
13106 .init_disas_context = arm_tr_init_disas_context,
13107 .tb_start = arm_tr_tb_start,
13108 .insn_start = arm_tr_insn_start,
13109 .breakpoint_check = arm_tr_breakpoint_check,
13110 .translate_insn = thumb_tr_translate_insn,
13111 .tb_stop = arm_tr_tb_stop,
13112 .disas_log = arm_tr_disas_log,
13115 /* generate intermediate code for basic block 'tb'. */
13116 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
13118 DisasContext dc;
13119 const TranslatorOps *ops = &arm_translator_ops;
13121 if (FIELD_EX32(tb->flags, TBFLAG_A32, THUMB)) {
13122 ops = &thumb_translator_ops;
13124 #ifdef TARGET_AARCH64
13125 if (FIELD_EX32(tb->flags, TBFLAG_ANY, AARCH64_STATE)) {
13126 ops = &aarch64_translator_ops;
13128 #endif
13130 translator_loop(ops, &dc.base, cpu, tb, max_insns);
13133 void arm_cpu_dump_state(CPUState *cs, FILE *f, int flags)
13135 ARMCPU *cpu = ARM_CPU(cs);
13136 CPUARMState *env = &cpu->env;
13137 int i;
13139 if (is_a64(env)) {
13140 aarch64_cpu_dump_state(cs, f, flags);
13141 return;
13144 for(i=0;i<16;i++) {
13145 qemu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
13146 if ((i % 4) == 3)
13147 qemu_fprintf(f, "\n");
13148 else
13149 qemu_fprintf(f, " ");
13152 if (arm_feature(env, ARM_FEATURE_M)) {
13153 uint32_t xpsr = xpsr_read(env);
13154 const char *mode;
13155 const char *ns_status = "";
13157 if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
13158 ns_status = env->v7m.secure ? "S " : "NS ";
13161 if (xpsr & XPSR_EXCP) {
13162 mode = "handler";
13163 } else {
13164 if (env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_NPRIV_MASK) {
13165 mode = "unpriv-thread";
13166 } else {
13167 mode = "priv-thread";
13171 qemu_fprintf(f, "XPSR=%08x %c%c%c%c %c %s%s\n",
13172 xpsr,
13173 xpsr & XPSR_N ? 'N' : '-',
13174 xpsr & XPSR_Z ? 'Z' : '-',
13175 xpsr & XPSR_C ? 'C' : '-',
13176 xpsr & XPSR_V ? 'V' : '-',
13177 xpsr & XPSR_T ? 'T' : 'A',
13178 ns_status,
13179 mode);
13180 } else {
13181 uint32_t psr = cpsr_read(env);
13182 const char *ns_status = "";
13184 if (arm_feature(env, ARM_FEATURE_EL3) &&
13185 (psr & CPSR_M) != ARM_CPU_MODE_MON) {
13186 ns_status = env->cp15.scr_el3 & SCR_NS ? "NS " : "S ";
13189 qemu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%s%d\n",
13190 psr,
13191 psr & CPSR_N ? 'N' : '-',
13192 psr & CPSR_Z ? 'Z' : '-',
13193 psr & CPSR_C ? 'C' : '-',
13194 psr & CPSR_V ? 'V' : '-',
13195 psr & CPSR_T ? 'T' : 'A',
13196 ns_status,
13197 aarch32_mode_name(psr), (psr & 0x10) ? 32 : 26);
13200 if (flags & CPU_DUMP_FPU) {
13201 int numvfpregs = 0;
13202 if (arm_feature(env, ARM_FEATURE_VFP)) {
13203 numvfpregs += 16;
13205 if (arm_feature(env, ARM_FEATURE_VFP3)) {
13206 numvfpregs += 16;
13208 for (i = 0; i < numvfpregs; i++) {
13209 uint64_t v = *aa32_vfp_dreg(env, i);
13210 qemu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
13211 i * 2, (uint32_t)v,
13212 i * 2 + 1, (uint32_t)(v >> 32),
13213 i, v);
13215 qemu_fprintf(f, "FPSCR: %08x\n", vfp_get_fpscr(env));
13219 void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
13220 target_ulong *data)
13222 if (is_a64(env)) {
13223 env->pc = data[0];
13224 env->condexec_bits = 0;
13225 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
13226 } else {
13227 env->regs[15] = data[0];
13228 env->condexec_bits = data[1];
13229 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;