ui/cocoa: Subclass NSApplication so we can implement sendEvent
[qemu/ar7.git] / target / arm / translate.c
blob8f7f5b95aabb5c1f37241839d038bd50df3ee893
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 "arm_ldst.h"
32 #include "exec/semihost.h"
34 #include "exec/helper-proto.h"
35 #include "exec/helper-gen.h"
37 #include "trace-tcg.h"
38 #include "exec/log.h"
41 #define ENABLE_ARCH_4T arm_dc_feature(s, ARM_FEATURE_V4T)
42 #define ENABLE_ARCH_5 arm_dc_feature(s, ARM_FEATURE_V5)
43 /* currently all emulated v5 cores are also v5TE, so don't bother */
44 #define ENABLE_ARCH_5TE arm_dc_feature(s, ARM_FEATURE_V5)
45 #define ENABLE_ARCH_5J dc_isar_feature(jazelle, s)
46 #define ENABLE_ARCH_6 arm_dc_feature(s, ARM_FEATURE_V6)
47 #define ENABLE_ARCH_6K arm_dc_feature(s, ARM_FEATURE_V6K)
48 #define ENABLE_ARCH_6T2 arm_dc_feature(s, ARM_FEATURE_THUMB2)
49 #define ENABLE_ARCH_7 arm_dc_feature(s, ARM_FEATURE_V7)
50 #define ENABLE_ARCH_8 arm_dc_feature(s, ARM_FEATURE_V8)
52 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
54 #include "translate.h"
56 #if defined(CONFIG_USER_ONLY)
57 #define IS_USER(s) 1
58 #else
59 #define IS_USER(s) (s->user)
60 #endif
62 /* We reuse the same 64-bit temporaries for efficiency. */
63 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
64 static TCGv_i32 cpu_R[16];
65 TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
66 TCGv_i64 cpu_exclusive_addr;
67 TCGv_i64 cpu_exclusive_val;
69 /* FIXME: These should be removed. */
70 static TCGv_i32 cpu_F0s, cpu_F1s;
71 static TCGv_i64 cpu_F0d, cpu_F1d;
73 #include "exec/gen-icount.h"
75 static const char * const regnames[] =
76 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
77 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
79 /* Function prototypes for gen_ functions calling Neon helpers. */
80 typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32,
81 TCGv_i32, TCGv_i32);
83 /* initialize TCG globals. */
84 void arm_translate_init(void)
86 int i;
88 for (i = 0; i < 16; i++) {
89 cpu_R[i] = tcg_global_mem_new_i32(cpu_env,
90 offsetof(CPUARMState, regs[i]),
91 regnames[i]);
93 cpu_CF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, CF), "CF");
94 cpu_NF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, NF), "NF");
95 cpu_VF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, VF), "VF");
96 cpu_ZF = tcg_global_mem_new_i32(cpu_env, offsetof(CPUARMState, ZF), "ZF");
98 cpu_exclusive_addr = tcg_global_mem_new_i64(cpu_env,
99 offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
100 cpu_exclusive_val = tcg_global_mem_new_i64(cpu_env,
101 offsetof(CPUARMState, exclusive_val), "exclusive_val");
103 a64_translate_init();
106 /* Flags for the disas_set_da_iss info argument:
107 * lower bits hold the Rt register number, higher bits are flags.
109 typedef enum ISSInfo {
110 ISSNone = 0,
111 ISSRegMask = 0x1f,
112 ISSInvalid = (1 << 5),
113 ISSIsAcqRel = (1 << 6),
114 ISSIsWrite = (1 << 7),
115 ISSIs16Bit = (1 << 8),
116 } ISSInfo;
118 /* Save the syndrome information for a Data Abort */
119 static void disas_set_da_iss(DisasContext *s, TCGMemOp memop, ISSInfo issinfo)
121 uint32_t syn;
122 int sas = memop & MO_SIZE;
123 bool sse = memop & MO_SIGN;
124 bool is_acqrel = issinfo & ISSIsAcqRel;
125 bool is_write = issinfo & ISSIsWrite;
126 bool is_16bit = issinfo & ISSIs16Bit;
127 int srt = issinfo & ISSRegMask;
129 if (issinfo & ISSInvalid) {
130 /* Some callsites want to conditionally provide ISS info,
131 * eg "only if this was not a writeback"
133 return;
136 if (srt == 15) {
137 /* For AArch32, insns where the src/dest is R15 never generate
138 * ISS information. Catching that here saves checking at all
139 * the call sites.
141 return;
144 syn = syn_data_abort_with_iss(0, sas, sse, srt, 0, is_acqrel,
145 0, 0, 0, is_write, 0, is_16bit);
146 disas_set_insn_syndrome(s, syn);
149 static inline int get_a32_user_mem_index(DisasContext *s)
151 /* Return the core mmu_idx to use for A32/T32 "unprivileged load/store"
152 * insns:
153 * if PL2, UNPREDICTABLE (we choose to implement as if PL0)
154 * otherwise, access as if at PL0.
156 switch (s->mmu_idx) {
157 case ARMMMUIdx_S1E2: /* this one is UNPREDICTABLE */
158 case ARMMMUIdx_S12NSE0:
159 case ARMMMUIdx_S12NSE1:
160 return arm_to_core_mmu_idx(ARMMMUIdx_S12NSE0);
161 case ARMMMUIdx_S1E3:
162 case ARMMMUIdx_S1SE0:
163 case ARMMMUIdx_S1SE1:
164 return arm_to_core_mmu_idx(ARMMMUIdx_S1SE0);
165 case ARMMMUIdx_MUser:
166 case ARMMMUIdx_MPriv:
167 return arm_to_core_mmu_idx(ARMMMUIdx_MUser);
168 case ARMMMUIdx_MUserNegPri:
169 case ARMMMUIdx_MPrivNegPri:
170 return arm_to_core_mmu_idx(ARMMMUIdx_MUserNegPri);
171 case ARMMMUIdx_MSUser:
172 case ARMMMUIdx_MSPriv:
173 return arm_to_core_mmu_idx(ARMMMUIdx_MSUser);
174 case ARMMMUIdx_MSUserNegPri:
175 case ARMMMUIdx_MSPrivNegPri:
176 return arm_to_core_mmu_idx(ARMMMUIdx_MSUserNegPri);
177 case ARMMMUIdx_S2NS:
178 default:
179 g_assert_not_reached();
183 static inline TCGv_i32 load_cpu_offset(int offset)
185 TCGv_i32 tmp = tcg_temp_new_i32();
186 tcg_gen_ld_i32(tmp, cpu_env, offset);
187 return tmp;
190 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
192 static inline void store_cpu_offset(TCGv_i32 var, int offset)
194 tcg_gen_st_i32(var, cpu_env, offset);
195 tcg_temp_free_i32(var);
198 #define store_cpu_field(var, name) \
199 store_cpu_offset(var, offsetof(CPUARMState, name))
201 /* Set a variable to the value of a CPU register. */
202 static void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
204 if (reg == 15) {
205 uint32_t addr;
206 /* normally, since we updated PC, we need only to add one insn */
207 if (s->thumb)
208 addr = (long)s->pc + 2;
209 else
210 addr = (long)s->pc + 4;
211 tcg_gen_movi_i32(var, addr);
212 } else {
213 tcg_gen_mov_i32(var, cpu_R[reg]);
217 /* Create a new temporary and set it to the value of a CPU register. */
218 static inline TCGv_i32 load_reg(DisasContext *s, int reg)
220 TCGv_i32 tmp = tcg_temp_new_i32();
221 load_reg_var(s, tmp, reg);
222 return tmp;
225 /* Set a CPU register. The source must be a temporary and will be
226 marked as dead. */
227 static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
229 if (reg == 15) {
230 /* In Thumb mode, we must ignore bit 0.
231 * In ARM mode, for ARMv4 and ARMv5, it is UNPREDICTABLE if bits [1:0]
232 * are not 0b00, but for ARMv6 and above, we must ignore bits [1:0].
233 * We choose to ignore [1:0] in ARM mode for all architecture versions.
235 tcg_gen_andi_i32(var, var, s->thumb ? ~1 : ~3);
236 s->base.is_jmp = DISAS_JUMP;
238 tcg_gen_mov_i32(cpu_R[reg], var);
239 tcg_temp_free_i32(var);
243 * Variant of store_reg which applies v8M stack-limit checks before updating
244 * SP. If the check fails this will result in an exception being taken.
245 * We disable the stack checks for CONFIG_USER_ONLY because we have
246 * no idea what the stack limits should be in that case.
247 * If stack checking is not being done this just acts like store_reg().
249 static void store_sp_checked(DisasContext *s, TCGv_i32 var)
251 #ifndef CONFIG_USER_ONLY
252 if (s->v8m_stackcheck) {
253 gen_helper_v8m_stackcheck(cpu_env, var);
255 #endif
256 store_reg(s, 13, var);
259 /* Value extensions. */
260 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
261 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
262 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
263 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
265 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
266 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
269 static inline void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
271 TCGv_i32 tmp_mask = tcg_const_i32(mask);
272 gen_helper_cpsr_write(cpu_env, var, tmp_mask);
273 tcg_temp_free_i32(tmp_mask);
275 /* Set NZCV flags from the high 4 bits of var. */
276 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
278 static void gen_exception_internal(int excp)
280 TCGv_i32 tcg_excp = tcg_const_i32(excp);
282 assert(excp_is_internal(excp));
283 gen_helper_exception_internal(cpu_env, tcg_excp);
284 tcg_temp_free_i32(tcg_excp);
287 static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el)
289 TCGv_i32 tcg_excp = tcg_const_i32(excp);
290 TCGv_i32 tcg_syn = tcg_const_i32(syndrome);
291 TCGv_i32 tcg_el = tcg_const_i32(target_el);
293 gen_helper_exception_with_syndrome(cpu_env, tcg_excp,
294 tcg_syn, tcg_el);
296 tcg_temp_free_i32(tcg_el);
297 tcg_temp_free_i32(tcg_syn);
298 tcg_temp_free_i32(tcg_excp);
301 static void gen_ss_advance(DisasContext *s)
303 /* If the singlestep state is Active-not-pending, advance to
304 * Active-pending.
306 if (s->ss_active) {
307 s->pstate_ss = 0;
308 gen_helper_clear_pstate_ss(cpu_env);
312 static void gen_step_complete_exception(DisasContext *s)
314 /* We just completed step of an insn. Move from Active-not-pending
315 * to Active-pending, and then also take the swstep exception.
316 * This corresponds to making the (IMPDEF) choice to prioritize
317 * swstep exceptions over asynchronous exceptions taken to an exception
318 * level where debug is disabled. This choice has the advantage that
319 * we do not need to maintain internal state corresponding to the
320 * ISV/EX syndrome bits between completion of the step and generation
321 * of the exception, and our syndrome information is always correct.
323 gen_ss_advance(s);
324 gen_exception(EXCP_UDEF, syn_swstep(s->ss_same_el, 1, s->is_ldex),
325 default_exception_el(s));
326 s->base.is_jmp = DISAS_NORETURN;
329 static void gen_singlestep_exception(DisasContext *s)
331 /* Generate the right kind of exception for singlestep, which is
332 * either the architectural singlestep or EXCP_DEBUG for QEMU's
333 * gdb singlestepping.
335 if (s->ss_active) {
336 gen_step_complete_exception(s);
337 } else {
338 gen_exception_internal(EXCP_DEBUG);
342 static inline bool is_singlestepping(DisasContext *s)
344 /* Return true if we are singlestepping either because of
345 * architectural singlestep or QEMU gdbstub singlestep. This does
346 * not include the command line '-singlestep' mode which is rather
347 * misnamed as it only means "one instruction per TB" and doesn't
348 * affect the code we generate.
350 return s->base.singlestep_enabled || s->ss_active;
353 static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
355 TCGv_i32 tmp1 = tcg_temp_new_i32();
356 TCGv_i32 tmp2 = tcg_temp_new_i32();
357 tcg_gen_ext16s_i32(tmp1, a);
358 tcg_gen_ext16s_i32(tmp2, b);
359 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
360 tcg_temp_free_i32(tmp2);
361 tcg_gen_sari_i32(a, a, 16);
362 tcg_gen_sari_i32(b, b, 16);
363 tcg_gen_mul_i32(b, b, a);
364 tcg_gen_mov_i32(a, tmp1);
365 tcg_temp_free_i32(tmp1);
368 /* Byteswap each halfword. */
369 static void gen_rev16(TCGv_i32 var)
371 TCGv_i32 tmp = tcg_temp_new_i32();
372 TCGv_i32 mask = tcg_const_i32(0x00ff00ff);
373 tcg_gen_shri_i32(tmp, var, 8);
374 tcg_gen_and_i32(tmp, tmp, mask);
375 tcg_gen_and_i32(var, var, mask);
376 tcg_gen_shli_i32(var, var, 8);
377 tcg_gen_or_i32(var, var, tmp);
378 tcg_temp_free_i32(mask);
379 tcg_temp_free_i32(tmp);
382 /* Byteswap low halfword and sign extend. */
383 static void gen_revsh(TCGv_i32 var)
385 tcg_gen_ext16u_i32(var, var);
386 tcg_gen_bswap16_i32(var, var);
387 tcg_gen_ext16s_i32(var, var);
390 /* Return (b << 32) + a. Mark inputs as dead */
391 static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv_i32 b)
393 TCGv_i64 tmp64 = tcg_temp_new_i64();
395 tcg_gen_extu_i32_i64(tmp64, b);
396 tcg_temp_free_i32(b);
397 tcg_gen_shli_i64(tmp64, tmp64, 32);
398 tcg_gen_add_i64(a, tmp64, a);
400 tcg_temp_free_i64(tmp64);
401 return a;
404 /* Return (b << 32) - a. Mark inputs as dead. */
405 static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv_i32 b)
407 TCGv_i64 tmp64 = tcg_temp_new_i64();
409 tcg_gen_extu_i32_i64(tmp64, b);
410 tcg_temp_free_i32(b);
411 tcg_gen_shli_i64(tmp64, tmp64, 32);
412 tcg_gen_sub_i64(a, tmp64, a);
414 tcg_temp_free_i64(tmp64);
415 return a;
418 /* 32x32->64 multiply. Marks inputs as dead. */
419 static TCGv_i64 gen_mulu_i64_i32(TCGv_i32 a, TCGv_i32 b)
421 TCGv_i32 lo = tcg_temp_new_i32();
422 TCGv_i32 hi = tcg_temp_new_i32();
423 TCGv_i64 ret;
425 tcg_gen_mulu2_i32(lo, hi, a, b);
426 tcg_temp_free_i32(a);
427 tcg_temp_free_i32(b);
429 ret = tcg_temp_new_i64();
430 tcg_gen_concat_i32_i64(ret, lo, hi);
431 tcg_temp_free_i32(lo);
432 tcg_temp_free_i32(hi);
434 return ret;
437 static TCGv_i64 gen_muls_i64_i32(TCGv_i32 a, TCGv_i32 b)
439 TCGv_i32 lo = tcg_temp_new_i32();
440 TCGv_i32 hi = tcg_temp_new_i32();
441 TCGv_i64 ret;
443 tcg_gen_muls2_i32(lo, hi, a, b);
444 tcg_temp_free_i32(a);
445 tcg_temp_free_i32(b);
447 ret = tcg_temp_new_i64();
448 tcg_gen_concat_i32_i64(ret, lo, hi);
449 tcg_temp_free_i32(lo);
450 tcg_temp_free_i32(hi);
452 return ret;
455 /* Swap low and high halfwords. */
456 static void gen_swap_half(TCGv_i32 var)
458 TCGv_i32 tmp = tcg_temp_new_i32();
459 tcg_gen_shri_i32(tmp, var, 16);
460 tcg_gen_shli_i32(var, var, 16);
461 tcg_gen_or_i32(var, var, tmp);
462 tcg_temp_free_i32(tmp);
465 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
466 tmp = (t0 ^ t1) & 0x8000;
467 t0 &= ~0x8000;
468 t1 &= ~0x8000;
469 t0 = (t0 + t1) ^ tmp;
472 static void gen_add16(TCGv_i32 t0, TCGv_i32 t1)
474 TCGv_i32 tmp = tcg_temp_new_i32();
475 tcg_gen_xor_i32(tmp, t0, t1);
476 tcg_gen_andi_i32(tmp, tmp, 0x8000);
477 tcg_gen_andi_i32(t0, t0, ~0x8000);
478 tcg_gen_andi_i32(t1, t1, ~0x8000);
479 tcg_gen_add_i32(t0, t0, t1);
480 tcg_gen_xor_i32(t0, t0, tmp);
481 tcg_temp_free_i32(tmp);
482 tcg_temp_free_i32(t1);
485 /* Set CF to the top bit of var. */
486 static void gen_set_CF_bit31(TCGv_i32 var)
488 tcg_gen_shri_i32(cpu_CF, var, 31);
491 /* Set N and Z flags from var. */
492 static inline void gen_logic_CC(TCGv_i32 var)
494 tcg_gen_mov_i32(cpu_NF, var);
495 tcg_gen_mov_i32(cpu_ZF, var);
498 /* T0 += T1 + CF. */
499 static void gen_adc(TCGv_i32 t0, TCGv_i32 t1)
501 tcg_gen_add_i32(t0, t0, t1);
502 tcg_gen_add_i32(t0, t0, cpu_CF);
505 /* dest = T0 + T1 + CF. */
506 static void gen_add_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
508 tcg_gen_add_i32(dest, t0, t1);
509 tcg_gen_add_i32(dest, dest, cpu_CF);
512 /* dest = T0 - T1 + CF - 1. */
513 static void gen_sub_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
515 tcg_gen_sub_i32(dest, t0, t1);
516 tcg_gen_add_i32(dest, dest, cpu_CF);
517 tcg_gen_subi_i32(dest, dest, 1);
520 /* dest = T0 + T1. Compute C, N, V and Z flags */
521 static void gen_add_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
523 TCGv_i32 tmp = tcg_temp_new_i32();
524 tcg_gen_movi_i32(tmp, 0);
525 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, t1, tmp);
526 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
527 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
528 tcg_gen_xor_i32(tmp, t0, t1);
529 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
530 tcg_temp_free_i32(tmp);
531 tcg_gen_mov_i32(dest, cpu_NF);
534 /* dest = T0 + T1 + CF. Compute C, N, V and Z flags */
535 static void gen_adc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
537 TCGv_i32 tmp = tcg_temp_new_i32();
538 if (TCG_TARGET_HAS_add2_i32) {
539 tcg_gen_movi_i32(tmp, 0);
540 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp);
541 tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1, tmp);
542 } else {
543 TCGv_i64 q0 = tcg_temp_new_i64();
544 TCGv_i64 q1 = tcg_temp_new_i64();
545 tcg_gen_extu_i32_i64(q0, t0);
546 tcg_gen_extu_i32_i64(q1, t1);
547 tcg_gen_add_i64(q0, q0, q1);
548 tcg_gen_extu_i32_i64(q1, cpu_CF);
549 tcg_gen_add_i64(q0, q0, q1);
550 tcg_gen_extr_i64_i32(cpu_NF, cpu_CF, q0);
551 tcg_temp_free_i64(q0);
552 tcg_temp_free_i64(q1);
554 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
555 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
556 tcg_gen_xor_i32(tmp, t0, t1);
557 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
558 tcg_temp_free_i32(tmp);
559 tcg_gen_mov_i32(dest, cpu_NF);
562 /* dest = T0 - T1. Compute C, N, V and Z flags */
563 static void gen_sub_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
565 TCGv_i32 tmp;
566 tcg_gen_sub_i32(cpu_NF, t0, t1);
567 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
568 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0, t1);
569 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
570 tmp = tcg_temp_new_i32();
571 tcg_gen_xor_i32(tmp, t0, t1);
572 tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
573 tcg_temp_free_i32(tmp);
574 tcg_gen_mov_i32(dest, cpu_NF);
577 /* dest = T0 + ~T1 + CF. Compute C, N, V and Z flags */
578 static void gen_sbc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
580 TCGv_i32 tmp = tcg_temp_new_i32();
581 tcg_gen_not_i32(tmp, t1);
582 gen_adc_CC(dest, t0, tmp);
583 tcg_temp_free_i32(tmp);
586 #define GEN_SHIFT(name) \
587 static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \
589 TCGv_i32 tmp1, tmp2, tmp3; \
590 tmp1 = tcg_temp_new_i32(); \
591 tcg_gen_andi_i32(tmp1, t1, 0xff); \
592 tmp2 = tcg_const_i32(0); \
593 tmp3 = tcg_const_i32(0x1f); \
594 tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
595 tcg_temp_free_i32(tmp3); \
596 tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
597 tcg_gen_##name##_i32(dest, tmp2, tmp1); \
598 tcg_temp_free_i32(tmp2); \
599 tcg_temp_free_i32(tmp1); \
601 GEN_SHIFT(shl)
602 GEN_SHIFT(shr)
603 #undef GEN_SHIFT
605 static void gen_sar(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
607 TCGv_i32 tmp1, tmp2;
608 tmp1 = tcg_temp_new_i32();
609 tcg_gen_andi_i32(tmp1, t1, 0xff);
610 tmp2 = tcg_const_i32(0x1f);
611 tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1);
612 tcg_temp_free_i32(tmp2);
613 tcg_gen_sar_i32(dest, t0, tmp1);
614 tcg_temp_free_i32(tmp1);
617 static void tcg_gen_abs_i32(TCGv_i32 dest, TCGv_i32 src)
619 TCGv_i32 c0 = tcg_const_i32(0);
620 TCGv_i32 tmp = tcg_temp_new_i32();
621 tcg_gen_neg_i32(tmp, src);
622 tcg_gen_movcond_i32(TCG_COND_GT, dest, src, c0, src, tmp);
623 tcg_temp_free_i32(c0);
624 tcg_temp_free_i32(tmp);
627 static void shifter_out_im(TCGv_i32 var, int shift)
629 if (shift == 0) {
630 tcg_gen_andi_i32(cpu_CF, var, 1);
631 } else {
632 tcg_gen_shri_i32(cpu_CF, var, shift);
633 if (shift != 31) {
634 tcg_gen_andi_i32(cpu_CF, cpu_CF, 1);
639 /* Shift by immediate. Includes special handling for shift == 0. */
640 static inline void gen_arm_shift_im(TCGv_i32 var, int shiftop,
641 int shift, int flags)
643 switch (shiftop) {
644 case 0: /* LSL */
645 if (shift != 0) {
646 if (flags)
647 shifter_out_im(var, 32 - shift);
648 tcg_gen_shli_i32(var, var, shift);
650 break;
651 case 1: /* LSR */
652 if (shift == 0) {
653 if (flags) {
654 tcg_gen_shri_i32(cpu_CF, var, 31);
656 tcg_gen_movi_i32(var, 0);
657 } else {
658 if (flags)
659 shifter_out_im(var, shift - 1);
660 tcg_gen_shri_i32(var, var, shift);
662 break;
663 case 2: /* ASR */
664 if (shift == 0)
665 shift = 32;
666 if (flags)
667 shifter_out_im(var, shift - 1);
668 if (shift == 32)
669 shift = 31;
670 tcg_gen_sari_i32(var, var, shift);
671 break;
672 case 3: /* ROR/RRX */
673 if (shift != 0) {
674 if (flags)
675 shifter_out_im(var, shift - 1);
676 tcg_gen_rotri_i32(var, var, shift); break;
677 } else {
678 TCGv_i32 tmp = tcg_temp_new_i32();
679 tcg_gen_shli_i32(tmp, cpu_CF, 31);
680 if (flags)
681 shifter_out_im(var, 0);
682 tcg_gen_shri_i32(var, var, 1);
683 tcg_gen_or_i32(var, var, tmp);
684 tcg_temp_free_i32(tmp);
689 static inline void gen_arm_shift_reg(TCGv_i32 var, int shiftop,
690 TCGv_i32 shift, int flags)
692 if (flags) {
693 switch (shiftop) {
694 case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break;
695 case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break;
696 case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break;
697 case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break;
699 } else {
700 switch (shiftop) {
701 case 0:
702 gen_shl(var, var, shift);
703 break;
704 case 1:
705 gen_shr(var, var, shift);
706 break;
707 case 2:
708 gen_sar(var, var, shift);
709 break;
710 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
711 tcg_gen_rotr_i32(var, var, shift); break;
714 tcg_temp_free_i32(shift);
717 #define PAS_OP(pfx) \
718 switch (op2) { \
719 case 0: gen_pas_helper(glue(pfx,add16)); break; \
720 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
721 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
722 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
723 case 4: gen_pas_helper(glue(pfx,add8)); break; \
724 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
726 static void gen_arm_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
728 TCGv_ptr tmp;
730 switch (op1) {
731 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
732 case 1:
733 tmp = tcg_temp_new_ptr();
734 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
735 PAS_OP(s)
736 tcg_temp_free_ptr(tmp);
737 break;
738 case 5:
739 tmp = tcg_temp_new_ptr();
740 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
741 PAS_OP(u)
742 tcg_temp_free_ptr(tmp);
743 break;
744 #undef gen_pas_helper
745 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
746 case 2:
747 PAS_OP(q);
748 break;
749 case 3:
750 PAS_OP(sh);
751 break;
752 case 6:
753 PAS_OP(uq);
754 break;
755 case 7:
756 PAS_OP(uh);
757 break;
758 #undef gen_pas_helper
761 #undef PAS_OP
763 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
764 #define PAS_OP(pfx) \
765 switch (op1) { \
766 case 0: gen_pas_helper(glue(pfx,add8)); break; \
767 case 1: gen_pas_helper(glue(pfx,add16)); break; \
768 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
769 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
770 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
771 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
773 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
775 TCGv_ptr tmp;
777 switch (op2) {
778 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
779 case 0:
780 tmp = tcg_temp_new_ptr();
781 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
782 PAS_OP(s)
783 tcg_temp_free_ptr(tmp);
784 break;
785 case 4:
786 tmp = tcg_temp_new_ptr();
787 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
788 PAS_OP(u)
789 tcg_temp_free_ptr(tmp);
790 break;
791 #undef gen_pas_helper
792 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
793 case 1:
794 PAS_OP(q);
795 break;
796 case 2:
797 PAS_OP(sh);
798 break;
799 case 5:
800 PAS_OP(uq);
801 break;
802 case 6:
803 PAS_OP(uh);
804 break;
805 #undef gen_pas_helper
808 #undef PAS_OP
811 * Generate a conditional based on ARM condition code cc.
812 * This is common between ARM and Aarch64 targets.
814 void arm_test_cc(DisasCompare *cmp, int cc)
816 TCGv_i32 value;
817 TCGCond cond;
818 bool global = true;
820 switch (cc) {
821 case 0: /* eq: Z */
822 case 1: /* ne: !Z */
823 cond = TCG_COND_EQ;
824 value = cpu_ZF;
825 break;
827 case 2: /* cs: C */
828 case 3: /* cc: !C */
829 cond = TCG_COND_NE;
830 value = cpu_CF;
831 break;
833 case 4: /* mi: N */
834 case 5: /* pl: !N */
835 cond = TCG_COND_LT;
836 value = cpu_NF;
837 break;
839 case 6: /* vs: V */
840 case 7: /* vc: !V */
841 cond = TCG_COND_LT;
842 value = cpu_VF;
843 break;
845 case 8: /* hi: C && !Z */
846 case 9: /* ls: !C || Z -> !(C && !Z) */
847 cond = TCG_COND_NE;
848 value = tcg_temp_new_i32();
849 global = false;
850 /* CF is 1 for C, so -CF is an all-bits-set mask for C;
851 ZF is non-zero for !Z; so AND the two subexpressions. */
852 tcg_gen_neg_i32(value, cpu_CF);
853 tcg_gen_and_i32(value, value, cpu_ZF);
854 break;
856 case 10: /* ge: N == V -> N ^ V == 0 */
857 case 11: /* lt: N != V -> N ^ V != 0 */
858 /* Since we're only interested in the sign bit, == 0 is >= 0. */
859 cond = TCG_COND_GE;
860 value = tcg_temp_new_i32();
861 global = false;
862 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
863 break;
865 case 12: /* gt: !Z && N == V */
866 case 13: /* le: Z || N != V */
867 cond = TCG_COND_NE;
868 value = tcg_temp_new_i32();
869 global = false;
870 /* (N == V) is equal to the sign bit of ~(NF ^ VF). Propagate
871 * the sign bit then AND with ZF to yield the result. */
872 tcg_gen_xor_i32(value, cpu_VF, cpu_NF);
873 tcg_gen_sari_i32(value, value, 31);
874 tcg_gen_andc_i32(value, cpu_ZF, value);
875 break;
877 case 14: /* always */
878 case 15: /* always */
879 /* Use the ALWAYS condition, which will fold early.
880 * It doesn't matter what we use for the value. */
881 cond = TCG_COND_ALWAYS;
882 value = cpu_ZF;
883 goto no_invert;
885 default:
886 fprintf(stderr, "Bad condition code 0x%x\n", cc);
887 abort();
890 if (cc & 1) {
891 cond = tcg_invert_cond(cond);
894 no_invert:
895 cmp->cond = cond;
896 cmp->value = value;
897 cmp->value_global = global;
900 void arm_free_cc(DisasCompare *cmp)
902 if (!cmp->value_global) {
903 tcg_temp_free_i32(cmp->value);
907 void arm_jump_cc(DisasCompare *cmp, TCGLabel *label)
909 tcg_gen_brcondi_i32(cmp->cond, cmp->value, 0, label);
912 void arm_gen_test_cc(int cc, TCGLabel *label)
914 DisasCompare cmp;
915 arm_test_cc(&cmp, cc);
916 arm_jump_cc(&cmp, label);
917 arm_free_cc(&cmp);
920 static const uint8_t table_logic_cc[16] = {
921 1, /* and */
922 1, /* xor */
923 0, /* sub */
924 0, /* rsb */
925 0, /* add */
926 0, /* adc */
927 0, /* sbc */
928 0, /* rsc */
929 1, /* andl */
930 1, /* xorl */
931 0, /* cmp */
932 0, /* cmn */
933 1, /* orr */
934 1, /* mov */
935 1, /* bic */
936 1, /* mvn */
939 static inline void gen_set_condexec(DisasContext *s)
941 if (s->condexec_mask) {
942 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
943 TCGv_i32 tmp = tcg_temp_new_i32();
944 tcg_gen_movi_i32(tmp, val);
945 store_cpu_field(tmp, condexec_bits);
949 static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
951 tcg_gen_movi_i32(cpu_R[15], val);
954 /* Set PC and Thumb state from an immediate address. */
955 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
957 TCGv_i32 tmp;
959 s->base.is_jmp = DISAS_JUMP;
960 if (s->thumb != (addr & 1)) {
961 tmp = tcg_temp_new_i32();
962 tcg_gen_movi_i32(tmp, addr & 1);
963 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, thumb));
964 tcg_temp_free_i32(tmp);
966 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
969 /* Set PC and Thumb state from var. var is marked as dead. */
970 static inline void gen_bx(DisasContext *s, TCGv_i32 var)
972 s->base.is_jmp = DISAS_JUMP;
973 tcg_gen_andi_i32(cpu_R[15], var, ~1);
974 tcg_gen_andi_i32(var, var, 1);
975 store_cpu_field(var, thumb);
978 /* Set PC and Thumb state from var. var is marked as dead.
979 * For M-profile CPUs, include logic to detect exception-return
980 * branches and handle them. This is needed for Thumb POP/LDM to PC, LDR to PC,
981 * and BX reg, and no others, and happens only for code in Handler mode.
983 static inline void gen_bx_excret(DisasContext *s, TCGv_i32 var)
985 /* Generate the same code here as for a simple bx, but flag via
986 * s->base.is_jmp that we need to do the rest of the work later.
988 gen_bx(s, var);
989 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY) ||
990 (s->v7m_handler_mode && arm_dc_feature(s, ARM_FEATURE_M))) {
991 s->base.is_jmp = DISAS_BX_EXCRET;
995 static inline void gen_bx_excret_final_code(DisasContext *s)
997 /* Generate the code to finish possible exception return and end the TB */
998 TCGLabel *excret_label = gen_new_label();
999 uint32_t min_magic;
1001 if (arm_dc_feature(s, ARM_FEATURE_M_SECURITY)) {
1002 /* Covers FNC_RETURN and EXC_RETURN magic */
1003 min_magic = FNC_RETURN_MIN_MAGIC;
1004 } else {
1005 /* EXC_RETURN magic only */
1006 min_magic = EXC_RETURN_MIN_MAGIC;
1009 /* Is the new PC value in the magic range indicating exception return? */
1010 tcg_gen_brcondi_i32(TCG_COND_GEU, cpu_R[15], min_magic, excret_label);
1011 /* No: end the TB as we would for a DISAS_JMP */
1012 if (is_singlestepping(s)) {
1013 gen_singlestep_exception(s);
1014 } else {
1015 tcg_gen_exit_tb(NULL, 0);
1017 gen_set_label(excret_label);
1018 /* Yes: this is an exception return.
1019 * At this point in runtime env->regs[15] and env->thumb will hold
1020 * the exception-return magic number, which do_v7m_exception_exit()
1021 * will read. Nothing else will be able to see those values because
1022 * the cpu-exec main loop guarantees that we will always go straight
1023 * from raising the exception to the exception-handling code.
1025 * gen_ss_advance(s) does nothing on M profile currently but
1026 * calling it is conceptually the right thing as we have executed
1027 * this instruction (compare SWI, HVC, SMC handling).
1029 gen_ss_advance(s);
1030 gen_exception_internal(EXCP_EXCEPTION_EXIT);
1033 static inline void gen_bxns(DisasContext *s, int rm)
1035 TCGv_i32 var = load_reg(s, rm);
1037 /* The bxns helper may raise an EXCEPTION_EXIT exception, so in theory
1038 * we need to sync state before calling it, but:
1039 * - we don't need to do gen_set_pc_im() because the bxns helper will
1040 * always set the PC itself
1041 * - we don't need to do gen_set_condexec() because BXNS is UNPREDICTABLE
1042 * unless it's outside an IT block or the last insn in an IT block,
1043 * so we know that condexec == 0 (already set at the top of the TB)
1044 * is correct in the non-UNPREDICTABLE cases, and we can choose
1045 * "zeroes the IT bits" as our UNPREDICTABLE behaviour otherwise.
1047 gen_helper_v7m_bxns(cpu_env, var);
1048 tcg_temp_free_i32(var);
1049 s->base.is_jmp = DISAS_EXIT;
1052 static inline void gen_blxns(DisasContext *s, int rm)
1054 TCGv_i32 var = load_reg(s, rm);
1056 /* We don't need to sync condexec state, for the same reason as bxns.
1057 * We do however need to set the PC, because the blxns helper reads it.
1058 * The blxns helper may throw an exception.
1060 gen_set_pc_im(s, s->pc);
1061 gen_helper_v7m_blxns(cpu_env, var);
1062 tcg_temp_free_i32(var);
1063 s->base.is_jmp = DISAS_EXIT;
1066 /* Variant of store_reg which uses branch&exchange logic when storing
1067 to r15 in ARM architecture v7 and above. The source must be a temporary
1068 and will be marked as dead. */
1069 static inline void store_reg_bx(DisasContext *s, int reg, TCGv_i32 var)
1071 if (reg == 15 && ENABLE_ARCH_7) {
1072 gen_bx(s, var);
1073 } else {
1074 store_reg(s, reg, var);
1078 /* Variant of store_reg which uses branch&exchange logic when storing
1079 * to r15 in ARM architecture v5T and above. This is used for storing
1080 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
1081 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
1082 static inline void store_reg_from_load(DisasContext *s, int reg, TCGv_i32 var)
1084 if (reg == 15 && ENABLE_ARCH_5) {
1085 gen_bx_excret(s, var);
1086 } else {
1087 store_reg(s, reg, var);
1091 #ifdef CONFIG_USER_ONLY
1092 #define IS_USER_ONLY 1
1093 #else
1094 #define IS_USER_ONLY 0
1095 #endif
1097 /* Abstractions of "generate code to do a guest load/store for
1098 * AArch32", where a vaddr is always 32 bits (and is zero
1099 * extended if we're a 64 bit core) and data is also
1100 * 32 bits unless specifically doing a 64 bit access.
1101 * These functions work like tcg_gen_qemu_{ld,st}* except
1102 * that the address argument is TCGv_i32 rather than TCGv.
1105 static inline TCGv gen_aa32_addr(DisasContext *s, TCGv_i32 a32, TCGMemOp op)
1107 TCGv addr = tcg_temp_new();
1108 tcg_gen_extu_i32_tl(addr, a32);
1110 /* Not needed for user-mode BE32, where we use MO_BE instead. */
1111 if (!IS_USER_ONLY && s->sctlr_b && (op & MO_SIZE) < MO_32) {
1112 tcg_gen_xori_tl(addr, addr, 4 - (1 << (op & MO_SIZE)));
1114 return addr;
1117 static void gen_aa32_ld_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
1118 int index, TCGMemOp opc)
1120 TCGv addr;
1122 if (arm_dc_feature(s, ARM_FEATURE_M) &&
1123 !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
1124 opc |= MO_ALIGN;
1127 addr = gen_aa32_addr(s, a32, opc);
1128 tcg_gen_qemu_ld_i32(val, addr, index, opc);
1129 tcg_temp_free(addr);
1132 static void gen_aa32_st_i32(DisasContext *s, TCGv_i32 val, TCGv_i32 a32,
1133 int index, TCGMemOp opc)
1135 TCGv addr;
1137 if (arm_dc_feature(s, ARM_FEATURE_M) &&
1138 !arm_dc_feature(s, ARM_FEATURE_M_MAIN)) {
1139 opc |= MO_ALIGN;
1142 addr = gen_aa32_addr(s, a32, opc);
1143 tcg_gen_qemu_st_i32(val, addr, index, opc);
1144 tcg_temp_free(addr);
1147 #define DO_GEN_LD(SUFF, OPC) \
1148 static inline void gen_aa32_ld##SUFF(DisasContext *s, TCGv_i32 val, \
1149 TCGv_i32 a32, int index) \
1151 gen_aa32_ld_i32(s, val, a32, index, OPC | s->be_data); \
1153 static inline void gen_aa32_ld##SUFF##_iss(DisasContext *s, \
1154 TCGv_i32 val, \
1155 TCGv_i32 a32, int index, \
1156 ISSInfo issinfo) \
1158 gen_aa32_ld##SUFF(s, val, a32, index); \
1159 disas_set_da_iss(s, OPC, issinfo); \
1162 #define DO_GEN_ST(SUFF, OPC) \
1163 static inline void gen_aa32_st##SUFF(DisasContext *s, TCGv_i32 val, \
1164 TCGv_i32 a32, int index) \
1166 gen_aa32_st_i32(s, val, a32, index, OPC | s->be_data); \
1168 static inline void gen_aa32_st##SUFF##_iss(DisasContext *s, \
1169 TCGv_i32 val, \
1170 TCGv_i32 a32, int index, \
1171 ISSInfo issinfo) \
1173 gen_aa32_st##SUFF(s, val, a32, index); \
1174 disas_set_da_iss(s, OPC, issinfo | ISSIsWrite); \
1177 static inline void gen_aa32_frob64(DisasContext *s, TCGv_i64 val)
1179 /* Not needed for user-mode BE32, where we use MO_BE instead. */
1180 if (!IS_USER_ONLY && s->sctlr_b) {
1181 tcg_gen_rotri_i64(val, val, 32);
1185 static void gen_aa32_ld_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
1186 int index, TCGMemOp opc)
1188 TCGv addr = gen_aa32_addr(s, a32, opc);
1189 tcg_gen_qemu_ld_i64(val, addr, index, opc);
1190 gen_aa32_frob64(s, val);
1191 tcg_temp_free(addr);
1194 static inline void gen_aa32_ld64(DisasContext *s, TCGv_i64 val,
1195 TCGv_i32 a32, int index)
1197 gen_aa32_ld_i64(s, val, a32, index, MO_Q | s->be_data);
1200 static void gen_aa32_st_i64(DisasContext *s, TCGv_i64 val, TCGv_i32 a32,
1201 int index, TCGMemOp opc)
1203 TCGv addr = gen_aa32_addr(s, a32, opc);
1205 /* Not needed for user-mode BE32, where we use MO_BE instead. */
1206 if (!IS_USER_ONLY && s->sctlr_b) {
1207 TCGv_i64 tmp = tcg_temp_new_i64();
1208 tcg_gen_rotri_i64(tmp, val, 32);
1209 tcg_gen_qemu_st_i64(tmp, addr, index, opc);
1210 tcg_temp_free_i64(tmp);
1211 } else {
1212 tcg_gen_qemu_st_i64(val, addr, index, opc);
1214 tcg_temp_free(addr);
1217 static inline void gen_aa32_st64(DisasContext *s, TCGv_i64 val,
1218 TCGv_i32 a32, int index)
1220 gen_aa32_st_i64(s, val, a32, index, MO_Q | s->be_data);
1223 DO_GEN_LD(8s, MO_SB)
1224 DO_GEN_LD(8u, MO_UB)
1225 DO_GEN_LD(16s, MO_SW)
1226 DO_GEN_LD(16u, MO_UW)
1227 DO_GEN_LD(32u, MO_UL)
1228 DO_GEN_ST(8, MO_UB)
1229 DO_GEN_ST(16, MO_UW)
1230 DO_GEN_ST(32, MO_UL)
1232 static inline void gen_hvc(DisasContext *s, int imm16)
1234 /* The pre HVC helper handles cases when HVC gets trapped
1235 * as an undefined insn by runtime configuration (ie before
1236 * the insn really executes).
1238 gen_set_pc_im(s, s->pc - 4);
1239 gen_helper_pre_hvc(cpu_env);
1240 /* Otherwise we will treat this as a real exception which
1241 * happens after execution of the insn. (The distinction matters
1242 * for the PC value reported to the exception handler and also
1243 * for single stepping.)
1245 s->svc_imm = imm16;
1246 gen_set_pc_im(s, s->pc);
1247 s->base.is_jmp = DISAS_HVC;
1250 static inline void gen_smc(DisasContext *s)
1252 /* As with HVC, we may take an exception either before or after
1253 * the insn executes.
1255 TCGv_i32 tmp;
1257 gen_set_pc_im(s, s->pc - 4);
1258 tmp = tcg_const_i32(syn_aa32_smc());
1259 gen_helper_pre_smc(cpu_env, tmp);
1260 tcg_temp_free_i32(tmp);
1261 gen_set_pc_im(s, s->pc);
1262 s->base.is_jmp = DISAS_SMC;
1265 static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
1267 gen_set_condexec(s);
1268 gen_set_pc_im(s, s->pc - offset);
1269 gen_exception_internal(excp);
1270 s->base.is_jmp = DISAS_NORETURN;
1273 static void gen_exception_insn(DisasContext *s, int offset, int excp,
1274 int syn, uint32_t target_el)
1276 gen_set_condexec(s);
1277 gen_set_pc_im(s, s->pc - offset);
1278 gen_exception(excp, syn, target_el);
1279 s->base.is_jmp = DISAS_NORETURN;
1282 static void gen_exception_bkpt_insn(DisasContext *s, int offset, uint32_t syn)
1284 TCGv_i32 tcg_syn;
1286 gen_set_condexec(s);
1287 gen_set_pc_im(s, s->pc - offset);
1288 tcg_syn = tcg_const_i32(syn);
1289 gen_helper_exception_bkpt_insn(cpu_env, tcg_syn);
1290 tcg_temp_free_i32(tcg_syn);
1291 s->base.is_jmp = DISAS_NORETURN;
1294 /* Force a TB lookup after an instruction that changes the CPU state. */
1295 static inline void gen_lookup_tb(DisasContext *s)
1297 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
1298 s->base.is_jmp = DISAS_EXIT;
1301 static inline void gen_hlt(DisasContext *s, int imm)
1303 /* HLT. This has two purposes.
1304 * Architecturally, it is an external halting debug instruction.
1305 * Since QEMU doesn't implement external debug, we treat this as
1306 * it is required for halting debug disabled: it will UNDEF.
1307 * Secondly, "HLT 0x3C" is a T32 semihosting trap instruction,
1308 * and "HLT 0xF000" is an A32 semihosting syscall. These traps
1309 * must trigger semihosting even for ARMv7 and earlier, where
1310 * HLT was an undefined encoding.
1311 * In system mode, we don't allow userspace access to
1312 * semihosting, to provide some semblance of security
1313 * (and for consistency with our 32-bit semihosting).
1315 if (semihosting_enabled() &&
1316 #ifndef CONFIG_USER_ONLY
1317 s->current_el != 0 &&
1318 #endif
1319 (imm == (s->thumb ? 0x3c : 0xf000))) {
1320 gen_exception_internal_insn(s, 0, EXCP_SEMIHOST);
1321 return;
1324 gen_exception_insn(s, s->thumb ? 2 : 4, EXCP_UDEF, syn_uncategorized(),
1325 default_exception_el(s));
1328 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
1329 TCGv_i32 var)
1331 int val, rm, shift, shiftop;
1332 TCGv_i32 offset;
1334 if (!(insn & (1 << 25))) {
1335 /* immediate */
1336 val = insn & 0xfff;
1337 if (!(insn & (1 << 23)))
1338 val = -val;
1339 if (val != 0)
1340 tcg_gen_addi_i32(var, var, val);
1341 } else {
1342 /* shift/register */
1343 rm = (insn) & 0xf;
1344 shift = (insn >> 7) & 0x1f;
1345 shiftop = (insn >> 5) & 3;
1346 offset = load_reg(s, rm);
1347 gen_arm_shift_im(offset, shiftop, shift, 0);
1348 if (!(insn & (1 << 23)))
1349 tcg_gen_sub_i32(var, var, offset);
1350 else
1351 tcg_gen_add_i32(var, var, offset);
1352 tcg_temp_free_i32(offset);
1356 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
1357 int extra, TCGv_i32 var)
1359 int val, rm;
1360 TCGv_i32 offset;
1362 if (insn & (1 << 22)) {
1363 /* immediate */
1364 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
1365 if (!(insn & (1 << 23)))
1366 val = -val;
1367 val += extra;
1368 if (val != 0)
1369 tcg_gen_addi_i32(var, var, val);
1370 } else {
1371 /* register */
1372 if (extra)
1373 tcg_gen_addi_i32(var, var, extra);
1374 rm = (insn) & 0xf;
1375 offset = load_reg(s, rm);
1376 if (!(insn & (1 << 23)))
1377 tcg_gen_sub_i32(var, var, offset);
1378 else
1379 tcg_gen_add_i32(var, var, offset);
1380 tcg_temp_free_i32(offset);
1384 static TCGv_ptr get_fpstatus_ptr(int neon)
1386 TCGv_ptr statusptr = tcg_temp_new_ptr();
1387 int offset;
1388 if (neon) {
1389 offset = offsetof(CPUARMState, vfp.standard_fp_status);
1390 } else {
1391 offset = offsetof(CPUARMState, vfp.fp_status);
1393 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
1394 return statusptr;
1397 #define VFP_OP2(name) \
1398 static inline void gen_vfp_##name(int dp) \
1400 TCGv_ptr fpst = get_fpstatus_ptr(0); \
1401 if (dp) { \
1402 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, fpst); \
1403 } else { \
1404 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, fpst); \
1406 tcg_temp_free_ptr(fpst); \
1409 VFP_OP2(add)
1410 VFP_OP2(sub)
1411 VFP_OP2(mul)
1412 VFP_OP2(div)
1414 #undef VFP_OP2
1416 static inline void gen_vfp_F1_mul(int dp)
1418 /* Like gen_vfp_mul() but put result in F1 */
1419 TCGv_ptr fpst = get_fpstatus_ptr(0);
1420 if (dp) {
1421 gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, fpst);
1422 } else {
1423 gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, fpst);
1425 tcg_temp_free_ptr(fpst);
1428 static inline void gen_vfp_F1_neg(int dp)
1430 /* Like gen_vfp_neg() but put result in F1 */
1431 if (dp) {
1432 gen_helper_vfp_negd(cpu_F1d, cpu_F0d);
1433 } else {
1434 gen_helper_vfp_negs(cpu_F1s, cpu_F0s);
1438 static inline void gen_vfp_abs(int dp)
1440 if (dp)
1441 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1442 else
1443 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1446 static inline void gen_vfp_neg(int dp)
1448 if (dp)
1449 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1450 else
1451 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1454 static inline void gen_vfp_sqrt(int dp)
1456 if (dp)
1457 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1458 else
1459 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1462 static inline void gen_vfp_cmp(int dp)
1464 if (dp)
1465 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1466 else
1467 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1470 static inline void gen_vfp_cmpe(int dp)
1472 if (dp)
1473 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1474 else
1475 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1478 static inline void gen_vfp_F1_ld0(int dp)
1480 if (dp)
1481 tcg_gen_movi_i64(cpu_F1d, 0);
1482 else
1483 tcg_gen_movi_i32(cpu_F1s, 0);
1486 #define VFP_GEN_ITOF(name) \
1487 static inline void gen_vfp_##name(int dp, int neon) \
1489 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1490 if (dp) { \
1491 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
1492 } else { \
1493 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1495 tcg_temp_free_ptr(statusptr); \
1498 VFP_GEN_ITOF(uito)
1499 VFP_GEN_ITOF(sito)
1500 #undef VFP_GEN_ITOF
1502 #define VFP_GEN_FTOI(name) \
1503 static inline void gen_vfp_##name(int dp, int neon) \
1505 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1506 if (dp) { \
1507 gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
1508 } else { \
1509 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1511 tcg_temp_free_ptr(statusptr); \
1514 VFP_GEN_FTOI(toui)
1515 VFP_GEN_FTOI(touiz)
1516 VFP_GEN_FTOI(tosi)
1517 VFP_GEN_FTOI(tosiz)
1518 #undef VFP_GEN_FTOI
1520 #define VFP_GEN_FIX(name, round) \
1521 static inline void gen_vfp_##name(int dp, int shift, int neon) \
1523 TCGv_i32 tmp_shift = tcg_const_i32(shift); \
1524 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1525 if (dp) { \
1526 gen_helper_vfp_##name##d##round(cpu_F0d, cpu_F0d, tmp_shift, \
1527 statusptr); \
1528 } else { \
1529 gen_helper_vfp_##name##s##round(cpu_F0s, cpu_F0s, tmp_shift, \
1530 statusptr); \
1532 tcg_temp_free_i32(tmp_shift); \
1533 tcg_temp_free_ptr(statusptr); \
1535 VFP_GEN_FIX(tosh, _round_to_zero)
1536 VFP_GEN_FIX(tosl, _round_to_zero)
1537 VFP_GEN_FIX(touh, _round_to_zero)
1538 VFP_GEN_FIX(toul, _round_to_zero)
1539 VFP_GEN_FIX(shto, )
1540 VFP_GEN_FIX(slto, )
1541 VFP_GEN_FIX(uhto, )
1542 VFP_GEN_FIX(ulto, )
1543 #undef VFP_GEN_FIX
1545 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr)
1547 if (dp) {
1548 gen_aa32_ld64(s, cpu_F0d, addr, get_mem_index(s));
1549 } else {
1550 gen_aa32_ld32u(s, cpu_F0s, addr, get_mem_index(s));
1554 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
1556 if (dp) {
1557 gen_aa32_st64(s, cpu_F0d, addr, get_mem_index(s));
1558 } else {
1559 gen_aa32_st32(s, cpu_F0s, addr, get_mem_index(s));
1563 static inline long vfp_reg_offset(bool dp, unsigned reg)
1565 if (dp) {
1566 return offsetof(CPUARMState, vfp.zregs[reg >> 1].d[reg & 1]);
1567 } else {
1568 long ofs = offsetof(CPUARMState, vfp.zregs[reg >> 2].d[(reg >> 1) & 1]);
1569 if (reg & 1) {
1570 ofs += offsetof(CPU_DoubleU, l.upper);
1571 } else {
1572 ofs += offsetof(CPU_DoubleU, l.lower);
1574 return ofs;
1578 /* Return the offset of a 32-bit piece of a NEON register.
1579 zero is the least significant end of the register. */
1580 static inline long
1581 neon_reg_offset (int reg, int n)
1583 int sreg;
1584 sreg = reg * 2 + n;
1585 return vfp_reg_offset(0, sreg);
1588 /* Return the offset of a 2**SIZE piece of a NEON register, at index ELE,
1589 * where 0 is the least significant end of the register.
1591 static inline long
1592 neon_element_offset(int reg, int element, TCGMemOp size)
1594 int element_size = 1 << size;
1595 int ofs = element * element_size;
1596 #ifdef HOST_WORDS_BIGENDIAN
1597 /* Calculate the offset assuming fully little-endian,
1598 * then XOR to account for the order of the 8-byte units.
1600 if (element_size < 8) {
1601 ofs ^= 8 - element_size;
1603 #endif
1604 return neon_reg_offset(reg, 0) + ofs;
1607 static TCGv_i32 neon_load_reg(int reg, int pass)
1609 TCGv_i32 tmp = tcg_temp_new_i32();
1610 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1611 return tmp;
1614 static void neon_load_element(TCGv_i32 var, int reg, int ele, TCGMemOp mop)
1616 long offset = neon_element_offset(reg, ele, mop & MO_SIZE);
1618 switch (mop) {
1619 case MO_UB:
1620 tcg_gen_ld8u_i32(var, cpu_env, offset);
1621 break;
1622 case MO_UW:
1623 tcg_gen_ld16u_i32(var, cpu_env, offset);
1624 break;
1625 case MO_UL:
1626 tcg_gen_ld_i32(var, cpu_env, offset);
1627 break;
1628 default:
1629 g_assert_not_reached();
1633 static void neon_load_element64(TCGv_i64 var, int reg, int ele, TCGMemOp mop)
1635 long offset = neon_element_offset(reg, ele, mop & MO_SIZE);
1637 switch (mop) {
1638 case MO_UB:
1639 tcg_gen_ld8u_i64(var, cpu_env, offset);
1640 break;
1641 case MO_UW:
1642 tcg_gen_ld16u_i64(var, cpu_env, offset);
1643 break;
1644 case MO_UL:
1645 tcg_gen_ld32u_i64(var, cpu_env, offset);
1646 break;
1647 case MO_Q:
1648 tcg_gen_ld_i64(var, cpu_env, offset);
1649 break;
1650 default:
1651 g_assert_not_reached();
1655 static void neon_store_reg(int reg, int pass, TCGv_i32 var)
1657 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1658 tcg_temp_free_i32(var);
1661 static void neon_store_element(int reg, int ele, TCGMemOp size, TCGv_i32 var)
1663 long offset = neon_element_offset(reg, ele, size);
1665 switch (size) {
1666 case MO_8:
1667 tcg_gen_st8_i32(var, cpu_env, offset);
1668 break;
1669 case MO_16:
1670 tcg_gen_st16_i32(var, cpu_env, offset);
1671 break;
1672 case MO_32:
1673 tcg_gen_st_i32(var, cpu_env, offset);
1674 break;
1675 default:
1676 g_assert_not_reached();
1680 static void neon_store_element64(int reg, int ele, TCGMemOp size, TCGv_i64 var)
1682 long offset = neon_element_offset(reg, ele, size);
1684 switch (size) {
1685 case MO_8:
1686 tcg_gen_st8_i64(var, cpu_env, offset);
1687 break;
1688 case MO_16:
1689 tcg_gen_st16_i64(var, cpu_env, offset);
1690 break;
1691 case MO_32:
1692 tcg_gen_st32_i64(var, cpu_env, offset);
1693 break;
1694 case MO_64:
1695 tcg_gen_st_i64(var, cpu_env, offset);
1696 break;
1697 default:
1698 g_assert_not_reached();
1702 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1704 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1707 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1709 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1712 static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
1714 TCGv_ptr ret = tcg_temp_new_ptr();
1715 tcg_gen_addi_ptr(ret, cpu_env, vfp_reg_offset(dp, reg));
1716 return ret;
1719 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1720 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1721 #define tcg_gen_st_f32 tcg_gen_st_i32
1722 #define tcg_gen_st_f64 tcg_gen_st_i64
1724 static inline void gen_mov_F0_vreg(int dp, int reg)
1726 if (dp)
1727 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1728 else
1729 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1732 static inline void gen_mov_F1_vreg(int dp, int reg)
1734 if (dp)
1735 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1736 else
1737 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1740 static inline void gen_mov_vreg_F0(int dp, int reg)
1742 if (dp)
1743 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1744 else
1745 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1748 #define ARM_CP_RW_BIT (1 << 20)
1750 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1752 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1755 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1757 tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1760 static inline TCGv_i32 iwmmxt_load_creg(int reg)
1762 TCGv_i32 var = tcg_temp_new_i32();
1763 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1764 return var;
1767 static inline void iwmmxt_store_creg(int reg, TCGv_i32 var)
1769 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1770 tcg_temp_free_i32(var);
1773 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1775 iwmmxt_store_reg(cpu_M0, rn);
1778 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1780 iwmmxt_load_reg(cpu_M0, rn);
1783 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1785 iwmmxt_load_reg(cpu_V1, rn);
1786 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1789 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1791 iwmmxt_load_reg(cpu_V1, rn);
1792 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1795 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1797 iwmmxt_load_reg(cpu_V1, rn);
1798 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1801 #define IWMMXT_OP(name) \
1802 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1804 iwmmxt_load_reg(cpu_V1, rn); \
1805 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1808 #define IWMMXT_OP_ENV(name) \
1809 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1811 iwmmxt_load_reg(cpu_V1, rn); \
1812 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1815 #define IWMMXT_OP_ENV_SIZE(name) \
1816 IWMMXT_OP_ENV(name##b) \
1817 IWMMXT_OP_ENV(name##w) \
1818 IWMMXT_OP_ENV(name##l)
1820 #define IWMMXT_OP_ENV1(name) \
1821 static inline void gen_op_iwmmxt_##name##_M0(void) \
1823 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1826 IWMMXT_OP(maddsq)
1827 IWMMXT_OP(madduq)
1828 IWMMXT_OP(sadb)
1829 IWMMXT_OP(sadw)
1830 IWMMXT_OP(mulslw)
1831 IWMMXT_OP(mulshw)
1832 IWMMXT_OP(mululw)
1833 IWMMXT_OP(muluhw)
1834 IWMMXT_OP(macsw)
1835 IWMMXT_OP(macuw)
1837 IWMMXT_OP_ENV_SIZE(unpackl)
1838 IWMMXT_OP_ENV_SIZE(unpackh)
1840 IWMMXT_OP_ENV1(unpacklub)
1841 IWMMXT_OP_ENV1(unpackluw)
1842 IWMMXT_OP_ENV1(unpacklul)
1843 IWMMXT_OP_ENV1(unpackhub)
1844 IWMMXT_OP_ENV1(unpackhuw)
1845 IWMMXT_OP_ENV1(unpackhul)
1846 IWMMXT_OP_ENV1(unpacklsb)
1847 IWMMXT_OP_ENV1(unpacklsw)
1848 IWMMXT_OP_ENV1(unpacklsl)
1849 IWMMXT_OP_ENV1(unpackhsb)
1850 IWMMXT_OP_ENV1(unpackhsw)
1851 IWMMXT_OP_ENV1(unpackhsl)
1853 IWMMXT_OP_ENV_SIZE(cmpeq)
1854 IWMMXT_OP_ENV_SIZE(cmpgtu)
1855 IWMMXT_OP_ENV_SIZE(cmpgts)
1857 IWMMXT_OP_ENV_SIZE(mins)
1858 IWMMXT_OP_ENV_SIZE(minu)
1859 IWMMXT_OP_ENV_SIZE(maxs)
1860 IWMMXT_OP_ENV_SIZE(maxu)
1862 IWMMXT_OP_ENV_SIZE(subn)
1863 IWMMXT_OP_ENV_SIZE(addn)
1864 IWMMXT_OP_ENV_SIZE(subu)
1865 IWMMXT_OP_ENV_SIZE(addu)
1866 IWMMXT_OP_ENV_SIZE(subs)
1867 IWMMXT_OP_ENV_SIZE(adds)
1869 IWMMXT_OP_ENV(avgb0)
1870 IWMMXT_OP_ENV(avgb1)
1871 IWMMXT_OP_ENV(avgw0)
1872 IWMMXT_OP_ENV(avgw1)
1874 IWMMXT_OP_ENV(packuw)
1875 IWMMXT_OP_ENV(packul)
1876 IWMMXT_OP_ENV(packuq)
1877 IWMMXT_OP_ENV(packsw)
1878 IWMMXT_OP_ENV(packsl)
1879 IWMMXT_OP_ENV(packsq)
1881 static void gen_op_iwmmxt_set_mup(void)
1883 TCGv_i32 tmp;
1884 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1885 tcg_gen_ori_i32(tmp, tmp, 2);
1886 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1889 static void gen_op_iwmmxt_set_cup(void)
1891 TCGv_i32 tmp;
1892 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1893 tcg_gen_ori_i32(tmp, tmp, 1);
1894 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1897 static void gen_op_iwmmxt_setpsr_nz(void)
1899 TCGv_i32 tmp = tcg_temp_new_i32();
1900 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1901 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1904 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1906 iwmmxt_load_reg(cpu_V1, rn);
1907 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1908 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1911 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn,
1912 TCGv_i32 dest)
1914 int rd;
1915 uint32_t offset;
1916 TCGv_i32 tmp;
1918 rd = (insn >> 16) & 0xf;
1919 tmp = load_reg(s, rd);
1921 offset = (insn & 0xff) << ((insn >> 7) & 2);
1922 if (insn & (1 << 24)) {
1923 /* Pre indexed */
1924 if (insn & (1 << 23))
1925 tcg_gen_addi_i32(tmp, tmp, offset);
1926 else
1927 tcg_gen_addi_i32(tmp, tmp, -offset);
1928 tcg_gen_mov_i32(dest, tmp);
1929 if (insn & (1 << 21))
1930 store_reg(s, rd, tmp);
1931 else
1932 tcg_temp_free_i32(tmp);
1933 } else if (insn & (1 << 21)) {
1934 /* Post indexed */
1935 tcg_gen_mov_i32(dest, tmp);
1936 if (insn & (1 << 23))
1937 tcg_gen_addi_i32(tmp, tmp, offset);
1938 else
1939 tcg_gen_addi_i32(tmp, tmp, -offset);
1940 store_reg(s, rd, tmp);
1941 } else if (!(insn & (1 << 23)))
1942 return 1;
1943 return 0;
1946 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest)
1948 int rd = (insn >> 0) & 0xf;
1949 TCGv_i32 tmp;
1951 if (insn & (1 << 8)) {
1952 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1953 return 1;
1954 } else {
1955 tmp = iwmmxt_load_creg(rd);
1957 } else {
1958 tmp = tcg_temp_new_i32();
1959 iwmmxt_load_reg(cpu_V0, rd);
1960 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
1962 tcg_gen_andi_i32(tmp, tmp, mask);
1963 tcg_gen_mov_i32(dest, tmp);
1964 tcg_temp_free_i32(tmp);
1965 return 0;
1968 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
1969 (ie. an undefined instruction). */
1970 static int disas_iwmmxt_insn(DisasContext *s, uint32_t insn)
1972 int rd, wrd;
1973 int rdhi, rdlo, rd0, rd1, i;
1974 TCGv_i32 addr;
1975 TCGv_i32 tmp, tmp2, tmp3;
1977 if ((insn & 0x0e000e00) == 0x0c000000) {
1978 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1979 wrd = insn & 0xf;
1980 rdlo = (insn >> 12) & 0xf;
1981 rdhi = (insn >> 16) & 0xf;
1982 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1983 iwmmxt_load_reg(cpu_V0, wrd);
1984 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
1985 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1986 tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
1987 } else { /* TMCRR */
1988 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1989 iwmmxt_store_reg(cpu_V0, wrd);
1990 gen_op_iwmmxt_set_mup();
1992 return 0;
1995 wrd = (insn >> 12) & 0xf;
1996 addr = tcg_temp_new_i32();
1997 if (gen_iwmmxt_address(s, insn, addr)) {
1998 tcg_temp_free_i32(addr);
1999 return 1;
2001 if (insn & ARM_CP_RW_BIT) {
2002 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
2003 tmp = tcg_temp_new_i32();
2004 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
2005 iwmmxt_store_creg(wrd, tmp);
2006 } else {
2007 i = 1;
2008 if (insn & (1 << 8)) {
2009 if (insn & (1 << 22)) { /* WLDRD */
2010 gen_aa32_ld64(s, cpu_M0, addr, get_mem_index(s));
2011 i = 0;
2012 } else { /* WLDRW wRd */
2013 tmp = tcg_temp_new_i32();
2014 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
2016 } else {
2017 tmp = tcg_temp_new_i32();
2018 if (insn & (1 << 22)) { /* WLDRH */
2019 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
2020 } else { /* WLDRB */
2021 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
2024 if (i) {
2025 tcg_gen_extu_i32_i64(cpu_M0, tmp);
2026 tcg_temp_free_i32(tmp);
2028 gen_op_iwmmxt_movq_wRn_M0(wrd);
2030 } else {
2031 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
2032 tmp = iwmmxt_load_creg(wrd);
2033 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
2034 } else {
2035 gen_op_iwmmxt_movq_M0_wRn(wrd);
2036 tmp = tcg_temp_new_i32();
2037 if (insn & (1 << 8)) {
2038 if (insn & (1 << 22)) { /* WSTRD */
2039 gen_aa32_st64(s, cpu_M0, addr, get_mem_index(s));
2040 } else { /* WSTRW wRd */
2041 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2042 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
2044 } else {
2045 if (insn & (1 << 22)) { /* WSTRH */
2046 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2047 gen_aa32_st16(s, tmp, addr, get_mem_index(s));
2048 } else { /* WSTRB */
2049 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2050 gen_aa32_st8(s, tmp, addr, get_mem_index(s));
2054 tcg_temp_free_i32(tmp);
2056 tcg_temp_free_i32(addr);
2057 return 0;
2060 if ((insn & 0x0f000000) != 0x0e000000)
2061 return 1;
2063 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
2064 case 0x000: /* WOR */
2065 wrd = (insn >> 12) & 0xf;
2066 rd0 = (insn >> 0) & 0xf;
2067 rd1 = (insn >> 16) & 0xf;
2068 gen_op_iwmmxt_movq_M0_wRn(rd0);
2069 gen_op_iwmmxt_orq_M0_wRn(rd1);
2070 gen_op_iwmmxt_setpsr_nz();
2071 gen_op_iwmmxt_movq_wRn_M0(wrd);
2072 gen_op_iwmmxt_set_mup();
2073 gen_op_iwmmxt_set_cup();
2074 break;
2075 case 0x011: /* TMCR */
2076 if (insn & 0xf)
2077 return 1;
2078 rd = (insn >> 12) & 0xf;
2079 wrd = (insn >> 16) & 0xf;
2080 switch (wrd) {
2081 case ARM_IWMMXT_wCID:
2082 case ARM_IWMMXT_wCASF:
2083 break;
2084 case ARM_IWMMXT_wCon:
2085 gen_op_iwmmxt_set_cup();
2086 /* Fall through. */
2087 case ARM_IWMMXT_wCSSF:
2088 tmp = iwmmxt_load_creg(wrd);
2089 tmp2 = load_reg(s, rd);
2090 tcg_gen_andc_i32(tmp, tmp, tmp2);
2091 tcg_temp_free_i32(tmp2);
2092 iwmmxt_store_creg(wrd, tmp);
2093 break;
2094 case ARM_IWMMXT_wCGR0:
2095 case ARM_IWMMXT_wCGR1:
2096 case ARM_IWMMXT_wCGR2:
2097 case ARM_IWMMXT_wCGR3:
2098 gen_op_iwmmxt_set_cup();
2099 tmp = load_reg(s, rd);
2100 iwmmxt_store_creg(wrd, tmp);
2101 break;
2102 default:
2103 return 1;
2105 break;
2106 case 0x100: /* WXOR */
2107 wrd = (insn >> 12) & 0xf;
2108 rd0 = (insn >> 0) & 0xf;
2109 rd1 = (insn >> 16) & 0xf;
2110 gen_op_iwmmxt_movq_M0_wRn(rd0);
2111 gen_op_iwmmxt_xorq_M0_wRn(rd1);
2112 gen_op_iwmmxt_setpsr_nz();
2113 gen_op_iwmmxt_movq_wRn_M0(wrd);
2114 gen_op_iwmmxt_set_mup();
2115 gen_op_iwmmxt_set_cup();
2116 break;
2117 case 0x111: /* TMRC */
2118 if (insn & 0xf)
2119 return 1;
2120 rd = (insn >> 12) & 0xf;
2121 wrd = (insn >> 16) & 0xf;
2122 tmp = iwmmxt_load_creg(wrd);
2123 store_reg(s, rd, tmp);
2124 break;
2125 case 0x300: /* WANDN */
2126 wrd = (insn >> 12) & 0xf;
2127 rd0 = (insn >> 0) & 0xf;
2128 rd1 = (insn >> 16) & 0xf;
2129 gen_op_iwmmxt_movq_M0_wRn(rd0);
2130 tcg_gen_neg_i64(cpu_M0, cpu_M0);
2131 gen_op_iwmmxt_andq_M0_wRn(rd1);
2132 gen_op_iwmmxt_setpsr_nz();
2133 gen_op_iwmmxt_movq_wRn_M0(wrd);
2134 gen_op_iwmmxt_set_mup();
2135 gen_op_iwmmxt_set_cup();
2136 break;
2137 case 0x200: /* WAND */
2138 wrd = (insn >> 12) & 0xf;
2139 rd0 = (insn >> 0) & 0xf;
2140 rd1 = (insn >> 16) & 0xf;
2141 gen_op_iwmmxt_movq_M0_wRn(rd0);
2142 gen_op_iwmmxt_andq_M0_wRn(rd1);
2143 gen_op_iwmmxt_setpsr_nz();
2144 gen_op_iwmmxt_movq_wRn_M0(wrd);
2145 gen_op_iwmmxt_set_mup();
2146 gen_op_iwmmxt_set_cup();
2147 break;
2148 case 0x810: case 0xa10: /* WMADD */
2149 wrd = (insn >> 12) & 0xf;
2150 rd0 = (insn >> 0) & 0xf;
2151 rd1 = (insn >> 16) & 0xf;
2152 gen_op_iwmmxt_movq_M0_wRn(rd0);
2153 if (insn & (1 << 21))
2154 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
2155 else
2156 gen_op_iwmmxt_madduq_M0_wRn(rd1);
2157 gen_op_iwmmxt_movq_wRn_M0(wrd);
2158 gen_op_iwmmxt_set_mup();
2159 break;
2160 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
2161 wrd = (insn >> 12) & 0xf;
2162 rd0 = (insn >> 16) & 0xf;
2163 rd1 = (insn >> 0) & 0xf;
2164 gen_op_iwmmxt_movq_M0_wRn(rd0);
2165 switch ((insn >> 22) & 3) {
2166 case 0:
2167 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
2168 break;
2169 case 1:
2170 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
2171 break;
2172 case 2:
2173 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
2174 break;
2175 case 3:
2176 return 1;
2178 gen_op_iwmmxt_movq_wRn_M0(wrd);
2179 gen_op_iwmmxt_set_mup();
2180 gen_op_iwmmxt_set_cup();
2181 break;
2182 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
2183 wrd = (insn >> 12) & 0xf;
2184 rd0 = (insn >> 16) & 0xf;
2185 rd1 = (insn >> 0) & 0xf;
2186 gen_op_iwmmxt_movq_M0_wRn(rd0);
2187 switch ((insn >> 22) & 3) {
2188 case 0:
2189 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
2190 break;
2191 case 1:
2192 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
2193 break;
2194 case 2:
2195 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
2196 break;
2197 case 3:
2198 return 1;
2200 gen_op_iwmmxt_movq_wRn_M0(wrd);
2201 gen_op_iwmmxt_set_mup();
2202 gen_op_iwmmxt_set_cup();
2203 break;
2204 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
2205 wrd = (insn >> 12) & 0xf;
2206 rd0 = (insn >> 16) & 0xf;
2207 rd1 = (insn >> 0) & 0xf;
2208 gen_op_iwmmxt_movq_M0_wRn(rd0);
2209 if (insn & (1 << 22))
2210 gen_op_iwmmxt_sadw_M0_wRn(rd1);
2211 else
2212 gen_op_iwmmxt_sadb_M0_wRn(rd1);
2213 if (!(insn & (1 << 20)))
2214 gen_op_iwmmxt_addl_M0_wRn(wrd);
2215 gen_op_iwmmxt_movq_wRn_M0(wrd);
2216 gen_op_iwmmxt_set_mup();
2217 break;
2218 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
2219 wrd = (insn >> 12) & 0xf;
2220 rd0 = (insn >> 16) & 0xf;
2221 rd1 = (insn >> 0) & 0xf;
2222 gen_op_iwmmxt_movq_M0_wRn(rd0);
2223 if (insn & (1 << 21)) {
2224 if (insn & (1 << 20))
2225 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
2226 else
2227 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
2228 } else {
2229 if (insn & (1 << 20))
2230 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
2231 else
2232 gen_op_iwmmxt_mululw_M0_wRn(rd1);
2234 gen_op_iwmmxt_movq_wRn_M0(wrd);
2235 gen_op_iwmmxt_set_mup();
2236 break;
2237 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
2238 wrd = (insn >> 12) & 0xf;
2239 rd0 = (insn >> 16) & 0xf;
2240 rd1 = (insn >> 0) & 0xf;
2241 gen_op_iwmmxt_movq_M0_wRn(rd0);
2242 if (insn & (1 << 21))
2243 gen_op_iwmmxt_macsw_M0_wRn(rd1);
2244 else
2245 gen_op_iwmmxt_macuw_M0_wRn(rd1);
2246 if (!(insn & (1 << 20))) {
2247 iwmmxt_load_reg(cpu_V1, wrd);
2248 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
2250 gen_op_iwmmxt_movq_wRn_M0(wrd);
2251 gen_op_iwmmxt_set_mup();
2252 break;
2253 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
2254 wrd = (insn >> 12) & 0xf;
2255 rd0 = (insn >> 16) & 0xf;
2256 rd1 = (insn >> 0) & 0xf;
2257 gen_op_iwmmxt_movq_M0_wRn(rd0);
2258 switch ((insn >> 22) & 3) {
2259 case 0:
2260 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
2261 break;
2262 case 1:
2263 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
2264 break;
2265 case 2:
2266 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
2267 break;
2268 case 3:
2269 return 1;
2271 gen_op_iwmmxt_movq_wRn_M0(wrd);
2272 gen_op_iwmmxt_set_mup();
2273 gen_op_iwmmxt_set_cup();
2274 break;
2275 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
2276 wrd = (insn >> 12) & 0xf;
2277 rd0 = (insn >> 16) & 0xf;
2278 rd1 = (insn >> 0) & 0xf;
2279 gen_op_iwmmxt_movq_M0_wRn(rd0);
2280 if (insn & (1 << 22)) {
2281 if (insn & (1 << 20))
2282 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
2283 else
2284 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
2285 } else {
2286 if (insn & (1 << 20))
2287 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
2288 else
2289 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
2291 gen_op_iwmmxt_movq_wRn_M0(wrd);
2292 gen_op_iwmmxt_set_mup();
2293 gen_op_iwmmxt_set_cup();
2294 break;
2295 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
2296 wrd = (insn >> 12) & 0xf;
2297 rd0 = (insn >> 16) & 0xf;
2298 rd1 = (insn >> 0) & 0xf;
2299 gen_op_iwmmxt_movq_M0_wRn(rd0);
2300 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
2301 tcg_gen_andi_i32(tmp, tmp, 7);
2302 iwmmxt_load_reg(cpu_V1, rd1);
2303 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2304 tcg_temp_free_i32(tmp);
2305 gen_op_iwmmxt_movq_wRn_M0(wrd);
2306 gen_op_iwmmxt_set_mup();
2307 break;
2308 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
2309 if (((insn >> 6) & 3) == 3)
2310 return 1;
2311 rd = (insn >> 12) & 0xf;
2312 wrd = (insn >> 16) & 0xf;
2313 tmp = load_reg(s, rd);
2314 gen_op_iwmmxt_movq_M0_wRn(wrd);
2315 switch ((insn >> 6) & 3) {
2316 case 0:
2317 tmp2 = tcg_const_i32(0xff);
2318 tmp3 = tcg_const_i32((insn & 7) << 3);
2319 break;
2320 case 1:
2321 tmp2 = tcg_const_i32(0xffff);
2322 tmp3 = tcg_const_i32((insn & 3) << 4);
2323 break;
2324 case 2:
2325 tmp2 = tcg_const_i32(0xffffffff);
2326 tmp3 = tcg_const_i32((insn & 1) << 5);
2327 break;
2328 default:
2329 tmp2 = NULL;
2330 tmp3 = NULL;
2332 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
2333 tcg_temp_free_i32(tmp3);
2334 tcg_temp_free_i32(tmp2);
2335 tcg_temp_free_i32(tmp);
2336 gen_op_iwmmxt_movq_wRn_M0(wrd);
2337 gen_op_iwmmxt_set_mup();
2338 break;
2339 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
2340 rd = (insn >> 12) & 0xf;
2341 wrd = (insn >> 16) & 0xf;
2342 if (rd == 15 || ((insn >> 22) & 3) == 3)
2343 return 1;
2344 gen_op_iwmmxt_movq_M0_wRn(wrd);
2345 tmp = tcg_temp_new_i32();
2346 switch ((insn >> 22) & 3) {
2347 case 0:
2348 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
2349 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2350 if (insn & 8) {
2351 tcg_gen_ext8s_i32(tmp, tmp);
2352 } else {
2353 tcg_gen_andi_i32(tmp, tmp, 0xff);
2355 break;
2356 case 1:
2357 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
2358 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2359 if (insn & 8) {
2360 tcg_gen_ext16s_i32(tmp, tmp);
2361 } else {
2362 tcg_gen_andi_i32(tmp, tmp, 0xffff);
2364 break;
2365 case 2:
2366 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
2367 tcg_gen_extrl_i64_i32(tmp, cpu_M0);
2368 break;
2370 store_reg(s, rd, tmp);
2371 break;
2372 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
2373 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
2374 return 1;
2375 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
2376 switch ((insn >> 22) & 3) {
2377 case 0:
2378 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
2379 break;
2380 case 1:
2381 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
2382 break;
2383 case 2:
2384 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
2385 break;
2387 tcg_gen_shli_i32(tmp, tmp, 28);
2388 gen_set_nzcv(tmp);
2389 tcg_temp_free_i32(tmp);
2390 break;
2391 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
2392 if (((insn >> 6) & 3) == 3)
2393 return 1;
2394 rd = (insn >> 12) & 0xf;
2395 wrd = (insn >> 16) & 0xf;
2396 tmp = load_reg(s, rd);
2397 switch ((insn >> 6) & 3) {
2398 case 0:
2399 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
2400 break;
2401 case 1:
2402 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
2403 break;
2404 case 2:
2405 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
2406 break;
2408 tcg_temp_free_i32(tmp);
2409 gen_op_iwmmxt_movq_wRn_M0(wrd);
2410 gen_op_iwmmxt_set_mup();
2411 break;
2412 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
2413 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
2414 return 1;
2415 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
2416 tmp2 = tcg_temp_new_i32();
2417 tcg_gen_mov_i32(tmp2, tmp);
2418 switch ((insn >> 22) & 3) {
2419 case 0:
2420 for (i = 0; i < 7; i ++) {
2421 tcg_gen_shli_i32(tmp2, tmp2, 4);
2422 tcg_gen_and_i32(tmp, tmp, tmp2);
2424 break;
2425 case 1:
2426 for (i = 0; i < 3; i ++) {
2427 tcg_gen_shli_i32(tmp2, tmp2, 8);
2428 tcg_gen_and_i32(tmp, tmp, tmp2);
2430 break;
2431 case 2:
2432 tcg_gen_shli_i32(tmp2, tmp2, 16);
2433 tcg_gen_and_i32(tmp, tmp, tmp2);
2434 break;
2436 gen_set_nzcv(tmp);
2437 tcg_temp_free_i32(tmp2);
2438 tcg_temp_free_i32(tmp);
2439 break;
2440 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
2441 wrd = (insn >> 12) & 0xf;
2442 rd0 = (insn >> 16) & 0xf;
2443 gen_op_iwmmxt_movq_M0_wRn(rd0);
2444 switch ((insn >> 22) & 3) {
2445 case 0:
2446 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
2447 break;
2448 case 1:
2449 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
2450 break;
2451 case 2:
2452 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
2453 break;
2454 case 3:
2455 return 1;
2457 gen_op_iwmmxt_movq_wRn_M0(wrd);
2458 gen_op_iwmmxt_set_mup();
2459 break;
2460 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
2461 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
2462 return 1;
2463 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
2464 tmp2 = tcg_temp_new_i32();
2465 tcg_gen_mov_i32(tmp2, tmp);
2466 switch ((insn >> 22) & 3) {
2467 case 0:
2468 for (i = 0; i < 7; i ++) {
2469 tcg_gen_shli_i32(tmp2, tmp2, 4);
2470 tcg_gen_or_i32(tmp, tmp, tmp2);
2472 break;
2473 case 1:
2474 for (i = 0; i < 3; i ++) {
2475 tcg_gen_shli_i32(tmp2, tmp2, 8);
2476 tcg_gen_or_i32(tmp, tmp, tmp2);
2478 break;
2479 case 2:
2480 tcg_gen_shli_i32(tmp2, tmp2, 16);
2481 tcg_gen_or_i32(tmp, tmp, tmp2);
2482 break;
2484 gen_set_nzcv(tmp);
2485 tcg_temp_free_i32(tmp2);
2486 tcg_temp_free_i32(tmp);
2487 break;
2488 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
2489 rd = (insn >> 12) & 0xf;
2490 rd0 = (insn >> 16) & 0xf;
2491 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
2492 return 1;
2493 gen_op_iwmmxt_movq_M0_wRn(rd0);
2494 tmp = tcg_temp_new_i32();
2495 switch ((insn >> 22) & 3) {
2496 case 0:
2497 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
2498 break;
2499 case 1:
2500 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
2501 break;
2502 case 2:
2503 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
2504 break;
2506 store_reg(s, rd, tmp);
2507 break;
2508 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
2509 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2510 wrd = (insn >> 12) & 0xf;
2511 rd0 = (insn >> 16) & 0xf;
2512 rd1 = (insn >> 0) & 0xf;
2513 gen_op_iwmmxt_movq_M0_wRn(rd0);
2514 switch ((insn >> 22) & 3) {
2515 case 0:
2516 if (insn & (1 << 21))
2517 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2518 else
2519 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2520 break;
2521 case 1:
2522 if (insn & (1 << 21))
2523 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2524 else
2525 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2526 break;
2527 case 2:
2528 if (insn & (1 << 21))
2529 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2530 else
2531 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2532 break;
2533 case 3:
2534 return 1;
2536 gen_op_iwmmxt_movq_wRn_M0(wrd);
2537 gen_op_iwmmxt_set_mup();
2538 gen_op_iwmmxt_set_cup();
2539 break;
2540 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2541 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2542 wrd = (insn >> 12) & 0xf;
2543 rd0 = (insn >> 16) & 0xf;
2544 gen_op_iwmmxt_movq_M0_wRn(rd0);
2545 switch ((insn >> 22) & 3) {
2546 case 0:
2547 if (insn & (1 << 21))
2548 gen_op_iwmmxt_unpacklsb_M0();
2549 else
2550 gen_op_iwmmxt_unpacklub_M0();
2551 break;
2552 case 1:
2553 if (insn & (1 << 21))
2554 gen_op_iwmmxt_unpacklsw_M0();
2555 else
2556 gen_op_iwmmxt_unpackluw_M0();
2557 break;
2558 case 2:
2559 if (insn & (1 << 21))
2560 gen_op_iwmmxt_unpacklsl_M0();
2561 else
2562 gen_op_iwmmxt_unpacklul_M0();
2563 break;
2564 case 3:
2565 return 1;
2567 gen_op_iwmmxt_movq_wRn_M0(wrd);
2568 gen_op_iwmmxt_set_mup();
2569 gen_op_iwmmxt_set_cup();
2570 break;
2571 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2572 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2573 wrd = (insn >> 12) & 0xf;
2574 rd0 = (insn >> 16) & 0xf;
2575 gen_op_iwmmxt_movq_M0_wRn(rd0);
2576 switch ((insn >> 22) & 3) {
2577 case 0:
2578 if (insn & (1 << 21))
2579 gen_op_iwmmxt_unpackhsb_M0();
2580 else
2581 gen_op_iwmmxt_unpackhub_M0();
2582 break;
2583 case 1:
2584 if (insn & (1 << 21))
2585 gen_op_iwmmxt_unpackhsw_M0();
2586 else
2587 gen_op_iwmmxt_unpackhuw_M0();
2588 break;
2589 case 2:
2590 if (insn & (1 << 21))
2591 gen_op_iwmmxt_unpackhsl_M0();
2592 else
2593 gen_op_iwmmxt_unpackhul_M0();
2594 break;
2595 case 3:
2596 return 1;
2598 gen_op_iwmmxt_movq_wRn_M0(wrd);
2599 gen_op_iwmmxt_set_mup();
2600 gen_op_iwmmxt_set_cup();
2601 break;
2602 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2603 case 0x214: case 0x614: case 0xa14: case 0xe14:
2604 if (((insn >> 22) & 3) == 0)
2605 return 1;
2606 wrd = (insn >> 12) & 0xf;
2607 rd0 = (insn >> 16) & 0xf;
2608 gen_op_iwmmxt_movq_M0_wRn(rd0);
2609 tmp = tcg_temp_new_i32();
2610 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2611 tcg_temp_free_i32(tmp);
2612 return 1;
2614 switch ((insn >> 22) & 3) {
2615 case 1:
2616 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
2617 break;
2618 case 2:
2619 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
2620 break;
2621 case 3:
2622 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
2623 break;
2625 tcg_temp_free_i32(tmp);
2626 gen_op_iwmmxt_movq_wRn_M0(wrd);
2627 gen_op_iwmmxt_set_mup();
2628 gen_op_iwmmxt_set_cup();
2629 break;
2630 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2631 case 0x014: case 0x414: case 0x814: case 0xc14:
2632 if (((insn >> 22) & 3) == 0)
2633 return 1;
2634 wrd = (insn >> 12) & 0xf;
2635 rd0 = (insn >> 16) & 0xf;
2636 gen_op_iwmmxt_movq_M0_wRn(rd0);
2637 tmp = tcg_temp_new_i32();
2638 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2639 tcg_temp_free_i32(tmp);
2640 return 1;
2642 switch ((insn >> 22) & 3) {
2643 case 1:
2644 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2645 break;
2646 case 2:
2647 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2648 break;
2649 case 3:
2650 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2651 break;
2653 tcg_temp_free_i32(tmp);
2654 gen_op_iwmmxt_movq_wRn_M0(wrd);
2655 gen_op_iwmmxt_set_mup();
2656 gen_op_iwmmxt_set_cup();
2657 break;
2658 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2659 case 0x114: case 0x514: case 0x914: case 0xd14:
2660 if (((insn >> 22) & 3) == 0)
2661 return 1;
2662 wrd = (insn >> 12) & 0xf;
2663 rd0 = (insn >> 16) & 0xf;
2664 gen_op_iwmmxt_movq_M0_wRn(rd0);
2665 tmp = tcg_temp_new_i32();
2666 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2667 tcg_temp_free_i32(tmp);
2668 return 1;
2670 switch ((insn >> 22) & 3) {
2671 case 1:
2672 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2673 break;
2674 case 2:
2675 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2676 break;
2677 case 3:
2678 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2679 break;
2681 tcg_temp_free_i32(tmp);
2682 gen_op_iwmmxt_movq_wRn_M0(wrd);
2683 gen_op_iwmmxt_set_mup();
2684 gen_op_iwmmxt_set_cup();
2685 break;
2686 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2687 case 0x314: case 0x714: case 0xb14: case 0xf14:
2688 if (((insn >> 22) & 3) == 0)
2689 return 1;
2690 wrd = (insn >> 12) & 0xf;
2691 rd0 = (insn >> 16) & 0xf;
2692 gen_op_iwmmxt_movq_M0_wRn(rd0);
2693 tmp = tcg_temp_new_i32();
2694 switch ((insn >> 22) & 3) {
2695 case 1:
2696 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2697 tcg_temp_free_i32(tmp);
2698 return 1;
2700 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2701 break;
2702 case 2:
2703 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2704 tcg_temp_free_i32(tmp);
2705 return 1;
2707 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2708 break;
2709 case 3:
2710 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2711 tcg_temp_free_i32(tmp);
2712 return 1;
2714 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2715 break;
2717 tcg_temp_free_i32(tmp);
2718 gen_op_iwmmxt_movq_wRn_M0(wrd);
2719 gen_op_iwmmxt_set_mup();
2720 gen_op_iwmmxt_set_cup();
2721 break;
2722 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2723 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2724 wrd = (insn >> 12) & 0xf;
2725 rd0 = (insn >> 16) & 0xf;
2726 rd1 = (insn >> 0) & 0xf;
2727 gen_op_iwmmxt_movq_M0_wRn(rd0);
2728 switch ((insn >> 22) & 3) {
2729 case 0:
2730 if (insn & (1 << 21))
2731 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2732 else
2733 gen_op_iwmmxt_minub_M0_wRn(rd1);
2734 break;
2735 case 1:
2736 if (insn & (1 << 21))
2737 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2738 else
2739 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2740 break;
2741 case 2:
2742 if (insn & (1 << 21))
2743 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2744 else
2745 gen_op_iwmmxt_minul_M0_wRn(rd1);
2746 break;
2747 case 3:
2748 return 1;
2750 gen_op_iwmmxt_movq_wRn_M0(wrd);
2751 gen_op_iwmmxt_set_mup();
2752 break;
2753 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2754 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2755 wrd = (insn >> 12) & 0xf;
2756 rd0 = (insn >> 16) & 0xf;
2757 rd1 = (insn >> 0) & 0xf;
2758 gen_op_iwmmxt_movq_M0_wRn(rd0);
2759 switch ((insn >> 22) & 3) {
2760 case 0:
2761 if (insn & (1 << 21))
2762 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2763 else
2764 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2765 break;
2766 case 1:
2767 if (insn & (1 << 21))
2768 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2769 else
2770 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2771 break;
2772 case 2:
2773 if (insn & (1 << 21))
2774 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2775 else
2776 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2777 break;
2778 case 3:
2779 return 1;
2781 gen_op_iwmmxt_movq_wRn_M0(wrd);
2782 gen_op_iwmmxt_set_mup();
2783 break;
2784 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2785 case 0x402: case 0x502: case 0x602: case 0x702:
2786 wrd = (insn >> 12) & 0xf;
2787 rd0 = (insn >> 16) & 0xf;
2788 rd1 = (insn >> 0) & 0xf;
2789 gen_op_iwmmxt_movq_M0_wRn(rd0);
2790 tmp = tcg_const_i32((insn >> 20) & 3);
2791 iwmmxt_load_reg(cpu_V1, rd1);
2792 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2793 tcg_temp_free_i32(tmp);
2794 gen_op_iwmmxt_movq_wRn_M0(wrd);
2795 gen_op_iwmmxt_set_mup();
2796 break;
2797 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2798 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2799 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2800 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2801 wrd = (insn >> 12) & 0xf;
2802 rd0 = (insn >> 16) & 0xf;
2803 rd1 = (insn >> 0) & 0xf;
2804 gen_op_iwmmxt_movq_M0_wRn(rd0);
2805 switch ((insn >> 20) & 0xf) {
2806 case 0x0:
2807 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2808 break;
2809 case 0x1:
2810 gen_op_iwmmxt_subub_M0_wRn(rd1);
2811 break;
2812 case 0x3:
2813 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2814 break;
2815 case 0x4:
2816 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2817 break;
2818 case 0x5:
2819 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2820 break;
2821 case 0x7:
2822 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2823 break;
2824 case 0x8:
2825 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2826 break;
2827 case 0x9:
2828 gen_op_iwmmxt_subul_M0_wRn(rd1);
2829 break;
2830 case 0xb:
2831 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2832 break;
2833 default:
2834 return 1;
2836 gen_op_iwmmxt_movq_wRn_M0(wrd);
2837 gen_op_iwmmxt_set_mup();
2838 gen_op_iwmmxt_set_cup();
2839 break;
2840 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2841 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2842 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2843 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2844 wrd = (insn >> 12) & 0xf;
2845 rd0 = (insn >> 16) & 0xf;
2846 gen_op_iwmmxt_movq_M0_wRn(rd0);
2847 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2848 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2849 tcg_temp_free_i32(tmp);
2850 gen_op_iwmmxt_movq_wRn_M0(wrd);
2851 gen_op_iwmmxt_set_mup();
2852 gen_op_iwmmxt_set_cup();
2853 break;
2854 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2855 case 0x418: case 0x518: case 0x618: case 0x718:
2856 case 0x818: case 0x918: case 0xa18: case 0xb18:
2857 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2858 wrd = (insn >> 12) & 0xf;
2859 rd0 = (insn >> 16) & 0xf;
2860 rd1 = (insn >> 0) & 0xf;
2861 gen_op_iwmmxt_movq_M0_wRn(rd0);
2862 switch ((insn >> 20) & 0xf) {
2863 case 0x0:
2864 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2865 break;
2866 case 0x1:
2867 gen_op_iwmmxt_addub_M0_wRn(rd1);
2868 break;
2869 case 0x3:
2870 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2871 break;
2872 case 0x4:
2873 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2874 break;
2875 case 0x5:
2876 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2877 break;
2878 case 0x7:
2879 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2880 break;
2881 case 0x8:
2882 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2883 break;
2884 case 0x9:
2885 gen_op_iwmmxt_addul_M0_wRn(rd1);
2886 break;
2887 case 0xb:
2888 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2889 break;
2890 default:
2891 return 1;
2893 gen_op_iwmmxt_movq_wRn_M0(wrd);
2894 gen_op_iwmmxt_set_mup();
2895 gen_op_iwmmxt_set_cup();
2896 break;
2897 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2898 case 0x408: case 0x508: case 0x608: case 0x708:
2899 case 0x808: case 0x908: case 0xa08: case 0xb08:
2900 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2901 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2902 return 1;
2903 wrd = (insn >> 12) & 0xf;
2904 rd0 = (insn >> 16) & 0xf;
2905 rd1 = (insn >> 0) & 0xf;
2906 gen_op_iwmmxt_movq_M0_wRn(rd0);
2907 switch ((insn >> 22) & 3) {
2908 case 1:
2909 if (insn & (1 << 21))
2910 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2911 else
2912 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2913 break;
2914 case 2:
2915 if (insn & (1 << 21))
2916 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2917 else
2918 gen_op_iwmmxt_packul_M0_wRn(rd1);
2919 break;
2920 case 3:
2921 if (insn & (1 << 21))
2922 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2923 else
2924 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2925 break;
2927 gen_op_iwmmxt_movq_wRn_M0(wrd);
2928 gen_op_iwmmxt_set_mup();
2929 gen_op_iwmmxt_set_cup();
2930 break;
2931 case 0x201: case 0x203: case 0x205: case 0x207:
2932 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2933 case 0x211: case 0x213: case 0x215: case 0x217:
2934 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2935 wrd = (insn >> 5) & 0xf;
2936 rd0 = (insn >> 12) & 0xf;
2937 rd1 = (insn >> 0) & 0xf;
2938 if (rd0 == 0xf || rd1 == 0xf)
2939 return 1;
2940 gen_op_iwmmxt_movq_M0_wRn(wrd);
2941 tmp = load_reg(s, rd0);
2942 tmp2 = load_reg(s, rd1);
2943 switch ((insn >> 16) & 0xf) {
2944 case 0x0: /* TMIA */
2945 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2946 break;
2947 case 0x8: /* TMIAPH */
2948 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2949 break;
2950 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2951 if (insn & (1 << 16))
2952 tcg_gen_shri_i32(tmp, tmp, 16);
2953 if (insn & (1 << 17))
2954 tcg_gen_shri_i32(tmp2, tmp2, 16);
2955 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2956 break;
2957 default:
2958 tcg_temp_free_i32(tmp2);
2959 tcg_temp_free_i32(tmp);
2960 return 1;
2962 tcg_temp_free_i32(tmp2);
2963 tcg_temp_free_i32(tmp);
2964 gen_op_iwmmxt_movq_wRn_M0(wrd);
2965 gen_op_iwmmxt_set_mup();
2966 break;
2967 default:
2968 return 1;
2971 return 0;
2974 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
2975 (ie. an undefined instruction). */
2976 static int disas_dsp_insn(DisasContext *s, uint32_t insn)
2978 int acc, rd0, rd1, rdhi, rdlo;
2979 TCGv_i32 tmp, tmp2;
2981 if ((insn & 0x0ff00f10) == 0x0e200010) {
2982 /* Multiply with Internal Accumulate Format */
2983 rd0 = (insn >> 12) & 0xf;
2984 rd1 = insn & 0xf;
2985 acc = (insn >> 5) & 7;
2987 if (acc != 0)
2988 return 1;
2990 tmp = load_reg(s, rd0);
2991 tmp2 = load_reg(s, rd1);
2992 switch ((insn >> 16) & 0xf) {
2993 case 0x0: /* MIA */
2994 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2995 break;
2996 case 0x8: /* MIAPH */
2997 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2998 break;
2999 case 0xc: /* MIABB */
3000 case 0xd: /* MIABT */
3001 case 0xe: /* MIATB */
3002 case 0xf: /* MIATT */
3003 if (insn & (1 << 16))
3004 tcg_gen_shri_i32(tmp, tmp, 16);
3005 if (insn & (1 << 17))
3006 tcg_gen_shri_i32(tmp2, tmp2, 16);
3007 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
3008 break;
3009 default:
3010 return 1;
3012 tcg_temp_free_i32(tmp2);
3013 tcg_temp_free_i32(tmp);
3015 gen_op_iwmmxt_movq_wRn_M0(acc);
3016 return 0;
3019 if ((insn & 0x0fe00ff8) == 0x0c400000) {
3020 /* Internal Accumulator Access Format */
3021 rdhi = (insn >> 16) & 0xf;
3022 rdlo = (insn >> 12) & 0xf;
3023 acc = insn & 7;
3025 if (acc != 0)
3026 return 1;
3028 if (insn & ARM_CP_RW_BIT) { /* MRA */
3029 iwmmxt_load_reg(cpu_V0, acc);
3030 tcg_gen_extrl_i64_i32(cpu_R[rdlo], cpu_V0);
3031 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
3032 tcg_gen_extrl_i64_i32(cpu_R[rdhi], cpu_V0);
3033 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
3034 } else { /* MAR */
3035 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
3036 iwmmxt_store_reg(cpu_V0, acc);
3038 return 0;
3041 return 1;
3044 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
3045 #define VFP_SREG(insn, bigbit, smallbit) \
3046 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
3047 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
3048 if (arm_dc_feature(s, ARM_FEATURE_VFP3)) { \
3049 reg = (((insn) >> (bigbit)) & 0x0f) \
3050 | (((insn) >> ((smallbit) - 4)) & 0x10); \
3051 } else { \
3052 if (insn & (1 << (smallbit))) \
3053 return 1; \
3054 reg = ((insn) >> (bigbit)) & 0x0f; \
3055 }} while (0)
3057 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
3058 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
3059 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
3060 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
3061 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
3062 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
3064 /* Move between integer and VFP cores. */
3065 static TCGv_i32 gen_vfp_mrs(void)
3067 TCGv_i32 tmp = tcg_temp_new_i32();
3068 tcg_gen_mov_i32(tmp, cpu_F0s);
3069 return tmp;
3072 static void gen_vfp_msr(TCGv_i32 tmp)
3074 tcg_gen_mov_i32(cpu_F0s, tmp);
3075 tcg_temp_free_i32(tmp);
3078 static void gen_neon_dup_low16(TCGv_i32 var)
3080 TCGv_i32 tmp = tcg_temp_new_i32();
3081 tcg_gen_ext16u_i32(var, var);
3082 tcg_gen_shli_i32(tmp, var, 16);
3083 tcg_gen_or_i32(var, var, tmp);
3084 tcg_temp_free_i32(tmp);
3087 static void gen_neon_dup_high16(TCGv_i32 var)
3089 TCGv_i32 tmp = tcg_temp_new_i32();
3090 tcg_gen_andi_i32(var, var, 0xffff0000);
3091 tcg_gen_shri_i32(tmp, var, 16);
3092 tcg_gen_or_i32(var, var, tmp);
3093 tcg_temp_free_i32(tmp);
3096 static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
3097 uint32_t dp)
3099 uint32_t cc = extract32(insn, 20, 2);
3101 if (dp) {
3102 TCGv_i64 frn, frm, dest;
3103 TCGv_i64 tmp, zero, zf, nf, vf;
3105 zero = tcg_const_i64(0);
3107 frn = tcg_temp_new_i64();
3108 frm = tcg_temp_new_i64();
3109 dest = tcg_temp_new_i64();
3111 zf = tcg_temp_new_i64();
3112 nf = tcg_temp_new_i64();
3113 vf = tcg_temp_new_i64();
3115 tcg_gen_extu_i32_i64(zf, cpu_ZF);
3116 tcg_gen_ext_i32_i64(nf, cpu_NF);
3117 tcg_gen_ext_i32_i64(vf, cpu_VF);
3119 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
3120 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
3121 switch (cc) {
3122 case 0: /* eq: Z */
3123 tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero,
3124 frn, frm);
3125 break;
3126 case 1: /* vs: V */
3127 tcg_gen_movcond_i64(TCG_COND_LT, dest, vf, zero,
3128 frn, frm);
3129 break;
3130 case 2: /* ge: N == V -> N ^ V == 0 */
3131 tmp = tcg_temp_new_i64();
3132 tcg_gen_xor_i64(tmp, vf, nf);
3133 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
3134 frn, frm);
3135 tcg_temp_free_i64(tmp);
3136 break;
3137 case 3: /* gt: !Z && N == V */
3138 tcg_gen_movcond_i64(TCG_COND_NE, dest, zf, zero,
3139 frn, frm);
3140 tmp = tcg_temp_new_i64();
3141 tcg_gen_xor_i64(tmp, vf, nf);
3142 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
3143 dest, frm);
3144 tcg_temp_free_i64(tmp);
3145 break;
3147 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
3148 tcg_temp_free_i64(frn);
3149 tcg_temp_free_i64(frm);
3150 tcg_temp_free_i64(dest);
3152 tcg_temp_free_i64(zf);
3153 tcg_temp_free_i64(nf);
3154 tcg_temp_free_i64(vf);
3156 tcg_temp_free_i64(zero);
3157 } else {
3158 TCGv_i32 frn, frm, dest;
3159 TCGv_i32 tmp, zero;
3161 zero = tcg_const_i32(0);
3163 frn = tcg_temp_new_i32();
3164 frm = tcg_temp_new_i32();
3165 dest = tcg_temp_new_i32();
3166 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
3167 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
3168 switch (cc) {
3169 case 0: /* eq: Z */
3170 tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero,
3171 frn, frm);
3172 break;
3173 case 1: /* vs: V */
3174 tcg_gen_movcond_i32(TCG_COND_LT, dest, cpu_VF, zero,
3175 frn, frm);
3176 break;
3177 case 2: /* ge: N == V -> N ^ V == 0 */
3178 tmp = tcg_temp_new_i32();
3179 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
3180 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
3181 frn, frm);
3182 tcg_temp_free_i32(tmp);
3183 break;
3184 case 3: /* gt: !Z && N == V */
3185 tcg_gen_movcond_i32(TCG_COND_NE, dest, cpu_ZF, zero,
3186 frn, frm);
3187 tmp = tcg_temp_new_i32();
3188 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
3189 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
3190 dest, frm);
3191 tcg_temp_free_i32(tmp);
3192 break;
3194 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
3195 tcg_temp_free_i32(frn);
3196 tcg_temp_free_i32(frm);
3197 tcg_temp_free_i32(dest);
3199 tcg_temp_free_i32(zero);
3202 return 0;
3205 static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn,
3206 uint32_t rm, uint32_t dp)
3208 uint32_t vmin = extract32(insn, 6, 1);
3209 TCGv_ptr fpst = get_fpstatus_ptr(0);
3211 if (dp) {
3212 TCGv_i64 frn, frm, dest;
3214 frn = tcg_temp_new_i64();
3215 frm = tcg_temp_new_i64();
3216 dest = tcg_temp_new_i64();
3218 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
3219 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
3220 if (vmin) {
3221 gen_helper_vfp_minnumd(dest, frn, frm, fpst);
3222 } else {
3223 gen_helper_vfp_maxnumd(dest, frn, frm, fpst);
3225 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
3226 tcg_temp_free_i64(frn);
3227 tcg_temp_free_i64(frm);
3228 tcg_temp_free_i64(dest);
3229 } else {
3230 TCGv_i32 frn, frm, dest;
3232 frn = tcg_temp_new_i32();
3233 frm = tcg_temp_new_i32();
3234 dest = tcg_temp_new_i32();
3236 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
3237 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
3238 if (vmin) {
3239 gen_helper_vfp_minnums(dest, frn, frm, fpst);
3240 } else {
3241 gen_helper_vfp_maxnums(dest, frn, frm, fpst);
3243 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
3244 tcg_temp_free_i32(frn);
3245 tcg_temp_free_i32(frm);
3246 tcg_temp_free_i32(dest);
3249 tcg_temp_free_ptr(fpst);
3250 return 0;
3253 static int handle_vrint(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
3254 int rounding)
3256 TCGv_ptr fpst = get_fpstatus_ptr(0);
3257 TCGv_i32 tcg_rmode;
3259 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
3260 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
3262 if (dp) {
3263 TCGv_i64 tcg_op;
3264 TCGv_i64 tcg_res;
3265 tcg_op = tcg_temp_new_i64();
3266 tcg_res = tcg_temp_new_i64();
3267 tcg_gen_ld_f64(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
3268 gen_helper_rintd(tcg_res, tcg_op, fpst);
3269 tcg_gen_st_f64(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
3270 tcg_temp_free_i64(tcg_op);
3271 tcg_temp_free_i64(tcg_res);
3272 } else {
3273 TCGv_i32 tcg_op;
3274 TCGv_i32 tcg_res;
3275 tcg_op = tcg_temp_new_i32();
3276 tcg_res = tcg_temp_new_i32();
3277 tcg_gen_ld_f32(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
3278 gen_helper_rints(tcg_res, tcg_op, fpst);
3279 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
3280 tcg_temp_free_i32(tcg_op);
3281 tcg_temp_free_i32(tcg_res);
3284 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
3285 tcg_temp_free_i32(tcg_rmode);
3287 tcg_temp_free_ptr(fpst);
3288 return 0;
3291 static int handle_vcvt(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
3292 int rounding)
3294 bool is_signed = extract32(insn, 7, 1);
3295 TCGv_ptr fpst = get_fpstatus_ptr(0);
3296 TCGv_i32 tcg_rmode, tcg_shift;
3298 tcg_shift = tcg_const_i32(0);
3300 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
3301 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
3303 if (dp) {
3304 TCGv_i64 tcg_double, tcg_res;
3305 TCGv_i32 tcg_tmp;
3306 /* Rd is encoded as a single precision register even when the source
3307 * is double precision.
3309 rd = ((rd << 1) & 0x1e) | ((rd >> 4) & 0x1);
3310 tcg_double = tcg_temp_new_i64();
3311 tcg_res = tcg_temp_new_i64();
3312 tcg_tmp = tcg_temp_new_i32();
3313 tcg_gen_ld_f64(tcg_double, cpu_env, vfp_reg_offset(1, rm));
3314 if (is_signed) {
3315 gen_helper_vfp_tosld(tcg_res, tcg_double, tcg_shift, fpst);
3316 } else {
3317 gen_helper_vfp_tould(tcg_res, tcg_double, tcg_shift, fpst);
3319 tcg_gen_extrl_i64_i32(tcg_tmp, tcg_res);
3320 tcg_gen_st_f32(tcg_tmp, cpu_env, vfp_reg_offset(0, rd));
3321 tcg_temp_free_i32(tcg_tmp);
3322 tcg_temp_free_i64(tcg_res);
3323 tcg_temp_free_i64(tcg_double);
3324 } else {
3325 TCGv_i32 tcg_single, tcg_res;
3326 tcg_single = tcg_temp_new_i32();
3327 tcg_res = tcg_temp_new_i32();
3328 tcg_gen_ld_f32(tcg_single, cpu_env, vfp_reg_offset(0, rm));
3329 if (is_signed) {
3330 gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst);
3331 } else {
3332 gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst);
3334 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(0, rd));
3335 tcg_temp_free_i32(tcg_res);
3336 tcg_temp_free_i32(tcg_single);
3339 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
3340 tcg_temp_free_i32(tcg_rmode);
3342 tcg_temp_free_i32(tcg_shift);
3344 tcg_temp_free_ptr(fpst);
3346 return 0;
3349 /* Table for converting the most common AArch32 encoding of
3350 * rounding mode to arm_fprounding order (which matches the
3351 * common AArch64 order); see ARM ARM pseudocode FPDecodeRM().
3353 static const uint8_t fp_decode_rm[] = {
3354 FPROUNDING_TIEAWAY,
3355 FPROUNDING_TIEEVEN,
3356 FPROUNDING_POSINF,
3357 FPROUNDING_NEGINF,
3360 static int disas_vfp_misc_insn(DisasContext *s, uint32_t insn)
3362 uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
3364 if (dp) {
3365 VFP_DREG_D(rd, insn);
3366 VFP_DREG_N(rn, insn);
3367 VFP_DREG_M(rm, insn);
3368 } else {
3369 rd = VFP_SREG_D(insn);
3370 rn = VFP_SREG_N(insn);
3371 rm = VFP_SREG_M(insn);
3374 if ((insn & 0x0f800e50) == 0x0e000a00 && dc_isar_feature(aa32_vsel, s)) {
3375 return handle_vsel(insn, rd, rn, rm, dp);
3376 } else if ((insn & 0x0fb00e10) == 0x0e800a00 &&
3377 dc_isar_feature(aa32_vminmaxnm, s)) {
3378 return handle_vminmaxnm(insn, rd, rn, rm, dp);
3379 } else if ((insn & 0x0fbc0ed0) == 0x0eb80a40 &&
3380 dc_isar_feature(aa32_vrint, s)) {
3381 /* VRINTA, VRINTN, VRINTP, VRINTM */
3382 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
3383 return handle_vrint(insn, rd, rm, dp, rounding);
3384 } else if ((insn & 0x0fbc0e50) == 0x0ebc0a40 &&
3385 dc_isar_feature(aa32_vcvt_dr, s)) {
3386 /* VCVTA, VCVTN, VCVTP, VCVTM */
3387 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
3388 return handle_vcvt(insn, rd, rm, dp, rounding);
3390 return 1;
3393 /* Disassemble a VFP instruction. Returns nonzero if an error occurred
3394 (ie. an undefined instruction). */
3395 static int disas_vfp_insn(DisasContext *s, uint32_t insn)
3397 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
3398 int dp, veclen;
3399 TCGv_i32 addr;
3400 TCGv_i32 tmp;
3401 TCGv_i32 tmp2;
3403 if (!arm_dc_feature(s, ARM_FEATURE_VFP)) {
3404 return 1;
3407 /* FIXME: this access check should not take precedence over UNDEF
3408 * for invalid encodings; we will generate incorrect syndrome information
3409 * for attempts to execute invalid vfp/neon encodings with FP disabled.
3411 if (s->fp_excp_el) {
3412 gen_exception_insn(s, 4, EXCP_UDEF,
3413 syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
3414 return 0;
3417 if (!s->vfp_enabled) {
3418 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
3419 if ((insn & 0x0fe00fff) != 0x0ee00a10)
3420 return 1;
3421 rn = (insn >> 16) & 0xf;
3422 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC && rn != ARM_VFP_MVFR2
3423 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0) {
3424 return 1;
3428 if (extract32(insn, 28, 4) == 0xf) {
3430 * Encodings with T=1 (Thumb) or unconditional (ARM):
3431 * only used for the "miscellaneous VFP features" added in v8A
3432 * and v7M (and gated on the MVFR2.FPMisc field).
3434 return disas_vfp_misc_insn(s, insn);
3437 dp = ((insn & 0xf00) == 0xb00);
3438 switch ((insn >> 24) & 0xf) {
3439 case 0xe:
3440 if (insn & (1 << 4)) {
3441 /* single register transfer */
3442 rd = (insn >> 12) & 0xf;
3443 if (dp) {
3444 int size;
3445 int pass;
3447 VFP_DREG_N(rn, insn);
3448 if (insn & 0xf)
3449 return 1;
3450 if (insn & 0x00c00060
3451 && !arm_dc_feature(s, ARM_FEATURE_NEON)) {
3452 return 1;
3455 pass = (insn >> 21) & 1;
3456 if (insn & (1 << 22)) {
3457 size = 0;
3458 offset = ((insn >> 5) & 3) * 8;
3459 } else if (insn & (1 << 5)) {
3460 size = 1;
3461 offset = (insn & (1 << 6)) ? 16 : 0;
3462 } else {
3463 size = 2;
3464 offset = 0;
3466 if (insn & ARM_CP_RW_BIT) {
3467 /* vfp->arm */
3468 tmp = neon_load_reg(rn, pass);
3469 switch (size) {
3470 case 0:
3471 if (offset)
3472 tcg_gen_shri_i32(tmp, tmp, offset);
3473 if (insn & (1 << 23))
3474 gen_uxtb(tmp);
3475 else
3476 gen_sxtb(tmp);
3477 break;
3478 case 1:
3479 if (insn & (1 << 23)) {
3480 if (offset) {
3481 tcg_gen_shri_i32(tmp, tmp, 16);
3482 } else {
3483 gen_uxth(tmp);
3485 } else {
3486 if (offset) {
3487 tcg_gen_sari_i32(tmp, tmp, 16);
3488 } else {
3489 gen_sxth(tmp);
3492 break;
3493 case 2:
3494 break;
3496 store_reg(s, rd, tmp);
3497 } else {
3498 /* arm->vfp */
3499 tmp = load_reg(s, rd);
3500 if (insn & (1 << 23)) {
3501 /* VDUP */
3502 int vec_size = pass ? 16 : 8;
3503 tcg_gen_gvec_dup_i32(size, neon_reg_offset(rn, 0),
3504 vec_size, vec_size, tmp);
3505 tcg_temp_free_i32(tmp);
3506 } else {
3507 /* VMOV */
3508 switch (size) {
3509 case 0:
3510 tmp2 = neon_load_reg(rn, pass);
3511 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 8);
3512 tcg_temp_free_i32(tmp2);
3513 break;
3514 case 1:
3515 tmp2 = neon_load_reg(rn, pass);
3516 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 16);
3517 tcg_temp_free_i32(tmp2);
3518 break;
3519 case 2:
3520 break;
3522 neon_store_reg(rn, pass, tmp);
3525 } else { /* !dp */
3526 if ((insn & 0x6f) != 0x00)
3527 return 1;
3528 rn = VFP_SREG_N(insn);
3529 if (insn & ARM_CP_RW_BIT) {
3530 /* vfp->arm */
3531 if (insn & (1 << 21)) {
3532 /* system register */
3533 rn >>= 1;
3535 switch (rn) {
3536 case ARM_VFP_FPSID:
3537 /* VFP2 allows access to FSID from userspace.
3538 VFP3 restricts all id registers to privileged
3539 accesses. */
3540 if (IS_USER(s)
3541 && arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3542 return 1;
3544 tmp = load_cpu_field(vfp.xregs[rn]);
3545 break;
3546 case ARM_VFP_FPEXC:
3547 if (IS_USER(s))
3548 return 1;
3549 tmp = load_cpu_field(vfp.xregs[rn]);
3550 break;
3551 case ARM_VFP_FPINST:
3552 case ARM_VFP_FPINST2:
3553 /* Not present in VFP3. */
3554 if (IS_USER(s)
3555 || arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3556 return 1;
3558 tmp = load_cpu_field(vfp.xregs[rn]);
3559 break;
3560 case ARM_VFP_FPSCR:
3561 if (rd == 15) {
3562 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
3563 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
3564 } else {
3565 tmp = tcg_temp_new_i32();
3566 gen_helper_vfp_get_fpscr(tmp, cpu_env);
3568 break;
3569 case ARM_VFP_MVFR2:
3570 if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
3571 return 1;
3573 /* fall through */
3574 case ARM_VFP_MVFR0:
3575 case ARM_VFP_MVFR1:
3576 if (IS_USER(s)
3577 || !arm_dc_feature(s, ARM_FEATURE_MVFR)) {
3578 return 1;
3580 tmp = load_cpu_field(vfp.xregs[rn]);
3581 break;
3582 default:
3583 return 1;
3585 } else {
3586 gen_mov_F0_vreg(0, rn);
3587 tmp = gen_vfp_mrs();
3589 if (rd == 15) {
3590 /* Set the 4 flag bits in the CPSR. */
3591 gen_set_nzcv(tmp);
3592 tcg_temp_free_i32(tmp);
3593 } else {
3594 store_reg(s, rd, tmp);
3596 } else {
3597 /* arm->vfp */
3598 if (insn & (1 << 21)) {
3599 rn >>= 1;
3600 /* system register */
3601 switch (rn) {
3602 case ARM_VFP_FPSID:
3603 case ARM_VFP_MVFR0:
3604 case ARM_VFP_MVFR1:
3605 /* Writes are ignored. */
3606 break;
3607 case ARM_VFP_FPSCR:
3608 tmp = load_reg(s, rd);
3609 gen_helper_vfp_set_fpscr(cpu_env, tmp);
3610 tcg_temp_free_i32(tmp);
3611 gen_lookup_tb(s);
3612 break;
3613 case ARM_VFP_FPEXC:
3614 if (IS_USER(s))
3615 return 1;
3616 /* TODO: VFP subarchitecture support.
3617 * For now, keep the EN bit only */
3618 tmp = load_reg(s, rd);
3619 tcg_gen_andi_i32(tmp, tmp, 1 << 30);
3620 store_cpu_field(tmp, vfp.xregs[rn]);
3621 gen_lookup_tb(s);
3622 break;
3623 case ARM_VFP_FPINST:
3624 case ARM_VFP_FPINST2:
3625 if (IS_USER(s)) {
3626 return 1;
3628 tmp = load_reg(s, rd);
3629 store_cpu_field(tmp, vfp.xregs[rn]);
3630 break;
3631 default:
3632 return 1;
3634 } else {
3635 tmp = load_reg(s, rd);
3636 gen_vfp_msr(tmp);
3637 gen_mov_vreg_F0(0, rn);
3641 } else {
3642 /* data processing */
3643 bool rd_is_dp = dp;
3644 bool rm_is_dp = dp;
3645 bool no_output = false;
3647 /* The opcode is in bits 23, 21, 20 and 6. */
3648 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
3649 rn = VFP_SREG_N(insn);
3651 if (op == 15) {
3652 /* rn is opcode, encoded as per VFP_SREG_N. */
3653 switch (rn) {
3654 case 0x00: /* vmov */
3655 case 0x01: /* vabs */
3656 case 0x02: /* vneg */
3657 case 0x03: /* vsqrt */
3658 break;
3660 case 0x04: /* vcvtb.f64.f16, vcvtb.f32.f16 */
3661 case 0x05: /* vcvtt.f64.f16, vcvtt.f32.f16 */
3663 * VCVTB, VCVTT: only present with the halfprec extension
3664 * UNPREDICTABLE if bit 8 is set prior to ARMv8
3665 * (we choose to UNDEF)
3667 if (dp) {
3668 if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
3669 return 1;
3671 } else {
3672 if (!dc_isar_feature(aa32_fp16_spconv, s)) {
3673 return 1;
3676 rm_is_dp = false;
3677 break;
3678 case 0x06: /* vcvtb.f16.f32, vcvtb.f16.f64 */
3679 case 0x07: /* vcvtt.f16.f32, vcvtt.f16.f64 */
3680 if (dp) {
3681 if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
3682 return 1;
3684 } else {
3685 if (!dc_isar_feature(aa32_fp16_spconv, s)) {
3686 return 1;
3689 rd_is_dp = false;
3690 break;
3692 case 0x08: case 0x0a: /* vcmp, vcmpz */
3693 case 0x09: case 0x0b: /* vcmpe, vcmpez */
3694 no_output = true;
3695 break;
3697 case 0x0c: /* vrintr */
3698 case 0x0d: /* vrintz */
3699 case 0x0e: /* vrintx */
3700 break;
3702 case 0x0f: /* vcvt double<->single */
3703 rd_is_dp = !dp;
3704 break;
3706 case 0x10: /* vcvt.fxx.u32 */
3707 case 0x11: /* vcvt.fxx.s32 */
3708 rm_is_dp = false;
3709 break;
3710 case 0x18: /* vcvtr.u32.fxx */
3711 case 0x19: /* vcvtz.u32.fxx */
3712 case 0x1a: /* vcvtr.s32.fxx */
3713 case 0x1b: /* vcvtz.s32.fxx */
3714 rd_is_dp = false;
3715 break;
3717 case 0x14: /* vcvt fp <-> fixed */
3718 case 0x15:
3719 case 0x16:
3720 case 0x17:
3721 case 0x1c:
3722 case 0x1d:
3723 case 0x1e:
3724 case 0x1f:
3725 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3726 return 1;
3728 /* Immediate frac_bits has same format as SREG_M. */
3729 rm_is_dp = false;
3730 break;
3732 case 0x13: /* vjcvt */
3733 if (!dp || !dc_isar_feature(aa32_jscvt, s)) {
3734 return 1;
3736 rd_is_dp = false;
3737 break;
3739 default:
3740 return 1;
3742 } else if (dp) {
3743 /* rn is register number */
3744 VFP_DREG_N(rn, insn);
3747 if (rd_is_dp) {
3748 VFP_DREG_D(rd, insn);
3749 } else {
3750 rd = VFP_SREG_D(insn);
3752 if (rm_is_dp) {
3753 VFP_DREG_M(rm, insn);
3754 } else {
3755 rm = VFP_SREG_M(insn);
3758 veclen = s->vec_len;
3759 if (op == 15 && rn > 3) {
3760 veclen = 0;
3763 /* Shut up compiler warnings. */
3764 delta_m = 0;
3765 delta_d = 0;
3766 bank_mask = 0;
3768 if (veclen > 0) {
3769 if (dp)
3770 bank_mask = 0xc;
3771 else
3772 bank_mask = 0x18;
3774 /* Figure out what type of vector operation this is. */
3775 if ((rd & bank_mask) == 0) {
3776 /* scalar */
3777 veclen = 0;
3778 } else {
3779 if (dp)
3780 delta_d = (s->vec_stride >> 1) + 1;
3781 else
3782 delta_d = s->vec_stride + 1;
3784 if ((rm & bank_mask) == 0) {
3785 /* mixed scalar/vector */
3786 delta_m = 0;
3787 } else {
3788 /* vector */
3789 delta_m = delta_d;
3794 /* Load the initial operands. */
3795 if (op == 15) {
3796 switch (rn) {
3797 case 0x08: case 0x09: /* Compare */
3798 gen_mov_F0_vreg(dp, rd);
3799 gen_mov_F1_vreg(dp, rm);
3800 break;
3801 case 0x0a: case 0x0b: /* Compare with zero */
3802 gen_mov_F0_vreg(dp, rd);
3803 gen_vfp_F1_ld0(dp);
3804 break;
3805 case 0x14: /* vcvt fp <-> fixed */
3806 case 0x15:
3807 case 0x16:
3808 case 0x17:
3809 case 0x1c:
3810 case 0x1d:
3811 case 0x1e:
3812 case 0x1f:
3813 /* Source and destination the same. */
3814 gen_mov_F0_vreg(dp, rd);
3815 break;
3816 default:
3817 /* One source operand. */
3818 gen_mov_F0_vreg(rm_is_dp, rm);
3819 break;
3821 } else {
3822 /* Two source operands. */
3823 gen_mov_F0_vreg(dp, rn);
3824 gen_mov_F1_vreg(dp, rm);
3827 for (;;) {
3828 /* Perform the calculation. */
3829 switch (op) {
3830 case 0: /* VMLA: fd + (fn * fm) */
3831 /* Note that order of inputs to the add matters for NaNs */
3832 gen_vfp_F1_mul(dp);
3833 gen_mov_F0_vreg(dp, rd);
3834 gen_vfp_add(dp);
3835 break;
3836 case 1: /* VMLS: fd + -(fn * fm) */
3837 gen_vfp_mul(dp);
3838 gen_vfp_F1_neg(dp);
3839 gen_mov_F0_vreg(dp, rd);
3840 gen_vfp_add(dp);
3841 break;
3842 case 2: /* VNMLS: -fd + (fn * fm) */
3843 /* Note that it isn't valid to replace (-A + B) with (B - A)
3844 * or similar plausible looking simplifications
3845 * because this will give wrong results for NaNs.
3847 gen_vfp_F1_mul(dp);
3848 gen_mov_F0_vreg(dp, rd);
3849 gen_vfp_neg(dp);
3850 gen_vfp_add(dp);
3851 break;
3852 case 3: /* VNMLA: -fd + -(fn * fm) */
3853 gen_vfp_mul(dp);
3854 gen_vfp_F1_neg(dp);
3855 gen_mov_F0_vreg(dp, rd);
3856 gen_vfp_neg(dp);
3857 gen_vfp_add(dp);
3858 break;
3859 case 4: /* mul: fn * fm */
3860 gen_vfp_mul(dp);
3861 break;
3862 case 5: /* nmul: -(fn * fm) */
3863 gen_vfp_mul(dp);
3864 gen_vfp_neg(dp);
3865 break;
3866 case 6: /* add: fn + fm */
3867 gen_vfp_add(dp);
3868 break;
3869 case 7: /* sub: fn - fm */
3870 gen_vfp_sub(dp);
3871 break;
3872 case 8: /* div: fn / fm */
3873 gen_vfp_div(dp);
3874 break;
3875 case 10: /* VFNMA : fd = muladd(-fd, fn, fm) */
3876 case 11: /* VFNMS : fd = muladd(-fd, -fn, fm) */
3877 case 12: /* VFMA : fd = muladd( fd, fn, fm) */
3878 case 13: /* VFMS : fd = muladd( fd, -fn, fm) */
3879 /* These are fused multiply-add, and must be done as one
3880 * floating point operation with no rounding between the
3881 * multiplication and addition steps.
3882 * NB that doing the negations here as separate steps is
3883 * correct : an input NaN should come out with its sign bit
3884 * flipped if it is a negated-input.
3886 if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
3887 return 1;
3889 if (dp) {
3890 TCGv_ptr fpst;
3891 TCGv_i64 frd;
3892 if (op & 1) {
3893 /* VFNMS, VFMS */
3894 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
3896 frd = tcg_temp_new_i64();
3897 tcg_gen_ld_f64(frd, cpu_env, vfp_reg_offset(dp, rd));
3898 if (op & 2) {
3899 /* VFNMA, VFNMS */
3900 gen_helper_vfp_negd(frd, frd);
3902 fpst = get_fpstatus_ptr(0);
3903 gen_helper_vfp_muladdd(cpu_F0d, cpu_F0d,
3904 cpu_F1d, frd, fpst);
3905 tcg_temp_free_ptr(fpst);
3906 tcg_temp_free_i64(frd);
3907 } else {
3908 TCGv_ptr fpst;
3909 TCGv_i32 frd;
3910 if (op & 1) {
3911 /* VFNMS, VFMS */
3912 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
3914 frd = tcg_temp_new_i32();
3915 tcg_gen_ld_f32(frd, cpu_env, vfp_reg_offset(dp, rd));
3916 if (op & 2) {
3917 gen_helper_vfp_negs(frd, frd);
3919 fpst = get_fpstatus_ptr(0);
3920 gen_helper_vfp_muladds(cpu_F0s, cpu_F0s,
3921 cpu_F1s, frd, fpst);
3922 tcg_temp_free_ptr(fpst);
3923 tcg_temp_free_i32(frd);
3925 break;
3926 case 14: /* fconst */
3927 if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
3928 return 1;
3931 n = (insn << 12) & 0x80000000;
3932 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3933 if (dp) {
3934 if (i & 0x40)
3935 i |= 0x3f80;
3936 else
3937 i |= 0x4000;
3938 n |= i << 16;
3939 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3940 } else {
3941 if (i & 0x40)
3942 i |= 0x780;
3943 else
3944 i |= 0x800;
3945 n |= i << 19;
3946 tcg_gen_movi_i32(cpu_F0s, n);
3948 break;
3949 case 15: /* extension space */
3950 switch (rn) {
3951 case 0: /* cpy */
3952 /* no-op */
3953 break;
3954 case 1: /* abs */
3955 gen_vfp_abs(dp);
3956 break;
3957 case 2: /* neg */
3958 gen_vfp_neg(dp);
3959 break;
3960 case 3: /* sqrt */
3961 gen_vfp_sqrt(dp);
3962 break;
3963 case 4: /* vcvtb.f32.f16, vcvtb.f64.f16 */
3965 TCGv_ptr fpst = get_fpstatus_ptr(false);
3966 TCGv_i32 ahp_mode = get_ahp_flag();
3967 tmp = gen_vfp_mrs();
3968 tcg_gen_ext16u_i32(tmp, tmp);
3969 if (dp) {
3970 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
3971 fpst, ahp_mode);
3972 } else {
3973 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
3974 fpst, ahp_mode);
3976 tcg_temp_free_i32(ahp_mode);
3977 tcg_temp_free_ptr(fpst);
3978 tcg_temp_free_i32(tmp);
3979 break;
3981 case 5: /* vcvtt.f32.f16, vcvtt.f64.f16 */
3983 TCGv_ptr fpst = get_fpstatus_ptr(false);
3984 TCGv_i32 ahp = get_ahp_flag();
3985 tmp = gen_vfp_mrs();
3986 tcg_gen_shri_i32(tmp, tmp, 16);
3987 if (dp) {
3988 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
3989 fpst, ahp);
3990 } else {
3991 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
3992 fpst, ahp);
3994 tcg_temp_free_i32(tmp);
3995 tcg_temp_free_i32(ahp);
3996 tcg_temp_free_ptr(fpst);
3997 break;
3999 case 6: /* vcvtb.f16.f32, vcvtb.f16.f64 */
4001 TCGv_ptr fpst = get_fpstatus_ptr(false);
4002 TCGv_i32 ahp = get_ahp_flag();
4003 tmp = tcg_temp_new_i32();
4005 if (dp) {
4006 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
4007 fpst, ahp);
4008 } else {
4009 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
4010 fpst, ahp);
4012 tcg_temp_free_i32(ahp);
4013 tcg_temp_free_ptr(fpst);
4014 gen_mov_F0_vreg(0, rd);
4015 tmp2 = gen_vfp_mrs();
4016 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
4017 tcg_gen_or_i32(tmp, tmp, tmp2);
4018 tcg_temp_free_i32(tmp2);
4019 gen_vfp_msr(tmp);
4020 break;
4022 case 7: /* vcvtt.f16.f32, vcvtt.f16.f64 */
4024 TCGv_ptr fpst = get_fpstatus_ptr(false);
4025 TCGv_i32 ahp = get_ahp_flag();
4026 tmp = tcg_temp_new_i32();
4027 if (dp) {
4028 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
4029 fpst, ahp);
4030 } else {
4031 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
4032 fpst, ahp);
4034 tcg_temp_free_i32(ahp);
4035 tcg_temp_free_ptr(fpst);
4036 tcg_gen_shli_i32(tmp, tmp, 16);
4037 gen_mov_F0_vreg(0, rd);
4038 tmp2 = gen_vfp_mrs();
4039 tcg_gen_ext16u_i32(tmp2, tmp2);
4040 tcg_gen_or_i32(tmp, tmp, tmp2);
4041 tcg_temp_free_i32(tmp2);
4042 gen_vfp_msr(tmp);
4043 break;
4045 case 8: /* cmp */
4046 gen_vfp_cmp(dp);
4047 break;
4048 case 9: /* cmpe */
4049 gen_vfp_cmpe(dp);
4050 break;
4051 case 10: /* cmpz */
4052 gen_vfp_cmp(dp);
4053 break;
4054 case 11: /* cmpez */
4055 gen_vfp_F1_ld0(dp);
4056 gen_vfp_cmpe(dp);
4057 break;
4058 case 12: /* vrintr */
4060 TCGv_ptr fpst = get_fpstatus_ptr(0);
4061 if (dp) {
4062 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
4063 } else {
4064 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
4066 tcg_temp_free_ptr(fpst);
4067 break;
4069 case 13: /* vrintz */
4071 TCGv_ptr fpst = get_fpstatus_ptr(0);
4072 TCGv_i32 tcg_rmode;
4073 tcg_rmode = tcg_const_i32(float_round_to_zero);
4074 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
4075 if (dp) {
4076 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
4077 } else {
4078 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
4080 gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
4081 tcg_temp_free_i32(tcg_rmode);
4082 tcg_temp_free_ptr(fpst);
4083 break;
4085 case 14: /* vrintx */
4087 TCGv_ptr fpst = get_fpstatus_ptr(0);
4088 if (dp) {
4089 gen_helper_rintd_exact(cpu_F0d, cpu_F0d, fpst);
4090 } else {
4091 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpst);
4093 tcg_temp_free_ptr(fpst);
4094 break;
4096 case 15: /* single<->double conversion */
4097 if (dp) {
4098 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
4099 } else {
4100 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
4102 break;
4103 case 16: /* fuito */
4104 gen_vfp_uito(dp, 0);
4105 break;
4106 case 17: /* fsito */
4107 gen_vfp_sito(dp, 0);
4108 break;
4109 case 19: /* vjcvt */
4110 gen_helper_vjcvt(cpu_F0s, cpu_F0d, cpu_env);
4111 break;
4112 case 20: /* fshto */
4113 gen_vfp_shto(dp, 16 - rm, 0);
4114 break;
4115 case 21: /* fslto */
4116 gen_vfp_slto(dp, 32 - rm, 0);
4117 break;
4118 case 22: /* fuhto */
4119 gen_vfp_uhto(dp, 16 - rm, 0);
4120 break;
4121 case 23: /* fulto */
4122 gen_vfp_ulto(dp, 32 - rm, 0);
4123 break;
4124 case 24: /* ftoui */
4125 gen_vfp_toui(dp, 0);
4126 break;
4127 case 25: /* ftouiz */
4128 gen_vfp_touiz(dp, 0);
4129 break;
4130 case 26: /* ftosi */
4131 gen_vfp_tosi(dp, 0);
4132 break;
4133 case 27: /* ftosiz */
4134 gen_vfp_tosiz(dp, 0);
4135 break;
4136 case 28: /* ftosh */
4137 gen_vfp_tosh(dp, 16 - rm, 0);
4138 break;
4139 case 29: /* ftosl */
4140 gen_vfp_tosl(dp, 32 - rm, 0);
4141 break;
4142 case 30: /* ftouh */
4143 gen_vfp_touh(dp, 16 - rm, 0);
4144 break;
4145 case 31: /* ftoul */
4146 gen_vfp_toul(dp, 32 - rm, 0);
4147 break;
4148 default: /* undefined */
4149 g_assert_not_reached();
4151 break;
4152 default: /* undefined */
4153 return 1;
4156 /* Write back the result, if any. */
4157 if (!no_output) {
4158 gen_mov_vreg_F0(rd_is_dp, rd);
4161 /* break out of the loop if we have finished */
4162 if (veclen == 0) {
4163 break;
4166 if (op == 15 && delta_m == 0) {
4167 /* single source one-many */
4168 while (veclen--) {
4169 rd = ((rd + delta_d) & (bank_mask - 1))
4170 | (rd & bank_mask);
4171 gen_mov_vreg_F0(dp, rd);
4173 break;
4175 /* Setup the next operands. */
4176 veclen--;
4177 rd = ((rd + delta_d) & (bank_mask - 1))
4178 | (rd & bank_mask);
4180 if (op == 15) {
4181 /* One source operand. */
4182 rm = ((rm + delta_m) & (bank_mask - 1))
4183 | (rm & bank_mask);
4184 gen_mov_F0_vreg(dp, rm);
4185 } else {
4186 /* Two source operands. */
4187 rn = ((rn + delta_d) & (bank_mask - 1))
4188 | (rn & bank_mask);
4189 gen_mov_F0_vreg(dp, rn);
4190 if (delta_m) {
4191 rm = ((rm + delta_m) & (bank_mask - 1))
4192 | (rm & bank_mask);
4193 gen_mov_F1_vreg(dp, rm);
4198 break;
4199 case 0xc:
4200 case 0xd:
4201 if ((insn & 0x03e00000) == 0x00400000) {
4202 /* two-register transfer */
4203 rn = (insn >> 16) & 0xf;
4204 rd = (insn >> 12) & 0xf;
4205 if (dp) {
4206 VFP_DREG_M(rm, insn);
4207 } else {
4208 rm = VFP_SREG_M(insn);
4211 if (insn & ARM_CP_RW_BIT) {
4212 /* vfp->arm */
4213 if (dp) {
4214 gen_mov_F0_vreg(0, rm * 2);
4215 tmp = gen_vfp_mrs();
4216 store_reg(s, rd, tmp);
4217 gen_mov_F0_vreg(0, rm * 2 + 1);
4218 tmp = gen_vfp_mrs();
4219 store_reg(s, rn, tmp);
4220 } else {
4221 gen_mov_F0_vreg(0, rm);
4222 tmp = gen_vfp_mrs();
4223 store_reg(s, rd, tmp);
4224 gen_mov_F0_vreg(0, rm + 1);
4225 tmp = gen_vfp_mrs();
4226 store_reg(s, rn, tmp);
4228 } else {
4229 /* arm->vfp */
4230 if (dp) {
4231 tmp = load_reg(s, rd);
4232 gen_vfp_msr(tmp);
4233 gen_mov_vreg_F0(0, rm * 2);
4234 tmp = load_reg(s, rn);
4235 gen_vfp_msr(tmp);
4236 gen_mov_vreg_F0(0, rm * 2 + 1);
4237 } else {
4238 tmp = load_reg(s, rd);
4239 gen_vfp_msr(tmp);
4240 gen_mov_vreg_F0(0, rm);
4241 tmp = load_reg(s, rn);
4242 gen_vfp_msr(tmp);
4243 gen_mov_vreg_F0(0, rm + 1);
4246 } else {
4247 /* Load/store */
4248 rn = (insn >> 16) & 0xf;
4249 if (dp)
4250 VFP_DREG_D(rd, insn);
4251 else
4252 rd = VFP_SREG_D(insn);
4253 if ((insn & 0x01200000) == 0x01000000) {
4254 /* Single load/store */
4255 offset = (insn & 0xff) << 2;
4256 if ((insn & (1 << 23)) == 0)
4257 offset = -offset;
4258 if (s->thumb && rn == 15) {
4259 /* This is actually UNPREDICTABLE */
4260 addr = tcg_temp_new_i32();
4261 tcg_gen_movi_i32(addr, s->pc & ~2);
4262 } else {
4263 addr = load_reg(s, rn);
4265 tcg_gen_addi_i32(addr, addr, offset);
4266 if (insn & (1 << 20)) {
4267 gen_vfp_ld(s, dp, addr);
4268 gen_mov_vreg_F0(dp, rd);
4269 } else {
4270 gen_mov_F0_vreg(dp, rd);
4271 gen_vfp_st(s, dp, addr);
4273 tcg_temp_free_i32(addr);
4274 } else {
4275 /* load/store multiple */
4276 int w = insn & (1 << 21);
4277 if (dp)
4278 n = (insn >> 1) & 0x7f;
4279 else
4280 n = insn & 0xff;
4282 if (w && !(((insn >> 23) ^ (insn >> 24)) & 1)) {
4283 /* P == U , W == 1 => UNDEF */
4284 return 1;
4286 if (n == 0 || (rd + n) > 32 || (dp && n > 16)) {
4287 /* UNPREDICTABLE cases for bad immediates: we choose to
4288 * UNDEF to avoid generating huge numbers of TCG ops
4290 return 1;
4292 if (rn == 15 && w) {
4293 /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
4294 return 1;
4297 if (s->thumb && rn == 15) {
4298 /* This is actually UNPREDICTABLE */
4299 addr = tcg_temp_new_i32();
4300 tcg_gen_movi_i32(addr, s->pc & ~2);
4301 } else {
4302 addr = load_reg(s, rn);
4304 if (insn & (1 << 24)) /* pre-decrement */
4305 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
4307 if (s->v8m_stackcheck && rn == 13 && w) {
4309 * Here 'addr' is the lowest address we will store to,
4310 * and is either the old SP (if post-increment) or
4311 * the new SP (if pre-decrement). For post-increment
4312 * where the old value is below the limit and the new
4313 * value is above, it is UNKNOWN whether the limit check
4314 * triggers; we choose to trigger.
4316 gen_helper_v8m_stackcheck(cpu_env, addr);
4319 if (dp)
4320 offset = 8;
4321 else
4322 offset = 4;
4323 for (i = 0; i < n; i++) {
4324 if (insn & ARM_CP_RW_BIT) {
4325 /* load */
4326 gen_vfp_ld(s, dp, addr);
4327 gen_mov_vreg_F0(dp, rd + i);
4328 } else {
4329 /* store */
4330 gen_mov_F0_vreg(dp, rd + i);
4331 gen_vfp_st(s, dp, addr);
4333 tcg_gen_addi_i32(addr, addr, offset);
4335 if (w) {
4336 /* writeback */
4337 if (insn & (1 << 24))
4338 offset = -offset * n;
4339 else if (dp && (insn & 1))
4340 offset = 4;
4341 else
4342 offset = 0;
4344 if (offset != 0)
4345 tcg_gen_addi_i32(addr, addr, offset);
4346 store_reg(s, rn, addr);
4347 } else {
4348 tcg_temp_free_i32(addr);
4352 break;
4353 default:
4354 /* Should never happen. */
4355 return 1;
4357 return 0;
4360 static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
4362 #ifndef CONFIG_USER_ONLY
4363 return (s->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
4364 ((s->pc - 1) & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
4365 #else
4366 return true;
4367 #endif
4370 static void gen_goto_ptr(void)
4372 tcg_gen_lookup_and_goto_ptr();
4375 /* This will end the TB but doesn't guarantee we'll return to
4376 * cpu_loop_exec. Any live exit_requests will be processed as we
4377 * enter the next TB.
4379 static void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
4381 if (use_goto_tb(s, dest)) {
4382 tcg_gen_goto_tb(n);
4383 gen_set_pc_im(s, dest);
4384 tcg_gen_exit_tb(s->base.tb, n);
4385 } else {
4386 gen_set_pc_im(s, dest);
4387 gen_goto_ptr();
4389 s->base.is_jmp = DISAS_NORETURN;
4392 static inline void gen_jmp (DisasContext *s, uint32_t dest)
4394 if (unlikely(is_singlestepping(s))) {
4395 /* An indirect jump so that we still trigger the debug exception. */
4396 if (s->thumb)
4397 dest |= 1;
4398 gen_bx_im(s, dest);
4399 } else {
4400 gen_goto_tb(s, 0, dest);
4404 static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
4406 if (x)
4407 tcg_gen_sari_i32(t0, t0, 16);
4408 else
4409 gen_sxth(t0);
4410 if (y)
4411 tcg_gen_sari_i32(t1, t1, 16);
4412 else
4413 gen_sxth(t1);
4414 tcg_gen_mul_i32(t0, t0, t1);
4417 /* Return the mask of PSR bits set by a MSR instruction. */
4418 static uint32_t msr_mask(DisasContext *s, int flags, int spsr)
4420 uint32_t mask;
4422 mask = 0;
4423 if (flags & (1 << 0))
4424 mask |= 0xff;
4425 if (flags & (1 << 1))
4426 mask |= 0xff00;
4427 if (flags & (1 << 2))
4428 mask |= 0xff0000;
4429 if (flags & (1 << 3))
4430 mask |= 0xff000000;
4432 /* Mask out undefined bits. */
4433 mask &= ~CPSR_RESERVED;
4434 if (!arm_dc_feature(s, ARM_FEATURE_V4T)) {
4435 mask &= ~CPSR_T;
4437 if (!arm_dc_feature(s, ARM_FEATURE_V5)) {
4438 mask &= ~CPSR_Q; /* V5TE in reality*/
4440 if (!arm_dc_feature(s, ARM_FEATURE_V6)) {
4441 mask &= ~(CPSR_E | CPSR_GE);
4443 if (!arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
4444 mask &= ~CPSR_IT;
4446 /* Mask out execution state and reserved bits. */
4447 if (!spsr) {
4448 mask &= ~(CPSR_EXEC | CPSR_RESERVED);
4450 /* Mask out privileged bits. */
4451 if (IS_USER(s))
4452 mask &= CPSR_USER;
4453 return mask;
4456 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
4457 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
4459 TCGv_i32 tmp;
4460 if (spsr) {
4461 /* ??? This is also undefined in system mode. */
4462 if (IS_USER(s))
4463 return 1;
4465 tmp = load_cpu_field(spsr);
4466 tcg_gen_andi_i32(tmp, tmp, ~mask);
4467 tcg_gen_andi_i32(t0, t0, mask);
4468 tcg_gen_or_i32(tmp, tmp, t0);
4469 store_cpu_field(tmp, spsr);
4470 } else {
4471 gen_set_cpsr(t0, mask);
4473 tcg_temp_free_i32(t0);
4474 gen_lookup_tb(s);
4475 return 0;
4478 /* Returns nonzero if access to the PSR is not permitted. */
4479 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
4481 TCGv_i32 tmp;
4482 tmp = tcg_temp_new_i32();
4483 tcg_gen_movi_i32(tmp, val);
4484 return gen_set_psr(s, mask, spsr, tmp);
4487 static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
4488 int *tgtmode, int *regno)
4490 /* Decode the r and sysm fields of MSR/MRS banked accesses into
4491 * the target mode and register number, and identify the various
4492 * unpredictable cases.
4493 * MSR (banked) and MRS (banked) are CONSTRAINED UNPREDICTABLE if:
4494 * + executed in user mode
4495 * + using R15 as the src/dest register
4496 * + accessing an unimplemented register
4497 * + accessing a register that's inaccessible at current PL/security state*
4498 * + accessing a register that you could access with a different insn
4499 * We choose to UNDEF in all these cases.
4500 * Since we don't know which of the various AArch32 modes we are in
4501 * we have to defer some checks to runtime.
4502 * Accesses to Monitor mode registers from Secure EL1 (which implies
4503 * that EL3 is AArch64) must trap to EL3.
4505 * If the access checks fail this function will emit code to take
4506 * an exception and return false. Otherwise it will return true,
4507 * and set *tgtmode and *regno appropriately.
4509 int exc_target = default_exception_el(s);
4511 /* These instructions are present only in ARMv8, or in ARMv7 with the
4512 * Virtualization Extensions.
4514 if (!arm_dc_feature(s, ARM_FEATURE_V8) &&
4515 !arm_dc_feature(s, ARM_FEATURE_EL2)) {
4516 goto undef;
4519 if (IS_USER(s) || rn == 15) {
4520 goto undef;
4523 /* The table in the v8 ARM ARM section F5.2.3 describes the encoding
4524 * of registers into (r, sysm).
4526 if (r) {
4527 /* SPSRs for other modes */
4528 switch (sysm) {
4529 case 0xe: /* SPSR_fiq */
4530 *tgtmode = ARM_CPU_MODE_FIQ;
4531 break;
4532 case 0x10: /* SPSR_irq */
4533 *tgtmode = ARM_CPU_MODE_IRQ;
4534 break;
4535 case 0x12: /* SPSR_svc */
4536 *tgtmode = ARM_CPU_MODE_SVC;
4537 break;
4538 case 0x14: /* SPSR_abt */
4539 *tgtmode = ARM_CPU_MODE_ABT;
4540 break;
4541 case 0x16: /* SPSR_und */
4542 *tgtmode = ARM_CPU_MODE_UND;
4543 break;
4544 case 0x1c: /* SPSR_mon */
4545 *tgtmode = ARM_CPU_MODE_MON;
4546 break;
4547 case 0x1e: /* SPSR_hyp */
4548 *tgtmode = ARM_CPU_MODE_HYP;
4549 break;
4550 default: /* unallocated */
4551 goto undef;
4553 /* We arbitrarily assign SPSR a register number of 16. */
4554 *regno = 16;
4555 } else {
4556 /* general purpose registers for other modes */
4557 switch (sysm) {
4558 case 0x0 ... 0x6: /* 0b00xxx : r8_usr ... r14_usr */
4559 *tgtmode = ARM_CPU_MODE_USR;
4560 *regno = sysm + 8;
4561 break;
4562 case 0x8 ... 0xe: /* 0b01xxx : r8_fiq ... r14_fiq */
4563 *tgtmode = ARM_CPU_MODE_FIQ;
4564 *regno = sysm;
4565 break;
4566 case 0x10 ... 0x11: /* 0b1000x : r14_irq, r13_irq */
4567 *tgtmode = ARM_CPU_MODE_IRQ;
4568 *regno = sysm & 1 ? 13 : 14;
4569 break;
4570 case 0x12 ... 0x13: /* 0b1001x : r14_svc, r13_svc */
4571 *tgtmode = ARM_CPU_MODE_SVC;
4572 *regno = sysm & 1 ? 13 : 14;
4573 break;
4574 case 0x14 ... 0x15: /* 0b1010x : r14_abt, r13_abt */
4575 *tgtmode = ARM_CPU_MODE_ABT;
4576 *regno = sysm & 1 ? 13 : 14;
4577 break;
4578 case 0x16 ... 0x17: /* 0b1011x : r14_und, r13_und */
4579 *tgtmode = ARM_CPU_MODE_UND;
4580 *regno = sysm & 1 ? 13 : 14;
4581 break;
4582 case 0x1c ... 0x1d: /* 0b1110x : r14_mon, r13_mon */
4583 *tgtmode = ARM_CPU_MODE_MON;
4584 *regno = sysm & 1 ? 13 : 14;
4585 break;
4586 case 0x1e ... 0x1f: /* 0b1111x : elr_hyp, r13_hyp */
4587 *tgtmode = ARM_CPU_MODE_HYP;
4588 /* Arbitrarily pick 17 for ELR_Hyp (which is not a banked LR!) */
4589 *regno = sysm & 1 ? 13 : 17;
4590 break;
4591 default: /* unallocated */
4592 goto undef;
4596 /* Catch the 'accessing inaccessible register' cases we can detect
4597 * at translate time.
4599 switch (*tgtmode) {
4600 case ARM_CPU_MODE_MON:
4601 if (!arm_dc_feature(s, ARM_FEATURE_EL3) || s->ns) {
4602 goto undef;
4604 if (s->current_el == 1) {
4605 /* If we're in Secure EL1 (which implies that EL3 is AArch64)
4606 * then accesses to Mon registers trap to EL3
4608 exc_target = 3;
4609 goto undef;
4611 break;
4612 case ARM_CPU_MODE_HYP:
4614 * SPSR_hyp and r13_hyp can only be accessed from Monitor mode
4615 * (and so we can forbid accesses from EL2 or below). elr_hyp
4616 * can be accessed also from Hyp mode, so forbid accesses from
4617 * EL0 or EL1.
4619 if (!arm_dc_feature(s, ARM_FEATURE_EL2) || s->current_el < 2 ||
4620 (s->current_el < 3 && *regno != 17)) {
4621 goto undef;
4623 break;
4624 default:
4625 break;
4628 return true;
4630 undef:
4631 /* If we get here then some access check did not pass */
4632 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), exc_target);
4633 return false;
4636 static void gen_msr_banked(DisasContext *s, int r, int sysm, int rn)
4638 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
4639 int tgtmode = 0, regno = 0;
4641 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
4642 return;
4645 /* Sync state because msr_banked() can raise exceptions */
4646 gen_set_condexec(s);
4647 gen_set_pc_im(s, s->pc - 4);
4648 tcg_reg = load_reg(s, rn);
4649 tcg_tgtmode = tcg_const_i32(tgtmode);
4650 tcg_regno = tcg_const_i32(regno);
4651 gen_helper_msr_banked(cpu_env, tcg_reg, tcg_tgtmode, tcg_regno);
4652 tcg_temp_free_i32(tcg_tgtmode);
4653 tcg_temp_free_i32(tcg_regno);
4654 tcg_temp_free_i32(tcg_reg);
4655 s->base.is_jmp = DISAS_UPDATE;
4658 static void gen_mrs_banked(DisasContext *s, int r, int sysm, int rn)
4660 TCGv_i32 tcg_reg, tcg_tgtmode, tcg_regno;
4661 int tgtmode = 0, regno = 0;
4663 if (!msr_banked_access_decode(s, r, sysm, rn, &tgtmode, &regno)) {
4664 return;
4667 /* Sync state because mrs_banked() can raise exceptions */
4668 gen_set_condexec(s);
4669 gen_set_pc_im(s, s->pc - 4);
4670 tcg_reg = tcg_temp_new_i32();
4671 tcg_tgtmode = tcg_const_i32(tgtmode);
4672 tcg_regno = tcg_const_i32(regno);
4673 gen_helper_mrs_banked(tcg_reg, cpu_env, tcg_tgtmode, tcg_regno);
4674 tcg_temp_free_i32(tcg_tgtmode);
4675 tcg_temp_free_i32(tcg_regno);
4676 store_reg(s, rn, tcg_reg);
4677 s->base.is_jmp = DISAS_UPDATE;
4680 /* Store value to PC as for an exception return (ie don't
4681 * mask bits). The subsequent call to gen_helper_cpsr_write_eret()
4682 * will do the masking based on the new value of the Thumb bit.
4684 static void store_pc_exc_ret(DisasContext *s, TCGv_i32 pc)
4686 tcg_gen_mov_i32(cpu_R[15], pc);
4687 tcg_temp_free_i32(pc);
4690 /* Generate a v6 exception return. Marks both values as dead. */
4691 static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
4693 store_pc_exc_ret(s, pc);
4694 /* The cpsr_write_eret helper will mask the low bits of PC
4695 * appropriately depending on the new Thumb bit, so it must
4696 * be called after storing the new PC.
4698 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
4699 gen_io_start();
4701 gen_helper_cpsr_write_eret(cpu_env, cpsr);
4702 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
4703 gen_io_end();
4705 tcg_temp_free_i32(cpsr);
4706 /* Must exit loop to check un-masked IRQs */
4707 s->base.is_jmp = DISAS_EXIT;
4710 /* Generate an old-style exception return. Marks pc as dead. */
4711 static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
4713 gen_rfe(s, pc, load_cpu_field(spsr));
4717 * For WFI we will halt the vCPU until an IRQ. For WFE and YIELD we
4718 * only call the helper when running single threaded TCG code to ensure
4719 * the next round-robin scheduled vCPU gets a crack. In MTTCG mode we
4720 * just skip this instruction. Currently the SEV/SEVL instructions
4721 * which are *one* of many ways to wake the CPU from WFE are not
4722 * implemented so we can't sleep like WFI does.
4724 static void gen_nop_hint(DisasContext *s, int val)
4726 switch (val) {
4727 /* When running in MTTCG we don't generate jumps to the yield and
4728 * WFE helpers as it won't affect the scheduling of other vCPUs.
4729 * If we wanted to more completely model WFE/SEV so we don't busy
4730 * spin unnecessarily we would need to do something more involved.
4732 case 1: /* yield */
4733 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
4734 gen_set_pc_im(s, s->pc);
4735 s->base.is_jmp = DISAS_YIELD;
4737 break;
4738 case 3: /* wfi */
4739 gen_set_pc_im(s, s->pc);
4740 s->base.is_jmp = DISAS_WFI;
4741 break;
4742 case 2: /* wfe */
4743 if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
4744 gen_set_pc_im(s, s->pc);
4745 s->base.is_jmp = DISAS_WFE;
4747 break;
4748 case 4: /* sev */
4749 case 5: /* sevl */
4750 /* TODO: Implement SEV, SEVL and WFE. May help SMP performance. */
4751 default: /* nop */
4752 break;
4756 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
4758 static inline void gen_neon_add(int size, TCGv_i32 t0, TCGv_i32 t1)
4760 switch (size) {
4761 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
4762 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
4763 case 2: tcg_gen_add_i32(t0, t0, t1); break;
4764 default: abort();
4768 static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
4770 switch (size) {
4771 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
4772 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
4773 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
4774 default: return;
4778 /* 32-bit pairwise ops end up the same as the elementwise versions. */
4779 #define gen_helper_neon_pmax_s32 tcg_gen_smax_i32
4780 #define gen_helper_neon_pmax_u32 tcg_gen_umax_i32
4781 #define gen_helper_neon_pmin_s32 tcg_gen_smin_i32
4782 #define gen_helper_neon_pmin_u32 tcg_gen_umin_i32
4784 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
4785 switch ((size << 1) | u) { \
4786 case 0: \
4787 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
4788 break; \
4789 case 1: \
4790 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
4791 break; \
4792 case 2: \
4793 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
4794 break; \
4795 case 3: \
4796 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
4797 break; \
4798 case 4: \
4799 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
4800 break; \
4801 case 5: \
4802 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
4803 break; \
4804 default: return 1; \
4805 }} while (0)
4807 #define GEN_NEON_INTEGER_OP(name) do { \
4808 switch ((size << 1) | u) { \
4809 case 0: \
4810 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
4811 break; \
4812 case 1: \
4813 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
4814 break; \
4815 case 2: \
4816 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
4817 break; \
4818 case 3: \
4819 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
4820 break; \
4821 case 4: \
4822 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
4823 break; \
4824 case 5: \
4825 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
4826 break; \
4827 default: return 1; \
4828 }} while (0)
4830 static TCGv_i32 neon_load_scratch(int scratch)
4832 TCGv_i32 tmp = tcg_temp_new_i32();
4833 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
4834 return tmp;
4837 static void neon_store_scratch(int scratch, TCGv_i32 var)
4839 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
4840 tcg_temp_free_i32(var);
4843 static inline TCGv_i32 neon_get_scalar(int size, int reg)
4845 TCGv_i32 tmp;
4846 if (size == 1) {
4847 tmp = neon_load_reg(reg & 7, reg >> 4);
4848 if (reg & 8) {
4849 gen_neon_dup_high16(tmp);
4850 } else {
4851 gen_neon_dup_low16(tmp);
4853 } else {
4854 tmp = neon_load_reg(reg & 15, reg >> 4);
4856 return tmp;
4859 static int gen_neon_unzip(int rd, int rm, int size, int q)
4861 TCGv_ptr pd, pm;
4863 if (!q && size == 2) {
4864 return 1;
4866 pd = vfp_reg_ptr(true, rd);
4867 pm = vfp_reg_ptr(true, rm);
4868 if (q) {
4869 switch (size) {
4870 case 0:
4871 gen_helper_neon_qunzip8(pd, pm);
4872 break;
4873 case 1:
4874 gen_helper_neon_qunzip16(pd, pm);
4875 break;
4876 case 2:
4877 gen_helper_neon_qunzip32(pd, pm);
4878 break;
4879 default:
4880 abort();
4882 } else {
4883 switch (size) {
4884 case 0:
4885 gen_helper_neon_unzip8(pd, pm);
4886 break;
4887 case 1:
4888 gen_helper_neon_unzip16(pd, pm);
4889 break;
4890 default:
4891 abort();
4894 tcg_temp_free_ptr(pd);
4895 tcg_temp_free_ptr(pm);
4896 return 0;
4899 static int gen_neon_zip(int rd, int rm, int size, int q)
4901 TCGv_ptr pd, pm;
4903 if (!q && size == 2) {
4904 return 1;
4906 pd = vfp_reg_ptr(true, rd);
4907 pm = vfp_reg_ptr(true, rm);
4908 if (q) {
4909 switch (size) {
4910 case 0:
4911 gen_helper_neon_qzip8(pd, pm);
4912 break;
4913 case 1:
4914 gen_helper_neon_qzip16(pd, pm);
4915 break;
4916 case 2:
4917 gen_helper_neon_qzip32(pd, pm);
4918 break;
4919 default:
4920 abort();
4922 } else {
4923 switch (size) {
4924 case 0:
4925 gen_helper_neon_zip8(pd, pm);
4926 break;
4927 case 1:
4928 gen_helper_neon_zip16(pd, pm);
4929 break;
4930 default:
4931 abort();
4934 tcg_temp_free_ptr(pd);
4935 tcg_temp_free_ptr(pm);
4936 return 0;
4939 static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
4941 TCGv_i32 rd, tmp;
4943 rd = tcg_temp_new_i32();
4944 tmp = tcg_temp_new_i32();
4946 tcg_gen_shli_i32(rd, t0, 8);
4947 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
4948 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
4949 tcg_gen_or_i32(rd, rd, tmp);
4951 tcg_gen_shri_i32(t1, t1, 8);
4952 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
4953 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
4954 tcg_gen_or_i32(t1, t1, tmp);
4955 tcg_gen_mov_i32(t0, rd);
4957 tcg_temp_free_i32(tmp);
4958 tcg_temp_free_i32(rd);
4961 static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
4963 TCGv_i32 rd, tmp;
4965 rd = tcg_temp_new_i32();
4966 tmp = tcg_temp_new_i32();
4968 tcg_gen_shli_i32(rd, t0, 16);
4969 tcg_gen_andi_i32(tmp, t1, 0xffff);
4970 tcg_gen_or_i32(rd, rd, tmp);
4971 tcg_gen_shri_i32(t1, t1, 16);
4972 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
4973 tcg_gen_or_i32(t1, t1, tmp);
4974 tcg_gen_mov_i32(t0, rd);
4976 tcg_temp_free_i32(tmp);
4977 tcg_temp_free_i32(rd);
4981 static struct {
4982 int nregs;
4983 int interleave;
4984 int spacing;
4985 } const neon_ls_element_type[11] = {
4986 {1, 4, 1},
4987 {1, 4, 2},
4988 {4, 1, 1},
4989 {2, 2, 2},
4990 {1, 3, 1},
4991 {1, 3, 2},
4992 {3, 1, 1},
4993 {1, 1, 1},
4994 {1, 2, 1},
4995 {1, 2, 2},
4996 {2, 1, 1}
4999 /* Translate a NEON load/store element instruction. Return nonzero if the
5000 instruction is invalid. */
5001 static int disas_neon_ls_insn(DisasContext *s, uint32_t insn)
5003 int rd, rn, rm;
5004 int op;
5005 int nregs;
5006 int interleave;
5007 int spacing;
5008 int stride;
5009 int size;
5010 int reg;
5011 int load;
5012 int n;
5013 int vec_size;
5014 int mmu_idx;
5015 TCGMemOp endian;
5016 TCGv_i32 addr;
5017 TCGv_i32 tmp;
5018 TCGv_i32 tmp2;
5019 TCGv_i64 tmp64;
5021 /* FIXME: this access check should not take precedence over UNDEF
5022 * for invalid encodings; we will generate incorrect syndrome information
5023 * for attempts to execute invalid vfp/neon encodings with FP disabled.
5025 if (s->fp_excp_el) {
5026 gen_exception_insn(s, 4, EXCP_UDEF,
5027 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
5028 return 0;
5031 if (!s->vfp_enabled)
5032 return 1;
5033 VFP_DREG_D(rd, insn);
5034 rn = (insn >> 16) & 0xf;
5035 rm = insn & 0xf;
5036 load = (insn & (1 << 21)) != 0;
5037 endian = s->be_data;
5038 mmu_idx = get_mem_index(s);
5039 if ((insn & (1 << 23)) == 0) {
5040 /* Load store all elements. */
5041 op = (insn >> 8) & 0xf;
5042 size = (insn >> 6) & 3;
5043 if (op > 10)
5044 return 1;
5045 /* Catch UNDEF cases for bad values of align field */
5046 switch (op & 0xc) {
5047 case 4:
5048 if (((insn >> 5) & 1) == 1) {
5049 return 1;
5051 break;
5052 case 8:
5053 if (((insn >> 4) & 3) == 3) {
5054 return 1;
5056 break;
5057 default:
5058 break;
5060 nregs = neon_ls_element_type[op].nregs;
5061 interleave = neon_ls_element_type[op].interleave;
5062 spacing = neon_ls_element_type[op].spacing;
5063 if (size == 3 && (interleave | spacing) != 1) {
5064 return 1;
5066 /* For our purposes, bytes are always little-endian. */
5067 if (size == 0) {
5068 endian = MO_LE;
5070 /* Consecutive little-endian elements from a single register
5071 * can be promoted to a larger little-endian operation.
5073 if (interleave == 1 && endian == MO_LE) {
5074 size = 3;
5076 tmp64 = tcg_temp_new_i64();
5077 addr = tcg_temp_new_i32();
5078 tmp2 = tcg_const_i32(1 << size);
5079 load_reg_var(s, addr, rn);
5080 for (reg = 0; reg < nregs; reg++) {
5081 for (n = 0; n < 8 >> size; n++) {
5082 int xs;
5083 for (xs = 0; xs < interleave; xs++) {
5084 int tt = rd + reg + spacing * xs;
5086 if (load) {
5087 gen_aa32_ld_i64(s, tmp64, addr, mmu_idx, endian | size);
5088 neon_store_element64(tt, n, size, tmp64);
5089 } else {
5090 neon_load_element64(tmp64, tt, n, size);
5091 gen_aa32_st_i64(s, tmp64, addr, mmu_idx, endian | size);
5093 tcg_gen_add_i32(addr, addr, tmp2);
5097 tcg_temp_free_i32(addr);
5098 tcg_temp_free_i32(tmp2);
5099 tcg_temp_free_i64(tmp64);
5100 stride = nregs * interleave * 8;
5101 } else {
5102 size = (insn >> 10) & 3;
5103 if (size == 3) {
5104 /* Load single element to all lanes. */
5105 int a = (insn >> 4) & 1;
5106 if (!load) {
5107 return 1;
5109 size = (insn >> 6) & 3;
5110 nregs = ((insn >> 8) & 3) + 1;
5112 if (size == 3) {
5113 if (nregs != 4 || a == 0) {
5114 return 1;
5116 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
5117 size = 2;
5119 if (nregs == 1 && a == 1 && size == 0) {
5120 return 1;
5122 if (nregs == 3 && a == 1) {
5123 return 1;
5125 addr = tcg_temp_new_i32();
5126 load_reg_var(s, addr, rn);
5128 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write.
5129 * VLD2/3/4 to all lanes: bit 5 indicates register stride.
5131 stride = (insn & (1 << 5)) ? 2 : 1;
5132 vec_size = nregs == 1 ? stride * 8 : 8;
5134 tmp = tcg_temp_new_i32();
5135 for (reg = 0; reg < nregs; reg++) {
5136 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
5137 s->be_data | size);
5138 if ((rd & 1) && vec_size == 16) {
5139 /* We cannot write 16 bytes at once because the
5140 * destination is unaligned.
5142 tcg_gen_gvec_dup_i32(size, neon_reg_offset(rd, 0),
5143 8, 8, tmp);
5144 tcg_gen_gvec_mov(0, neon_reg_offset(rd + 1, 0),
5145 neon_reg_offset(rd, 0), 8, 8);
5146 } else {
5147 tcg_gen_gvec_dup_i32(size, neon_reg_offset(rd, 0),
5148 vec_size, vec_size, tmp);
5150 tcg_gen_addi_i32(addr, addr, 1 << size);
5151 rd += stride;
5153 tcg_temp_free_i32(tmp);
5154 tcg_temp_free_i32(addr);
5155 stride = (1 << size) * nregs;
5156 } else {
5157 /* Single element. */
5158 int idx = (insn >> 4) & 0xf;
5159 int reg_idx;
5160 switch (size) {
5161 case 0:
5162 reg_idx = (insn >> 5) & 7;
5163 stride = 1;
5164 break;
5165 case 1:
5166 reg_idx = (insn >> 6) & 3;
5167 stride = (insn & (1 << 5)) ? 2 : 1;
5168 break;
5169 case 2:
5170 reg_idx = (insn >> 7) & 1;
5171 stride = (insn & (1 << 6)) ? 2 : 1;
5172 break;
5173 default:
5174 abort();
5176 nregs = ((insn >> 8) & 3) + 1;
5177 /* Catch the UNDEF cases. This is unavoidably a bit messy. */
5178 switch (nregs) {
5179 case 1:
5180 if (((idx & (1 << size)) != 0) ||
5181 (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
5182 return 1;
5184 break;
5185 case 3:
5186 if ((idx & 1) != 0) {
5187 return 1;
5189 /* fall through */
5190 case 2:
5191 if (size == 2 && (idx & 2) != 0) {
5192 return 1;
5194 break;
5195 case 4:
5196 if ((size == 2) && ((idx & 3) == 3)) {
5197 return 1;
5199 break;
5200 default:
5201 abort();
5203 if ((rd + stride * (nregs - 1)) > 31) {
5204 /* Attempts to write off the end of the register file
5205 * are UNPREDICTABLE; we choose to UNDEF because otherwise
5206 * the neon_load_reg() would write off the end of the array.
5208 return 1;
5210 tmp = tcg_temp_new_i32();
5211 addr = tcg_temp_new_i32();
5212 load_reg_var(s, addr, rn);
5213 for (reg = 0; reg < nregs; reg++) {
5214 if (load) {
5215 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s),
5216 s->be_data | size);
5217 neon_store_element(rd, reg_idx, size, tmp);
5218 } else { /* Store */
5219 neon_load_element(tmp, rd, reg_idx, size);
5220 gen_aa32_st_i32(s, tmp, addr, get_mem_index(s),
5221 s->be_data | size);
5223 rd += stride;
5224 tcg_gen_addi_i32(addr, addr, 1 << size);
5226 tcg_temp_free_i32(addr);
5227 tcg_temp_free_i32(tmp);
5228 stride = nregs * (1 << size);
5231 if (rm != 15) {
5232 TCGv_i32 base;
5234 base = load_reg(s, rn);
5235 if (rm == 13) {
5236 tcg_gen_addi_i32(base, base, stride);
5237 } else {
5238 TCGv_i32 index;
5239 index = load_reg(s, rm);
5240 tcg_gen_add_i32(base, base, index);
5241 tcg_temp_free_i32(index);
5243 store_reg(s, rn, base);
5245 return 0;
5248 static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src)
5250 switch (size) {
5251 case 0: gen_helper_neon_narrow_u8(dest, src); break;
5252 case 1: gen_helper_neon_narrow_u16(dest, src); break;
5253 case 2: tcg_gen_extrl_i64_i32(dest, src); break;
5254 default: abort();
5258 static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
5260 switch (size) {
5261 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
5262 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
5263 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
5264 default: abort();
5268 static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src)
5270 switch (size) {
5271 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
5272 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
5273 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
5274 default: abort();
5278 static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
5280 switch (size) {
5281 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
5282 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
5283 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
5284 default: abort();
5288 static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift,
5289 int q, int u)
5291 if (q) {
5292 if (u) {
5293 switch (size) {
5294 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
5295 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
5296 default: abort();
5298 } else {
5299 switch (size) {
5300 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
5301 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
5302 default: abort();
5305 } else {
5306 if (u) {
5307 switch (size) {
5308 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
5309 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
5310 default: abort();
5312 } else {
5313 switch (size) {
5314 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
5315 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
5316 default: abort();
5322 static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
5324 if (u) {
5325 switch (size) {
5326 case 0: gen_helper_neon_widen_u8(dest, src); break;
5327 case 1: gen_helper_neon_widen_u16(dest, src); break;
5328 case 2: tcg_gen_extu_i32_i64(dest, src); break;
5329 default: abort();
5331 } else {
5332 switch (size) {
5333 case 0: gen_helper_neon_widen_s8(dest, src); break;
5334 case 1: gen_helper_neon_widen_s16(dest, src); break;
5335 case 2: tcg_gen_ext_i32_i64(dest, src); break;
5336 default: abort();
5339 tcg_temp_free_i32(src);
5342 static inline void gen_neon_addl(int size)
5344 switch (size) {
5345 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
5346 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
5347 case 2: tcg_gen_add_i64(CPU_V001); break;
5348 default: abort();
5352 static inline void gen_neon_subl(int size)
5354 switch (size) {
5355 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
5356 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
5357 case 2: tcg_gen_sub_i64(CPU_V001); break;
5358 default: abort();
5362 static inline void gen_neon_negl(TCGv_i64 var, int size)
5364 switch (size) {
5365 case 0: gen_helper_neon_negl_u16(var, var); break;
5366 case 1: gen_helper_neon_negl_u32(var, var); break;
5367 case 2:
5368 tcg_gen_neg_i64(var, var);
5369 break;
5370 default: abort();
5374 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
5376 switch (size) {
5377 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
5378 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
5379 default: abort();
5383 static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b,
5384 int size, int u)
5386 TCGv_i64 tmp;
5388 switch ((size << 1) | u) {
5389 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
5390 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
5391 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
5392 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
5393 case 4:
5394 tmp = gen_muls_i64_i32(a, b);
5395 tcg_gen_mov_i64(dest, tmp);
5396 tcg_temp_free_i64(tmp);
5397 break;
5398 case 5:
5399 tmp = gen_mulu_i64_i32(a, b);
5400 tcg_gen_mov_i64(dest, tmp);
5401 tcg_temp_free_i64(tmp);
5402 break;
5403 default: abort();
5406 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
5407 Don't forget to clean them now. */
5408 if (size < 2) {
5409 tcg_temp_free_i32(a);
5410 tcg_temp_free_i32(b);
5414 static void gen_neon_narrow_op(int op, int u, int size,
5415 TCGv_i32 dest, TCGv_i64 src)
5417 if (op) {
5418 if (u) {
5419 gen_neon_unarrow_sats(size, dest, src);
5420 } else {
5421 gen_neon_narrow(size, dest, src);
5423 } else {
5424 if (u) {
5425 gen_neon_narrow_satu(size, dest, src);
5426 } else {
5427 gen_neon_narrow_sats(size, dest, src);
5432 /* Symbolic constants for op fields for Neon 3-register same-length.
5433 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
5434 * table A7-9.
5436 #define NEON_3R_VHADD 0
5437 #define NEON_3R_VQADD 1
5438 #define NEON_3R_VRHADD 2
5439 #define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
5440 #define NEON_3R_VHSUB 4
5441 #define NEON_3R_VQSUB 5
5442 #define NEON_3R_VCGT 6
5443 #define NEON_3R_VCGE 7
5444 #define NEON_3R_VSHL 8
5445 #define NEON_3R_VQSHL 9
5446 #define NEON_3R_VRSHL 10
5447 #define NEON_3R_VQRSHL 11
5448 #define NEON_3R_VMAX 12
5449 #define NEON_3R_VMIN 13
5450 #define NEON_3R_VABD 14
5451 #define NEON_3R_VABA 15
5452 #define NEON_3R_VADD_VSUB 16
5453 #define NEON_3R_VTST_VCEQ 17
5454 #define NEON_3R_VML 18 /* VMLA, VMLS */
5455 #define NEON_3R_VMUL 19
5456 #define NEON_3R_VPMAX 20
5457 #define NEON_3R_VPMIN 21
5458 #define NEON_3R_VQDMULH_VQRDMULH 22
5459 #define NEON_3R_VPADD_VQRDMLAH 23
5460 #define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */
5461 #define NEON_3R_VFM_VQRDMLSH 25 /* VFMA, VFMS, VQRDMLSH */
5462 #define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
5463 #define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
5464 #define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
5465 #define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
5466 #define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
5467 #define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */
5469 static const uint8_t neon_3r_sizes[] = {
5470 [NEON_3R_VHADD] = 0x7,
5471 [NEON_3R_VQADD] = 0xf,
5472 [NEON_3R_VRHADD] = 0x7,
5473 [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
5474 [NEON_3R_VHSUB] = 0x7,
5475 [NEON_3R_VQSUB] = 0xf,
5476 [NEON_3R_VCGT] = 0x7,
5477 [NEON_3R_VCGE] = 0x7,
5478 [NEON_3R_VSHL] = 0xf,
5479 [NEON_3R_VQSHL] = 0xf,
5480 [NEON_3R_VRSHL] = 0xf,
5481 [NEON_3R_VQRSHL] = 0xf,
5482 [NEON_3R_VMAX] = 0x7,
5483 [NEON_3R_VMIN] = 0x7,
5484 [NEON_3R_VABD] = 0x7,
5485 [NEON_3R_VABA] = 0x7,
5486 [NEON_3R_VADD_VSUB] = 0xf,
5487 [NEON_3R_VTST_VCEQ] = 0x7,
5488 [NEON_3R_VML] = 0x7,
5489 [NEON_3R_VMUL] = 0x7,
5490 [NEON_3R_VPMAX] = 0x7,
5491 [NEON_3R_VPMIN] = 0x7,
5492 [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
5493 [NEON_3R_VPADD_VQRDMLAH] = 0x7,
5494 [NEON_3R_SHA] = 0xf, /* size field encodes op type */
5495 [NEON_3R_VFM_VQRDMLSH] = 0x7, /* For VFM, size bit 1 encodes op */
5496 [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
5497 [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
5498 [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
5499 [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
5500 [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
5501 [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */
5504 /* Symbolic constants for op fields for Neon 2-register miscellaneous.
5505 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
5506 * table A7-13.
5508 #define NEON_2RM_VREV64 0
5509 #define NEON_2RM_VREV32 1
5510 #define NEON_2RM_VREV16 2
5511 #define NEON_2RM_VPADDL 4
5512 #define NEON_2RM_VPADDL_U 5
5513 #define NEON_2RM_AESE 6 /* Includes AESD */
5514 #define NEON_2RM_AESMC 7 /* Includes AESIMC */
5515 #define NEON_2RM_VCLS 8
5516 #define NEON_2RM_VCLZ 9
5517 #define NEON_2RM_VCNT 10
5518 #define NEON_2RM_VMVN 11
5519 #define NEON_2RM_VPADAL 12
5520 #define NEON_2RM_VPADAL_U 13
5521 #define NEON_2RM_VQABS 14
5522 #define NEON_2RM_VQNEG 15
5523 #define NEON_2RM_VCGT0 16
5524 #define NEON_2RM_VCGE0 17
5525 #define NEON_2RM_VCEQ0 18
5526 #define NEON_2RM_VCLE0 19
5527 #define NEON_2RM_VCLT0 20
5528 #define NEON_2RM_SHA1H 21
5529 #define NEON_2RM_VABS 22
5530 #define NEON_2RM_VNEG 23
5531 #define NEON_2RM_VCGT0_F 24
5532 #define NEON_2RM_VCGE0_F 25
5533 #define NEON_2RM_VCEQ0_F 26
5534 #define NEON_2RM_VCLE0_F 27
5535 #define NEON_2RM_VCLT0_F 28
5536 #define NEON_2RM_VABS_F 30
5537 #define NEON_2RM_VNEG_F 31
5538 #define NEON_2RM_VSWP 32
5539 #define NEON_2RM_VTRN 33
5540 #define NEON_2RM_VUZP 34
5541 #define NEON_2RM_VZIP 35
5542 #define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
5543 #define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
5544 #define NEON_2RM_VSHLL 38
5545 #define NEON_2RM_SHA1SU1 39 /* Includes SHA256SU0 */
5546 #define NEON_2RM_VRINTN 40
5547 #define NEON_2RM_VRINTX 41
5548 #define NEON_2RM_VRINTA 42
5549 #define NEON_2RM_VRINTZ 43
5550 #define NEON_2RM_VCVT_F16_F32 44
5551 #define NEON_2RM_VRINTM 45
5552 #define NEON_2RM_VCVT_F32_F16 46
5553 #define NEON_2RM_VRINTP 47
5554 #define NEON_2RM_VCVTAU 48
5555 #define NEON_2RM_VCVTAS 49
5556 #define NEON_2RM_VCVTNU 50
5557 #define NEON_2RM_VCVTNS 51
5558 #define NEON_2RM_VCVTPU 52
5559 #define NEON_2RM_VCVTPS 53
5560 #define NEON_2RM_VCVTMU 54
5561 #define NEON_2RM_VCVTMS 55
5562 #define NEON_2RM_VRECPE 56
5563 #define NEON_2RM_VRSQRTE 57
5564 #define NEON_2RM_VRECPE_F 58
5565 #define NEON_2RM_VRSQRTE_F 59
5566 #define NEON_2RM_VCVT_FS 60
5567 #define NEON_2RM_VCVT_FU 61
5568 #define NEON_2RM_VCVT_SF 62
5569 #define NEON_2RM_VCVT_UF 63
5571 static int neon_2rm_is_float_op(int op)
5573 /* Return true if this neon 2reg-misc op is float-to-float */
5574 return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
5575 (op >= NEON_2RM_VRINTN && op <= NEON_2RM_VRINTZ) ||
5576 op == NEON_2RM_VRINTM ||
5577 (op >= NEON_2RM_VRINTP && op <= NEON_2RM_VCVTMS) ||
5578 op >= NEON_2RM_VRECPE_F);
5581 static bool neon_2rm_is_v8_op(int op)
5583 /* Return true if this neon 2reg-misc op is ARMv8 and up */
5584 switch (op) {
5585 case NEON_2RM_VRINTN:
5586 case NEON_2RM_VRINTA:
5587 case NEON_2RM_VRINTM:
5588 case NEON_2RM_VRINTP:
5589 case NEON_2RM_VRINTZ:
5590 case NEON_2RM_VRINTX:
5591 case NEON_2RM_VCVTAU:
5592 case NEON_2RM_VCVTAS:
5593 case NEON_2RM_VCVTNU:
5594 case NEON_2RM_VCVTNS:
5595 case NEON_2RM_VCVTPU:
5596 case NEON_2RM_VCVTPS:
5597 case NEON_2RM_VCVTMU:
5598 case NEON_2RM_VCVTMS:
5599 return true;
5600 default:
5601 return false;
5605 /* Each entry in this array has bit n set if the insn allows
5606 * size value n (otherwise it will UNDEF). Since unallocated
5607 * op values will have no bits set they always UNDEF.
5609 static const uint8_t neon_2rm_sizes[] = {
5610 [NEON_2RM_VREV64] = 0x7,
5611 [NEON_2RM_VREV32] = 0x3,
5612 [NEON_2RM_VREV16] = 0x1,
5613 [NEON_2RM_VPADDL] = 0x7,
5614 [NEON_2RM_VPADDL_U] = 0x7,
5615 [NEON_2RM_AESE] = 0x1,
5616 [NEON_2RM_AESMC] = 0x1,
5617 [NEON_2RM_VCLS] = 0x7,
5618 [NEON_2RM_VCLZ] = 0x7,
5619 [NEON_2RM_VCNT] = 0x1,
5620 [NEON_2RM_VMVN] = 0x1,
5621 [NEON_2RM_VPADAL] = 0x7,
5622 [NEON_2RM_VPADAL_U] = 0x7,
5623 [NEON_2RM_VQABS] = 0x7,
5624 [NEON_2RM_VQNEG] = 0x7,
5625 [NEON_2RM_VCGT0] = 0x7,
5626 [NEON_2RM_VCGE0] = 0x7,
5627 [NEON_2RM_VCEQ0] = 0x7,
5628 [NEON_2RM_VCLE0] = 0x7,
5629 [NEON_2RM_VCLT0] = 0x7,
5630 [NEON_2RM_SHA1H] = 0x4,
5631 [NEON_2RM_VABS] = 0x7,
5632 [NEON_2RM_VNEG] = 0x7,
5633 [NEON_2RM_VCGT0_F] = 0x4,
5634 [NEON_2RM_VCGE0_F] = 0x4,
5635 [NEON_2RM_VCEQ0_F] = 0x4,
5636 [NEON_2RM_VCLE0_F] = 0x4,
5637 [NEON_2RM_VCLT0_F] = 0x4,
5638 [NEON_2RM_VABS_F] = 0x4,
5639 [NEON_2RM_VNEG_F] = 0x4,
5640 [NEON_2RM_VSWP] = 0x1,
5641 [NEON_2RM_VTRN] = 0x7,
5642 [NEON_2RM_VUZP] = 0x7,
5643 [NEON_2RM_VZIP] = 0x7,
5644 [NEON_2RM_VMOVN] = 0x7,
5645 [NEON_2RM_VQMOVN] = 0x7,
5646 [NEON_2RM_VSHLL] = 0x7,
5647 [NEON_2RM_SHA1SU1] = 0x4,
5648 [NEON_2RM_VRINTN] = 0x4,
5649 [NEON_2RM_VRINTX] = 0x4,
5650 [NEON_2RM_VRINTA] = 0x4,
5651 [NEON_2RM_VRINTZ] = 0x4,
5652 [NEON_2RM_VCVT_F16_F32] = 0x2,
5653 [NEON_2RM_VRINTM] = 0x4,
5654 [NEON_2RM_VCVT_F32_F16] = 0x2,
5655 [NEON_2RM_VRINTP] = 0x4,
5656 [NEON_2RM_VCVTAU] = 0x4,
5657 [NEON_2RM_VCVTAS] = 0x4,
5658 [NEON_2RM_VCVTNU] = 0x4,
5659 [NEON_2RM_VCVTNS] = 0x4,
5660 [NEON_2RM_VCVTPU] = 0x4,
5661 [NEON_2RM_VCVTPS] = 0x4,
5662 [NEON_2RM_VCVTMU] = 0x4,
5663 [NEON_2RM_VCVTMS] = 0x4,
5664 [NEON_2RM_VRECPE] = 0x4,
5665 [NEON_2RM_VRSQRTE] = 0x4,
5666 [NEON_2RM_VRECPE_F] = 0x4,
5667 [NEON_2RM_VRSQRTE_F] = 0x4,
5668 [NEON_2RM_VCVT_FS] = 0x4,
5669 [NEON_2RM_VCVT_FU] = 0x4,
5670 [NEON_2RM_VCVT_SF] = 0x4,
5671 [NEON_2RM_VCVT_UF] = 0x4,
5675 /* Expand v8.1 simd helper. */
5676 static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
5677 int q, int rd, int rn, int rm)
5679 if (dc_isar_feature(aa32_rdm, s)) {
5680 int opr_sz = (1 + q) * 8;
5681 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
5682 vfp_reg_offset(1, rn),
5683 vfp_reg_offset(1, rm), cpu_env,
5684 opr_sz, opr_sz, 0, fn);
5685 return 0;
5687 return 1;
5691 * Expanders for VBitOps_VBIF, VBIT, VBSL.
5693 static void gen_bsl_i64(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
5695 tcg_gen_xor_i64(rn, rn, rm);
5696 tcg_gen_and_i64(rn, rn, rd);
5697 tcg_gen_xor_i64(rd, rm, rn);
5700 static void gen_bit_i64(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
5702 tcg_gen_xor_i64(rn, rn, rd);
5703 tcg_gen_and_i64(rn, rn, rm);
5704 tcg_gen_xor_i64(rd, rd, rn);
5707 static void gen_bif_i64(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
5709 tcg_gen_xor_i64(rn, rn, rd);
5710 tcg_gen_andc_i64(rn, rn, rm);
5711 tcg_gen_xor_i64(rd, rd, rn);
5714 static void gen_bsl_vec(unsigned vece, TCGv_vec rd, TCGv_vec rn, TCGv_vec rm)
5716 tcg_gen_xor_vec(vece, rn, rn, rm);
5717 tcg_gen_and_vec(vece, rn, rn, rd);
5718 tcg_gen_xor_vec(vece, rd, rm, rn);
5721 static void gen_bit_vec(unsigned vece, TCGv_vec rd, TCGv_vec rn, TCGv_vec rm)
5723 tcg_gen_xor_vec(vece, rn, rn, rd);
5724 tcg_gen_and_vec(vece, rn, rn, rm);
5725 tcg_gen_xor_vec(vece, rd, rd, rn);
5728 static void gen_bif_vec(unsigned vece, TCGv_vec rd, TCGv_vec rn, TCGv_vec rm)
5730 tcg_gen_xor_vec(vece, rn, rn, rd);
5731 tcg_gen_andc_vec(vece, rn, rn, rm);
5732 tcg_gen_xor_vec(vece, rd, rd, rn);
5735 const GVecGen3 bsl_op = {
5736 .fni8 = gen_bsl_i64,
5737 .fniv = gen_bsl_vec,
5738 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5739 .load_dest = true
5742 const GVecGen3 bit_op = {
5743 .fni8 = gen_bit_i64,
5744 .fniv = gen_bit_vec,
5745 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5746 .load_dest = true
5749 const GVecGen3 bif_op = {
5750 .fni8 = gen_bif_i64,
5751 .fniv = gen_bif_vec,
5752 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5753 .load_dest = true
5756 static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5758 tcg_gen_vec_sar8i_i64(a, a, shift);
5759 tcg_gen_vec_add8_i64(d, d, a);
5762 static void gen_ssra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5764 tcg_gen_vec_sar16i_i64(a, a, shift);
5765 tcg_gen_vec_add16_i64(d, d, a);
5768 static void gen_ssra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
5770 tcg_gen_sari_i32(a, a, shift);
5771 tcg_gen_add_i32(d, d, a);
5774 static void gen_ssra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5776 tcg_gen_sari_i64(a, a, shift);
5777 tcg_gen_add_i64(d, d, a);
5780 static void gen_ssra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
5782 tcg_gen_sari_vec(vece, a, a, sh);
5783 tcg_gen_add_vec(vece, d, d, a);
5786 const GVecGen2i ssra_op[4] = {
5787 { .fni8 = gen_ssra8_i64,
5788 .fniv = gen_ssra_vec,
5789 .load_dest = true,
5790 .opc = INDEX_op_sari_vec,
5791 .vece = MO_8 },
5792 { .fni8 = gen_ssra16_i64,
5793 .fniv = gen_ssra_vec,
5794 .load_dest = true,
5795 .opc = INDEX_op_sari_vec,
5796 .vece = MO_16 },
5797 { .fni4 = gen_ssra32_i32,
5798 .fniv = gen_ssra_vec,
5799 .load_dest = true,
5800 .opc = INDEX_op_sari_vec,
5801 .vece = MO_32 },
5802 { .fni8 = gen_ssra64_i64,
5803 .fniv = gen_ssra_vec,
5804 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5805 .load_dest = true,
5806 .opc = INDEX_op_sari_vec,
5807 .vece = MO_64 },
5810 static void gen_usra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5812 tcg_gen_vec_shr8i_i64(a, a, shift);
5813 tcg_gen_vec_add8_i64(d, d, a);
5816 static void gen_usra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5818 tcg_gen_vec_shr16i_i64(a, a, shift);
5819 tcg_gen_vec_add16_i64(d, d, a);
5822 static void gen_usra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
5824 tcg_gen_shri_i32(a, a, shift);
5825 tcg_gen_add_i32(d, d, a);
5828 static void gen_usra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5830 tcg_gen_shri_i64(a, a, shift);
5831 tcg_gen_add_i64(d, d, a);
5834 static void gen_usra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
5836 tcg_gen_shri_vec(vece, a, a, sh);
5837 tcg_gen_add_vec(vece, d, d, a);
5840 const GVecGen2i usra_op[4] = {
5841 { .fni8 = gen_usra8_i64,
5842 .fniv = gen_usra_vec,
5843 .load_dest = true,
5844 .opc = INDEX_op_shri_vec,
5845 .vece = MO_8, },
5846 { .fni8 = gen_usra16_i64,
5847 .fniv = gen_usra_vec,
5848 .load_dest = true,
5849 .opc = INDEX_op_shri_vec,
5850 .vece = MO_16, },
5851 { .fni4 = gen_usra32_i32,
5852 .fniv = gen_usra_vec,
5853 .load_dest = true,
5854 .opc = INDEX_op_shri_vec,
5855 .vece = MO_32, },
5856 { .fni8 = gen_usra64_i64,
5857 .fniv = gen_usra_vec,
5858 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5859 .load_dest = true,
5860 .opc = INDEX_op_shri_vec,
5861 .vece = MO_64, },
5864 static void gen_shr8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5866 uint64_t mask = dup_const(MO_8, 0xff >> shift);
5867 TCGv_i64 t = tcg_temp_new_i64();
5869 tcg_gen_shri_i64(t, a, shift);
5870 tcg_gen_andi_i64(t, t, mask);
5871 tcg_gen_andi_i64(d, d, ~mask);
5872 tcg_gen_or_i64(d, d, t);
5873 tcg_temp_free_i64(t);
5876 static void gen_shr16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5878 uint64_t mask = dup_const(MO_16, 0xffff >> shift);
5879 TCGv_i64 t = tcg_temp_new_i64();
5881 tcg_gen_shri_i64(t, a, shift);
5882 tcg_gen_andi_i64(t, t, mask);
5883 tcg_gen_andi_i64(d, d, ~mask);
5884 tcg_gen_or_i64(d, d, t);
5885 tcg_temp_free_i64(t);
5888 static void gen_shr32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
5890 tcg_gen_shri_i32(a, a, shift);
5891 tcg_gen_deposit_i32(d, d, a, 0, 32 - shift);
5894 static void gen_shr64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5896 tcg_gen_shri_i64(a, a, shift);
5897 tcg_gen_deposit_i64(d, d, a, 0, 64 - shift);
5900 static void gen_shr_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
5902 if (sh == 0) {
5903 tcg_gen_mov_vec(d, a);
5904 } else {
5905 TCGv_vec t = tcg_temp_new_vec_matching(d);
5906 TCGv_vec m = tcg_temp_new_vec_matching(d);
5908 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK((8 << vece) - sh, sh));
5909 tcg_gen_shri_vec(vece, t, a, sh);
5910 tcg_gen_and_vec(vece, d, d, m);
5911 tcg_gen_or_vec(vece, d, d, t);
5913 tcg_temp_free_vec(t);
5914 tcg_temp_free_vec(m);
5918 const GVecGen2i sri_op[4] = {
5919 { .fni8 = gen_shr8_ins_i64,
5920 .fniv = gen_shr_ins_vec,
5921 .load_dest = true,
5922 .opc = INDEX_op_shri_vec,
5923 .vece = MO_8 },
5924 { .fni8 = gen_shr16_ins_i64,
5925 .fniv = gen_shr_ins_vec,
5926 .load_dest = true,
5927 .opc = INDEX_op_shri_vec,
5928 .vece = MO_16 },
5929 { .fni4 = gen_shr32_ins_i32,
5930 .fniv = gen_shr_ins_vec,
5931 .load_dest = true,
5932 .opc = INDEX_op_shri_vec,
5933 .vece = MO_32 },
5934 { .fni8 = gen_shr64_ins_i64,
5935 .fniv = gen_shr_ins_vec,
5936 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
5937 .load_dest = true,
5938 .opc = INDEX_op_shri_vec,
5939 .vece = MO_64 },
5942 static void gen_shl8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5944 uint64_t mask = dup_const(MO_8, 0xff << shift);
5945 TCGv_i64 t = tcg_temp_new_i64();
5947 tcg_gen_shli_i64(t, a, shift);
5948 tcg_gen_andi_i64(t, t, mask);
5949 tcg_gen_andi_i64(d, d, ~mask);
5950 tcg_gen_or_i64(d, d, t);
5951 tcg_temp_free_i64(t);
5954 static void gen_shl16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5956 uint64_t mask = dup_const(MO_16, 0xffff << shift);
5957 TCGv_i64 t = tcg_temp_new_i64();
5959 tcg_gen_shli_i64(t, a, shift);
5960 tcg_gen_andi_i64(t, t, mask);
5961 tcg_gen_andi_i64(d, d, ~mask);
5962 tcg_gen_or_i64(d, d, t);
5963 tcg_temp_free_i64(t);
5966 static void gen_shl32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
5968 tcg_gen_deposit_i32(d, d, a, shift, 32 - shift);
5971 static void gen_shl64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
5973 tcg_gen_deposit_i64(d, d, a, shift, 64 - shift);
5976 static void gen_shl_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
5978 if (sh == 0) {
5979 tcg_gen_mov_vec(d, a);
5980 } else {
5981 TCGv_vec t = tcg_temp_new_vec_matching(d);
5982 TCGv_vec m = tcg_temp_new_vec_matching(d);
5984 tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK(0, sh));
5985 tcg_gen_shli_vec(vece, t, a, sh);
5986 tcg_gen_and_vec(vece, d, d, m);
5987 tcg_gen_or_vec(vece, d, d, t);
5989 tcg_temp_free_vec(t);
5990 tcg_temp_free_vec(m);
5994 const GVecGen2i sli_op[4] = {
5995 { .fni8 = gen_shl8_ins_i64,
5996 .fniv = gen_shl_ins_vec,
5997 .load_dest = true,
5998 .opc = INDEX_op_shli_vec,
5999 .vece = MO_8 },
6000 { .fni8 = gen_shl16_ins_i64,
6001 .fniv = gen_shl_ins_vec,
6002 .load_dest = true,
6003 .opc = INDEX_op_shli_vec,
6004 .vece = MO_16 },
6005 { .fni4 = gen_shl32_ins_i32,
6006 .fniv = gen_shl_ins_vec,
6007 .load_dest = true,
6008 .opc = INDEX_op_shli_vec,
6009 .vece = MO_32 },
6010 { .fni8 = gen_shl64_ins_i64,
6011 .fniv = gen_shl_ins_vec,
6012 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
6013 .load_dest = true,
6014 .opc = INDEX_op_shli_vec,
6015 .vece = MO_64 },
6018 static void gen_mla8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
6020 gen_helper_neon_mul_u8(a, a, b);
6021 gen_helper_neon_add_u8(d, d, a);
6024 static void gen_mls8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
6026 gen_helper_neon_mul_u8(a, a, b);
6027 gen_helper_neon_sub_u8(d, d, a);
6030 static void gen_mla16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
6032 gen_helper_neon_mul_u16(a, a, b);
6033 gen_helper_neon_add_u16(d, d, a);
6036 static void gen_mls16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
6038 gen_helper_neon_mul_u16(a, a, b);
6039 gen_helper_neon_sub_u16(d, d, a);
6042 static void gen_mla32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
6044 tcg_gen_mul_i32(a, a, b);
6045 tcg_gen_add_i32(d, d, a);
6048 static void gen_mls32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
6050 tcg_gen_mul_i32(a, a, b);
6051 tcg_gen_sub_i32(d, d, a);
6054 static void gen_mla64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
6056 tcg_gen_mul_i64(a, a, b);
6057 tcg_gen_add_i64(d, d, a);
6060 static void gen_mls64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
6062 tcg_gen_mul_i64(a, a, b);
6063 tcg_gen_sub_i64(d, d, a);
6066 static void gen_mla_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
6068 tcg_gen_mul_vec(vece, a, a, b);
6069 tcg_gen_add_vec(vece, d, d, a);
6072 static void gen_mls_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
6074 tcg_gen_mul_vec(vece, a, a, b);
6075 tcg_gen_sub_vec(vece, d, d, a);
6078 /* Note that while NEON does not support VMLA and VMLS as 64-bit ops,
6079 * these tables are shared with AArch64 which does support them.
6081 const GVecGen3 mla_op[4] = {
6082 { .fni4 = gen_mla8_i32,
6083 .fniv = gen_mla_vec,
6084 .opc = INDEX_op_mul_vec,
6085 .load_dest = true,
6086 .vece = MO_8 },
6087 { .fni4 = gen_mla16_i32,
6088 .fniv = gen_mla_vec,
6089 .opc = INDEX_op_mul_vec,
6090 .load_dest = true,
6091 .vece = MO_16 },
6092 { .fni4 = gen_mla32_i32,
6093 .fniv = gen_mla_vec,
6094 .opc = INDEX_op_mul_vec,
6095 .load_dest = true,
6096 .vece = MO_32 },
6097 { .fni8 = gen_mla64_i64,
6098 .fniv = gen_mla_vec,
6099 .opc = INDEX_op_mul_vec,
6100 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
6101 .load_dest = true,
6102 .vece = MO_64 },
6105 const GVecGen3 mls_op[4] = {
6106 { .fni4 = gen_mls8_i32,
6107 .fniv = gen_mls_vec,
6108 .opc = INDEX_op_mul_vec,
6109 .load_dest = true,
6110 .vece = MO_8 },
6111 { .fni4 = gen_mls16_i32,
6112 .fniv = gen_mls_vec,
6113 .opc = INDEX_op_mul_vec,
6114 .load_dest = true,
6115 .vece = MO_16 },
6116 { .fni4 = gen_mls32_i32,
6117 .fniv = gen_mls_vec,
6118 .opc = INDEX_op_mul_vec,
6119 .load_dest = true,
6120 .vece = MO_32 },
6121 { .fni8 = gen_mls64_i64,
6122 .fniv = gen_mls_vec,
6123 .opc = INDEX_op_mul_vec,
6124 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
6125 .load_dest = true,
6126 .vece = MO_64 },
6129 /* CMTST : test is "if (X & Y != 0)". */
6130 static void gen_cmtst_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
6132 tcg_gen_and_i32(d, a, b);
6133 tcg_gen_setcondi_i32(TCG_COND_NE, d, d, 0);
6134 tcg_gen_neg_i32(d, d);
6137 void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
6139 tcg_gen_and_i64(d, a, b);
6140 tcg_gen_setcondi_i64(TCG_COND_NE, d, d, 0);
6141 tcg_gen_neg_i64(d, d);
6144 static void gen_cmtst_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
6146 tcg_gen_and_vec(vece, d, a, b);
6147 tcg_gen_dupi_vec(vece, a, 0);
6148 tcg_gen_cmp_vec(TCG_COND_NE, vece, d, d, a);
6151 const GVecGen3 cmtst_op[4] = {
6152 { .fni4 = gen_helper_neon_tst_u8,
6153 .fniv = gen_cmtst_vec,
6154 .vece = MO_8 },
6155 { .fni4 = gen_helper_neon_tst_u16,
6156 .fniv = gen_cmtst_vec,
6157 .vece = MO_16 },
6158 { .fni4 = gen_cmtst_i32,
6159 .fniv = gen_cmtst_vec,
6160 .vece = MO_32 },
6161 { .fni8 = gen_cmtst_i64,
6162 .fniv = gen_cmtst_vec,
6163 .prefer_i64 = TCG_TARGET_REG_BITS == 64,
6164 .vece = MO_64 },
6167 static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
6168 TCGv_vec a, TCGv_vec b)
6170 TCGv_vec x = tcg_temp_new_vec_matching(t);
6171 tcg_gen_add_vec(vece, x, a, b);
6172 tcg_gen_usadd_vec(vece, t, a, b);
6173 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
6174 tcg_gen_or_vec(vece, sat, sat, x);
6175 tcg_temp_free_vec(x);
6178 const GVecGen4 uqadd_op[4] = {
6179 { .fniv = gen_uqadd_vec,
6180 .fno = gen_helper_gvec_uqadd_b,
6181 .opc = INDEX_op_usadd_vec,
6182 .write_aofs = true,
6183 .vece = MO_8 },
6184 { .fniv = gen_uqadd_vec,
6185 .fno = gen_helper_gvec_uqadd_h,
6186 .opc = INDEX_op_usadd_vec,
6187 .write_aofs = true,
6188 .vece = MO_16 },
6189 { .fniv = gen_uqadd_vec,
6190 .fno = gen_helper_gvec_uqadd_s,
6191 .opc = INDEX_op_usadd_vec,
6192 .write_aofs = true,
6193 .vece = MO_32 },
6194 { .fniv = gen_uqadd_vec,
6195 .fno = gen_helper_gvec_uqadd_d,
6196 .opc = INDEX_op_usadd_vec,
6197 .write_aofs = true,
6198 .vece = MO_64 },
6201 static void gen_sqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
6202 TCGv_vec a, TCGv_vec b)
6204 TCGv_vec x = tcg_temp_new_vec_matching(t);
6205 tcg_gen_add_vec(vece, x, a, b);
6206 tcg_gen_ssadd_vec(vece, t, a, b);
6207 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
6208 tcg_gen_or_vec(vece, sat, sat, x);
6209 tcg_temp_free_vec(x);
6212 const GVecGen4 sqadd_op[4] = {
6213 { .fniv = gen_sqadd_vec,
6214 .fno = gen_helper_gvec_sqadd_b,
6215 .opc = INDEX_op_ssadd_vec,
6216 .write_aofs = true,
6217 .vece = MO_8 },
6218 { .fniv = gen_sqadd_vec,
6219 .fno = gen_helper_gvec_sqadd_h,
6220 .opc = INDEX_op_ssadd_vec,
6221 .write_aofs = true,
6222 .vece = MO_16 },
6223 { .fniv = gen_sqadd_vec,
6224 .fno = gen_helper_gvec_sqadd_s,
6225 .opc = INDEX_op_ssadd_vec,
6226 .write_aofs = true,
6227 .vece = MO_32 },
6228 { .fniv = gen_sqadd_vec,
6229 .fno = gen_helper_gvec_sqadd_d,
6230 .opc = INDEX_op_ssadd_vec,
6231 .write_aofs = true,
6232 .vece = MO_64 },
6235 static void gen_uqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
6236 TCGv_vec a, TCGv_vec b)
6238 TCGv_vec x = tcg_temp_new_vec_matching(t);
6239 tcg_gen_sub_vec(vece, x, a, b);
6240 tcg_gen_ussub_vec(vece, t, a, b);
6241 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
6242 tcg_gen_or_vec(vece, sat, sat, x);
6243 tcg_temp_free_vec(x);
6246 const GVecGen4 uqsub_op[4] = {
6247 { .fniv = gen_uqsub_vec,
6248 .fno = gen_helper_gvec_uqsub_b,
6249 .opc = INDEX_op_ussub_vec,
6250 .write_aofs = true,
6251 .vece = MO_8 },
6252 { .fniv = gen_uqsub_vec,
6253 .fno = gen_helper_gvec_uqsub_h,
6254 .opc = INDEX_op_ussub_vec,
6255 .write_aofs = true,
6256 .vece = MO_16 },
6257 { .fniv = gen_uqsub_vec,
6258 .fno = gen_helper_gvec_uqsub_s,
6259 .opc = INDEX_op_ussub_vec,
6260 .write_aofs = true,
6261 .vece = MO_32 },
6262 { .fniv = gen_uqsub_vec,
6263 .fno = gen_helper_gvec_uqsub_d,
6264 .opc = INDEX_op_ussub_vec,
6265 .write_aofs = true,
6266 .vece = MO_64 },
6269 static void gen_sqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
6270 TCGv_vec a, TCGv_vec b)
6272 TCGv_vec x = tcg_temp_new_vec_matching(t);
6273 tcg_gen_sub_vec(vece, x, a, b);
6274 tcg_gen_sssub_vec(vece, t, a, b);
6275 tcg_gen_cmp_vec(TCG_COND_NE, vece, x, x, t);
6276 tcg_gen_or_vec(vece, sat, sat, x);
6277 tcg_temp_free_vec(x);
6280 const GVecGen4 sqsub_op[4] = {
6281 { .fniv = gen_sqsub_vec,
6282 .fno = gen_helper_gvec_sqsub_b,
6283 .opc = INDEX_op_sssub_vec,
6284 .write_aofs = true,
6285 .vece = MO_8 },
6286 { .fniv = gen_sqsub_vec,
6287 .fno = gen_helper_gvec_sqsub_h,
6288 .opc = INDEX_op_sssub_vec,
6289 .write_aofs = true,
6290 .vece = MO_16 },
6291 { .fniv = gen_sqsub_vec,
6292 .fno = gen_helper_gvec_sqsub_s,
6293 .opc = INDEX_op_sssub_vec,
6294 .write_aofs = true,
6295 .vece = MO_32 },
6296 { .fniv = gen_sqsub_vec,
6297 .fno = gen_helper_gvec_sqsub_d,
6298 .opc = INDEX_op_sssub_vec,
6299 .write_aofs = true,
6300 .vece = MO_64 },
6303 /* Translate a NEON data processing instruction. Return nonzero if the
6304 instruction is invalid.
6305 We process data in a mixture of 32-bit and 64-bit chunks.
6306 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
6308 static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
6310 int op;
6311 int q;
6312 int rd, rn, rm, rd_ofs, rn_ofs, rm_ofs;
6313 int size;
6314 int shift;
6315 int pass;
6316 int count;
6317 int pairwise;
6318 int u;
6319 int vec_size;
6320 uint32_t imm;
6321 TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
6322 TCGv_ptr ptr1, ptr2, ptr3;
6323 TCGv_i64 tmp64;
6325 /* FIXME: this access check should not take precedence over UNDEF
6326 * for invalid encodings; we will generate incorrect syndrome information
6327 * for attempts to execute invalid vfp/neon encodings with FP disabled.
6329 if (s->fp_excp_el) {
6330 gen_exception_insn(s, 4, EXCP_UDEF,
6331 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
6332 return 0;
6335 if (!s->vfp_enabled)
6336 return 1;
6337 q = (insn & (1 << 6)) != 0;
6338 u = (insn >> 24) & 1;
6339 VFP_DREG_D(rd, insn);
6340 VFP_DREG_N(rn, insn);
6341 VFP_DREG_M(rm, insn);
6342 size = (insn >> 20) & 3;
6343 vec_size = q ? 16 : 8;
6344 rd_ofs = neon_reg_offset(rd, 0);
6345 rn_ofs = neon_reg_offset(rn, 0);
6346 rm_ofs = neon_reg_offset(rm, 0);
6348 if ((insn & (1 << 23)) == 0) {
6349 /* Three register same length. */
6350 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
6351 /* Catch invalid op and bad size combinations: UNDEF */
6352 if ((neon_3r_sizes[op] & (1 << size)) == 0) {
6353 return 1;
6355 /* All insns of this form UNDEF for either this condition or the
6356 * superset of cases "Q==1"; we catch the latter later.
6358 if (q && ((rd | rn | rm) & 1)) {
6359 return 1;
6361 switch (op) {
6362 case NEON_3R_SHA:
6363 /* The SHA-1/SHA-256 3-register instructions require special
6364 * treatment here, as their size field is overloaded as an
6365 * op type selector, and they all consume their input in a
6366 * single pass.
6368 if (!q) {
6369 return 1;
6371 if (!u) { /* SHA-1 */
6372 if (!dc_isar_feature(aa32_sha1, s)) {
6373 return 1;
6375 ptr1 = vfp_reg_ptr(true, rd);
6376 ptr2 = vfp_reg_ptr(true, rn);
6377 ptr3 = vfp_reg_ptr(true, rm);
6378 tmp4 = tcg_const_i32(size);
6379 gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp4);
6380 tcg_temp_free_i32(tmp4);
6381 } else { /* SHA-256 */
6382 if (!dc_isar_feature(aa32_sha2, s) || size == 3) {
6383 return 1;
6385 ptr1 = vfp_reg_ptr(true, rd);
6386 ptr2 = vfp_reg_ptr(true, rn);
6387 ptr3 = vfp_reg_ptr(true, rm);
6388 switch (size) {
6389 case 0:
6390 gen_helper_crypto_sha256h(ptr1, ptr2, ptr3);
6391 break;
6392 case 1:
6393 gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3);
6394 break;
6395 case 2:
6396 gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3);
6397 break;
6400 tcg_temp_free_ptr(ptr1);
6401 tcg_temp_free_ptr(ptr2);
6402 tcg_temp_free_ptr(ptr3);
6403 return 0;
6405 case NEON_3R_VPADD_VQRDMLAH:
6406 if (!u) {
6407 break; /* VPADD */
6409 /* VQRDMLAH */
6410 switch (size) {
6411 case 1:
6412 return do_v81_helper(s, gen_helper_gvec_qrdmlah_s16,
6413 q, rd, rn, rm);
6414 case 2:
6415 return do_v81_helper(s, gen_helper_gvec_qrdmlah_s32,
6416 q, rd, rn, rm);
6418 return 1;
6420 case NEON_3R_VFM_VQRDMLSH:
6421 if (!u) {
6422 /* VFM, VFMS */
6423 if (size == 1) {
6424 return 1;
6426 break;
6428 /* VQRDMLSH */
6429 switch (size) {
6430 case 1:
6431 return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s16,
6432 q, rd, rn, rm);
6433 case 2:
6434 return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s32,
6435 q, rd, rn, rm);
6437 return 1;
6439 case NEON_3R_LOGIC: /* Logic ops. */
6440 switch ((u << 2) | size) {
6441 case 0: /* VAND */
6442 tcg_gen_gvec_and(0, rd_ofs, rn_ofs, rm_ofs,
6443 vec_size, vec_size);
6444 break;
6445 case 1: /* VBIC */
6446 tcg_gen_gvec_andc(0, rd_ofs, rn_ofs, rm_ofs,
6447 vec_size, vec_size);
6448 break;
6449 case 2: /* VORR */
6450 tcg_gen_gvec_or(0, rd_ofs, rn_ofs, rm_ofs,
6451 vec_size, vec_size);
6452 break;
6453 case 3: /* VORN */
6454 tcg_gen_gvec_orc(0, rd_ofs, rn_ofs, rm_ofs,
6455 vec_size, vec_size);
6456 break;
6457 case 4: /* VEOR */
6458 tcg_gen_gvec_xor(0, rd_ofs, rn_ofs, rm_ofs,
6459 vec_size, vec_size);
6460 break;
6461 case 5: /* VBSL */
6462 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
6463 vec_size, vec_size, &bsl_op);
6464 break;
6465 case 6: /* VBIT */
6466 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
6467 vec_size, vec_size, &bit_op);
6468 break;
6469 case 7: /* VBIF */
6470 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
6471 vec_size, vec_size, &bif_op);
6472 break;
6474 return 0;
6476 case NEON_3R_VADD_VSUB:
6477 if (u) {
6478 tcg_gen_gvec_sub(size, rd_ofs, rn_ofs, rm_ofs,
6479 vec_size, vec_size);
6480 } else {
6481 tcg_gen_gvec_add(size, rd_ofs, rn_ofs, rm_ofs,
6482 vec_size, vec_size);
6484 return 0;
6486 case NEON_3R_VQADD:
6487 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
6488 rn_ofs, rm_ofs, vec_size, vec_size,
6489 (u ? uqadd_op : sqadd_op) + size);
6490 break;
6492 case NEON_3R_VQSUB:
6493 tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
6494 rn_ofs, rm_ofs, vec_size, vec_size,
6495 (u ? uqsub_op : sqsub_op) + size);
6496 break;
6498 case NEON_3R_VMUL: /* VMUL */
6499 if (u) {
6500 /* Polynomial case allows only P8 and is handled below. */
6501 if (size != 0) {
6502 return 1;
6504 } else {
6505 tcg_gen_gvec_mul(size, rd_ofs, rn_ofs, rm_ofs,
6506 vec_size, vec_size);
6507 return 0;
6509 break;
6511 case NEON_3R_VML: /* VMLA, VMLS */
6512 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size,
6513 u ? &mls_op[size] : &mla_op[size]);
6514 return 0;
6516 case NEON_3R_VTST_VCEQ:
6517 if (u) { /* VCEQ */
6518 tcg_gen_gvec_cmp(TCG_COND_EQ, size, rd_ofs, rn_ofs, rm_ofs,
6519 vec_size, vec_size);
6520 } else { /* VTST */
6521 tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
6522 vec_size, vec_size, &cmtst_op[size]);
6524 return 0;
6526 case NEON_3R_VCGT:
6527 tcg_gen_gvec_cmp(u ? TCG_COND_GTU : TCG_COND_GT, size,
6528 rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
6529 return 0;
6531 case NEON_3R_VCGE:
6532 tcg_gen_gvec_cmp(u ? TCG_COND_GEU : TCG_COND_GE, size,
6533 rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size);
6534 return 0;
6536 case NEON_3R_VMAX:
6537 if (u) {
6538 tcg_gen_gvec_umax(size, rd_ofs, rn_ofs, rm_ofs,
6539 vec_size, vec_size);
6540 } else {
6541 tcg_gen_gvec_smax(size, rd_ofs, rn_ofs, rm_ofs,
6542 vec_size, vec_size);
6544 return 0;
6545 case NEON_3R_VMIN:
6546 if (u) {
6547 tcg_gen_gvec_umin(size, rd_ofs, rn_ofs, rm_ofs,
6548 vec_size, vec_size);
6549 } else {
6550 tcg_gen_gvec_smin(size, rd_ofs, rn_ofs, rm_ofs,
6551 vec_size, vec_size);
6553 return 0;
6556 if (size == 3) {
6557 /* 64-bit element instructions. */
6558 for (pass = 0; pass < (q ? 2 : 1); pass++) {
6559 neon_load_reg64(cpu_V0, rn + pass);
6560 neon_load_reg64(cpu_V1, rm + pass);
6561 switch (op) {
6562 case NEON_3R_VSHL:
6563 if (u) {
6564 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
6565 } else {
6566 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
6568 break;
6569 case NEON_3R_VQSHL:
6570 if (u) {
6571 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
6572 cpu_V1, cpu_V0);
6573 } else {
6574 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
6575 cpu_V1, cpu_V0);
6577 break;
6578 case NEON_3R_VRSHL:
6579 if (u) {
6580 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
6581 } else {
6582 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
6584 break;
6585 case NEON_3R_VQRSHL:
6586 if (u) {
6587 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
6588 cpu_V1, cpu_V0);
6589 } else {
6590 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
6591 cpu_V1, cpu_V0);
6593 break;
6594 default:
6595 abort();
6597 neon_store_reg64(cpu_V0, rd + pass);
6599 return 0;
6601 pairwise = 0;
6602 switch (op) {
6603 case NEON_3R_VSHL:
6604 case NEON_3R_VQSHL:
6605 case NEON_3R_VRSHL:
6606 case NEON_3R_VQRSHL:
6608 int rtmp;
6609 /* Shift instruction operands are reversed. */
6610 rtmp = rn;
6611 rn = rm;
6612 rm = rtmp;
6614 break;
6615 case NEON_3R_VPADD_VQRDMLAH:
6616 case NEON_3R_VPMAX:
6617 case NEON_3R_VPMIN:
6618 pairwise = 1;
6619 break;
6620 case NEON_3R_FLOAT_ARITH:
6621 pairwise = (u && size < 2); /* if VPADD (float) */
6622 break;
6623 case NEON_3R_FLOAT_MINMAX:
6624 pairwise = u; /* if VPMIN/VPMAX (float) */
6625 break;
6626 case NEON_3R_FLOAT_CMP:
6627 if (!u && size) {
6628 /* no encoding for U=0 C=1x */
6629 return 1;
6631 break;
6632 case NEON_3R_FLOAT_ACMP:
6633 if (!u) {
6634 return 1;
6636 break;
6637 case NEON_3R_FLOAT_MISC:
6638 /* VMAXNM/VMINNM in ARMv8 */
6639 if (u && !arm_dc_feature(s, ARM_FEATURE_V8)) {
6640 return 1;
6642 break;
6643 case NEON_3R_VFM_VQRDMLSH:
6644 if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
6645 return 1;
6647 break;
6648 default:
6649 break;
6652 if (pairwise && q) {
6653 /* All the pairwise insns UNDEF if Q is set */
6654 return 1;
6657 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6659 if (pairwise) {
6660 /* Pairwise. */
6661 if (pass < 1) {
6662 tmp = neon_load_reg(rn, 0);
6663 tmp2 = neon_load_reg(rn, 1);
6664 } else {
6665 tmp = neon_load_reg(rm, 0);
6666 tmp2 = neon_load_reg(rm, 1);
6668 } else {
6669 /* Elementwise. */
6670 tmp = neon_load_reg(rn, pass);
6671 tmp2 = neon_load_reg(rm, pass);
6673 switch (op) {
6674 case NEON_3R_VHADD:
6675 GEN_NEON_INTEGER_OP(hadd);
6676 break;
6677 case NEON_3R_VRHADD:
6678 GEN_NEON_INTEGER_OP(rhadd);
6679 break;
6680 case NEON_3R_VHSUB:
6681 GEN_NEON_INTEGER_OP(hsub);
6682 break;
6683 case NEON_3R_VSHL:
6684 GEN_NEON_INTEGER_OP(shl);
6685 break;
6686 case NEON_3R_VQSHL:
6687 GEN_NEON_INTEGER_OP_ENV(qshl);
6688 break;
6689 case NEON_3R_VRSHL:
6690 GEN_NEON_INTEGER_OP(rshl);
6691 break;
6692 case NEON_3R_VQRSHL:
6693 GEN_NEON_INTEGER_OP_ENV(qrshl);
6694 break;
6695 case NEON_3R_VABD:
6696 GEN_NEON_INTEGER_OP(abd);
6697 break;
6698 case NEON_3R_VABA:
6699 GEN_NEON_INTEGER_OP(abd);
6700 tcg_temp_free_i32(tmp2);
6701 tmp2 = neon_load_reg(rd, pass);
6702 gen_neon_add(size, tmp, tmp2);
6703 break;
6704 case NEON_3R_VMUL:
6705 /* VMUL.P8; other cases already eliminated. */
6706 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
6707 break;
6708 case NEON_3R_VPMAX:
6709 GEN_NEON_INTEGER_OP(pmax);
6710 break;
6711 case NEON_3R_VPMIN:
6712 GEN_NEON_INTEGER_OP(pmin);
6713 break;
6714 case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
6715 if (!u) { /* VQDMULH */
6716 switch (size) {
6717 case 1:
6718 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
6719 break;
6720 case 2:
6721 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
6722 break;
6723 default: abort();
6725 } else { /* VQRDMULH */
6726 switch (size) {
6727 case 1:
6728 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
6729 break;
6730 case 2:
6731 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
6732 break;
6733 default: abort();
6736 break;
6737 case NEON_3R_VPADD_VQRDMLAH:
6738 switch (size) {
6739 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
6740 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
6741 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
6742 default: abort();
6744 break;
6745 case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
6747 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6748 switch ((u << 2) | size) {
6749 case 0: /* VADD */
6750 case 4: /* VPADD */
6751 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
6752 break;
6753 case 2: /* VSUB */
6754 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
6755 break;
6756 case 6: /* VABD */
6757 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
6758 break;
6759 default:
6760 abort();
6762 tcg_temp_free_ptr(fpstatus);
6763 break;
6765 case NEON_3R_FLOAT_MULTIPLY:
6767 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6768 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
6769 if (!u) {
6770 tcg_temp_free_i32(tmp2);
6771 tmp2 = neon_load_reg(rd, pass);
6772 if (size == 0) {
6773 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
6774 } else {
6775 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
6778 tcg_temp_free_ptr(fpstatus);
6779 break;
6781 case NEON_3R_FLOAT_CMP:
6783 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6784 if (!u) {
6785 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
6786 } else {
6787 if (size == 0) {
6788 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
6789 } else {
6790 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
6793 tcg_temp_free_ptr(fpstatus);
6794 break;
6796 case NEON_3R_FLOAT_ACMP:
6798 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6799 if (size == 0) {
6800 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
6801 } else {
6802 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
6804 tcg_temp_free_ptr(fpstatus);
6805 break;
6807 case NEON_3R_FLOAT_MINMAX:
6809 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6810 if (size == 0) {
6811 gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus);
6812 } else {
6813 gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus);
6815 tcg_temp_free_ptr(fpstatus);
6816 break;
6818 case NEON_3R_FLOAT_MISC:
6819 if (u) {
6820 /* VMAXNM/VMINNM */
6821 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6822 if (size == 0) {
6823 gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus);
6824 } else {
6825 gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus);
6827 tcg_temp_free_ptr(fpstatus);
6828 } else {
6829 if (size == 0) {
6830 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
6831 } else {
6832 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
6835 break;
6836 case NEON_3R_VFM_VQRDMLSH:
6838 /* VFMA, VFMS: fused multiply-add */
6839 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6840 TCGv_i32 tmp3 = neon_load_reg(rd, pass);
6841 if (size) {
6842 /* VFMS */
6843 gen_helper_vfp_negs(tmp, tmp);
6845 gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus);
6846 tcg_temp_free_i32(tmp3);
6847 tcg_temp_free_ptr(fpstatus);
6848 break;
6850 default:
6851 abort();
6853 tcg_temp_free_i32(tmp2);
6855 /* Save the result. For elementwise operations we can put it
6856 straight into the destination register. For pairwise operations
6857 we have to be careful to avoid clobbering the source operands. */
6858 if (pairwise && rd == rm) {
6859 neon_store_scratch(pass, tmp);
6860 } else {
6861 neon_store_reg(rd, pass, tmp);
6864 } /* for pass */
6865 if (pairwise && rd == rm) {
6866 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6867 tmp = neon_load_scratch(pass);
6868 neon_store_reg(rd, pass, tmp);
6871 /* End of 3 register same size operations. */
6872 } else if (insn & (1 << 4)) {
6873 if ((insn & 0x00380080) != 0) {
6874 /* Two registers and shift. */
6875 op = (insn >> 8) & 0xf;
6876 if (insn & (1 << 7)) {
6877 /* 64-bit shift. */
6878 if (op > 7) {
6879 return 1;
6881 size = 3;
6882 } else {
6883 size = 2;
6884 while ((insn & (1 << (size + 19))) == 0)
6885 size--;
6887 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
6888 if (op < 8) {
6889 /* Shift by immediate:
6890 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
6891 if (q && ((rd | rm) & 1)) {
6892 return 1;
6894 if (!u && (op == 4 || op == 6)) {
6895 return 1;
6897 /* Right shifts are encoded as N - shift, where N is the
6898 element size in bits. */
6899 if (op <= 4) {
6900 shift = shift - (1 << (size + 3));
6903 switch (op) {
6904 case 0: /* VSHR */
6905 /* Right shift comes here negative. */
6906 shift = -shift;
6907 /* Shifts larger than the element size are architecturally
6908 * valid. Unsigned results in all zeros; signed results
6909 * in all sign bits.
6911 if (!u) {
6912 tcg_gen_gvec_sari(size, rd_ofs, rm_ofs,
6913 MIN(shift, (8 << size) - 1),
6914 vec_size, vec_size);
6915 } else if (shift >= 8 << size) {
6916 tcg_gen_gvec_dup8i(rd_ofs, vec_size, vec_size, 0);
6917 } else {
6918 tcg_gen_gvec_shri(size, rd_ofs, rm_ofs, shift,
6919 vec_size, vec_size);
6921 return 0;
6923 case 1: /* VSRA */
6924 /* Right shift comes here negative. */
6925 shift = -shift;
6926 /* Shifts larger than the element size are architecturally
6927 * valid. Unsigned results in all zeros; signed results
6928 * in all sign bits.
6930 if (!u) {
6931 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
6932 MIN(shift, (8 << size) - 1),
6933 &ssra_op[size]);
6934 } else if (shift >= 8 << size) {
6935 /* rd += 0 */
6936 } else {
6937 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
6938 shift, &usra_op[size]);
6940 return 0;
6942 case 4: /* VSRI */
6943 if (!u) {
6944 return 1;
6946 /* Right shift comes here negative. */
6947 shift = -shift;
6948 /* Shift out of range leaves destination unchanged. */
6949 if (shift < 8 << size) {
6950 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
6951 shift, &sri_op[size]);
6953 return 0;
6955 case 5: /* VSHL, VSLI */
6956 if (u) { /* VSLI */
6957 /* Shift out of range leaves destination unchanged. */
6958 if (shift < 8 << size) {
6959 tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size,
6960 vec_size, shift, &sli_op[size]);
6962 } else { /* VSHL */
6963 /* Shifts larger than the element size are
6964 * architecturally valid and results in zero.
6966 if (shift >= 8 << size) {
6967 tcg_gen_gvec_dup8i(rd_ofs, vec_size, vec_size, 0);
6968 } else {
6969 tcg_gen_gvec_shli(size, rd_ofs, rm_ofs, shift,
6970 vec_size, vec_size);
6973 return 0;
6976 if (size == 3) {
6977 count = q + 1;
6978 } else {
6979 count = q ? 4: 2;
6982 /* To avoid excessive duplication of ops we implement shift
6983 * by immediate using the variable shift operations.
6985 imm = dup_const(size, shift);
6987 for (pass = 0; pass < count; pass++) {
6988 if (size == 3) {
6989 neon_load_reg64(cpu_V0, rm + pass);
6990 tcg_gen_movi_i64(cpu_V1, imm);
6991 switch (op) {
6992 case 2: /* VRSHR */
6993 case 3: /* VRSRA */
6994 if (u)
6995 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
6996 else
6997 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
6998 break;
6999 case 6: /* VQSHLU */
7000 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
7001 cpu_V0, cpu_V1);
7002 break;
7003 case 7: /* VQSHL */
7004 if (u) {
7005 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
7006 cpu_V0, cpu_V1);
7007 } else {
7008 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
7009 cpu_V0, cpu_V1);
7011 break;
7012 default:
7013 g_assert_not_reached();
7015 if (op == 3) {
7016 /* Accumulate. */
7017 neon_load_reg64(cpu_V1, rd + pass);
7018 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
7020 neon_store_reg64(cpu_V0, rd + pass);
7021 } else { /* size < 3 */
7022 /* Operands in T0 and T1. */
7023 tmp = neon_load_reg(rm, pass);
7024 tmp2 = tcg_temp_new_i32();
7025 tcg_gen_movi_i32(tmp2, imm);
7026 switch (op) {
7027 case 2: /* VRSHR */
7028 case 3: /* VRSRA */
7029 GEN_NEON_INTEGER_OP(rshl);
7030 break;
7031 case 6: /* VQSHLU */
7032 switch (size) {
7033 case 0:
7034 gen_helper_neon_qshlu_s8(tmp, cpu_env,
7035 tmp, tmp2);
7036 break;
7037 case 1:
7038 gen_helper_neon_qshlu_s16(tmp, cpu_env,
7039 tmp, tmp2);
7040 break;
7041 case 2:
7042 gen_helper_neon_qshlu_s32(tmp, cpu_env,
7043 tmp, tmp2);
7044 break;
7045 default:
7046 abort();
7048 break;
7049 case 7: /* VQSHL */
7050 GEN_NEON_INTEGER_OP_ENV(qshl);
7051 break;
7052 default:
7053 g_assert_not_reached();
7055 tcg_temp_free_i32(tmp2);
7057 if (op == 3) {
7058 /* Accumulate. */
7059 tmp2 = neon_load_reg(rd, pass);
7060 gen_neon_add(size, tmp, tmp2);
7061 tcg_temp_free_i32(tmp2);
7063 neon_store_reg(rd, pass, tmp);
7065 } /* for pass */
7066 } else if (op < 10) {
7067 /* Shift by immediate and narrow:
7068 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
7069 int input_unsigned = (op == 8) ? !u : u;
7070 if (rm & 1) {
7071 return 1;
7073 shift = shift - (1 << (size + 3));
7074 size++;
7075 if (size == 3) {
7076 tmp64 = tcg_const_i64(shift);
7077 neon_load_reg64(cpu_V0, rm);
7078 neon_load_reg64(cpu_V1, rm + 1);
7079 for (pass = 0; pass < 2; pass++) {
7080 TCGv_i64 in;
7081 if (pass == 0) {
7082 in = cpu_V0;
7083 } else {
7084 in = cpu_V1;
7086 if (q) {
7087 if (input_unsigned) {
7088 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
7089 } else {
7090 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
7092 } else {
7093 if (input_unsigned) {
7094 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
7095 } else {
7096 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
7099 tmp = tcg_temp_new_i32();
7100 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
7101 neon_store_reg(rd, pass, tmp);
7102 } /* for pass */
7103 tcg_temp_free_i64(tmp64);
7104 } else {
7105 if (size == 1) {
7106 imm = (uint16_t)shift;
7107 imm |= imm << 16;
7108 } else {
7109 /* size == 2 */
7110 imm = (uint32_t)shift;
7112 tmp2 = tcg_const_i32(imm);
7113 tmp4 = neon_load_reg(rm + 1, 0);
7114 tmp5 = neon_load_reg(rm + 1, 1);
7115 for (pass = 0; pass < 2; pass++) {
7116 if (pass == 0) {
7117 tmp = neon_load_reg(rm, 0);
7118 } else {
7119 tmp = tmp4;
7121 gen_neon_shift_narrow(size, tmp, tmp2, q,
7122 input_unsigned);
7123 if (pass == 0) {
7124 tmp3 = neon_load_reg(rm, 1);
7125 } else {
7126 tmp3 = tmp5;
7128 gen_neon_shift_narrow(size, tmp3, tmp2, q,
7129 input_unsigned);
7130 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
7131 tcg_temp_free_i32(tmp);
7132 tcg_temp_free_i32(tmp3);
7133 tmp = tcg_temp_new_i32();
7134 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
7135 neon_store_reg(rd, pass, tmp);
7136 } /* for pass */
7137 tcg_temp_free_i32(tmp2);
7139 } else if (op == 10) {
7140 /* VSHLL, VMOVL */
7141 if (q || (rd & 1)) {
7142 return 1;
7144 tmp = neon_load_reg(rm, 0);
7145 tmp2 = neon_load_reg(rm, 1);
7146 for (pass = 0; pass < 2; pass++) {
7147 if (pass == 1)
7148 tmp = tmp2;
7150 gen_neon_widen(cpu_V0, tmp, size, u);
7152 if (shift != 0) {
7153 /* The shift is less than the width of the source
7154 type, so we can just shift the whole register. */
7155 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
7156 /* Widen the result of shift: we need to clear
7157 * the potential overflow bits resulting from
7158 * left bits of the narrow input appearing as
7159 * right bits of left the neighbour narrow
7160 * input. */
7161 if (size < 2 || !u) {
7162 uint64_t imm64;
7163 if (size == 0) {
7164 imm = (0xffu >> (8 - shift));
7165 imm |= imm << 16;
7166 } else if (size == 1) {
7167 imm = 0xffff >> (16 - shift);
7168 } else {
7169 /* size == 2 */
7170 imm = 0xffffffff >> (32 - shift);
7172 if (size < 2) {
7173 imm64 = imm | (((uint64_t)imm) << 32);
7174 } else {
7175 imm64 = imm;
7177 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
7180 neon_store_reg64(cpu_V0, rd + pass);
7182 } else if (op >= 14) {
7183 /* VCVT fixed-point. */
7184 if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
7185 return 1;
7187 /* We have already masked out the must-be-1 top bit of imm6,
7188 * hence this 32-shift where the ARM ARM has 64-imm6.
7190 shift = 32 - shift;
7191 for (pass = 0; pass < (q ? 4 : 2); pass++) {
7192 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
7193 if (!(op & 1)) {
7194 if (u)
7195 gen_vfp_ulto(0, shift, 1);
7196 else
7197 gen_vfp_slto(0, shift, 1);
7198 } else {
7199 if (u)
7200 gen_vfp_toul(0, shift, 1);
7201 else
7202 gen_vfp_tosl(0, shift, 1);
7204 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
7206 } else {
7207 return 1;
7209 } else { /* (insn & 0x00380080) == 0 */
7210 int invert, reg_ofs, vec_size;
7212 if (q && (rd & 1)) {
7213 return 1;
7216 op = (insn >> 8) & 0xf;
7217 /* One register and immediate. */
7218 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
7219 invert = (insn & (1 << 5)) != 0;
7220 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
7221 * We choose to not special-case this and will behave as if a
7222 * valid constant encoding of 0 had been given.
7224 switch (op) {
7225 case 0: case 1:
7226 /* no-op */
7227 break;
7228 case 2: case 3:
7229 imm <<= 8;
7230 break;
7231 case 4: case 5:
7232 imm <<= 16;
7233 break;
7234 case 6: case 7:
7235 imm <<= 24;
7236 break;
7237 case 8: case 9:
7238 imm |= imm << 16;
7239 break;
7240 case 10: case 11:
7241 imm = (imm << 8) | (imm << 24);
7242 break;
7243 case 12:
7244 imm = (imm << 8) | 0xff;
7245 break;
7246 case 13:
7247 imm = (imm << 16) | 0xffff;
7248 break;
7249 case 14:
7250 imm |= (imm << 8) | (imm << 16) | (imm << 24);
7251 if (invert) {
7252 imm = ~imm;
7254 break;
7255 case 15:
7256 if (invert) {
7257 return 1;
7259 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
7260 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
7261 break;
7263 if (invert) {
7264 imm = ~imm;
7267 reg_ofs = neon_reg_offset(rd, 0);
7268 vec_size = q ? 16 : 8;
7270 if (op & 1 && op < 12) {
7271 if (invert) {
7272 /* The immediate value has already been inverted,
7273 * so BIC becomes AND.
7275 tcg_gen_gvec_andi(MO_32, reg_ofs, reg_ofs, imm,
7276 vec_size, vec_size);
7277 } else {
7278 tcg_gen_gvec_ori(MO_32, reg_ofs, reg_ofs, imm,
7279 vec_size, vec_size);
7281 } else {
7282 /* VMOV, VMVN. */
7283 if (op == 14 && invert) {
7284 TCGv_i64 t64 = tcg_temp_new_i64();
7286 for (pass = 0; pass <= q; ++pass) {
7287 uint64_t val = 0;
7288 int n;
7290 for (n = 0; n < 8; n++) {
7291 if (imm & (1 << (n + pass * 8))) {
7292 val |= 0xffull << (n * 8);
7295 tcg_gen_movi_i64(t64, val);
7296 neon_store_reg64(t64, rd + pass);
7298 tcg_temp_free_i64(t64);
7299 } else {
7300 tcg_gen_gvec_dup32i(reg_ofs, vec_size, vec_size, imm);
7304 } else { /* (insn & 0x00800010 == 0x00800000) */
7305 if (size != 3) {
7306 op = (insn >> 8) & 0xf;
7307 if ((insn & (1 << 6)) == 0) {
7308 /* Three registers of different lengths. */
7309 int src1_wide;
7310 int src2_wide;
7311 int prewiden;
7312 /* undefreq: bit 0 : UNDEF if size == 0
7313 * bit 1 : UNDEF if size == 1
7314 * bit 2 : UNDEF if size == 2
7315 * bit 3 : UNDEF if U == 1
7316 * Note that [2:0] set implies 'always UNDEF'
7318 int undefreq;
7319 /* prewiden, src1_wide, src2_wide, undefreq */
7320 static const int neon_3reg_wide[16][4] = {
7321 {1, 0, 0, 0}, /* VADDL */
7322 {1, 1, 0, 0}, /* VADDW */
7323 {1, 0, 0, 0}, /* VSUBL */
7324 {1, 1, 0, 0}, /* VSUBW */
7325 {0, 1, 1, 0}, /* VADDHN */
7326 {0, 0, 0, 0}, /* VABAL */
7327 {0, 1, 1, 0}, /* VSUBHN */
7328 {0, 0, 0, 0}, /* VABDL */
7329 {0, 0, 0, 0}, /* VMLAL */
7330 {0, 0, 0, 9}, /* VQDMLAL */
7331 {0, 0, 0, 0}, /* VMLSL */
7332 {0, 0, 0, 9}, /* VQDMLSL */
7333 {0, 0, 0, 0}, /* Integer VMULL */
7334 {0, 0, 0, 1}, /* VQDMULL */
7335 {0, 0, 0, 0xa}, /* Polynomial VMULL */
7336 {0, 0, 0, 7}, /* Reserved: always UNDEF */
7339 prewiden = neon_3reg_wide[op][0];
7340 src1_wide = neon_3reg_wide[op][1];
7341 src2_wide = neon_3reg_wide[op][2];
7342 undefreq = neon_3reg_wide[op][3];
7344 if ((undefreq & (1 << size)) ||
7345 ((undefreq & 8) && u)) {
7346 return 1;
7348 if ((src1_wide && (rn & 1)) ||
7349 (src2_wide && (rm & 1)) ||
7350 (!src2_wide && (rd & 1))) {
7351 return 1;
7354 /* Handle VMULL.P64 (Polynomial 64x64 to 128 bit multiply)
7355 * outside the loop below as it only performs a single pass.
7357 if (op == 14 && size == 2) {
7358 TCGv_i64 tcg_rn, tcg_rm, tcg_rd;
7360 if (!dc_isar_feature(aa32_pmull, s)) {
7361 return 1;
7363 tcg_rn = tcg_temp_new_i64();
7364 tcg_rm = tcg_temp_new_i64();
7365 tcg_rd = tcg_temp_new_i64();
7366 neon_load_reg64(tcg_rn, rn);
7367 neon_load_reg64(tcg_rm, rm);
7368 gen_helper_neon_pmull_64_lo(tcg_rd, tcg_rn, tcg_rm);
7369 neon_store_reg64(tcg_rd, rd);
7370 gen_helper_neon_pmull_64_hi(tcg_rd, tcg_rn, tcg_rm);
7371 neon_store_reg64(tcg_rd, rd + 1);
7372 tcg_temp_free_i64(tcg_rn);
7373 tcg_temp_free_i64(tcg_rm);
7374 tcg_temp_free_i64(tcg_rd);
7375 return 0;
7378 /* Avoid overlapping operands. Wide source operands are
7379 always aligned so will never overlap with wide
7380 destinations in problematic ways. */
7381 if (rd == rm && !src2_wide) {
7382 tmp = neon_load_reg(rm, 1);
7383 neon_store_scratch(2, tmp);
7384 } else if (rd == rn && !src1_wide) {
7385 tmp = neon_load_reg(rn, 1);
7386 neon_store_scratch(2, tmp);
7388 tmp3 = NULL;
7389 for (pass = 0; pass < 2; pass++) {
7390 if (src1_wide) {
7391 neon_load_reg64(cpu_V0, rn + pass);
7392 tmp = NULL;
7393 } else {
7394 if (pass == 1 && rd == rn) {
7395 tmp = neon_load_scratch(2);
7396 } else {
7397 tmp = neon_load_reg(rn, pass);
7399 if (prewiden) {
7400 gen_neon_widen(cpu_V0, tmp, size, u);
7403 if (src2_wide) {
7404 neon_load_reg64(cpu_V1, rm + pass);
7405 tmp2 = NULL;
7406 } else {
7407 if (pass == 1 && rd == rm) {
7408 tmp2 = neon_load_scratch(2);
7409 } else {
7410 tmp2 = neon_load_reg(rm, pass);
7412 if (prewiden) {
7413 gen_neon_widen(cpu_V1, tmp2, size, u);
7416 switch (op) {
7417 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
7418 gen_neon_addl(size);
7419 break;
7420 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
7421 gen_neon_subl(size);
7422 break;
7423 case 5: case 7: /* VABAL, VABDL */
7424 switch ((size << 1) | u) {
7425 case 0:
7426 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
7427 break;
7428 case 1:
7429 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
7430 break;
7431 case 2:
7432 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
7433 break;
7434 case 3:
7435 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
7436 break;
7437 case 4:
7438 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
7439 break;
7440 case 5:
7441 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
7442 break;
7443 default: abort();
7445 tcg_temp_free_i32(tmp2);
7446 tcg_temp_free_i32(tmp);
7447 break;
7448 case 8: case 9: case 10: case 11: case 12: case 13:
7449 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
7450 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
7451 break;
7452 case 14: /* Polynomial VMULL */
7453 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
7454 tcg_temp_free_i32(tmp2);
7455 tcg_temp_free_i32(tmp);
7456 break;
7457 default: /* 15 is RESERVED: caught earlier */
7458 abort();
7460 if (op == 13) {
7461 /* VQDMULL */
7462 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
7463 neon_store_reg64(cpu_V0, rd + pass);
7464 } else if (op == 5 || (op >= 8 && op <= 11)) {
7465 /* Accumulate. */
7466 neon_load_reg64(cpu_V1, rd + pass);
7467 switch (op) {
7468 case 10: /* VMLSL */
7469 gen_neon_negl(cpu_V0, size);
7470 /* Fall through */
7471 case 5: case 8: /* VABAL, VMLAL */
7472 gen_neon_addl(size);
7473 break;
7474 case 9: case 11: /* VQDMLAL, VQDMLSL */
7475 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
7476 if (op == 11) {
7477 gen_neon_negl(cpu_V0, size);
7479 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
7480 break;
7481 default:
7482 abort();
7484 neon_store_reg64(cpu_V0, rd + pass);
7485 } else if (op == 4 || op == 6) {
7486 /* Narrowing operation. */
7487 tmp = tcg_temp_new_i32();
7488 if (!u) {
7489 switch (size) {
7490 case 0:
7491 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
7492 break;
7493 case 1:
7494 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
7495 break;
7496 case 2:
7497 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
7498 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
7499 break;
7500 default: abort();
7502 } else {
7503 switch (size) {
7504 case 0:
7505 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
7506 break;
7507 case 1:
7508 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
7509 break;
7510 case 2:
7511 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
7512 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
7513 tcg_gen_extrl_i64_i32(tmp, cpu_V0);
7514 break;
7515 default: abort();
7518 if (pass == 0) {
7519 tmp3 = tmp;
7520 } else {
7521 neon_store_reg(rd, 0, tmp3);
7522 neon_store_reg(rd, 1, tmp);
7524 } else {
7525 /* Write back the result. */
7526 neon_store_reg64(cpu_V0, rd + pass);
7529 } else {
7530 /* Two registers and a scalar. NB that for ops of this form
7531 * the ARM ARM labels bit 24 as Q, but it is in our variable
7532 * 'u', not 'q'.
7534 if (size == 0) {
7535 return 1;
7537 switch (op) {
7538 case 1: /* Float VMLA scalar */
7539 case 5: /* Floating point VMLS scalar */
7540 case 9: /* Floating point VMUL scalar */
7541 if (size == 1) {
7542 return 1;
7544 /* fall through */
7545 case 0: /* Integer VMLA scalar */
7546 case 4: /* Integer VMLS scalar */
7547 case 8: /* Integer VMUL scalar */
7548 case 12: /* VQDMULH scalar */
7549 case 13: /* VQRDMULH scalar */
7550 if (u && ((rd | rn) & 1)) {
7551 return 1;
7553 tmp = neon_get_scalar(size, rm);
7554 neon_store_scratch(0, tmp);
7555 for (pass = 0; pass < (u ? 4 : 2); pass++) {
7556 tmp = neon_load_scratch(0);
7557 tmp2 = neon_load_reg(rn, pass);
7558 if (op == 12) {
7559 if (size == 1) {
7560 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
7561 } else {
7562 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
7564 } else if (op == 13) {
7565 if (size == 1) {
7566 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
7567 } else {
7568 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
7570 } else if (op & 1) {
7571 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7572 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
7573 tcg_temp_free_ptr(fpstatus);
7574 } else {
7575 switch (size) {
7576 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
7577 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
7578 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
7579 default: abort();
7582 tcg_temp_free_i32(tmp2);
7583 if (op < 8) {
7584 /* Accumulate. */
7585 tmp2 = neon_load_reg(rd, pass);
7586 switch (op) {
7587 case 0:
7588 gen_neon_add(size, tmp, tmp2);
7589 break;
7590 case 1:
7592 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7593 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
7594 tcg_temp_free_ptr(fpstatus);
7595 break;
7597 case 4:
7598 gen_neon_rsb(size, tmp, tmp2);
7599 break;
7600 case 5:
7602 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
7603 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
7604 tcg_temp_free_ptr(fpstatus);
7605 break;
7607 default:
7608 abort();
7610 tcg_temp_free_i32(tmp2);
7612 neon_store_reg(rd, pass, tmp);
7614 break;
7615 case 3: /* VQDMLAL scalar */
7616 case 7: /* VQDMLSL scalar */
7617 case 11: /* VQDMULL scalar */
7618 if (u == 1) {
7619 return 1;
7621 /* fall through */
7622 case 2: /* VMLAL sclar */
7623 case 6: /* VMLSL scalar */
7624 case 10: /* VMULL scalar */
7625 if (rd & 1) {
7626 return 1;
7628 tmp2 = neon_get_scalar(size, rm);
7629 /* We need a copy of tmp2 because gen_neon_mull
7630 * deletes it during pass 0. */
7631 tmp4 = tcg_temp_new_i32();
7632 tcg_gen_mov_i32(tmp4, tmp2);
7633 tmp3 = neon_load_reg(rn, 1);
7635 for (pass = 0; pass < 2; pass++) {
7636 if (pass == 0) {
7637 tmp = neon_load_reg(rn, 0);
7638 } else {
7639 tmp = tmp3;
7640 tmp2 = tmp4;
7642 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
7643 if (op != 11) {
7644 neon_load_reg64(cpu_V1, rd + pass);
7646 switch (op) {
7647 case 6:
7648 gen_neon_negl(cpu_V0, size);
7649 /* Fall through */
7650 case 2:
7651 gen_neon_addl(size);
7652 break;
7653 case 3: case 7:
7654 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
7655 if (op == 7) {
7656 gen_neon_negl(cpu_V0, size);
7658 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
7659 break;
7660 case 10:
7661 /* no-op */
7662 break;
7663 case 11:
7664 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
7665 break;
7666 default:
7667 abort();
7669 neon_store_reg64(cpu_V0, rd + pass);
7671 break;
7672 case 14: /* VQRDMLAH scalar */
7673 case 15: /* VQRDMLSH scalar */
7675 NeonGenThreeOpEnvFn *fn;
7677 if (!dc_isar_feature(aa32_rdm, s)) {
7678 return 1;
7680 if (u && ((rd | rn) & 1)) {
7681 return 1;
7683 if (op == 14) {
7684 if (size == 1) {
7685 fn = gen_helper_neon_qrdmlah_s16;
7686 } else {
7687 fn = gen_helper_neon_qrdmlah_s32;
7689 } else {
7690 if (size == 1) {
7691 fn = gen_helper_neon_qrdmlsh_s16;
7692 } else {
7693 fn = gen_helper_neon_qrdmlsh_s32;
7697 tmp2 = neon_get_scalar(size, rm);
7698 for (pass = 0; pass < (u ? 4 : 2); pass++) {
7699 tmp = neon_load_reg(rn, pass);
7700 tmp3 = neon_load_reg(rd, pass);
7701 fn(tmp, cpu_env, tmp, tmp2, tmp3);
7702 tcg_temp_free_i32(tmp3);
7703 neon_store_reg(rd, pass, tmp);
7705 tcg_temp_free_i32(tmp2);
7707 break;
7708 default:
7709 g_assert_not_reached();
7712 } else { /* size == 3 */
7713 if (!u) {
7714 /* Extract. */
7715 imm = (insn >> 8) & 0xf;
7717 if (imm > 7 && !q)
7718 return 1;
7720 if (q && ((rd | rn | rm) & 1)) {
7721 return 1;
7724 if (imm == 0) {
7725 neon_load_reg64(cpu_V0, rn);
7726 if (q) {
7727 neon_load_reg64(cpu_V1, rn + 1);
7729 } else if (imm == 8) {
7730 neon_load_reg64(cpu_V0, rn + 1);
7731 if (q) {
7732 neon_load_reg64(cpu_V1, rm);
7734 } else if (q) {
7735 tmp64 = tcg_temp_new_i64();
7736 if (imm < 8) {
7737 neon_load_reg64(cpu_V0, rn);
7738 neon_load_reg64(tmp64, rn + 1);
7739 } else {
7740 neon_load_reg64(cpu_V0, rn + 1);
7741 neon_load_reg64(tmp64, rm);
7743 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
7744 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
7745 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
7746 if (imm < 8) {
7747 neon_load_reg64(cpu_V1, rm);
7748 } else {
7749 neon_load_reg64(cpu_V1, rm + 1);
7750 imm -= 8;
7752 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
7753 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
7754 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
7755 tcg_temp_free_i64(tmp64);
7756 } else {
7757 /* BUGFIX */
7758 neon_load_reg64(cpu_V0, rn);
7759 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
7760 neon_load_reg64(cpu_V1, rm);
7761 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
7762 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
7764 neon_store_reg64(cpu_V0, rd);
7765 if (q) {
7766 neon_store_reg64(cpu_V1, rd + 1);
7768 } else if ((insn & (1 << 11)) == 0) {
7769 /* Two register misc. */
7770 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
7771 size = (insn >> 18) & 3;
7772 /* UNDEF for unknown op values and bad op-size combinations */
7773 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
7774 return 1;
7776 if (neon_2rm_is_v8_op(op) &&
7777 !arm_dc_feature(s, ARM_FEATURE_V8)) {
7778 return 1;
7780 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
7781 q && ((rm | rd) & 1)) {
7782 return 1;
7784 switch (op) {
7785 case NEON_2RM_VREV64:
7786 for (pass = 0; pass < (q ? 2 : 1); pass++) {
7787 tmp = neon_load_reg(rm, pass * 2);
7788 tmp2 = neon_load_reg(rm, pass * 2 + 1);
7789 switch (size) {
7790 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
7791 case 1: gen_swap_half(tmp); break;
7792 case 2: /* no-op */ break;
7793 default: abort();
7795 neon_store_reg(rd, pass * 2 + 1, tmp);
7796 if (size == 2) {
7797 neon_store_reg(rd, pass * 2, tmp2);
7798 } else {
7799 switch (size) {
7800 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
7801 case 1: gen_swap_half(tmp2); break;
7802 default: abort();
7804 neon_store_reg(rd, pass * 2, tmp2);
7807 break;
7808 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
7809 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
7810 for (pass = 0; pass < q + 1; pass++) {
7811 tmp = neon_load_reg(rm, pass * 2);
7812 gen_neon_widen(cpu_V0, tmp, size, op & 1);
7813 tmp = neon_load_reg(rm, pass * 2 + 1);
7814 gen_neon_widen(cpu_V1, tmp, size, op & 1);
7815 switch (size) {
7816 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
7817 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
7818 case 2: tcg_gen_add_i64(CPU_V001); break;
7819 default: abort();
7821 if (op >= NEON_2RM_VPADAL) {
7822 /* Accumulate. */
7823 neon_load_reg64(cpu_V1, rd + pass);
7824 gen_neon_addl(size);
7826 neon_store_reg64(cpu_V0, rd + pass);
7828 break;
7829 case NEON_2RM_VTRN:
7830 if (size == 2) {
7831 int n;
7832 for (n = 0; n < (q ? 4 : 2); n += 2) {
7833 tmp = neon_load_reg(rm, n);
7834 tmp2 = neon_load_reg(rd, n + 1);
7835 neon_store_reg(rm, n, tmp2);
7836 neon_store_reg(rd, n + 1, tmp);
7838 } else {
7839 goto elementwise;
7841 break;
7842 case NEON_2RM_VUZP:
7843 if (gen_neon_unzip(rd, rm, size, q)) {
7844 return 1;
7846 break;
7847 case NEON_2RM_VZIP:
7848 if (gen_neon_zip(rd, rm, size, q)) {
7849 return 1;
7851 break;
7852 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
7853 /* also VQMOVUN; op field and mnemonics don't line up */
7854 if (rm & 1) {
7855 return 1;
7857 tmp2 = NULL;
7858 for (pass = 0; pass < 2; pass++) {
7859 neon_load_reg64(cpu_V0, rm + pass);
7860 tmp = tcg_temp_new_i32();
7861 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
7862 tmp, cpu_V0);
7863 if (pass == 0) {
7864 tmp2 = tmp;
7865 } else {
7866 neon_store_reg(rd, 0, tmp2);
7867 neon_store_reg(rd, 1, tmp);
7870 break;
7871 case NEON_2RM_VSHLL:
7872 if (q || (rd & 1)) {
7873 return 1;
7875 tmp = neon_load_reg(rm, 0);
7876 tmp2 = neon_load_reg(rm, 1);
7877 for (pass = 0; pass < 2; pass++) {
7878 if (pass == 1)
7879 tmp = tmp2;
7880 gen_neon_widen(cpu_V0, tmp, size, 1);
7881 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
7882 neon_store_reg64(cpu_V0, rd + pass);
7884 break;
7885 case NEON_2RM_VCVT_F16_F32:
7887 TCGv_ptr fpst;
7888 TCGv_i32 ahp;
7890 if (!dc_isar_feature(aa32_fp16_spconv, s) ||
7891 q || (rm & 1)) {
7892 return 1;
7894 tmp = tcg_temp_new_i32();
7895 tmp2 = tcg_temp_new_i32();
7896 fpst = get_fpstatus_ptr(true);
7897 ahp = get_ahp_flag();
7898 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
7899 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, fpst, ahp);
7900 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
7901 gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, fpst, ahp);
7902 tcg_gen_shli_i32(tmp2, tmp2, 16);
7903 tcg_gen_or_i32(tmp2, tmp2, tmp);
7904 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
7905 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, fpst, ahp);
7906 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
7907 neon_store_reg(rd, 0, tmp2);
7908 tmp2 = tcg_temp_new_i32();
7909 gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, fpst, ahp);
7910 tcg_gen_shli_i32(tmp2, tmp2, 16);
7911 tcg_gen_or_i32(tmp2, tmp2, tmp);
7912 neon_store_reg(rd, 1, tmp2);
7913 tcg_temp_free_i32(tmp);
7914 tcg_temp_free_i32(ahp);
7915 tcg_temp_free_ptr(fpst);
7916 break;
7918 case NEON_2RM_VCVT_F32_F16:
7920 TCGv_ptr fpst;
7921 TCGv_i32 ahp;
7922 if (!dc_isar_feature(aa32_fp16_spconv, s) ||
7923 q || (rd & 1)) {
7924 return 1;
7926 fpst = get_fpstatus_ptr(true);
7927 ahp = get_ahp_flag();
7928 tmp3 = tcg_temp_new_i32();
7929 tmp = neon_load_reg(rm, 0);
7930 tmp2 = neon_load_reg(rm, 1);
7931 tcg_gen_ext16u_i32(tmp3, tmp);
7932 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
7933 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
7934 tcg_gen_shri_i32(tmp3, tmp, 16);
7935 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
7936 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
7937 tcg_temp_free_i32(tmp);
7938 tcg_gen_ext16u_i32(tmp3, tmp2);
7939 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
7940 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
7941 tcg_gen_shri_i32(tmp3, tmp2, 16);
7942 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, fpst, ahp);
7943 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
7944 tcg_temp_free_i32(tmp2);
7945 tcg_temp_free_i32(tmp3);
7946 tcg_temp_free_i32(ahp);
7947 tcg_temp_free_ptr(fpst);
7948 break;
7950 case NEON_2RM_AESE: case NEON_2RM_AESMC:
7951 if (!dc_isar_feature(aa32_aes, s) || ((rm | rd) & 1)) {
7952 return 1;
7954 ptr1 = vfp_reg_ptr(true, rd);
7955 ptr2 = vfp_reg_ptr(true, rm);
7957 /* Bit 6 is the lowest opcode bit; it distinguishes between
7958 * encryption (AESE/AESMC) and decryption (AESD/AESIMC)
7960 tmp3 = tcg_const_i32(extract32(insn, 6, 1));
7962 if (op == NEON_2RM_AESE) {
7963 gen_helper_crypto_aese(ptr1, ptr2, tmp3);
7964 } else {
7965 gen_helper_crypto_aesmc(ptr1, ptr2, tmp3);
7967 tcg_temp_free_ptr(ptr1);
7968 tcg_temp_free_ptr(ptr2);
7969 tcg_temp_free_i32(tmp3);
7970 break;
7971 case NEON_2RM_SHA1H:
7972 if (!dc_isar_feature(aa32_sha1, s) || ((rm | rd) & 1)) {
7973 return 1;
7975 ptr1 = vfp_reg_ptr(true, rd);
7976 ptr2 = vfp_reg_ptr(true, rm);
7978 gen_helper_crypto_sha1h(ptr1, ptr2);
7980 tcg_temp_free_ptr(ptr1);
7981 tcg_temp_free_ptr(ptr2);
7982 break;
7983 case NEON_2RM_SHA1SU1:
7984 if ((rm | rd) & 1) {
7985 return 1;
7987 /* bit 6 (q): set -> SHA256SU0, cleared -> SHA1SU1 */
7988 if (q) {
7989 if (!dc_isar_feature(aa32_sha2, s)) {
7990 return 1;
7992 } else if (!dc_isar_feature(aa32_sha1, s)) {
7993 return 1;
7995 ptr1 = vfp_reg_ptr(true, rd);
7996 ptr2 = vfp_reg_ptr(true, rm);
7997 if (q) {
7998 gen_helper_crypto_sha256su0(ptr1, ptr2);
7999 } else {
8000 gen_helper_crypto_sha1su1(ptr1, ptr2);
8002 tcg_temp_free_ptr(ptr1);
8003 tcg_temp_free_ptr(ptr2);
8004 break;
8006 case NEON_2RM_VMVN:
8007 tcg_gen_gvec_not(0, rd_ofs, rm_ofs, vec_size, vec_size);
8008 break;
8009 case NEON_2RM_VNEG:
8010 tcg_gen_gvec_neg(size, rd_ofs, rm_ofs, vec_size, vec_size);
8011 break;
8013 default:
8014 elementwise:
8015 for (pass = 0; pass < (q ? 4 : 2); pass++) {
8016 if (neon_2rm_is_float_op(op)) {
8017 tcg_gen_ld_f32(cpu_F0s, cpu_env,
8018 neon_reg_offset(rm, pass));
8019 tmp = NULL;
8020 } else {
8021 tmp = neon_load_reg(rm, pass);
8023 switch (op) {
8024 case NEON_2RM_VREV32:
8025 switch (size) {
8026 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
8027 case 1: gen_swap_half(tmp); break;
8028 default: abort();
8030 break;
8031 case NEON_2RM_VREV16:
8032 gen_rev16(tmp);
8033 break;
8034 case NEON_2RM_VCLS:
8035 switch (size) {
8036 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
8037 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
8038 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
8039 default: abort();
8041 break;
8042 case NEON_2RM_VCLZ:
8043 switch (size) {
8044 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
8045 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
8046 case 2: tcg_gen_clzi_i32(tmp, tmp, 32); break;
8047 default: abort();
8049 break;
8050 case NEON_2RM_VCNT:
8051 gen_helper_neon_cnt_u8(tmp, tmp);
8052 break;
8053 case NEON_2RM_VQABS:
8054 switch (size) {
8055 case 0:
8056 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
8057 break;
8058 case 1:
8059 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
8060 break;
8061 case 2:
8062 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
8063 break;
8064 default: abort();
8066 break;
8067 case NEON_2RM_VQNEG:
8068 switch (size) {
8069 case 0:
8070 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
8071 break;
8072 case 1:
8073 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
8074 break;
8075 case 2:
8076 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
8077 break;
8078 default: abort();
8080 break;
8081 case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
8082 tmp2 = tcg_const_i32(0);
8083 switch(size) {
8084 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
8085 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
8086 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
8087 default: abort();
8089 tcg_temp_free_i32(tmp2);
8090 if (op == NEON_2RM_VCLE0) {
8091 tcg_gen_not_i32(tmp, tmp);
8093 break;
8094 case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
8095 tmp2 = tcg_const_i32(0);
8096 switch(size) {
8097 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
8098 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
8099 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
8100 default: abort();
8102 tcg_temp_free_i32(tmp2);
8103 if (op == NEON_2RM_VCLT0) {
8104 tcg_gen_not_i32(tmp, tmp);
8106 break;
8107 case NEON_2RM_VCEQ0:
8108 tmp2 = tcg_const_i32(0);
8109 switch(size) {
8110 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
8111 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
8112 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
8113 default: abort();
8115 tcg_temp_free_i32(tmp2);
8116 break;
8117 case NEON_2RM_VABS:
8118 switch(size) {
8119 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
8120 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
8121 case 2: tcg_gen_abs_i32(tmp, tmp); break;
8122 default: abort();
8124 break;
8125 case NEON_2RM_VCGT0_F:
8127 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8128 tmp2 = tcg_const_i32(0);
8129 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
8130 tcg_temp_free_i32(tmp2);
8131 tcg_temp_free_ptr(fpstatus);
8132 break;
8134 case NEON_2RM_VCGE0_F:
8136 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8137 tmp2 = tcg_const_i32(0);
8138 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
8139 tcg_temp_free_i32(tmp2);
8140 tcg_temp_free_ptr(fpstatus);
8141 break;
8143 case NEON_2RM_VCEQ0_F:
8145 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8146 tmp2 = tcg_const_i32(0);
8147 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
8148 tcg_temp_free_i32(tmp2);
8149 tcg_temp_free_ptr(fpstatus);
8150 break;
8152 case NEON_2RM_VCLE0_F:
8154 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8155 tmp2 = tcg_const_i32(0);
8156 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
8157 tcg_temp_free_i32(tmp2);
8158 tcg_temp_free_ptr(fpstatus);
8159 break;
8161 case NEON_2RM_VCLT0_F:
8163 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8164 tmp2 = tcg_const_i32(0);
8165 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
8166 tcg_temp_free_i32(tmp2);
8167 tcg_temp_free_ptr(fpstatus);
8168 break;
8170 case NEON_2RM_VABS_F:
8171 gen_vfp_abs(0);
8172 break;
8173 case NEON_2RM_VNEG_F:
8174 gen_vfp_neg(0);
8175 break;
8176 case NEON_2RM_VSWP:
8177 tmp2 = neon_load_reg(rd, pass);
8178 neon_store_reg(rm, pass, tmp2);
8179 break;
8180 case NEON_2RM_VTRN:
8181 tmp2 = neon_load_reg(rd, pass);
8182 switch (size) {
8183 case 0: gen_neon_trn_u8(tmp, tmp2); break;
8184 case 1: gen_neon_trn_u16(tmp, tmp2); break;
8185 default: abort();
8187 neon_store_reg(rm, pass, tmp2);
8188 break;
8189 case NEON_2RM_VRINTN:
8190 case NEON_2RM_VRINTA:
8191 case NEON_2RM_VRINTM:
8192 case NEON_2RM_VRINTP:
8193 case NEON_2RM_VRINTZ:
8195 TCGv_i32 tcg_rmode;
8196 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8197 int rmode;
8199 if (op == NEON_2RM_VRINTZ) {
8200 rmode = FPROUNDING_ZERO;
8201 } else {
8202 rmode = fp_decode_rm[((op & 0x6) >> 1) ^ 1];
8205 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
8206 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
8207 cpu_env);
8208 gen_helper_rints(cpu_F0s, cpu_F0s, fpstatus);
8209 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
8210 cpu_env);
8211 tcg_temp_free_ptr(fpstatus);
8212 tcg_temp_free_i32(tcg_rmode);
8213 break;
8215 case NEON_2RM_VRINTX:
8217 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8218 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpstatus);
8219 tcg_temp_free_ptr(fpstatus);
8220 break;
8222 case NEON_2RM_VCVTAU:
8223 case NEON_2RM_VCVTAS:
8224 case NEON_2RM_VCVTNU:
8225 case NEON_2RM_VCVTNS:
8226 case NEON_2RM_VCVTPU:
8227 case NEON_2RM_VCVTPS:
8228 case NEON_2RM_VCVTMU:
8229 case NEON_2RM_VCVTMS:
8231 bool is_signed = !extract32(insn, 7, 1);
8232 TCGv_ptr fpst = get_fpstatus_ptr(1);
8233 TCGv_i32 tcg_rmode, tcg_shift;
8234 int rmode = fp_decode_rm[extract32(insn, 8, 2)];
8236 tcg_shift = tcg_const_i32(0);
8237 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
8238 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
8239 cpu_env);
8241 if (is_signed) {
8242 gen_helper_vfp_tosls(cpu_F0s, cpu_F0s,
8243 tcg_shift, fpst);
8244 } else {
8245 gen_helper_vfp_touls(cpu_F0s, cpu_F0s,
8246 tcg_shift, fpst);
8249 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
8250 cpu_env);
8251 tcg_temp_free_i32(tcg_rmode);
8252 tcg_temp_free_i32(tcg_shift);
8253 tcg_temp_free_ptr(fpst);
8254 break;
8256 case NEON_2RM_VRECPE:
8258 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8259 gen_helper_recpe_u32(tmp, tmp, fpstatus);
8260 tcg_temp_free_ptr(fpstatus);
8261 break;
8263 case NEON_2RM_VRSQRTE:
8265 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8266 gen_helper_rsqrte_u32(tmp, tmp, fpstatus);
8267 tcg_temp_free_ptr(fpstatus);
8268 break;
8270 case NEON_2RM_VRECPE_F:
8272 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8273 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, fpstatus);
8274 tcg_temp_free_ptr(fpstatus);
8275 break;
8277 case NEON_2RM_VRSQRTE_F:
8279 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
8280 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, fpstatus);
8281 tcg_temp_free_ptr(fpstatus);
8282 break;
8284 case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
8285 gen_vfp_sito(0, 1);
8286 break;
8287 case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
8288 gen_vfp_uito(0, 1);
8289 break;
8290 case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
8291 gen_vfp_tosiz(0, 1);
8292 break;
8293 case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
8294 gen_vfp_touiz(0, 1);
8295 break;
8296 default:
8297 /* Reserved op values were caught by the
8298 * neon_2rm_sizes[] check earlier.
8300 abort();
8302 if (neon_2rm_is_float_op(op)) {
8303 tcg_gen_st_f32(cpu_F0s, cpu_env,
8304 neon_reg_offset(rd, pass));
8305 } else {
8306 neon_store_reg(rd, pass, tmp);
8309 break;
8311 } else if ((insn & (1 << 10)) == 0) {
8312 /* VTBL, VTBX. */
8313 int n = ((insn >> 8) & 3) + 1;
8314 if ((rn + n) > 32) {
8315 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
8316 * helper function running off the end of the register file.
8318 return 1;
8320 n <<= 3;
8321 if (insn & (1 << 6)) {
8322 tmp = neon_load_reg(rd, 0);
8323 } else {
8324 tmp = tcg_temp_new_i32();
8325 tcg_gen_movi_i32(tmp, 0);
8327 tmp2 = neon_load_reg(rm, 0);
8328 ptr1 = vfp_reg_ptr(true, rn);
8329 tmp5 = tcg_const_i32(n);
8330 gen_helper_neon_tbl(tmp2, tmp2, tmp, ptr1, tmp5);
8331 tcg_temp_free_i32(tmp);
8332 if (insn & (1 << 6)) {
8333 tmp = neon_load_reg(rd, 1);
8334 } else {
8335 tmp = tcg_temp_new_i32();
8336 tcg_gen_movi_i32(tmp, 0);
8338 tmp3 = neon_load_reg(rm, 1);
8339 gen_helper_neon_tbl(tmp3, tmp3, tmp, ptr1, tmp5);
8340 tcg_temp_free_i32(tmp5);
8341 tcg_temp_free_ptr(ptr1);
8342 neon_store_reg(rd, 0, tmp2);
8343 neon_store_reg(rd, 1, tmp3);
8344 tcg_temp_free_i32(tmp);
8345 } else if ((insn & 0x380) == 0) {
8346 /* VDUP */
8347 int element;
8348 TCGMemOp size;
8350 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
8351 return 1;
8353 if (insn & (1 << 16)) {
8354 size = MO_8;
8355 element = (insn >> 17) & 7;
8356 } else if (insn & (1 << 17)) {
8357 size = MO_16;
8358 element = (insn >> 18) & 3;
8359 } else {
8360 size = MO_32;
8361 element = (insn >> 19) & 1;
8363 tcg_gen_gvec_dup_mem(size, neon_reg_offset(rd, 0),
8364 neon_element_offset(rm, element, size),
8365 q ? 16 : 8, q ? 16 : 8);
8366 } else {
8367 return 1;
8371 return 0;
8374 /* Advanced SIMD three registers of the same length extension.
8375 * 31 25 23 22 20 16 12 11 10 9 8 3 0
8376 * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
8377 * | 1 1 1 1 1 1 0 | op1 | D | op2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
8378 * +---------------+-----+---+-----+----+----+---+----+---+----+---------+----+
8380 static int disas_neon_insn_3same_ext(DisasContext *s, uint32_t insn)
8382 gen_helper_gvec_3 *fn_gvec = NULL;
8383 gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
8384 int rd, rn, rm, opr_sz;
8385 int data = 0;
8386 int off_rn, off_rm;
8387 bool is_long = false, q = extract32(insn, 6, 1);
8388 bool ptr_is_env = false;
8390 if ((insn & 0xfe200f10) == 0xfc200800) {
8391 /* VCMLA -- 1111 110R R.1S .... .... 1000 ...0 .... */
8392 int size = extract32(insn, 20, 1);
8393 data = extract32(insn, 23, 2); /* rot */
8394 if (!dc_isar_feature(aa32_vcma, s)
8395 || (!size && !dc_isar_feature(aa32_fp16_arith, s))) {
8396 return 1;
8398 fn_gvec_ptr = size ? gen_helper_gvec_fcmlas : gen_helper_gvec_fcmlah;
8399 } else if ((insn & 0xfea00f10) == 0xfc800800) {
8400 /* VCADD -- 1111 110R 1.0S .... .... 1000 ...0 .... */
8401 int size = extract32(insn, 20, 1);
8402 data = extract32(insn, 24, 1); /* rot */
8403 if (!dc_isar_feature(aa32_vcma, s)
8404 || (!size && !dc_isar_feature(aa32_fp16_arith, s))) {
8405 return 1;
8407 fn_gvec_ptr = size ? gen_helper_gvec_fcadds : gen_helper_gvec_fcaddh;
8408 } else if ((insn & 0xfeb00f00) == 0xfc200d00) {
8409 /* V[US]DOT -- 1111 1100 0.10 .... .... 1101 .Q.U .... */
8410 bool u = extract32(insn, 4, 1);
8411 if (!dc_isar_feature(aa32_dp, s)) {
8412 return 1;
8414 fn_gvec = u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b;
8415 } else if ((insn & 0xff300f10) == 0xfc200810) {
8416 /* VFM[AS]L -- 1111 1100 S.10 .... .... 1000 .Q.1 .... */
8417 int is_s = extract32(insn, 23, 1);
8418 if (!dc_isar_feature(aa32_fhm, s)) {
8419 return 1;
8421 is_long = true;
8422 data = is_s; /* is_2 == 0 */
8423 fn_gvec_ptr = gen_helper_gvec_fmlal_a32;
8424 ptr_is_env = true;
8425 } else {
8426 return 1;
8429 VFP_DREG_D(rd, insn);
8430 if (rd & q) {
8431 return 1;
8433 if (q || !is_long) {
8434 VFP_DREG_N(rn, insn);
8435 VFP_DREG_M(rm, insn);
8436 if ((rn | rm) & q & !is_long) {
8437 return 1;
8439 off_rn = vfp_reg_offset(1, rn);
8440 off_rm = vfp_reg_offset(1, rm);
8441 } else {
8442 rn = VFP_SREG_N(insn);
8443 rm = VFP_SREG_M(insn);
8444 off_rn = vfp_reg_offset(0, rn);
8445 off_rm = vfp_reg_offset(0, rm);
8448 if (s->fp_excp_el) {
8449 gen_exception_insn(s, 4, EXCP_UDEF,
8450 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
8451 return 0;
8453 if (!s->vfp_enabled) {
8454 return 1;
8457 opr_sz = (1 + q) * 8;
8458 if (fn_gvec_ptr) {
8459 TCGv_ptr ptr;
8460 if (ptr_is_env) {
8461 ptr = cpu_env;
8462 } else {
8463 ptr = get_fpstatus_ptr(1);
8465 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
8466 opr_sz, opr_sz, data, fn_gvec_ptr);
8467 if (!ptr_is_env) {
8468 tcg_temp_free_ptr(ptr);
8470 } else {
8471 tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
8472 opr_sz, opr_sz, data, fn_gvec);
8474 return 0;
8477 /* Advanced SIMD two registers and a scalar extension.
8478 * 31 24 23 22 20 16 12 11 10 9 8 3 0
8479 * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
8480 * | 1 1 1 1 1 1 1 0 | o1 | D | o2 | Vn | Vd | 1 | o3 | 0 | o4 | N Q M U | Vm |
8481 * +-----------------+----+---+----+----+----+---+----+---+----+---------+----+
8485 static int disas_neon_insn_2reg_scalar_ext(DisasContext *s, uint32_t insn)
8487 gen_helper_gvec_3 *fn_gvec = NULL;
8488 gen_helper_gvec_3_ptr *fn_gvec_ptr = NULL;
8489 int rd, rn, rm, opr_sz, data;
8490 int off_rn, off_rm;
8491 bool is_long = false, q = extract32(insn, 6, 1);
8492 bool ptr_is_env = false;
8494 if ((insn & 0xff000f10) == 0xfe000800) {
8495 /* VCMLA (indexed) -- 1111 1110 S.RR .... .... 1000 ...0 .... */
8496 int rot = extract32(insn, 20, 2);
8497 int size = extract32(insn, 23, 1);
8498 int index;
8500 if (!dc_isar_feature(aa32_vcma, s)) {
8501 return 1;
8503 if (size == 0) {
8504 if (!dc_isar_feature(aa32_fp16_arith, s)) {
8505 return 1;
8507 /* For fp16, rm is just Vm, and index is M. */
8508 rm = extract32(insn, 0, 4);
8509 index = extract32(insn, 5, 1);
8510 } else {
8511 /* For fp32, rm is the usual M:Vm, and index is 0. */
8512 VFP_DREG_M(rm, insn);
8513 index = 0;
8515 data = (index << 2) | rot;
8516 fn_gvec_ptr = (size ? gen_helper_gvec_fcmlas_idx
8517 : gen_helper_gvec_fcmlah_idx);
8518 } else if ((insn & 0xffb00f00) == 0xfe200d00) {
8519 /* V[US]DOT -- 1111 1110 0.10 .... .... 1101 .Q.U .... */
8520 int u = extract32(insn, 4, 1);
8522 if (!dc_isar_feature(aa32_dp, s)) {
8523 return 1;
8525 fn_gvec = u ? gen_helper_gvec_udot_idx_b : gen_helper_gvec_sdot_idx_b;
8526 /* rm is just Vm, and index is M. */
8527 data = extract32(insn, 5, 1); /* index */
8528 rm = extract32(insn, 0, 4);
8529 } else if ((insn & 0xffa00f10) == 0xfe000810) {
8530 /* VFM[AS]L -- 1111 1110 0.0S .... .... 1000 .Q.1 .... */
8531 int is_s = extract32(insn, 20, 1);
8532 int vm20 = extract32(insn, 0, 3);
8533 int vm3 = extract32(insn, 3, 1);
8534 int m = extract32(insn, 5, 1);
8535 int index;
8537 if (!dc_isar_feature(aa32_fhm, s)) {
8538 return 1;
8540 if (q) {
8541 rm = vm20;
8542 index = m * 2 + vm3;
8543 } else {
8544 rm = vm20 * 2 + m;
8545 index = vm3;
8547 is_long = true;
8548 data = (index << 2) | is_s; /* is_2 == 0 */
8549 fn_gvec_ptr = gen_helper_gvec_fmlal_idx_a32;
8550 ptr_is_env = true;
8551 } else {
8552 return 1;
8555 VFP_DREG_D(rd, insn);
8556 if (rd & q) {
8557 return 1;
8559 if (q || !is_long) {
8560 VFP_DREG_N(rn, insn);
8561 if (rn & q & !is_long) {
8562 return 1;
8564 off_rn = vfp_reg_offset(1, rn);
8565 off_rm = vfp_reg_offset(1, rm);
8566 } else {
8567 rn = VFP_SREG_N(insn);
8568 off_rn = vfp_reg_offset(0, rn);
8569 off_rm = vfp_reg_offset(0, rm);
8571 if (s->fp_excp_el) {
8572 gen_exception_insn(s, 4, EXCP_UDEF,
8573 syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
8574 return 0;
8576 if (!s->vfp_enabled) {
8577 return 1;
8580 opr_sz = (1 + q) * 8;
8581 if (fn_gvec_ptr) {
8582 TCGv_ptr ptr;
8583 if (ptr_is_env) {
8584 ptr = cpu_env;
8585 } else {
8586 ptr = get_fpstatus_ptr(1);
8588 tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd), off_rn, off_rm, ptr,
8589 opr_sz, opr_sz, data, fn_gvec_ptr);
8590 if (!ptr_is_env) {
8591 tcg_temp_free_ptr(ptr);
8593 } else {
8594 tcg_gen_gvec_3_ool(vfp_reg_offset(1, rd), off_rn, off_rm,
8595 opr_sz, opr_sz, data, fn_gvec);
8597 return 0;
8600 static int disas_coproc_insn(DisasContext *s, uint32_t insn)
8602 int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
8603 const ARMCPRegInfo *ri;
8605 cpnum = (insn >> 8) & 0xf;
8607 /* First check for coprocessor space used for XScale/iwMMXt insns */
8608 if (arm_dc_feature(s, ARM_FEATURE_XSCALE) && (cpnum < 2)) {
8609 if (extract32(s->c15_cpar, cpnum, 1) == 0) {
8610 return 1;
8612 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
8613 return disas_iwmmxt_insn(s, insn);
8614 } else if (arm_dc_feature(s, ARM_FEATURE_XSCALE)) {
8615 return disas_dsp_insn(s, insn);
8617 return 1;
8620 /* Otherwise treat as a generic register access */
8621 is64 = (insn & (1 << 25)) == 0;
8622 if (!is64 && ((insn & (1 << 4)) == 0)) {
8623 /* cdp */
8624 return 1;
8627 crm = insn & 0xf;
8628 if (is64) {
8629 crn = 0;
8630 opc1 = (insn >> 4) & 0xf;
8631 opc2 = 0;
8632 rt2 = (insn >> 16) & 0xf;
8633 } else {
8634 crn = (insn >> 16) & 0xf;
8635 opc1 = (insn >> 21) & 7;
8636 opc2 = (insn >> 5) & 7;
8637 rt2 = 0;
8639 isread = (insn >> 20) & 1;
8640 rt = (insn >> 12) & 0xf;
8642 ri = get_arm_cp_reginfo(s->cp_regs,
8643 ENCODE_CP_REG(cpnum, is64, s->ns, crn, crm, opc1, opc2));
8644 if (ri) {
8645 /* Check access permissions */
8646 if (!cp_access_ok(s->current_el, ri, isread)) {
8647 return 1;
8650 if (ri->accessfn ||
8651 (arm_dc_feature(s, ARM_FEATURE_XSCALE) && cpnum < 14)) {
8652 /* Emit code to perform further access permissions checks at
8653 * runtime; this may result in an exception.
8654 * Note that on XScale all cp0..c13 registers do an access check
8655 * call in order to handle c15_cpar.
8657 TCGv_ptr tmpptr;
8658 TCGv_i32 tcg_syn, tcg_isread;
8659 uint32_t syndrome;
8661 /* Note that since we are an implementation which takes an
8662 * exception on a trapped conditional instruction only if the
8663 * instruction passes its condition code check, we can take
8664 * advantage of the clause in the ARM ARM that allows us to set
8665 * the COND field in the instruction to 0xE in all cases.
8666 * We could fish the actual condition out of the insn (ARM)
8667 * or the condexec bits (Thumb) but it isn't necessary.
8669 switch (cpnum) {
8670 case 14:
8671 if (is64) {
8672 syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
8673 isread, false);
8674 } else {
8675 syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
8676 rt, isread, false);
8678 break;
8679 case 15:
8680 if (is64) {
8681 syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
8682 isread, false);
8683 } else {
8684 syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
8685 rt, isread, false);
8687 break;
8688 default:
8689 /* ARMv8 defines that only coprocessors 14 and 15 exist,
8690 * so this can only happen if this is an ARMv7 or earlier CPU,
8691 * in which case the syndrome information won't actually be
8692 * guest visible.
8694 assert(!arm_dc_feature(s, ARM_FEATURE_V8));
8695 syndrome = syn_uncategorized();
8696 break;
8699 gen_set_condexec(s);
8700 gen_set_pc_im(s, s->pc - 4);
8701 tmpptr = tcg_const_ptr(ri);
8702 tcg_syn = tcg_const_i32(syndrome);
8703 tcg_isread = tcg_const_i32(isread);
8704 gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn,
8705 tcg_isread);
8706 tcg_temp_free_ptr(tmpptr);
8707 tcg_temp_free_i32(tcg_syn);
8708 tcg_temp_free_i32(tcg_isread);
8711 /* Handle special cases first */
8712 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
8713 case ARM_CP_NOP:
8714 return 0;
8715 case ARM_CP_WFI:
8716 if (isread) {
8717 return 1;
8719 gen_set_pc_im(s, s->pc);
8720 s->base.is_jmp = DISAS_WFI;
8721 return 0;
8722 default:
8723 break;
8726 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
8727 gen_io_start();
8730 if (isread) {
8731 /* Read */
8732 if (is64) {
8733 TCGv_i64 tmp64;
8734 TCGv_i32 tmp;
8735 if (ri->type & ARM_CP_CONST) {
8736 tmp64 = tcg_const_i64(ri->resetvalue);
8737 } else if (ri->readfn) {
8738 TCGv_ptr tmpptr;
8739 tmp64 = tcg_temp_new_i64();
8740 tmpptr = tcg_const_ptr(ri);
8741 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
8742 tcg_temp_free_ptr(tmpptr);
8743 } else {
8744 tmp64 = tcg_temp_new_i64();
8745 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
8747 tmp = tcg_temp_new_i32();
8748 tcg_gen_extrl_i64_i32(tmp, tmp64);
8749 store_reg(s, rt, tmp);
8750 tcg_gen_shri_i64(tmp64, tmp64, 32);
8751 tmp = tcg_temp_new_i32();
8752 tcg_gen_extrl_i64_i32(tmp, tmp64);
8753 tcg_temp_free_i64(tmp64);
8754 store_reg(s, rt2, tmp);
8755 } else {
8756 TCGv_i32 tmp;
8757 if (ri->type & ARM_CP_CONST) {
8758 tmp = tcg_const_i32(ri->resetvalue);
8759 } else if (ri->readfn) {
8760 TCGv_ptr tmpptr;
8761 tmp = tcg_temp_new_i32();
8762 tmpptr = tcg_const_ptr(ri);
8763 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
8764 tcg_temp_free_ptr(tmpptr);
8765 } else {
8766 tmp = load_cpu_offset(ri->fieldoffset);
8768 if (rt == 15) {
8769 /* Destination register of r15 for 32 bit loads sets
8770 * the condition codes from the high 4 bits of the value
8772 gen_set_nzcv(tmp);
8773 tcg_temp_free_i32(tmp);
8774 } else {
8775 store_reg(s, rt, tmp);
8778 } else {
8779 /* Write */
8780 if (ri->type & ARM_CP_CONST) {
8781 /* If not forbidden by access permissions, treat as WI */
8782 return 0;
8785 if (is64) {
8786 TCGv_i32 tmplo, tmphi;
8787 TCGv_i64 tmp64 = tcg_temp_new_i64();
8788 tmplo = load_reg(s, rt);
8789 tmphi = load_reg(s, rt2);
8790 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
8791 tcg_temp_free_i32(tmplo);
8792 tcg_temp_free_i32(tmphi);
8793 if (ri->writefn) {
8794 TCGv_ptr tmpptr = tcg_const_ptr(ri);
8795 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
8796 tcg_temp_free_ptr(tmpptr);
8797 } else {
8798 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
8800 tcg_temp_free_i64(tmp64);
8801 } else {
8802 if (ri->writefn) {
8803 TCGv_i32 tmp;
8804 TCGv_ptr tmpptr;
8805 tmp = load_reg(s, rt);
8806 tmpptr = tcg_const_ptr(ri);
8807 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
8808 tcg_temp_free_ptr(tmpptr);
8809 tcg_temp_free_i32(tmp);
8810 } else {
8811 TCGv_i32 tmp = load_reg(s, rt);
8812 store_cpu_offset(tmp, ri->fieldoffset);
8817 if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
8818 /* I/O operations must end the TB here (whether read or write) */
8819 gen_io_end();
8820 gen_lookup_tb(s);
8821 } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
8822 /* We default to ending the TB on a coprocessor register write,
8823 * but allow this to be suppressed by the register definition
8824 * (usually only necessary to work around guest bugs).
8826 gen_lookup_tb(s);
8829 return 0;
8832 /* Unknown register; this might be a guest error or a QEMU
8833 * unimplemented feature.
8835 if (is64) {
8836 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
8837 "64 bit system register cp:%d opc1: %d crm:%d "
8838 "(%s)\n",
8839 isread ? "read" : "write", cpnum, opc1, crm,
8840 s->ns ? "non-secure" : "secure");
8841 } else {
8842 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
8843 "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d "
8844 "(%s)\n",
8845 isread ? "read" : "write", cpnum, opc1, crn, crm, opc2,
8846 s->ns ? "non-secure" : "secure");
8849 return 1;
8853 /* Store a 64-bit value to a register pair. Clobbers val. */
8854 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
8856 TCGv_i32 tmp;
8857 tmp = tcg_temp_new_i32();
8858 tcg_gen_extrl_i64_i32(tmp, val);
8859 store_reg(s, rlow, tmp);
8860 tmp = tcg_temp_new_i32();
8861 tcg_gen_shri_i64(val, val, 32);
8862 tcg_gen_extrl_i64_i32(tmp, val);
8863 store_reg(s, rhigh, tmp);
8866 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
8867 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
8869 TCGv_i64 tmp;
8870 TCGv_i32 tmp2;
8872 /* Load value and extend to 64 bits. */
8873 tmp = tcg_temp_new_i64();
8874 tmp2 = load_reg(s, rlow);
8875 tcg_gen_extu_i32_i64(tmp, tmp2);
8876 tcg_temp_free_i32(tmp2);
8877 tcg_gen_add_i64(val, val, tmp);
8878 tcg_temp_free_i64(tmp);
8881 /* load and add a 64-bit value from a register pair. */
8882 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
8884 TCGv_i64 tmp;
8885 TCGv_i32 tmpl;
8886 TCGv_i32 tmph;
8888 /* Load 64-bit value rd:rn. */
8889 tmpl = load_reg(s, rlow);
8890 tmph = load_reg(s, rhigh);
8891 tmp = tcg_temp_new_i64();
8892 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
8893 tcg_temp_free_i32(tmpl);
8894 tcg_temp_free_i32(tmph);
8895 tcg_gen_add_i64(val, val, tmp);
8896 tcg_temp_free_i64(tmp);
8899 /* Set N and Z flags from hi|lo. */
8900 static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
8902 tcg_gen_mov_i32(cpu_NF, hi);
8903 tcg_gen_or_i32(cpu_ZF, lo, hi);
8906 /* Load/Store exclusive instructions are implemented by remembering
8907 the value/address loaded, and seeing if these are the same
8908 when the store is performed. This should be sufficient to implement
8909 the architecturally mandated semantics, and avoids having to monitor
8910 regular stores. The compare vs the remembered value is done during
8911 the cmpxchg operation, but we must compare the addresses manually. */
8912 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
8913 TCGv_i32 addr, int size)
8915 TCGv_i32 tmp = tcg_temp_new_i32();
8916 TCGMemOp opc = size | MO_ALIGN | s->be_data;
8918 s->is_ldex = true;
8920 if (size == 3) {
8921 TCGv_i32 tmp2 = tcg_temp_new_i32();
8922 TCGv_i64 t64 = tcg_temp_new_i64();
8924 /* For AArch32, architecturally the 32-bit word at the lowest
8925 * address is always Rt and the one at addr+4 is Rt2, even if
8926 * the CPU is big-endian. That means we don't want to do a
8927 * gen_aa32_ld_i64(), which invokes gen_aa32_frob64() as if
8928 * for an architecturally 64-bit access, but instead do a
8929 * 64-bit access using MO_BE if appropriate and then split
8930 * the two halves.
8931 * This only makes a difference for BE32 user-mode, where
8932 * frob64() must not flip the two halves of the 64-bit data
8933 * but this code must treat BE32 user-mode like BE32 system.
8935 TCGv taddr = gen_aa32_addr(s, addr, opc);
8937 tcg_gen_qemu_ld_i64(t64, taddr, get_mem_index(s), opc);
8938 tcg_temp_free(taddr);
8939 tcg_gen_mov_i64(cpu_exclusive_val, t64);
8940 if (s->be_data == MO_BE) {
8941 tcg_gen_extr_i64_i32(tmp2, tmp, t64);
8942 } else {
8943 tcg_gen_extr_i64_i32(tmp, tmp2, t64);
8945 tcg_temp_free_i64(t64);
8947 store_reg(s, rt2, tmp2);
8948 } else {
8949 gen_aa32_ld_i32(s, tmp, addr, get_mem_index(s), opc);
8950 tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
8953 store_reg(s, rt, tmp);
8954 tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
8957 static void gen_clrex(DisasContext *s)
8959 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
8962 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
8963 TCGv_i32 addr, int size)
8965 TCGv_i32 t0, t1, t2;
8966 TCGv_i64 extaddr;
8967 TCGv taddr;
8968 TCGLabel *done_label;
8969 TCGLabel *fail_label;
8970 TCGMemOp opc = size | MO_ALIGN | s->be_data;
8972 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
8973 [addr] = {Rt};
8974 {Rd} = 0;
8975 } else {
8976 {Rd} = 1;
8977 } */
8978 fail_label = gen_new_label();
8979 done_label = gen_new_label();
8980 extaddr = tcg_temp_new_i64();
8981 tcg_gen_extu_i32_i64(extaddr, addr);
8982 tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
8983 tcg_temp_free_i64(extaddr);
8985 taddr = gen_aa32_addr(s, addr, opc);
8986 t0 = tcg_temp_new_i32();
8987 t1 = load_reg(s, rt);
8988 if (size == 3) {
8989 TCGv_i64 o64 = tcg_temp_new_i64();
8990 TCGv_i64 n64 = tcg_temp_new_i64();
8992 t2 = load_reg(s, rt2);
8993 /* For AArch32, architecturally the 32-bit word at the lowest
8994 * address is always Rt and the one at addr+4 is Rt2, even if
8995 * the CPU is big-endian. Since we're going to treat this as a
8996 * single 64-bit BE store, we need to put the two halves in the
8997 * opposite order for BE to LE, so that they end up in the right
8998 * places.
8999 * We don't want gen_aa32_frob64() because that does the wrong
9000 * thing for BE32 usermode.
9002 if (s->be_data == MO_BE) {
9003 tcg_gen_concat_i32_i64(n64, t2, t1);
9004 } else {
9005 tcg_gen_concat_i32_i64(n64, t1, t2);
9007 tcg_temp_free_i32(t2);
9009 tcg_gen_atomic_cmpxchg_i64(o64, taddr, cpu_exclusive_val, n64,
9010 get_mem_index(s), opc);
9011 tcg_temp_free_i64(n64);
9013 tcg_gen_setcond_i64(TCG_COND_NE, o64, o64, cpu_exclusive_val);
9014 tcg_gen_extrl_i64_i32(t0, o64);
9016 tcg_temp_free_i64(o64);
9017 } else {
9018 t2 = tcg_temp_new_i32();
9019 tcg_gen_extrl_i64_i32(t2, cpu_exclusive_val);
9020 tcg_gen_atomic_cmpxchg_i32(t0, taddr, t2, t1, get_mem_index(s), opc);
9021 tcg_gen_setcond_i32(TCG_COND_NE, t0, t0, t2);
9022 tcg_temp_free_i32(t2);
9024 tcg_temp_free_i32(t1);
9025 tcg_temp_free(taddr);
9026 tcg_gen_mov_i32(cpu_R[rd], t0);
9027 tcg_temp_free_i32(t0);
9028 tcg_gen_br(done_label);
9030 gen_set_label(fail_label);
9031 tcg_gen_movi_i32(cpu_R[rd], 1);
9032 gen_set_label(done_label);
9033 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
9036 /* gen_srs:
9037 * @env: CPUARMState
9038 * @s: DisasContext
9039 * @mode: mode field from insn (which stack to store to)
9040 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
9041 * @writeback: true if writeback bit set
9043 * Generate code for the SRS (Store Return State) insn.
9045 static void gen_srs(DisasContext *s,
9046 uint32_t mode, uint32_t amode, bool writeback)
9048 int32_t offset;
9049 TCGv_i32 addr, tmp;
9050 bool undef = false;
9052 /* SRS is:
9053 * - trapped to EL3 if EL3 is AArch64 and we are at Secure EL1
9054 * and specified mode is monitor mode
9055 * - UNDEFINED in Hyp mode
9056 * - UNPREDICTABLE in User or System mode
9057 * - UNPREDICTABLE if the specified mode is:
9058 * -- not implemented
9059 * -- not a valid mode number
9060 * -- a mode that's at a higher exception level
9061 * -- Monitor, if we are Non-secure
9062 * For the UNPREDICTABLE cases we choose to UNDEF.
9064 if (s->current_el == 1 && !s->ns && mode == ARM_CPU_MODE_MON) {
9065 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(), 3);
9066 return;
9069 if (s->current_el == 0 || s->current_el == 2) {
9070 undef = true;
9073 switch (mode) {
9074 case ARM_CPU_MODE_USR:
9075 case ARM_CPU_MODE_FIQ:
9076 case ARM_CPU_MODE_IRQ:
9077 case ARM_CPU_MODE_SVC:
9078 case ARM_CPU_MODE_ABT:
9079 case ARM_CPU_MODE_UND:
9080 case ARM_CPU_MODE_SYS:
9081 break;
9082 case ARM_CPU_MODE_HYP:
9083 if (s->current_el == 1 || !arm_dc_feature(s, ARM_FEATURE_EL2)) {
9084 undef = true;
9086 break;
9087 case ARM_CPU_MODE_MON:
9088 /* No need to check specifically for "are we non-secure" because
9089 * we've already made EL0 UNDEF and handled the trap for S-EL1;
9090 * so if this isn't EL3 then we must be non-secure.
9092 if (s->current_el != 3) {
9093 undef = true;
9095 break;
9096 default:
9097 undef = true;
9100 if (undef) {
9101 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
9102 default_exception_el(s));
9103 return;
9106 addr = tcg_temp_new_i32();
9107 tmp = tcg_const_i32(mode);
9108 /* get_r13_banked() will raise an exception if called from System mode */
9109 gen_set_condexec(s);
9110 gen_set_pc_im(s, s->pc - 4);
9111 gen_helper_get_r13_banked(addr, cpu_env, tmp);
9112 tcg_temp_free_i32(tmp);
9113 switch (amode) {
9114 case 0: /* DA */
9115 offset = -4;
9116 break;
9117 case 1: /* IA */
9118 offset = 0;
9119 break;
9120 case 2: /* DB */
9121 offset = -8;
9122 break;
9123 case 3: /* IB */
9124 offset = 4;
9125 break;
9126 default:
9127 abort();
9129 tcg_gen_addi_i32(addr, addr, offset);
9130 tmp = load_reg(s, 14);
9131 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
9132 tcg_temp_free_i32(tmp);
9133 tmp = load_cpu_field(spsr);
9134 tcg_gen_addi_i32(addr, addr, 4);
9135 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
9136 tcg_temp_free_i32(tmp);
9137 if (writeback) {
9138 switch (amode) {
9139 case 0:
9140 offset = -8;
9141 break;
9142 case 1:
9143 offset = 4;
9144 break;
9145 case 2:
9146 offset = -4;
9147 break;
9148 case 3:
9149 offset = 0;
9150 break;
9151 default:
9152 abort();
9154 tcg_gen_addi_i32(addr, addr, offset);
9155 tmp = tcg_const_i32(mode);
9156 gen_helper_set_r13_banked(cpu_env, tmp, addr);
9157 tcg_temp_free_i32(tmp);
9159 tcg_temp_free_i32(addr);
9160 s->base.is_jmp = DISAS_UPDATE;
9163 /* Generate a label used for skipping this instruction */
9164 static void arm_gen_condlabel(DisasContext *s)
9166 if (!s->condjmp) {
9167 s->condlabel = gen_new_label();
9168 s->condjmp = 1;
9172 /* Skip this instruction if the ARM condition is false */
9173 static void arm_skip_unless(DisasContext *s, uint32_t cond)
9175 arm_gen_condlabel(s);
9176 arm_gen_test_cc(cond ^ 1, s->condlabel);
9179 static void disas_arm_insn(DisasContext *s, unsigned int insn)
9181 unsigned int cond, val, op1, i, shift, rm, rs, rn, rd, sh;
9182 TCGv_i32 tmp;
9183 TCGv_i32 tmp2;
9184 TCGv_i32 tmp3;
9185 TCGv_i32 addr;
9186 TCGv_i64 tmp64;
9188 /* M variants do not implement ARM mode; this must raise the INVSTATE
9189 * UsageFault exception.
9191 if (arm_dc_feature(s, ARM_FEATURE_M)) {
9192 gen_exception_insn(s, 4, EXCP_INVSTATE, syn_uncategorized(),
9193 default_exception_el(s));
9194 return;
9196 cond = insn >> 28;
9197 if (cond == 0xf){
9198 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
9199 * choose to UNDEF. In ARMv5 and above the space is used
9200 * for miscellaneous unconditional instructions.
9202 ARCH(5);
9204 /* Unconditional instructions. */
9205 if (((insn >> 25) & 7) == 1) {
9206 /* NEON Data processing. */
9207 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
9208 goto illegal_op;
9211 if (disas_neon_data_insn(s, insn)) {
9212 goto illegal_op;
9214 return;
9216 if ((insn & 0x0f100000) == 0x04000000) {
9217 /* NEON load/store. */
9218 if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
9219 goto illegal_op;
9222 if (disas_neon_ls_insn(s, insn)) {
9223 goto illegal_op;
9225 return;
9227 if ((insn & 0x0f000e10) == 0x0e000a00) {
9228 /* VFP. */
9229 if (disas_vfp_insn(s, insn)) {
9230 goto illegal_op;
9232 return;
9234 if (((insn & 0x0f30f000) == 0x0510f000) ||
9235 ((insn & 0x0f30f010) == 0x0710f000)) {
9236 if ((insn & (1 << 22)) == 0) {
9237 /* PLDW; v7MP */
9238 if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
9239 goto illegal_op;
9242 /* Otherwise PLD; v5TE+ */
9243 ARCH(5TE);
9244 return;
9246 if (((insn & 0x0f70f000) == 0x0450f000) ||
9247 ((insn & 0x0f70f010) == 0x0650f000)) {
9248 ARCH(7);
9249 return; /* PLI; V7 */
9251 if (((insn & 0x0f700000) == 0x04100000) ||
9252 ((insn & 0x0f700010) == 0x06100000)) {
9253 if (!arm_dc_feature(s, ARM_FEATURE_V7MP)) {
9254 goto illegal_op;
9256 return; /* v7MP: Unallocated memory hint: must NOP */
9259 if ((insn & 0x0ffffdff) == 0x01010000) {
9260 ARCH(6);
9261 /* setend */
9262 if (((insn >> 9) & 1) != !!(s->be_data == MO_BE)) {
9263 gen_helper_setend(cpu_env);
9264 s->base.is_jmp = DISAS_UPDATE;
9266 return;
9267 } else if ((insn & 0x0fffff00) == 0x057ff000) {
9268 switch ((insn >> 4) & 0xf) {
9269 case 1: /* clrex */
9270 ARCH(6K);
9271 gen_clrex(s);
9272 return;
9273 case 4: /* dsb */
9274 case 5: /* dmb */
9275 ARCH(7);
9276 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
9277 return;
9278 case 6: /* isb */
9279 /* We need to break the TB after this insn to execute
9280 * self-modifying code correctly and also to take
9281 * any pending interrupts immediately.
9283 gen_goto_tb(s, 0, s->pc & ~1);
9284 return;
9285 default:
9286 goto illegal_op;
9288 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
9289 /* srs */
9290 ARCH(6);
9291 gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21));
9292 return;
9293 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
9294 /* rfe */
9295 int32_t offset;
9296 if (IS_USER(s))
9297 goto illegal_op;
9298 ARCH(6);
9299 rn = (insn >> 16) & 0xf;
9300 addr = load_reg(s, rn);
9301 i = (insn >> 23) & 3;
9302 switch (i) {
9303 case 0: offset = -4; break; /* DA */
9304 case 1: offset = 0; break; /* IA */
9305 case 2: offset = -8; break; /* DB */
9306 case 3: offset = 4; break; /* IB */
9307 default: abort();
9309 if (offset)
9310 tcg_gen_addi_i32(addr, addr, offset);
9311 /* Load PC into tmp and CPSR into tmp2. */
9312 tmp = tcg_temp_new_i32();
9313 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
9314 tcg_gen_addi_i32(addr, addr, 4);
9315 tmp2 = tcg_temp_new_i32();
9316 gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
9317 if (insn & (1 << 21)) {
9318 /* Base writeback. */
9319 switch (i) {
9320 case 0: offset = -8; break;
9321 case 1: offset = 4; break;
9322 case 2: offset = -4; break;
9323 case 3: offset = 0; break;
9324 default: abort();
9326 if (offset)
9327 tcg_gen_addi_i32(addr, addr, offset);
9328 store_reg(s, rn, addr);
9329 } else {
9330 tcg_temp_free_i32(addr);
9332 gen_rfe(s, tmp, tmp2);
9333 return;
9334 } else if ((insn & 0x0e000000) == 0x0a000000) {
9335 /* branch link and change to thumb (blx <offset>) */
9336 int32_t offset;
9338 val = (uint32_t)s->pc;
9339 tmp = tcg_temp_new_i32();
9340 tcg_gen_movi_i32(tmp, val);
9341 store_reg(s, 14, tmp);
9342 /* Sign-extend the 24-bit offset */
9343 offset = (((int32_t)insn) << 8) >> 8;
9344 /* offset * 4 + bit24 * 2 + (thumb bit) */
9345 val += (offset << 2) | ((insn >> 23) & 2) | 1;
9346 /* pipeline offset */
9347 val += 4;
9348 /* protected by ARCH(5); above, near the start of uncond block */
9349 gen_bx_im(s, val);
9350 return;
9351 } else if ((insn & 0x0e000f00) == 0x0c000100) {
9352 if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
9353 /* iWMMXt register transfer. */
9354 if (extract32(s->c15_cpar, 1, 1)) {
9355 if (!disas_iwmmxt_insn(s, insn)) {
9356 return;
9360 } else if ((insn & 0x0e000a00) == 0x0c000800
9361 && arm_dc_feature(s, ARM_FEATURE_V8)) {
9362 if (disas_neon_insn_3same_ext(s, insn)) {
9363 goto illegal_op;
9365 return;
9366 } else if ((insn & 0x0f000a00) == 0x0e000800
9367 && arm_dc_feature(s, ARM_FEATURE_V8)) {
9368 if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
9369 goto illegal_op;
9371 return;
9372 } else if ((insn & 0x0fe00000) == 0x0c400000) {
9373 /* Coprocessor double register transfer. */
9374 ARCH(5TE);
9375 } else if ((insn & 0x0f000010) == 0x0e000010) {
9376 /* Additional coprocessor register transfer. */
9377 } else if ((insn & 0x0ff10020) == 0x01000000) {
9378 uint32_t mask;
9379 uint32_t val;
9380 /* cps (privileged) */
9381 if (IS_USER(s))
9382 return;
9383 mask = val = 0;
9384 if (insn & (1 << 19)) {
9385 if (insn & (1 << 8))
9386 mask |= CPSR_A;
9387 if (insn & (1 << 7))
9388 mask |= CPSR_I;
9389 if (insn & (1 << 6))
9390 mask |= CPSR_F;
9391 if (insn & (1 << 18))
9392 val |= mask;
9394 if (insn & (1 << 17)) {
9395 mask |= CPSR_M;
9396 val |= (insn & 0x1f);
9398 if (mask) {
9399 gen_set_psr_im(s, mask, 0, val);
9401 return;
9403 goto illegal_op;
9405 if (cond != 0xe) {
9406 /* if not always execute, we generate a conditional jump to
9407 next instruction */
9408 arm_skip_unless(s, cond);
9410 if ((insn & 0x0f900000) == 0x03000000) {
9411 if ((insn & (1 << 21)) == 0) {
9412 ARCH(6T2);
9413 rd = (insn >> 12) & 0xf;
9414 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
9415 if ((insn & (1 << 22)) == 0) {
9416 /* MOVW */
9417 tmp = tcg_temp_new_i32();
9418 tcg_gen_movi_i32(tmp, val);
9419 } else {
9420 /* MOVT */
9421 tmp = load_reg(s, rd);
9422 tcg_gen_ext16u_i32(tmp, tmp);
9423 tcg_gen_ori_i32(tmp, tmp, val << 16);
9425 store_reg(s, rd, tmp);
9426 } else {
9427 if (((insn >> 12) & 0xf) != 0xf)
9428 goto illegal_op;
9429 if (((insn >> 16) & 0xf) == 0) {
9430 gen_nop_hint(s, insn & 0xff);
9431 } else {
9432 /* CPSR = immediate */
9433 val = insn & 0xff;
9434 shift = ((insn >> 8) & 0xf) * 2;
9435 if (shift)
9436 val = (val >> shift) | (val << (32 - shift));
9437 i = ((insn & (1 << 22)) != 0);
9438 if (gen_set_psr_im(s, msr_mask(s, (insn >> 16) & 0xf, i),
9439 i, val)) {
9440 goto illegal_op;
9444 } else if ((insn & 0x0f900000) == 0x01000000
9445 && (insn & 0x00000090) != 0x00000090) {
9446 /* miscellaneous instructions */
9447 op1 = (insn >> 21) & 3;
9448 sh = (insn >> 4) & 0xf;
9449 rm = insn & 0xf;
9450 switch (sh) {
9451 case 0x0: /* MSR, MRS */
9452 if (insn & (1 << 9)) {
9453 /* MSR (banked) and MRS (banked) */
9454 int sysm = extract32(insn, 16, 4) |
9455 (extract32(insn, 8, 1) << 4);
9456 int r = extract32(insn, 22, 1);
9458 if (op1 & 1) {
9459 /* MSR (banked) */
9460 gen_msr_banked(s, r, sysm, rm);
9461 } else {
9462 /* MRS (banked) */
9463 int rd = extract32(insn, 12, 4);
9465 gen_mrs_banked(s, r, sysm, rd);
9467 break;
9470 /* MSR, MRS (for PSRs) */
9471 if (op1 & 1) {
9472 /* PSR = reg */
9473 tmp = load_reg(s, rm);
9474 i = ((op1 & 2) != 0);
9475 if (gen_set_psr(s, msr_mask(s, (insn >> 16) & 0xf, i), i, tmp))
9476 goto illegal_op;
9477 } else {
9478 /* reg = PSR */
9479 rd = (insn >> 12) & 0xf;
9480 if (op1 & 2) {
9481 if (IS_USER(s))
9482 goto illegal_op;
9483 tmp = load_cpu_field(spsr);
9484 } else {
9485 tmp = tcg_temp_new_i32();
9486 gen_helper_cpsr_read(tmp, cpu_env);
9488 store_reg(s, rd, tmp);
9490 break;
9491 case 0x1:
9492 if (op1 == 1) {
9493 /* branch/exchange thumb (bx). */
9494 ARCH(4T);
9495 tmp = load_reg(s, rm);
9496 gen_bx(s, tmp);
9497 } else if (op1 == 3) {
9498 /* clz */
9499 ARCH(5);
9500 rd = (insn >> 12) & 0xf;
9501 tmp = load_reg(s, rm);
9502 tcg_gen_clzi_i32(tmp, tmp, 32);
9503 store_reg(s, rd, tmp);
9504 } else {
9505 goto illegal_op;
9507 break;
9508 case 0x2:
9509 if (op1 == 1) {
9510 ARCH(5J); /* bxj */
9511 /* Trivial implementation equivalent to bx. */
9512 tmp = load_reg(s, rm);
9513 gen_bx(s, tmp);
9514 } else {
9515 goto illegal_op;
9517 break;
9518 case 0x3:
9519 if (op1 != 1)
9520 goto illegal_op;
9522 ARCH(5);
9523 /* branch link/exchange thumb (blx) */
9524 tmp = load_reg(s, rm);
9525 tmp2 = tcg_temp_new_i32();
9526 tcg_gen_movi_i32(tmp2, s->pc);
9527 store_reg(s, 14, tmp2);
9528 gen_bx(s, tmp);
9529 break;
9530 case 0x4:
9532 /* crc32/crc32c */
9533 uint32_t c = extract32(insn, 8, 4);
9535 /* Check this CPU supports ARMv8 CRC instructions.
9536 * op1 == 3 is UNPREDICTABLE but handle as UNDEFINED.
9537 * Bits 8, 10 and 11 should be zero.
9539 if (!dc_isar_feature(aa32_crc32, s) || op1 == 0x3 || (c & 0xd) != 0) {
9540 goto illegal_op;
9543 rn = extract32(insn, 16, 4);
9544 rd = extract32(insn, 12, 4);
9546 tmp = load_reg(s, rn);
9547 tmp2 = load_reg(s, rm);
9548 if (op1 == 0) {
9549 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
9550 } else if (op1 == 1) {
9551 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
9553 tmp3 = tcg_const_i32(1 << op1);
9554 if (c & 0x2) {
9555 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
9556 } else {
9557 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
9559 tcg_temp_free_i32(tmp2);
9560 tcg_temp_free_i32(tmp3);
9561 store_reg(s, rd, tmp);
9562 break;
9564 case 0x5: /* saturating add/subtract */
9565 ARCH(5TE);
9566 rd = (insn >> 12) & 0xf;
9567 rn = (insn >> 16) & 0xf;
9568 tmp = load_reg(s, rm);
9569 tmp2 = load_reg(s, rn);
9570 if (op1 & 2)
9571 gen_helper_double_saturate(tmp2, cpu_env, tmp2);
9572 if (op1 & 1)
9573 gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2);
9574 else
9575 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
9576 tcg_temp_free_i32(tmp2);
9577 store_reg(s, rd, tmp);
9578 break;
9579 case 0x6: /* ERET */
9580 if (op1 != 3) {
9581 goto illegal_op;
9583 if (!arm_dc_feature(s, ARM_FEATURE_V7VE)) {
9584 goto illegal_op;
9586 if ((insn & 0x000fff0f) != 0x0000000e) {
9587 /* UNPREDICTABLE; we choose to UNDEF */
9588 goto illegal_op;
9591 if (s->current_el == 2) {
9592 tmp = load_cpu_field(elr_el[2]);
9593 } else {
9594 tmp = load_reg(s, 14);
9596 gen_exception_return(s, tmp);
9597 break;
9598 case 7:
9600 int imm16 = extract32(insn, 0, 4) | (extract32(insn, 8, 12) << 4);
9601 switch (op1) {
9602 case 0:
9603 /* HLT */
9604 gen_hlt(s, imm16);
9605 break;
9606 case 1:
9607 /* bkpt */
9608 ARCH(5);
9609 gen_exception_bkpt_insn(s, 4, syn_aa32_bkpt(imm16, false));
9610 break;
9611 case 2:
9612 /* Hypervisor call (v7) */
9613 ARCH(7);
9614 if (IS_USER(s)) {
9615 goto illegal_op;
9617 gen_hvc(s, imm16);
9618 break;
9619 case 3:
9620 /* Secure monitor call (v6+) */
9621 ARCH(6K);
9622 if (IS_USER(s)) {
9623 goto illegal_op;
9625 gen_smc(s);
9626 break;
9627 default:
9628 g_assert_not_reached();
9630 break;
9632 case 0x8: /* signed multiply */
9633 case 0xa:
9634 case 0xc:
9635 case 0xe:
9636 ARCH(5TE);
9637 rs = (insn >> 8) & 0xf;
9638 rn = (insn >> 12) & 0xf;
9639 rd = (insn >> 16) & 0xf;
9640 if (op1 == 1) {
9641 /* (32 * 16) >> 16 */
9642 tmp = load_reg(s, rm);
9643 tmp2 = load_reg(s, rs);
9644 if (sh & 4)
9645 tcg_gen_sari_i32(tmp2, tmp2, 16);
9646 else
9647 gen_sxth(tmp2);
9648 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9649 tcg_gen_shri_i64(tmp64, tmp64, 16);
9650 tmp = tcg_temp_new_i32();
9651 tcg_gen_extrl_i64_i32(tmp, tmp64);
9652 tcg_temp_free_i64(tmp64);
9653 if ((sh & 2) == 0) {
9654 tmp2 = load_reg(s, rn);
9655 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9656 tcg_temp_free_i32(tmp2);
9658 store_reg(s, rd, tmp);
9659 } else {
9660 /* 16 * 16 */
9661 tmp = load_reg(s, rm);
9662 tmp2 = load_reg(s, rs);
9663 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
9664 tcg_temp_free_i32(tmp2);
9665 if (op1 == 2) {
9666 tmp64 = tcg_temp_new_i64();
9667 tcg_gen_ext_i32_i64(tmp64, tmp);
9668 tcg_temp_free_i32(tmp);
9669 gen_addq(s, tmp64, rn, rd);
9670 gen_storeq_reg(s, rn, rd, tmp64);
9671 tcg_temp_free_i64(tmp64);
9672 } else {
9673 if (op1 == 0) {
9674 tmp2 = load_reg(s, rn);
9675 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9676 tcg_temp_free_i32(tmp2);
9678 store_reg(s, rd, tmp);
9681 break;
9682 default:
9683 goto illegal_op;
9685 } else if (((insn & 0x0e000000) == 0 &&
9686 (insn & 0x00000090) != 0x90) ||
9687 ((insn & 0x0e000000) == (1 << 25))) {
9688 int set_cc, logic_cc, shiftop;
9690 op1 = (insn >> 21) & 0xf;
9691 set_cc = (insn >> 20) & 1;
9692 logic_cc = table_logic_cc[op1] & set_cc;
9694 /* data processing instruction */
9695 if (insn & (1 << 25)) {
9696 /* immediate operand */
9697 val = insn & 0xff;
9698 shift = ((insn >> 8) & 0xf) * 2;
9699 if (shift) {
9700 val = (val >> shift) | (val << (32 - shift));
9702 tmp2 = tcg_temp_new_i32();
9703 tcg_gen_movi_i32(tmp2, val);
9704 if (logic_cc && shift) {
9705 gen_set_CF_bit31(tmp2);
9707 } else {
9708 /* register */
9709 rm = (insn) & 0xf;
9710 tmp2 = load_reg(s, rm);
9711 shiftop = (insn >> 5) & 3;
9712 if (!(insn & (1 << 4))) {
9713 shift = (insn >> 7) & 0x1f;
9714 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
9715 } else {
9716 rs = (insn >> 8) & 0xf;
9717 tmp = load_reg(s, rs);
9718 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
9721 if (op1 != 0x0f && op1 != 0x0d) {
9722 rn = (insn >> 16) & 0xf;
9723 tmp = load_reg(s, rn);
9724 } else {
9725 tmp = NULL;
9727 rd = (insn >> 12) & 0xf;
9728 switch(op1) {
9729 case 0x00:
9730 tcg_gen_and_i32(tmp, tmp, tmp2);
9731 if (logic_cc) {
9732 gen_logic_CC(tmp);
9734 store_reg_bx(s, rd, tmp);
9735 break;
9736 case 0x01:
9737 tcg_gen_xor_i32(tmp, tmp, tmp2);
9738 if (logic_cc) {
9739 gen_logic_CC(tmp);
9741 store_reg_bx(s, rd, tmp);
9742 break;
9743 case 0x02:
9744 if (set_cc && rd == 15) {
9745 /* SUBS r15, ... is used for exception return. */
9746 if (IS_USER(s)) {
9747 goto illegal_op;
9749 gen_sub_CC(tmp, tmp, tmp2);
9750 gen_exception_return(s, tmp);
9751 } else {
9752 if (set_cc) {
9753 gen_sub_CC(tmp, tmp, tmp2);
9754 } else {
9755 tcg_gen_sub_i32(tmp, tmp, tmp2);
9757 store_reg_bx(s, rd, tmp);
9759 break;
9760 case 0x03:
9761 if (set_cc) {
9762 gen_sub_CC(tmp, tmp2, tmp);
9763 } else {
9764 tcg_gen_sub_i32(tmp, tmp2, tmp);
9766 store_reg_bx(s, rd, tmp);
9767 break;
9768 case 0x04:
9769 if (set_cc) {
9770 gen_add_CC(tmp, tmp, tmp2);
9771 } else {
9772 tcg_gen_add_i32(tmp, tmp, tmp2);
9774 store_reg_bx(s, rd, tmp);
9775 break;
9776 case 0x05:
9777 if (set_cc) {
9778 gen_adc_CC(tmp, tmp, tmp2);
9779 } else {
9780 gen_add_carry(tmp, tmp, tmp2);
9782 store_reg_bx(s, rd, tmp);
9783 break;
9784 case 0x06:
9785 if (set_cc) {
9786 gen_sbc_CC(tmp, tmp, tmp2);
9787 } else {
9788 gen_sub_carry(tmp, tmp, tmp2);
9790 store_reg_bx(s, rd, tmp);
9791 break;
9792 case 0x07:
9793 if (set_cc) {
9794 gen_sbc_CC(tmp, tmp2, tmp);
9795 } else {
9796 gen_sub_carry(tmp, tmp2, tmp);
9798 store_reg_bx(s, rd, tmp);
9799 break;
9800 case 0x08:
9801 if (set_cc) {
9802 tcg_gen_and_i32(tmp, tmp, tmp2);
9803 gen_logic_CC(tmp);
9805 tcg_temp_free_i32(tmp);
9806 break;
9807 case 0x09:
9808 if (set_cc) {
9809 tcg_gen_xor_i32(tmp, tmp, tmp2);
9810 gen_logic_CC(tmp);
9812 tcg_temp_free_i32(tmp);
9813 break;
9814 case 0x0a:
9815 if (set_cc) {
9816 gen_sub_CC(tmp, tmp, tmp2);
9818 tcg_temp_free_i32(tmp);
9819 break;
9820 case 0x0b:
9821 if (set_cc) {
9822 gen_add_CC(tmp, tmp, tmp2);
9824 tcg_temp_free_i32(tmp);
9825 break;
9826 case 0x0c:
9827 tcg_gen_or_i32(tmp, tmp, tmp2);
9828 if (logic_cc) {
9829 gen_logic_CC(tmp);
9831 store_reg_bx(s, rd, tmp);
9832 break;
9833 case 0x0d:
9834 if (logic_cc && rd == 15) {
9835 /* MOVS r15, ... is used for exception return. */
9836 if (IS_USER(s)) {
9837 goto illegal_op;
9839 gen_exception_return(s, tmp2);
9840 } else {
9841 if (logic_cc) {
9842 gen_logic_CC(tmp2);
9844 store_reg_bx(s, rd, tmp2);
9846 break;
9847 case 0x0e:
9848 tcg_gen_andc_i32(tmp, tmp, tmp2);
9849 if (logic_cc) {
9850 gen_logic_CC(tmp);
9852 store_reg_bx(s, rd, tmp);
9853 break;
9854 default:
9855 case 0x0f:
9856 tcg_gen_not_i32(tmp2, tmp2);
9857 if (logic_cc) {
9858 gen_logic_CC(tmp2);
9860 store_reg_bx(s, rd, tmp2);
9861 break;
9863 if (op1 != 0x0f && op1 != 0x0d) {
9864 tcg_temp_free_i32(tmp2);
9866 } else {
9867 /* other instructions */
9868 op1 = (insn >> 24) & 0xf;
9869 switch(op1) {
9870 case 0x0:
9871 case 0x1:
9872 /* multiplies, extra load/stores */
9873 sh = (insn >> 5) & 3;
9874 if (sh == 0) {
9875 if (op1 == 0x0) {
9876 rd = (insn >> 16) & 0xf;
9877 rn = (insn >> 12) & 0xf;
9878 rs = (insn >> 8) & 0xf;
9879 rm = (insn) & 0xf;
9880 op1 = (insn >> 20) & 0xf;
9881 switch (op1) {
9882 case 0: case 1: case 2: case 3: case 6:
9883 /* 32 bit mul */
9884 tmp = load_reg(s, rs);
9885 tmp2 = load_reg(s, rm);
9886 tcg_gen_mul_i32(tmp, tmp, tmp2);
9887 tcg_temp_free_i32(tmp2);
9888 if (insn & (1 << 22)) {
9889 /* Subtract (mls) */
9890 ARCH(6T2);
9891 tmp2 = load_reg(s, rn);
9892 tcg_gen_sub_i32(tmp, tmp2, tmp);
9893 tcg_temp_free_i32(tmp2);
9894 } else if (insn & (1 << 21)) {
9895 /* Add */
9896 tmp2 = load_reg(s, rn);
9897 tcg_gen_add_i32(tmp, tmp, tmp2);
9898 tcg_temp_free_i32(tmp2);
9900 if (insn & (1 << 20))
9901 gen_logic_CC(tmp);
9902 store_reg(s, rd, tmp);
9903 break;
9904 case 4:
9905 /* 64 bit mul double accumulate (UMAAL) */
9906 ARCH(6);
9907 tmp = load_reg(s, rs);
9908 tmp2 = load_reg(s, rm);
9909 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
9910 gen_addq_lo(s, tmp64, rn);
9911 gen_addq_lo(s, tmp64, rd);
9912 gen_storeq_reg(s, rn, rd, tmp64);
9913 tcg_temp_free_i64(tmp64);
9914 break;
9915 case 8: case 9: case 10: case 11:
9916 case 12: case 13: case 14: case 15:
9917 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
9918 tmp = load_reg(s, rs);
9919 tmp2 = load_reg(s, rm);
9920 if (insn & (1 << 22)) {
9921 tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2);
9922 } else {
9923 tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2);
9925 if (insn & (1 << 21)) { /* mult accumulate */
9926 TCGv_i32 al = load_reg(s, rn);
9927 TCGv_i32 ah = load_reg(s, rd);
9928 tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, al, ah);
9929 tcg_temp_free_i32(al);
9930 tcg_temp_free_i32(ah);
9932 if (insn & (1 << 20)) {
9933 gen_logicq_cc(tmp, tmp2);
9935 store_reg(s, rn, tmp);
9936 store_reg(s, rd, tmp2);
9937 break;
9938 default:
9939 goto illegal_op;
9941 } else {
9942 rn = (insn >> 16) & 0xf;
9943 rd = (insn >> 12) & 0xf;
9944 if (insn & (1 << 23)) {
9945 /* load/store exclusive */
9946 bool is_ld = extract32(insn, 20, 1);
9947 bool is_lasr = !extract32(insn, 8, 1);
9948 int op2 = (insn >> 8) & 3;
9949 op1 = (insn >> 21) & 0x3;
9951 switch (op2) {
9952 case 0: /* lda/stl */
9953 if (op1 == 1) {
9954 goto illegal_op;
9956 ARCH(8);
9957 break;
9958 case 1: /* reserved */
9959 goto illegal_op;
9960 case 2: /* ldaex/stlex */
9961 ARCH(8);
9962 break;
9963 case 3: /* ldrex/strex */
9964 if (op1) {
9965 ARCH(6K);
9966 } else {
9967 ARCH(6);
9969 break;
9972 addr = tcg_temp_local_new_i32();
9973 load_reg_var(s, addr, rn);
9975 if (is_lasr && !is_ld) {
9976 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
9979 if (op2 == 0) {
9980 if (is_ld) {
9981 tmp = tcg_temp_new_i32();
9982 switch (op1) {
9983 case 0: /* lda */
9984 gen_aa32_ld32u_iss(s, tmp, addr,
9985 get_mem_index(s),
9986 rd | ISSIsAcqRel);
9987 break;
9988 case 2: /* ldab */
9989 gen_aa32_ld8u_iss(s, tmp, addr,
9990 get_mem_index(s),
9991 rd | ISSIsAcqRel);
9992 break;
9993 case 3: /* ldah */
9994 gen_aa32_ld16u_iss(s, tmp, addr,
9995 get_mem_index(s),
9996 rd | ISSIsAcqRel);
9997 break;
9998 default:
9999 abort();
10001 store_reg(s, rd, tmp);
10002 } else {
10003 rm = insn & 0xf;
10004 tmp = load_reg(s, rm);
10005 switch (op1) {
10006 case 0: /* stl */
10007 gen_aa32_st32_iss(s, tmp, addr,
10008 get_mem_index(s),
10009 rm | ISSIsAcqRel);
10010 break;
10011 case 2: /* stlb */
10012 gen_aa32_st8_iss(s, tmp, addr,
10013 get_mem_index(s),
10014 rm | ISSIsAcqRel);
10015 break;
10016 case 3: /* stlh */
10017 gen_aa32_st16_iss(s, tmp, addr,
10018 get_mem_index(s),
10019 rm | ISSIsAcqRel);
10020 break;
10021 default:
10022 abort();
10024 tcg_temp_free_i32(tmp);
10026 } else if (is_ld) {
10027 switch (op1) {
10028 case 0: /* ldrex */
10029 gen_load_exclusive(s, rd, 15, addr, 2);
10030 break;
10031 case 1: /* ldrexd */
10032 gen_load_exclusive(s, rd, rd + 1, addr, 3);
10033 break;
10034 case 2: /* ldrexb */
10035 gen_load_exclusive(s, rd, 15, addr, 0);
10036 break;
10037 case 3: /* ldrexh */
10038 gen_load_exclusive(s, rd, 15, addr, 1);
10039 break;
10040 default:
10041 abort();
10043 } else {
10044 rm = insn & 0xf;
10045 switch (op1) {
10046 case 0: /* strex */
10047 gen_store_exclusive(s, rd, rm, 15, addr, 2);
10048 break;
10049 case 1: /* strexd */
10050 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
10051 break;
10052 case 2: /* strexb */
10053 gen_store_exclusive(s, rd, rm, 15, addr, 0);
10054 break;
10055 case 3: /* strexh */
10056 gen_store_exclusive(s, rd, rm, 15, addr, 1);
10057 break;
10058 default:
10059 abort();
10062 tcg_temp_free_i32(addr);
10064 if (is_lasr && is_ld) {
10065 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
10067 } else if ((insn & 0x00300f00) == 0) {
10068 /* 0bcccc_0001_0x00_xxxx_xxxx_0000_1001_xxxx
10069 * - SWP, SWPB
10072 TCGv taddr;
10073 TCGMemOp opc = s->be_data;
10075 rm = (insn) & 0xf;
10077 if (insn & (1 << 22)) {
10078 opc |= MO_UB;
10079 } else {
10080 opc |= MO_UL | MO_ALIGN;
10083 addr = load_reg(s, rn);
10084 taddr = gen_aa32_addr(s, addr, opc);
10085 tcg_temp_free_i32(addr);
10087 tmp = load_reg(s, rm);
10088 tcg_gen_atomic_xchg_i32(tmp, taddr, tmp,
10089 get_mem_index(s), opc);
10090 tcg_temp_free(taddr);
10091 store_reg(s, rd, tmp);
10092 } else {
10093 goto illegal_op;
10096 } else {
10097 int address_offset;
10098 bool load = insn & (1 << 20);
10099 bool wbit = insn & (1 << 21);
10100 bool pbit = insn & (1 << 24);
10101 bool doubleword = false;
10102 ISSInfo issinfo;
10104 /* Misc load/store */
10105 rn = (insn >> 16) & 0xf;
10106 rd = (insn >> 12) & 0xf;
10108 /* ISS not valid if writeback */
10109 issinfo = (pbit & !wbit) ? rd : ISSInvalid;
10111 if (!load && (sh & 2)) {
10112 /* doubleword */
10113 ARCH(5TE);
10114 if (rd & 1) {
10115 /* UNPREDICTABLE; we choose to UNDEF */
10116 goto illegal_op;
10118 load = (sh & 1) == 0;
10119 doubleword = true;
10122 addr = load_reg(s, rn);
10123 if (pbit) {
10124 gen_add_datah_offset(s, insn, 0, addr);
10126 address_offset = 0;
10128 if (doubleword) {
10129 if (!load) {
10130 /* store */
10131 tmp = load_reg(s, rd);
10132 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
10133 tcg_temp_free_i32(tmp);
10134 tcg_gen_addi_i32(addr, addr, 4);
10135 tmp = load_reg(s, rd + 1);
10136 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
10137 tcg_temp_free_i32(tmp);
10138 } else {
10139 /* load */
10140 tmp = tcg_temp_new_i32();
10141 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
10142 store_reg(s, rd, tmp);
10143 tcg_gen_addi_i32(addr, addr, 4);
10144 tmp = tcg_temp_new_i32();
10145 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
10146 rd++;
10148 address_offset = -4;
10149 } else if (load) {
10150 /* load */
10151 tmp = tcg_temp_new_i32();
10152 switch (sh) {
10153 case 1:
10154 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s),
10155 issinfo);
10156 break;
10157 case 2:
10158 gen_aa32_ld8s_iss(s, tmp, addr, get_mem_index(s),
10159 issinfo);
10160 break;
10161 default:
10162 case 3:
10163 gen_aa32_ld16s_iss(s, tmp, addr, get_mem_index(s),
10164 issinfo);
10165 break;
10167 } else {
10168 /* store */
10169 tmp = load_reg(s, rd);
10170 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), issinfo);
10171 tcg_temp_free_i32(tmp);
10173 /* Perform base writeback before the loaded value to
10174 ensure correct behavior with overlapping index registers.
10175 ldrd with base writeback is undefined if the
10176 destination and index registers overlap. */
10177 if (!pbit) {
10178 gen_add_datah_offset(s, insn, address_offset, addr);
10179 store_reg(s, rn, addr);
10180 } else if (wbit) {
10181 if (address_offset)
10182 tcg_gen_addi_i32(addr, addr, address_offset);
10183 store_reg(s, rn, addr);
10184 } else {
10185 tcg_temp_free_i32(addr);
10187 if (load) {
10188 /* Complete the load. */
10189 store_reg(s, rd, tmp);
10192 break;
10193 case 0x4:
10194 case 0x5:
10195 goto do_ldst;
10196 case 0x6:
10197 case 0x7:
10198 if (insn & (1 << 4)) {
10199 ARCH(6);
10200 /* Armv6 Media instructions. */
10201 rm = insn & 0xf;
10202 rn = (insn >> 16) & 0xf;
10203 rd = (insn >> 12) & 0xf;
10204 rs = (insn >> 8) & 0xf;
10205 switch ((insn >> 23) & 3) {
10206 case 0: /* Parallel add/subtract. */
10207 op1 = (insn >> 20) & 7;
10208 tmp = load_reg(s, rn);
10209 tmp2 = load_reg(s, rm);
10210 sh = (insn >> 5) & 7;
10211 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
10212 goto illegal_op;
10213 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
10214 tcg_temp_free_i32(tmp2);
10215 store_reg(s, rd, tmp);
10216 break;
10217 case 1:
10218 if ((insn & 0x00700020) == 0) {
10219 /* Halfword pack. */
10220 tmp = load_reg(s, rn);
10221 tmp2 = load_reg(s, rm);
10222 shift = (insn >> 7) & 0x1f;
10223 if (insn & (1 << 6)) {
10224 /* pkhtb */
10225 if (shift == 0)
10226 shift = 31;
10227 tcg_gen_sari_i32(tmp2, tmp2, shift);
10228 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
10229 tcg_gen_ext16u_i32(tmp2, tmp2);
10230 } else {
10231 /* pkhbt */
10232 if (shift)
10233 tcg_gen_shli_i32(tmp2, tmp2, shift);
10234 tcg_gen_ext16u_i32(tmp, tmp);
10235 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
10237 tcg_gen_or_i32(tmp, tmp, tmp2);
10238 tcg_temp_free_i32(tmp2);
10239 store_reg(s, rd, tmp);
10240 } else if ((insn & 0x00200020) == 0x00200000) {
10241 /* [us]sat */
10242 tmp = load_reg(s, rm);
10243 shift = (insn >> 7) & 0x1f;
10244 if (insn & (1 << 6)) {
10245 if (shift == 0)
10246 shift = 31;
10247 tcg_gen_sari_i32(tmp, tmp, shift);
10248 } else {
10249 tcg_gen_shli_i32(tmp, tmp, shift);
10251 sh = (insn >> 16) & 0x1f;
10252 tmp2 = tcg_const_i32(sh);
10253 if (insn & (1 << 22))
10254 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
10255 else
10256 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
10257 tcg_temp_free_i32(tmp2);
10258 store_reg(s, rd, tmp);
10259 } else if ((insn & 0x00300fe0) == 0x00200f20) {
10260 /* [us]sat16 */
10261 tmp = load_reg(s, rm);
10262 sh = (insn >> 16) & 0x1f;
10263 tmp2 = tcg_const_i32(sh);
10264 if (insn & (1 << 22))
10265 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
10266 else
10267 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
10268 tcg_temp_free_i32(tmp2);
10269 store_reg(s, rd, tmp);
10270 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
10271 /* Select bytes. */
10272 tmp = load_reg(s, rn);
10273 tmp2 = load_reg(s, rm);
10274 tmp3 = tcg_temp_new_i32();
10275 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
10276 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
10277 tcg_temp_free_i32(tmp3);
10278 tcg_temp_free_i32(tmp2);
10279 store_reg(s, rd, tmp);
10280 } else if ((insn & 0x000003e0) == 0x00000060) {
10281 tmp = load_reg(s, rm);
10282 shift = (insn >> 10) & 3;
10283 /* ??? In many cases it's not necessary to do a
10284 rotate, a shift is sufficient. */
10285 if (shift != 0)
10286 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
10287 op1 = (insn >> 20) & 7;
10288 switch (op1) {
10289 case 0: gen_sxtb16(tmp); break;
10290 case 2: gen_sxtb(tmp); break;
10291 case 3: gen_sxth(tmp); break;
10292 case 4: gen_uxtb16(tmp); break;
10293 case 6: gen_uxtb(tmp); break;
10294 case 7: gen_uxth(tmp); break;
10295 default: goto illegal_op;
10297 if (rn != 15) {
10298 tmp2 = load_reg(s, rn);
10299 if ((op1 & 3) == 0) {
10300 gen_add16(tmp, tmp2);
10301 } else {
10302 tcg_gen_add_i32(tmp, tmp, tmp2);
10303 tcg_temp_free_i32(tmp2);
10306 store_reg(s, rd, tmp);
10307 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
10308 /* rev */
10309 tmp = load_reg(s, rm);
10310 if (insn & (1 << 22)) {
10311 if (insn & (1 << 7)) {
10312 gen_revsh(tmp);
10313 } else {
10314 ARCH(6T2);
10315 gen_helper_rbit(tmp, tmp);
10317 } else {
10318 if (insn & (1 << 7))
10319 gen_rev16(tmp);
10320 else
10321 tcg_gen_bswap32_i32(tmp, tmp);
10323 store_reg(s, rd, tmp);
10324 } else {
10325 goto illegal_op;
10327 break;
10328 case 2: /* Multiplies (Type 3). */
10329 switch ((insn >> 20) & 0x7) {
10330 case 5:
10331 if (((insn >> 6) ^ (insn >> 7)) & 1) {
10332 /* op2 not 00x or 11x : UNDEF */
10333 goto illegal_op;
10335 /* Signed multiply most significant [accumulate].
10336 (SMMUL, SMMLA, SMMLS) */
10337 tmp = load_reg(s, rm);
10338 tmp2 = load_reg(s, rs);
10339 tmp64 = gen_muls_i64_i32(tmp, tmp2);
10341 if (rd != 15) {
10342 tmp = load_reg(s, rd);
10343 if (insn & (1 << 6)) {
10344 tmp64 = gen_subq_msw(tmp64, tmp);
10345 } else {
10346 tmp64 = gen_addq_msw(tmp64, tmp);
10349 if (insn & (1 << 5)) {
10350 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
10352 tcg_gen_shri_i64(tmp64, tmp64, 32);
10353 tmp = tcg_temp_new_i32();
10354 tcg_gen_extrl_i64_i32(tmp, tmp64);
10355 tcg_temp_free_i64(tmp64);
10356 store_reg(s, rn, tmp);
10357 break;
10358 case 0:
10359 case 4:
10360 /* SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD */
10361 if (insn & (1 << 7)) {
10362 goto illegal_op;
10364 tmp = load_reg(s, rm);
10365 tmp2 = load_reg(s, rs);
10366 if (insn & (1 << 5))
10367 gen_swap_half(tmp2);
10368 gen_smul_dual(tmp, tmp2);
10369 if (insn & (1 << 22)) {
10370 /* smlald, smlsld */
10371 TCGv_i64 tmp64_2;
10373 tmp64 = tcg_temp_new_i64();
10374 tmp64_2 = tcg_temp_new_i64();
10375 tcg_gen_ext_i32_i64(tmp64, tmp);
10376 tcg_gen_ext_i32_i64(tmp64_2, tmp2);
10377 tcg_temp_free_i32(tmp);
10378 tcg_temp_free_i32(tmp2);
10379 if (insn & (1 << 6)) {
10380 tcg_gen_sub_i64(tmp64, tmp64, tmp64_2);
10381 } else {
10382 tcg_gen_add_i64(tmp64, tmp64, tmp64_2);
10384 tcg_temp_free_i64(tmp64_2);
10385 gen_addq(s, tmp64, rd, rn);
10386 gen_storeq_reg(s, rd, rn, tmp64);
10387 tcg_temp_free_i64(tmp64);
10388 } else {
10389 /* smuad, smusd, smlad, smlsd */
10390 if (insn & (1 << 6)) {
10391 /* This subtraction cannot overflow. */
10392 tcg_gen_sub_i32(tmp, tmp, tmp2);
10393 } else {
10394 /* This addition cannot overflow 32 bits;
10395 * however it may overflow considered as a
10396 * signed operation, in which case we must set
10397 * the Q flag.
10399 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
10401 tcg_temp_free_i32(tmp2);
10402 if (rd != 15)
10404 tmp2 = load_reg(s, rd);
10405 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
10406 tcg_temp_free_i32(tmp2);
10408 store_reg(s, rn, tmp);
10410 break;
10411 case 1:
10412 case 3:
10413 /* SDIV, UDIV */
10414 if (!dc_isar_feature(arm_div, s)) {
10415 goto illegal_op;
10417 if (((insn >> 5) & 7) || (rd != 15)) {
10418 goto illegal_op;
10420 tmp = load_reg(s, rm);
10421 tmp2 = load_reg(s, rs);
10422 if (insn & (1 << 21)) {
10423 gen_helper_udiv(tmp, tmp, tmp2);
10424 } else {
10425 gen_helper_sdiv(tmp, tmp, tmp2);
10427 tcg_temp_free_i32(tmp2);
10428 store_reg(s, rn, tmp);
10429 break;
10430 default:
10431 goto illegal_op;
10433 break;
10434 case 3:
10435 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
10436 switch (op1) {
10437 case 0: /* Unsigned sum of absolute differences. */
10438 ARCH(6);
10439 tmp = load_reg(s, rm);
10440 tmp2 = load_reg(s, rs);
10441 gen_helper_usad8(tmp, tmp, tmp2);
10442 tcg_temp_free_i32(tmp2);
10443 if (rd != 15) {
10444 tmp2 = load_reg(s, rd);
10445 tcg_gen_add_i32(tmp, tmp, tmp2);
10446 tcg_temp_free_i32(tmp2);
10448 store_reg(s, rn, tmp);
10449 break;
10450 case 0x20: case 0x24: case 0x28: case 0x2c:
10451 /* Bitfield insert/clear. */
10452 ARCH(6T2);
10453 shift = (insn >> 7) & 0x1f;
10454 i = (insn >> 16) & 0x1f;
10455 if (i < shift) {
10456 /* UNPREDICTABLE; we choose to UNDEF */
10457 goto illegal_op;
10459 i = i + 1 - shift;
10460 if (rm == 15) {
10461 tmp = tcg_temp_new_i32();
10462 tcg_gen_movi_i32(tmp, 0);
10463 } else {
10464 tmp = load_reg(s, rm);
10466 if (i != 32) {
10467 tmp2 = load_reg(s, rd);
10468 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, i);
10469 tcg_temp_free_i32(tmp2);
10471 store_reg(s, rd, tmp);
10472 break;
10473 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
10474 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
10475 ARCH(6T2);
10476 tmp = load_reg(s, rm);
10477 shift = (insn >> 7) & 0x1f;
10478 i = ((insn >> 16) & 0x1f) + 1;
10479 if (shift + i > 32)
10480 goto illegal_op;
10481 if (i < 32) {
10482 if (op1 & 0x20) {
10483 tcg_gen_extract_i32(tmp, tmp, shift, i);
10484 } else {
10485 tcg_gen_sextract_i32(tmp, tmp, shift, i);
10488 store_reg(s, rd, tmp);
10489 break;
10490 default:
10491 goto illegal_op;
10493 break;
10495 break;
10497 do_ldst:
10498 /* Check for undefined extension instructions
10499 * per the ARM Bible IE:
10500 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
10502 sh = (0xf << 20) | (0xf << 4);
10503 if (op1 == 0x7 && ((insn & sh) == sh))
10505 goto illegal_op;
10507 /* load/store byte/word */
10508 rn = (insn >> 16) & 0xf;
10509 rd = (insn >> 12) & 0xf;
10510 tmp2 = load_reg(s, rn);
10511 if ((insn & 0x01200000) == 0x00200000) {
10512 /* ldrt/strt */
10513 i = get_a32_user_mem_index(s);
10514 } else {
10515 i = get_mem_index(s);
10517 if (insn & (1 << 24))
10518 gen_add_data_offset(s, insn, tmp2);
10519 if (insn & (1 << 20)) {
10520 /* load */
10521 tmp = tcg_temp_new_i32();
10522 if (insn & (1 << 22)) {
10523 gen_aa32_ld8u_iss(s, tmp, tmp2, i, rd);
10524 } else {
10525 gen_aa32_ld32u_iss(s, tmp, tmp2, i, rd);
10527 } else {
10528 /* store */
10529 tmp = load_reg(s, rd);
10530 if (insn & (1 << 22)) {
10531 gen_aa32_st8_iss(s, tmp, tmp2, i, rd);
10532 } else {
10533 gen_aa32_st32_iss(s, tmp, tmp2, i, rd);
10535 tcg_temp_free_i32(tmp);
10537 if (!(insn & (1 << 24))) {
10538 gen_add_data_offset(s, insn, tmp2);
10539 store_reg(s, rn, tmp2);
10540 } else if (insn & (1 << 21)) {
10541 store_reg(s, rn, tmp2);
10542 } else {
10543 tcg_temp_free_i32(tmp2);
10545 if (insn & (1 << 20)) {
10546 /* Complete the load. */
10547 store_reg_from_load(s, rd, tmp);
10549 break;
10550 case 0x08:
10551 case 0x09:
10553 int j, n, loaded_base;
10554 bool exc_return = false;
10555 bool is_load = extract32(insn, 20, 1);
10556 bool user = false;
10557 TCGv_i32 loaded_var;
10558 /* load/store multiple words */
10559 /* XXX: store correct base if write back */
10560 if (insn & (1 << 22)) {
10561 /* LDM (user), LDM (exception return) and STM (user) */
10562 if (IS_USER(s))
10563 goto illegal_op; /* only usable in supervisor mode */
10565 if (is_load && extract32(insn, 15, 1)) {
10566 exc_return = true;
10567 } else {
10568 user = true;
10571 rn = (insn >> 16) & 0xf;
10572 addr = load_reg(s, rn);
10574 /* compute total size */
10575 loaded_base = 0;
10576 loaded_var = NULL;
10577 n = 0;
10578 for(i=0;i<16;i++) {
10579 if (insn & (1 << i))
10580 n++;
10582 /* XXX: test invalid n == 0 case ? */
10583 if (insn & (1 << 23)) {
10584 if (insn & (1 << 24)) {
10585 /* pre increment */
10586 tcg_gen_addi_i32(addr, addr, 4);
10587 } else {
10588 /* post increment */
10590 } else {
10591 if (insn & (1 << 24)) {
10592 /* pre decrement */
10593 tcg_gen_addi_i32(addr, addr, -(n * 4));
10594 } else {
10595 /* post decrement */
10596 if (n != 1)
10597 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
10600 j = 0;
10601 for(i=0;i<16;i++) {
10602 if (insn & (1 << i)) {
10603 if (is_load) {
10604 /* load */
10605 tmp = tcg_temp_new_i32();
10606 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
10607 if (user) {
10608 tmp2 = tcg_const_i32(i);
10609 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
10610 tcg_temp_free_i32(tmp2);
10611 tcg_temp_free_i32(tmp);
10612 } else if (i == rn) {
10613 loaded_var = tmp;
10614 loaded_base = 1;
10615 } else if (rn == 15 && exc_return) {
10616 store_pc_exc_ret(s, tmp);
10617 } else {
10618 store_reg_from_load(s, i, tmp);
10620 } else {
10621 /* store */
10622 if (i == 15) {
10623 /* special case: r15 = PC + 8 */
10624 val = (long)s->pc + 4;
10625 tmp = tcg_temp_new_i32();
10626 tcg_gen_movi_i32(tmp, val);
10627 } else if (user) {
10628 tmp = tcg_temp_new_i32();
10629 tmp2 = tcg_const_i32(i);
10630 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
10631 tcg_temp_free_i32(tmp2);
10632 } else {
10633 tmp = load_reg(s, i);
10635 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
10636 tcg_temp_free_i32(tmp);
10638 j++;
10639 /* no need to add after the last transfer */
10640 if (j != n)
10641 tcg_gen_addi_i32(addr, addr, 4);
10644 if (insn & (1 << 21)) {
10645 /* write back */
10646 if (insn & (1 << 23)) {
10647 if (insn & (1 << 24)) {
10648 /* pre increment */
10649 } else {
10650 /* post increment */
10651 tcg_gen_addi_i32(addr, addr, 4);
10653 } else {
10654 if (insn & (1 << 24)) {
10655 /* pre decrement */
10656 if (n != 1)
10657 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
10658 } else {
10659 /* post decrement */
10660 tcg_gen_addi_i32(addr, addr, -(n * 4));
10663 store_reg(s, rn, addr);
10664 } else {
10665 tcg_temp_free_i32(addr);
10667 if (loaded_base) {
10668 store_reg(s, rn, loaded_var);
10670 if (exc_return) {
10671 /* Restore CPSR from SPSR. */
10672 tmp = load_cpu_field(spsr);
10673 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
10674 gen_io_start();
10676 gen_helper_cpsr_write_eret(cpu_env, tmp);
10677 if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
10678 gen_io_end();
10680 tcg_temp_free_i32(tmp);
10681 /* Must exit loop to check un-masked IRQs */
10682 s->base.is_jmp = DISAS_EXIT;
10685 break;
10686 case 0xa:
10687 case 0xb:
10689 int32_t offset;
10691 /* branch (and link) */
10692 val = (int32_t)s->pc;
10693 if (insn & (1 << 24)) {
10694 tmp = tcg_temp_new_i32();
10695 tcg_gen_movi_i32(tmp, val);
10696 store_reg(s, 14, tmp);
10698 offset = sextract32(insn << 2, 0, 26);
10699 val += offset + 4;
10700 gen_jmp(s, val);
10702 break;
10703 case 0xc:
10704 case 0xd:
10705 case 0xe:
10706 if (((insn >> 8) & 0xe) == 10) {
10707 /* VFP. */
10708 if (disas_vfp_insn(s, insn)) {
10709 goto illegal_op;
10711 } else if (disas_coproc_insn(s, insn)) {
10712 /* Coprocessor. */
10713 goto illegal_op;
10715 break;
10716 case 0xf:
10717 /* swi */
10718 gen_set_pc_im(s, s->pc);
10719 s->svc_imm = extract32(insn, 0, 24);
10720 s->base.is_jmp = DISAS_SWI;
10721 break;
10722 default:
10723 illegal_op:
10724 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
10725 default_exception_el(s));
10726 break;
10731 static bool thumb_insn_is_16bit(DisasContext *s, uint32_t insn)
10733 /* Return true if this is a 16 bit instruction. We must be precise
10734 * about this (matching the decode). We assume that s->pc still
10735 * points to the first 16 bits of the insn.
10737 if ((insn >> 11) < 0x1d) {
10738 /* Definitely a 16-bit instruction */
10739 return true;
10742 /* Top five bits 0b11101 / 0b11110 / 0b11111 : this is the
10743 * first half of a 32-bit Thumb insn. Thumb-1 cores might
10744 * end up actually treating this as two 16-bit insns, though,
10745 * if it's half of a bl/blx pair that might span a page boundary.
10747 if (arm_dc_feature(s, ARM_FEATURE_THUMB2) ||
10748 arm_dc_feature(s, ARM_FEATURE_M)) {
10749 /* Thumb2 cores (including all M profile ones) always treat
10750 * 32-bit insns as 32-bit.
10752 return false;
10755 if ((insn >> 11) == 0x1e && s->pc - s->page_start < TARGET_PAGE_SIZE - 3) {
10756 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix, and the suffix
10757 * is not on the next page; we merge this into a 32-bit
10758 * insn.
10760 return false;
10762 /* 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF);
10763 * 0b1111_1xxx_xxxx_xxxx : BL suffix;
10764 * 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix on the end of a page
10765 * -- handle as single 16 bit insn
10767 return true;
10770 /* Return true if this is a Thumb-2 logical op. */
10771 static int
10772 thumb2_logic_op(int op)
10774 return (op < 8);
10777 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
10778 then set condition code flags based on the result of the operation.
10779 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
10780 to the high bit of T1.
10781 Returns zero if the opcode is valid. */
10783 static int
10784 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out,
10785 TCGv_i32 t0, TCGv_i32 t1)
10787 int logic_cc;
10789 logic_cc = 0;
10790 switch (op) {
10791 case 0: /* and */
10792 tcg_gen_and_i32(t0, t0, t1);
10793 logic_cc = conds;
10794 break;
10795 case 1: /* bic */
10796 tcg_gen_andc_i32(t0, t0, t1);
10797 logic_cc = conds;
10798 break;
10799 case 2: /* orr */
10800 tcg_gen_or_i32(t0, t0, t1);
10801 logic_cc = conds;
10802 break;
10803 case 3: /* orn */
10804 tcg_gen_orc_i32(t0, t0, t1);
10805 logic_cc = conds;
10806 break;
10807 case 4: /* eor */
10808 tcg_gen_xor_i32(t0, t0, t1);
10809 logic_cc = conds;
10810 break;
10811 case 8: /* add */
10812 if (conds)
10813 gen_add_CC(t0, t0, t1);
10814 else
10815 tcg_gen_add_i32(t0, t0, t1);
10816 break;
10817 case 10: /* adc */
10818 if (conds)
10819 gen_adc_CC(t0, t0, t1);
10820 else
10821 gen_adc(t0, t1);
10822 break;
10823 case 11: /* sbc */
10824 if (conds) {
10825 gen_sbc_CC(t0, t0, t1);
10826 } else {
10827 gen_sub_carry(t0, t0, t1);
10829 break;
10830 case 13: /* sub */
10831 if (conds)
10832 gen_sub_CC(t0, t0, t1);
10833 else
10834 tcg_gen_sub_i32(t0, t0, t1);
10835 break;
10836 case 14: /* rsb */
10837 if (conds)
10838 gen_sub_CC(t0, t1, t0);
10839 else
10840 tcg_gen_sub_i32(t0, t1, t0);
10841 break;
10842 default: /* 5, 6, 7, 9, 12, 15. */
10843 return 1;
10845 if (logic_cc) {
10846 gen_logic_CC(t0);
10847 if (shifter_out)
10848 gen_set_CF_bit31(t1);
10850 return 0;
10853 /* Translate a 32-bit thumb instruction. */
10854 static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
10856 uint32_t imm, shift, offset;
10857 uint32_t rd, rn, rm, rs;
10858 TCGv_i32 tmp;
10859 TCGv_i32 tmp2;
10860 TCGv_i32 tmp3;
10861 TCGv_i32 addr;
10862 TCGv_i64 tmp64;
10863 int op;
10864 int shiftop;
10865 int conds;
10866 int logic_cc;
10869 * ARMv6-M supports a limited subset of Thumb2 instructions.
10870 * Other Thumb1 architectures allow only 32-bit
10871 * combined BL/BLX prefix and suffix.
10873 if (arm_dc_feature(s, ARM_FEATURE_M) &&
10874 !arm_dc_feature(s, ARM_FEATURE_V7)) {
10875 int i;
10876 bool found = false;
10877 static const uint32_t armv6m_insn[] = {0xf3808000 /* msr */,
10878 0xf3b08040 /* dsb */,
10879 0xf3b08050 /* dmb */,
10880 0xf3b08060 /* isb */,
10881 0xf3e08000 /* mrs */,
10882 0xf000d000 /* bl */};
10883 static const uint32_t armv6m_mask[] = {0xffe0d000,
10884 0xfff0d0f0,
10885 0xfff0d0f0,
10886 0xfff0d0f0,
10887 0xffe0d000,
10888 0xf800d000};
10890 for (i = 0; i < ARRAY_SIZE(armv6m_insn); i++) {
10891 if ((insn & armv6m_mask[i]) == armv6m_insn[i]) {
10892 found = true;
10893 break;
10896 if (!found) {
10897 goto illegal_op;
10899 } else if ((insn & 0xf800e800) != 0xf000e800) {
10900 ARCH(6T2);
10903 rn = (insn >> 16) & 0xf;
10904 rs = (insn >> 12) & 0xf;
10905 rd = (insn >> 8) & 0xf;
10906 rm = insn & 0xf;
10907 switch ((insn >> 25) & 0xf) {
10908 case 0: case 1: case 2: case 3:
10909 /* 16-bit instructions. Should never happen. */
10910 abort();
10911 case 4:
10912 if (insn & (1 << 22)) {
10913 /* 0b1110_100x_x1xx_xxxx_xxxx_xxxx_xxxx_xxxx
10914 * - load/store doubleword, load/store exclusive, ldacq/strel,
10915 * table branch, TT.
10917 if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_M) &&
10918 arm_dc_feature(s, ARM_FEATURE_V8)) {
10919 /* 0b1110_1001_0111_1111_1110_1001_0111_111
10920 * - SG (v8M only)
10921 * The bulk of the behaviour for this instruction is implemented
10922 * in v7m_handle_execute_nsc(), which deals with the insn when
10923 * it is executed by a CPU in non-secure state from memory
10924 * which is Secure & NonSecure-Callable.
10925 * Here we only need to handle the remaining cases:
10926 * * in NS memory (including the "security extension not
10927 * implemented" case) : NOP
10928 * * in S memory but CPU already secure (clear IT bits)
10929 * We know that the attribute for the memory this insn is
10930 * in must match the current CPU state, because otherwise
10931 * get_phys_addr_pmsav8 would have generated an exception.
10933 if (s->v8m_secure) {
10934 /* Like the IT insn, we don't need to generate any code */
10935 s->condexec_cond = 0;
10936 s->condexec_mask = 0;
10938 } else if (insn & 0x01200000) {
10939 /* 0b1110_1000_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
10940 * - load/store dual (post-indexed)
10941 * 0b1111_1001_x10x_xxxx_xxxx_xxxx_xxxx_xxxx
10942 * - load/store dual (literal and immediate)
10943 * 0b1111_1001_x11x_xxxx_xxxx_xxxx_xxxx_xxxx
10944 * - load/store dual (pre-indexed)
10946 bool wback = extract32(insn, 21, 1);
10948 if (rn == 15) {
10949 if (insn & (1 << 21)) {
10950 /* UNPREDICTABLE */
10951 goto illegal_op;
10953 addr = tcg_temp_new_i32();
10954 tcg_gen_movi_i32(addr, s->pc & ~3);
10955 } else {
10956 addr = load_reg(s, rn);
10958 offset = (insn & 0xff) * 4;
10959 if ((insn & (1 << 23)) == 0) {
10960 offset = -offset;
10963 if (s->v8m_stackcheck && rn == 13 && wback) {
10965 * Here 'addr' is the current SP; if offset is +ve we're
10966 * moving SP up, else down. It is UNKNOWN whether the limit
10967 * check triggers when SP starts below the limit and ends
10968 * up above it; check whichever of the current and final
10969 * SP is lower, so QEMU will trigger in that situation.
10971 if ((int32_t)offset < 0) {
10972 TCGv_i32 newsp = tcg_temp_new_i32();
10974 tcg_gen_addi_i32(newsp, addr, offset);
10975 gen_helper_v8m_stackcheck(cpu_env, newsp);
10976 tcg_temp_free_i32(newsp);
10977 } else {
10978 gen_helper_v8m_stackcheck(cpu_env, addr);
10982 if (insn & (1 << 24)) {
10983 tcg_gen_addi_i32(addr, addr, offset);
10984 offset = 0;
10986 if (insn & (1 << 20)) {
10987 /* ldrd */
10988 tmp = tcg_temp_new_i32();
10989 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
10990 store_reg(s, rs, tmp);
10991 tcg_gen_addi_i32(addr, addr, 4);
10992 tmp = tcg_temp_new_i32();
10993 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
10994 store_reg(s, rd, tmp);
10995 } else {
10996 /* strd */
10997 tmp = load_reg(s, rs);
10998 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
10999 tcg_temp_free_i32(tmp);
11000 tcg_gen_addi_i32(addr, addr, 4);
11001 tmp = load_reg(s, rd);
11002 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
11003 tcg_temp_free_i32(tmp);
11005 if (wback) {
11006 /* Base writeback. */
11007 tcg_gen_addi_i32(addr, addr, offset - 4);
11008 store_reg(s, rn, addr);
11009 } else {
11010 tcg_temp_free_i32(addr);
11012 } else if ((insn & (1 << 23)) == 0) {
11013 /* 0b1110_1000_010x_xxxx_xxxx_xxxx_xxxx_xxxx
11014 * - load/store exclusive word
11015 * - TT (v8M only)
11017 if (rs == 15) {
11018 if (!(insn & (1 << 20)) &&
11019 arm_dc_feature(s, ARM_FEATURE_M) &&
11020 arm_dc_feature(s, ARM_FEATURE_V8)) {
11021 /* 0b1110_1000_0100_xxxx_1111_xxxx_xxxx_xxxx
11022 * - TT (v8M only)
11024 bool alt = insn & (1 << 7);
11025 TCGv_i32 addr, op, ttresp;
11027 if ((insn & 0x3f) || rd == 13 || rd == 15 || rn == 15) {
11028 /* we UNDEF for these UNPREDICTABLE cases */
11029 goto illegal_op;
11032 if (alt && !s->v8m_secure) {
11033 goto illegal_op;
11036 addr = load_reg(s, rn);
11037 op = tcg_const_i32(extract32(insn, 6, 2));
11038 ttresp = tcg_temp_new_i32();
11039 gen_helper_v7m_tt(ttresp, cpu_env, addr, op);
11040 tcg_temp_free_i32(addr);
11041 tcg_temp_free_i32(op);
11042 store_reg(s, rd, ttresp);
11043 break;
11045 goto illegal_op;
11047 addr = tcg_temp_local_new_i32();
11048 load_reg_var(s, addr, rn);
11049 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
11050 if (insn & (1 << 20)) {
11051 gen_load_exclusive(s, rs, 15, addr, 2);
11052 } else {
11053 gen_store_exclusive(s, rd, rs, 15, addr, 2);
11055 tcg_temp_free_i32(addr);
11056 } else if ((insn & (7 << 5)) == 0) {
11057 /* Table Branch. */
11058 if (rn == 15) {
11059 addr = tcg_temp_new_i32();
11060 tcg_gen_movi_i32(addr, s->pc);
11061 } else {
11062 addr = load_reg(s, rn);
11064 tmp = load_reg(s, rm);
11065 tcg_gen_add_i32(addr, addr, tmp);
11066 if (insn & (1 << 4)) {
11067 /* tbh */
11068 tcg_gen_add_i32(addr, addr, tmp);
11069 tcg_temp_free_i32(tmp);
11070 tmp = tcg_temp_new_i32();
11071 gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
11072 } else { /* tbb */
11073 tcg_temp_free_i32(tmp);
11074 tmp = tcg_temp_new_i32();
11075 gen_aa32_ld8u(s, tmp, addr, get_mem_index(s));
11077 tcg_temp_free_i32(addr);
11078 tcg_gen_shli_i32(tmp, tmp, 1);
11079 tcg_gen_addi_i32(tmp, tmp, s->pc);
11080 store_reg(s, 15, tmp);
11081 } else {
11082 bool is_lasr = false;
11083 bool is_ld = extract32(insn, 20, 1);
11084 int op2 = (insn >> 6) & 0x3;
11085 op = (insn >> 4) & 0x3;
11086 switch (op2) {
11087 case 0:
11088 goto illegal_op;
11089 case 1:
11090 /* Load/store exclusive byte/halfword/doubleword */
11091 if (op == 2) {
11092 goto illegal_op;
11094 ARCH(7);
11095 break;
11096 case 2:
11097 /* Load-acquire/store-release */
11098 if (op == 3) {
11099 goto illegal_op;
11101 /* Fall through */
11102 case 3:
11103 /* Load-acquire/store-release exclusive */
11104 ARCH(8);
11105 is_lasr = true;
11106 break;
11109 if (is_lasr && !is_ld) {
11110 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
11113 addr = tcg_temp_local_new_i32();
11114 load_reg_var(s, addr, rn);
11115 if (!(op2 & 1)) {
11116 if (is_ld) {
11117 tmp = tcg_temp_new_i32();
11118 switch (op) {
11119 case 0: /* ldab */
11120 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s),
11121 rs | ISSIsAcqRel);
11122 break;
11123 case 1: /* ldah */
11124 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s),
11125 rs | ISSIsAcqRel);
11126 break;
11127 case 2: /* lda */
11128 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s),
11129 rs | ISSIsAcqRel);
11130 break;
11131 default:
11132 abort();
11134 store_reg(s, rs, tmp);
11135 } else {
11136 tmp = load_reg(s, rs);
11137 switch (op) {
11138 case 0: /* stlb */
11139 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s),
11140 rs | ISSIsAcqRel);
11141 break;
11142 case 1: /* stlh */
11143 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s),
11144 rs | ISSIsAcqRel);
11145 break;
11146 case 2: /* stl */
11147 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s),
11148 rs | ISSIsAcqRel);
11149 break;
11150 default:
11151 abort();
11153 tcg_temp_free_i32(tmp);
11155 } else if (is_ld) {
11156 gen_load_exclusive(s, rs, rd, addr, op);
11157 } else {
11158 gen_store_exclusive(s, rm, rs, rd, addr, op);
11160 tcg_temp_free_i32(addr);
11162 if (is_lasr && is_ld) {
11163 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
11166 } else {
11167 /* Load/store multiple, RFE, SRS. */
11168 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
11169 /* RFE, SRS: not available in user mode or on M profile */
11170 if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
11171 goto illegal_op;
11173 if (insn & (1 << 20)) {
11174 /* rfe */
11175 addr = load_reg(s, rn);
11176 if ((insn & (1 << 24)) == 0)
11177 tcg_gen_addi_i32(addr, addr, -8);
11178 /* Load PC into tmp and CPSR into tmp2. */
11179 tmp = tcg_temp_new_i32();
11180 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
11181 tcg_gen_addi_i32(addr, addr, 4);
11182 tmp2 = tcg_temp_new_i32();
11183 gen_aa32_ld32u(s, tmp2, addr, get_mem_index(s));
11184 if (insn & (1 << 21)) {
11185 /* Base writeback. */
11186 if (insn & (1 << 24)) {
11187 tcg_gen_addi_i32(addr, addr, 4);
11188 } else {
11189 tcg_gen_addi_i32(addr, addr, -4);
11191 store_reg(s, rn, addr);
11192 } else {
11193 tcg_temp_free_i32(addr);
11195 gen_rfe(s, tmp, tmp2);
11196 } else {
11197 /* srs */
11198 gen_srs(s, (insn & 0x1f), (insn & (1 << 24)) ? 1 : 2,
11199 insn & (1 << 21));
11201 } else {
11202 int i, loaded_base = 0;
11203 TCGv_i32 loaded_var;
11204 bool wback = extract32(insn, 21, 1);
11205 /* Load/store multiple. */
11206 addr = load_reg(s, rn);
11207 offset = 0;
11208 for (i = 0; i < 16; i++) {
11209 if (insn & (1 << i))
11210 offset += 4;
11213 if (insn & (1 << 24)) {
11214 tcg_gen_addi_i32(addr, addr, -offset);
11217 if (s->v8m_stackcheck && rn == 13 && wback) {
11219 * If the writeback is incrementing SP rather than
11220 * decrementing it, and the initial SP is below the
11221 * stack limit but the final written-back SP would
11222 * be above, then then we must not perform any memory
11223 * accesses, but it is IMPDEF whether we generate
11224 * an exception. We choose to do so in this case.
11225 * At this point 'addr' is the lowest address, so
11226 * either the original SP (if incrementing) or our
11227 * final SP (if decrementing), so that's what we check.
11229 gen_helper_v8m_stackcheck(cpu_env, addr);
11232 loaded_var = NULL;
11233 for (i = 0; i < 16; i++) {
11234 if ((insn & (1 << i)) == 0)
11235 continue;
11236 if (insn & (1 << 20)) {
11237 /* Load. */
11238 tmp = tcg_temp_new_i32();
11239 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
11240 if (i == 15) {
11241 gen_bx_excret(s, tmp);
11242 } else if (i == rn) {
11243 loaded_var = tmp;
11244 loaded_base = 1;
11245 } else {
11246 store_reg(s, i, tmp);
11248 } else {
11249 /* Store. */
11250 tmp = load_reg(s, i);
11251 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
11252 tcg_temp_free_i32(tmp);
11254 tcg_gen_addi_i32(addr, addr, 4);
11256 if (loaded_base) {
11257 store_reg(s, rn, loaded_var);
11259 if (wback) {
11260 /* Base register writeback. */
11261 if (insn & (1 << 24)) {
11262 tcg_gen_addi_i32(addr, addr, -offset);
11264 /* Fault if writeback register is in register list. */
11265 if (insn & (1 << rn))
11266 goto illegal_op;
11267 store_reg(s, rn, addr);
11268 } else {
11269 tcg_temp_free_i32(addr);
11273 break;
11274 case 5:
11276 op = (insn >> 21) & 0xf;
11277 if (op == 6) {
11278 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11279 goto illegal_op;
11281 /* Halfword pack. */
11282 tmp = load_reg(s, rn);
11283 tmp2 = load_reg(s, rm);
11284 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
11285 if (insn & (1 << 5)) {
11286 /* pkhtb */
11287 if (shift == 0)
11288 shift = 31;
11289 tcg_gen_sari_i32(tmp2, tmp2, shift);
11290 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
11291 tcg_gen_ext16u_i32(tmp2, tmp2);
11292 } else {
11293 /* pkhbt */
11294 if (shift)
11295 tcg_gen_shli_i32(tmp2, tmp2, shift);
11296 tcg_gen_ext16u_i32(tmp, tmp);
11297 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
11299 tcg_gen_or_i32(tmp, tmp, tmp2);
11300 tcg_temp_free_i32(tmp2);
11301 store_reg(s, rd, tmp);
11302 } else {
11303 /* Data processing register constant shift. */
11304 if (rn == 15) {
11305 tmp = tcg_temp_new_i32();
11306 tcg_gen_movi_i32(tmp, 0);
11307 } else {
11308 tmp = load_reg(s, rn);
11310 tmp2 = load_reg(s, rm);
11312 shiftop = (insn >> 4) & 3;
11313 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
11314 conds = (insn & (1 << 20)) != 0;
11315 logic_cc = (conds && thumb2_logic_op(op));
11316 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
11317 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
11318 goto illegal_op;
11319 tcg_temp_free_i32(tmp2);
11320 if (rd == 13 &&
11321 ((op == 2 && rn == 15) ||
11322 (op == 8 && rn == 13) ||
11323 (op == 13 && rn == 13))) {
11324 /* MOV SP, ... or ADD SP, SP, ... or SUB SP, SP, ... */
11325 store_sp_checked(s, tmp);
11326 } else if (rd != 15) {
11327 store_reg(s, rd, tmp);
11328 } else {
11329 tcg_temp_free_i32(tmp);
11332 break;
11333 case 13: /* Misc data processing. */
11334 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
11335 if (op < 4 && (insn & 0xf000) != 0xf000)
11336 goto illegal_op;
11337 switch (op) {
11338 case 0: /* Register controlled shift. */
11339 tmp = load_reg(s, rn);
11340 tmp2 = load_reg(s, rm);
11341 if ((insn & 0x70) != 0)
11342 goto illegal_op;
11344 * 0b1111_1010_0xxx_xxxx_1111_xxxx_0000_xxxx:
11345 * - MOV, MOVS (register-shifted register), flagsetting
11347 op = (insn >> 21) & 3;
11348 logic_cc = (insn & (1 << 20)) != 0;
11349 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
11350 if (logic_cc)
11351 gen_logic_CC(tmp);
11352 store_reg(s, rd, tmp);
11353 break;
11354 case 1: /* Sign/zero extend. */
11355 op = (insn >> 20) & 7;
11356 switch (op) {
11357 case 0: /* SXTAH, SXTH */
11358 case 1: /* UXTAH, UXTH */
11359 case 4: /* SXTAB, SXTB */
11360 case 5: /* UXTAB, UXTB */
11361 break;
11362 case 2: /* SXTAB16, SXTB16 */
11363 case 3: /* UXTAB16, UXTB16 */
11364 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11365 goto illegal_op;
11367 break;
11368 default:
11369 goto illegal_op;
11371 if (rn != 15) {
11372 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11373 goto illegal_op;
11376 tmp = load_reg(s, rm);
11377 shift = (insn >> 4) & 3;
11378 /* ??? In many cases it's not necessary to do a
11379 rotate, a shift is sufficient. */
11380 if (shift != 0)
11381 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
11382 op = (insn >> 20) & 7;
11383 switch (op) {
11384 case 0: gen_sxth(tmp); break;
11385 case 1: gen_uxth(tmp); break;
11386 case 2: gen_sxtb16(tmp); break;
11387 case 3: gen_uxtb16(tmp); break;
11388 case 4: gen_sxtb(tmp); break;
11389 case 5: gen_uxtb(tmp); break;
11390 default:
11391 g_assert_not_reached();
11393 if (rn != 15) {
11394 tmp2 = load_reg(s, rn);
11395 if ((op >> 1) == 1) {
11396 gen_add16(tmp, tmp2);
11397 } else {
11398 tcg_gen_add_i32(tmp, tmp, tmp2);
11399 tcg_temp_free_i32(tmp2);
11402 store_reg(s, rd, tmp);
11403 break;
11404 case 2: /* SIMD add/subtract. */
11405 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11406 goto illegal_op;
11408 op = (insn >> 20) & 7;
11409 shift = (insn >> 4) & 7;
11410 if ((op & 3) == 3 || (shift & 3) == 3)
11411 goto illegal_op;
11412 tmp = load_reg(s, rn);
11413 tmp2 = load_reg(s, rm);
11414 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
11415 tcg_temp_free_i32(tmp2);
11416 store_reg(s, rd, tmp);
11417 break;
11418 case 3: /* Other data processing. */
11419 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
11420 if (op < 4) {
11421 /* Saturating add/subtract. */
11422 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11423 goto illegal_op;
11425 tmp = load_reg(s, rn);
11426 tmp2 = load_reg(s, rm);
11427 if (op & 1)
11428 gen_helper_double_saturate(tmp, cpu_env, tmp);
11429 if (op & 2)
11430 gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);
11431 else
11432 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
11433 tcg_temp_free_i32(tmp2);
11434 } else {
11435 switch (op) {
11436 case 0x0a: /* rbit */
11437 case 0x08: /* rev */
11438 case 0x09: /* rev16 */
11439 case 0x0b: /* revsh */
11440 case 0x18: /* clz */
11441 break;
11442 case 0x10: /* sel */
11443 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11444 goto illegal_op;
11446 break;
11447 case 0x20: /* crc32/crc32c */
11448 case 0x21:
11449 case 0x22:
11450 case 0x28:
11451 case 0x29:
11452 case 0x2a:
11453 if (!dc_isar_feature(aa32_crc32, s)) {
11454 goto illegal_op;
11456 break;
11457 default:
11458 goto illegal_op;
11460 tmp = load_reg(s, rn);
11461 switch (op) {
11462 case 0x0a: /* rbit */
11463 gen_helper_rbit(tmp, tmp);
11464 break;
11465 case 0x08: /* rev */
11466 tcg_gen_bswap32_i32(tmp, tmp);
11467 break;
11468 case 0x09: /* rev16 */
11469 gen_rev16(tmp);
11470 break;
11471 case 0x0b: /* revsh */
11472 gen_revsh(tmp);
11473 break;
11474 case 0x10: /* sel */
11475 tmp2 = load_reg(s, rm);
11476 tmp3 = tcg_temp_new_i32();
11477 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
11478 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
11479 tcg_temp_free_i32(tmp3);
11480 tcg_temp_free_i32(tmp2);
11481 break;
11482 case 0x18: /* clz */
11483 tcg_gen_clzi_i32(tmp, tmp, 32);
11484 break;
11485 case 0x20:
11486 case 0x21:
11487 case 0x22:
11488 case 0x28:
11489 case 0x29:
11490 case 0x2a:
11492 /* crc32/crc32c */
11493 uint32_t sz = op & 0x3;
11494 uint32_t c = op & 0x8;
11496 tmp2 = load_reg(s, rm);
11497 if (sz == 0) {
11498 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
11499 } else if (sz == 1) {
11500 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
11502 tmp3 = tcg_const_i32(1 << sz);
11503 if (c) {
11504 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
11505 } else {
11506 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
11508 tcg_temp_free_i32(tmp2);
11509 tcg_temp_free_i32(tmp3);
11510 break;
11512 default:
11513 g_assert_not_reached();
11516 store_reg(s, rd, tmp);
11517 break;
11518 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
11519 switch ((insn >> 20) & 7) {
11520 case 0: /* 32 x 32 -> 32 */
11521 case 7: /* Unsigned sum of absolute differences. */
11522 break;
11523 case 1: /* 16 x 16 -> 32 */
11524 case 2: /* Dual multiply add. */
11525 case 3: /* 32 * 16 -> 32msb */
11526 case 4: /* Dual multiply subtract. */
11527 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
11528 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11529 goto illegal_op;
11531 break;
11533 op = (insn >> 4) & 0xf;
11534 tmp = load_reg(s, rn);
11535 tmp2 = load_reg(s, rm);
11536 switch ((insn >> 20) & 7) {
11537 case 0: /* 32 x 32 -> 32 */
11538 tcg_gen_mul_i32(tmp, tmp, tmp2);
11539 tcg_temp_free_i32(tmp2);
11540 if (rs != 15) {
11541 tmp2 = load_reg(s, rs);
11542 if (op)
11543 tcg_gen_sub_i32(tmp, tmp2, tmp);
11544 else
11545 tcg_gen_add_i32(tmp, tmp, tmp2);
11546 tcg_temp_free_i32(tmp2);
11548 break;
11549 case 1: /* 16 x 16 -> 32 */
11550 gen_mulxy(tmp, tmp2, op & 2, op & 1);
11551 tcg_temp_free_i32(tmp2);
11552 if (rs != 15) {
11553 tmp2 = load_reg(s, rs);
11554 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
11555 tcg_temp_free_i32(tmp2);
11557 break;
11558 case 2: /* Dual multiply add. */
11559 case 4: /* Dual multiply subtract. */
11560 if (op)
11561 gen_swap_half(tmp2);
11562 gen_smul_dual(tmp, tmp2);
11563 if (insn & (1 << 22)) {
11564 /* This subtraction cannot overflow. */
11565 tcg_gen_sub_i32(tmp, tmp, tmp2);
11566 } else {
11567 /* This addition cannot overflow 32 bits;
11568 * however it may overflow considered as a signed
11569 * operation, in which case we must set the Q flag.
11571 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
11573 tcg_temp_free_i32(tmp2);
11574 if (rs != 15)
11576 tmp2 = load_reg(s, rs);
11577 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
11578 tcg_temp_free_i32(tmp2);
11580 break;
11581 case 3: /* 32 * 16 -> 32msb */
11582 if (op)
11583 tcg_gen_sari_i32(tmp2, tmp2, 16);
11584 else
11585 gen_sxth(tmp2);
11586 tmp64 = gen_muls_i64_i32(tmp, tmp2);
11587 tcg_gen_shri_i64(tmp64, tmp64, 16);
11588 tmp = tcg_temp_new_i32();
11589 tcg_gen_extrl_i64_i32(tmp, tmp64);
11590 tcg_temp_free_i64(tmp64);
11591 if (rs != 15)
11593 tmp2 = load_reg(s, rs);
11594 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
11595 tcg_temp_free_i32(tmp2);
11597 break;
11598 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
11599 tmp64 = gen_muls_i64_i32(tmp, tmp2);
11600 if (rs != 15) {
11601 tmp = load_reg(s, rs);
11602 if (insn & (1 << 20)) {
11603 tmp64 = gen_addq_msw(tmp64, tmp);
11604 } else {
11605 tmp64 = gen_subq_msw(tmp64, tmp);
11608 if (insn & (1 << 4)) {
11609 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
11611 tcg_gen_shri_i64(tmp64, tmp64, 32);
11612 tmp = tcg_temp_new_i32();
11613 tcg_gen_extrl_i64_i32(tmp, tmp64);
11614 tcg_temp_free_i64(tmp64);
11615 break;
11616 case 7: /* Unsigned sum of absolute differences. */
11617 gen_helper_usad8(tmp, tmp, tmp2);
11618 tcg_temp_free_i32(tmp2);
11619 if (rs != 15) {
11620 tmp2 = load_reg(s, rs);
11621 tcg_gen_add_i32(tmp, tmp, tmp2);
11622 tcg_temp_free_i32(tmp2);
11624 break;
11626 store_reg(s, rd, tmp);
11627 break;
11628 case 6: case 7: /* 64-bit multiply, Divide. */
11629 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
11630 tmp = load_reg(s, rn);
11631 tmp2 = load_reg(s, rm);
11632 if ((op & 0x50) == 0x10) {
11633 /* sdiv, udiv */
11634 if (!dc_isar_feature(thumb_div, s)) {
11635 goto illegal_op;
11637 if (op & 0x20)
11638 gen_helper_udiv(tmp, tmp, tmp2);
11639 else
11640 gen_helper_sdiv(tmp, tmp, tmp2);
11641 tcg_temp_free_i32(tmp2);
11642 store_reg(s, rd, tmp);
11643 } else if ((op & 0xe) == 0xc) {
11644 /* Dual multiply accumulate long. */
11645 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11646 tcg_temp_free_i32(tmp);
11647 tcg_temp_free_i32(tmp2);
11648 goto illegal_op;
11650 if (op & 1)
11651 gen_swap_half(tmp2);
11652 gen_smul_dual(tmp, tmp2);
11653 if (op & 0x10) {
11654 tcg_gen_sub_i32(tmp, tmp, tmp2);
11655 } else {
11656 tcg_gen_add_i32(tmp, tmp, tmp2);
11658 tcg_temp_free_i32(tmp2);
11659 /* BUGFIX */
11660 tmp64 = tcg_temp_new_i64();
11661 tcg_gen_ext_i32_i64(tmp64, tmp);
11662 tcg_temp_free_i32(tmp);
11663 gen_addq(s, tmp64, rs, rd);
11664 gen_storeq_reg(s, rs, rd, tmp64);
11665 tcg_temp_free_i64(tmp64);
11666 } else {
11667 if (op & 0x20) {
11668 /* Unsigned 64-bit multiply */
11669 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
11670 } else {
11671 if (op & 8) {
11672 /* smlalxy */
11673 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11674 tcg_temp_free_i32(tmp2);
11675 tcg_temp_free_i32(tmp);
11676 goto illegal_op;
11678 gen_mulxy(tmp, tmp2, op & 2, op & 1);
11679 tcg_temp_free_i32(tmp2);
11680 tmp64 = tcg_temp_new_i64();
11681 tcg_gen_ext_i32_i64(tmp64, tmp);
11682 tcg_temp_free_i32(tmp);
11683 } else {
11684 /* Signed 64-bit multiply */
11685 tmp64 = gen_muls_i64_i32(tmp, tmp2);
11688 if (op & 4) {
11689 /* umaal */
11690 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
11691 tcg_temp_free_i64(tmp64);
11692 goto illegal_op;
11694 gen_addq_lo(s, tmp64, rs);
11695 gen_addq_lo(s, tmp64, rd);
11696 } else if (op & 0x40) {
11697 /* 64-bit accumulate. */
11698 gen_addq(s, tmp64, rs, rd);
11700 gen_storeq_reg(s, rs, rd, tmp64);
11701 tcg_temp_free_i64(tmp64);
11703 break;
11705 break;
11706 case 6: case 7: case 14: case 15:
11707 /* Coprocessor. */
11708 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11709 /* We don't currently implement M profile FP support,
11710 * so this entire space should give a NOCP fault, with
11711 * the exception of the v8M VLLDM and VLSTM insns, which
11712 * must be NOPs in Secure state and UNDEF in Nonsecure state.
11714 if (arm_dc_feature(s, ARM_FEATURE_V8) &&
11715 (insn & 0xffa00f00) == 0xec200a00) {
11716 /* 0b1110_1100_0x1x_xxxx_xxxx_1010_xxxx_xxxx
11717 * - VLLDM, VLSTM
11718 * We choose to UNDEF if the RAZ bits are non-zero.
11720 if (!s->v8m_secure || (insn & 0x0040f0ff)) {
11721 goto illegal_op;
11723 /* Just NOP since FP support is not implemented */
11724 break;
11726 /* All other insns: NOCP */
11727 gen_exception_insn(s, 4, EXCP_NOCP, syn_uncategorized(),
11728 default_exception_el(s));
11729 break;
11731 if ((insn & 0xfe000a00) == 0xfc000800
11732 && arm_dc_feature(s, ARM_FEATURE_V8)) {
11733 /* The Thumb2 and ARM encodings are identical. */
11734 if (disas_neon_insn_3same_ext(s, insn)) {
11735 goto illegal_op;
11737 } else if ((insn & 0xff000a00) == 0xfe000800
11738 && arm_dc_feature(s, ARM_FEATURE_V8)) {
11739 /* The Thumb2 and ARM encodings are identical. */
11740 if (disas_neon_insn_2reg_scalar_ext(s, insn)) {
11741 goto illegal_op;
11743 } else if (((insn >> 24) & 3) == 3) {
11744 /* Translate into the equivalent ARM encoding. */
11745 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
11746 if (disas_neon_data_insn(s, insn)) {
11747 goto illegal_op;
11749 } else if (((insn >> 8) & 0xe) == 10) {
11750 if (disas_vfp_insn(s, insn)) {
11751 goto illegal_op;
11753 } else {
11754 if (insn & (1 << 28))
11755 goto illegal_op;
11756 if (disas_coproc_insn(s, insn)) {
11757 goto illegal_op;
11760 break;
11761 case 8: case 9: case 10: case 11:
11762 if (insn & (1 << 15)) {
11763 /* Branches, misc control. */
11764 if (insn & 0x5000) {
11765 /* Unconditional branch. */
11766 /* signextend(hw1[10:0]) -> offset[:12]. */
11767 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
11768 /* hw1[10:0] -> offset[11:1]. */
11769 offset |= (insn & 0x7ff) << 1;
11770 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
11771 offset[24:22] already have the same value because of the
11772 sign extension above. */
11773 offset ^= ((~insn) & (1 << 13)) << 10;
11774 offset ^= ((~insn) & (1 << 11)) << 11;
11776 if (insn & (1 << 14)) {
11777 /* Branch and link. */
11778 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
11781 offset += s->pc;
11782 if (insn & (1 << 12)) {
11783 /* b/bl */
11784 gen_jmp(s, offset);
11785 } else {
11786 /* blx */
11787 offset &= ~(uint32_t)2;
11788 /* thumb2 bx, no need to check */
11789 gen_bx_im(s, offset);
11791 } else if (((insn >> 23) & 7) == 7) {
11792 /* Misc control */
11793 if (insn & (1 << 13))
11794 goto illegal_op;
11796 if (insn & (1 << 26)) {
11797 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11798 goto illegal_op;
11800 if (!(insn & (1 << 20))) {
11801 /* Hypervisor call (v7) */
11802 int imm16 = extract32(insn, 16, 4) << 12
11803 | extract32(insn, 0, 12);
11804 ARCH(7);
11805 if (IS_USER(s)) {
11806 goto illegal_op;
11808 gen_hvc(s, imm16);
11809 } else {
11810 /* Secure monitor call (v6+) */
11811 ARCH(6K);
11812 if (IS_USER(s)) {
11813 goto illegal_op;
11815 gen_smc(s);
11817 } else {
11818 op = (insn >> 20) & 7;
11819 switch (op) {
11820 case 0: /* msr cpsr. */
11821 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11822 tmp = load_reg(s, rn);
11823 /* the constant is the mask and SYSm fields */
11824 addr = tcg_const_i32(insn & 0xfff);
11825 gen_helper_v7m_msr(cpu_env, addr, tmp);
11826 tcg_temp_free_i32(addr);
11827 tcg_temp_free_i32(tmp);
11828 gen_lookup_tb(s);
11829 break;
11831 /* fall through */
11832 case 1: /* msr spsr. */
11833 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11834 goto illegal_op;
11837 if (extract32(insn, 5, 1)) {
11838 /* MSR (banked) */
11839 int sysm = extract32(insn, 8, 4) |
11840 (extract32(insn, 4, 1) << 4);
11841 int r = op & 1;
11843 gen_msr_banked(s, r, sysm, rm);
11844 break;
11847 /* MSR (for PSRs) */
11848 tmp = load_reg(s, rn);
11849 if (gen_set_psr(s,
11850 msr_mask(s, (insn >> 8) & 0xf, op == 1),
11851 op == 1, tmp))
11852 goto illegal_op;
11853 break;
11854 case 2: /* cps, nop-hint. */
11855 if (((insn >> 8) & 7) == 0) {
11856 gen_nop_hint(s, insn & 0xff);
11858 /* Implemented as NOP in user mode. */
11859 if (IS_USER(s))
11860 break;
11861 offset = 0;
11862 imm = 0;
11863 if (insn & (1 << 10)) {
11864 if (insn & (1 << 7))
11865 offset |= CPSR_A;
11866 if (insn & (1 << 6))
11867 offset |= CPSR_I;
11868 if (insn & (1 << 5))
11869 offset |= CPSR_F;
11870 if (insn & (1 << 9))
11871 imm = CPSR_A | CPSR_I | CPSR_F;
11873 if (insn & (1 << 8)) {
11874 offset |= 0x1f;
11875 imm |= (insn & 0x1f);
11877 if (offset) {
11878 gen_set_psr_im(s, offset, 0, imm);
11880 break;
11881 case 3: /* Special control operations. */
11882 if (!arm_dc_feature(s, ARM_FEATURE_V7) &&
11883 !arm_dc_feature(s, ARM_FEATURE_M)) {
11884 goto illegal_op;
11886 op = (insn >> 4) & 0xf;
11887 switch (op) {
11888 case 2: /* clrex */
11889 gen_clrex(s);
11890 break;
11891 case 4: /* dsb */
11892 case 5: /* dmb */
11893 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
11894 break;
11895 case 6: /* isb */
11896 /* We need to break the TB after this insn
11897 * to execute self-modifying code correctly
11898 * and also to take any pending interrupts
11899 * immediately.
11901 gen_goto_tb(s, 0, s->pc & ~1);
11902 break;
11903 default:
11904 goto illegal_op;
11906 break;
11907 case 4: /* bxj */
11908 /* Trivial implementation equivalent to bx.
11909 * This instruction doesn't exist at all for M-profile.
11911 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11912 goto illegal_op;
11914 tmp = load_reg(s, rn);
11915 gen_bx(s, tmp);
11916 break;
11917 case 5: /* Exception return. */
11918 if (IS_USER(s)) {
11919 goto illegal_op;
11921 if (rn != 14 || rd != 15) {
11922 goto illegal_op;
11924 if (s->current_el == 2) {
11925 /* ERET from Hyp uses ELR_Hyp, not LR */
11926 if (insn & 0xff) {
11927 goto illegal_op;
11929 tmp = load_cpu_field(elr_el[2]);
11930 } else {
11931 tmp = load_reg(s, rn);
11932 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
11934 gen_exception_return(s, tmp);
11935 break;
11936 case 6: /* MRS */
11937 if (extract32(insn, 5, 1) &&
11938 !arm_dc_feature(s, ARM_FEATURE_M)) {
11939 /* MRS (banked) */
11940 int sysm = extract32(insn, 16, 4) |
11941 (extract32(insn, 4, 1) << 4);
11943 gen_mrs_banked(s, 0, sysm, rd);
11944 break;
11947 if (extract32(insn, 16, 4) != 0xf) {
11948 goto illegal_op;
11950 if (!arm_dc_feature(s, ARM_FEATURE_M) &&
11951 extract32(insn, 0, 8) != 0) {
11952 goto illegal_op;
11955 /* mrs cpsr */
11956 tmp = tcg_temp_new_i32();
11957 if (arm_dc_feature(s, ARM_FEATURE_M)) {
11958 addr = tcg_const_i32(insn & 0xff);
11959 gen_helper_v7m_mrs(tmp, cpu_env, addr);
11960 tcg_temp_free_i32(addr);
11961 } else {
11962 gen_helper_cpsr_read(tmp, cpu_env);
11964 store_reg(s, rd, tmp);
11965 break;
11966 case 7: /* MRS */
11967 if (extract32(insn, 5, 1) &&
11968 !arm_dc_feature(s, ARM_FEATURE_M)) {
11969 /* MRS (banked) */
11970 int sysm = extract32(insn, 16, 4) |
11971 (extract32(insn, 4, 1) << 4);
11973 gen_mrs_banked(s, 1, sysm, rd);
11974 break;
11977 /* mrs spsr. */
11978 /* Not accessible in user mode. */
11979 if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) {
11980 goto illegal_op;
11983 if (extract32(insn, 16, 4) != 0xf ||
11984 extract32(insn, 0, 8) != 0) {
11985 goto illegal_op;
11988 tmp = load_cpu_field(spsr);
11989 store_reg(s, rd, tmp);
11990 break;
11993 } else {
11994 /* Conditional branch. */
11995 op = (insn >> 22) & 0xf;
11996 /* Generate a conditional jump to next instruction. */
11997 arm_skip_unless(s, op);
11999 /* offset[11:1] = insn[10:0] */
12000 offset = (insn & 0x7ff) << 1;
12001 /* offset[17:12] = insn[21:16]. */
12002 offset |= (insn & 0x003f0000) >> 4;
12003 /* offset[31:20] = insn[26]. */
12004 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
12005 /* offset[18] = insn[13]. */
12006 offset |= (insn & (1 << 13)) << 5;
12007 /* offset[19] = insn[11]. */
12008 offset |= (insn & (1 << 11)) << 8;
12010 /* jump to the offset */
12011 gen_jmp(s, s->pc + offset);
12013 } else {
12015 * 0b1111_0xxx_xxxx_0xxx_xxxx_xxxx
12016 * - Data-processing (modified immediate, plain binary immediate)
12018 if (insn & (1 << 25)) {
12020 * 0b1111_0x1x_xxxx_0xxx_xxxx_xxxx
12021 * - Data-processing (plain binary immediate)
12023 if (insn & (1 << 24)) {
12024 if (insn & (1 << 20))
12025 goto illegal_op;
12026 /* Bitfield/Saturate. */
12027 op = (insn >> 21) & 7;
12028 imm = insn & 0x1f;
12029 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
12030 if (rn == 15) {
12031 tmp = tcg_temp_new_i32();
12032 tcg_gen_movi_i32(tmp, 0);
12033 } else {
12034 tmp = load_reg(s, rn);
12036 switch (op) {
12037 case 2: /* Signed bitfield extract. */
12038 imm++;
12039 if (shift + imm > 32)
12040 goto illegal_op;
12041 if (imm < 32) {
12042 tcg_gen_sextract_i32(tmp, tmp, shift, imm);
12044 break;
12045 case 6: /* Unsigned bitfield extract. */
12046 imm++;
12047 if (shift + imm > 32)
12048 goto illegal_op;
12049 if (imm < 32) {
12050 tcg_gen_extract_i32(tmp, tmp, shift, imm);
12052 break;
12053 case 3: /* Bitfield insert/clear. */
12054 if (imm < shift)
12055 goto illegal_op;
12056 imm = imm + 1 - shift;
12057 if (imm != 32) {
12058 tmp2 = load_reg(s, rd);
12059 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, imm);
12060 tcg_temp_free_i32(tmp2);
12062 break;
12063 case 7:
12064 goto illegal_op;
12065 default: /* Saturate. */
12066 if (shift) {
12067 if (op & 1)
12068 tcg_gen_sari_i32(tmp, tmp, shift);
12069 else
12070 tcg_gen_shli_i32(tmp, tmp, shift);
12072 tmp2 = tcg_const_i32(imm);
12073 if (op & 4) {
12074 /* Unsigned. */
12075 if ((op & 1) && shift == 0) {
12076 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
12077 tcg_temp_free_i32(tmp);
12078 tcg_temp_free_i32(tmp2);
12079 goto illegal_op;
12081 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
12082 } else {
12083 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
12085 } else {
12086 /* Signed. */
12087 if ((op & 1) && shift == 0) {
12088 if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) {
12089 tcg_temp_free_i32(tmp);
12090 tcg_temp_free_i32(tmp2);
12091 goto illegal_op;
12093 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
12094 } else {
12095 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
12098 tcg_temp_free_i32(tmp2);
12099 break;
12101 store_reg(s, rd, tmp);
12102 } else {
12103 imm = ((insn & 0x04000000) >> 15)
12104 | ((insn & 0x7000) >> 4) | (insn & 0xff);
12105 if (insn & (1 << 22)) {
12106 /* 16-bit immediate. */
12107 imm |= (insn >> 4) & 0xf000;
12108 if (insn & (1 << 23)) {
12109 /* movt */
12110 tmp = load_reg(s, rd);
12111 tcg_gen_ext16u_i32(tmp, tmp);
12112 tcg_gen_ori_i32(tmp, tmp, imm << 16);
12113 } else {
12114 /* movw */
12115 tmp = tcg_temp_new_i32();
12116 tcg_gen_movi_i32(tmp, imm);
12118 store_reg(s, rd, tmp);
12119 } else {
12120 /* Add/sub 12-bit immediate. */
12121 if (rn == 15) {
12122 offset = s->pc & ~(uint32_t)3;
12123 if (insn & (1 << 23))
12124 offset -= imm;
12125 else
12126 offset += imm;
12127 tmp = tcg_temp_new_i32();
12128 tcg_gen_movi_i32(tmp, offset);
12129 store_reg(s, rd, tmp);
12130 } else {
12131 tmp = load_reg(s, rn);
12132 if (insn & (1 << 23))
12133 tcg_gen_subi_i32(tmp, tmp, imm);
12134 else
12135 tcg_gen_addi_i32(tmp, tmp, imm);
12136 if (rn == 13 && rd == 13) {
12137 /* ADD SP, SP, imm or SUB SP, SP, imm */
12138 store_sp_checked(s, tmp);
12139 } else {
12140 store_reg(s, rd, tmp);
12145 } else {
12147 * 0b1111_0x0x_xxxx_0xxx_xxxx_xxxx
12148 * - Data-processing (modified immediate)
12150 int shifter_out = 0;
12151 /* modified 12-bit immediate. */
12152 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
12153 imm = (insn & 0xff);
12154 switch (shift) {
12155 case 0: /* XY */
12156 /* Nothing to do. */
12157 break;
12158 case 1: /* 00XY00XY */
12159 imm |= imm << 16;
12160 break;
12161 case 2: /* XY00XY00 */
12162 imm |= imm << 16;
12163 imm <<= 8;
12164 break;
12165 case 3: /* XYXYXYXY */
12166 imm |= imm << 16;
12167 imm |= imm << 8;
12168 break;
12169 default: /* Rotated constant. */
12170 shift = (shift << 1) | (imm >> 7);
12171 imm |= 0x80;
12172 imm = imm << (32 - shift);
12173 shifter_out = 1;
12174 break;
12176 tmp2 = tcg_temp_new_i32();
12177 tcg_gen_movi_i32(tmp2, imm);
12178 rn = (insn >> 16) & 0xf;
12179 if (rn == 15) {
12180 tmp = tcg_temp_new_i32();
12181 tcg_gen_movi_i32(tmp, 0);
12182 } else {
12183 tmp = load_reg(s, rn);
12185 op = (insn >> 21) & 0xf;
12186 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
12187 shifter_out, tmp, tmp2))
12188 goto illegal_op;
12189 tcg_temp_free_i32(tmp2);
12190 rd = (insn >> 8) & 0xf;
12191 if (rd == 13 && rn == 13
12192 && (op == 8 || op == 13)) {
12193 /* ADD(S) SP, SP, imm or SUB(S) SP, SP, imm */
12194 store_sp_checked(s, tmp);
12195 } else if (rd != 15) {
12196 store_reg(s, rd, tmp);
12197 } else {
12198 tcg_temp_free_i32(tmp);
12202 break;
12203 case 12: /* Load/store single data item. */
12205 int postinc = 0;
12206 int writeback = 0;
12207 int memidx;
12208 ISSInfo issinfo;
12210 if ((insn & 0x01100000) == 0x01000000) {
12211 if (disas_neon_ls_insn(s, insn)) {
12212 goto illegal_op;
12214 break;
12216 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
12217 if (rs == 15) {
12218 if (!(insn & (1 << 20))) {
12219 goto illegal_op;
12221 if (op != 2) {
12222 /* Byte or halfword load space with dest == r15 : memory hints.
12223 * Catch them early so we don't emit pointless addressing code.
12224 * This space is a mix of:
12225 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
12226 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
12227 * cores)
12228 * unallocated hints, which must be treated as NOPs
12229 * UNPREDICTABLE space, which we NOP or UNDEF depending on
12230 * which is easiest for the decoding logic
12231 * Some space which must UNDEF
12233 int op1 = (insn >> 23) & 3;
12234 int op2 = (insn >> 6) & 0x3f;
12235 if (op & 2) {
12236 goto illegal_op;
12238 if (rn == 15) {
12239 /* UNPREDICTABLE, unallocated hint or
12240 * PLD/PLDW/PLI (literal)
12242 return;
12244 if (op1 & 1) {
12245 return; /* PLD/PLDW/PLI or unallocated hint */
12247 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
12248 return; /* PLD/PLDW/PLI or unallocated hint */
12250 /* UNDEF space, or an UNPREDICTABLE */
12251 goto illegal_op;
12254 memidx = get_mem_index(s);
12255 if (rn == 15) {
12256 addr = tcg_temp_new_i32();
12257 /* PC relative. */
12258 /* s->pc has already been incremented by 4. */
12259 imm = s->pc & 0xfffffffc;
12260 if (insn & (1 << 23))
12261 imm += insn & 0xfff;
12262 else
12263 imm -= insn & 0xfff;
12264 tcg_gen_movi_i32(addr, imm);
12265 } else {
12266 addr = load_reg(s, rn);
12267 if (insn & (1 << 23)) {
12268 /* Positive offset. */
12269 imm = insn & 0xfff;
12270 tcg_gen_addi_i32(addr, addr, imm);
12271 } else {
12272 imm = insn & 0xff;
12273 switch ((insn >> 8) & 0xf) {
12274 case 0x0: /* Shifted Register. */
12275 shift = (insn >> 4) & 0xf;
12276 if (shift > 3) {
12277 tcg_temp_free_i32(addr);
12278 goto illegal_op;
12280 tmp = load_reg(s, rm);
12281 if (shift)
12282 tcg_gen_shli_i32(tmp, tmp, shift);
12283 tcg_gen_add_i32(addr, addr, tmp);
12284 tcg_temp_free_i32(tmp);
12285 break;
12286 case 0xc: /* Negative offset. */
12287 tcg_gen_addi_i32(addr, addr, -imm);
12288 break;
12289 case 0xe: /* User privilege. */
12290 tcg_gen_addi_i32(addr, addr, imm);
12291 memidx = get_a32_user_mem_index(s);
12292 break;
12293 case 0x9: /* Post-decrement. */
12294 imm = -imm;
12295 /* Fall through. */
12296 case 0xb: /* Post-increment. */
12297 postinc = 1;
12298 writeback = 1;
12299 break;
12300 case 0xd: /* Pre-decrement. */
12301 imm = -imm;
12302 /* Fall through. */
12303 case 0xf: /* Pre-increment. */
12304 writeback = 1;
12305 break;
12306 default:
12307 tcg_temp_free_i32(addr);
12308 goto illegal_op;
12313 issinfo = writeback ? ISSInvalid : rs;
12315 if (s->v8m_stackcheck && rn == 13 && writeback) {
12317 * Stackcheck. Here we know 'addr' is the current SP;
12318 * if imm is +ve we're moving SP up, else down. It is
12319 * UNKNOWN whether the limit check triggers when SP starts
12320 * below the limit and ends up above it; we chose to do so.
12322 if ((int32_t)imm < 0) {
12323 TCGv_i32 newsp = tcg_temp_new_i32();
12325 tcg_gen_addi_i32(newsp, addr, imm);
12326 gen_helper_v8m_stackcheck(cpu_env, newsp);
12327 tcg_temp_free_i32(newsp);
12328 } else {
12329 gen_helper_v8m_stackcheck(cpu_env, addr);
12333 if (writeback && !postinc) {
12334 tcg_gen_addi_i32(addr, addr, imm);
12337 if (insn & (1 << 20)) {
12338 /* Load. */
12339 tmp = tcg_temp_new_i32();
12340 switch (op) {
12341 case 0:
12342 gen_aa32_ld8u_iss(s, tmp, addr, memidx, issinfo);
12343 break;
12344 case 4:
12345 gen_aa32_ld8s_iss(s, tmp, addr, memidx, issinfo);
12346 break;
12347 case 1:
12348 gen_aa32_ld16u_iss(s, tmp, addr, memidx, issinfo);
12349 break;
12350 case 5:
12351 gen_aa32_ld16s_iss(s, tmp, addr, memidx, issinfo);
12352 break;
12353 case 2:
12354 gen_aa32_ld32u_iss(s, tmp, addr, memidx, issinfo);
12355 break;
12356 default:
12357 tcg_temp_free_i32(tmp);
12358 tcg_temp_free_i32(addr);
12359 goto illegal_op;
12361 if (rs == 15) {
12362 gen_bx_excret(s, tmp);
12363 } else {
12364 store_reg(s, rs, tmp);
12366 } else {
12367 /* Store. */
12368 tmp = load_reg(s, rs);
12369 switch (op) {
12370 case 0:
12371 gen_aa32_st8_iss(s, tmp, addr, memidx, issinfo);
12372 break;
12373 case 1:
12374 gen_aa32_st16_iss(s, tmp, addr, memidx, issinfo);
12375 break;
12376 case 2:
12377 gen_aa32_st32_iss(s, tmp, addr, memidx, issinfo);
12378 break;
12379 default:
12380 tcg_temp_free_i32(tmp);
12381 tcg_temp_free_i32(addr);
12382 goto illegal_op;
12384 tcg_temp_free_i32(tmp);
12386 if (postinc)
12387 tcg_gen_addi_i32(addr, addr, imm);
12388 if (writeback) {
12389 store_reg(s, rn, addr);
12390 } else {
12391 tcg_temp_free_i32(addr);
12394 break;
12395 default:
12396 goto illegal_op;
12398 return;
12399 illegal_op:
12400 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
12401 default_exception_el(s));
12404 static void disas_thumb_insn(DisasContext *s, uint32_t insn)
12406 uint32_t val, op, rm, rn, rd, shift, cond;
12407 int32_t offset;
12408 int i;
12409 TCGv_i32 tmp;
12410 TCGv_i32 tmp2;
12411 TCGv_i32 addr;
12413 switch (insn >> 12) {
12414 case 0: case 1:
12416 rd = insn & 7;
12417 op = (insn >> 11) & 3;
12418 if (op == 3) {
12420 * 0b0001_1xxx_xxxx_xxxx
12421 * - Add, subtract (three low registers)
12422 * - Add, subtract (two low registers and immediate)
12424 rn = (insn >> 3) & 7;
12425 tmp = load_reg(s, rn);
12426 if (insn & (1 << 10)) {
12427 /* immediate */
12428 tmp2 = tcg_temp_new_i32();
12429 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
12430 } else {
12431 /* reg */
12432 rm = (insn >> 6) & 7;
12433 tmp2 = load_reg(s, rm);
12435 if (insn & (1 << 9)) {
12436 if (s->condexec_mask)
12437 tcg_gen_sub_i32(tmp, tmp, tmp2);
12438 else
12439 gen_sub_CC(tmp, tmp, tmp2);
12440 } else {
12441 if (s->condexec_mask)
12442 tcg_gen_add_i32(tmp, tmp, tmp2);
12443 else
12444 gen_add_CC(tmp, tmp, tmp2);
12446 tcg_temp_free_i32(tmp2);
12447 store_reg(s, rd, tmp);
12448 } else {
12449 /* shift immediate */
12450 rm = (insn >> 3) & 7;
12451 shift = (insn >> 6) & 0x1f;
12452 tmp = load_reg(s, rm);
12453 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
12454 if (!s->condexec_mask)
12455 gen_logic_CC(tmp);
12456 store_reg(s, rd, tmp);
12458 break;
12459 case 2: case 3:
12461 * 0b001x_xxxx_xxxx_xxxx
12462 * - Add, subtract, compare, move (one low register and immediate)
12464 op = (insn >> 11) & 3;
12465 rd = (insn >> 8) & 0x7;
12466 if (op == 0) { /* mov */
12467 tmp = tcg_temp_new_i32();
12468 tcg_gen_movi_i32(tmp, insn & 0xff);
12469 if (!s->condexec_mask)
12470 gen_logic_CC(tmp);
12471 store_reg(s, rd, tmp);
12472 } else {
12473 tmp = load_reg(s, rd);
12474 tmp2 = tcg_temp_new_i32();
12475 tcg_gen_movi_i32(tmp2, insn & 0xff);
12476 switch (op) {
12477 case 1: /* cmp */
12478 gen_sub_CC(tmp, tmp, tmp2);
12479 tcg_temp_free_i32(tmp);
12480 tcg_temp_free_i32(tmp2);
12481 break;
12482 case 2: /* add */
12483 if (s->condexec_mask)
12484 tcg_gen_add_i32(tmp, tmp, tmp2);
12485 else
12486 gen_add_CC(tmp, tmp, tmp2);
12487 tcg_temp_free_i32(tmp2);
12488 store_reg(s, rd, tmp);
12489 break;
12490 case 3: /* sub */
12491 if (s->condexec_mask)
12492 tcg_gen_sub_i32(tmp, tmp, tmp2);
12493 else
12494 gen_sub_CC(tmp, tmp, tmp2);
12495 tcg_temp_free_i32(tmp2);
12496 store_reg(s, rd, tmp);
12497 break;
12500 break;
12501 case 4:
12502 if (insn & (1 << 11)) {
12503 rd = (insn >> 8) & 7;
12504 /* load pc-relative. Bit 1 of PC is ignored. */
12505 val = s->pc + 2 + ((insn & 0xff) * 4);
12506 val &= ~(uint32_t)2;
12507 addr = tcg_temp_new_i32();
12508 tcg_gen_movi_i32(addr, val);
12509 tmp = tcg_temp_new_i32();
12510 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s),
12511 rd | ISSIs16Bit);
12512 tcg_temp_free_i32(addr);
12513 store_reg(s, rd, tmp);
12514 break;
12516 if (insn & (1 << 10)) {
12517 /* 0b0100_01xx_xxxx_xxxx
12518 * - data processing extended, branch and exchange
12520 rd = (insn & 7) | ((insn >> 4) & 8);
12521 rm = (insn >> 3) & 0xf;
12522 op = (insn >> 8) & 3;
12523 switch (op) {
12524 case 0: /* add */
12525 tmp = load_reg(s, rd);
12526 tmp2 = load_reg(s, rm);
12527 tcg_gen_add_i32(tmp, tmp, tmp2);
12528 tcg_temp_free_i32(tmp2);
12529 if (rd == 13) {
12530 /* ADD SP, SP, reg */
12531 store_sp_checked(s, tmp);
12532 } else {
12533 store_reg(s, rd, tmp);
12535 break;
12536 case 1: /* cmp */
12537 tmp = load_reg(s, rd);
12538 tmp2 = load_reg(s, rm);
12539 gen_sub_CC(tmp, tmp, tmp2);
12540 tcg_temp_free_i32(tmp2);
12541 tcg_temp_free_i32(tmp);
12542 break;
12543 case 2: /* mov/cpy */
12544 tmp = load_reg(s, rm);
12545 if (rd == 13) {
12546 /* MOV SP, reg */
12547 store_sp_checked(s, tmp);
12548 } else {
12549 store_reg(s, rd, tmp);
12551 break;
12552 case 3:
12554 /* 0b0100_0111_xxxx_xxxx
12555 * - branch [and link] exchange thumb register
12557 bool link = insn & (1 << 7);
12559 if (insn & 3) {
12560 goto undef;
12562 if (link) {
12563 ARCH(5);
12565 if ((insn & 4)) {
12566 /* BXNS/BLXNS: only exists for v8M with the
12567 * security extensions, and always UNDEF if NonSecure.
12568 * We don't implement these in the user-only mode
12569 * either (in theory you can use them from Secure User
12570 * mode but they are too tied in to system emulation.)
12572 if (!s->v8m_secure || IS_USER_ONLY) {
12573 goto undef;
12575 if (link) {
12576 gen_blxns(s, rm);
12577 } else {
12578 gen_bxns(s, rm);
12580 break;
12582 /* BLX/BX */
12583 tmp = load_reg(s, rm);
12584 if (link) {
12585 val = (uint32_t)s->pc | 1;
12586 tmp2 = tcg_temp_new_i32();
12587 tcg_gen_movi_i32(tmp2, val);
12588 store_reg(s, 14, tmp2);
12589 gen_bx(s, tmp);
12590 } else {
12591 /* Only BX works as exception-return, not BLX */
12592 gen_bx_excret(s, tmp);
12594 break;
12597 break;
12601 * 0b0100_00xx_xxxx_xxxx
12602 * - Data-processing (two low registers)
12604 rd = insn & 7;
12605 rm = (insn >> 3) & 7;
12606 op = (insn >> 6) & 0xf;
12607 if (op == 2 || op == 3 || op == 4 || op == 7) {
12608 /* the shift/rotate ops want the operands backwards */
12609 val = rm;
12610 rm = rd;
12611 rd = val;
12612 val = 1;
12613 } else {
12614 val = 0;
12617 if (op == 9) { /* neg */
12618 tmp = tcg_temp_new_i32();
12619 tcg_gen_movi_i32(tmp, 0);
12620 } else if (op != 0xf) { /* mvn doesn't read its first operand */
12621 tmp = load_reg(s, rd);
12622 } else {
12623 tmp = NULL;
12626 tmp2 = load_reg(s, rm);
12627 switch (op) {
12628 case 0x0: /* and */
12629 tcg_gen_and_i32(tmp, tmp, tmp2);
12630 if (!s->condexec_mask)
12631 gen_logic_CC(tmp);
12632 break;
12633 case 0x1: /* eor */
12634 tcg_gen_xor_i32(tmp, tmp, tmp2);
12635 if (!s->condexec_mask)
12636 gen_logic_CC(tmp);
12637 break;
12638 case 0x2: /* lsl */
12639 if (s->condexec_mask) {
12640 gen_shl(tmp2, tmp2, tmp);
12641 } else {
12642 gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
12643 gen_logic_CC(tmp2);
12645 break;
12646 case 0x3: /* lsr */
12647 if (s->condexec_mask) {
12648 gen_shr(tmp2, tmp2, tmp);
12649 } else {
12650 gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
12651 gen_logic_CC(tmp2);
12653 break;
12654 case 0x4: /* asr */
12655 if (s->condexec_mask) {
12656 gen_sar(tmp2, tmp2, tmp);
12657 } else {
12658 gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
12659 gen_logic_CC(tmp2);
12661 break;
12662 case 0x5: /* adc */
12663 if (s->condexec_mask) {
12664 gen_adc(tmp, tmp2);
12665 } else {
12666 gen_adc_CC(tmp, tmp, tmp2);
12668 break;
12669 case 0x6: /* sbc */
12670 if (s->condexec_mask) {
12671 gen_sub_carry(tmp, tmp, tmp2);
12672 } else {
12673 gen_sbc_CC(tmp, tmp, tmp2);
12675 break;
12676 case 0x7: /* ror */
12677 if (s->condexec_mask) {
12678 tcg_gen_andi_i32(tmp, tmp, 0x1f);
12679 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
12680 } else {
12681 gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);
12682 gen_logic_CC(tmp2);
12684 break;
12685 case 0x8: /* tst */
12686 tcg_gen_and_i32(tmp, tmp, tmp2);
12687 gen_logic_CC(tmp);
12688 rd = 16;
12689 break;
12690 case 0x9: /* neg */
12691 if (s->condexec_mask)
12692 tcg_gen_neg_i32(tmp, tmp2);
12693 else
12694 gen_sub_CC(tmp, tmp, tmp2);
12695 break;
12696 case 0xa: /* cmp */
12697 gen_sub_CC(tmp, tmp, tmp2);
12698 rd = 16;
12699 break;
12700 case 0xb: /* cmn */
12701 gen_add_CC(tmp, tmp, tmp2);
12702 rd = 16;
12703 break;
12704 case 0xc: /* orr */
12705 tcg_gen_or_i32(tmp, tmp, tmp2);
12706 if (!s->condexec_mask)
12707 gen_logic_CC(tmp);
12708 break;
12709 case 0xd: /* mul */
12710 tcg_gen_mul_i32(tmp, tmp, tmp2);
12711 if (!s->condexec_mask)
12712 gen_logic_CC(tmp);
12713 break;
12714 case 0xe: /* bic */
12715 tcg_gen_andc_i32(tmp, tmp, tmp2);
12716 if (!s->condexec_mask)
12717 gen_logic_CC(tmp);
12718 break;
12719 case 0xf: /* mvn */
12720 tcg_gen_not_i32(tmp2, tmp2);
12721 if (!s->condexec_mask)
12722 gen_logic_CC(tmp2);
12723 val = 1;
12724 rm = rd;
12725 break;
12727 if (rd != 16) {
12728 if (val) {
12729 store_reg(s, rm, tmp2);
12730 if (op != 0xf)
12731 tcg_temp_free_i32(tmp);
12732 } else {
12733 store_reg(s, rd, tmp);
12734 tcg_temp_free_i32(tmp2);
12736 } else {
12737 tcg_temp_free_i32(tmp);
12738 tcg_temp_free_i32(tmp2);
12740 break;
12742 case 5:
12743 /* load/store register offset. */
12744 rd = insn & 7;
12745 rn = (insn >> 3) & 7;
12746 rm = (insn >> 6) & 7;
12747 op = (insn >> 9) & 7;
12748 addr = load_reg(s, rn);
12749 tmp = load_reg(s, rm);
12750 tcg_gen_add_i32(addr, addr, tmp);
12751 tcg_temp_free_i32(tmp);
12753 if (op < 3) { /* store */
12754 tmp = load_reg(s, rd);
12755 } else {
12756 tmp = tcg_temp_new_i32();
12759 switch (op) {
12760 case 0: /* str */
12761 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12762 break;
12763 case 1: /* strh */
12764 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12765 break;
12766 case 2: /* strb */
12767 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12768 break;
12769 case 3: /* ldrsb */
12770 gen_aa32_ld8s_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12771 break;
12772 case 4: /* ldr */
12773 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12774 break;
12775 case 5: /* ldrh */
12776 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12777 break;
12778 case 6: /* ldrb */
12779 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12780 break;
12781 case 7: /* ldrsh */
12782 gen_aa32_ld16s_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12783 break;
12785 if (op >= 3) { /* load */
12786 store_reg(s, rd, tmp);
12787 } else {
12788 tcg_temp_free_i32(tmp);
12790 tcg_temp_free_i32(addr);
12791 break;
12793 case 6:
12794 /* load/store word immediate offset */
12795 rd = insn & 7;
12796 rn = (insn >> 3) & 7;
12797 addr = load_reg(s, rn);
12798 val = (insn >> 4) & 0x7c;
12799 tcg_gen_addi_i32(addr, addr, val);
12801 if (insn & (1 << 11)) {
12802 /* load */
12803 tmp = tcg_temp_new_i32();
12804 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
12805 store_reg(s, rd, tmp);
12806 } else {
12807 /* store */
12808 tmp = load_reg(s, rd);
12809 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
12810 tcg_temp_free_i32(tmp);
12812 tcg_temp_free_i32(addr);
12813 break;
12815 case 7:
12816 /* load/store byte immediate offset */
12817 rd = insn & 7;
12818 rn = (insn >> 3) & 7;
12819 addr = load_reg(s, rn);
12820 val = (insn >> 6) & 0x1f;
12821 tcg_gen_addi_i32(addr, addr, val);
12823 if (insn & (1 << 11)) {
12824 /* load */
12825 tmp = tcg_temp_new_i32();
12826 gen_aa32_ld8u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12827 store_reg(s, rd, tmp);
12828 } else {
12829 /* store */
12830 tmp = load_reg(s, rd);
12831 gen_aa32_st8_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12832 tcg_temp_free_i32(tmp);
12834 tcg_temp_free_i32(addr);
12835 break;
12837 case 8:
12838 /* load/store halfword immediate offset */
12839 rd = insn & 7;
12840 rn = (insn >> 3) & 7;
12841 addr = load_reg(s, rn);
12842 val = (insn >> 5) & 0x3e;
12843 tcg_gen_addi_i32(addr, addr, val);
12845 if (insn & (1 << 11)) {
12846 /* load */
12847 tmp = tcg_temp_new_i32();
12848 gen_aa32_ld16u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12849 store_reg(s, rd, tmp);
12850 } else {
12851 /* store */
12852 tmp = load_reg(s, rd);
12853 gen_aa32_st16_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12854 tcg_temp_free_i32(tmp);
12856 tcg_temp_free_i32(addr);
12857 break;
12859 case 9:
12860 /* load/store from stack */
12861 rd = (insn >> 8) & 7;
12862 addr = load_reg(s, 13);
12863 val = (insn & 0xff) * 4;
12864 tcg_gen_addi_i32(addr, addr, val);
12866 if (insn & (1 << 11)) {
12867 /* load */
12868 tmp = tcg_temp_new_i32();
12869 gen_aa32_ld32u_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12870 store_reg(s, rd, tmp);
12871 } else {
12872 /* store */
12873 tmp = load_reg(s, rd);
12874 gen_aa32_st32_iss(s, tmp, addr, get_mem_index(s), rd | ISSIs16Bit);
12875 tcg_temp_free_i32(tmp);
12877 tcg_temp_free_i32(addr);
12878 break;
12880 case 10:
12882 * 0b1010_xxxx_xxxx_xxxx
12883 * - Add PC/SP (immediate)
12885 rd = (insn >> 8) & 7;
12886 if (insn & (1 << 11)) {
12887 /* SP */
12888 tmp = load_reg(s, 13);
12889 } else {
12890 /* PC. bit 1 is ignored. */
12891 tmp = tcg_temp_new_i32();
12892 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
12894 val = (insn & 0xff) * 4;
12895 tcg_gen_addi_i32(tmp, tmp, val);
12896 store_reg(s, rd, tmp);
12897 break;
12899 case 11:
12900 /* misc */
12901 op = (insn >> 8) & 0xf;
12902 switch (op) {
12903 case 0:
12905 * 0b1011_0000_xxxx_xxxx
12906 * - ADD (SP plus immediate)
12907 * - SUB (SP minus immediate)
12909 tmp = load_reg(s, 13);
12910 val = (insn & 0x7f) * 4;
12911 if (insn & (1 << 7))
12912 val = -(int32_t)val;
12913 tcg_gen_addi_i32(tmp, tmp, val);
12914 store_sp_checked(s, tmp);
12915 break;
12917 case 2: /* sign/zero extend. */
12918 ARCH(6);
12919 rd = insn & 7;
12920 rm = (insn >> 3) & 7;
12921 tmp = load_reg(s, rm);
12922 switch ((insn >> 6) & 3) {
12923 case 0: gen_sxth(tmp); break;
12924 case 1: gen_sxtb(tmp); break;
12925 case 2: gen_uxth(tmp); break;
12926 case 3: gen_uxtb(tmp); break;
12928 store_reg(s, rd, tmp);
12929 break;
12930 case 4: case 5: case 0xc: case 0xd:
12932 * 0b1011_x10x_xxxx_xxxx
12933 * - push/pop
12935 addr = load_reg(s, 13);
12936 if (insn & (1 << 8))
12937 offset = 4;
12938 else
12939 offset = 0;
12940 for (i = 0; i < 8; i++) {
12941 if (insn & (1 << i))
12942 offset += 4;
12944 if ((insn & (1 << 11)) == 0) {
12945 tcg_gen_addi_i32(addr, addr, -offset);
12948 if (s->v8m_stackcheck) {
12950 * Here 'addr' is the lower of "old SP" and "new SP";
12951 * if this is a pop that starts below the limit and ends
12952 * above it, it is UNKNOWN whether the limit check triggers;
12953 * we choose to trigger.
12955 gen_helper_v8m_stackcheck(cpu_env, addr);
12958 for (i = 0; i < 8; i++) {
12959 if (insn & (1 << i)) {
12960 if (insn & (1 << 11)) {
12961 /* pop */
12962 tmp = tcg_temp_new_i32();
12963 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
12964 store_reg(s, i, tmp);
12965 } else {
12966 /* push */
12967 tmp = load_reg(s, i);
12968 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
12969 tcg_temp_free_i32(tmp);
12971 /* advance to the next address. */
12972 tcg_gen_addi_i32(addr, addr, 4);
12975 tmp = NULL;
12976 if (insn & (1 << 8)) {
12977 if (insn & (1 << 11)) {
12978 /* pop pc */
12979 tmp = tcg_temp_new_i32();
12980 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
12981 /* don't set the pc until the rest of the instruction
12982 has completed */
12983 } else {
12984 /* push lr */
12985 tmp = load_reg(s, 14);
12986 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
12987 tcg_temp_free_i32(tmp);
12989 tcg_gen_addi_i32(addr, addr, 4);
12991 if ((insn & (1 << 11)) == 0) {
12992 tcg_gen_addi_i32(addr, addr, -offset);
12994 /* write back the new stack pointer */
12995 store_reg(s, 13, addr);
12996 /* set the new PC value */
12997 if ((insn & 0x0900) == 0x0900) {
12998 store_reg_from_load(s, 15, tmp);
13000 break;
13002 case 1: case 3: case 9: case 11: /* czb */
13003 rm = insn & 7;
13004 tmp = load_reg(s, rm);
13005 arm_gen_condlabel(s);
13006 if (insn & (1 << 11))
13007 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
13008 else
13009 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
13010 tcg_temp_free_i32(tmp);
13011 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
13012 val = (uint32_t)s->pc + 2;
13013 val += offset;
13014 gen_jmp(s, val);
13015 break;
13017 case 15: /* IT, nop-hint. */
13018 if ((insn & 0xf) == 0) {
13019 gen_nop_hint(s, (insn >> 4) & 0xf);
13020 break;
13022 /* If Then. */
13023 s->condexec_cond = (insn >> 4) & 0xe;
13024 s->condexec_mask = insn & 0x1f;
13025 /* No actual code generated for this insn, just setup state. */
13026 break;
13028 case 0xe: /* bkpt */
13030 int imm8 = extract32(insn, 0, 8);
13031 ARCH(5);
13032 gen_exception_bkpt_insn(s, 2, syn_aa32_bkpt(imm8, true));
13033 break;
13036 case 0xa: /* rev, and hlt */
13038 int op1 = extract32(insn, 6, 2);
13040 if (op1 == 2) {
13041 /* HLT */
13042 int imm6 = extract32(insn, 0, 6);
13044 gen_hlt(s, imm6);
13045 break;
13048 /* Otherwise this is rev */
13049 ARCH(6);
13050 rn = (insn >> 3) & 0x7;
13051 rd = insn & 0x7;
13052 tmp = load_reg(s, rn);
13053 switch (op1) {
13054 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
13055 case 1: gen_rev16(tmp); break;
13056 case 3: gen_revsh(tmp); break;
13057 default:
13058 g_assert_not_reached();
13060 store_reg(s, rd, tmp);
13061 break;
13064 case 6:
13065 switch ((insn >> 5) & 7) {
13066 case 2:
13067 /* setend */
13068 ARCH(6);
13069 if (((insn >> 3) & 1) != !!(s->be_data == MO_BE)) {
13070 gen_helper_setend(cpu_env);
13071 s->base.is_jmp = DISAS_UPDATE;
13073 break;
13074 case 3:
13075 /* cps */
13076 ARCH(6);
13077 if (IS_USER(s)) {
13078 break;
13080 if (arm_dc_feature(s, ARM_FEATURE_M)) {
13081 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
13082 /* FAULTMASK */
13083 if (insn & 1) {
13084 addr = tcg_const_i32(19);
13085 gen_helper_v7m_msr(cpu_env, addr, tmp);
13086 tcg_temp_free_i32(addr);
13088 /* PRIMASK */
13089 if (insn & 2) {
13090 addr = tcg_const_i32(16);
13091 gen_helper_v7m_msr(cpu_env, addr, tmp);
13092 tcg_temp_free_i32(addr);
13094 tcg_temp_free_i32(tmp);
13095 gen_lookup_tb(s);
13096 } else {
13097 if (insn & (1 << 4)) {
13098 shift = CPSR_A | CPSR_I | CPSR_F;
13099 } else {
13100 shift = 0;
13102 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
13104 break;
13105 default:
13106 goto undef;
13108 break;
13110 default:
13111 goto undef;
13113 break;
13115 case 12:
13117 /* load/store multiple */
13118 TCGv_i32 loaded_var = NULL;
13119 rn = (insn >> 8) & 0x7;
13120 addr = load_reg(s, rn);
13121 for (i = 0; i < 8; i++) {
13122 if (insn & (1 << i)) {
13123 if (insn & (1 << 11)) {
13124 /* load */
13125 tmp = tcg_temp_new_i32();
13126 gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
13127 if (i == rn) {
13128 loaded_var = tmp;
13129 } else {
13130 store_reg(s, i, tmp);
13132 } else {
13133 /* store */
13134 tmp = load_reg(s, i);
13135 gen_aa32_st32(s, tmp, addr, get_mem_index(s));
13136 tcg_temp_free_i32(tmp);
13138 /* advance to the next address */
13139 tcg_gen_addi_i32(addr, addr, 4);
13142 if ((insn & (1 << rn)) == 0) {
13143 /* base reg not in list: base register writeback */
13144 store_reg(s, rn, addr);
13145 } else {
13146 /* base reg in list: if load, complete it now */
13147 if (insn & (1 << 11)) {
13148 store_reg(s, rn, loaded_var);
13150 tcg_temp_free_i32(addr);
13152 break;
13154 case 13:
13155 /* conditional branch or swi */
13156 cond = (insn >> 8) & 0xf;
13157 if (cond == 0xe)
13158 goto undef;
13160 if (cond == 0xf) {
13161 /* swi */
13162 gen_set_pc_im(s, s->pc);
13163 s->svc_imm = extract32(insn, 0, 8);
13164 s->base.is_jmp = DISAS_SWI;
13165 break;
13167 /* generate a conditional jump to next instruction */
13168 arm_skip_unless(s, cond);
13170 /* jump to the offset */
13171 val = (uint32_t)s->pc + 2;
13172 offset = ((int32_t)insn << 24) >> 24;
13173 val += offset << 1;
13174 gen_jmp(s, val);
13175 break;
13177 case 14:
13178 if (insn & (1 << 11)) {
13179 /* thumb_insn_is_16bit() ensures we can't get here for
13180 * a Thumb2 CPU, so this must be a thumb1 split BL/BLX:
13181 * 0b1110_1xxx_xxxx_xxxx : BLX suffix (or UNDEF)
13183 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
13184 ARCH(5);
13185 offset = ((insn & 0x7ff) << 1);
13186 tmp = load_reg(s, 14);
13187 tcg_gen_addi_i32(tmp, tmp, offset);
13188 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
13190 tmp2 = tcg_temp_new_i32();
13191 tcg_gen_movi_i32(tmp2, s->pc | 1);
13192 store_reg(s, 14, tmp2);
13193 gen_bx(s, tmp);
13194 break;
13196 /* unconditional branch */
13197 val = (uint32_t)s->pc;
13198 offset = ((int32_t)insn << 21) >> 21;
13199 val += (offset << 1) + 2;
13200 gen_jmp(s, val);
13201 break;
13203 case 15:
13204 /* thumb_insn_is_16bit() ensures we can't get here for
13205 * a Thumb2 CPU, so this must be a thumb1 split BL/BLX.
13207 assert(!arm_dc_feature(s, ARM_FEATURE_THUMB2));
13209 if (insn & (1 << 11)) {
13210 /* 0b1111_1xxx_xxxx_xxxx : BL suffix */
13211 offset = ((insn & 0x7ff) << 1) | 1;
13212 tmp = load_reg(s, 14);
13213 tcg_gen_addi_i32(tmp, tmp, offset);
13215 tmp2 = tcg_temp_new_i32();
13216 tcg_gen_movi_i32(tmp2, s->pc | 1);
13217 store_reg(s, 14, tmp2);
13218 gen_bx(s, tmp);
13219 } else {
13220 /* 0b1111_0xxx_xxxx_xxxx : BL/BLX prefix */
13221 uint32_t uoffset = ((int32_t)insn << 21) >> 9;
13223 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + uoffset);
13225 break;
13227 return;
13228 illegal_op:
13229 undef:
13230 gen_exception_insn(s, 2, EXCP_UDEF, syn_uncategorized(),
13231 default_exception_el(s));
13234 static bool insn_crosses_page(CPUARMState *env, DisasContext *s)
13236 /* Return true if the insn at dc->pc might cross a page boundary.
13237 * (False positives are OK, false negatives are not.)
13238 * We know this is a Thumb insn, and our caller ensures we are
13239 * only called if dc->pc is less than 4 bytes from the page
13240 * boundary, so we cross the page if the first 16 bits indicate
13241 * that this is a 32 bit insn.
13243 uint16_t insn = arm_lduw_code(env, s->pc, s->sctlr_b);
13245 return !thumb_insn_is_16bit(s, insn);
13248 static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
13250 DisasContext *dc = container_of(dcbase, DisasContext, base);
13251 CPUARMState *env = cs->env_ptr;
13252 ARMCPU *cpu = arm_env_get_cpu(env);
13253 uint32_t tb_flags = dc->base.tb->flags;
13254 uint32_t condexec, core_mmu_idx;
13256 dc->isar = &cpu->isar;
13257 dc->pc = dc->base.pc_first;
13258 dc->condjmp = 0;
13260 dc->aarch64 = 0;
13261 /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
13262 * there is no secure EL1, so we route exceptions to EL3.
13264 dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
13265 !arm_el_is_aa64(env, 3);
13266 dc->thumb = FIELD_EX32(tb_flags, TBFLAG_A32, THUMB);
13267 dc->sctlr_b = FIELD_EX32(tb_flags, TBFLAG_A32, SCTLR_B);
13268 dc->be_data = FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
13269 condexec = FIELD_EX32(tb_flags, TBFLAG_A32, CONDEXEC);
13270 dc->condexec_mask = (condexec & 0xf) << 1;
13271 dc->condexec_cond = condexec >> 4;
13272 core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX);
13273 dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
13274 dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
13275 #if !defined(CONFIG_USER_ONLY)
13276 dc->user = (dc->current_el == 0);
13277 #endif
13278 dc->ns = FIELD_EX32(tb_flags, TBFLAG_A32, NS);
13279 dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL);
13280 dc->vfp_enabled = FIELD_EX32(tb_flags, TBFLAG_A32, VFPEN);
13281 dc->vec_len = FIELD_EX32(tb_flags, TBFLAG_A32, VECLEN);
13282 dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
13283 dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
13284 dc->v7m_handler_mode = FIELD_EX32(tb_flags, TBFLAG_A32, HANDLER);
13285 dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
13286 regime_is_secure(env, dc->mmu_idx);
13287 dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_A32, STACKCHECK);
13288 dc->cp_regs = cpu->cp_regs;
13289 dc->features = env->features;
13291 /* Single step state. The code-generation logic here is:
13292 * SS_ACTIVE == 0:
13293 * generate code with no special handling for single-stepping (except
13294 * that anything that can make us go to SS_ACTIVE == 1 must end the TB;
13295 * this happens anyway because those changes are all system register or
13296 * PSTATE writes).
13297 * SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
13298 * emit code for one insn
13299 * emit code to clear PSTATE.SS
13300 * emit code to generate software step exception for completed step
13301 * end TB (as usual for having generated an exception)
13302 * SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
13303 * emit code to generate a software step exception
13304 * end the TB
13306 dc->ss_active = FIELD_EX32(tb_flags, TBFLAG_ANY, SS_ACTIVE);
13307 dc->pstate_ss = FIELD_EX32(tb_flags, TBFLAG_ANY, PSTATE_SS);
13308 dc->is_ldex = false;
13309 dc->ss_same_el = false; /* Can't be true since EL_d must be AArch64 */
13311 dc->page_start = dc->base.pc_first & TARGET_PAGE_MASK;
13313 /* If architectural single step active, limit to 1. */
13314 if (is_singlestepping(dc)) {
13315 dc->base.max_insns = 1;
13318 /* ARM is a fixed-length ISA. Bound the number of insns to execute
13319 to those left on the page. */
13320 if (!dc->thumb) {
13321 int bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
13322 dc->base.max_insns = MIN(dc->base.max_insns, bound);
13325 cpu_F0s = tcg_temp_new_i32();
13326 cpu_F1s = tcg_temp_new_i32();
13327 cpu_F0d = tcg_temp_new_i64();
13328 cpu_F1d = tcg_temp_new_i64();
13329 cpu_V0 = cpu_F0d;
13330 cpu_V1 = cpu_F1d;
13331 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
13332 cpu_M0 = tcg_temp_new_i64();
13335 static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
13337 DisasContext *dc = container_of(dcbase, DisasContext, base);
13339 /* A note on handling of the condexec (IT) bits:
13341 * We want to avoid the overhead of having to write the updated condexec
13342 * bits back to the CPUARMState for every instruction in an IT block. So:
13343 * (1) if the condexec bits are not already zero then we write
13344 * zero back into the CPUARMState now. This avoids complications trying
13345 * to do it at the end of the block. (For example if we don't do this
13346 * it's hard to identify whether we can safely skip writing condexec
13347 * at the end of the TB, which we definitely want to do for the case
13348 * where a TB doesn't do anything with the IT state at all.)
13349 * (2) if we are going to leave the TB then we call gen_set_condexec()
13350 * which will write the correct value into CPUARMState if zero is wrong.
13351 * This is done both for leaving the TB at the end, and for leaving
13352 * it because of an exception we know will happen, which is done in
13353 * gen_exception_insn(). The latter is necessary because we need to
13354 * leave the TB with the PC/IT state just prior to execution of the
13355 * instruction which caused the exception.
13356 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
13357 * then the CPUARMState will be wrong and we need to reset it.
13358 * This is handled in the same way as restoration of the
13359 * PC in these situations; we save the value of the condexec bits
13360 * for each PC via tcg_gen_insn_start(), and restore_state_to_opc()
13361 * then uses this to restore them after an exception.
13363 * Note that there are no instructions which can read the condexec
13364 * bits, and none which can write non-static values to them, so
13365 * we don't need to care about whether CPUARMState is correct in the
13366 * middle of a TB.
13369 /* Reset the conditional execution bits immediately. This avoids
13370 complications trying to do it at the end of the block. */
13371 if (dc->condexec_mask || dc->condexec_cond) {
13372 TCGv_i32 tmp = tcg_temp_new_i32();
13373 tcg_gen_movi_i32(tmp, 0);
13374 store_cpu_field(tmp, condexec_bits);
13378 static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
13380 DisasContext *dc = container_of(dcbase, DisasContext, base);
13382 tcg_gen_insn_start(dc->pc,
13383 (dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
13385 dc->insn_start = tcg_last_op();
13388 static bool arm_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
13389 const CPUBreakpoint *bp)
13391 DisasContext *dc = container_of(dcbase, DisasContext, base);
13393 if (bp->flags & BP_CPU) {
13394 gen_set_condexec(dc);
13395 gen_set_pc_im(dc, dc->pc);
13396 gen_helper_check_breakpoints(cpu_env);
13397 /* End the TB early; it's likely not going to be executed */
13398 dc->base.is_jmp = DISAS_TOO_MANY;
13399 } else {
13400 gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
13401 /* The address covered by the breakpoint must be
13402 included in [tb->pc, tb->pc + tb->size) in order
13403 to for it to be properly cleared -- thus we
13404 increment the PC here so that the logic setting
13405 tb->size below does the right thing. */
13406 /* TODO: Advance PC by correct instruction length to
13407 * avoid disassembler error messages */
13408 dc->pc += 2;
13409 dc->base.is_jmp = DISAS_NORETURN;
13412 return true;
13415 static bool arm_pre_translate_insn(DisasContext *dc)
13417 #ifdef CONFIG_USER_ONLY
13418 /* Intercept jump to the magic kernel page. */
13419 if (dc->pc >= 0xffff0000) {
13420 /* We always get here via a jump, so know we are not in a
13421 conditional execution block. */
13422 gen_exception_internal(EXCP_KERNEL_TRAP);
13423 dc->base.is_jmp = DISAS_NORETURN;
13424 return true;
13426 #endif
13428 if (dc->ss_active && !dc->pstate_ss) {
13429 /* Singlestep state is Active-pending.
13430 * If we're in this state at the start of a TB then either
13431 * a) we just took an exception to an EL which is being debugged
13432 * and this is the first insn in the exception handler
13433 * b) debug exceptions were masked and we just unmasked them
13434 * without changing EL (eg by clearing PSTATE.D)
13435 * In either case we're going to take a swstep exception in the
13436 * "did not step an insn" case, and so the syndrome ISV and EX
13437 * bits should be zero.
13439 assert(dc->base.num_insns == 1);
13440 gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
13441 default_exception_el(dc));
13442 dc->base.is_jmp = DISAS_NORETURN;
13443 return true;
13446 return false;
13449 static void arm_post_translate_insn(DisasContext *dc)
13451 if (dc->condjmp && !dc->base.is_jmp) {
13452 gen_set_label(dc->condlabel);
13453 dc->condjmp = 0;
13455 dc->base.pc_next = dc->pc;
13456 translator_loop_temp_check(&dc->base);
13459 static void arm_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
13461 DisasContext *dc = container_of(dcbase, DisasContext, base);
13462 CPUARMState *env = cpu->env_ptr;
13463 unsigned int insn;
13465 if (arm_pre_translate_insn(dc)) {
13466 return;
13469 insn = arm_ldl_code(env, dc->pc, dc->sctlr_b);
13470 dc->insn = insn;
13471 dc->pc += 4;
13472 disas_arm_insn(dc, insn);
13474 arm_post_translate_insn(dc);
13476 /* ARM is a fixed-length ISA. We performed the cross-page check
13477 in init_disas_context by adjusting max_insns. */
13480 static bool thumb_insn_is_unconditional(DisasContext *s, uint32_t insn)
13482 /* Return true if this Thumb insn is always unconditional,
13483 * even inside an IT block. This is true of only a very few
13484 * instructions: BKPT, HLT, and SG.
13486 * A larger class of instructions are UNPREDICTABLE if used
13487 * inside an IT block; we do not need to detect those here, because
13488 * what we do by default (perform the cc check and update the IT
13489 * bits state machine) is a permitted CONSTRAINED UNPREDICTABLE
13490 * choice for those situations.
13492 * insn is either a 16-bit or a 32-bit instruction; the two are
13493 * distinguishable because for the 16-bit case the top 16 bits
13494 * are zeroes, and that isn't a valid 32-bit encoding.
13496 if ((insn & 0xffffff00) == 0xbe00) {
13497 /* BKPT */
13498 return true;
13501 if ((insn & 0xffffffc0) == 0xba80 && arm_dc_feature(s, ARM_FEATURE_V8) &&
13502 !arm_dc_feature(s, ARM_FEATURE_M)) {
13503 /* HLT: v8A only. This is unconditional even when it is going to
13504 * UNDEF; see the v8A ARM ARM DDI0487B.a H3.3.
13505 * For v7 cores this was a plain old undefined encoding and so
13506 * honours its cc check. (We might be using the encoding as
13507 * a semihosting trap, but we don't change the cc check behaviour
13508 * on that account, because a debugger connected to a real v7A
13509 * core and emulating semihosting traps by catching the UNDEF
13510 * exception would also only see cases where the cc check passed.
13511 * No guest code should be trying to do a HLT semihosting trap
13512 * in an IT block anyway.
13514 return true;
13517 if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_V8) &&
13518 arm_dc_feature(s, ARM_FEATURE_M)) {
13519 /* SG: v8M only */
13520 return true;
13523 return false;
13526 static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
13528 DisasContext *dc = container_of(dcbase, DisasContext, base);
13529 CPUARMState *env = cpu->env_ptr;
13530 uint32_t insn;
13531 bool is_16bit;
13533 if (arm_pre_translate_insn(dc)) {
13534 return;
13537 insn = arm_lduw_code(env, dc->pc, dc->sctlr_b);
13538 is_16bit = thumb_insn_is_16bit(dc, insn);
13539 dc->pc += 2;
13540 if (!is_16bit) {
13541 uint32_t insn2 = arm_lduw_code(env, dc->pc, dc->sctlr_b);
13543 insn = insn << 16 | insn2;
13544 dc->pc += 2;
13546 dc->insn = insn;
13548 if (dc->condexec_mask && !thumb_insn_is_unconditional(dc, insn)) {
13549 uint32_t cond = dc->condexec_cond;
13551 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
13552 arm_skip_unless(dc, cond);
13556 if (is_16bit) {
13557 disas_thumb_insn(dc, insn);
13558 } else {
13559 disas_thumb2_insn(dc, insn);
13562 /* Advance the Thumb condexec condition. */
13563 if (dc->condexec_mask) {
13564 dc->condexec_cond = ((dc->condexec_cond & 0xe) |
13565 ((dc->condexec_mask >> 4) & 1));
13566 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
13567 if (dc->condexec_mask == 0) {
13568 dc->condexec_cond = 0;
13572 arm_post_translate_insn(dc);
13574 /* Thumb is a variable-length ISA. Stop translation when the next insn
13575 * will touch a new page. This ensures that prefetch aborts occur at
13576 * the right place.
13578 * We want to stop the TB if the next insn starts in a new page,
13579 * or if it spans between this page and the next. This means that
13580 * if we're looking at the last halfword in the page we need to
13581 * see if it's a 16-bit Thumb insn (which will fit in this TB)
13582 * or a 32-bit Thumb insn (which won't).
13583 * This is to avoid generating a silly TB with a single 16-bit insn
13584 * in it at the end of this page (which would execute correctly
13585 * but isn't very efficient).
13587 if (dc->base.is_jmp == DISAS_NEXT
13588 && (dc->pc - dc->page_start >= TARGET_PAGE_SIZE
13589 || (dc->pc - dc->page_start >= TARGET_PAGE_SIZE - 3
13590 && insn_crosses_page(env, dc)))) {
13591 dc->base.is_jmp = DISAS_TOO_MANY;
13595 static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
13597 DisasContext *dc = container_of(dcbase, DisasContext, base);
13599 if (tb_cflags(dc->base.tb) & CF_LAST_IO && dc->condjmp) {
13600 /* FIXME: This can theoretically happen with self-modifying code. */
13601 cpu_abort(cpu, "IO on conditional branch instruction");
13604 /* At this stage dc->condjmp will only be set when the skipped
13605 instruction was a conditional branch or trap, and the PC has
13606 already been written. */
13607 gen_set_condexec(dc);
13608 if (dc->base.is_jmp == DISAS_BX_EXCRET) {
13609 /* Exception return branches need some special case code at the
13610 * end of the TB, which is complex enough that it has to
13611 * handle the single-step vs not and the condition-failed
13612 * insn codepath itself.
13614 gen_bx_excret_final_code(dc);
13615 } else if (unlikely(is_singlestepping(dc))) {
13616 /* Unconditional and "condition passed" instruction codepath. */
13617 switch (dc->base.is_jmp) {
13618 case DISAS_SWI:
13619 gen_ss_advance(dc);
13620 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
13621 default_exception_el(dc));
13622 break;
13623 case DISAS_HVC:
13624 gen_ss_advance(dc);
13625 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
13626 break;
13627 case DISAS_SMC:
13628 gen_ss_advance(dc);
13629 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
13630 break;
13631 case DISAS_NEXT:
13632 case DISAS_TOO_MANY:
13633 case DISAS_UPDATE:
13634 gen_set_pc_im(dc, dc->pc);
13635 /* fall through */
13636 default:
13637 /* FIXME: Single stepping a WFI insn will not halt the CPU. */
13638 gen_singlestep_exception(dc);
13639 break;
13640 case DISAS_NORETURN:
13641 break;
13643 } else {
13644 /* While branches must always occur at the end of an IT block,
13645 there are a few other things that can cause us to terminate
13646 the TB in the middle of an IT block:
13647 - Exception generating instructions (bkpt, swi, undefined).
13648 - Page boundaries.
13649 - Hardware watchpoints.
13650 Hardware breakpoints have already been handled and skip this code.
13652 switch(dc->base.is_jmp) {
13653 case DISAS_NEXT:
13654 case DISAS_TOO_MANY:
13655 gen_goto_tb(dc, 1, dc->pc);
13656 break;
13657 case DISAS_JUMP:
13658 gen_goto_ptr();
13659 break;
13660 case DISAS_UPDATE:
13661 gen_set_pc_im(dc, dc->pc);
13662 /* fall through */
13663 default:
13664 /* indicate that the hash table must be used to find the next TB */
13665 tcg_gen_exit_tb(NULL, 0);
13666 break;
13667 case DISAS_NORETURN:
13668 /* nothing more to generate */
13669 break;
13670 case DISAS_WFI:
13672 TCGv_i32 tmp = tcg_const_i32((dc->thumb &&
13673 !(dc->insn & (1U << 31))) ? 2 : 4);
13675 gen_helper_wfi(cpu_env, tmp);
13676 tcg_temp_free_i32(tmp);
13677 /* The helper doesn't necessarily throw an exception, but we
13678 * must go back to the main loop to check for interrupts anyway.
13680 tcg_gen_exit_tb(NULL, 0);
13681 break;
13683 case DISAS_WFE:
13684 gen_helper_wfe(cpu_env);
13685 break;
13686 case DISAS_YIELD:
13687 gen_helper_yield(cpu_env);
13688 break;
13689 case DISAS_SWI:
13690 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
13691 default_exception_el(dc));
13692 break;
13693 case DISAS_HVC:
13694 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
13695 break;
13696 case DISAS_SMC:
13697 gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
13698 break;
13702 if (dc->condjmp) {
13703 /* "Condition failed" instruction codepath for the branch/trap insn */
13704 gen_set_label(dc->condlabel);
13705 gen_set_condexec(dc);
13706 if (unlikely(is_singlestepping(dc))) {
13707 gen_set_pc_im(dc, dc->pc);
13708 gen_singlestep_exception(dc);
13709 } else {
13710 gen_goto_tb(dc, 1, dc->pc);
13714 /* Functions above can change dc->pc, so re-align db->pc_next */
13715 dc->base.pc_next = dc->pc;
13718 static void arm_tr_disas_log(const DisasContextBase *dcbase, CPUState *cpu)
13720 DisasContext *dc = container_of(dcbase, DisasContext, base);
13722 qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
13723 log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
13726 static const TranslatorOps arm_translator_ops = {
13727 .init_disas_context = arm_tr_init_disas_context,
13728 .tb_start = arm_tr_tb_start,
13729 .insn_start = arm_tr_insn_start,
13730 .breakpoint_check = arm_tr_breakpoint_check,
13731 .translate_insn = arm_tr_translate_insn,
13732 .tb_stop = arm_tr_tb_stop,
13733 .disas_log = arm_tr_disas_log,
13736 static const TranslatorOps thumb_translator_ops = {
13737 .init_disas_context = arm_tr_init_disas_context,
13738 .tb_start = arm_tr_tb_start,
13739 .insn_start = arm_tr_insn_start,
13740 .breakpoint_check = arm_tr_breakpoint_check,
13741 .translate_insn = thumb_tr_translate_insn,
13742 .tb_stop = arm_tr_tb_stop,
13743 .disas_log = arm_tr_disas_log,
13746 /* generate intermediate code for basic block 'tb'. */
13747 void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb)
13749 DisasContext dc;
13750 const TranslatorOps *ops = &arm_translator_ops;
13752 if (FIELD_EX32(tb->flags, TBFLAG_A32, THUMB)) {
13753 ops = &thumb_translator_ops;
13755 #ifdef TARGET_AARCH64
13756 if (FIELD_EX32(tb->flags, TBFLAG_ANY, AARCH64_STATE)) {
13757 ops = &aarch64_translator_ops;
13759 #endif
13761 translator_loop(ops, &dc.base, cpu, tb);
13764 void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
13765 int flags)
13767 ARMCPU *cpu = ARM_CPU(cs);
13768 CPUARMState *env = &cpu->env;
13769 int i;
13771 if (is_a64(env)) {
13772 aarch64_cpu_dump_state(cs, f, cpu_fprintf, flags);
13773 return;
13776 for(i=0;i<16;i++) {
13777 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
13778 if ((i % 4) == 3)
13779 cpu_fprintf(f, "\n");
13780 else
13781 cpu_fprintf(f, " ");
13784 if (arm_feature(env, ARM_FEATURE_M)) {
13785 uint32_t xpsr = xpsr_read(env);
13786 const char *mode;
13787 const char *ns_status = "";
13789 if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
13790 ns_status = env->v7m.secure ? "S " : "NS ";
13793 if (xpsr & XPSR_EXCP) {
13794 mode = "handler";
13795 } else {
13796 if (env->v7m.control[env->v7m.secure] & R_V7M_CONTROL_NPRIV_MASK) {
13797 mode = "unpriv-thread";
13798 } else {
13799 mode = "priv-thread";
13803 cpu_fprintf(f, "XPSR=%08x %c%c%c%c %c %s%s\n",
13804 xpsr,
13805 xpsr & XPSR_N ? 'N' : '-',
13806 xpsr & XPSR_Z ? 'Z' : '-',
13807 xpsr & XPSR_C ? 'C' : '-',
13808 xpsr & XPSR_V ? 'V' : '-',
13809 xpsr & XPSR_T ? 'T' : 'A',
13810 ns_status,
13811 mode);
13812 } else {
13813 uint32_t psr = cpsr_read(env);
13814 const char *ns_status = "";
13816 if (arm_feature(env, ARM_FEATURE_EL3) &&
13817 (psr & CPSR_M) != ARM_CPU_MODE_MON) {
13818 ns_status = env->cp15.scr_el3 & SCR_NS ? "NS " : "S ";
13821 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%s%d\n",
13822 psr,
13823 psr & CPSR_N ? 'N' : '-',
13824 psr & CPSR_Z ? 'Z' : '-',
13825 psr & CPSR_C ? 'C' : '-',
13826 psr & CPSR_V ? 'V' : '-',
13827 psr & CPSR_T ? 'T' : 'A',
13828 ns_status,
13829 aarch32_mode_name(psr), (psr & 0x10) ? 32 : 26);
13832 if (flags & CPU_DUMP_FPU) {
13833 int numvfpregs = 0;
13834 if (arm_feature(env, ARM_FEATURE_VFP)) {
13835 numvfpregs += 16;
13837 if (arm_feature(env, ARM_FEATURE_VFP3)) {
13838 numvfpregs += 16;
13840 for (i = 0; i < numvfpregs; i++) {
13841 uint64_t v = *aa32_vfp_dreg(env, i);
13842 cpu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
13843 i * 2, (uint32_t)v,
13844 i * 2 + 1, (uint32_t)(v >> 32),
13845 i, v);
13847 cpu_fprintf(f, "FPSCR: %08x\n", vfp_get_fpscr(env));
13851 void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
13852 target_ulong *data)
13854 if (is_a64(env)) {
13855 env->pc = data[0];
13856 env->condexec_bits = 0;
13857 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;
13858 } else {
13859 env->regs[15] = data[0];
13860 env->condexec_bits = data[1];
13861 env->exception.syndrome = data[2] << ARM_INSN_START_WORD2_SHIFT;