target-arm: Implement adc_cc inline
[qemu/pbrook.git] / target-arm / translate.c
blob493448a63741403a70235fd61b95a89c3daa2336
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 <stdarg.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <inttypes.h>
27 #include "cpu.h"
28 #include "disas/disas.h"
29 #include "tcg-op.h"
30 #include "qemu/log.h"
32 #include "helper.h"
33 #define GEN_HELPER 1
34 #include "helper.h"
36 #define ENABLE_ARCH_4T arm_feature(env, ARM_FEATURE_V4T)
37 #define ENABLE_ARCH_5 arm_feature(env, ARM_FEATURE_V5)
38 /* currently all emulated v5 cores are also v5TE, so don't bother */
39 #define ENABLE_ARCH_5TE arm_feature(env, ARM_FEATURE_V5)
40 #define ENABLE_ARCH_5J 0
41 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
42 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
43 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
44 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
46 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
48 /* internal defines */
49 typedef struct DisasContext {
50 target_ulong pc;
51 int is_jmp;
52 /* Nonzero if this instruction has been conditionally skipped. */
53 int condjmp;
54 /* The label that will be jumped to when the instruction is skipped. */
55 int condlabel;
56 /* Thumb-2 conditional execution bits. */
57 int condexec_mask;
58 int condexec_cond;
59 struct TranslationBlock *tb;
60 int singlestep_enabled;
61 int thumb;
62 int bswap_code;
63 #if !defined(CONFIG_USER_ONLY)
64 int user;
65 #endif
66 int vfp_enabled;
67 int vec_len;
68 int vec_stride;
69 } DisasContext;
71 static uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE];
73 #if defined(CONFIG_USER_ONLY)
74 #define IS_USER(s) 1
75 #else
76 #define IS_USER(s) (s->user)
77 #endif
79 /* These instructions trap after executing, so defer them until after the
80 conditional execution state has been updated. */
81 #define DISAS_WFI 4
82 #define DISAS_SWI 5
84 static TCGv_ptr cpu_env;
85 /* We reuse the same 64-bit temporaries for efficiency. */
86 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
87 static TCGv_i32 cpu_R[16];
88 static TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
89 static TCGv_i32 cpu_exclusive_addr;
90 static TCGv_i32 cpu_exclusive_val;
91 static TCGv_i32 cpu_exclusive_high;
92 #ifdef CONFIG_USER_ONLY
93 static TCGv_i32 cpu_exclusive_test;
94 static TCGv_i32 cpu_exclusive_info;
95 #endif
97 /* FIXME: These should be removed. */
98 static TCGv cpu_F0s, cpu_F1s;
99 static TCGv_i64 cpu_F0d, cpu_F1d;
101 #include "exec/gen-icount.h"
103 static const char *regnames[] =
104 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
105 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
107 /* initialize TCG globals. */
108 void arm_translate_init(void)
110 int i;
112 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
114 for (i = 0; i < 16; i++) {
115 cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
116 offsetof(CPUARMState, regs[i]),
117 regnames[i]);
119 cpu_CF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, CF), "CF");
120 cpu_NF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, NF), "NF");
121 cpu_VF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, VF), "VF");
122 cpu_ZF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, ZF), "ZF");
124 cpu_exclusive_addr = tcg_global_mem_new_i32(TCG_AREG0,
125 offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
126 cpu_exclusive_val = tcg_global_mem_new_i32(TCG_AREG0,
127 offsetof(CPUARMState, exclusive_val), "exclusive_val");
128 cpu_exclusive_high = tcg_global_mem_new_i32(TCG_AREG0,
129 offsetof(CPUARMState, exclusive_high), "exclusive_high");
130 #ifdef CONFIG_USER_ONLY
131 cpu_exclusive_test = tcg_global_mem_new_i32(TCG_AREG0,
132 offsetof(CPUARMState, exclusive_test), "exclusive_test");
133 cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0,
134 offsetof(CPUARMState, exclusive_info), "exclusive_info");
135 #endif
137 #define GEN_HELPER 2
138 #include "helper.h"
141 static inline TCGv load_cpu_offset(int offset)
143 TCGv tmp = tcg_temp_new_i32();
144 tcg_gen_ld_i32(tmp, cpu_env, offset);
145 return tmp;
148 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
150 static inline void store_cpu_offset(TCGv var, int offset)
152 tcg_gen_st_i32(var, cpu_env, offset);
153 tcg_temp_free_i32(var);
156 #define store_cpu_field(var, name) \
157 store_cpu_offset(var, offsetof(CPUARMState, name))
159 /* Set a variable to the value of a CPU register. */
160 static void load_reg_var(DisasContext *s, TCGv var, int reg)
162 if (reg == 15) {
163 uint32_t addr;
164 /* normally, since we updated PC, we need only to add one insn */
165 if (s->thumb)
166 addr = (long)s->pc + 2;
167 else
168 addr = (long)s->pc + 4;
169 tcg_gen_movi_i32(var, addr);
170 } else {
171 tcg_gen_mov_i32(var, cpu_R[reg]);
175 /* Create a new temporary and set it to the value of a CPU register. */
176 static inline TCGv load_reg(DisasContext *s, int reg)
178 TCGv tmp = tcg_temp_new_i32();
179 load_reg_var(s, tmp, reg);
180 return tmp;
183 /* Set a CPU register. The source must be a temporary and will be
184 marked as dead. */
185 static void store_reg(DisasContext *s, int reg, TCGv var)
187 if (reg == 15) {
188 tcg_gen_andi_i32(var, var, ~1);
189 s->is_jmp = DISAS_JUMP;
191 tcg_gen_mov_i32(cpu_R[reg], var);
192 tcg_temp_free_i32(var);
195 /* Value extensions. */
196 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
197 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
198 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
199 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
201 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
202 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
205 static inline void gen_set_cpsr(TCGv var, uint32_t mask)
207 TCGv tmp_mask = tcg_const_i32(mask);
208 gen_helper_cpsr_write(cpu_env, var, tmp_mask);
209 tcg_temp_free_i32(tmp_mask);
211 /* Set NZCV flags from the high 4 bits of var. */
212 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
214 static void gen_exception(int excp)
216 TCGv tmp = tcg_temp_new_i32();
217 tcg_gen_movi_i32(tmp, excp);
218 gen_helper_exception(cpu_env, tmp);
219 tcg_temp_free_i32(tmp);
222 static void gen_smul_dual(TCGv a, TCGv b)
224 TCGv tmp1 = tcg_temp_new_i32();
225 TCGv tmp2 = tcg_temp_new_i32();
226 tcg_gen_ext16s_i32(tmp1, a);
227 tcg_gen_ext16s_i32(tmp2, b);
228 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
229 tcg_temp_free_i32(tmp2);
230 tcg_gen_sari_i32(a, a, 16);
231 tcg_gen_sari_i32(b, b, 16);
232 tcg_gen_mul_i32(b, b, a);
233 tcg_gen_mov_i32(a, tmp1);
234 tcg_temp_free_i32(tmp1);
237 /* Byteswap each halfword. */
238 static void gen_rev16(TCGv var)
240 TCGv tmp = tcg_temp_new_i32();
241 tcg_gen_shri_i32(tmp, var, 8);
242 tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
243 tcg_gen_shli_i32(var, var, 8);
244 tcg_gen_andi_i32(var, var, 0xff00ff00);
245 tcg_gen_or_i32(var, var, tmp);
246 tcg_temp_free_i32(tmp);
249 /* Byteswap low halfword and sign extend. */
250 static void gen_revsh(TCGv var)
252 tcg_gen_ext16u_i32(var, var);
253 tcg_gen_bswap16_i32(var, var);
254 tcg_gen_ext16s_i32(var, var);
257 /* Unsigned bitfield extract. */
258 static void gen_ubfx(TCGv var, int shift, uint32_t mask)
260 if (shift)
261 tcg_gen_shri_i32(var, var, shift);
262 tcg_gen_andi_i32(var, var, mask);
265 /* Signed bitfield extract. */
266 static void gen_sbfx(TCGv var, int shift, int width)
268 uint32_t signbit;
270 if (shift)
271 tcg_gen_sari_i32(var, var, shift);
272 if (shift + width < 32) {
273 signbit = 1u << (width - 1);
274 tcg_gen_andi_i32(var, var, (1u << width) - 1);
275 tcg_gen_xori_i32(var, var, signbit);
276 tcg_gen_subi_i32(var, var, signbit);
280 /* Return (b << 32) + a. Mark inputs as dead */
281 static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv b)
283 TCGv_i64 tmp64 = tcg_temp_new_i64();
285 tcg_gen_extu_i32_i64(tmp64, b);
286 tcg_temp_free_i32(b);
287 tcg_gen_shli_i64(tmp64, tmp64, 32);
288 tcg_gen_add_i64(a, tmp64, a);
290 tcg_temp_free_i64(tmp64);
291 return a;
294 /* Return (b << 32) - a. Mark inputs as dead. */
295 static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv b)
297 TCGv_i64 tmp64 = tcg_temp_new_i64();
299 tcg_gen_extu_i32_i64(tmp64, b);
300 tcg_temp_free_i32(b);
301 tcg_gen_shli_i64(tmp64, tmp64, 32);
302 tcg_gen_sub_i64(a, tmp64, a);
304 tcg_temp_free_i64(tmp64);
305 return a;
308 /* 32x32->64 multiply. Marks inputs as dead. */
309 static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b)
311 TCGv lo = tcg_temp_new_i32();
312 TCGv hi = tcg_temp_new_i32();
313 TCGv_i64 ret;
315 tcg_gen_mulu2_i32(lo, hi, a, b);
316 tcg_temp_free_i32(a);
317 tcg_temp_free_i32(b);
319 ret = tcg_temp_new_i64();
320 tcg_gen_concat_i32_i64(ret, lo, hi);
321 tcg_temp_free(lo);
322 tcg_temp_free(hi);
324 return ret;
327 static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
329 TCGv lo = tcg_temp_new_i32();
330 TCGv hi = tcg_temp_new_i32();
331 TCGv_i64 ret;
333 tcg_gen_muls2_i32(lo, hi, a, b);
334 tcg_temp_free_i32(a);
335 tcg_temp_free_i32(b);
337 ret = tcg_temp_new_i64();
338 tcg_gen_concat_i32_i64(ret, lo, hi);
339 tcg_temp_free(lo);
340 tcg_temp_free(hi);
342 return ret;
345 /* Swap low and high halfwords. */
346 static void gen_swap_half(TCGv var)
348 TCGv tmp = tcg_temp_new_i32();
349 tcg_gen_shri_i32(tmp, var, 16);
350 tcg_gen_shli_i32(var, var, 16);
351 tcg_gen_or_i32(var, var, tmp);
352 tcg_temp_free_i32(tmp);
355 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
356 tmp = (t0 ^ t1) & 0x8000;
357 t0 &= ~0x8000;
358 t1 &= ~0x8000;
359 t0 = (t0 + t1) ^ tmp;
362 static void gen_add16(TCGv t0, TCGv t1)
364 TCGv tmp = tcg_temp_new_i32();
365 tcg_gen_xor_i32(tmp, t0, t1);
366 tcg_gen_andi_i32(tmp, tmp, 0x8000);
367 tcg_gen_andi_i32(t0, t0, ~0x8000);
368 tcg_gen_andi_i32(t1, t1, ~0x8000);
369 tcg_gen_add_i32(t0, t0, t1);
370 tcg_gen_xor_i32(t0, t0, tmp);
371 tcg_temp_free_i32(tmp);
372 tcg_temp_free_i32(t1);
375 /* Set CF to the top bit of var. */
376 static void gen_set_CF_bit31(TCGv var)
378 tcg_gen_shri_i32(cpu_CF, var, 31);
381 /* Set N and Z flags from var. */
382 static inline void gen_logic_CC(TCGv var)
384 tcg_gen_mov_i32(cpu_NF, var);
385 tcg_gen_mov_i32(cpu_ZF, var);
388 /* T0 += T1 + CF. */
389 static void gen_adc(TCGv t0, TCGv t1)
391 tcg_gen_add_i32(t0, t0, t1);
392 tcg_gen_add_i32(t0, t0, cpu_CF);
395 /* dest = T0 + T1 + CF. */
396 static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
398 tcg_gen_add_i32(dest, t0, t1);
399 tcg_gen_add_i32(dest, dest, cpu_CF);
402 /* dest = T0 - T1 + CF - 1. */
403 static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
405 tcg_gen_sub_i32(dest, t0, t1);
406 tcg_gen_add_i32(dest, dest, cpu_CF);
407 tcg_gen_subi_i32(dest, dest, 1);
410 /* dest = T0 + T1. Compute C, N, V and Z flags */
411 static void gen_add_CC(TCGv dest, TCGv t0, TCGv t1)
413 TCGv tmp = tcg_temp_new_i32();
414 tcg_gen_movi_i32(tmp, 0);
415 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, t1, tmp);
416 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
417 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
418 tcg_gen_xor_i32(tmp, t0, t1);
419 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
420 tcg_temp_free_i32(tmp);
421 tcg_gen_mov_i32(dest, cpu_NF);
424 /* dest = T0 + T1 + CF. Compute C, N, V and Z flags */
425 static void gen_adc_CC(TCGv dest, TCGv t0, TCGv t1)
427 TCGv tmp = tcg_temp_new_i32();
428 if (TCG_TARGET_HAS_add2_i32) {
429 tcg_gen_movi_i32(tmp, 0);
430 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp);
431 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, cpu_CF, t1, tmp);
432 } else {
433 TCGv_i64 q0 = tcg_temp_new_i64();
434 TCGv_i64 q1 = tcg_temp_new_i64();
435 tcg_gen_extu_i32_i64(q0, t0);
436 tcg_gen_extu_i32_i64(q1, t1);
437 tcg_gen_add_i64(q0, q0, q1);
438 tcg_gen_extu_i32_i64(q1, cpu_CF);
439 tcg_gen_add_i64(q0, q0, q1);
440 tcg_gen_extr_i64_i32(cpu_NF, cpu_CF, q0);
441 tcg_temp_free_i64(q0);
442 tcg_temp_free_i64(q1);
444 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
445 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
446 tcg_gen_xor_i32(tmp, t0, t1);
447 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
448 tcg_temp_free_i32(tmp);
449 tcg_gen_mov_i32(dest, cpu_NF);
452 /* dest = T0 - T1. Compute C, N, V and Z flags */
453 static void gen_sub_CC(TCGv dest, TCGv t0, TCGv t1)
455 TCGv tmp;
456 tcg_gen_sub_i32(cpu_NF, t0, t1);
457 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
458 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0, t1);
459 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
460 tmp = tcg_temp_new_i32();
461 tcg_gen_xor_i32(tmp, t0, t1);
462 tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
463 tcg_temp_free_i32(tmp);
464 tcg_gen_mov_i32(dest, cpu_NF);
467 #define GEN_SHIFT(name) \
468 static void gen_##name(TCGv dest, TCGv t0, TCGv t1) \
470 TCGv tmp1, tmp2, tmp3; \
471 tmp1 = tcg_temp_new_i32(); \
472 tcg_gen_andi_i32(tmp1, t1, 0xff); \
473 tmp2 = tcg_const_i32(0); \
474 tmp3 = tcg_const_i32(0x1f); \
475 tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
476 tcg_temp_free_i32(tmp3); \
477 tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
478 tcg_gen_##name##_i32(dest, tmp2, tmp1); \
479 tcg_temp_free_i32(tmp2); \
480 tcg_temp_free_i32(tmp1); \
482 GEN_SHIFT(shl)
483 GEN_SHIFT(shr)
484 #undef GEN_SHIFT
486 static void gen_sar(TCGv dest, TCGv t0, TCGv t1)
488 TCGv tmp1, tmp2;
489 tmp1 = tcg_temp_new_i32();
490 tcg_gen_andi_i32(tmp1, t1, 0xff);
491 tmp2 = tcg_const_i32(0x1f);
492 tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1);
493 tcg_temp_free_i32(tmp2);
494 tcg_gen_sar_i32(dest, t0, tmp1);
495 tcg_temp_free_i32(tmp1);
498 static void tcg_gen_abs_i32(TCGv dest, TCGv src)
500 TCGv c0 = tcg_const_i32(0);
501 TCGv tmp = tcg_temp_new_i32();
502 tcg_gen_neg_i32(tmp, src);
503 tcg_gen_movcond_i32(TCG_COND_GT, dest, src, c0, src, tmp);
504 tcg_temp_free_i32(c0);
505 tcg_temp_free_i32(tmp);
508 static void shifter_out_im(TCGv var, int shift)
510 if (shift == 0) {
511 tcg_gen_andi_i32(cpu_CF, var, 1);
512 } else {
513 tcg_gen_shri_i32(cpu_CF, var, shift);
514 if (shift != 31) {
515 tcg_gen_andi_i32(cpu_CF, cpu_CF, 1);
520 /* Shift by immediate. Includes special handling for shift == 0. */
521 static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
523 switch (shiftop) {
524 case 0: /* LSL */
525 if (shift != 0) {
526 if (flags)
527 shifter_out_im(var, 32 - shift);
528 tcg_gen_shli_i32(var, var, shift);
530 break;
531 case 1: /* LSR */
532 if (shift == 0) {
533 if (flags) {
534 tcg_gen_shri_i32(cpu_CF, var, 31);
536 tcg_gen_movi_i32(var, 0);
537 } else {
538 if (flags)
539 shifter_out_im(var, shift - 1);
540 tcg_gen_shri_i32(var, var, shift);
542 break;
543 case 2: /* ASR */
544 if (shift == 0)
545 shift = 32;
546 if (flags)
547 shifter_out_im(var, shift - 1);
548 if (shift == 32)
549 shift = 31;
550 tcg_gen_sari_i32(var, var, shift);
551 break;
552 case 3: /* ROR/RRX */
553 if (shift != 0) {
554 if (flags)
555 shifter_out_im(var, shift - 1);
556 tcg_gen_rotri_i32(var, var, shift); break;
557 } else {
558 TCGv tmp = tcg_temp_new_i32();
559 tcg_gen_shli_i32(tmp, cpu_CF, 31);
560 if (flags)
561 shifter_out_im(var, 0);
562 tcg_gen_shri_i32(var, var, 1);
563 tcg_gen_or_i32(var, var, tmp);
564 tcg_temp_free_i32(tmp);
569 static inline void gen_arm_shift_reg(TCGv var, int shiftop,
570 TCGv shift, int flags)
572 if (flags) {
573 switch (shiftop) {
574 case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break;
575 case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break;
576 case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break;
577 case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break;
579 } else {
580 switch (shiftop) {
581 case 0:
582 gen_shl(var, var, shift);
583 break;
584 case 1:
585 gen_shr(var, var, shift);
586 break;
587 case 2:
588 gen_sar(var, var, shift);
589 break;
590 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
591 tcg_gen_rotr_i32(var, var, shift); break;
594 tcg_temp_free_i32(shift);
597 #define PAS_OP(pfx) \
598 switch (op2) { \
599 case 0: gen_pas_helper(glue(pfx,add16)); break; \
600 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
601 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
602 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
603 case 4: gen_pas_helper(glue(pfx,add8)); break; \
604 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
606 static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
608 TCGv_ptr tmp;
610 switch (op1) {
611 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
612 case 1:
613 tmp = tcg_temp_new_ptr();
614 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
615 PAS_OP(s)
616 tcg_temp_free_ptr(tmp);
617 break;
618 case 5:
619 tmp = tcg_temp_new_ptr();
620 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
621 PAS_OP(u)
622 tcg_temp_free_ptr(tmp);
623 break;
624 #undef gen_pas_helper
625 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
626 case 2:
627 PAS_OP(q);
628 break;
629 case 3:
630 PAS_OP(sh);
631 break;
632 case 6:
633 PAS_OP(uq);
634 break;
635 case 7:
636 PAS_OP(uh);
637 break;
638 #undef gen_pas_helper
641 #undef PAS_OP
643 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
644 #define PAS_OP(pfx) \
645 switch (op1) { \
646 case 0: gen_pas_helper(glue(pfx,add8)); break; \
647 case 1: gen_pas_helper(glue(pfx,add16)); break; \
648 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
649 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
650 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
651 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
653 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
655 TCGv_ptr tmp;
657 switch (op2) {
658 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
659 case 0:
660 tmp = tcg_temp_new_ptr();
661 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
662 PAS_OP(s)
663 tcg_temp_free_ptr(tmp);
664 break;
665 case 4:
666 tmp = tcg_temp_new_ptr();
667 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
668 PAS_OP(u)
669 tcg_temp_free_ptr(tmp);
670 break;
671 #undef gen_pas_helper
672 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
673 case 1:
674 PAS_OP(q);
675 break;
676 case 2:
677 PAS_OP(sh);
678 break;
679 case 5:
680 PAS_OP(uq);
681 break;
682 case 6:
683 PAS_OP(uh);
684 break;
685 #undef gen_pas_helper
688 #undef PAS_OP
690 static void gen_test_cc(int cc, int label)
692 TCGv tmp;
693 int inv;
695 switch (cc) {
696 case 0: /* eq: Z */
697 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
698 break;
699 case 1: /* ne: !Z */
700 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_ZF, 0, label);
701 break;
702 case 2: /* cs: C */
703 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_CF, 0, label);
704 break;
705 case 3: /* cc: !C */
706 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, label);
707 break;
708 case 4: /* mi: N */
709 tcg_gen_brcondi_i32(TCG_COND_LT, cpu_NF, 0, label);
710 break;
711 case 5: /* pl: !N */
712 tcg_gen_brcondi_i32(TCG_COND_GE, cpu_NF, 0, label);
713 break;
714 case 6: /* vs: V */
715 tcg_gen_brcondi_i32(TCG_COND_LT, cpu_VF, 0, label);
716 break;
717 case 7: /* vc: !V */
718 tcg_gen_brcondi_i32(TCG_COND_GE, cpu_VF, 0, label);
719 break;
720 case 8: /* hi: C && !Z */
721 inv = gen_new_label();
722 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, inv);
723 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_ZF, 0, label);
724 gen_set_label(inv);
725 break;
726 case 9: /* ls: !C || Z */
727 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, label);
728 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
729 break;
730 case 10: /* ge: N == V -> N ^ V == 0 */
731 tmp = tcg_temp_new_i32();
732 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
733 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
734 tcg_temp_free_i32(tmp);
735 break;
736 case 11: /* lt: N != V -> N ^ V != 0 */
737 tmp = tcg_temp_new_i32();
738 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
739 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
740 tcg_temp_free_i32(tmp);
741 break;
742 case 12: /* gt: !Z && N == V */
743 inv = gen_new_label();
744 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, inv);
745 tmp = tcg_temp_new_i32();
746 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
747 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
748 tcg_temp_free_i32(tmp);
749 gen_set_label(inv);
750 break;
751 case 13: /* le: Z || N != V */
752 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
753 tmp = tcg_temp_new_i32();
754 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
755 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
756 tcg_temp_free_i32(tmp);
757 break;
758 default:
759 fprintf(stderr, "Bad condition code 0x%x\n", cc);
760 abort();
764 static const uint8_t table_logic_cc[16] = {
765 1, /* and */
766 1, /* xor */
767 0, /* sub */
768 0, /* rsb */
769 0, /* add */
770 0, /* adc */
771 0, /* sbc */
772 0, /* rsc */
773 1, /* andl */
774 1, /* xorl */
775 0, /* cmp */
776 0, /* cmn */
777 1, /* orr */
778 1, /* mov */
779 1, /* bic */
780 1, /* mvn */
783 /* Set PC and Thumb state from an immediate address. */
784 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
786 TCGv tmp;
788 s->is_jmp = DISAS_UPDATE;
789 if (s->thumb != (addr & 1)) {
790 tmp = tcg_temp_new_i32();
791 tcg_gen_movi_i32(tmp, addr & 1);
792 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, thumb));
793 tcg_temp_free_i32(tmp);
795 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
798 /* Set PC and Thumb state from var. var is marked as dead. */
799 static inline void gen_bx(DisasContext *s, TCGv var)
801 s->is_jmp = DISAS_UPDATE;
802 tcg_gen_andi_i32(cpu_R[15], var, ~1);
803 tcg_gen_andi_i32(var, var, 1);
804 store_cpu_field(var, thumb);
807 /* Variant of store_reg which uses branch&exchange logic when storing
808 to r15 in ARM architecture v7 and above. The source must be a temporary
809 and will be marked as dead. */
810 static inline void store_reg_bx(CPUARMState *env, DisasContext *s,
811 int reg, TCGv var)
813 if (reg == 15 && ENABLE_ARCH_7) {
814 gen_bx(s, var);
815 } else {
816 store_reg(s, reg, var);
820 /* Variant of store_reg which uses branch&exchange logic when storing
821 * to r15 in ARM architecture v5T and above. This is used for storing
822 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
823 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
824 static inline void store_reg_from_load(CPUARMState *env, DisasContext *s,
825 int reg, TCGv var)
827 if (reg == 15 && ENABLE_ARCH_5) {
828 gen_bx(s, var);
829 } else {
830 store_reg(s, reg, var);
834 static inline TCGv gen_ld8s(TCGv addr, int index)
836 TCGv tmp = tcg_temp_new_i32();
837 tcg_gen_qemu_ld8s(tmp, addr, index);
838 return tmp;
840 static inline TCGv gen_ld8u(TCGv addr, int index)
842 TCGv tmp = tcg_temp_new_i32();
843 tcg_gen_qemu_ld8u(tmp, addr, index);
844 return tmp;
846 static inline TCGv gen_ld16s(TCGv addr, int index)
848 TCGv tmp = tcg_temp_new_i32();
849 tcg_gen_qemu_ld16s(tmp, addr, index);
850 return tmp;
852 static inline TCGv gen_ld16u(TCGv addr, int index)
854 TCGv tmp = tcg_temp_new_i32();
855 tcg_gen_qemu_ld16u(tmp, addr, index);
856 return tmp;
858 static inline TCGv gen_ld32(TCGv addr, int index)
860 TCGv tmp = tcg_temp_new_i32();
861 tcg_gen_qemu_ld32u(tmp, addr, index);
862 return tmp;
864 static inline TCGv_i64 gen_ld64(TCGv addr, int index)
866 TCGv_i64 tmp = tcg_temp_new_i64();
867 tcg_gen_qemu_ld64(tmp, addr, index);
868 return tmp;
870 static inline void gen_st8(TCGv val, TCGv addr, int index)
872 tcg_gen_qemu_st8(val, addr, index);
873 tcg_temp_free_i32(val);
875 static inline void gen_st16(TCGv val, TCGv addr, int index)
877 tcg_gen_qemu_st16(val, addr, index);
878 tcg_temp_free_i32(val);
880 static inline void gen_st32(TCGv val, TCGv addr, int index)
882 tcg_gen_qemu_st32(val, addr, index);
883 tcg_temp_free_i32(val);
885 static inline void gen_st64(TCGv_i64 val, TCGv addr, int index)
887 tcg_gen_qemu_st64(val, addr, index);
888 tcg_temp_free_i64(val);
891 static inline void gen_set_pc_im(uint32_t val)
893 tcg_gen_movi_i32(cpu_R[15], val);
896 /* Force a TB lookup after an instruction that changes the CPU state. */
897 static inline void gen_lookup_tb(DisasContext *s)
899 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
900 s->is_jmp = DISAS_UPDATE;
903 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
904 TCGv var)
906 int val, rm, shift, shiftop;
907 TCGv offset;
909 if (!(insn & (1 << 25))) {
910 /* immediate */
911 val = insn & 0xfff;
912 if (!(insn & (1 << 23)))
913 val = -val;
914 if (val != 0)
915 tcg_gen_addi_i32(var, var, val);
916 } else {
917 /* shift/register */
918 rm = (insn) & 0xf;
919 shift = (insn >> 7) & 0x1f;
920 shiftop = (insn >> 5) & 3;
921 offset = load_reg(s, rm);
922 gen_arm_shift_im(offset, shiftop, shift, 0);
923 if (!(insn & (1 << 23)))
924 tcg_gen_sub_i32(var, var, offset);
925 else
926 tcg_gen_add_i32(var, var, offset);
927 tcg_temp_free_i32(offset);
931 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
932 int extra, TCGv var)
934 int val, rm;
935 TCGv offset;
937 if (insn & (1 << 22)) {
938 /* immediate */
939 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
940 if (!(insn & (1 << 23)))
941 val = -val;
942 val += extra;
943 if (val != 0)
944 tcg_gen_addi_i32(var, var, val);
945 } else {
946 /* register */
947 if (extra)
948 tcg_gen_addi_i32(var, var, extra);
949 rm = (insn) & 0xf;
950 offset = load_reg(s, rm);
951 if (!(insn & (1 << 23)))
952 tcg_gen_sub_i32(var, var, offset);
953 else
954 tcg_gen_add_i32(var, var, offset);
955 tcg_temp_free_i32(offset);
959 static TCGv_ptr get_fpstatus_ptr(int neon)
961 TCGv_ptr statusptr = tcg_temp_new_ptr();
962 int offset;
963 if (neon) {
964 offset = offsetof(CPUARMState, vfp.standard_fp_status);
965 } else {
966 offset = offsetof(CPUARMState, vfp.fp_status);
968 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
969 return statusptr;
972 #define VFP_OP2(name) \
973 static inline void gen_vfp_##name(int dp) \
975 TCGv_ptr fpst = get_fpstatus_ptr(0); \
976 if (dp) { \
977 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, fpst); \
978 } else { \
979 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, fpst); \
981 tcg_temp_free_ptr(fpst); \
984 VFP_OP2(add)
985 VFP_OP2(sub)
986 VFP_OP2(mul)
987 VFP_OP2(div)
989 #undef VFP_OP2
991 static inline void gen_vfp_F1_mul(int dp)
993 /* Like gen_vfp_mul() but put result in F1 */
994 TCGv_ptr fpst = get_fpstatus_ptr(0);
995 if (dp) {
996 gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, fpst);
997 } else {
998 gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, fpst);
1000 tcg_temp_free_ptr(fpst);
1003 static inline void gen_vfp_F1_neg(int dp)
1005 /* Like gen_vfp_neg() but put result in F1 */
1006 if (dp) {
1007 gen_helper_vfp_negd(cpu_F1d, cpu_F0d);
1008 } else {
1009 gen_helper_vfp_negs(cpu_F1s, cpu_F0s);
1013 static inline void gen_vfp_abs(int dp)
1015 if (dp)
1016 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1017 else
1018 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1021 static inline void gen_vfp_neg(int dp)
1023 if (dp)
1024 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1025 else
1026 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1029 static inline void gen_vfp_sqrt(int dp)
1031 if (dp)
1032 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1033 else
1034 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1037 static inline void gen_vfp_cmp(int dp)
1039 if (dp)
1040 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1041 else
1042 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1045 static inline void gen_vfp_cmpe(int dp)
1047 if (dp)
1048 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1049 else
1050 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1053 static inline void gen_vfp_F1_ld0(int dp)
1055 if (dp)
1056 tcg_gen_movi_i64(cpu_F1d, 0);
1057 else
1058 tcg_gen_movi_i32(cpu_F1s, 0);
1061 #define VFP_GEN_ITOF(name) \
1062 static inline void gen_vfp_##name(int dp, int neon) \
1064 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1065 if (dp) { \
1066 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
1067 } else { \
1068 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1070 tcg_temp_free_ptr(statusptr); \
1073 VFP_GEN_ITOF(uito)
1074 VFP_GEN_ITOF(sito)
1075 #undef VFP_GEN_ITOF
1077 #define VFP_GEN_FTOI(name) \
1078 static inline void gen_vfp_##name(int dp, int neon) \
1080 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1081 if (dp) { \
1082 gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
1083 } else { \
1084 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1086 tcg_temp_free_ptr(statusptr); \
1089 VFP_GEN_FTOI(toui)
1090 VFP_GEN_FTOI(touiz)
1091 VFP_GEN_FTOI(tosi)
1092 VFP_GEN_FTOI(tosiz)
1093 #undef VFP_GEN_FTOI
1095 #define VFP_GEN_FIX(name) \
1096 static inline void gen_vfp_##name(int dp, int shift, int neon) \
1098 TCGv tmp_shift = tcg_const_i32(shift); \
1099 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1100 if (dp) { \
1101 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, statusptr); \
1102 } else { \
1103 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, statusptr); \
1105 tcg_temp_free_i32(tmp_shift); \
1106 tcg_temp_free_ptr(statusptr); \
1108 VFP_GEN_FIX(tosh)
1109 VFP_GEN_FIX(tosl)
1110 VFP_GEN_FIX(touh)
1111 VFP_GEN_FIX(toul)
1112 VFP_GEN_FIX(shto)
1113 VFP_GEN_FIX(slto)
1114 VFP_GEN_FIX(uhto)
1115 VFP_GEN_FIX(ulto)
1116 #undef VFP_GEN_FIX
1118 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv addr)
1120 if (dp)
1121 tcg_gen_qemu_ld64(cpu_F0d, addr, IS_USER(s));
1122 else
1123 tcg_gen_qemu_ld32u(cpu_F0s, addr, IS_USER(s));
1126 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv addr)
1128 if (dp)
1129 tcg_gen_qemu_st64(cpu_F0d, addr, IS_USER(s));
1130 else
1131 tcg_gen_qemu_st32(cpu_F0s, addr, IS_USER(s));
1134 static inline long
1135 vfp_reg_offset (int dp, int reg)
1137 if (dp)
1138 return offsetof(CPUARMState, vfp.regs[reg]);
1139 else if (reg & 1) {
1140 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1141 + offsetof(CPU_DoubleU, l.upper);
1142 } else {
1143 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1144 + offsetof(CPU_DoubleU, l.lower);
1148 /* Return the offset of a 32-bit piece of a NEON register.
1149 zero is the least significant end of the register. */
1150 static inline long
1151 neon_reg_offset (int reg, int n)
1153 int sreg;
1154 sreg = reg * 2 + n;
1155 return vfp_reg_offset(0, sreg);
1158 static TCGv neon_load_reg(int reg, int pass)
1160 TCGv tmp = tcg_temp_new_i32();
1161 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1162 return tmp;
1165 static void neon_store_reg(int reg, int pass, TCGv var)
1167 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1168 tcg_temp_free_i32(var);
1171 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1173 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1176 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1178 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1181 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1182 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1183 #define tcg_gen_st_f32 tcg_gen_st_i32
1184 #define tcg_gen_st_f64 tcg_gen_st_i64
1186 static inline void gen_mov_F0_vreg(int dp, int reg)
1188 if (dp)
1189 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1190 else
1191 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1194 static inline void gen_mov_F1_vreg(int dp, int reg)
1196 if (dp)
1197 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1198 else
1199 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1202 static inline void gen_mov_vreg_F0(int dp, int reg)
1204 if (dp)
1205 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1206 else
1207 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1210 #define ARM_CP_RW_BIT (1 << 20)
1212 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1214 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1217 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1219 tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1222 static inline TCGv iwmmxt_load_creg(int reg)
1224 TCGv var = tcg_temp_new_i32();
1225 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1226 return var;
1229 static inline void iwmmxt_store_creg(int reg, TCGv var)
1231 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1232 tcg_temp_free_i32(var);
1235 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1237 iwmmxt_store_reg(cpu_M0, rn);
1240 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1242 iwmmxt_load_reg(cpu_M0, rn);
1245 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1247 iwmmxt_load_reg(cpu_V1, rn);
1248 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1251 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1253 iwmmxt_load_reg(cpu_V1, rn);
1254 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1257 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1259 iwmmxt_load_reg(cpu_V1, rn);
1260 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1263 #define IWMMXT_OP(name) \
1264 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1266 iwmmxt_load_reg(cpu_V1, rn); \
1267 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1270 #define IWMMXT_OP_ENV(name) \
1271 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1273 iwmmxt_load_reg(cpu_V1, rn); \
1274 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1277 #define IWMMXT_OP_ENV_SIZE(name) \
1278 IWMMXT_OP_ENV(name##b) \
1279 IWMMXT_OP_ENV(name##w) \
1280 IWMMXT_OP_ENV(name##l)
1282 #define IWMMXT_OP_ENV1(name) \
1283 static inline void gen_op_iwmmxt_##name##_M0(void) \
1285 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1288 IWMMXT_OP(maddsq)
1289 IWMMXT_OP(madduq)
1290 IWMMXT_OP(sadb)
1291 IWMMXT_OP(sadw)
1292 IWMMXT_OP(mulslw)
1293 IWMMXT_OP(mulshw)
1294 IWMMXT_OP(mululw)
1295 IWMMXT_OP(muluhw)
1296 IWMMXT_OP(macsw)
1297 IWMMXT_OP(macuw)
1299 IWMMXT_OP_ENV_SIZE(unpackl)
1300 IWMMXT_OP_ENV_SIZE(unpackh)
1302 IWMMXT_OP_ENV1(unpacklub)
1303 IWMMXT_OP_ENV1(unpackluw)
1304 IWMMXT_OP_ENV1(unpacklul)
1305 IWMMXT_OP_ENV1(unpackhub)
1306 IWMMXT_OP_ENV1(unpackhuw)
1307 IWMMXT_OP_ENV1(unpackhul)
1308 IWMMXT_OP_ENV1(unpacklsb)
1309 IWMMXT_OP_ENV1(unpacklsw)
1310 IWMMXT_OP_ENV1(unpacklsl)
1311 IWMMXT_OP_ENV1(unpackhsb)
1312 IWMMXT_OP_ENV1(unpackhsw)
1313 IWMMXT_OP_ENV1(unpackhsl)
1315 IWMMXT_OP_ENV_SIZE(cmpeq)
1316 IWMMXT_OP_ENV_SIZE(cmpgtu)
1317 IWMMXT_OP_ENV_SIZE(cmpgts)
1319 IWMMXT_OP_ENV_SIZE(mins)
1320 IWMMXT_OP_ENV_SIZE(minu)
1321 IWMMXT_OP_ENV_SIZE(maxs)
1322 IWMMXT_OP_ENV_SIZE(maxu)
1324 IWMMXT_OP_ENV_SIZE(subn)
1325 IWMMXT_OP_ENV_SIZE(addn)
1326 IWMMXT_OP_ENV_SIZE(subu)
1327 IWMMXT_OP_ENV_SIZE(addu)
1328 IWMMXT_OP_ENV_SIZE(subs)
1329 IWMMXT_OP_ENV_SIZE(adds)
1331 IWMMXT_OP_ENV(avgb0)
1332 IWMMXT_OP_ENV(avgb1)
1333 IWMMXT_OP_ENV(avgw0)
1334 IWMMXT_OP_ENV(avgw1)
1336 IWMMXT_OP(msadb)
1338 IWMMXT_OP_ENV(packuw)
1339 IWMMXT_OP_ENV(packul)
1340 IWMMXT_OP_ENV(packuq)
1341 IWMMXT_OP_ENV(packsw)
1342 IWMMXT_OP_ENV(packsl)
1343 IWMMXT_OP_ENV(packsq)
1345 static void gen_op_iwmmxt_set_mup(void)
1347 TCGv tmp;
1348 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1349 tcg_gen_ori_i32(tmp, tmp, 2);
1350 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1353 static void gen_op_iwmmxt_set_cup(void)
1355 TCGv tmp;
1356 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1357 tcg_gen_ori_i32(tmp, tmp, 1);
1358 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1361 static void gen_op_iwmmxt_setpsr_nz(void)
1363 TCGv tmp = tcg_temp_new_i32();
1364 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1365 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1368 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1370 iwmmxt_load_reg(cpu_V1, rn);
1371 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1372 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1375 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn, TCGv dest)
1377 int rd;
1378 uint32_t offset;
1379 TCGv tmp;
1381 rd = (insn >> 16) & 0xf;
1382 tmp = load_reg(s, rd);
1384 offset = (insn & 0xff) << ((insn >> 7) & 2);
1385 if (insn & (1 << 24)) {
1386 /* Pre indexed */
1387 if (insn & (1 << 23))
1388 tcg_gen_addi_i32(tmp, tmp, offset);
1389 else
1390 tcg_gen_addi_i32(tmp, tmp, -offset);
1391 tcg_gen_mov_i32(dest, tmp);
1392 if (insn & (1 << 21))
1393 store_reg(s, rd, tmp);
1394 else
1395 tcg_temp_free_i32(tmp);
1396 } else if (insn & (1 << 21)) {
1397 /* Post indexed */
1398 tcg_gen_mov_i32(dest, tmp);
1399 if (insn & (1 << 23))
1400 tcg_gen_addi_i32(tmp, tmp, offset);
1401 else
1402 tcg_gen_addi_i32(tmp, tmp, -offset);
1403 store_reg(s, rd, tmp);
1404 } else if (!(insn & (1 << 23)))
1405 return 1;
1406 return 0;
1409 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv dest)
1411 int rd = (insn >> 0) & 0xf;
1412 TCGv tmp;
1414 if (insn & (1 << 8)) {
1415 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1416 return 1;
1417 } else {
1418 tmp = iwmmxt_load_creg(rd);
1420 } else {
1421 tmp = tcg_temp_new_i32();
1422 iwmmxt_load_reg(cpu_V0, rd);
1423 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
1425 tcg_gen_andi_i32(tmp, tmp, mask);
1426 tcg_gen_mov_i32(dest, tmp);
1427 tcg_temp_free_i32(tmp);
1428 return 0;
1431 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
1432 (ie. an undefined instruction). */
1433 static int disas_iwmmxt_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
1435 int rd, wrd;
1436 int rdhi, rdlo, rd0, rd1, i;
1437 TCGv addr;
1438 TCGv tmp, tmp2, tmp3;
1440 if ((insn & 0x0e000e00) == 0x0c000000) {
1441 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1442 wrd = insn & 0xf;
1443 rdlo = (insn >> 12) & 0xf;
1444 rdhi = (insn >> 16) & 0xf;
1445 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1446 iwmmxt_load_reg(cpu_V0, wrd);
1447 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
1448 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1449 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
1450 } else { /* TMCRR */
1451 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1452 iwmmxt_store_reg(cpu_V0, wrd);
1453 gen_op_iwmmxt_set_mup();
1455 return 0;
1458 wrd = (insn >> 12) & 0xf;
1459 addr = tcg_temp_new_i32();
1460 if (gen_iwmmxt_address(s, insn, addr)) {
1461 tcg_temp_free_i32(addr);
1462 return 1;
1464 if (insn & ARM_CP_RW_BIT) {
1465 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1466 tmp = tcg_temp_new_i32();
1467 tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s));
1468 iwmmxt_store_creg(wrd, tmp);
1469 } else {
1470 i = 1;
1471 if (insn & (1 << 8)) {
1472 if (insn & (1 << 22)) { /* WLDRD */
1473 tcg_gen_qemu_ld64(cpu_M0, addr, IS_USER(s));
1474 i = 0;
1475 } else { /* WLDRW wRd */
1476 tmp = gen_ld32(addr, IS_USER(s));
1478 } else {
1479 if (insn & (1 << 22)) { /* WLDRH */
1480 tmp = gen_ld16u(addr, IS_USER(s));
1481 } else { /* WLDRB */
1482 tmp = gen_ld8u(addr, IS_USER(s));
1485 if (i) {
1486 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1487 tcg_temp_free_i32(tmp);
1489 gen_op_iwmmxt_movq_wRn_M0(wrd);
1491 } else {
1492 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1493 tmp = iwmmxt_load_creg(wrd);
1494 gen_st32(tmp, addr, IS_USER(s));
1495 } else {
1496 gen_op_iwmmxt_movq_M0_wRn(wrd);
1497 tmp = tcg_temp_new_i32();
1498 if (insn & (1 << 8)) {
1499 if (insn & (1 << 22)) { /* WSTRD */
1500 tcg_temp_free_i32(tmp);
1501 tcg_gen_qemu_st64(cpu_M0, addr, IS_USER(s));
1502 } else { /* WSTRW wRd */
1503 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1504 gen_st32(tmp, addr, IS_USER(s));
1506 } else {
1507 if (insn & (1 << 22)) { /* WSTRH */
1508 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1509 gen_st16(tmp, addr, IS_USER(s));
1510 } else { /* WSTRB */
1511 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1512 gen_st8(tmp, addr, IS_USER(s));
1517 tcg_temp_free_i32(addr);
1518 return 0;
1521 if ((insn & 0x0f000000) != 0x0e000000)
1522 return 1;
1524 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1525 case 0x000: /* WOR */
1526 wrd = (insn >> 12) & 0xf;
1527 rd0 = (insn >> 0) & 0xf;
1528 rd1 = (insn >> 16) & 0xf;
1529 gen_op_iwmmxt_movq_M0_wRn(rd0);
1530 gen_op_iwmmxt_orq_M0_wRn(rd1);
1531 gen_op_iwmmxt_setpsr_nz();
1532 gen_op_iwmmxt_movq_wRn_M0(wrd);
1533 gen_op_iwmmxt_set_mup();
1534 gen_op_iwmmxt_set_cup();
1535 break;
1536 case 0x011: /* TMCR */
1537 if (insn & 0xf)
1538 return 1;
1539 rd = (insn >> 12) & 0xf;
1540 wrd = (insn >> 16) & 0xf;
1541 switch (wrd) {
1542 case ARM_IWMMXT_wCID:
1543 case ARM_IWMMXT_wCASF:
1544 break;
1545 case ARM_IWMMXT_wCon:
1546 gen_op_iwmmxt_set_cup();
1547 /* Fall through. */
1548 case ARM_IWMMXT_wCSSF:
1549 tmp = iwmmxt_load_creg(wrd);
1550 tmp2 = load_reg(s, rd);
1551 tcg_gen_andc_i32(tmp, tmp, tmp2);
1552 tcg_temp_free_i32(tmp2);
1553 iwmmxt_store_creg(wrd, tmp);
1554 break;
1555 case ARM_IWMMXT_wCGR0:
1556 case ARM_IWMMXT_wCGR1:
1557 case ARM_IWMMXT_wCGR2:
1558 case ARM_IWMMXT_wCGR3:
1559 gen_op_iwmmxt_set_cup();
1560 tmp = load_reg(s, rd);
1561 iwmmxt_store_creg(wrd, tmp);
1562 break;
1563 default:
1564 return 1;
1566 break;
1567 case 0x100: /* WXOR */
1568 wrd = (insn >> 12) & 0xf;
1569 rd0 = (insn >> 0) & 0xf;
1570 rd1 = (insn >> 16) & 0xf;
1571 gen_op_iwmmxt_movq_M0_wRn(rd0);
1572 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1573 gen_op_iwmmxt_setpsr_nz();
1574 gen_op_iwmmxt_movq_wRn_M0(wrd);
1575 gen_op_iwmmxt_set_mup();
1576 gen_op_iwmmxt_set_cup();
1577 break;
1578 case 0x111: /* TMRC */
1579 if (insn & 0xf)
1580 return 1;
1581 rd = (insn >> 12) & 0xf;
1582 wrd = (insn >> 16) & 0xf;
1583 tmp = iwmmxt_load_creg(wrd);
1584 store_reg(s, rd, tmp);
1585 break;
1586 case 0x300: /* WANDN */
1587 wrd = (insn >> 12) & 0xf;
1588 rd0 = (insn >> 0) & 0xf;
1589 rd1 = (insn >> 16) & 0xf;
1590 gen_op_iwmmxt_movq_M0_wRn(rd0);
1591 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1592 gen_op_iwmmxt_andq_M0_wRn(rd1);
1593 gen_op_iwmmxt_setpsr_nz();
1594 gen_op_iwmmxt_movq_wRn_M0(wrd);
1595 gen_op_iwmmxt_set_mup();
1596 gen_op_iwmmxt_set_cup();
1597 break;
1598 case 0x200: /* WAND */
1599 wrd = (insn >> 12) & 0xf;
1600 rd0 = (insn >> 0) & 0xf;
1601 rd1 = (insn >> 16) & 0xf;
1602 gen_op_iwmmxt_movq_M0_wRn(rd0);
1603 gen_op_iwmmxt_andq_M0_wRn(rd1);
1604 gen_op_iwmmxt_setpsr_nz();
1605 gen_op_iwmmxt_movq_wRn_M0(wrd);
1606 gen_op_iwmmxt_set_mup();
1607 gen_op_iwmmxt_set_cup();
1608 break;
1609 case 0x810: case 0xa10: /* WMADD */
1610 wrd = (insn >> 12) & 0xf;
1611 rd0 = (insn >> 0) & 0xf;
1612 rd1 = (insn >> 16) & 0xf;
1613 gen_op_iwmmxt_movq_M0_wRn(rd0);
1614 if (insn & (1 << 21))
1615 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1616 else
1617 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1618 gen_op_iwmmxt_movq_wRn_M0(wrd);
1619 gen_op_iwmmxt_set_mup();
1620 break;
1621 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1622 wrd = (insn >> 12) & 0xf;
1623 rd0 = (insn >> 16) & 0xf;
1624 rd1 = (insn >> 0) & 0xf;
1625 gen_op_iwmmxt_movq_M0_wRn(rd0);
1626 switch ((insn >> 22) & 3) {
1627 case 0:
1628 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1629 break;
1630 case 1:
1631 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1632 break;
1633 case 2:
1634 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1635 break;
1636 case 3:
1637 return 1;
1639 gen_op_iwmmxt_movq_wRn_M0(wrd);
1640 gen_op_iwmmxt_set_mup();
1641 gen_op_iwmmxt_set_cup();
1642 break;
1643 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1644 wrd = (insn >> 12) & 0xf;
1645 rd0 = (insn >> 16) & 0xf;
1646 rd1 = (insn >> 0) & 0xf;
1647 gen_op_iwmmxt_movq_M0_wRn(rd0);
1648 switch ((insn >> 22) & 3) {
1649 case 0:
1650 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1651 break;
1652 case 1:
1653 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1654 break;
1655 case 2:
1656 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1657 break;
1658 case 3:
1659 return 1;
1661 gen_op_iwmmxt_movq_wRn_M0(wrd);
1662 gen_op_iwmmxt_set_mup();
1663 gen_op_iwmmxt_set_cup();
1664 break;
1665 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1666 wrd = (insn >> 12) & 0xf;
1667 rd0 = (insn >> 16) & 0xf;
1668 rd1 = (insn >> 0) & 0xf;
1669 gen_op_iwmmxt_movq_M0_wRn(rd0);
1670 if (insn & (1 << 22))
1671 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1672 else
1673 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1674 if (!(insn & (1 << 20)))
1675 gen_op_iwmmxt_addl_M0_wRn(wrd);
1676 gen_op_iwmmxt_movq_wRn_M0(wrd);
1677 gen_op_iwmmxt_set_mup();
1678 break;
1679 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1680 wrd = (insn >> 12) & 0xf;
1681 rd0 = (insn >> 16) & 0xf;
1682 rd1 = (insn >> 0) & 0xf;
1683 gen_op_iwmmxt_movq_M0_wRn(rd0);
1684 if (insn & (1 << 21)) {
1685 if (insn & (1 << 20))
1686 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1687 else
1688 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1689 } else {
1690 if (insn & (1 << 20))
1691 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1692 else
1693 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1695 gen_op_iwmmxt_movq_wRn_M0(wrd);
1696 gen_op_iwmmxt_set_mup();
1697 break;
1698 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1699 wrd = (insn >> 12) & 0xf;
1700 rd0 = (insn >> 16) & 0xf;
1701 rd1 = (insn >> 0) & 0xf;
1702 gen_op_iwmmxt_movq_M0_wRn(rd0);
1703 if (insn & (1 << 21))
1704 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1705 else
1706 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1707 if (!(insn & (1 << 20))) {
1708 iwmmxt_load_reg(cpu_V1, wrd);
1709 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1711 gen_op_iwmmxt_movq_wRn_M0(wrd);
1712 gen_op_iwmmxt_set_mup();
1713 break;
1714 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1715 wrd = (insn >> 12) & 0xf;
1716 rd0 = (insn >> 16) & 0xf;
1717 rd1 = (insn >> 0) & 0xf;
1718 gen_op_iwmmxt_movq_M0_wRn(rd0);
1719 switch ((insn >> 22) & 3) {
1720 case 0:
1721 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1722 break;
1723 case 1:
1724 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1725 break;
1726 case 2:
1727 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1728 break;
1729 case 3:
1730 return 1;
1732 gen_op_iwmmxt_movq_wRn_M0(wrd);
1733 gen_op_iwmmxt_set_mup();
1734 gen_op_iwmmxt_set_cup();
1735 break;
1736 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1737 wrd = (insn >> 12) & 0xf;
1738 rd0 = (insn >> 16) & 0xf;
1739 rd1 = (insn >> 0) & 0xf;
1740 gen_op_iwmmxt_movq_M0_wRn(rd0);
1741 if (insn & (1 << 22)) {
1742 if (insn & (1 << 20))
1743 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1744 else
1745 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1746 } else {
1747 if (insn & (1 << 20))
1748 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1749 else
1750 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1752 gen_op_iwmmxt_movq_wRn_M0(wrd);
1753 gen_op_iwmmxt_set_mup();
1754 gen_op_iwmmxt_set_cup();
1755 break;
1756 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1757 wrd = (insn >> 12) & 0xf;
1758 rd0 = (insn >> 16) & 0xf;
1759 rd1 = (insn >> 0) & 0xf;
1760 gen_op_iwmmxt_movq_M0_wRn(rd0);
1761 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1762 tcg_gen_andi_i32(tmp, tmp, 7);
1763 iwmmxt_load_reg(cpu_V1, rd1);
1764 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
1765 tcg_temp_free_i32(tmp);
1766 gen_op_iwmmxt_movq_wRn_M0(wrd);
1767 gen_op_iwmmxt_set_mup();
1768 break;
1769 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1770 if (((insn >> 6) & 3) == 3)
1771 return 1;
1772 rd = (insn >> 12) & 0xf;
1773 wrd = (insn >> 16) & 0xf;
1774 tmp = load_reg(s, rd);
1775 gen_op_iwmmxt_movq_M0_wRn(wrd);
1776 switch ((insn >> 6) & 3) {
1777 case 0:
1778 tmp2 = tcg_const_i32(0xff);
1779 tmp3 = tcg_const_i32((insn & 7) << 3);
1780 break;
1781 case 1:
1782 tmp2 = tcg_const_i32(0xffff);
1783 tmp3 = tcg_const_i32((insn & 3) << 4);
1784 break;
1785 case 2:
1786 tmp2 = tcg_const_i32(0xffffffff);
1787 tmp3 = tcg_const_i32((insn & 1) << 5);
1788 break;
1789 default:
1790 TCGV_UNUSED(tmp2);
1791 TCGV_UNUSED(tmp3);
1793 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
1794 tcg_temp_free(tmp3);
1795 tcg_temp_free(tmp2);
1796 tcg_temp_free_i32(tmp);
1797 gen_op_iwmmxt_movq_wRn_M0(wrd);
1798 gen_op_iwmmxt_set_mup();
1799 break;
1800 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1801 rd = (insn >> 12) & 0xf;
1802 wrd = (insn >> 16) & 0xf;
1803 if (rd == 15 || ((insn >> 22) & 3) == 3)
1804 return 1;
1805 gen_op_iwmmxt_movq_M0_wRn(wrd);
1806 tmp = tcg_temp_new_i32();
1807 switch ((insn >> 22) & 3) {
1808 case 0:
1809 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
1810 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1811 if (insn & 8) {
1812 tcg_gen_ext8s_i32(tmp, tmp);
1813 } else {
1814 tcg_gen_andi_i32(tmp, tmp, 0xff);
1816 break;
1817 case 1:
1818 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
1819 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1820 if (insn & 8) {
1821 tcg_gen_ext16s_i32(tmp, tmp);
1822 } else {
1823 tcg_gen_andi_i32(tmp, tmp, 0xffff);
1825 break;
1826 case 2:
1827 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
1828 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1829 break;
1831 store_reg(s, rd, tmp);
1832 break;
1833 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1834 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1835 return 1;
1836 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1837 switch ((insn >> 22) & 3) {
1838 case 0:
1839 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
1840 break;
1841 case 1:
1842 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
1843 break;
1844 case 2:
1845 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
1846 break;
1848 tcg_gen_shli_i32(tmp, tmp, 28);
1849 gen_set_nzcv(tmp);
1850 tcg_temp_free_i32(tmp);
1851 break;
1852 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1853 if (((insn >> 6) & 3) == 3)
1854 return 1;
1855 rd = (insn >> 12) & 0xf;
1856 wrd = (insn >> 16) & 0xf;
1857 tmp = load_reg(s, rd);
1858 switch ((insn >> 6) & 3) {
1859 case 0:
1860 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
1861 break;
1862 case 1:
1863 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
1864 break;
1865 case 2:
1866 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
1867 break;
1869 tcg_temp_free_i32(tmp);
1870 gen_op_iwmmxt_movq_wRn_M0(wrd);
1871 gen_op_iwmmxt_set_mup();
1872 break;
1873 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1874 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1875 return 1;
1876 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1877 tmp2 = tcg_temp_new_i32();
1878 tcg_gen_mov_i32(tmp2, tmp);
1879 switch ((insn >> 22) & 3) {
1880 case 0:
1881 for (i = 0; i < 7; i ++) {
1882 tcg_gen_shli_i32(tmp2, tmp2, 4);
1883 tcg_gen_and_i32(tmp, tmp, tmp2);
1885 break;
1886 case 1:
1887 for (i = 0; i < 3; i ++) {
1888 tcg_gen_shli_i32(tmp2, tmp2, 8);
1889 tcg_gen_and_i32(tmp, tmp, tmp2);
1891 break;
1892 case 2:
1893 tcg_gen_shli_i32(tmp2, tmp2, 16);
1894 tcg_gen_and_i32(tmp, tmp, tmp2);
1895 break;
1897 gen_set_nzcv(tmp);
1898 tcg_temp_free_i32(tmp2);
1899 tcg_temp_free_i32(tmp);
1900 break;
1901 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1902 wrd = (insn >> 12) & 0xf;
1903 rd0 = (insn >> 16) & 0xf;
1904 gen_op_iwmmxt_movq_M0_wRn(rd0);
1905 switch ((insn >> 22) & 3) {
1906 case 0:
1907 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1908 break;
1909 case 1:
1910 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1911 break;
1912 case 2:
1913 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1914 break;
1915 case 3:
1916 return 1;
1918 gen_op_iwmmxt_movq_wRn_M0(wrd);
1919 gen_op_iwmmxt_set_mup();
1920 break;
1921 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1922 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1923 return 1;
1924 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1925 tmp2 = tcg_temp_new_i32();
1926 tcg_gen_mov_i32(tmp2, tmp);
1927 switch ((insn >> 22) & 3) {
1928 case 0:
1929 for (i = 0; i < 7; i ++) {
1930 tcg_gen_shli_i32(tmp2, tmp2, 4);
1931 tcg_gen_or_i32(tmp, tmp, tmp2);
1933 break;
1934 case 1:
1935 for (i = 0; i < 3; i ++) {
1936 tcg_gen_shli_i32(tmp2, tmp2, 8);
1937 tcg_gen_or_i32(tmp, tmp, tmp2);
1939 break;
1940 case 2:
1941 tcg_gen_shli_i32(tmp2, tmp2, 16);
1942 tcg_gen_or_i32(tmp, tmp, tmp2);
1943 break;
1945 gen_set_nzcv(tmp);
1946 tcg_temp_free_i32(tmp2);
1947 tcg_temp_free_i32(tmp);
1948 break;
1949 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1950 rd = (insn >> 12) & 0xf;
1951 rd0 = (insn >> 16) & 0xf;
1952 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
1953 return 1;
1954 gen_op_iwmmxt_movq_M0_wRn(rd0);
1955 tmp = tcg_temp_new_i32();
1956 switch ((insn >> 22) & 3) {
1957 case 0:
1958 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
1959 break;
1960 case 1:
1961 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
1962 break;
1963 case 2:
1964 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
1965 break;
1967 store_reg(s, rd, tmp);
1968 break;
1969 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1970 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1971 wrd = (insn >> 12) & 0xf;
1972 rd0 = (insn >> 16) & 0xf;
1973 rd1 = (insn >> 0) & 0xf;
1974 gen_op_iwmmxt_movq_M0_wRn(rd0);
1975 switch ((insn >> 22) & 3) {
1976 case 0:
1977 if (insn & (1 << 21))
1978 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1979 else
1980 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1981 break;
1982 case 1:
1983 if (insn & (1 << 21))
1984 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1985 else
1986 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
1987 break;
1988 case 2:
1989 if (insn & (1 << 21))
1990 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
1991 else
1992 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
1993 break;
1994 case 3:
1995 return 1;
1997 gen_op_iwmmxt_movq_wRn_M0(wrd);
1998 gen_op_iwmmxt_set_mup();
1999 gen_op_iwmmxt_set_cup();
2000 break;
2001 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2002 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2003 wrd = (insn >> 12) & 0xf;
2004 rd0 = (insn >> 16) & 0xf;
2005 gen_op_iwmmxt_movq_M0_wRn(rd0);
2006 switch ((insn >> 22) & 3) {
2007 case 0:
2008 if (insn & (1 << 21))
2009 gen_op_iwmmxt_unpacklsb_M0();
2010 else
2011 gen_op_iwmmxt_unpacklub_M0();
2012 break;
2013 case 1:
2014 if (insn & (1 << 21))
2015 gen_op_iwmmxt_unpacklsw_M0();
2016 else
2017 gen_op_iwmmxt_unpackluw_M0();
2018 break;
2019 case 2:
2020 if (insn & (1 << 21))
2021 gen_op_iwmmxt_unpacklsl_M0();
2022 else
2023 gen_op_iwmmxt_unpacklul_M0();
2024 break;
2025 case 3:
2026 return 1;
2028 gen_op_iwmmxt_movq_wRn_M0(wrd);
2029 gen_op_iwmmxt_set_mup();
2030 gen_op_iwmmxt_set_cup();
2031 break;
2032 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2033 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2034 wrd = (insn >> 12) & 0xf;
2035 rd0 = (insn >> 16) & 0xf;
2036 gen_op_iwmmxt_movq_M0_wRn(rd0);
2037 switch ((insn >> 22) & 3) {
2038 case 0:
2039 if (insn & (1 << 21))
2040 gen_op_iwmmxt_unpackhsb_M0();
2041 else
2042 gen_op_iwmmxt_unpackhub_M0();
2043 break;
2044 case 1:
2045 if (insn & (1 << 21))
2046 gen_op_iwmmxt_unpackhsw_M0();
2047 else
2048 gen_op_iwmmxt_unpackhuw_M0();
2049 break;
2050 case 2:
2051 if (insn & (1 << 21))
2052 gen_op_iwmmxt_unpackhsl_M0();
2053 else
2054 gen_op_iwmmxt_unpackhul_M0();
2055 break;
2056 case 3:
2057 return 1;
2059 gen_op_iwmmxt_movq_wRn_M0(wrd);
2060 gen_op_iwmmxt_set_mup();
2061 gen_op_iwmmxt_set_cup();
2062 break;
2063 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2064 case 0x214: case 0x614: case 0xa14: case 0xe14:
2065 if (((insn >> 22) & 3) == 0)
2066 return 1;
2067 wrd = (insn >> 12) & 0xf;
2068 rd0 = (insn >> 16) & 0xf;
2069 gen_op_iwmmxt_movq_M0_wRn(rd0);
2070 tmp = tcg_temp_new_i32();
2071 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2072 tcg_temp_free_i32(tmp);
2073 return 1;
2075 switch ((insn >> 22) & 3) {
2076 case 1:
2077 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
2078 break;
2079 case 2:
2080 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
2081 break;
2082 case 3:
2083 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
2084 break;
2086 tcg_temp_free_i32(tmp);
2087 gen_op_iwmmxt_movq_wRn_M0(wrd);
2088 gen_op_iwmmxt_set_mup();
2089 gen_op_iwmmxt_set_cup();
2090 break;
2091 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2092 case 0x014: case 0x414: case 0x814: case 0xc14:
2093 if (((insn >> 22) & 3) == 0)
2094 return 1;
2095 wrd = (insn >> 12) & 0xf;
2096 rd0 = (insn >> 16) & 0xf;
2097 gen_op_iwmmxt_movq_M0_wRn(rd0);
2098 tmp = tcg_temp_new_i32();
2099 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2100 tcg_temp_free_i32(tmp);
2101 return 1;
2103 switch ((insn >> 22) & 3) {
2104 case 1:
2105 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2106 break;
2107 case 2:
2108 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2109 break;
2110 case 3:
2111 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2112 break;
2114 tcg_temp_free_i32(tmp);
2115 gen_op_iwmmxt_movq_wRn_M0(wrd);
2116 gen_op_iwmmxt_set_mup();
2117 gen_op_iwmmxt_set_cup();
2118 break;
2119 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2120 case 0x114: case 0x514: case 0x914: case 0xd14:
2121 if (((insn >> 22) & 3) == 0)
2122 return 1;
2123 wrd = (insn >> 12) & 0xf;
2124 rd0 = (insn >> 16) & 0xf;
2125 gen_op_iwmmxt_movq_M0_wRn(rd0);
2126 tmp = tcg_temp_new_i32();
2127 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2128 tcg_temp_free_i32(tmp);
2129 return 1;
2131 switch ((insn >> 22) & 3) {
2132 case 1:
2133 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2134 break;
2135 case 2:
2136 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2137 break;
2138 case 3:
2139 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2140 break;
2142 tcg_temp_free_i32(tmp);
2143 gen_op_iwmmxt_movq_wRn_M0(wrd);
2144 gen_op_iwmmxt_set_mup();
2145 gen_op_iwmmxt_set_cup();
2146 break;
2147 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2148 case 0x314: case 0x714: case 0xb14: case 0xf14:
2149 if (((insn >> 22) & 3) == 0)
2150 return 1;
2151 wrd = (insn >> 12) & 0xf;
2152 rd0 = (insn >> 16) & 0xf;
2153 gen_op_iwmmxt_movq_M0_wRn(rd0);
2154 tmp = tcg_temp_new_i32();
2155 switch ((insn >> 22) & 3) {
2156 case 1:
2157 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2158 tcg_temp_free_i32(tmp);
2159 return 1;
2161 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2162 break;
2163 case 2:
2164 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2165 tcg_temp_free_i32(tmp);
2166 return 1;
2168 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2169 break;
2170 case 3:
2171 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2172 tcg_temp_free_i32(tmp);
2173 return 1;
2175 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2176 break;
2178 tcg_temp_free_i32(tmp);
2179 gen_op_iwmmxt_movq_wRn_M0(wrd);
2180 gen_op_iwmmxt_set_mup();
2181 gen_op_iwmmxt_set_cup();
2182 break;
2183 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2184 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2185 wrd = (insn >> 12) & 0xf;
2186 rd0 = (insn >> 16) & 0xf;
2187 rd1 = (insn >> 0) & 0xf;
2188 gen_op_iwmmxt_movq_M0_wRn(rd0);
2189 switch ((insn >> 22) & 3) {
2190 case 0:
2191 if (insn & (1 << 21))
2192 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2193 else
2194 gen_op_iwmmxt_minub_M0_wRn(rd1);
2195 break;
2196 case 1:
2197 if (insn & (1 << 21))
2198 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2199 else
2200 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2201 break;
2202 case 2:
2203 if (insn & (1 << 21))
2204 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2205 else
2206 gen_op_iwmmxt_minul_M0_wRn(rd1);
2207 break;
2208 case 3:
2209 return 1;
2211 gen_op_iwmmxt_movq_wRn_M0(wrd);
2212 gen_op_iwmmxt_set_mup();
2213 break;
2214 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2215 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2216 wrd = (insn >> 12) & 0xf;
2217 rd0 = (insn >> 16) & 0xf;
2218 rd1 = (insn >> 0) & 0xf;
2219 gen_op_iwmmxt_movq_M0_wRn(rd0);
2220 switch ((insn >> 22) & 3) {
2221 case 0:
2222 if (insn & (1 << 21))
2223 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2224 else
2225 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2226 break;
2227 case 1:
2228 if (insn & (1 << 21))
2229 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2230 else
2231 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2232 break;
2233 case 2:
2234 if (insn & (1 << 21))
2235 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2236 else
2237 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2238 break;
2239 case 3:
2240 return 1;
2242 gen_op_iwmmxt_movq_wRn_M0(wrd);
2243 gen_op_iwmmxt_set_mup();
2244 break;
2245 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2246 case 0x402: case 0x502: case 0x602: case 0x702:
2247 wrd = (insn >> 12) & 0xf;
2248 rd0 = (insn >> 16) & 0xf;
2249 rd1 = (insn >> 0) & 0xf;
2250 gen_op_iwmmxt_movq_M0_wRn(rd0);
2251 tmp = tcg_const_i32((insn >> 20) & 3);
2252 iwmmxt_load_reg(cpu_V1, rd1);
2253 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2254 tcg_temp_free(tmp);
2255 gen_op_iwmmxt_movq_wRn_M0(wrd);
2256 gen_op_iwmmxt_set_mup();
2257 break;
2258 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2259 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2260 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2261 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2262 wrd = (insn >> 12) & 0xf;
2263 rd0 = (insn >> 16) & 0xf;
2264 rd1 = (insn >> 0) & 0xf;
2265 gen_op_iwmmxt_movq_M0_wRn(rd0);
2266 switch ((insn >> 20) & 0xf) {
2267 case 0x0:
2268 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2269 break;
2270 case 0x1:
2271 gen_op_iwmmxt_subub_M0_wRn(rd1);
2272 break;
2273 case 0x3:
2274 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2275 break;
2276 case 0x4:
2277 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2278 break;
2279 case 0x5:
2280 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2281 break;
2282 case 0x7:
2283 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2284 break;
2285 case 0x8:
2286 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2287 break;
2288 case 0x9:
2289 gen_op_iwmmxt_subul_M0_wRn(rd1);
2290 break;
2291 case 0xb:
2292 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2293 break;
2294 default:
2295 return 1;
2297 gen_op_iwmmxt_movq_wRn_M0(wrd);
2298 gen_op_iwmmxt_set_mup();
2299 gen_op_iwmmxt_set_cup();
2300 break;
2301 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2302 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2303 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2304 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2305 wrd = (insn >> 12) & 0xf;
2306 rd0 = (insn >> 16) & 0xf;
2307 gen_op_iwmmxt_movq_M0_wRn(rd0);
2308 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2309 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2310 tcg_temp_free(tmp);
2311 gen_op_iwmmxt_movq_wRn_M0(wrd);
2312 gen_op_iwmmxt_set_mup();
2313 gen_op_iwmmxt_set_cup();
2314 break;
2315 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2316 case 0x418: case 0x518: case 0x618: case 0x718:
2317 case 0x818: case 0x918: case 0xa18: case 0xb18:
2318 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2319 wrd = (insn >> 12) & 0xf;
2320 rd0 = (insn >> 16) & 0xf;
2321 rd1 = (insn >> 0) & 0xf;
2322 gen_op_iwmmxt_movq_M0_wRn(rd0);
2323 switch ((insn >> 20) & 0xf) {
2324 case 0x0:
2325 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2326 break;
2327 case 0x1:
2328 gen_op_iwmmxt_addub_M0_wRn(rd1);
2329 break;
2330 case 0x3:
2331 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2332 break;
2333 case 0x4:
2334 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2335 break;
2336 case 0x5:
2337 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2338 break;
2339 case 0x7:
2340 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2341 break;
2342 case 0x8:
2343 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2344 break;
2345 case 0x9:
2346 gen_op_iwmmxt_addul_M0_wRn(rd1);
2347 break;
2348 case 0xb:
2349 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2350 break;
2351 default:
2352 return 1;
2354 gen_op_iwmmxt_movq_wRn_M0(wrd);
2355 gen_op_iwmmxt_set_mup();
2356 gen_op_iwmmxt_set_cup();
2357 break;
2358 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2359 case 0x408: case 0x508: case 0x608: case 0x708:
2360 case 0x808: case 0x908: case 0xa08: case 0xb08:
2361 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2362 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2363 return 1;
2364 wrd = (insn >> 12) & 0xf;
2365 rd0 = (insn >> 16) & 0xf;
2366 rd1 = (insn >> 0) & 0xf;
2367 gen_op_iwmmxt_movq_M0_wRn(rd0);
2368 switch ((insn >> 22) & 3) {
2369 case 1:
2370 if (insn & (1 << 21))
2371 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2372 else
2373 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2374 break;
2375 case 2:
2376 if (insn & (1 << 21))
2377 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2378 else
2379 gen_op_iwmmxt_packul_M0_wRn(rd1);
2380 break;
2381 case 3:
2382 if (insn & (1 << 21))
2383 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2384 else
2385 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2386 break;
2388 gen_op_iwmmxt_movq_wRn_M0(wrd);
2389 gen_op_iwmmxt_set_mup();
2390 gen_op_iwmmxt_set_cup();
2391 break;
2392 case 0x201: case 0x203: case 0x205: case 0x207:
2393 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2394 case 0x211: case 0x213: case 0x215: case 0x217:
2395 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2396 wrd = (insn >> 5) & 0xf;
2397 rd0 = (insn >> 12) & 0xf;
2398 rd1 = (insn >> 0) & 0xf;
2399 if (rd0 == 0xf || rd1 == 0xf)
2400 return 1;
2401 gen_op_iwmmxt_movq_M0_wRn(wrd);
2402 tmp = load_reg(s, rd0);
2403 tmp2 = load_reg(s, rd1);
2404 switch ((insn >> 16) & 0xf) {
2405 case 0x0: /* TMIA */
2406 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2407 break;
2408 case 0x8: /* TMIAPH */
2409 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2410 break;
2411 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2412 if (insn & (1 << 16))
2413 tcg_gen_shri_i32(tmp, tmp, 16);
2414 if (insn & (1 << 17))
2415 tcg_gen_shri_i32(tmp2, tmp2, 16);
2416 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2417 break;
2418 default:
2419 tcg_temp_free_i32(tmp2);
2420 tcg_temp_free_i32(tmp);
2421 return 1;
2423 tcg_temp_free_i32(tmp2);
2424 tcg_temp_free_i32(tmp);
2425 gen_op_iwmmxt_movq_wRn_M0(wrd);
2426 gen_op_iwmmxt_set_mup();
2427 break;
2428 default:
2429 return 1;
2432 return 0;
2435 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
2436 (ie. an undefined instruction). */
2437 static int disas_dsp_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
2439 int acc, rd0, rd1, rdhi, rdlo;
2440 TCGv tmp, tmp2;
2442 if ((insn & 0x0ff00f10) == 0x0e200010) {
2443 /* Multiply with Internal Accumulate Format */
2444 rd0 = (insn >> 12) & 0xf;
2445 rd1 = insn & 0xf;
2446 acc = (insn >> 5) & 7;
2448 if (acc != 0)
2449 return 1;
2451 tmp = load_reg(s, rd0);
2452 tmp2 = load_reg(s, rd1);
2453 switch ((insn >> 16) & 0xf) {
2454 case 0x0: /* MIA */
2455 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2456 break;
2457 case 0x8: /* MIAPH */
2458 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2459 break;
2460 case 0xc: /* MIABB */
2461 case 0xd: /* MIABT */
2462 case 0xe: /* MIATB */
2463 case 0xf: /* MIATT */
2464 if (insn & (1 << 16))
2465 tcg_gen_shri_i32(tmp, tmp, 16);
2466 if (insn & (1 << 17))
2467 tcg_gen_shri_i32(tmp2, tmp2, 16);
2468 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2469 break;
2470 default:
2471 return 1;
2473 tcg_temp_free_i32(tmp2);
2474 tcg_temp_free_i32(tmp);
2476 gen_op_iwmmxt_movq_wRn_M0(acc);
2477 return 0;
2480 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2481 /* Internal Accumulator Access Format */
2482 rdhi = (insn >> 16) & 0xf;
2483 rdlo = (insn >> 12) & 0xf;
2484 acc = insn & 7;
2486 if (acc != 0)
2487 return 1;
2489 if (insn & ARM_CP_RW_BIT) { /* MRA */
2490 iwmmxt_load_reg(cpu_V0, acc);
2491 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
2492 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
2493 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
2494 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2495 } else { /* MAR */
2496 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2497 iwmmxt_store_reg(cpu_V0, acc);
2499 return 0;
2502 return 1;
2505 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2506 #define VFP_SREG(insn, bigbit, smallbit) \
2507 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2508 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2509 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2510 reg = (((insn) >> (bigbit)) & 0x0f) \
2511 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2512 } else { \
2513 if (insn & (1 << (smallbit))) \
2514 return 1; \
2515 reg = ((insn) >> (bigbit)) & 0x0f; \
2516 }} while (0)
2518 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2519 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2520 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2521 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2522 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2523 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2525 /* Move between integer and VFP cores. */
2526 static TCGv gen_vfp_mrs(void)
2528 TCGv tmp = tcg_temp_new_i32();
2529 tcg_gen_mov_i32(tmp, cpu_F0s);
2530 return tmp;
2533 static void gen_vfp_msr(TCGv tmp)
2535 tcg_gen_mov_i32(cpu_F0s, tmp);
2536 tcg_temp_free_i32(tmp);
2539 static void gen_neon_dup_u8(TCGv var, int shift)
2541 TCGv tmp = tcg_temp_new_i32();
2542 if (shift)
2543 tcg_gen_shri_i32(var, var, shift);
2544 tcg_gen_ext8u_i32(var, var);
2545 tcg_gen_shli_i32(tmp, var, 8);
2546 tcg_gen_or_i32(var, var, tmp);
2547 tcg_gen_shli_i32(tmp, var, 16);
2548 tcg_gen_or_i32(var, var, tmp);
2549 tcg_temp_free_i32(tmp);
2552 static void gen_neon_dup_low16(TCGv var)
2554 TCGv tmp = tcg_temp_new_i32();
2555 tcg_gen_ext16u_i32(var, var);
2556 tcg_gen_shli_i32(tmp, var, 16);
2557 tcg_gen_or_i32(var, var, tmp);
2558 tcg_temp_free_i32(tmp);
2561 static void gen_neon_dup_high16(TCGv var)
2563 TCGv tmp = tcg_temp_new_i32();
2564 tcg_gen_andi_i32(var, var, 0xffff0000);
2565 tcg_gen_shri_i32(tmp, var, 16);
2566 tcg_gen_or_i32(var, var, tmp);
2567 tcg_temp_free_i32(tmp);
2570 static TCGv gen_load_and_replicate(DisasContext *s, TCGv addr, int size)
2572 /* Load a single Neon element and replicate into a 32 bit TCG reg */
2573 TCGv tmp;
2574 switch (size) {
2575 case 0:
2576 tmp = gen_ld8u(addr, IS_USER(s));
2577 gen_neon_dup_u8(tmp, 0);
2578 break;
2579 case 1:
2580 tmp = gen_ld16u(addr, IS_USER(s));
2581 gen_neon_dup_low16(tmp);
2582 break;
2583 case 2:
2584 tmp = gen_ld32(addr, IS_USER(s));
2585 break;
2586 default: /* Avoid compiler warnings. */
2587 abort();
2589 return tmp;
2592 /* Disassemble a VFP instruction. Returns nonzero if an error occurred
2593 (ie. an undefined instruction). */
2594 static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
2596 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2597 int dp, veclen;
2598 TCGv addr;
2599 TCGv tmp;
2600 TCGv tmp2;
2602 if (!arm_feature(env, ARM_FEATURE_VFP))
2603 return 1;
2605 if (!s->vfp_enabled) {
2606 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2607 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2608 return 1;
2609 rn = (insn >> 16) & 0xf;
2610 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2611 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2612 return 1;
2614 dp = ((insn & 0xf00) == 0xb00);
2615 switch ((insn >> 24) & 0xf) {
2616 case 0xe:
2617 if (insn & (1 << 4)) {
2618 /* single register transfer */
2619 rd = (insn >> 12) & 0xf;
2620 if (dp) {
2621 int size;
2622 int pass;
2624 VFP_DREG_N(rn, insn);
2625 if (insn & 0xf)
2626 return 1;
2627 if (insn & 0x00c00060
2628 && !arm_feature(env, ARM_FEATURE_NEON))
2629 return 1;
2631 pass = (insn >> 21) & 1;
2632 if (insn & (1 << 22)) {
2633 size = 0;
2634 offset = ((insn >> 5) & 3) * 8;
2635 } else if (insn & (1 << 5)) {
2636 size = 1;
2637 offset = (insn & (1 << 6)) ? 16 : 0;
2638 } else {
2639 size = 2;
2640 offset = 0;
2642 if (insn & ARM_CP_RW_BIT) {
2643 /* vfp->arm */
2644 tmp = neon_load_reg(rn, pass);
2645 switch (size) {
2646 case 0:
2647 if (offset)
2648 tcg_gen_shri_i32(tmp, tmp, offset);
2649 if (insn & (1 << 23))
2650 gen_uxtb(tmp);
2651 else
2652 gen_sxtb(tmp);
2653 break;
2654 case 1:
2655 if (insn & (1 << 23)) {
2656 if (offset) {
2657 tcg_gen_shri_i32(tmp, tmp, 16);
2658 } else {
2659 gen_uxth(tmp);
2661 } else {
2662 if (offset) {
2663 tcg_gen_sari_i32(tmp, tmp, 16);
2664 } else {
2665 gen_sxth(tmp);
2668 break;
2669 case 2:
2670 break;
2672 store_reg(s, rd, tmp);
2673 } else {
2674 /* arm->vfp */
2675 tmp = load_reg(s, rd);
2676 if (insn & (1 << 23)) {
2677 /* VDUP */
2678 if (size == 0) {
2679 gen_neon_dup_u8(tmp, 0);
2680 } else if (size == 1) {
2681 gen_neon_dup_low16(tmp);
2683 for (n = 0; n <= pass * 2; n++) {
2684 tmp2 = tcg_temp_new_i32();
2685 tcg_gen_mov_i32(tmp2, tmp);
2686 neon_store_reg(rn, n, tmp2);
2688 neon_store_reg(rn, n, tmp);
2689 } else {
2690 /* VMOV */
2691 switch (size) {
2692 case 0:
2693 tmp2 = neon_load_reg(rn, pass);
2694 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 8);
2695 tcg_temp_free_i32(tmp2);
2696 break;
2697 case 1:
2698 tmp2 = neon_load_reg(rn, pass);
2699 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 16);
2700 tcg_temp_free_i32(tmp2);
2701 break;
2702 case 2:
2703 break;
2705 neon_store_reg(rn, pass, tmp);
2708 } else { /* !dp */
2709 if ((insn & 0x6f) != 0x00)
2710 return 1;
2711 rn = VFP_SREG_N(insn);
2712 if (insn & ARM_CP_RW_BIT) {
2713 /* vfp->arm */
2714 if (insn & (1 << 21)) {
2715 /* system register */
2716 rn >>= 1;
2718 switch (rn) {
2719 case ARM_VFP_FPSID:
2720 /* VFP2 allows access to FSID from userspace.
2721 VFP3 restricts all id registers to privileged
2722 accesses. */
2723 if (IS_USER(s)
2724 && arm_feature(env, ARM_FEATURE_VFP3))
2725 return 1;
2726 tmp = load_cpu_field(vfp.xregs[rn]);
2727 break;
2728 case ARM_VFP_FPEXC:
2729 if (IS_USER(s))
2730 return 1;
2731 tmp = load_cpu_field(vfp.xregs[rn]);
2732 break;
2733 case ARM_VFP_FPINST:
2734 case ARM_VFP_FPINST2:
2735 /* Not present in VFP3. */
2736 if (IS_USER(s)
2737 || arm_feature(env, ARM_FEATURE_VFP3))
2738 return 1;
2739 tmp = load_cpu_field(vfp.xregs[rn]);
2740 break;
2741 case ARM_VFP_FPSCR:
2742 if (rd == 15) {
2743 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2744 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2745 } else {
2746 tmp = tcg_temp_new_i32();
2747 gen_helper_vfp_get_fpscr(tmp, cpu_env);
2749 break;
2750 case ARM_VFP_MVFR0:
2751 case ARM_VFP_MVFR1:
2752 if (IS_USER(s)
2753 || !arm_feature(env, ARM_FEATURE_MVFR))
2754 return 1;
2755 tmp = load_cpu_field(vfp.xregs[rn]);
2756 break;
2757 default:
2758 return 1;
2760 } else {
2761 gen_mov_F0_vreg(0, rn);
2762 tmp = gen_vfp_mrs();
2764 if (rd == 15) {
2765 /* Set the 4 flag bits in the CPSR. */
2766 gen_set_nzcv(tmp);
2767 tcg_temp_free_i32(tmp);
2768 } else {
2769 store_reg(s, rd, tmp);
2771 } else {
2772 /* arm->vfp */
2773 if (insn & (1 << 21)) {
2774 rn >>= 1;
2775 /* system register */
2776 switch (rn) {
2777 case ARM_VFP_FPSID:
2778 case ARM_VFP_MVFR0:
2779 case ARM_VFP_MVFR1:
2780 /* Writes are ignored. */
2781 break;
2782 case ARM_VFP_FPSCR:
2783 tmp = load_reg(s, rd);
2784 gen_helper_vfp_set_fpscr(cpu_env, tmp);
2785 tcg_temp_free_i32(tmp);
2786 gen_lookup_tb(s);
2787 break;
2788 case ARM_VFP_FPEXC:
2789 if (IS_USER(s))
2790 return 1;
2791 /* TODO: VFP subarchitecture support.
2792 * For now, keep the EN bit only */
2793 tmp = load_reg(s, rd);
2794 tcg_gen_andi_i32(tmp, tmp, 1 << 30);
2795 store_cpu_field(tmp, vfp.xregs[rn]);
2796 gen_lookup_tb(s);
2797 break;
2798 case ARM_VFP_FPINST:
2799 case ARM_VFP_FPINST2:
2800 tmp = load_reg(s, rd);
2801 store_cpu_field(tmp, vfp.xregs[rn]);
2802 break;
2803 default:
2804 return 1;
2806 } else {
2807 tmp = load_reg(s, rd);
2808 gen_vfp_msr(tmp);
2809 gen_mov_vreg_F0(0, rn);
2813 } else {
2814 /* data processing */
2815 /* The opcode is in bits 23, 21, 20 and 6. */
2816 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2817 if (dp) {
2818 if (op == 15) {
2819 /* rn is opcode */
2820 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2821 } else {
2822 /* rn is register number */
2823 VFP_DREG_N(rn, insn);
2826 if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18))) {
2827 /* Integer or single precision destination. */
2828 rd = VFP_SREG_D(insn);
2829 } else {
2830 VFP_DREG_D(rd, insn);
2832 if (op == 15 &&
2833 (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14))) {
2834 /* VCVT from int is always from S reg regardless of dp bit.
2835 * VCVT with immediate frac_bits has same format as SREG_M
2837 rm = VFP_SREG_M(insn);
2838 } else {
2839 VFP_DREG_M(rm, insn);
2841 } else {
2842 rn = VFP_SREG_N(insn);
2843 if (op == 15 && rn == 15) {
2844 /* Double precision destination. */
2845 VFP_DREG_D(rd, insn);
2846 } else {
2847 rd = VFP_SREG_D(insn);
2849 /* NB that we implicitly rely on the encoding for the frac_bits
2850 * in VCVT of fixed to float being the same as that of an SREG_M
2852 rm = VFP_SREG_M(insn);
2855 veclen = s->vec_len;
2856 if (op == 15 && rn > 3)
2857 veclen = 0;
2859 /* Shut up compiler warnings. */
2860 delta_m = 0;
2861 delta_d = 0;
2862 bank_mask = 0;
2864 if (veclen > 0) {
2865 if (dp)
2866 bank_mask = 0xc;
2867 else
2868 bank_mask = 0x18;
2870 /* Figure out what type of vector operation this is. */
2871 if ((rd & bank_mask) == 0) {
2872 /* scalar */
2873 veclen = 0;
2874 } else {
2875 if (dp)
2876 delta_d = (s->vec_stride >> 1) + 1;
2877 else
2878 delta_d = s->vec_stride + 1;
2880 if ((rm & bank_mask) == 0) {
2881 /* mixed scalar/vector */
2882 delta_m = 0;
2883 } else {
2884 /* vector */
2885 delta_m = delta_d;
2890 /* Load the initial operands. */
2891 if (op == 15) {
2892 switch (rn) {
2893 case 16:
2894 case 17:
2895 /* Integer source */
2896 gen_mov_F0_vreg(0, rm);
2897 break;
2898 case 8:
2899 case 9:
2900 /* Compare */
2901 gen_mov_F0_vreg(dp, rd);
2902 gen_mov_F1_vreg(dp, rm);
2903 break;
2904 case 10:
2905 case 11:
2906 /* Compare with zero */
2907 gen_mov_F0_vreg(dp, rd);
2908 gen_vfp_F1_ld0(dp);
2909 break;
2910 case 20:
2911 case 21:
2912 case 22:
2913 case 23:
2914 case 28:
2915 case 29:
2916 case 30:
2917 case 31:
2918 /* Source and destination the same. */
2919 gen_mov_F0_vreg(dp, rd);
2920 break;
2921 case 4:
2922 case 5:
2923 case 6:
2924 case 7:
2925 /* VCVTB, VCVTT: only present with the halfprec extension,
2926 * UNPREDICTABLE if bit 8 is set (we choose to UNDEF)
2928 if (dp || !arm_feature(env, ARM_FEATURE_VFP_FP16)) {
2929 return 1;
2931 /* Otherwise fall through */
2932 default:
2933 /* One source operand. */
2934 gen_mov_F0_vreg(dp, rm);
2935 break;
2937 } else {
2938 /* Two source operands. */
2939 gen_mov_F0_vreg(dp, rn);
2940 gen_mov_F1_vreg(dp, rm);
2943 for (;;) {
2944 /* Perform the calculation. */
2945 switch (op) {
2946 case 0: /* VMLA: fd + (fn * fm) */
2947 /* Note that order of inputs to the add matters for NaNs */
2948 gen_vfp_F1_mul(dp);
2949 gen_mov_F0_vreg(dp, rd);
2950 gen_vfp_add(dp);
2951 break;
2952 case 1: /* VMLS: fd + -(fn * fm) */
2953 gen_vfp_mul(dp);
2954 gen_vfp_F1_neg(dp);
2955 gen_mov_F0_vreg(dp, rd);
2956 gen_vfp_add(dp);
2957 break;
2958 case 2: /* VNMLS: -fd + (fn * fm) */
2959 /* Note that it isn't valid to replace (-A + B) with (B - A)
2960 * or similar plausible looking simplifications
2961 * because this will give wrong results for NaNs.
2963 gen_vfp_F1_mul(dp);
2964 gen_mov_F0_vreg(dp, rd);
2965 gen_vfp_neg(dp);
2966 gen_vfp_add(dp);
2967 break;
2968 case 3: /* VNMLA: -fd + -(fn * fm) */
2969 gen_vfp_mul(dp);
2970 gen_vfp_F1_neg(dp);
2971 gen_mov_F0_vreg(dp, rd);
2972 gen_vfp_neg(dp);
2973 gen_vfp_add(dp);
2974 break;
2975 case 4: /* mul: fn * fm */
2976 gen_vfp_mul(dp);
2977 break;
2978 case 5: /* nmul: -(fn * fm) */
2979 gen_vfp_mul(dp);
2980 gen_vfp_neg(dp);
2981 break;
2982 case 6: /* add: fn + fm */
2983 gen_vfp_add(dp);
2984 break;
2985 case 7: /* sub: fn - fm */
2986 gen_vfp_sub(dp);
2987 break;
2988 case 8: /* div: fn / fm */
2989 gen_vfp_div(dp);
2990 break;
2991 case 10: /* VFNMA : fd = muladd(-fd, fn, fm) */
2992 case 11: /* VFNMS : fd = muladd(-fd, -fn, fm) */
2993 case 12: /* VFMA : fd = muladd( fd, fn, fm) */
2994 case 13: /* VFMS : fd = muladd( fd, -fn, fm) */
2995 /* These are fused multiply-add, and must be done as one
2996 * floating point operation with no rounding between the
2997 * multiplication and addition steps.
2998 * NB that doing the negations here as separate steps is
2999 * correct : an input NaN should come out with its sign bit
3000 * flipped if it is a negated-input.
3002 if (!arm_feature(env, ARM_FEATURE_VFP4)) {
3003 return 1;
3005 if (dp) {
3006 TCGv_ptr fpst;
3007 TCGv_i64 frd;
3008 if (op & 1) {
3009 /* VFNMS, VFMS */
3010 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
3012 frd = tcg_temp_new_i64();
3013 tcg_gen_ld_f64(frd, cpu_env, vfp_reg_offset(dp, rd));
3014 if (op & 2) {
3015 /* VFNMA, VFNMS */
3016 gen_helper_vfp_negd(frd, frd);
3018 fpst = get_fpstatus_ptr(0);
3019 gen_helper_vfp_muladdd(cpu_F0d, cpu_F0d,
3020 cpu_F1d, frd, fpst);
3021 tcg_temp_free_ptr(fpst);
3022 tcg_temp_free_i64(frd);
3023 } else {
3024 TCGv_ptr fpst;
3025 TCGv_i32 frd;
3026 if (op & 1) {
3027 /* VFNMS, VFMS */
3028 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
3030 frd = tcg_temp_new_i32();
3031 tcg_gen_ld_f32(frd, cpu_env, vfp_reg_offset(dp, rd));
3032 if (op & 2) {
3033 gen_helper_vfp_negs(frd, frd);
3035 fpst = get_fpstatus_ptr(0);
3036 gen_helper_vfp_muladds(cpu_F0s, cpu_F0s,
3037 cpu_F1s, frd, fpst);
3038 tcg_temp_free_ptr(fpst);
3039 tcg_temp_free_i32(frd);
3041 break;
3042 case 14: /* fconst */
3043 if (!arm_feature(env, ARM_FEATURE_VFP3))
3044 return 1;
3046 n = (insn << 12) & 0x80000000;
3047 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3048 if (dp) {
3049 if (i & 0x40)
3050 i |= 0x3f80;
3051 else
3052 i |= 0x4000;
3053 n |= i << 16;
3054 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3055 } else {
3056 if (i & 0x40)
3057 i |= 0x780;
3058 else
3059 i |= 0x800;
3060 n |= i << 19;
3061 tcg_gen_movi_i32(cpu_F0s, n);
3063 break;
3064 case 15: /* extension space */
3065 switch (rn) {
3066 case 0: /* cpy */
3067 /* no-op */
3068 break;
3069 case 1: /* abs */
3070 gen_vfp_abs(dp);
3071 break;
3072 case 2: /* neg */
3073 gen_vfp_neg(dp);
3074 break;
3075 case 3: /* sqrt */
3076 gen_vfp_sqrt(dp);
3077 break;
3078 case 4: /* vcvtb.f32.f16 */
3079 tmp = gen_vfp_mrs();
3080 tcg_gen_ext16u_i32(tmp, tmp);
3081 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3082 tcg_temp_free_i32(tmp);
3083 break;
3084 case 5: /* vcvtt.f32.f16 */
3085 tmp = gen_vfp_mrs();
3086 tcg_gen_shri_i32(tmp, tmp, 16);
3087 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3088 tcg_temp_free_i32(tmp);
3089 break;
3090 case 6: /* vcvtb.f16.f32 */
3091 tmp = tcg_temp_new_i32();
3092 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3093 gen_mov_F0_vreg(0, rd);
3094 tmp2 = gen_vfp_mrs();
3095 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3096 tcg_gen_or_i32(tmp, tmp, tmp2);
3097 tcg_temp_free_i32(tmp2);
3098 gen_vfp_msr(tmp);
3099 break;
3100 case 7: /* vcvtt.f16.f32 */
3101 tmp = tcg_temp_new_i32();
3102 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3103 tcg_gen_shli_i32(tmp, tmp, 16);
3104 gen_mov_F0_vreg(0, rd);
3105 tmp2 = gen_vfp_mrs();
3106 tcg_gen_ext16u_i32(tmp2, tmp2);
3107 tcg_gen_or_i32(tmp, tmp, tmp2);
3108 tcg_temp_free_i32(tmp2);
3109 gen_vfp_msr(tmp);
3110 break;
3111 case 8: /* cmp */
3112 gen_vfp_cmp(dp);
3113 break;
3114 case 9: /* cmpe */
3115 gen_vfp_cmpe(dp);
3116 break;
3117 case 10: /* cmpz */
3118 gen_vfp_cmp(dp);
3119 break;
3120 case 11: /* cmpez */
3121 gen_vfp_F1_ld0(dp);
3122 gen_vfp_cmpe(dp);
3123 break;
3124 case 15: /* single<->double conversion */
3125 if (dp)
3126 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3127 else
3128 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3129 break;
3130 case 16: /* fuito */
3131 gen_vfp_uito(dp, 0);
3132 break;
3133 case 17: /* fsito */
3134 gen_vfp_sito(dp, 0);
3135 break;
3136 case 20: /* fshto */
3137 if (!arm_feature(env, ARM_FEATURE_VFP3))
3138 return 1;
3139 gen_vfp_shto(dp, 16 - rm, 0);
3140 break;
3141 case 21: /* fslto */
3142 if (!arm_feature(env, ARM_FEATURE_VFP3))
3143 return 1;
3144 gen_vfp_slto(dp, 32 - rm, 0);
3145 break;
3146 case 22: /* fuhto */
3147 if (!arm_feature(env, ARM_FEATURE_VFP3))
3148 return 1;
3149 gen_vfp_uhto(dp, 16 - rm, 0);
3150 break;
3151 case 23: /* fulto */
3152 if (!arm_feature(env, ARM_FEATURE_VFP3))
3153 return 1;
3154 gen_vfp_ulto(dp, 32 - rm, 0);
3155 break;
3156 case 24: /* ftoui */
3157 gen_vfp_toui(dp, 0);
3158 break;
3159 case 25: /* ftouiz */
3160 gen_vfp_touiz(dp, 0);
3161 break;
3162 case 26: /* ftosi */
3163 gen_vfp_tosi(dp, 0);
3164 break;
3165 case 27: /* ftosiz */
3166 gen_vfp_tosiz(dp, 0);
3167 break;
3168 case 28: /* ftosh */
3169 if (!arm_feature(env, ARM_FEATURE_VFP3))
3170 return 1;
3171 gen_vfp_tosh(dp, 16 - rm, 0);
3172 break;
3173 case 29: /* ftosl */
3174 if (!arm_feature(env, ARM_FEATURE_VFP3))
3175 return 1;
3176 gen_vfp_tosl(dp, 32 - rm, 0);
3177 break;
3178 case 30: /* ftouh */
3179 if (!arm_feature(env, ARM_FEATURE_VFP3))
3180 return 1;
3181 gen_vfp_touh(dp, 16 - rm, 0);
3182 break;
3183 case 31: /* ftoul */
3184 if (!arm_feature(env, ARM_FEATURE_VFP3))
3185 return 1;
3186 gen_vfp_toul(dp, 32 - rm, 0);
3187 break;
3188 default: /* undefined */
3189 return 1;
3191 break;
3192 default: /* undefined */
3193 return 1;
3196 /* Write back the result. */
3197 if (op == 15 && (rn >= 8 && rn <= 11))
3198 ; /* Comparison, do nothing. */
3199 else if (op == 15 && dp && ((rn & 0x1c) == 0x18))
3200 /* VCVT double to int: always integer result. */
3201 gen_mov_vreg_F0(0, rd);
3202 else if (op == 15 && rn == 15)
3203 /* conversion */
3204 gen_mov_vreg_F0(!dp, rd);
3205 else
3206 gen_mov_vreg_F0(dp, rd);
3208 /* break out of the loop if we have finished */
3209 if (veclen == 0)
3210 break;
3212 if (op == 15 && delta_m == 0) {
3213 /* single source one-many */
3214 while (veclen--) {
3215 rd = ((rd + delta_d) & (bank_mask - 1))
3216 | (rd & bank_mask);
3217 gen_mov_vreg_F0(dp, rd);
3219 break;
3221 /* Setup the next operands. */
3222 veclen--;
3223 rd = ((rd + delta_d) & (bank_mask - 1))
3224 | (rd & bank_mask);
3226 if (op == 15) {
3227 /* One source operand. */
3228 rm = ((rm + delta_m) & (bank_mask - 1))
3229 | (rm & bank_mask);
3230 gen_mov_F0_vreg(dp, rm);
3231 } else {
3232 /* Two source operands. */
3233 rn = ((rn + delta_d) & (bank_mask - 1))
3234 | (rn & bank_mask);
3235 gen_mov_F0_vreg(dp, rn);
3236 if (delta_m) {
3237 rm = ((rm + delta_m) & (bank_mask - 1))
3238 | (rm & bank_mask);
3239 gen_mov_F1_vreg(dp, rm);
3244 break;
3245 case 0xc:
3246 case 0xd:
3247 if ((insn & 0x03e00000) == 0x00400000) {
3248 /* two-register transfer */
3249 rn = (insn >> 16) & 0xf;
3250 rd = (insn >> 12) & 0xf;
3251 if (dp) {
3252 VFP_DREG_M(rm, insn);
3253 } else {
3254 rm = VFP_SREG_M(insn);
3257 if (insn & ARM_CP_RW_BIT) {
3258 /* vfp->arm */
3259 if (dp) {
3260 gen_mov_F0_vreg(0, rm * 2);
3261 tmp = gen_vfp_mrs();
3262 store_reg(s, rd, tmp);
3263 gen_mov_F0_vreg(0, rm * 2 + 1);
3264 tmp = gen_vfp_mrs();
3265 store_reg(s, rn, tmp);
3266 } else {
3267 gen_mov_F0_vreg(0, rm);
3268 tmp = gen_vfp_mrs();
3269 store_reg(s, rd, tmp);
3270 gen_mov_F0_vreg(0, rm + 1);
3271 tmp = gen_vfp_mrs();
3272 store_reg(s, rn, tmp);
3274 } else {
3275 /* arm->vfp */
3276 if (dp) {
3277 tmp = load_reg(s, rd);
3278 gen_vfp_msr(tmp);
3279 gen_mov_vreg_F0(0, rm * 2);
3280 tmp = load_reg(s, rn);
3281 gen_vfp_msr(tmp);
3282 gen_mov_vreg_F0(0, rm * 2 + 1);
3283 } else {
3284 tmp = load_reg(s, rd);
3285 gen_vfp_msr(tmp);
3286 gen_mov_vreg_F0(0, rm);
3287 tmp = load_reg(s, rn);
3288 gen_vfp_msr(tmp);
3289 gen_mov_vreg_F0(0, rm + 1);
3292 } else {
3293 /* Load/store */
3294 rn = (insn >> 16) & 0xf;
3295 if (dp)
3296 VFP_DREG_D(rd, insn);
3297 else
3298 rd = VFP_SREG_D(insn);
3299 if ((insn & 0x01200000) == 0x01000000) {
3300 /* Single load/store */
3301 offset = (insn & 0xff) << 2;
3302 if ((insn & (1 << 23)) == 0)
3303 offset = -offset;
3304 if (s->thumb && rn == 15) {
3305 /* This is actually UNPREDICTABLE */
3306 addr = tcg_temp_new_i32();
3307 tcg_gen_movi_i32(addr, s->pc & ~2);
3308 } else {
3309 addr = load_reg(s, rn);
3311 tcg_gen_addi_i32(addr, addr, offset);
3312 if (insn & (1 << 20)) {
3313 gen_vfp_ld(s, dp, addr);
3314 gen_mov_vreg_F0(dp, rd);
3315 } else {
3316 gen_mov_F0_vreg(dp, rd);
3317 gen_vfp_st(s, dp, addr);
3319 tcg_temp_free_i32(addr);
3320 } else {
3321 /* load/store multiple */
3322 int w = insn & (1 << 21);
3323 if (dp)
3324 n = (insn >> 1) & 0x7f;
3325 else
3326 n = insn & 0xff;
3328 if (w && !(((insn >> 23) ^ (insn >> 24)) & 1)) {
3329 /* P == U , W == 1 => UNDEF */
3330 return 1;
3332 if (n == 0 || (rd + n) > 32 || (dp && n > 16)) {
3333 /* UNPREDICTABLE cases for bad immediates: we choose to
3334 * UNDEF to avoid generating huge numbers of TCG ops
3336 return 1;
3338 if (rn == 15 && w) {
3339 /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
3340 return 1;
3343 if (s->thumb && rn == 15) {
3344 /* This is actually UNPREDICTABLE */
3345 addr = tcg_temp_new_i32();
3346 tcg_gen_movi_i32(addr, s->pc & ~2);
3347 } else {
3348 addr = load_reg(s, rn);
3350 if (insn & (1 << 24)) /* pre-decrement */
3351 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
3353 if (dp)
3354 offset = 8;
3355 else
3356 offset = 4;
3357 for (i = 0; i < n; i++) {
3358 if (insn & ARM_CP_RW_BIT) {
3359 /* load */
3360 gen_vfp_ld(s, dp, addr);
3361 gen_mov_vreg_F0(dp, rd + i);
3362 } else {
3363 /* store */
3364 gen_mov_F0_vreg(dp, rd + i);
3365 gen_vfp_st(s, dp, addr);
3367 tcg_gen_addi_i32(addr, addr, offset);
3369 if (w) {
3370 /* writeback */
3371 if (insn & (1 << 24))
3372 offset = -offset * n;
3373 else if (dp && (insn & 1))
3374 offset = 4;
3375 else
3376 offset = 0;
3378 if (offset != 0)
3379 tcg_gen_addi_i32(addr, addr, offset);
3380 store_reg(s, rn, addr);
3381 } else {
3382 tcg_temp_free_i32(addr);
3386 break;
3387 default:
3388 /* Should never happen. */
3389 return 1;
3391 return 0;
3394 static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3396 TranslationBlock *tb;
3398 tb = s->tb;
3399 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3400 tcg_gen_goto_tb(n);
3401 gen_set_pc_im(dest);
3402 tcg_gen_exit_tb((tcg_target_long)tb + n);
3403 } else {
3404 gen_set_pc_im(dest);
3405 tcg_gen_exit_tb(0);
3409 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3411 if (unlikely(s->singlestep_enabled)) {
3412 /* An indirect jump so that we still trigger the debug exception. */
3413 if (s->thumb)
3414 dest |= 1;
3415 gen_bx_im(s, dest);
3416 } else {
3417 gen_goto_tb(s, 0, dest);
3418 s->is_jmp = DISAS_TB_JUMP;
3422 static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3424 if (x)
3425 tcg_gen_sari_i32(t0, t0, 16);
3426 else
3427 gen_sxth(t0);
3428 if (y)
3429 tcg_gen_sari_i32(t1, t1, 16);
3430 else
3431 gen_sxth(t1);
3432 tcg_gen_mul_i32(t0, t0, t1);
3435 /* Return the mask of PSR bits set by a MSR instruction. */
3436 static uint32_t msr_mask(CPUARMState *env, DisasContext *s, int flags, int spsr) {
3437 uint32_t mask;
3439 mask = 0;
3440 if (flags & (1 << 0))
3441 mask |= 0xff;
3442 if (flags & (1 << 1))
3443 mask |= 0xff00;
3444 if (flags & (1 << 2))
3445 mask |= 0xff0000;
3446 if (flags & (1 << 3))
3447 mask |= 0xff000000;
3449 /* Mask out undefined bits. */
3450 mask &= ~CPSR_RESERVED;
3451 if (!arm_feature(env, ARM_FEATURE_V4T))
3452 mask &= ~CPSR_T;
3453 if (!arm_feature(env, ARM_FEATURE_V5))
3454 mask &= ~CPSR_Q; /* V5TE in reality*/
3455 if (!arm_feature(env, ARM_FEATURE_V6))
3456 mask &= ~(CPSR_E | CPSR_GE);
3457 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3458 mask &= ~CPSR_IT;
3459 /* Mask out execution state bits. */
3460 if (!spsr)
3461 mask &= ~CPSR_EXEC;
3462 /* Mask out privileged bits. */
3463 if (IS_USER(s))
3464 mask &= CPSR_USER;
3465 return mask;
3468 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3469 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0)
3471 TCGv tmp;
3472 if (spsr) {
3473 /* ??? This is also undefined in system mode. */
3474 if (IS_USER(s))
3475 return 1;
3477 tmp = load_cpu_field(spsr);
3478 tcg_gen_andi_i32(tmp, tmp, ~mask);
3479 tcg_gen_andi_i32(t0, t0, mask);
3480 tcg_gen_or_i32(tmp, tmp, t0);
3481 store_cpu_field(tmp, spsr);
3482 } else {
3483 gen_set_cpsr(t0, mask);
3485 tcg_temp_free_i32(t0);
3486 gen_lookup_tb(s);
3487 return 0;
3490 /* Returns nonzero if access to the PSR is not permitted. */
3491 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3493 TCGv tmp;
3494 tmp = tcg_temp_new_i32();
3495 tcg_gen_movi_i32(tmp, val);
3496 return gen_set_psr(s, mask, spsr, tmp);
3499 /* Generate an old-style exception return. Marks pc as dead. */
3500 static void gen_exception_return(DisasContext *s, TCGv pc)
3502 TCGv tmp;
3503 store_reg(s, 15, pc);
3504 tmp = load_cpu_field(spsr);
3505 gen_set_cpsr(tmp, 0xffffffff);
3506 tcg_temp_free_i32(tmp);
3507 s->is_jmp = DISAS_UPDATE;
3510 /* Generate a v6 exception return. Marks both values as dead. */
3511 static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3513 gen_set_cpsr(cpsr, 0xffffffff);
3514 tcg_temp_free_i32(cpsr);
3515 store_reg(s, 15, pc);
3516 s->is_jmp = DISAS_UPDATE;
3519 static inline void
3520 gen_set_condexec (DisasContext *s)
3522 if (s->condexec_mask) {
3523 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3524 TCGv tmp = tcg_temp_new_i32();
3525 tcg_gen_movi_i32(tmp, val);
3526 store_cpu_field(tmp, condexec_bits);
3530 static void gen_exception_insn(DisasContext *s, int offset, int excp)
3532 gen_set_condexec(s);
3533 gen_set_pc_im(s->pc - offset);
3534 gen_exception(excp);
3535 s->is_jmp = DISAS_JUMP;
3538 static void gen_nop_hint(DisasContext *s, int val)
3540 switch (val) {
3541 case 3: /* wfi */
3542 gen_set_pc_im(s->pc);
3543 s->is_jmp = DISAS_WFI;
3544 break;
3545 case 2: /* wfe */
3546 case 4: /* sev */
3547 /* TODO: Implement SEV and WFE. May help SMP performance. */
3548 default: /* nop */
3549 break;
3553 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3555 static inline void gen_neon_add(int size, TCGv t0, TCGv t1)
3557 switch (size) {
3558 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
3559 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
3560 case 2: tcg_gen_add_i32(t0, t0, t1); break;
3561 default: abort();
3565 static inline void gen_neon_rsb(int size, TCGv t0, TCGv t1)
3567 switch (size) {
3568 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
3569 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
3570 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
3571 default: return;
3575 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3576 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3577 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3578 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3579 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3581 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3582 switch ((size << 1) | u) { \
3583 case 0: \
3584 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3585 break; \
3586 case 1: \
3587 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3588 break; \
3589 case 2: \
3590 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3591 break; \
3592 case 3: \
3593 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3594 break; \
3595 case 4: \
3596 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3597 break; \
3598 case 5: \
3599 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3600 break; \
3601 default: return 1; \
3602 }} while (0)
3604 #define GEN_NEON_INTEGER_OP(name) do { \
3605 switch ((size << 1) | u) { \
3606 case 0: \
3607 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3608 break; \
3609 case 1: \
3610 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3611 break; \
3612 case 2: \
3613 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3614 break; \
3615 case 3: \
3616 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3617 break; \
3618 case 4: \
3619 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3620 break; \
3621 case 5: \
3622 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3623 break; \
3624 default: return 1; \
3625 }} while (0)
3627 static TCGv neon_load_scratch(int scratch)
3629 TCGv tmp = tcg_temp_new_i32();
3630 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3631 return tmp;
3634 static void neon_store_scratch(int scratch, TCGv var)
3636 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3637 tcg_temp_free_i32(var);
3640 static inline TCGv neon_get_scalar(int size, int reg)
3642 TCGv tmp;
3643 if (size == 1) {
3644 tmp = neon_load_reg(reg & 7, reg >> 4);
3645 if (reg & 8) {
3646 gen_neon_dup_high16(tmp);
3647 } else {
3648 gen_neon_dup_low16(tmp);
3650 } else {
3651 tmp = neon_load_reg(reg & 15, reg >> 4);
3653 return tmp;
3656 static int gen_neon_unzip(int rd, int rm, int size, int q)
3658 TCGv tmp, tmp2;
3659 if (!q && size == 2) {
3660 return 1;
3662 tmp = tcg_const_i32(rd);
3663 tmp2 = tcg_const_i32(rm);
3664 if (q) {
3665 switch (size) {
3666 case 0:
3667 gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
3668 break;
3669 case 1:
3670 gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
3671 break;
3672 case 2:
3673 gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
3674 break;
3675 default:
3676 abort();
3678 } else {
3679 switch (size) {
3680 case 0:
3681 gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
3682 break;
3683 case 1:
3684 gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
3685 break;
3686 default:
3687 abort();
3690 tcg_temp_free_i32(tmp);
3691 tcg_temp_free_i32(tmp2);
3692 return 0;
3695 static int gen_neon_zip(int rd, int rm, int size, int q)
3697 TCGv tmp, tmp2;
3698 if (!q && size == 2) {
3699 return 1;
3701 tmp = tcg_const_i32(rd);
3702 tmp2 = tcg_const_i32(rm);
3703 if (q) {
3704 switch (size) {
3705 case 0:
3706 gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
3707 break;
3708 case 1:
3709 gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
3710 break;
3711 case 2:
3712 gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
3713 break;
3714 default:
3715 abort();
3717 } else {
3718 switch (size) {
3719 case 0:
3720 gen_helper_neon_zip8(cpu_env, tmp, tmp2);
3721 break;
3722 case 1:
3723 gen_helper_neon_zip16(cpu_env, tmp, tmp2);
3724 break;
3725 default:
3726 abort();
3729 tcg_temp_free_i32(tmp);
3730 tcg_temp_free_i32(tmp2);
3731 return 0;
3734 static void gen_neon_trn_u8(TCGv t0, TCGv t1)
3736 TCGv rd, tmp;
3738 rd = tcg_temp_new_i32();
3739 tmp = tcg_temp_new_i32();
3741 tcg_gen_shli_i32(rd, t0, 8);
3742 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3743 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3744 tcg_gen_or_i32(rd, rd, tmp);
3746 tcg_gen_shri_i32(t1, t1, 8);
3747 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3748 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3749 tcg_gen_or_i32(t1, t1, tmp);
3750 tcg_gen_mov_i32(t0, rd);
3752 tcg_temp_free_i32(tmp);
3753 tcg_temp_free_i32(rd);
3756 static void gen_neon_trn_u16(TCGv t0, TCGv t1)
3758 TCGv rd, tmp;
3760 rd = tcg_temp_new_i32();
3761 tmp = tcg_temp_new_i32();
3763 tcg_gen_shli_i32(rd, t0, 16);
3764 tcg_gen_andi_i32(tmp, t1, 0xffff);
3765 tcg_gen_or_i32(rd, rd, tmp);
3766 tcg_gen_shri_i32(t1, t1, 16);
3767 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3768 tcg_gen_or_i32(t1, t1, tmp);
3769 tcg_gen_mov_i32(t0, rd);
3771 tcg_temp_free_i32(tmp);
3772 tcg_temp_free_i32(rd);
3776 static struct {
3777 int nregs;
3778 int interleave;
3779 int spacing;
3780 } neon_ls_element_type[11] = {
3781 {4, 4, 1},
3782 {4, 4, 2},
3783 {4, 1, 1},
3784 {4, 2, 1},
3785 {3, 3, 1},
3786 {3, 3, 2},
3787 {3, 1, 1},
3788 {1, 1, 1},
3789 {2, 2, 1},
3790 {2, 2, 2},
3791 {2, 1, 1}
3794 /* Translate a NEON load/store element instruction. Return nonzero if the
3795 instruction is invalid. */
3796 static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
3798 int rd, rn, rm;
3799 int op;
3800 int nregs;
3801 int interleave;
3802 int spacing;
3803 int stride;
3804 int size;
3805 int reg;
3806 int pass;
3807 int load;
3808 int shift;
3809 int n;
3810 TCGv addr;
3811 TCGv tmp;
3812 TCGv tmp2;
3813 TCGv_i64 tmp64;
3815 if (!s->vfp_enabled)
3816 return 1;
3817 VFP_DREG_D(rd, insn);
3818 rn = (insn >> 16) & 0xf;
3819 rm = insn & 0xf;
3820 load = (insn & (1 << 21)) != 0;
3821 if ((insn & (1 << 23)) == 0) {
3822 /* Load store all elements. */
3823 op = (insn >> 8) & 0xf;
3824 size = (insn >> 6) & 3;
3825 if (op > 10)
3826 return 1;
3827 /* Catch UNDEF cases for bad values of align field */
3828 switch (op & 0xc) {
3829 case 4:
3830 if (((insn >> 5) & 1) == 1) {
3831 return 1;
3833 break;
3834 case 8:
3835 if (((insn >> 4) & 3) == 3) {
3836 return 1;
3838 break;
3839 default:
3840 break;
3842 nregs = neon_ls_element_type[op].nregs;
3843 interleave = neon_ls_element_type[op].interleave;
3844 spacing = neon_ls_element_type[op].spacing;
3845 if (size == 3 && (interleave | spacing) != 1)
3846 return 1;
3847 addr = tcg_temp_new_i32();
3848 load_reg_var(s, addr, rn);
3849 stride = (1 << size) * interleave;
3850 for (reg = 0; reg < nregs; reg++) {
3851 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3852 load_reg_var(s, addr, rn);
3853 tcg_gen_addi_i32(addr, addr, (1 << size) * reg);
3854 } else if (interleave == 2 && nregs == 4 && reg == 2) {
3855 load_reg_var(s, addr, rn);
3856 tcg_gen_addi_i32(addr, addr, 1 << size);
3858 if (size == 3) {
3859 if (load) {
3860 tmp64 = gen_ld64(addr, IS_USER(s));
3861 neon_store_reg64(tmp64, rd);
3862 tcg_temp_free_i64(tmp64);
3863 } else {
3864 tmp64 = tcg_temp_new_i64();
3865 neon_load_reg64(tmp64, rd);
3866 gen_st64(tmp64, addr, IS_USER(s));
3868 tcg_gen_addi_i32(addr, addr, stride);
3869 } else {
3870 for (pass = 0; pass < 2; pass++) {
3871 if (size == 2) {
3872 if (load) {
3873 tmp = gen_ld32(addr, IS_USER(s));
3874 neon_store_reg(rd, pass, tmp);
3875 } else {
3876 tmp = neon_load_reg(rd, pass);
3877 gen_st32(tmp, addr, IS_USER(s));
3879 tcg_gen_addi_i32(addr, addr, stride);
3880 } else if (size == 1) {
3881 if (load) {
3882 tmp = gen_ld16u(addr, IS_USER(s));
3883 tcg_gen_addi_i32(addr, addr, stride);
3884 tmp2 = gen_ld16u(addr, IS_USER(s));
3885 tcg_gen_addi_i32(addr, addr, stride);
3886 tcg_gen_shli_i32(tmp2, tmp2, 16);
3887 tcg_gen_or_i32(tmp, tmp, tmp2);
3888 tcg_temp_free_i32(tmp2);
3889 neon_store_reg(rd, pass, tmp);
3890 } else {
3891 tmp = neon_load_reg(rd, pass);
3892 tmp2 = tcg_temp_new_i32();
3893 tcg_gen_shri_i32(tmp2, tmp, 16);
3894 gen_st16(tmp, addr, IS_USER(s));
3895 tcg_gen_addi_i32(addr, addr, stride);
3896 gen_st16(tmp2, addr, IS_USER(s));
3897 tcg_gen_addi_i32(addr, addr, stride);
3899 } else /* size == 0 */ {
3900 if (load) {
3901 TCGV_UNUSED(tmp2);
3902 for (n = 0; n < 4; n++) {
3903 tmp = gen_ld8u(addr, IS_USER(s));
3904 tcg_gen_addi_i32(addr, addr, stride);
3905 if (n == 0) {
3906 tmp2 = tmp;
3907 } else {
3908 tcg_gen_shli_i32(tmp, tmp, n * 8);
3909 tcg_gen_or_i32(tmp2, tmp2, tmp);
3910 tcg_temp_free_i32(tmp);
3913 neon_store_reg(rd, pass, tmp2);
3914 } else {
3915 tmp2 = neon_load_reg(rd, pass);
3916 for (n = 0; n < 4; n++) {
3917 tmp = tcg_temp_new_i32();
3918 if (n == 0) {
3919 tcg_gen_mov_i32(tmp, tmp2);
3920 } else {
3921 tcg_gen_shri_i32(tmp, tmp2, n * 8);
3923 gen_st8(tmp, addr, IS_USER(s));
3924 tcg_gen_addi_i32(addr, addr, stride);
3926 tcg_temp_free_i32(tmp2);
3931 rd += spacing;
3933 tcg_temp_free_i32(addr);
3934 stride = nregs * 8;
3935 } else {
3936 size = (insn >> 10) & 3;
3937 if (size == 3) {
3938 /* Load single element to all lanes. */
3939 int a = (insn >> 4) & 1;
3940 if (!load) {
3941 return 1;
3943 size = (insn >> 6) & 3;
3944 nregs = ((insn >> 8) & 3) + 1;
3946 if (size == 3) {
3947 if (nregs != 4 || a == 0) {
3948 return 1;
3950 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
3951 size = 2;
3953 if (nregs == 1 && a == 1 && size == 0) {
3954 return 1;
3956 if (nregs == 3 && a == 1) {
3957 return 1;
3959 addr = tcg_temp_new_i32();
3960 load_reg_var(s, addr, rn);
3961 if (nregs == 1) {
3962 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */
3963 tmp = gen_load_and_replicate(s, addr, size);
3964 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
3965 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
3966 if (insn & (1 << 5)) {
3967 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 0));
3968 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 1));
3970 tcg_temp_free_i32(tmp);
3971 } else {
3972 /* VLD2/3/4 to all lanes: bit 5 indicates register stride */
3973 stride = (insn & (1 << 5)) ? 2 : 1;
3974 for (reg = 0; reg < nregs; reg++) {
3975 tmp = gen_load_and_replicate(s, addr, size);
3976 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
3977 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
3978 tcg_temp_free_i32(tmp);
3979 tcg_gen_addi_i32(addr, addr, 1 << size);
3980 rd += stride;
3983 tcg_temp_free_i32(addr);
3984 stride = (1 << size) * nregs;
3985 } else {
3986 /* Single element. */
3987 int idx = (insn >> 4) & 0xf;
3988 pass = (insn >> 7) & 1;
3989 switch (size) {
3990 case 0:
3991 shift = ((insn >> 5) & 3) * 8;
3992 stride = 1;
3993 break;
3994 case 1:
3995 shift = ((insn >> 6) & 1) * 16;
3996 stride = (insn & (1 << 5)) ? 2 : 1;
3997 break;
3998 case 2:
3999 shift = 0;
4000 stride = (insn & (1 << 6)) ? 2 : 1;
4001 break;
4002 default:
4003 abort();
4005 nregs = ((insn >> 8) & 3) + 1;
4006 /* Catch the UNDEF cases. This is unavoidably a bit messy. */
4007 switch (nregs) {
4008 case 1:
4009 if (((idx & (1 << size)) != 0) ||
4010 (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
4011 return 1;
4013 break;
4014 case 3:
4015 if ((idx & 1) != 0) {
4016 return 1;
4018 /* fall through */
4019 case 2:
4020 if (size == 2 && (idx & 2) != 0) {
4021 return 1;
4023 break;
4024 case 4:
4025 if ((size == 2) && ((idx & 3) == 3)) {
4026 return 1;
4028 break;
4029 default:
4030 abort();
4032 if ((rd + stride * (nregs - 1)) > 31) {
4033 /* Attempts to write off the end of the register file
4034 * are UNPREDICTABLE; we choose to UNDEF because otherwise
4035 * the neon_load_reg() would write off the end of the array.
4037 return 1;
4039 addr = tcg_temp_new_i32();
4040 load_reg_var(s, addr, rn);
4041 for (reg = 0; reg < nregs; reg++) {
4042 if (load) {
4043 switch (size) {
4044 case 0:
4045 tmp = gen_ld8u(addr, IS_USER(s));
4046 break;
4047 case 1:
4048 tmp = gen_ld16u(addr, IS_USER(s));
4049 break;
4050 case 2:
4051 tmp = gen_ld32(addr, IS_USER(s));
4052 break;
4053 default: /* Avoid compiler warnings. */
4054 abort();
4056 if (size != 2) {
4057 tmp2 = neon_load_reg(rd, pass);
4058 tcg_gen_deposit_i32(tmp, tmp2, tmp,
4059 shift, size ? 16 : 8);
4060 tcg_temp_free_i32(tmp2);
4062 neon_store_reg(rd, pass, tmp);
4063 } else { /* Store */
4064 tmp = neon_load_reg(rd, pass);
4065 if (shift)
4066 tcg_gen_shri_i32(tmp, tmp, shift);
4067 switch (size) {
4068 case 0:
4069 gen_st8(tmp, addr, IS_USER(s));
4070 break;
4071 case 1:
4072 gen_st16(tmp, addr, IS_USER(s));
4073 break;
4074 case 2:
4075 gen_st32(tmp, addr, IS_USER(s));
4076 break;
4079 rd += stride;
4080 tcg_gen_addi_i32(addr, addr, 1 << size);
4082 tcg_temp_free_i32(addr);
4083 stride = nregs * (1 << size);
4086 if (rm != 15) {
4087 TCGv base;
4089 base = load_reg(s, rn);
4090 if (rm == 13) {
4091 tcg_gen_addi_i32(base, base, stride);
4092 } else {
4093 TCGv index;
4094 index = load_reg(s, rm);
4095 tcg_gen_add_i32(base, base, index);
4096 tcg_temp_free_i32(index);
4098 store_reg(s, rn, base);
4100 return 0;
4103 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4104 static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
4106 tcg_gen_and_i32(t, t, c);
4107 tcg_gen_andc_i32(f, f, c);
4108 tcg_gen_or_i32(dest, t, f);
4111 static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
4113 switch (size) {
4114 case 0: gen_helper_neon_narrow_u8(dest, src); break;
4115 case 1: gen_helper_neon_narrow_u16(dest, src); break;
4116 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
4117 default: abort();
4121 static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
4123 switch (size) {
4124 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
4125 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
4126 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
4127 default: abort();
4131 static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
4133 switch (size) {
4134 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
4135 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
4136 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
4137 default: abort();
4141 static inline void gen_neon_unarrow_sats(int size, TCGv dest, TCGv_i64 src)
4143 switch (size) {
4144 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
4145 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
4146 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
4147 default: abort();
4151 static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
4152 int q, int u)
4154 if (q) {
4155 if (u) {
4156 switch (size) {
4157 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4158 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4159 default: abort();
4161 } else {
4162 switch (size) {
4163 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
4164 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
4165 default: abort();
4168 } else {
4169 if (u) {
4170 switch (size) {
4171 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
4172 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
4173 default: abort();
4175 } else {
4176 switch (size) {
4177 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
4178 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
4179 default: abort();
4185 static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
4187 if (u) {
4188 switch (size) {
4189 case 0: gen_helper_neon_widen_u8(dest, src); break;
4190 case 1: gen_helper_neon_widen_u16(dest, src); break;
4191 case 2: tcg_gen_extu_i32_i64(dest, src); break;
4192 default: abort();
4194 } else {
4195 switch (size) {
4196 case 0: gen_helper_neon_widen_s8(dest, src); break;
4197 case 1: gen_helper_neon_widen_s16(dest, src); break;
4198 case 2: tcg_gen_ext_i32_i64(dest, src); break;
4199 default: abort();
4202 tcg_temp_free_i32(src);
4205 static inline void gen_neon_addl(int size)
4207 switch (size) {
4208 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4209 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4210 case 2: tcg_gen_add_i64(CPU_V001); break;
4211 default: abort();
4215 static inline void gen_neon_subl(int size)
4217 switch (size) {
4218 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4219 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4220 case 2: tcg_gen_sub_i64(CPU_V001); break;
4221 default: abort();
4225 static inline void gen_neon_negl(TCGv_i64 var, int size)
4227 switch (size) {
4228 case 0: gen_helper_neon_negl_u16(var, var); break;
4229 case 1: gen_helper_neon_negl_u32(var, var); break;
4230 case 2:
4231 tcg_gen_neg_i64(var, var);
4232 break;
4233 default: abort();
4237 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4239 switch (size) {
4240 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4241 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4242 default: abort();
4246 static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
4248 TCGv_i64 tmp;
4250 switch ((size << 1) | u) {
4251 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4252 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4253 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4254 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4255 case 4:
4256 tmp = gen_muls_i64_i32(a, b);
4257 tcg_gen_mov_i64(dest, tmp);
4258 tcg_temp_free_i64(tmp);
4259 break;
4260 case 5:
4261 tmp = gen_mulu_i64_i32(a, b);
4262 tcg_gen_mov_i64(dest, tmp);
4263 tcg_temp_free_i64(tmp);
4264 break;
4265 default: abort();
4268 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
4269 Don't forget to clean them now. */
4270 if (size < 2) {
4271 tcg_temp_free_i32(a);
4272 tcg_temp_free_i32(b);
4276 static void gen_neon_narrow_op(int op, int u, int size, TCGv dest, TCGv_i64 src)
4278 if (op) {
4279 if (u) {
4280 gen_neon_unarrow_sats(size, dest, src);
4281 } else {
4282 gen_neon_narrow(size, dest, src);
4284 } else {
4285 if (u) {
4286 gen_neon_narrow_satu(size, dest, src);
4287 } else {
4288 gen_neon_narrow_sats(size, dest, src);
4293 /* Symbolic constants for op fields for Neon 3-register same-length.
4294 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
4295 * table A7-9.
4297 #define NEON_3R_VHADD 0
4298 #define NEON_3R_VQADD 1
4299 #define NEON_3R_VRHADD 2
4300 #define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
4301 #define NEON_3R_VHSUB 4
4302 #define NEON_3R_VQSUB 5
4303 #define NEON_3R_VCGT 6
4304 #define NEON_3R_VCGE 7
4305 #define NEON_3R_VSHL 8
4306 #define NEON_3R_VQSHL 9
4307 #define NEON_3R_VRSHL 10
4308 #define NEON_3R_VQRSHL 11
4309 #define NEON_3R_VMAX 12
4310 #define NEON_3R_VMIN 13
4311 #define NEON_3R_VABD 14
4312 #define NEON_3R_VABA 15
4313 #define NEON_3R_VADD_VSUB 16
4314 #define NEON_3R_VTST_VCEQ 17
4315 #define NEON_3R_VML 18 /* VMLA, VMLAL, VMLS, VMLSL */
4316 #define NEON_3R_VMUL 19
4317 #define NEON_3R_VPMAX 20
4318 #define NEON_3R_VPMIN 21
4319 #define NEON_3R_VQDMULH_VQRDMULH 22
4320 #define NEON_3R_VPADD 23
4321 #define NEON_3R_VFM 25 /* VFMA, VFMS : float fused multiply-add */
4322 #define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
4323 #define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
4324 #define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
4325 #define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
4326 #define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
4327 #define NEON_3R_VRECPS_VRSQRTS 31 /* float VRECPS, VRSQRTS */
4329 static const uint8_t neon_3r_sizes[] = {
4330 [NEON_3R_VHADD] = 0x7,
4331 [NEON_3R_VQADD] = 0xf,
4332 [NEON_3R_VRHADD] = 0x7,
4333 [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
4334 [NEON_3R_VHSUB] = 0x7,
4335 [NEON_3R_VQSUB] = 0xf,
4336 [NEON_3R_VCGT] = 0x7,
4337 [NEON_3R_VCGE] = 0x7,
4338 [NEON_3R_VSHL] = 0xf,
4339 [NEON_3R_VQSHL] = 0xf,
4340 [NEON_3R_VRSHL] = 0xf,
4341 [NEON_3R_VQRSHL] = 0xf,
4342 [NEON_3R_VMAX] = 0x7,
4343 [NEON_3R_VMIN] = 0x7,
4344 [NEON_3R_VABD] = 0x7,
4345 [NEON_3R_VABA] = 0x7,
4346 [NEON_3R_VADD_VSUB] = 0xf,
4347 [NEON_3R_VTST_VCEQ] = 0x7,
4348 [NEON_3R_VML] = 0x7,
4349 [NEON_3R_VMUL] = 0x7,
4350 [NEON_3R_VPMAX] = 0x7,
4351 [NEON_3R_VPMIN] = 0x7,
4352 [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
4353 [NEON_3R_VPADD] = 0x7,
4354 [NEON_3R_VFM] = 0x5, /* size bit 1 encodes op */
4355 [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
4356 [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
4357 [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
4358 [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
4359 [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
4360 [NEON_3R_VRECPS_VRSQRTS] = 0x5, /* size bit 1 encodes op */
4363 /* Symbolic constants for op fields for Neon 2-register miscellaneous.
4364 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
4365 * table A7-13.
4367 #define NEON_2RM_VREV64 0
4368 #define NEON_2RM_VREV32 1
4369 #define NEON_2RM_VREV16 2
4370 #define NEON_2RM_VPADDL 4
4371 #define NEON_2RM_VPADDL_U 5
4372 #define NEON_2RM_VCLS 8
4373 #define NEON_2RM_VCLZ 9
4374 #define NEON_2RM_VCNT 10
4375 #define NEON_2RM_VMVN 11
4376 #define NEON_2RM_VPADAL 12
4377 #define NEON_2RM_VPADAL_U 13
4378 #define NEON_2RM_VQABS 14
4379 #define NEON_2RM_VQNEG 15
4380 #define NEON_2RM_VCGT0 16
4381 #define NEON_2RM_VCGE0 17
4382 #define NEON_2RM_VCEQ0 18
4383 #define NEON_2RM_VCLE0 19
4384 #define NEON_2RM_VCLT0 20
4385 #define NEON_2RM_VABS 22
4386 #define NEON_2RM_VNEG 23
4387 #define NEON_2RM_VCGT0_F 24
4388 #define NEON_2RM_VCGE0_F 25
4389 #define NEON_2RM_VCEQ0_F 26
4390 #define NEON_2RM_VCLE0_F 27
4391 #define NEON_2RM_VCLT0_F 28
4392 #define NEON_2RM_VABS_F 30
4393 #define NEON_2RM_VNEG_F 31
4394 #define NEON_2RM_VSWP 32
4395 #define NEON_2RM_VTRN 33
4396 #define NEON_2RM_VUZP 34
4397 #define NEON_2RM_VZIP 35
4398 #define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
4399 #define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
4400 #define NEON_2RM_VSHLL 38
4401 #define NEON_2RM_VCVT_F16_F32 44
4402 #define NEON_2RM_VCVT_F32_F16 46
4403 #define NEON_2RM_VRECPE 56
4404 #define NEON_2RM_VRSQRTE 57
4405 #define NEON_2RM_VRECPE_F 58
4406 #define NEON_2RM_VRSQRTE_F 59
4407 #define NEON_2RM_VCVT_FS 60
4408 #define NEON_2RM_VCVT_FU 61
4409 #define NEON_2RM_VCVT_SF 62
4410 #define NEON_2RM_VCVT_UF 63
4412 static int neon_2rm_is_float_op(int op)
4414 /* Return true if this neon 2reg-misc op is float-to-float */
4415 return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
4416 op >= NEON_2RM_VRECPE_F);
4419 /* Each entry in this array has bit n set if the insn allows
4420 * size value n (otherwise it will UNDEF). Since unallocated
4421 * op values will have no bits set they always UNDEF.
4423 static const uint8_t neon_2rm_sizes[] = {
4424 [NEON_2RM_VREV64] = 0x7,
4425 [NEON_2RM_VREV32] = 0x3,
4426 [NEON_2RM_VREV16] = 0x1,
4427 [NEON_2RM_VPADDL] = 0x7,
4428 [NEON_2RM_VPADDL_U] = 0x7,
4429 [NEON_2RM_VCLS] = 0x7,
4430 [NEON_2RM_VCLZ] = 0x7,
4431 [NEON_2RM_VCNT] = 0x1,
4432 [NEON_2RM_VMVN] = 0x1,
4433 [NEON_2RM_VPADAL] = 0x7,
4434 [NEON_2RM_VPADAL_U] = 0x7,
4435 [NEON_2RM_VQABS] = 0x7,
4436 [NEON_2RM_VQNEG] = 0x7,
4437 [NEON_2RM_VCGT0] = 0x7,
4438 [NEON_2RM_VCGE0] = 0x7,
4439 [NEON_2RM_VCEQ0] = 0x7,
4440 [NEON_2RM_VCLE0] = 0x7,
4441 [NEON_2RM_VCLT0] = 0x7,
4442 [NEON_2RM_VABS] = 0x7,
4443 [NEON_2RM_VNEG] = 0x7,
4444 [NEON_2RM_VCGT0_F] = 0x4,
4445 [NEON_2RM_VCGE0_F] = 0x4,
4446 [NEON_2RM_VCEQ0_F] = 0x4,
4447 [NEON_2RM_VCLE0_F] = 0x4,
4448 [NEON_2RM_VCLT0_F] = 0x4,
4449 [NEON_2RM_VABS_F] = 0x4,
4450 [NEON_2RM_VNEG_F] = 0x4,
4451 [NEON_2RM_VSWP] = 0x1,
4452 [NEON_2RM_VTRN] = 0x7,
4453 [NEON_2RM_VUZP] = 0x7,
4454 [NEON_2RM_VZIP] = 0x7,
4455 [NEON_2RM_VMOVN] = 0x7,
4456 [NEON_2RM_VQMOVN] = 0x7,
4457 [NEON_2RM_VSHLL] = 0x7,
4458 [NEON_2RM_VCVT_F16_F32] = 0x2,
4459 [NEON_2RM_VCVT_F32_F16] = 0x2,
4460 [NEON_2RM_VRECPE] = 0x4,
4461 [NEON_2RM_VRSQRTE] = 0x4,
4462 [NEON_2RM_VRECPE_F] = 0x4,
4463 [NEON_2RM_VRSQRTE_F] = 0x4,
4464 [NEON_2RM_VCVT_FS] = 0x4,
4465 [NEON_2RM_VCVT_FU] = 0x4,
4466 [NEON_2RM_VCVT_SF] = 0x4,
4467 [NEON_2RM_VCVT_UF] = 0x4,
4470 /* Translate a NEON data processing instruction. Return nonzero if the
4471 instruction is invalid.
4472 We process data in a mixture of 32-bit and 64-bit chunks.
4473 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4475 static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
4477 int op;
4478 int q;
4479 int rd, rn, rm;
4480 int size;
4481 int shift;
4482 int pass;
4483 int count;
4484 int pairwise;
4485 int u;
4486 uint32_t imm, mask;
4487 TCGv tmp, tmp2, tmp3, tmp4, tmp5;
4488 TCGv_i64 tmp64;
4490 if (!s->vfp_enabled)
4491 return 1;
4492 q = (insn & (1 << 6)) != 0;
4493 u = (insn >> 24) & 1;
4494 VFP_DREG_D(rd, insn);
4495 VFP_DREG_N(rn, insn);
4496 VFP_DREG_M(rm, insn);
4497 size = (insn >> 20) & 3;
4498 if ((insn & (1 << 23)) == 0) {
4499 /* Three register same length. */
4500 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4501 /* Catch invalid op and bad size combinations: UNDEF */
4502 if ((neon_3r_sizes[op] & (1 << size)) == 0) {
4503 return 1;
4505 /* All insns of this form UNDEF for either this condition or the
4506 * superset of cases "Q==1"; we catch the latter later.
4508 if (q && ((rd | rn | rm) & 1)) {
4509 return 1;
4511 if (size == 3 && op != NEON_3R_LOGIC) {
4512 /* 64-bit element instructions. */
4513 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4514 neon_load_reg64(cpu_V0, rn + pass);
4515 neon_load_reg64(cpu_V1, rm + pass);
4516 switch (op) {
4517 case NEON_3R_VQADD:
4518 if (u) {
4519 gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
4520 cpu_V0, cpu_V1);
4521 } else {
4522 gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
4523 cpu_V0, cpu_V1);
4525 break;
4526 case NEON_3R_VQSUB:
4527 if (u) {
4528 gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
4529 cpu_V0, cpu_V1);
4530 } else {
4531 gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
4532 cpu_V0, cpu_V1);
4534 break;
4535 case NEON_3R_VSHL:
4536 if (u) {
4537 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4538 } else {
4539 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4541 break;
4542 case NEON_3R_VQSHL:
4543 if (u) {
4544 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4545 cpu_V1, cpu_V0);
4546 } else {
4547 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
4548 cpu_V1, cpu_V0);
4550 break;
4551 case NEON_3R_VRSHL:
4552 if (u) {
4553 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4554 } else {
4555 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4557 break;
4558 case NEON_3R_VQRSHL:
4559 if (u) {
4560 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4561 cpu_V1, cpu_V0);
4562 } else {
4563 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4564 cpu_V1, cpu_V0);
4566 break;
4567 case NEON_3R_VADD_VSUB:
4568 if (u) {
4569 tcg_gen_sub_i64(CPU_V001);
4570 } else {
4571 tcg_gen_add_i64(CPU_V001);
4573 break;
4574 default:
4575 abort();
4577 neon_store_reg64(cpu_V0, rd + pass);
4579 return 0;
4581 pairwise = 0;
4582 switch (op) {
4583 case NEON_3R_VSHL:
4584 case NEON_3R_VQSHL:
4585 case NEON_3R_VRSHL:
4586 case NEON_3R_VQRSHL:
4588 int rtmp;
4589 /* Shift instruction operands are reversed. */
4590 rtmp = rn;
4591 rn = rm;
4592 rm = rtmp;
4594 break;
4595 case NEON_3R_VPADD:
4596 if (u) {
4597 return 1;
4599 /* Fall through */
4600 case NEON_3R_VPMAX:
4601 case NEON_3R_VPMIN:
4602 pairwise = 1;
4603 break;
4604 case NEON_3R_FLOAT_ARITH:
4605 pairwise = (u && size < 2); /* if VPADD (float) */
4606 break;
4607 case NEON_3R_FLOAT_MINMAX:
4608 pairwise = u; /* if VPMIN/VPMAX (float) */
4609 break;
4610 case NEON_3R_FLOAT_CMP:
4611 if (!u && size) {
4612 /* no encoding for U=0 C=1x */
4613 return 1;
4615 break;
4616 case NEON_3R_FLOAT_ACMP:
4617 if (!u) {
4618 return 1;
4620 break;
4621 case NEON_3R_VRECPS_VRSQRTS:
4622 if (u) {
4623 return 1;
4625 break;
4626 case NEON_3R_VMUL:
4627 if (u && (size != 0)) {
4628 /* UNDEF on invalid size for polynomial subcase */
4629 return 1;
4631 break;
4632 case NEON_3R_VFM:
4633 if (!arm_feature(env, ARM_FEATURE_VFP4) || u) {
4634 return 1;
4636 break;
4637 default:
4638 break;
4641 if (pairwise && q) {
4642 /* All the pairwise insns UNDEF if Q is set */
4643 return 1;
4646 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4648 if (pairwise) {
4649 /* Pairwise. */
4650 if (pass < 1) {
4651 tmp = neon_load_reg(rn, 0);
4652 tmp2 = neon_load_reg(rn, 1);
4653 } else {
4654 tmp = neon_load_reg(rm, 0);
4655 tmp2 = neon_load_reg(rm, 1);
4657 } else {
4658 /* Elementwise. */
4659 tmp = neon_load_reg(rn, pass);
4660 tmp2 = neon_load_reg(rm, pass);
4662 switch (op) {
4663 case NEON_3R_VHADD:
4664 GEN_NEON_INTEGER_OP(hadd);
4665 break;
4666 case NEON_3R_VQADD:
4667 GEN_NEON_INTEGER_OP_ENV(qadd);
4668 break;
4669 case NEON_3R_VRHADD:
4670 GEN_NEON_INTEGER_OP(rhadd);
4671 break;
4672 case NEON_3R_LOGIC: /* Logic ops. */
4673 switch ((u << 2) | size) {
4674 case 0: /* VAND */
4675 tcg_gen_and_i32(tmp, tmp, tmp2);
4676 break;
4677 case 1: /* BIC */
4678 tcg_gen_andc_i32(tmp, tmp, tmp2);
4679 break;
4680 case 2: /* VORR */
4681 tcg_gen_or_i32(tmp, tmp, tmp2);
4682 break;
4683 case 3: /* VORN */
4684 tcg_gen_orc_i32(tmp, tmp, tmp2);
4685 break;
4686 case 4: /* VEOR */
4687 tcg_gen_xor_i32(tmp, tmp, tmp2);
4688 break;
4689 case 5: /* VBSL */
4690 tmp3 = neon_load_reg(rd, pass);
4691 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
4692 tcg_temp_free_i32(tmp3);
4693 break;
4694 case 6: /* VBIT */
4695 tmp3 = neon_load_reg(rd, pass);
4696 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
4697 tcg_temp_free_i32(tmp3);
4698 break;
4699 case 7: /* VBIF */
4700 tmp3 = neon_load_reg(rd, pass);
4701 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
4702 tcg_temp_free_i32(tmp3);
4703 break;
4705 break;
4706 case NEON_3R_VHSUB:
4707 GEN_NEON_INTEGER_OP(hsub);
4708 break;
4709 case NEON_3R_VQSUB:
4710 GEN_NEON_INTEGER_OP_ENV(qsub);
4711 break;
4712 case NEON_3R_VCGT:
4713 GEN_NEON_INTEGER_OP(cgt);
4714 break;
4715 case NEON_3R_VCGE:
4716 GEN_NEON_INTEGER_OP(cge);
4717 break;
4718 case NEON_3R_VSHL:
4719 GEN_NEON_INTEGER_OP(shl);
4720 break;
4721 case NEON_3R_VQSHL:
4722 GEN_NEON_INTEGER_OP_ENV(qshl);
4723 break;
4724 case NEON_3R_VRSHL:
4725 GEN_NEON_INTEGER_OP(rshl);
4726 break;
4727 case NEON_3R_VQRSHL:
4728 GEN_NEON_INTEGER_OP_ENV(qrshl);
4729 break;
4730 case NEON_3R_VMAX:
4731 GEN_NEON_INTEGER_OP(max);
4732 break;
4733 case NEON_3R_VMIN:
4734 GEN_NEON_INTEGER_OP(min);
4735 break;
4736 case NEON_3R_VABD:
4737 GEN_NEON_INTEGER_OP(abd);
4738 break;
4739 case NEON_3R_VABA:
4740 GEN_NEON_INTEGER_OP(abd);
4741 tcg_temp_free_i32(tmp2);
4742 tmp2 = neon_load_reg(rd, pass);
4743 gen_neon_add(size, tmp, tmp2);
4744 break;
4745 case NEON_3R_VADD_VSUB:
4746 if (!u) { /* VADD */
4747 gen_neon_add(size, tmp, tmp2);
4748 } else { /* VSUB */
4749 switch (size) {
4750 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
4751 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
4752 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
4753 default: abort();
4756 break;
4757 case NEON_3R_VTST_VCEQ:
4758 if (!u) { /* VTST */
4759 switch (size) {
4760 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
4761 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
4762 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
4763 default: abort();
4765 } else { /* VCEQ */
4766 switch (size) {
4767 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
4768 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
4769 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
4770 default: abort();
4773 break;
4774 case NEON_3R_VML: /* VMLA, VMLAL, VMLS,VMLSL */
4775 switch (size) {
4776 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4777 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4778 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4779 default: abort();
4781 tcg_temp_free_i32(tmp2);
4782 tmp2 = neon_load_reg(rd, pass);
4783 if (u) { /* VMLS */
4784 gen_neon_rsb(size, tmp, tmp2);
4785 } else { /* VMLA */
4786 gen_neon_add(size, tmp, tmp2);
4788 break;
4789 case NEON_3R_VMUL:
4790 if (u) { /* polynomial */
4791 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
4792 } else { /* Integer */
4793 switch (size) {
4794 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4795 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4796 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4797 default: abort();
4800 break;
4801 case NEON_3R_VPMAX:
4802 GEN_NEON_INTEGER_OP(pmax);
4803 break;
4804 case NEON_3R_VPMIN:
4805 GEN_NEON_INTEGER_OP(pmin);
4806 break;
4807 case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
4808 if (!u) { /* VQDMULH */
4809 switch (size) {
4810 case 1:
4811 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
4812 break;
4813 case 2:
4814 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
4815 break;
4816 default: abort();
4818 } else { /* VQRDMULH */
4819 switch (size) {
4820 case 1:
4821 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
4822 break;
4823 case 2:
4824 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
4825 break;
4826 default: abort();
4829 break;
4830 case NEON_3R_VPADD:
4831 switch (size) {
4832 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
4833 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
4834 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
4835 default: abort();
4837 break;
4838 case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
4840 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
4841 switch ((u << 2) | size) {
4842 case 0: /* VADD */
4843 case 4: /* VPADD */
4844 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
4845 break;
4846 case 2: /* VSUB */
4847 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
4848 break;
4849 case 6: /* VABD */
4850 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
4851 break;
4852 default:
4853 abort();
4855 tcg_temp_free_ptr(fpstatus);
4856 break;
4858 case NEON_3R_FLOAT_MULTIPLY:
4860 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
4861 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
4862 if (!u) {
4863 tcg_temp_free_i32(tmp2);
4864 tmp2 = neon_load_reg(rd, pass);
4865 if (size == 0) {
4866 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
4867 } else {
4868 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
4871 tcg_temp_free_ptr(fpstatus);
4872 break;
4874 case NEON_3R_FLOAT_CMP:
4876 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
4877 if (!u) {
4878 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
4879 } else {
4880 if (size == 0) {
4881 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
4882 } else {
4883 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
4886 tcg_temp_free_ptr(fpstatus);
4887 break;
4889 case NEON_3R_FLOAT_ACMP:
4891 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
4892 if (size == 0) {
4893 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
4894 } else {
4895 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
4897 tcg_temp_free_ptr(fpstatus);
4898 break;
4900 case NEON_3R_FLOAT_MINMAX:
4902 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
4903 if (size == 0) {
4904 gen_helper_neon_max_f32(tmp, tmp, tmp2, fpstatus);
4905 } else {
4906 gen_helper_neon_min_f32(tmp, tmp, tmp2, fpstatus);
4908 tcg_temp_free_ptr(fpstatus);
4909 break;
4911 case NEON_3R_VRECPS_VRSQRTS:
4912 if (size == 0)
4913 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
4914 else
4915 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
4916 break;
4917 case NEON_3R_VFM:
4919 /* VFMA, VFMS: fused multiply-add */
4920 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
4921 TCGv_i32 tmp3 = neon_load_reg(rd, pass);
4922 if (size) {
4923 /* VFMS */
4924 gen_helper_vfp_negs(tmp, tmp);
4926 gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus);
4927 tcg_temp_free_i32(tmp3);
4928 tcg_temp_free_ptr(fpstatus);
4929 break;
4931 default:
4932 abort();
4934 tcg_temp_free_i32(tmp2);
4936 /* Save the result. For elementwise operations we can put it
4937 straight into the destination register. For pairwise operations
4938 we have to be careful to avoid clobbering the source operands. */
4939 if (pairwise && rd == rm) {
4940 neon_store_scratch(pass, tmp);
4941 } else {
4942 neon_store_reg(rd, pass, tmp);
4945 } /* for pass */
4946 if (pairwise && rd == rm) {
4947 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4948 tmp = neon_load_scratch(pass);
4949 neon_store_reg(rd, pass, tmp);
4952 /* End of 3 register same size operations. */
4953 } else if (insn & (1 << 4)) {
4954 if ((insn & 0x00380080) != 0) {
4955 /* Two registers and shift. */
4956 op = (insn >> 8) & 0xf;
4957 if (insn & (1 << 7)) {
4958 /* 64-bit shift. */
4959 if (op > 7) {
4960 return 1;
4962 size = 3;
4963 } else {
4964 size = 2;
4965 while ((insn & (1 << (size + 19))) == 0)
4966 size--;
4968 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4969 /* To avoid excessive duplication of ops we implement shift
4970 by immediate using the variable shift operations. */
4971 if (op < 8) {
4972 /* Shift by immediate:
4973 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4974 if (q && ((rd | rm) & 1)) {
4975 return 1;
4977 if (!u && (op == 4 || op == 6)) {
4978 return 1;
4980 /* Right shifts are encoded as N - shift, where N is the
4981 element size in bits. */
4982 if (op <= 4)
4983 shift = shift - (1 << (size + 3));
4984 if (size == 3) {
4985 count = q + 1;
4986 } else {
4987 count = q ? 4: 2;
4989 switch (size) {
4990 case 0:
4991 imm = (uint8_t) shift;
4992 imm |= imm << 8;
4993 imm |= imm << 16;
4994 break;
4995 case 1:
4996 imm = (uint16_t) shift;
4997 imm |= imm << 16;
4998 break;
4999 case 2:
5000 case 3:
5001 imm = shift;
5002 break;
5003 default:
5004 abort();
5007 for (pass = 0; pass < count; pass++) {
5008 if (size == 3) {
5009 neon_load_reg64(cpu_V0, rm + pass);
5010 tcg_gen_movi_i64(cpu_V1, imm);
5011 switch (op) {
5012 case 0: /* VSHR */
5013 case 1: /* VSRA */
5014 if (u)
5015 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
5016 else
5017 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
5018 break;
5019 case 2: /* VRSHR */
5020 case 3: /* VRSRA */
5021 if (u)
5022 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
5023 else
5024 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
5025 break;
5026 case 4: /* VSRI */
5027 case 5: /* VSHL, VSLI */
5028 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
5029 break;
5030 case 6: /* VQSHLU */
5031 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
5032 cpu_V0, cpu_V1);
5033 break;
5034 case 7: /* VQSHL */
5035 if (u) {
5036 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
5037 cpu_V0, cpu_V1);
5038 } else {
5039 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
5040 cpu_V0, cpu_V1);
5042 break;
5044 if (op == 1 || op == 3) {
5045 /* Accumulate. */
5046 neon_load_reg64(cpu_V1, rd + pass);
5047 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
5048 } else if (op == 4 || (op == 5 && u)) {
5049 /* Insert */
5050 neon_load_reg64(cpu_V1, rd + pass);
5051 uint64_t mask;
5052 if (shift < -63 || shift > 63) {
5053 mask = 0;
5054 } else {
5055 if (op == 4) {
5056 mask = 0xffffffffffffffffull >> -shift;
5057 } else {
5058 mask = 0xffffffffffffffffull << shift;
5061 tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask);
5062 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5064 neon_store_reg64(cpu_V0, rd + pass);
5065 } else { /* size < 3 */
5066 /* Operands in T0 and T1. */
5067 tmp = neon_load_reg(rm, pass);
5068 tmp2 = tcg_temp_new_i32();
5069 tcg_gen_movi_i32(tmp2, imm);
5070 switch (op) {
5071 case 0: /* VSHR */
5072 case 1: /* VSRA */
5073 GEN_NEON_INTEGER_OP(shl);
5074 break;
5075 case 2: /* VRSHR */
5076 case 3: /* VRSRA */
5077 GEN_NEON_INTEGER_OP(rshl);
5078 break;
5079 case 4: /* VSRI */
5080 case 5: /* VSHL, VSLI */
5081 switch (size) {
5082 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
5083 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
5084 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
5085 default: abort();
5087 break;
5088 case 6: /* VQSHLU */
5089 switch (size) {
5090 case 0:
5091 gen_helper_neon_qshlu_s8(tmp, cpu_env,
5092 tmp, tmp2);
5093 break;
5094 case 1:
5095 gen_helper_neon_qshlu_s16(tmp, cpu_env,
5096 tmp, tmp2);
5097 break;
5098 case 2:
5099 gen_helper_neon_qshlu_s32(tmp, cpu_env,
5100 tmp, tmp2);
5101 break;
5102 default:
5103 abort();
5105 break;
5106 case 7: /* VQSHL */
5107 GEN_NEON_INTEGER_OP_ENV(qshl);
5108 break;
5110 tcg_temp_free_i32(tmp2);
5112 if (op == 1 || op == 3) {
5113 /* Accumulate. */
5114 tmp2 = neon_load_reg(rd, pass);
5115 gen_neon_add(size, tmp, tmp2);
5116 tcg_temp_free_i32(tmp2);
5117 } else if (op == 4 || (op == 5 && u)) {
5118 /* Insert */
5119 switch (size) {
5120 case 0:
5121 if (op == 4)
5122 mask = 0xff >> -shift;
5123 else
5124 mask = (uint8_t)(0xff << shift);
5125 mask |= mask << 8;
5126 mask |= mask << 16;
5127 break;
5128 case 1:
5129 if (op == 4)
5130 mask = 0xffff >> -shift;
5131 else
5132 mask = (uint16_t)(0xffff << shift);
5133 mask |= mask << 16;
5134 break;
5135 case 2:
5136 if (shift < -31 || shift > 31) {
5137 mask = 0;
5138 } else {
5139 if (op == 4)
5140 mask = 0xffffffffu >> -shift;
5141 else
5142 mask = 0xffffffffu << shift;
5144 break;
5145 default:
5146 abort();
5148 tmp2 = neon_load_reg(rd, pass);
5149 tcg_gen_andi_i32(tmp, tmp, mask);
5150 tcg_gen_andi_i32(tmp2, tmp2, ~mask);
5151 tcg_gen_or_i32(tmp, tmp, tmp2);
5152 tcg_temp_free_i32(tmp2);
5154 neon_store_reg(rd, pass, tmp);
5156 } /* for pass */
5157 } else if (op < 10) {
5158 /* Shift by immediate and narrow:
5159 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
5160 int input_unsigned = (op == 8) ? !u : u;
5161 if (rm & 1) {
5162 return 1;
5164 shift = shift - (1 << (size + 3));
5165 size++;
5166 if (size == 3) {
5167 tmp64 = tcg_const_i64(shift);
5168 neon_load_reg64(cpu_V0, rm);
5169 neon_load_reg64(cpu_V1, rm + 1);
5170 for (pass = 0; pass < 2; pass++) {
5171 TCGv_i64 in;
5172 if (pass == 0) {
5173 in = cpu_V0;
5174 } else {
5175 in = cpu_V1;
5177 if (q) {
5178 if (input_unsigned) {
5179 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
5180 } else {
5181 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
5183 } else {
5184 if (input_unsigned) {
5185 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
5186 } else {
5187 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
5190 tmp = tcg_temp_new_i32();
5191 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5192 neon_store_reg(rd, pass, tmp);
5193 } /* for pass */
5194 tcg_temp_free_i64(tmp64);
5195 } else {
5196 if (size == 1) {
5197 imm = (uint16_t)shift;
5198 imm |= imm << 16;
5199 } else {
5200 /* size == 2 */
5201 imm = (uint32_t)shift;
5203 tmp2 = tcg_const_i32(imm);
5204 tmp4 = neon_load_reg(rm + 1, 0);
5205 tmp5 = neon_load_reg(rm + 1, 1);
5206 for (pass = 0; pass < 2; pass++) {
5207 if (pass == 0) {
5208 tmp = neon_load_reg(rm, 0);
5209 } else {
5210 tmp = tmp4;
5212 gen_neon_shift_narrow(size, tmp, tmp2, q,
5213 input_unsigned);
5214 if (pass == 0) {
5215 tmp3 = neon_load_reg(rm, 1);
5216 } else {
5217 tmp3 = tmp5;
5219 gen_neon_shift_narrow(size, tmp3, tmp2, q,
5220 input_unsigned);
5221 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
5222 tcg_temp_free_i32(tmp);
5223 tcg_temp_free_i32(tmp3);
5224 tmp = tcg_temp_new_i32();
5225 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5226 neon_store_reg(rd, pass, tmp);
5227 } /* for pass */
5228 tcg_temp_free_i32(tmp2);
5230 } else if (op == 10) {
5231 /* VSHLL, VMOVL */
5232 if (q || (rd & 1)) {
5233 return 1;
5235 tmp = neon_load_reg(rm, 0);
5236 tmp2 = neon_load_reg(rm, 1);
5237 for (pass = 0; pass < 2; pass++) {
5238 if (pass == 1)
5239 tmp = tmp2;
5241 gen_neon_widen(cpu_V0, tmp, size, u);
5243 if (shift != 0) {
5244 /* The shift is less than the width of the source
5245 type, so we can just shift the whole register. */
5246 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
5247 /* Widen the result of shift: we need to clear
5248 * the potential overflow bits resulting from
5249 * left bits of the narrow input appearing as
5250 * right bits of left the neighbour narrow
5251 * input. */
5252 if (size < 2 || !u) {
5253 uint64_t imm64;
5254 if (size == 0) {
5255 imm = (0xffu >> (8 - shift));
5256 imm |= imm << 16;
5257 } else if (size == 1) {
5258 imm = 0xffff >> (16 - shift);
5259 } else {
5260 /* size == 2 */
5261 imm = 0xffffffff >> (32 - shift);
5263 if (size < 2) {
5264 imm64 = imm | (((uint64_t)imm) << 32);
5265 } else {
5266 imm64 = imm;
5268 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
5271 neon_store_reg64(cpu_V0, rd + pass);
5273 } else if (op >= 14) {
5274 /* VCVT fixed-point. */
5275 if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
5276 return 1;
5278 /* We have already masked out the must-be-1 top bit of imm6,
5279 * hence this 32-shift where the ARM ARM has 64-imm6.
5281 shift = 32 - shift;
5282 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5283 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
5284 if (!(op & 1)) {
5285 if (u)
5286 gen_vfp_ulto(0, shift, 1);
5287 else
5288 gen_vfp_slto(0, shift, 1);
5289 } else {
5290 if (u)
5291 gen_vfp_toul(0, shift, 1);
5292 else
5293 gen_vfp_tosl(0, shift, 1);
5295 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
5297 } else {
5298 return 1;
5300 } else { /* (insn & 0x00380080) == 0 */
5301 int invert;
5302 if (q && (rd & 1)) {
5303 return 1;
5306 op = (insn >> 8) & 0xf;
5307 /* One register and immediate. */
5308 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
5309 invert = (insn & (1 << 5)) != 0;
5310 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
5311 * We choose to not special-case this and will behave as if a
5312 * valid constant encoding of 0 had been given.
5314 switch (op) {
5315 case 0: case 1:
5316 /* no-op */
5317 break;
5318 case 2: case 3:
5319 imm <<= 8;
5320 break;
5321 case 4: case 5:
5322 imm <<= 16;
5323 break;
5324 case 6: case 7:
5325 imm <<= 24;
5326 break;
5327 case 8: case 9:
5328 imm |= imm << 16;
5329 break;
5330 case 10: case 11:
5331 imm = (imm << 8) | (imm << 24);
5332 break;
5333 case 12:
5334 imm = (imm << 8) | 0xff;
5335 break;
5336 case 13:
5337 imm = (imm << 16) | 0xffff;
5338 break;
5339 case 14:
5340 imm |= (imm << 8) | (imm << 16) | (imm << 24);
5341 if (invert)
5342 imm = ~imm;
5343 break;
5344 case 15:
5345 if (invert) {
5346 return 1;
5348 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
5349 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
5350 break;
5352 if (invert)
5353 imm = ~imm;
5355 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5356 if (op & 1 && op < 12) {
5357 tmp = neon_load_reg(rd, pass);
5358 if (invert) {
5359 /* The immediate value has already been inverted, so
5360 BIC becomes AND. */
5361 tcg_gen_andi_i32(tmp, tmp, imm);
5362 } else {
5363 tcg_gen_ori_i32(tmp, tmp, imm);
5365 } else {
5366 /* VMOV, VMVN. */
5367 tmp = tcg_temp_new_i32();
5368 if (op == 14 && invert) {
5369 int n;
5370 uint32_t val;
5371 val = 0;
5372 for (n = 0; n < 4; n++) {
5373 if (imm & (1 << (n + (pass & 1) * 4)))
5374 val |= 0xff << (n * 8);
5376 tcg_gen_movi_i32(tmp, val);
5377 } else {
5378 tcg_gen_movi_i32(tmp, imm);
5381 neon_store_reg(rd, pass, tmp);
5384 } else { /* (insn & 0x00800010 == 0x00800000) */
5385 if (size != 3) {
5386 op = (insn >> 8) & 0xf;
5387 if ((insn & (1 << 6)) == 0) {
5388 /* Three registers of different lengths. */
5389 int src1_wide;
5390 int src2_wide;
5391 int prewiden;
5392 /* undefreq: bit 0 : UNDEF if size != 0
5393 * bit 1 : UNDEF if size == 0
5394 * bit 2 : UNDEF if U == 1
5395 * Note that [1:0] set implies 'always UNDEF'
5397 int undefreq;
5398 /* prewiden, src1_wide, src2_wide, undefreq */
5399 static const int neon_3reg_wide[16][4] = {
5400 {1, 0, 0, 0}, /* VADDL */
5401 {1, 1, 0, 0}, /* VADDW */
5402 {1, 0, 0, 0}, /* VSUBL */
5403 {1, 1, 0, 0}, /* VSUBW */
5404 {0, 1, 1, 0}, /* VADDHN */
5405 {0, 0, 0, 0}, /* VABAL */
5406 {0, 1, 1, 0}, /* VSUBHN */
5407 {0, 0, 0, 0}, /* VABDL */
5408 {0, 0, 0, 0}, /* VMLAL */
5409 {0, 0, 0, 6}, /* VQDMLAL */
5410 {0, 0, 0, 0}, /* VMLSL */
5411 {0, 0, 0, 6}, /* VQDMLSL */
5412 {0, 0, 0, 0}, /* Integer VMULL */
5413 {0, 0, 0, 2}, /* VQDMULL */
5414 {0, 0, 0, 5}, /* Polynomial VMULL */
5415 {0, 0, 0, 3}, /* Reserved: always UNDEF */
5418 prewiden = neon_3reg_wide[op][0];
5419 src1_wide = neon_3reg_wide[op][1];
5420 src2_wide = neon_3reg_wide[op][2];
5421 undefreq = neon_3reg_wide[op][3];
5423 if (((undefreq & 1) && (size != 0)) ||
5424 ((undefreq & 2) && (size == 0)) ||
5425 ((undefreq & 4) && u)) {
5426 return 1;
5428 if ((src1_wide && (rn & 1)) ||
5429 (src2_wide && (rm & 1)) ||
5430 (!src2_wide && (rd & 1))) {
5431 return 1;
5434 /* Avoid overlapping operands. Wide source operands are
5435 always aligned so will never overlap with wide
5436 destinations in problematic ways. */
5437 if (rd == rm && !src2_wide) {
5438 tmp = neon_load_reg(rm, 1);
5439 neon_store_scratch(2, tmp);
5440 } else if (rd == rn && !src1_wide) {
5441 tmp = neon_load_reg(rn, 1);
5442 neon_store_scratch(2, tmp);
5444 TCGV_UNUSED(tmp3);
5445 for (pass = 0; pass < 2; pass++) {
5446 if (src1_wide) {
5447 neon_load_reg64(cpu_V0, rn + pass);
5448 TCGV_UNUSED(tmp);
5449 } else {
5450 if (pass == 1 && rd == rn) {
5451 tmp = neon_load_scratch(2);
5452 } else {
5453 tmp = neon_load_reg(rn, pass);
5455 if (prewiden) {
5456 gen_neon_widen(cpu_V0, tmp, size, u);
5459 if (src2_wide) {
5460 neon_load_reg64(cpu_V1, rm + pass);
5461 TCGV_UNUSED(tmp2);
5462 } else {
5463 if (pass == 1 && rd == rm) {
5464 tmp2 = neon_load_scratch(2);
5465 } else {
5466 tmp2 = neon_load_reg(rm, pass);
5468 if (prewiden) {
5469 gen_neon_widen(cpu_V1, tmp2, size, u);
5472 switch (op) {
5473 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5474 gen_neon_addl(size);
5475 break;
5476 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
5477 gen_neon_subl(size);
5478 break;
5479 case 5: case 7: /* VABAL, VABDL */
5480 switch ((size << 1) | u) {
5481 case 0:
5482 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
5483 break;
5484 case 1:
5485 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
5486 break;
5487 case 2:
5488 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
5489 break;
5490 case 3:
5491 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
5492 break;
5493 case 4:
5494 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
5495 break;
5496 case 5:
5497 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
5498 break;
5499 default: abort();
5501 tcg_temp_free_i32(tmp2);
5502 tcg_temp_free_i32(tmp);
5503 break;
5504 case 8: case 9: case 10: case 11: case 12: case 13:
5505 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5506 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5507 break;
5508 case 14: /* Polynomial VMULL */
5509 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
5510 tcg_temp_free_i32(tmp2);
5511 tcg_temp_free_i32(tmp);
5512 break;
5513 default: /* 15 is RESERVED: caught earlier */
5514 abort();
5516 if (op == 13) {
5517 /* VQDMULL */
5518 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5519 neon_store_reg64(cpu_V0, rd + pass);
5520 } else if (op == 5 || (op >= 8 && op <= 11)) {
5521 /* Accumulate. */
5522 neon_load_reg64(cpu_V1, rd + pass);
5523 switch (op) {
5524 case 10: /* VMLSL */
5525 gen_neon_negl(cpu_V0, size);
5526 /* Fall through */
5527 case 5: case 8: /* VABAL, VMLAL */
5528 gen_neon_addl(size);
5529 break;
5530 case 9: case 11: /* VQDMLAL, VQDMLSL */
5531 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5532 if (op == 11) {
5533 gen_neon_negl(cpu_V0, size);
5535 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5536 break;
5537 default:
5538 abort();
5540 neon_store_reg64(cpu_V0, rd + pass);
5541 } else if (op == 4 || op == 6) {
5542 /* Narrowing operation. */
5543 tmp = tcg_temp_new_i32();
5544 if (!u) {
5545 switch (size) {
5546 case 0:
5547 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
5548 break;
5549 case 1:
5550 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
5551 break;
5552 case 2:
5553 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5554 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5555 break;
5556 default: abort();
5558 } else {
5559 switch (size) {
5560 case 0:
5561 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
5562 break;
5563 case 1:
5564 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
5565 break;
5566 case 2:
5567 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
5568 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5569 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5570 break;
5571 default: abort();
5574 if (pass == 0) {
5575 tmp3 = tmp;
5576 } else {
5577 neon_store_reg(rd, 0, tmp3);
5578 neon_store_reg(rd, 1, tmp);
5580 } else {
5581 /* Write back the result. */
5582 neon_store_reg64(cpu_V0, rd + pass);
5585 } else {
5586 /* Two registers and a scalar. NB that for ops of this form
5587 * the ARM ARM labels bit 24 as Q, but it is in our variable
5588 * 'u', not 'q'.
5590 if (size == 0) {
5591 return 1;
5593 switch (op) {
5594 case 1: /* Float VMLA scalar */
5595 case 5: /* Floating point VMLS scalar */
5596 case 9: /* Floating point VMUL scalar */
5597 if (size == 1) {
5598 return 1;
5600 /* fall through */
5601 case 0: /* Integer VMLA scalar */
5602 case 4: /* Integer VMLS scalar */
5603 case 8: /* Integer VMUL scalar */
5604 case 12: /* VQDMULH scalar */
5605 case 13: /* VQRDMULH scalar */
5606 if (u && ((rd | rn) & 1)) {
5607 return 1;
5609 tmp = neon_get_scalar(size, rm);
5610 neon_store_scratch(0, tmp);
5611 for (pass = 0; pass < (u ? 4 : 2); pass++) {
5612 tmp = neon_load_scratch(0);
5613 tmp2 = neon_load_reg(rn, pass);
5614 if (op == 12) {
5615 if (size == 1) {
5616 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5617 } else {
5618 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5620 } else if (op == 13) {
5621 if (size == 1) {
5622 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5623 } else {
5624 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5626 } else if (op & 1) {
5627 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5628 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
5629 tcg_temp_free_ptr(fpstatus);
5630 } else {
5631 switch (size) {
5632 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5633 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5634 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5635 default: abort();
5638 tcg_temp_free_i32(tmp2);
5639 if (op < 8) {
5640 /* Accumulate. */
5641 tmp2 = neon_load_reg(rd, pass);
5642 switch (op) {
5643 case 0:
5644 gen_neon_add(size, tmp, tmp2);
5645 break;
5646 case 1:
5648 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5649 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5650 tcg_temp_free_ptr(fpstatus);
5651 break;
5653 case 4:
5654 gen_neon_rsb(size, tmp, tmp2);
5655 break;
5656 case 5:
5658 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5659 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
5660 tcg_temp_free_ptr(fpstatus);
5661 break;
5663 default:
5664 abort();
5666 tcg_temp_free_i32(tmp2);
5668 neon_store_reg(rd, pass, tmp);
5670 break;
5671 case 3: /* VQDMLAL scalar */
5672 case 7: /* VQDMLSL scalar */
5673 case 11: /* VQDMULL scalar */
5674 if (u == 1) {
5675 return 1;
5677 /* fall through */
5678 case 2: /* VMLAL sclar */
5679 case 6: /* VMLSL scalar */
5680 case 10: /* VMULL scalar */
5681 if (rd & 1) {
5682 return 1;
5684 tmp2 = neon_get_scalar(size, rm);
5685 /* We need a copy of tmp2 because gen_neon_mull
5686 * deletes it during pass 0. */
5687 tmp4 = tcg_temp_new_i32();
5688 tcg_gen_mov_i32(tmp4, tmp2);
5689 tmp3 = neon_load_reg(rn, 1);
5691 for (pass = 0; pass < 2; pass++) {
5692 if (pass == 0) {
5693 tmp = neon_load_reg(rn, 0);
5694 } else {
5695 tmp = tmp3;
5696 tmp2 = tmp4;
5698 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5699 if (op != 11) {
5700 neon_load_reg64(cpu_V1, rd + pass);
5702 switch (op) {
5703 case 6:
5704 gen_neon_negl(cpu_V0, size);
5705 /* Fall through */
5706 case 2:
5707 gen_neon_addl(size);
5708 break;
5709 case 3: case 7:
5710 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5711 if (op == 7) {
5712 gen_neon_negl(cpu_V0, size);
5714 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5715 break;
5716 case 10:
5717 /* no-op */
5718 break;
5719 case 11:
5720 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5721 break;
5722 default:
5723 abort();
5725 neon_store_reg64(cpu_V0, rd + pass);
5729 break;
5730 default: /* 14 and 15 are RESERVED */
5731 return 1;
5734 } else { /* size == 3 */
5735 if (!u) {
5736 /* Extract. */
5737 imm = (insn >> 8) & 0xf;
5739 if (imm > 7 && !q)
5740 return 1;
5742 if (q && ((rd | rn | rm) & 1)) {
5743 return 1;
5746 if (imm == 0) {
5747 neon_load_reg64(cpu_V0, rn);
5748 if (q) {
5749 neon_load_reg64(cpu_V1, rn + 1);
5751 } else if (imm == 8) {
5752 neon_load_reg64(cpu_V0, rn + 1);
5753 if (q) {
5754 neon_load_reg64(cpu_V1, rm);
5756 } else if (q) {
5757 tmp64 = tcg_temp_new_i64();
5758 if (imm < 8) {
5759 neon_load_reg64(cpu_V0, rn);
5760 neon_load_reg64(tmp64, rn + 1);
5761 } else {
5762 neon_load_reg64(cpu_V0, rn + 1);
5763 neon_load_reg64(tmp64, rm);
5765 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5766 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
5767 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5768 if (imm < 8) {
5769 neon_load_reg64(cpu_V1, rm);
5770 } else {
5771 neon_load_reg64(cpu_V1, rm + 1);
5772 imm -= 8;
5774 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5775 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
5776 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
5777 tcg_temp_free_i64(tmp64);
5778 } else {
5779 /* BUGFIX */
5780 neon_load_reg64(cpu_V0, rn);
5781 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
5782 neon_load_reg64(cpu_V1, rm);
5783 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5784 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5786 neon_store_reg64(cpu_V0, rd);
5787 if (q) {
5788 neon_store_reg64(cpu_V1, rd + 1);
5790 } else if ((insn & (1 << 11)) == 0) {
5791 /* Two register misc. */
5792 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5793 size = (insn >> 18) & 3;
5794 /* UNDEF for unknown op values and bad op-size combinations */
5795 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
5796 return 1;
5798 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
5799 q && ((rm | rd) & 1)) {
5800 return 1;
5802 switch (op) {
5803 case NEON_2RM_VREV64:
5804 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5805 tmp = neon_load_reg(rm, pass * 2);
5806 tmp2 = neon_load_reg(rm, pass * 2 + 1);
5807 switch (size) {
5808 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5809 case 1: gen_swap_half(tmp); break;
5810 case 2: /* no-op */ break;
5811 default: abort();
5813 neon_store_reg(rd, pass * 2 + 1, tmp);
5814 if (size == 2) {
5815 neon_store_reg(rd, pass * 2, tmp2);
5816 } else {
5817 switch (size) {
5818 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
5819 case 1: gen_swap_half(tmp2); break;
5820 default: abort();
5822 neon_store_reg(rd, pass * 2, tmp2);
5825 break;
5826 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
5827 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
5828 for (pass = 0; pass < q + 1; pass++) {
5829 tmp = neon_load_reg(rm, pass * 2);
5830 gen_neon_widen(cpu_V0, tmp, size, op & 1);
5831 tmp = neon_load_reg(rm, pass * 2 + 1);
5832 gen_neon_widen(cpu_V1, tmp, size, op & 1);
5833 switch (size) {
5834 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5835 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5836 case 2: tcg_gen_add_i64(CPU_V001); break;
5837 default: abort();
5839 if (op >= NEON_2RM_VPADAL) {
5840 /* Accumulate. */
5841 neon_load_reg64(cpu_V1, rd + pass);
5842 gen_neon_addl(size);
5844 neon_store_reg64(cpu_V0, rd + pass);
5846 break;
5847 case NEON_2RM_VTRN:
5848 if (size == 2) {
5849 int n;
5850 for (n = 0; n < (q ? 4 : 2); n += 2) {
5851 tmp = neon_load_reg(rm, n);
5852 tmp2 = neon_load_reg(rd, n + 1);
5853 neon_store_reg(rm, n, tmp2);
5854 neon_store_reg(rd, n + 1, tmp);
5856 } else {
5857 goto elementwise;
5859 break;
5860 case NEON_2RM_VUZP:
5861 if (gen_neon_unzip(rd, rm, size, q)) {
5862 return 1;
5864 break;
5865 case NEON_2RM_VZIP:
5866 if (gen_neon_zip(rd, rm, size, q)) {
5867 return 1;
5869 break;
5870 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
5871 /* also VQMOVUN; op field and mnemonics don't line up */
5872 if (rm & 1) {
5873 return 1;
5875 TCGV_UNUSED(tmp2);
5876 for (pass = 0; pass < 2; pass++) {
5877 neon_load_reg64(cpu_V0, rm + pass);
5878 tmp = tcg_temp_new_i32();
5879 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
5880 tmp, cpu_V0);
5881 if (pass == 0) {
5882 tmp2 = tmp;
5883 } else {
5884 neon_store_reg(rd, 0, tmp2);
5885 neon_store_reg(rd, 1, tmp);
5888 break;
5889 case NEON_2RM_VSHLL:
5890 if (q || (rd & 1)) {
5891 return 1;
5893 tmp = neon_load_reg(rm, 0);
5894 tmp2 = neon_load_reg(rm, 1);
5895 for (pass = 0; pass < 2; pass++) {
5896 if (pass == 1)
5897 tmp = tmp2;
5898 gen_neon_widen(cpu_V0, tmp, size, 1);
5899 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
5900 neon_store_reg64(cpu_V0, rd + pass);
5902 break;
5903 case NEON_2RM_VCVT_F16_F32:
5904 if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
5905 q || (rm & 1)) {
5906 return 1;
5908 tmp = tcg_temp_new_i32();
5909 tmp2 = tcg_temp_new_i32();
5910 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
5911 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5912 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
5913 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
5914 tcg_gen_shli_i32(tmp2, tmp2, 16);
5915 tcg_gen_or_i32(tmp2, tmp2, tmp);
5916 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
5917 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5918 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
5919 neon_store_reg(rd, 0, tmp2);
5920 tmp2 = tcg_temp_new_i32();
5921 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
5922 tcg_gen_shli_i32(tmp2, tmp2, 16);
5923 tcg_gen_or_i32(tmp2, tmp2, tmp);
5924 neon_store_reg(rd, 1, tmp2);
5925 tcg_temp_free_i32(tmp);
5926 break;
5927 case NEON_2RM_VCVT_F32_F16:
5928 if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
5929 q || (rd & 1)) {
5930 return 1;
5932 tmp3 = tcg_temp_new_i32();
5933 tmp = neon_load_reg(rm, 0);
5934 tmp2 = neon_load_reg(rm, 1);
5935 tcg_gen_ext16u_i32(tmp3, tmp);
5936 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5937 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
5938 tcg_gen_shri_i32(tmp3, tmp, 16);
5939 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5940 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
5941 tcg_temp_free_i32(tmp);
5942 tcg_gen_ext16u_i32(tmp3, tmp2);
5943 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5944 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
5945 tcg_gen_shri_i32(tmp3, tmp2, 16);
5946 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5947 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
5948 tcg_temp_free_i32(tmp2);
5949 tcg_temp_free_i32(tmp3);
5950 break;
5951 default:
5952 elementwise:
5953 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5954 if (neon_2rm_is_float_op(op)) {
5955 tcg_gen_ld_f32(cpu_F0s, cpu_env,
5956 neon_reg_offset(rm, pass));
5957 TCGV_UNUSED(tmp);
5958 } else {
5959 tmp = neon_load_reg(rm, pass);
5961 switch (op) {
5962 case NEON_2RM_VREV32:
5963 switch (size) {
5964 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5965 case 1: gen_swap_half(tmp); break;
5966 default: abort();
5968 break;
5969 case NEON_2RM_VREV16:
5970 gen_rev16(tmp);
5971 break;
5972 case NEON_2RM_VCLS:
5973 switch (size) {
5974 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
5975 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
5976 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
5977 default: abort();
5979 break;
5980 case NEON_2RM_VCLZ:
5981 switch (size) {
5982 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
5983 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
5984 case 2: gen_helper_clz(tmp, tmp); break;
5985 default: abort();
5987 break;
5988 case NEON_2RM_VCNT:
5989 gen_helper_neon_cnt_u8(tmp, tmp);
5990 break;
5991 case NEON_2RM_VMVN:
5992 tcg_gen_not_i32(tmp, tmp);
5993 break;
5994 case NEON_2RM_VQABS:
5995 switch (size) {
5996 case 0:
5997 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
5998 break;
5999 case 1:
6000 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
6001 break;
6002 case 2:
6003 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
6004 break;
6005 default: abort();
6007 break;
6008 case NEON_2RM_VQNEG:
6009 switch (size) {
6010 case 0:
6011 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
6012 break;
6013 case 1:
6014 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
6015 break;
6016 case 2:
6017 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
6018 break;
6019 default: abort();
6021 break;
6022 case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
6023 tmp2 = tcg_const_i32(0);
6024 switch(size) {
6025 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
6026 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
6027 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
6028 default: abort();
6030 tcg_temp_free(tmp2);
6031 if (op == NEON_2RM_VCLE0) {
6032 tcg_gen_not_i32(tmp, tmp);
6034 break;
6035 case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
6036 tmp2 = tcg_const_i32(0);
6037 switch(size) {
6038 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
6039 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
6040 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
6041 default: abort();
6043 tcg_temp_free(tmp2);
6044 if (op == NEON_2RM_VCLT0) {
6045 tcg_gen_not_i32(tmp, tmp);
6047 break;
6048 case NEON_2RM_VCEQ0:
6049 tmp2 = tcg_const_i32(0);
6050 switch(size) {
6051 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
6052 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
6053 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
6054 default: abort();
6056 tcg_temp_free(tmp2);
6057 break;
6058 case NEON_2RM_VABS:
6059 switch(size) {
6060 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
6061 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
6062 case 2: tcg_gen_abs_i32(tmp, tmp); break;
6063 default: abort();
6065 break;
6066 case NEON_2RM_VNEG:
6067 tmp2 = tcg_const_i32(0);
6068 gen_neon_rsb(size, tmp, tmp2);
6069 tcg_temp_free(tmp2);
6070 break;
6071 case NEON_2RM_VCGT0_F:
6073 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6074 tmp2 = tcg_const_i32(0);
6075 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
6076 tcg_temp_free(tmp2);
6077 tcg_temp_free_ptr(fpstatus);
6078 break;
6080 case NEON_2RM_VCGE0_F:
6082 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6083 tmp2 = tcg_const_i32(0);
6084 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
6085 tcg_temp_free(tmp2);
6086 tcg_temp_free_ptr(fpstatus);
6087 break;
6089 case NEON_2RM_VCEQ0_F:
6091 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6092 tmp2 = tcg_const_i32(0);
6093 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
6094 tcg_temp_free(tmp2);
6095 tcg_temp_free_ptr(fpstatus);
6096 break;
6098 case NEON_2RM_VCLE0_F:
6100 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6101 tmp2 = tcg_const_i32(0);
6102 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
6103 tcg_temp_free(tmp2);
6104 tcg_temp_free_ptr(fpstatus);
6105 break;
6107 case NEON_2RM_VCLT0_F:
6109 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6110 tmp2 = tcg_const_i32(0);
6111 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
6112 tcg_temp_free(tmp2);
6113 tcg_temp_free_ptr(fpstatus);
6114 break;
6116 case NEON_2RM_VABS_F:
6117 gen_vfp_abs(0);
6118 break;
6119 case NEON_2RM_VNEG_F:
6120 gen_vfp_neg(0);
6121 break;
6122 case NEON_2RM_VSWP:
6123 tmp2 = neon_load_reg(rd, pass);
6124 neon_store_reg(rm, pass, tmp2);
6125 break;
6126 case NEON_2RM_VTRN:
6127 tmp2 = neon_load_reg(rd, pass);
6128 switch (size) {
6129 case 0: gen_neon_trn_u8(tmp, tmp2); break;
6130 case 1: gen_neon_trn_u16(tmp, tmp2); break;
6131 default: abort();
6133 neon_store_reg(rm, pass, tmp2);
6134 break;
6135 case NEON_2RM_VRECPE:
6136 gen_helper_recpe_u32(tmp, tmp, cpu_env);
6137 break;
6138 case NEON_2RM_VRSQRTE:
6139 gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
6140 break;
6141 case NEON_2RM_VRECPE_F:
6142 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
6143 break;
6144 case NEON_2RM_VRSQRTE_F:
6145 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
6146 break;
6147 case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
6148 gen_vfp_sito(0, 1);
6149 break;
6150 case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
6151 gen_vfp_uito(0, 1);
6152 break;
6153 case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
6154 gen_vfp_tosiz(0, 1);
6155 break;
6156 case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
6157 gen_vfp_touiz(0, 1);
6158 break;
6159 default:
6160 /* Reserved op values were caught by the
6161 * neon_2rm_sizes[] check earlier.
6163 abort();
6165 if (neon_2rm_is_float_op(op)) {
6166 tcg_gen_st_f32(cpu_F0s, cpu_env,
6167 neon_reg_offset(rd, pass));
6168 } else {
6169 neon_store_reg(rd, pass, tmp);
6172 break;
6174 } else if ((insn & (1 << 10)) == 0) {
6175 /* VTBL, VTBX. */
6176 int n = ((insn >> 8) & 3) + 1;
6177 if ((rn + n) > 32) {
6178 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
6179 * helper function running off the end of the register file.
6181 return 1;
6183 n <<= 3;
6184 if (insn & (1 << 6)) {
6185 tmp = neon_load_reg(rd, 0);
6186 } else {
6187 tmp = tcg_temp_new_i32();
6188 tcg_gen_movi_i32(tmp, 0);
6190 tmp2 = neon_load_reg(rm, 0);
6191 tmp4 = tcg_const_i32(rn);
6192 tmp5 = tcg_const_i32(n);
6193 gen_helper_neon_tbl(tmp2, cpu_env, tmp2, tmp, tmp4, tmp5);
6194 tcg_temp_free_i32(tmp);
6195 if (insn & (1 << 6)) {
6196 tmp = neon_load_reg(rd, 1);
6197 } else {
6198 tmp = tcg_temp_new_i32();
6199 tcg_gen_movi_i32(tmp, 0);
6201 tmp3 = neon_load_reg(rm, 1);
6202 gen_helper_neon_tbl(tmp3, cpu_env, tmp3, tmp, tmp4, tmp5);
6203 tcg_temp_free_i32(tmp5);
6204 tcg_temp_free_i32(tmp4);
6205 neon_store_reg(rd, 0, tmp2);
6206 neon_store_reg(rd, 1, tmp3);
6207 tcg_temp_free_i32(tmp);
6208 } else if ((insn & 0x380) == 0) {
6209 /* VDUP */
6210 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
6211 return 1;
6213 if (insn & (1 << 19)) {
6214 tmp = neon_load_reg(rm, 1);
6215 } else {
6216 tmp = neon_load_reg(rm, 0);
6218 if (insn & (1 << 16)) {
6219 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
6220 } else if (insn & (1 << 17)) {
6221 if ((insn >> 18) & 1)
6222 gen_neon_dup_high16(tmp);
6223 else
6224 gen_neon_dup_low16(tmp);
6226 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6227 tmp2 = tcg_temp_new_i32();
6228 tcg_gen_mov_i32(tmp2, tmp);
6229 neon_store_reg(rd, pass, tmp2);
6231 tcg_temp_free_i32(tmp);
6232 } else {
6233 return 1;
6237 return 0;
6240 static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
6242 int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
6243 const ARMCPRegInfo *ri;
6244 ARMCPU *cpu = arm_env_get_cpu(env);
6246 cpnum = (insn >> 8) & 0xf;
6247 if (arm_feature(env, ARM_FEATURE_XSCALE)
6248 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
6249 return 1;
6251 /* First check for coprocessor space used for actual instructions */
6252 switch (cpnum) {
6253 case 0:
6254 case 1:
6255 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
6256 return disas_iwmmxt_insn(env, s, insn);
6257 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
6258 return disas_dsp_insn(env, s, insn);
6260 return 1;
6261 case 10:
6262 case 11:
6263 return disas_vfp_insn (env, s, insn);
6264 default:
6265 break;
6268 /* Otherwise treat as a generic register access */
6269 is64 = (insn & (1 << 25)) == 0;
6270 if (!is64 && ((insn & (1 << 4)) == 0)) {
6271 /* cdp */
6272 return 1;
6275 crm = insn & 0xf;
6276 if (is64) {
6277 crn = 0;
6278 opc1 = (insn >> 4) & 0xf;
6279 opc2 = 0;
6280 rt2 = (insn >> 16) & 0xf;
6281 } else {
6282 crn = (insn >> 16) & 0xf;
6283 opc1 = (insn >> 21) & 7;
6284 opc2 = (insn >> 5) & 7;
6285 rt2 = 0;
6287 isread = (insn >> 20) & 1;
6288 rt = (insn >> 12) & 0xf;
6290 ri = get_arm_cp_reginfo(cpu,
6291 ENCODE_CP_REG(cpnum, is64, crn, crm, opc1, opc2));
6292 if (ri) {
6293 /* Check access permissions */
6294 if (!cp_access_ok(env, ri, isread)) {
6295 return 1;
6298 /* Handle special cases first */
6299 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
6300 case ARM_CP_NOP:
6301 return 0;
6302 case ARM_CP_WFI:
6303 if (isread) {
6304 return 1;
6306 gen_set_pc_im(s->pc);
6307 s->is_jmp = DISAS_WFI;
6308 return 0;
6309 default:
6310 break;
6313 if (isread) {
6314 /* Read */
6315 if (is64) {
6316 TCGv_i64 tmp64;
6317 TCGv_i32 tmp;
6318 if (ri->type & ARM_CP_CONST) {
6319 tmp64 = tcg_const_i64(ri->resetvalue);
6320 } else if (ri->readfn) {
6321 TCGv_ptr tmpptr;
6322 gen_set_pc_im(s->pc);
6323 tmp64 = tcg_temp_new_i64();
6324 tmpptr = tcg_const_ptr(ri);
6325 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
6326 tcg_temp_free_ptr(tmpptr);
6327 } else {
6328 tmp64 = tcg_temp_new_i64();
6329 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
6331 tmp = tcg_temp_new_i32();
6332 tcg_gen_trunc_i64_i32(tmp, tmp64);
6333 store_reg(s, rt, tmp);
6334 tcg_gen_shri_i64(tmp64, tmp64, 32);
6335 tmp = tcg_temp_new_i32();
6336 tcg_gen_trunc_i64_i32(tmp, tmp64);
6337 tcg_temp_free_i64(tmp64);
6338 store_reg(s, rt2, tmp);
6339 } else {
6340 TCGv tmp;
6341 if (ri->type & ARM_CP_CONST) {
6342 tmp = tcg_const_i32(ri->resetvalue);
6343 } else if (ri->readfn) {
6344 TCGv_ptr tmpptr;
6345 gen_set_pc_im(s->pc);
6346 tmp = tcg_temp_new_i32();
6347 tmpptr = tcg_const_ptr(ri);
6348 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
6349 tcg_temp_free_ptr(tmpptr);
6350 } else {
6351 tmp = load_cpu_offset(ri->fieldoffset);
6353 if (rt == 15) {
6354 /* Destination register of r15 for 32 bit loads sets
6355 * the condition codes from the high 4 bits of the value
6357 gen_set_nzcv(tmp);
6358 tcg_temp_free_i32(tmp);
6359 } else {
6360 store_reg(s, rt, tmp);
6363 } else {
6364 /* Write */
6365 if (ri->type & ARM_CP_CONST) {
6366 /* If not forbidden by access permissions, treat as WI */
6367 return 0;
6370 if (is64) {
6371 TCGv tmplo, tmphi;
6372 TCGv_i64 tmp64 = tcg_temp_new_i64();
6373 tmplo = load_reg(s, rt);
6374 tmphi = load_reg(s, rt2);
6375 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
6376 tcg_temp_free_i32(tmplo);
6377 tcg_temp_free_i32(tmphi);
6378 if (ri->writefn) {
6379 TCGv_ptr tmpptr = tcg_const_ptr(ri);
6380 gen_set_pc_im(s->pc);
6381 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
6382 tcg_temp_free_ptr(tmpptr);
6383 } else {
6384 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
6386 tcg_temp_free_i64(tmp64);
6387 } else {
6388 if (ri->writefn) {
6389 TCGv tmp;
6390 TCGv_ptr tmpptr;
6391 gen_set_pc_im(s->pc);
6392 tmp = load_reg(s, rt);
6393 tmpptr = tcg_const_ptr(ri);
6394 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
6395 tcg_temp_free_ptr(tmpptr);
6396 tcg_temp_free_i32(tmp);
6397 } else {
6398 TCGv tmp = load_reg(s, rt);
6399 store_cpu_offset(tmp, ri->fieldoffset);
6402 /* We default to ending the TB on a coprocessor register write,
6403 * but allow this to be suppressed by the register definition
6404 * (usually only necessary to work around guest bugs).
6406 if (!(ri->type & ARM_CP_SUPPRESS_TB_END)) {
6407 gen_lookup_tb(s);
6410 return 0;
6413 return 1;
6417 /* Store a 64-bit value to a register pair. Clobbers val. */
6418 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
6420 TCGv tmp;
6421 tmp = tcg_temp_new_i32();
6422 tcg_gen_trunc_i64_i32(tmp, val);
6423 store_reg(s, rlow, tmp);
6424 tmp = tcg_temp_new_i32();
6425 tcg_gen_shri_i64(val, val, 32);
6426 tcg_gen_trunc_i64_i32(tmp, val);
6427 store_reg(s, rhigh, tmp);
6430 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
6431 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
6433 TCGv_i64 tmp;
6434 TCGv tmp2;
6436 /* Load value and extend to 64 bits. */
6437 tmp = tcg_temp_new_i64();
6438 tmp2 = load_reg(s, rlow);
6439 tcg_gen_extu_i32_i64(tmp, tmp2);
6440 tcg_temp_free_i32(tmp2);
6441 tcg_gen_add_i64(val, val, tmp);
6442 tcg_temp_free_i64(tmp);
6445 /* load and add a 64-bit value from a register pair. */
6446 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
6448 TCGv_i64 tmp;
6449 TCGv tmpl;
6450 TCGv tmph;
6452 /* Load 64-bit value rd:rn. */
6453 tmpl = load_reg(s, rlow);
6454 tmph = load_reg(s, rhigh);
6455 tmp = tcg_temp_new_i64();
6456 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
6457 tcg_temp_free_i32(tmpl);
6458 tcg_temp_free_i32(tmph);
6459 tcg_gen_add_i64(val, val, tmp);
6460 tcg_temp_free_i64(tmp);
6463 /* Set N and Z flags from hi|lo. */
6464 static void gen_logicq_cc(TCGv lo, TCGv hi)
6466 tcg_gen_mov_i32(cpu_NF, hi);
6467 tcg_gen_or_i32(cpu_ZF, lo, hi);
6470 /* Load/Store exclusive instructions are implemented by remembering
6471 the value/address loaded, and seeing if these are the same
6472 when the store is performed. This should be sufficient to implement
6473 the architecturally mandated semantics, and avoids having to monitor
6474 regular stores.
6476 In system emulation mode only one CPU will be running at once, so
6477 this sequence is effectively atomic. In user emulation mode we
6478 throw an exception and handle the atomic operation elsewhere. */
6479 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
6480 TCGv addr, int size)
6482 TCGv tmp;
6484 switch (size) {
6485 case 0:
6486 tmp = gen_ld8u(addr, IS_USER(s));
6487 break;
6488 case 1:
6489 tmp = gen_ld16u(addr, IS_USER(s));
6490 break;
6491 case 2:
6492 case 3:
6493 tmp = gen_ld32(addr, IS_USER(s));
6494 break;
6495 default:
6496 abort();
6498 tcg_gen_mov_i32(cpu_exclusive_val, tmp);
6499 store_reg(s, rt, tmp);
6500 if (size == 3) {
6501 TCGv tmp2 = tcg_temp_new_i32();
6502 tcg_gen_addi_i32(tmp2, addr, 4);
6503 tmp = gen_ld32(tmp2, IS_USER(s));
6504 tcg_temp_free_i32(tmp2);
6505 tcg_gen_mov_i32(cpu_exclusive_high, tmp);
6506 store_reg(s, rt2, tmp);
6508 tcg_gen_mov_i32(cpu_exclusive_addr, addr);
6511 static void gen_clrex(DisasContext *s)
6513 tcg_gen_movi_i32(cpu_exclusive_addr, -1);
6516 #ifdef CONFIG_USER_ONLY
6517 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
6518 TCGv addr, int size)
6520 tcg_gen_mov_i32(cpu_exclusive_test, addr);
6521 tcg_gen_movi_i32(cpu_exclusive_info,
6522 size | (rd << 4) | (rt << 8) | (rt2 << 12));
6523 gen_exception_insn(s, 4, EXCP_STREX);
6525 #else
6526 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
6527 TCGv addr, int size)
6529 TCGv tmp;
6530 int done_label;
6531 int fail_label;
6533 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
6534 [addr] = {Rt};
6535 {Rd} = 0;
6536 } else {
6537 {Rd} = 1;
6538 } */
6539 fail_label = gen_new_label();
6540 done_label = gen_new_label();
6541 tcg_gen_brcond_i32(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
6542 switch (size) {
6543 case 0:
6544 tmp = gen_ld8u(addr, IS_USER(s));
6545 break;
6546 case 1:
6547 tmp = gen_ld16u(addr, IS_USER(s));
6548 break;
6549 case 2:
6550 case 3:
6551 tmp = gen_ld32(addr, IS_USER(s));
6552 break;
6553 default:
6554 abort();
6556 tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label);
6557 tcg_temp_free_i32(tmp);
6558 if (size == 3) {
6559 TCGv tmp2 = tcg_temp_new_i32();
6560 tcg_gen_addi_i32(tmp2, addr, 4);
6561 tmp = gen_ld32(tmp2, IS_USER(s));
6562 tcg_temp_free_i32(tmp2);
6563 tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_high, fail_label);
6564 tcg_temp_free_i32(tmp);
6566 tmp = load_reg(s, rt);
6567 switch (size) {
6568 case 0:
6569 gen_st8(tmp, addr, IS_USER(s));
6570 break;
6571 case 1:
6572 gen_st16(tmp, addr, IS_USER(s));
6573 break;
6574 case 2:
6575 case 3:
6576 gen_st32(tmp, addr, IS_USER(s));
6577 break;
6578 default:
6579 abort();
6581 if (size == 3) {
6582 tcg_gen_addi_i32(addr, addr, 4);
6583 tmp = load_reg(s, rt2);
6584 gen_st32(tmp, addr, IS_USER(s));
6586 tcg_gen_movi_i32(cpu_R[rd], 0);
6587 tcg_gen_br(done_label);
6588 gen_set_label(fail_label);
6589 tcg_gen_movi_i32(cpu_R[rd], 1);
6590 gen_set_label(done_label);
6591 tcg_gen_movi_i32(cpu_exclusive_addr, -1);
6593 #endif
6595 static void disas_arm_insn(CPUARMState * env, DisasContext *s)
6597 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
6598 TCGv tmp;
6599 TCGv tmp2;
6600 TCGv tmp3;
6601 TCGv addr;
6602 TCGv_i64 tmp64;
6604 insn = arm_ldl_code(env, s->pc, s->bswap_code);
6605 s->pc += 4;
6607 /* M variants do not implement ARM mode. */
6608 if (IS_M(env))
6609 goto illegal_op;
6610 cond = insn >> 28;
6611 if (cond == 0xf){
6612 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
6613 * choose to UNDEF. In ARMv5 and above the space is used
6614 * for miscellaneous unconditional instructions.
6616 ARCH(5);
6618 /* Unconditional instructions. */
6619 if (((insn >> 25) & 7) == 1) {
6620 /* NEON Data processing. */
6621 if (!arm_feature(env, ARM_FEATURE_NEON))
6622 goto illegal_op;
6624 if (disas_neon_data_insn(env, s, insn))
6625 goto illegal_op;
6626 return;
6628 if ((insn & 0x0f100000) == 0x04000000) {
6629 /* NEON load/store. */
6630 if (!arm_feature(env, ARM_FEATURE_NEON))
6631 goto illegal_op;
6633 if (disas_neon_ls_insn(env, s, insn))
6634 goto illegal_op;
6635 return;
6637 if (((insn & 0x0f30f000) == 0x0510f000) ||
6638 ((insn & 0x0f30f010) == 0x0710f000)) {
6639 if ((insn & (1 << 22)) == 0) {
6640 /* PLDW; v7MP */
6641 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
6642 goto illegal_op;
6645 /* Otherwise PLD; v5TE+ */
6646 ARCH(5TE);
6647 return;
6649 if (((insn & 0x0f70f000) == 0x0450f000) ||
6650 ((insn & 0x0f70f010) == 0x0650f000)) {
6651 ARCH(7);
6652 return; /* PLI; V7 */
6654 if (((insn & 0x0f700000) == 0x04100000) ||
6655 ((insn & 0x0f700010) == 0x06100000)) {
6656 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
6657 goto illegal_op;
6659 return; /* v7MP: Unallocated memory hint: must NOP */
6662 if ((insn & 0x0ffffdff) == 0x01010000) {
6663 ARCH(6);
6664 /* setend */
6665 if (((insn >> 9) & 1) != s->bswap_code) {
6666 /* Dynamic endianness switching not implemented. */
6667 goto illegal_op;
6669 return;
6670 } else if ((insn & 0x0fffff00) == 0x057ff000) {
6671 switch ((insn >> 4) & 0xf) {
6672 case 1: /* clrex */
6673 ARCH(6K);
6674 gen_clrex(s);
6675 return;
6676 case 4: /* dsb */
6677 case 5: /* dmb */
6678 case 6: /* isb */
6679 ARCH(7);
6680 /* We don't emulate caches so these are a no-op. */
6681 return;
6682 default:
6683 goto illegal_op;
6685 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
6686 /* srs */
6687 int32_t offset;
6688 if (IS_USER(s))
6689 goto illegal_op;
6690 ARCH(6);
6691 op1 = (insn & 0x1f);
6692 addr = tcg_temp_new_i32();
6693 tmp = tcg_const_i32(op1);
6694 gen_helper_get_r13_banked(addr, cpu_env, tmp);
6695 tcg_temp_free_i32(tmp);
6696 i = (insn >> 23) & 3;
6697 switch (i) {
6698 case 0: offset = -4; break; /* DA */
6699 case 1: offset = 0; break; /* IA */
6700 case 2: offset = -8; break; /* DB */
6701 case 3: offset = 4; break; /* IB */
6702 default: abort();
6704 if (offset)
6705 tcg_gen_addi_i32(addr, addr, offset);
6706 tmp = load_reg(s, 14);
6707 gen_st32(tmp, addr, 0);
6708 tmp = load_cpu_field(spsr);
6709 tcg_gen_addi_i32(addr, addr, 4);
6710 gen_st32(tmp, addr, 0);
6711 if (insn & (1 << 21)) {
6712 /* Base writeback. */
6713 switch (i) {
6714 case 0: offset = -8; break;
6715 case 1: offset = 4; break;
6716 case 2: offset = -4; break;
6717 case 3: offset = 0; break;
6718 default: abort();
6720 if (offset)
6721 tcg_gen_addi_i32(addr, addr, offset);
6722 tmp = tcg_const_i32(op1);
6723 gen_helper_set_r13_banked(cpu_env, tmp, addr);
6724 tcg_temp_free_i32(tmp);
6725 tcg_temp_free_i32(addr);
6726 } else {
6727 tcg_temp_free_i32(addr);
6729 return;
6730 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
6731 /* rfe */
6732 int32_t offset;
6733 if (IS_USER(s))
6734 goto illegal_op;
6735 ARCH(6);
6736 rn = (insn >> 16) & 0xf;
6737 addr = load_reg(s, rn);
6738 i = (insn >> 23) & 3;
6739 switch (i) {
6740 case 0: offset = -4; break; /* DA */
6741 case 1: offset = 0; break; /* IA */
6742 case 2: offset = -8; break; /* DB */
6743 case 3: offset = 4; break; /* IB */
6744 default: abort();
6746 if (offset)
6747 tcg_gen_addi_i32(addr, addr, offset);
6748 /* Load PC into tmp and CPSR into tmp2. */
6749 tmp = gen_ld32(addr, 0);
6750 tcg_gen_addi_i32(addr, addr, 4);
6751 tmp2 = gen_ld32(addr, 0);
6752 if (insn & (1 << 21)) {
6753 /* Base writeback. */
6754 switch (i) {
6755 case 0: offset = -8; break;
6756 case 1: offset = 4; break;
6757 case 2: offset = -4; break;
6758 case 3: offset = 0; break;
6759 default: abort();
6761 if (offset)
6762 tcg_gen_addi_i32(addr, addr, offset);
6763 store_reg(s, rn, addr);
6764 } else {
6765 tcg_temp_free_i32(addr);
6767 gen_rfe(s, tmp, tmp2);
6768 return;
6769 } else if ((insn & 0x0e000000) == 0x0a000000) {
6770 /* branch link and change to thumb (blx <offset>) */
6771 int32_t offset;
6773 val = (uint32_t)s->pc;
6774 tmp = tcg_temp_new_i32();
6775 tcg_gen_movi_i32(tmp, val);
6776 store_reg(s, 14, tmp);
6777 /* Sign-extend the 24-bit offset */
6778 offset = (((int32_t)insn) << 8) >> 8;
6779 /* offset * 4 + bit24 * 2 + (thumb bit) */
6780 val += (offset << 2) | ((insn >> 23) & 2) | 1;
6781 /* pipeline offset */
6782 val += 4;
6783 /* protected by ARCH(5); above, near the start of uncond block */
6784 gen_bx_im(s, val);
6785 return;
6786 } else if ((insn & 0x0e000f00) == 0x0c000100) {
6787 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
6788 /* iWMMXt register transfer. */
6789 if (env->cp15.c15_cpar & (1 << 1))
6790 if (!disas_iwmmxt_insn(env, s, insn))
6791 return;
6793 } else if ((insn & 0x0fe00000) == 0x0c400000) {
6794 /* Coprocessor double register transfer. */
6795 ARCH(5TE);
6796 } else if ((insn & 0x0f000010) == 0x0e000010) {
6797 /* Additional coprocessor register transfer. */
6798 } else if ((insn & 0x0ff10020) == 0x01000000) {
6799 uint32_t mask;
6800 uint32_t val;
6801 /* cps (privileged) */
6802 if (IS_USER(s))
6803 return;
6804 mask = val = 0;
6805 if (insn & (1 << 19)) {
6806 if (insn & (1 << 8))
6807 mask |= CPSR_A;
6808 if (insn & (1 << 7))
6809 mask |= CPSR_I;
6810 if (insn & (1 << 6))
6811 mask |= CPSR_F;
6812 if (insn & (1 << 18))
6813 val |= mask;
6815 if (insn & (1 << 17)) {
6816 mask |= CPSR_M;
6817 val |= (insn & 0x1f);
6819 if (mask) {
6820 gen_set_psr_im(s, mask, 0, val);
6822 return;
6824 goto illegal_op;
6826 if (cond != 0xe) {
6827 /* if not always execute, we generate a conditional jump to
6828 next instruction */
6829 s->condlabel = gen_new_label();
6830 gen_test_cc(cond ^ 1, s->condlabel);
6831 s->condjmp = 1;
6833 if ((insn & 0x0f900000) == 0x03000000) {
6834 if ((insn & (1 << 21)) == 0) {
6835 ARCH(6T2);
6836 rd = (insn >> 12) & 0xf;
6837 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
6838 if ((insn & (1 << 22)) == 0) {
6839 /* MOVW */
6840 tmp = tcg_temp_new_i32();
6841 tcg_gen_movi_i32(tmp, val);
6842 } else {
6843 /* MOVT */
6844 tmp = load_reg(s, rd);
6845 tcg_gen_ext16u_i32(tmp, tmp);
6846 tcg_gen_ori_i32(tmp, tmp, val << 16);
6848 store_reg(s, rd, tmp);
6849 } else {
6850 if (((insn >> 12) & 0xf) != 0xf)
6851 goto illegal_op;
6852 if (((insn >> 16) & 0xf) == 0) {
6853 gen_nop_hint(s, insn & 0xff);
6854 } else {
6855 /* CPSR = immediate */
6856 val = insn & 0xff;
6857 shift = ((insn >> 8) & 0xf) * 2;
6858 if (shift)
6859 val = (val >> shift) | (val << (32 - shift));
6860 i = ((insn & (1 << 22)) != 0);
6861 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
6862 goto illegal_op;
6865 } else if ((insn & 0x0f900000) == 0x01000000
6866 && (insn & 0x00000090) != 0x00000090) {
6867 /* miscellaneous instructions */
6868 op1 = (insn >> 21) & 3;
6869 sh = (insn >> 4) & 0xf;
6870 rm = insn & 0xf;
6871 switch (sh) {
6872 case 0x0: /* move program status register */
6873 if (op1 & 1) {
6874 /* PSR = reg */
6875 tmp = load_reg(s, rm);
6876 i = ((op1 & 2) != 0);
6877 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
6878 goto illegal_op;
6879 } else {
6880 /* reg = PSR */
6881 rd = (insn >> 12) & 0xf;
6882 if (op1 & 2) {
6883 if (IS_USER(s))
6884 goto illegal_op;
6885 tmp = load_cpu_field(spsr);
6886 } else {
6887 tmp = tcg_temp_new_i32();
6888 gen_helper_cpsr_read(tmp, cpu_env);
6890 store_reg(s, rd, tmp);
6892 break;
6893 case 0x1:
6894 if (op1 == 1) {
6895 /* branch/exchange thumb (bx). */
6896 ARCH(4T);
6897 tmp = load_reg(s, rm);
6898 gen_bx(s, tmp);
6899 } else if (op1 == 3) {
6900 /* clz */
6901 ARCH(5);
6902 rd = (insn >> 12) & 0xf;
6903 tmp = load_reg(s, rm);
6904 gen_helper_clz(tmp, tmp);
6905 store_reg(s, rd, tmp);
6906 } else {
6907 goto illegal_op;
6909 break;
6910 case 0x2:
6911 if (op1 == 1) {
6912 ARCH(5J); /* bxj */
6913 /* Trivial implementation equivalent to bx. */
6914 tmp = load_reg(s, rm);
6915 gen_bx(s, tmp);
6916 } else {
6917 goto illegal_op;
6919 break;
6920 case 0x3:
6921 if (op1 != 1)
6922 goto illegal_op;
6924 ARCH(5);
6925 /* branch link/exchange thumb (blx) */
6926 tmp = load_reg(s, rm);
6927 tmp2 = tcg_temp_new_i32();
6928 tcg_gen_movi_i32(tmp2, s->pc);
6929 store_reg(s, 14, tmp2);
6930 gen_bx(s, tmp);
6931 break;
6932 case 0x5: /* saturating add/subtract */
6933 ARCH(5TE);
6934 rd = (insn >> 12) & 0xf;
6935 rn = (insn >> 16) & 0xf;
6936 tmp = load_reg(s, rm);
6937 tmp2 = load_reg(s, rn);
6938 if (op1 & 2)
6939 gen_helper_double_saturate(tmp2, cpu_env, tmp2);
6940 if (op1 & 1)
6941 gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2);
6942 else
6943 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
6944 tcg_temp_free_i32(tmp2);
6945 store_reg(s, rd, tmp);
6946 break;
6947 case 7:
6948 /* SMC instruction (op1 == 3)
6949 and undefined instructions (op1 == 0 || op1 == 2)
6950 will trap */
6951 if (op1 != 1) {
6952 goto illegal_op;
6954 /* bkpt */
6955 ARCH(5);
6956 gen_exception_insn(s, 4, EXCP_BKPT);
6957 break;
6958 case 0x8: /* signed multiply */
6959 case 0xa:
6960 case 0xc:
6961 case 0xe:
6962 ARCH(5TE);
6963 rs = (insn >> 8) & 0xf;
6964 rn = (insn >> 12) & 0xf;
6965 rd = (insn >> 16) & 0xf;
6966 if (op1 == 1) {
6967 /* (32 * 16) >> 16 */
6968 tmp = load_reg(s, rm);
6969 tmp2 = load_reg(s, rs);
6970 if (sh & 4)
6971 tcg_gen_sari_i32(tmp2, tmp2, 16);
6972 else
6973 gen_sxth(tmp2);
6974 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6975 tcg_gen_shri_i64(tmp64, tmp64, 16);
6976 tmp = tcg_temp_new_i32();
6977 tcg_gen_trunc_i64_i32(tmp, tmp64);
6978 tcg_temp_free_i64(tmp64);
6979 if ((sh & 2) == 0) {
6980 tmp2 = load_reg(s, rn);
6981 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
6982 tcg_temp_free_i32(tmp2);
6984 store_reg(s, rd, tmp);
6985 } else {
6986 /* 16 * 16 */
6987 tmp = load_reg(s, rm);
6988 tmp2 = load_reg(s, rs);
6989 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
6990 tcg_temp_free_i32(tmp2);
6991 if (op1 == 2) {
6992 tmp64 = tcg_temp_new_i64();
6993 tcg_gen_ext_i32_i64(tmp64, tmp);
6994 tcg_temp_free_i32(tmp);
6995 gen_addq(s, tmp64, rn, rd);
6996 gen_storeq_reg(s, rn, rd, tmp64);
6997 tcg_temp_free_i64(tmp64);
6998 } else {
6999 if (op1 == 0) {
7000 tmp2 = load_reg(s, rn);
7001 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7002 tcg_temp_free_i32(tmp2);
7004 store_reg(s, rd, tmp);
7007 break;
7008 default:
7009 goto illegal_op;
7011 } else if (((insn & 0x0e000000) == 0 &&
7012 (insn & 0x00000090) != 0x90) ||
7013 ((insn & 0x0e000000) == (1 << 25))) {
7014 int set_cc, logic_cc, shiftop;
7016 op1 = (insn >> 21) & 0xf;
7017 set_cc = (insn >> 20) & 1;
7018 logic_cc = table_logic_cc[op1] & set_cc;
7020 /* data processing instruction */
7021 if (insn & (1 << 25)) {
7022 /* immediate operand */
7023 val = insn & 0xff;
7024 shift = ((insn >> 8) & 0xf) * 2;
7025 if (shift) {
7026 val = (val >> shift) | (val << (32 - shift));
7028 tmp2 = tcg_temp_new_i32();
7029 tcg_gen_movi_i32(tmp2, val);
7030 if (logic_cc && shift) {
7031 gen_set_CF_bit31(tmp2);
7033 } else {
7034 /* register */
7035 rm = (insn) & 0xf;
7036 tmp2 = load_reg(s, rm);
7037 shiftop = (insn >> 5) & 3;
7038 if (!(insn & (1 << 4))) {
7039 shift = (insn >> 7) & 0x1f;
7040 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
7041 } else {
7042 rs = (insn >> 8) & 0xf;
7043 tmp = load_reg(s, rs);
7044 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
7047 if (op1 != 0x0f && op1 != 0x0d) {
7048 rn = (insn >> 16) & 0xf;
7049 tmp = load_reg(s, rn);
7050 } else {
7051 TCGV_UNUSED(tmp);
7053 rd = (insn >> 12) & 0xf;
7054 switch(op1) {
7055 case 0x00:
7056 tcg_gen_and_i32(tmp, tmp, tmp2);
7057 if (logic_cc) {
7058 gen_logic_CC(tmp);
7060 store_reg_bx(env, s, rd, tmp);
7061 break;
7062 case 0x01:
7063 tcg_gen_xor_i32(tmp, tmp, tmp2);
7064 if (logic_cc) {
7065 gen_logic_CC(tmp);
7067 store_reg_bx(env, s, rd, tmp);
7068 break;
7069 case 0x02:
7070 if (set_cc && rd == 15) {
7071 /* SUBS r15, ... is used for exception return. */
7072 if (IS_USER(s)) {
7073 goto illegal_op;
7075 gen_sub_CC(tmp, tmp, tmp2);
7076 gen_exception_return(s, tmp);
7077 } else {
7078 if (set_cc) {
7079 gen_sub_CC(tmp, tmp, tmp2);
7080 } else {
7081 tcg_gen_sub_i32(tmp, tmp, tmp2);
7083 store_reg_bx(env, s, rd, tmp);
7085 break;
7086 case 0x03:
7087 if (set_cc) {
7088 gen_sub_CC(tmp, tmp2, tmp);
7089 } else {
7090 tcg_gen_sub_i32(tmp, tmp2, tmp);
7092 store_reg_bx(env, s, rd, tmp);
7093 break;
7094 case 0x04:
7095 if (set_cc) {
7096 gen_add_CC(tmp, tmp, tmp2);
7097 } else {
7098 tcg_gen_add_i32(tmp, tmp, tmp2);
7100 store_reg_bx(env, s, rd, tmp);
7101 break;
7102 case 0x05:
7103 if (set_cc) {
7104 gen_adc_CC(tmp, tmp, tmp2);
7105 } else {
7106 gen_add_carry(tmp, tmp, tmp2);
7108 store_reg_bx(env, s, rd, tmp);
7109 break;
7110 case 0x06:
7111 if (set_cc) {
7112 gen_helper_sbc_cc(tmp, cpu_env, tmp, tmp2);
7113 } else {
7114 gen_sub_carry(tmp, tmp, tmp2);
7116 store_reg_bx(env, s, rd, tmp);
7117 break;
7118 case 0x07:
7119 if (set_cc) {
7120 gen_helper_sbc_cc(tmp, cpu_env, tmp2, tmp);
7121 } else {
7122 gen_sub_carry(tmp, tmp2, tmp);
7124 store_reg_bx(env, s, rd, tmp);
7125 break;
7126 case 0x08:
7127 if (set_cc) {
7128 tcg_gen_and_i32(tmp, tmp, tmp2);
7129 gen_logic_CC(tmp);
7131 tcg_temp_free_i32(tmp);
7132 break;
7133 case 0x09:
7134 if (set_cc) {
7135 tcg_gen_xor_i32(tmp, tmp, tmp2);
7136 gen_logic_CC(tmp);
7138 tcg_temp_free_i32(tmp);
7139 break;
7140 case 0x0a:
7141 if (set_cc) {
7142 gen_sub_CC(tmp, tmp, tmp2);
7144 tcg_temp_free_i32(tmp);
7145 break;
7146 case 0x0b:
7147 if (set_cc) {
7148 gen_add_CC(tmp, tmp, tmp2);
7150 tcg_temp_free_i32(tmp);
7151 break;
7152 case 0x0c:
7153 tcg_gen_or_i32(tmp, tmp, tmp2);
7154 if (logic_cc) {
7155 gen_logic_CC(tmp);
7157 store_reg_bx(env, s, rd, tmp);
7158 break;
7159 case 0x0d:
7160 if (logic_cc && rd == 15) {
7161 /* MOVS r15, ... is used for exception return. */
7162 if (IS_USER(s)) {
7163 goto illegal_op;
7165 gen_exception_return(s, tmp2);
7166 } else {
7167 if (logic_cc) {
7168 gen_logic_CC(tmp2);
7170 store_reg_bx(env, s, rd, tmp2);
7172 break;
7173 case 0x0e:
7174 tcg_gen_andc_i32(tmp, tmp, tmp2);
7175 if (logic_cc) {
7176 gen_logic_CC(tmp);
7178 store_reg_bx(env, s, rd, tmp);
7179 break;
7180 default:
7181 case 0x0f:
7182 tcg_gen_not_i32(tmp2, tmp2);
7183 if (logic_cc) {
7184 gen_logic_CC(tmp2);
7186 store_reg_bx(env, s, rd, tmp2);
7187 break;
7189 if (op1 != 0x0f && op1 != 0x0d) {
7190 tcg_temp_free_i32(tmp2);
7192 } else {
7193 /* other instructions */
7194 op1 = (insn >> 24) & 0xf;
7195 switch(op1) {
7196 case 0x0:
7197 case 0x1:
7198 /* multiplies, extra load/stores */
7199 sh = (insn >> 5) & 3;
7200 if (sh == 0) {
7201 if (op1 == 0x0) {
7202 rd = (insn >> 16) & 0xf;
7203 rn = (insn >> 12) & 0xf;
7204 rs = (insn >> 8) & 0xf;
7205 rm = (insn) & 0xf;
7206 op1 = (insn >> 20) & 0xf;
7207 switch (op1) {
7208 case 0: case 1: case 2: case 3: case 6:
7209 /* 32 bit mul */
7210 tmp = load_reg(s, rs);
7211 tmp2 = load_reg(s, rm);
7212 tcg_gen_mul_i32(tmp, tmp, tmp2);
7213 tcg_temp_free_i32(tmp2);
7214 if (insn & (1 << 22)) {
7215 /* Subtract (mls) */
7216 ARCH(6T2);
7217 tmp2 = load_reg(s, rn);
7218 tcg_gen_sub_i32(tmp, tmp2, tmp);
7219 tcg_temp_free_i32(tmp2);
7220 } else if (insn & (1 << 21)) {
7221 /* Add */
7222 tmp2 = load_reg(s, rn);
7223 tcg_gen_add_i32(tmp, tmp, tmp2);
7224 tcg_temp_free_i32(tmp2);
7226 if (insn & (1 << 20))
7227 gen_logic_CC(tmp);
7228 store_reg(s, rd, tmp);
7229 break;
7230 case 4:
7231 /* 64 bit mul double accumulate (UMAAL) */
7232 ARCH(6);
7233 tmp = load_reg(s, rs);
7234 tmp2 = load_reg(s, rm);
7235 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7236 gen_addq_lo(s, tmp64, rn);
7237 gen_addq_lo(s, tmp64, rd);
7238 gen_storeq_reg(s, rn, rd, tmp64);
7239 tcg_temp_free_i64(tmp64);
7240 break;
7241 case 8: case 9: case 10: case 11:
7242 case 12: case 13: case 14: case 15:
7243 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
7244 tmp = load_reg(s, rs);
7245 tmp2 = load_reg(s, rm);
7246 if (insn & (1 << 22)) {
7247 tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2);
7248 } else {
7249 tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2);
7251 if (insn & (1 << 21)) { /* mult accumulate */
7252 TCGv al = load_reg(s, rn);
7253 TCGv ah = load_reg(s, rd);
7254 tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, al, ah);
7255 tcg_temp_free(al);
7256 tcg_temp_free(ah);
7258 if (insn & (1 << 20)) {
7259 gen_logicq_cc(tmp, tmp2);
7261 store_reg(s, rn, tmp);
7262 store_reg(s, rd, tmp2);
7263 break;
7264 default:
7265 goto illegal_op;
7267 } else {
7268 rn = (insn >> 16) & 0xf;
7269 rd = (insn >> 12) & 0xf;
7270 if (insn & (1 << 23)) {
7271 /* load/store exclusive */
7272 op1 = (insn >> 21) & 0x3;
7273 if (op1)
7274 ARCH(6K);
7275 else
7276 ARCH(6);
7277 addr = tcg_temp_local_new_i32();
7278 load_reg_var(s, addr, rn);
7279 if (insn & (1 << 20)) {
7280 switch (op1) {
7281 case 0: /* ldrex */
7282 gen_load_exclusive(s, rd, 15, addr, 2);
7283 break;
7284 case 1: /* ldrexd */
7285 gen_load_exclusive(s, rd, rd + 1, addr, 3);
7286 break;
7287 case 2: /* ldrexb */
7288 gen_load_exclusive(s, rd, 15, addr, 0);
7289 break;
7290 case 3: /* ldrexh */
7291 gen_load_exclusive(s, rd, 15, addr, 1);
7292 break;
7293 default:
7294 abort();
7296 } else {
7297 rm = insn & 0xf;
7298 switch (op1) {
7299 case 0: /* strex */
7300 gen_store_exclusive(s, rd, rm, 15, addr, 2);
7301 break;
7302 case 1: /* strexd */
7303 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
7304 break;
7305 case 2: /* strexb */
7306 gen_store_exclusive(s, rd, rm, 15, addr, 0);
7307 break;
7308 case 3: /* strexh */
7309 gen_store_exclusive(s, rd, rm, 15, addr, 1);
7310 break;
7311 default:
7312 abort();
7315 tcg_temp_free(addr);
7316 } else {
7317 /* SWP instruction */
7318 rm = (insn) & 0xf;
7320 /* ??? This is not really atomic. However we know
7321 we never have multiple CPUs running in parallel,
7322 so it is good enough. */
7323 addr = load_reg(s, rn);
7324 tmp = load_reg(s, rm);
7325 if (insn & (1 << 22)) {
7326 tmp2 = gen_ld8u(addr, IS_USER(s));
7327 gen_st8(tmp, addr, IS_USER(s));
7328 } else {
7329 tmp2 = gen_ld32(addr, IS_USER(s));
7330 gen_st32(tmp, addr, IS_USER(s));
7332 tcg_temp_free_i32(addr);
7333 store_reg(s, rd, tmp2);
7336 } else {
7337 int address_offset;
7338 int load;
7339 /* Misc load/store */
7340 rn = (insn >> 16) & 0xf;
7341 rd = (insn >> 12) & 0xf;
7342 addr = load_reg(s, rn);
7343 if (insn & (1 << 24))
7344 gen_add_datah_offset(s, insn, 0, addr);
7345 address_offset = 0;
7346 if (insn & (1 << 20)) {
7347 /* load */
7348 switch(sh) {
7349 case 1:
7350 tmp = gen_ld16u(addr, IS_USER(s));
7351 break;
7352 case 2:
7353 tmp = gen_ld8s(addr, IS_USER(s));
7354 break;
7355 default:
7356 case 3:
7357 tmp = gen_ld16s(addr, IS_USER(s));
7358 break;
7360 load = 1;
7361 } else if (sh & 2) {
7362 ARCH(5TE);
7363 /* doubleword */
7364 if (sh & 1) {
7365 /* store */
7366 tmp = load_reg(s, rd);
7367 gen_st32(tmp, addr, IS_USER(s));
7368 tcg_gen_addi_i32(addr, addr, 4);
7369 tmp = load_reg(s, rd + 1);
7370 gen_st32(tmp, addr, IS_USER(s));
7371 load = 0;
7372 } else {
7373 /* load */
7374 tmp = gen_ld32(addr, IS_USER(s));
7375 store_reg(s, rd, tmp);
7376 tcg_gen_addi_i32(addr, addr, 4);
7377 tmp = gen_ld32(addr, IS_USER(s));
7378 rd++;
7379 load = 1;
7381 address_offset = -4;
7382 } else {
7383 /* store */
7384 tmp = load_reg(s, rd);
7385 gen_st16(tmp, addr, IS_USER(s));
7386 load = 0;
7388 /* Perform base writeback before the loaded value to
7389 ensure correct behavior with overlapping index registers.
7390 ldrd with base writeback is is undefined if the
7391 destination and index registers overlap. */
7392 if (!(insn & (1 << 24))) {
7393 gen_add_datah_offset(s, insn, address_offset, addr);
7394 store_reg(s, rn, addr);
7395 } else if (insn & (1 << 21)) {
7396 if (address_offset)
7397 tcg_gen_addi_i32(addr, addr, address_offset);
7398 store_reg(s, rn, addr);
7399 } else {
7400 tcg_temp_free_i32(addr);
7402 if (load) {
7403 /* Complete the load. */
7404 store_reg(s, rd, tmp);
7407 break;
7408 case 0x4:
7409 case 0x5:
7410 goto do_ldst;
7411 case 0x6:
7412 case 0x7:
7413 if (insn & (1 << 4)) {
7414 ARCH(6);
7415 /* Armv6 Media instructions. */
7416 rm = insn & 0xf;
7417 rn = (insn >> 16) & 0xf;
7418 rd = (insn >> 12) & 0xf;
7419 rs = (insn >> 8) & 0xf;
7420 switch ((insn >> 23) & 3) {
7421 case 0: /* Parallel add/subtract. */
7422 op1 = (insn >> 20) & 7;
7423 tmp = load_reg(s, rn);
7424 tmp2 = load_reg(s, rm);
7425 sh = (insn >> 5) & 7;
7426 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
7427 goto illegal_op;
7428 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
7429 tcg_temp_free_i32(tmp2);
7430 store_reg(s, rd, tmp);
7431 break;
7432 case 1:
7433 if ((insn & 0x00700020) == 0) {
7434 /* Halfword pack. */
7435 tmp = load_reg(s, rn);
7436 tmp2 = load_reg(s, rm);
7437 shift = (insn >> 7) & 0x1f;
7438 if (insn & (1 << 6)) {
7439 /* pkhtb */
7440 if (shift == 0)
7441 shift = 31;
7442 tcg_gen_sari_i32(tmp2, tmp2, shift);
7443 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
7444 tcg_gen_ext16u_i32(tmp2, tmp2);
7445 } else {
7446 /* pkhbt */
7447 if (shift)
7448 tcg_gen_shli_i32(tmp2, tmp2, shift);
7449 tcg_gen_ext16u_i32(tmp, tmp);
7450 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
7452 tcg_gen_or_i32(tmp, tmp, tmp2);
7453 tcg_temp_free_i32(tmp2);
7454 store_reg(s, rd, tmp);
7455 } else if ((insn & 0x00200020) == 0x00200000) {
7456 /* [us]sat */
7457 tmp = load_reg(s, rm);
7458 shift = (insn >> 7) & 0x1f;
7459 if (insn & (1 << 6)) {
7460 if (shift == 0)
7461 shift = 31;
7462 tcg_gen_sari_i32(tmp, tmp, shift);
7463 } else {
7464 tcg_gen_shli_i32(tmp, tmp, shift);
7466 sh = (insn >> 16) & 0x1f;
7467 tmp2 = tcg_const_i32(sh);
7468 if (insn & (1 << 22))
7469 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
7470 else
7471 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
7472 tcg_temp_free_i32(tmp2);
7473 store_reg(s, rd, tmp);
7474 } else if ((insn & 0x00300fe0) == 0x00200f20) {
7475 /* [us]sat16 */
7476 tmp = load_reg(s, rm);
7477 sh = (insn >> 16) & 0x1f;
7478 tmp2 = tcg_const_i32(sh);
7479 if (insn & (1 << 22))
7480 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
7481 else
7482 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
7483 tcg_temp_free_i32(tmp2);
7484 store_reg(s, rd, tmp);
7485 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
7486 /* Select bytes. */
7487 tmp = load_reg(s, rn);
7488 tmp2 = load_reg(s, rm);
7489 tmp3 = tcg_temp_new_i32();
7490 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
7491 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7492 tcg_temp_free_i32(tmp3);
7493 tcg_temp_free_i32(tmp2);
7494 store_reg(s, rd, tmp);
7495 } else if ((insn & 0x000003e0) == 0x00000060) {
7496 tmp = load_reg(s, rm);
7497 shift = (insn >> 10) & 3;
7498 /* ??? In many cases it's not necessary to do a
7499 rotate, a shift is sufficient. */
7500 if (shift != 0)
7501 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
7502 op1 = (insn >> 20) & 7;
7503 switch (op1) {
7504 case 0: gen_sxtb16(tmp); break;
7505 case 2: gen_sxtb(tmp); break;
7506 case 3: gen_sxth(tmp); break;
7507 case 4: gen_uxtb16(tmp); break;
7508 case 6: gen_uxtb(tmp); break;
7509 case 7: gen_uxth(tmp); break;
7510 default: goto illegal_op;
7512 if (rn != 15) {
7513 tmp2 = load_reg(s, rn);
7514 if ((op1 & 3) == 0) {
7515 gen_add16(tmp, tmp2);
7516 } else {
7517 tcg_gen_add_i32(tmp, tmp, tmp2);
7518 tcg_temp_free_i32(tmp2);
7521 store_reg(s, rd, tmp);
7522 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
7523 /* rev */
7524 tmp = load_reg(s, rm);
7525 if (insn & (1 << 22)) {
7526 if (insn & (1 << 7)) {
7527 gen_revsh(tmp);
7528 } else {
7529 ARCH(6T2);
7530 gen_helper_rbit(tmp, tmp);
7532 } else {
7533 if (insn & (1 << 7))
7534 gen_rev16(tmp);
7535 else
7536 tcg_gen_bswap32_i32(tmp, tmp);
7538 store_reg(s, rd, tmp);
7539 } else {
7540 goto illegal_op;
7542 break;
7543 case 2: /* Multiplies (Type 3). */
7544 switch ((insn >> 20) & 0x7) {
7545 case 5:
7546 if (((insn >> 6) ^ (insn >> 7)) & 1) {
7547 /* op2 not 00x or 11x : UNDEF */
7548 goto illegal_op;
7550 /* Signed multiply most significant [accumulate].
7551 (SMMUL, SMMLA, SMMLS) */
7552 tmp = load_reg(s, rm);
7553 tmp2 = load_reg(s, rs);
7554 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7556 if (rd != 15) {
7557 tmp = load_reg(s, rd);
7558 if (insn & (1 << 6)) {
7559 tmp64 = gen_subq_msw(tmp64, tmp);
7560 } else {
7561 tmp64 = gen_addq_msw(tmp64, tmp);
7564 if (insn & (1 << 5)) {
7565 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
7567 tcg_gen_shri_i64(tmp64, tmp64, 32);
7568 tmp = tcg_temp_new_i32();
7569 tcg_gen_trunc_i64_i32(tmp, tmp64);
7570 tcg_temp_free_i64(tmp64);
7571 store_reg(s, rn, tmp);
7572 break;
7573 case 0:
7574 case 4:
7575 /* SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD */
7576 if (insn & (1 << 7)) {
7577 goto illegal_op;
7579 tmp = load_reg(s, rm);
7580 tmp2 = load_reg(s, rs);
7581 if (insn & (1 << 5))
7582 gen_swap_half(tmp2);
7583 gen_smul_dual(tmp, tmp2);
7584 if (insn & (1 << 6)) {
7585 /* This subtraction cannot overflow. */
7586 tcg_gen_sub_i32(tmp, tmp, tmp2);
7587 } else {
7588 /* This addition cannot overflow 32 bits;
7589 * however it may overflow considered as a signed
7590 * operation, in which case we must set the Q flag.
7592 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7594 tcg_temp_free_i32(tmp2);
7595 if (insn & (1 << 22)) {
7596 /* smlald, smlsld */
7597 tmp64 = tcg_temp_new_i64();
7598 tcg_gen_ext_i32_i64(tmp64, tmp);
7599 tcg_temp_free_i32(tmp);
7600 gen_addq(s, tmp64, rd, rn);
7601 gen_storeq_reg(s, rd, rn, tmp64);
7602 tcg_temp_free_i64(tmp64);
7603 } else {
7604 /* smuad, smusd, smlad, smlsd */
7605 if (rd != 15)
7607 tmp2 = load_reg(s, rd);
7608 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7609 tcg_temp_free_i32(tmp2);
7611 store_reg(s, rn, tmp);
7613 break;
7614 case 1:
7615 case 3:
7616 /* SDIV, UDIV */
7617 if (!arm_feature(env, ARM_FEATURE_ARM_DIV)) {
7618 goto illegal_op;
7620 if (((insn >> 5) & 7) || (rd != 15)) {
7621 goto illegal_op;
7623 tmp = load_reg(s, rm);
7624 tmp2 = load_reg(s, rs);
7625 if (insn & (1 << 21)) {
7626 gen_helper_udiv(tmp, tmp, tmp2);
7627 } else {
7628 gen_helper_sdiv(tmp, tmp, tmp2);
7630 tcg_temp_free_i32(tmp2);
7631 store_reg(s, rn, tmp);
7632 break;
7633 default:
7634 goto illegal_op;
7636 break;
7637 case 3:
7638 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
7639 switch (op1) {
7640 case 0: /* Unsigned sum of absolute differences. */
7641 ARCH(6);
7642 tmp = load_reg(s, rm);
7643 tmp2 = load_reg(s, rs);
7644 gen_helper_usad8(tmp, tmp, tmp2);
7645 tcg_temp_free_i32(tmp2);
7646 if (rd != 15) {
7647 tmp2 = load_reg(s, rd);
7648 tcg_gen_add_i32(tmp, tmp, tmp2);
7649 tcg_temp_free_i32(tmp2);
7651 store_reg(s, rn, tmp);
7652 break;
7653 case 0x20: case 0x24: case 0x28: case 0x2c:
7654 /* Bitfield insert/clear. */
7655 ARCH(6T2);
7656 shift = (insn >> 7) & 0x1f;
7657 i = (insn >> 16) & 0x1f;
7658 i = i + 1 - shift;
7659 if (rm == 15) {
7660 tmp = tcg_temp_new_i32();
7661 tcg_gen_movi_i32(tmp, 0);
7662 } else {
7663 tmp = load_reg(s, rm);
7665 if (i != 32) {
7666 tmp2 = load_reg(s, rd);
7667 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, i);
7668 tcg_temp_free_i32(tmp2);
7670 store_reg(s, rd, tmp);
7671 break;
7672 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
7673 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
7674 ARCH(6T2);
7675 tmp = load_reg(s, rm);
7676 shift = (insn >> 7) & 0x1f;
7677 i = ((insn >> 16) & 0x1f) + 1;
7678 if (shift + i > 32)
7679 goto illegal_op;
7680 if (i < 32) {
7681 if (op1 & 0x20) {
7682 gen_ubfx(tmp, shift, (1u << i) - 1);
7683 } else {
7684 gen_sbfx(tmp, shift, i);
7687 store_reg(s, rd, tmp);
7688 break;
7689 default:
7690 goto illegal_op;
7692 break;
7694 break;
7696 do_ldst:
7697 /* Check for undefined extension instructions
7698 * per the ARM Bible IE:
7699 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
7701 sh = (0xf << 20) | (0xf << 4);
7702 if (op1 == 0x7 && ((insn & sh) == sh))
7704 goto illegal_op;
7706 /* load/store byte/word */
7707 rn = (insn >> 16) & 0xf;
7708 rd = (insn >> 12) & 0xf;
7709 tmp2 = load_reg(s, rn);
7710 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
7711 if (insn & (1 << 24))
7712 gen_add_data_offset(s, insn, tmp2);
7713 if (insn & (1 << 20)) {
7714 /* load */
7715 if (insn & (1 << 22)) {
7716 tmp = gen_ld8u(tmp2, i);
7717 } else {
7718 tmp = gen_ld32(tmp2, i);
7720 } else {
7721 /* store */
7722 tmp = load_reg(s, rd);
7723 if (insn & (1 << 22))
7724 gen_st8(tmp, tmp2, i);
7725 else
7726 gen_st32(tmp, tmp2, i);
7728 if (!(insn & (1 << 24))) {
7729 gen_add_data_offset(s, insn, tmp2);
7730 store_reg(s, rn, tmp2);
7731 } else if (insn & (1 << 21)) {
7732 store_reg(s, rn, tmp2);
7733 } else {
7734 tcg_temp_free_i32(tmp2);
7736 if (insn & (1 << 20)) {
7737 /* Complete the load. */
7738 store_reg_from_load(env, s, rd, tmp);
7740 break;
7741 case 0x08:
7742 case 0x09:
7744 int j, n, user, loaded_base;
7745 TCGv loaded_var;
7746 /* load/store multiple words */
7747 /* XXX: store correct base if write back */
7748 user = 0;
7749 if (insn & (1 << 22)) {
7750 if (IS_USER(s))
7751 goto illegal_op; /* only usable in supervisor mode */
7753 if ((insn & (1 << 15)) == 0)
7754 user = 1;
7756 rn = (insn >> 16) & 0xf;
7757 addr = load_reg(s, rn);
7759 /* compute total size */
7760 loaded_base = 0;
7761 TCGV_UNUSED(loaded_var);
7762 n = 0;
7763 for(i=0;i<16;i++) {
7764 if (insn & (1 << i))
7765 n++;
7767 /* XXX: test invalid n == 0 case ? */
7768 if (insn & (1 << 23)) {
7769 if (insn & (1 << 24)) {
7770 /* pre increment */
7771 tcg_gen_addi_i32(addr, addr, 4);
7772 } else {
7773 /* post increment */
7775 } else {
7776 if (insn & (1 << 24)) {
7777 /* pre decrement */
7778 tcg_gen_addi_i32(addr, addr, -(n * 4));
7779 } else {
7780 /* post decrement */
7781 if (n != 1)
7782 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7785 j = 0;
7786 for(i=0;i<16;i++) {
7787 if (insn & (1 << i)) {
7788 if (insn & (1 << 20)) {
7789 /* load */
7790 tmp = gen_ld32(addr, IS_USER(s));
7791 if (user) {
7792 tmp2 = tcg_const_i32(i);
7793 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
7794 tcg_temp_free_i32(tmp2);
7795 tcg_temp_free_i32(tmp);
7796 } else if (i == rn) {
7797 loaded_var = tmp;
7798 loaded_base = 1;
7799 } else {
7800 store_reg_from_load(env, s, i, tmp);
7802 } else {
7803 /* store */
7804 if (i == 15) {
7805 /* special case: r15 = PC + 8 */
7806 val = (long)s->pc + 4;
7807 tmp = tcg_temp_new_i32();
7808 tcg_gen_movi_i32(tmp, val);
7809 } else if (user) {
7810 tmp = tcg_temp_new_i32();
7811 tmp2 = tcg_const_i32(i);
7812 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
7813 tcg_temp_free_i32(tmp2);
7814 } else {
7815 tmp = load_reg(s, i);
7817 gen_st32(tmp, addr, IS_USER(s));
7819 j++;
7820 /* no need to add after the last transfer */
7821 if (j != n)
7822 tcg_gen_addi_i32(addr, addr, 4);
7825 if (insn & (1 << 21)) {
7826 /* write back */
7827 if (insn & (1 << 23)) {
7828 if (insn & (1 << 24)) {
7829 /* pre increment */
7830 } else {
7831 /* post increment */
7832 tcg_gen_addi_i32(addr, addr, 4);
7834 } else {
7835 if (insn & (1 << 24)) {
7836 /* pre decrement */
7837 if (n != 1)
7838 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7839 } else {
7840 /* post decrement */
7841 tcg_gen_addi_i32(addr, addr, -(n * 4));
7844 store_reg(s, rn, addr);
7845 } else {
7846 tcg_temp_free_i32(addr);
7848 if (loaded_base) {
7849 store_reg(s, rn, loaded_var);
7851 if ((insn & (1 << 22)) && !user) {
7852 /* Restore CPSR from SPSR. */
7853 tmp = load_cpu_field(spsr);
7854 gen_set_cpsr(tmp, 0xffffffff);
7855 tcg_temp_free_i32(tmp);
7856 s->is_jmp = DISAS_UPDATE;
7859 break;
7860 case 0xa:
7861 case 0xb:
7863 int32_t offset;
7865 /* branch (and link) */
7866 val = (int32_t)s->pc;
7867 if (insn & (1 << 24)) {
7868 tmp = tcg_temp_new_i32();
7869 tcg_gen_movi_i32(tmp, val);
7870 store_reg(s, 14, tmp);
7872 offset = (((int32_t)insn << 8) >> 8);
7873 val += (offset << 2) + 4;
7874 gen_jmp(s, val);
7876 break;
7877 case 0xc:
7878 case 0xd:
7879 case 0xe:
7880 /* Coprocessor. */
7881 if (disas_coproc_insn(env, s, insn))
7882 goto illegal_op;
7883 break;
7884 case 0xf:
7885 /* swi */
7886 gen_set_pc_im(s->pc);
7887 s->is_jmp = DISAS_SWI;
7888 break;
7889 default:
7890 illegal_op:
7891 gen_exception_insn(s, 4, EXCP_UDEF);
7892 break;
7897 /* Return true if this is a Thumb-2 logical op. */
7898 static int
7899 thumb2_logic_op(int op)
7901 return (op < 8);
7904 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7905 then set condition code flags based on the result of the operation.
7906 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7907 to the high bit of T1.
7908 Returns zero if the opcode is valid. */
7910 static int
7911 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCGv t0, TCGv t1)
7913 int logic_cc;
7915 logic_cc = 0;
7916 switch (op) {
7917 case 0: /* and */
7918 tcg_gen_and_i32(t0, t0, t1);
7919 logic_cc = conds;
7920 break;
7921 case 1: /* bic */
7922 tcg_gen_andc_i32(t0, t0, t1);
7923 logic_cc = conds;
7924 break;
7925 case 2: /* orr */
7926 tcg_gen_or_i32(t0, t0, t1);
7927 logic_cc = conds;
7928 break;
7929 case 3: /* orn */
7930 tcg_gen_orc_i32(t0, t0, t1);
7931 logic_cc = conds;
7932 break;
7933 case 4: /* eor */
7934 tcg_gen_xor_i32(t0, t0, t1);
7935 logic_cc = conds;
7936 break;
7937 case 8: /* add */
7938 if (conds)
7939 gen_add_CC(t0, t0, t1);
7940 else
7941 tcg_gen_add_i32(t0, t0, t1);
7942 break;
7943 case 10: /* adc */
7944 if (conds)
7945 gen_adc_CC(t0, t0, t1);
7946 else
7947 gen_adc(t0, t1);
7948 break;
7949 case 11: /* sbc */
7950 if (conds)
7951 gen_helper_sbc_cc(t0, cpu_env, t0, t1);
7952 else
7953 gen_sub_carry(t0, t0, t1);
7954 break;
7955 case 13: /* sub */
7956 if (conds)
7957 gen_sub_CC(t0, t0, t1);
7958 else
7959 tcg_gen_sub_i32(t0, t0, t1);
7960 break;
7961 case 14: /* rsb */
7962 if (conds)
7963 gen_sub_CC(t0, t1, t0);
7964 else
7965 tcg_gen_sub_i32(t0, t1, t0);
7966 break;
7967 default: /* 5, 6, 7, 9, 12, 15. */
7968 return 1;
7970 if (logic_cc) {
7971 gen_logic_CC(t0);
7972 if (shifter_out)
7973 gen_set_CF_bit31(t1);
7975 return 0;
7978 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7979 is not legal. */
7980 static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw1)
7982 uint32_t insn, imm, shift, offset;
7983 uint32_t rd, rn, rm, rs;
7984 TCGv tmp;
7985 TCGv tmp2;
7986 TCGv tmp3;
7987 TCGv addr;
7988 TCGv_i64 tmp64;
7989 int op;
7990 int shiftop;
7991 int conds;
7992 int logic_cc;
7994 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
7995 || arm_feature (env, ARM_FEATURE_M))) {
7996 /* Thumb-1 cores may need to treat bl and blx as a pair of
7997 16-bit instructions to get correct prefetch abort behavior. */
7998 insn = insn_hw1;
7999 if ((insn & (1 << 12)) == 0) {
8000 ARCH(5);
8001 /* Second half of blx. */
8002 offset = ((insn & 0x7ff) << 1);
8003 tmp = load_reg(s, 14);
8004 tcg_gen_addi_i32(tmp, tmp, offset);
8005 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
8007 tmp2 = tcg_temp_new_i32();
8008 tcg_gen_movi_i32(tmp2, s->pc | 1);
8009 store_reg(s, 14, tmp2);
8010 gen_bx(s, tmp);
8011 return 0;
8013 if (insn & (1 << 11)) {
8014 /* Second half of bl. */
8015 offset = ((insn & 0x7ff) << 1) | 1;
8016 tmp = load_reg(s, 14);
8017 tcg_gen_addi_i32(tmp, tmp, offset);
8019 tmp2 = tcg_temp_new_i32();
8020 tcg_gen_movi_i32(tmp2, s->pc | 1);
8021 store_reg(s, 14, tmp2);
8022 gen_bx(s, tmp);
8023 return 0;
8025 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
8026 /* Instruction spans a page boundary. Implement it as two
8027 16-bit instructions in case the second half causes an
8028 prefetch abort. */
8029 offset = ((int32_t)insn << 21) >> 9;
8030 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
8031 return 0;
8033 /* Fall through to 32-bit decode. */
8036 insn = arm_lduw_code(env, s->pc, s->bswap_code);
8037 s->pc += 2;
8038 insn |= (uint32_t)insn_hw1 << 16;
8040 if ((insn & 0xf800e800) != 0xf000e800) {
8041 ARCH(6T2);
8044 rn = (insn >> 16) & 0xf;
8045 rs = (insn >> 12) & 0xf;
8046 rd = (insn >> 8) & 0xf;
8047 rm = insn & 0xf;
8048 switch ((insn >> 25) & 0xf) {
8049 case 0: case 1: case 2: case 3:
8050 /* 16-bit instructions. Should never happen. */
8051 abort();
8052 case 4:
8053 if (insn & (1 << 22)) {
8054 /* Other load/store, table branch. */
8055 if (insn & 0x01200000) {
8056 /* Load/store doubleword. */
8057 if (rn == 15) {
8058 addr = tcg_temp_new_i32();
8059 tcg_gen_movi_i32(addr, s->pc & ~3);
8060 } else {
8061 addr = load_reg(s, rn);
8063 offset = (insn & 0xff) * 4;
8064 if ((insn & (1 << 23)) == 0)
8065 offset = -offset;
8066 if (insn & (1 << 24)) {
8067 tcg_gen_addi_i32(addr, addr, offset);
8068 offset = 0;
8070 if (insn & (1 << 20)) {
8071 /* ldrd */
8072 tmp = gen_ld32(addr, IS_USER(s));
8073 store_reg(s, rs, tmp);
8074 tcg_gen_addi_i32(addr, addr, 4);
8075 tmp = gen_ld32(addr, IS_USER(s));
8076 store_reg(s, rd, tmp);
8077 } else {
8078 /* strd */
8079 tmp = load_reg(s, rs);
8080 gen_st32(tmp, addr, IS_USER(s));
8081 tcg_gen_addi_i32(addr, addr, 4);
8082 tmp = load_reg(s, rd);
8083 gen_st32(tmp, addr, IS_USER(s));
8085 if (insn & (1 << 21)) {
8086 /* Base writeback. */
8087 if (rn == 15)
8088 goto illegal_op;
8089 tcg_gen_addi_i32(addr, addr, offset - 4);
8090 store_reg(s, rn, addr);
8091 } else {
8092 tcg_temp_free_i32(addr);
8094 } else if ((insn & (1 << 23)) == 0) {
8095 /* Load/store exclusive word. */
8096 addr = tcg_temp_local_new();
8097 load_reg_var(s, addr, rn);
8098 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
8099 if (insn & (1 << 20)) {
8100 gen_load_exclusive(s, rs, 15, addr, 2);
8101 } else {
8102 gen_store_exclusive(s, rd, rs, 15, addr, 2);
8104 tcg_temp_free(addr);
8105 } else if ((insn & (1 << 6)) == 0) {
8106 /* Table Branch. */
8107 if (rn == 15) {
8108 addr = tcg_temp_new_i32();
8109 tcg_gen_movi_i32(addr, s->pc);
8110 } else {
8111 addr = load_reg(s, rn);
8113 tmp = load_reg(s, rm);
8114 tcg_gen_add_i32(addr, addr, tmp);
8115 if (insn & (1 << 4)) {
8116 /* tbh */
8117 tcg_gen_add_i32(addr, addr, tmp);
8118 tcg_temp_free_i32(tmp);
8119 tmp = gen_ld16u(addr, IS_USER(s));
8120 } else { /* tbb */
8121 tcg_temp_free_i32(tmp);
8122 tmp = gen_ld8u(addr, IS_USER(s));
8124 tcg_temp_free_i32(addr);
8125 tcg_gen_shli_i32(tmp, tmp, 1);
8126 tcg_gen_addi_i32(tmp, tmp, s->pc);
8127 store_reg(s, 15, tmp);
8128 } else {
8129 /* Load/store exclusive byte/halfword/doubleword. */
8130 ARCH(7);
8131 op = (insn >> 4) & 0x3;
8132 if (op == 2) {
8133 goto illegal_op;
8135 addr = tcg_temp_local_new();
8136 load_reg_var(s, addr, rn);
8137 if (insn & (1 << 20)) {
8138 gen_load_exclusive(s, rs, rd, addr, op);
8139 } else {
8140 gen_store_exclusive(s, rm, rs, rd, addr, op);
8142 tcg_temp_free(addr);
8144 } else {
8145 /* Load/store multiple, RFE, SRS. */
8146 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
8147 /* Not available in user mode. */
8148 if (IS_USER(s))
8149 goto illegal_op;
8150 if (insn & (1 << 20)) {
8151 /* rfe */
8152 addr = load_reg(s, rn);
8153 if ((insn & (1 << 24)) == 0)
8154 tcg_gen_addi_i32(addr, addr, -8);
8155 /* Load PC into tmp and CPSR into tmp2. */
8156 tmp = gen_ld32(addr, 0);
8157 tcg_gen_addi_i32(addr, addr, 4);
8158 tmp2 = gen_ld32(addr, 0);
8159 if (insn & (1 << 21)) {
8160 /* Base writeback. */
8161 if (insn & (1 << 24)) {
8162 tcg_gen_addi_i32(addr, addr, 4);
8163 } else {
8164 tcg_gen_addi_i32(addr, addr, -4);
8166 store_reg(s, rn, addr);
8167 } else {
8168 tcg_temp_free_i32(addr);
8170 gen_rfe(s, tmp, tmp2);
8171 } else {
8172 /* srs */
8173 op = (insn & 0x1f);
8174 addr = tcg_temp_new_i32();
8175 tmp = tcg_const_i32(op);
8176 gen_helper_get_r13_banked(addr, cpu_env, tmp);
8177 tcg_temp_free_i32(tmp);
8178 if ((insn & (1 << 24)) == 0) {
8179 tcg_gen_addi_i32(addr, addr, -8);
8181 tmp = load_reg(s, 14);
8182 gen_st32(tmp, addr, 0);
8183 tcg_gen_addi_i32(addr, addr, 4);
8184 tmp = tcg_temp_new_i32();
8185 gen_helper_cpsr_read(tmp, cpu_env);
8186 gen_st32(tmp, addr, 0);
8187 if (insn & (1 << 21)) {
8188 if ((insn & (1 << 24)) == 0) {
8189 tcg_gen_addi_i32(addr, addr, -4);
8190 } else {
8191 tcg_gen_addi_i32(addr, addr, 4);
8193 tmp = tcg_const_i32(op);
8194 gen_helper_set_r13_banked(cpu_env, tmp, addr);
8195 tcg_temp_free_i32(tmp);
8196 } else {
8197 tcg_temp_free_i32(addr);
8200 } else {
8201 int i, loaded_base = 0;
8202 TCGv loaded_var;
8203 /* Load/store multiple. */
8204 addr = load_reg(s, rn);
8205 offset = 0;
8206 for (i = 0; i < 16; i++) {
8207 if (insn & (1 << i))
8208 offset += 4;
8210 if (insn & (1 << 24)) {
8211 tcg_gen_addi_i32(addr, addr, -offset);
8214 TCGV_UNUSED(loaded_var);
8215 for (i = 0; i < 16; i++) {
8216 if ((insn & (1 << i)) == 0)
8217 continue;
8218 if (insn & (1 << 20)) {
8219 /* Load. */
8220 tmp = gen_ld32(addr, IS_USER(s));
8221 if (i == 15) {
8222 gen_bx(s, tmp);
8223 } else if (i == rn) {
8224 loaded_var = tmp;
8225 loaded_base = 1;
8226 } else {
8227 store_reg(s, i, tmp);
8229 } else {
8230 /* Store. */
8231 tmp = load_reg(s, i);
8232 gen_st32(tmp, addr, IS_USER(s));
8234 tcg_gen_addi_i32(addr, addr, 4);
8236 if (loaded_base) {
8237 store_reg(s, rn, loaded_var);
8239 if (insn & (1 << 21)) {
8240 /* Base register writeback. */
8241 if (insn & (1 << 24)) {
8242 tcg_gen_addi_i32(addr, addr, -offset);
8244 /* Fault if writeback register is in register list. */
8245 if (insn & (1 << rn))
8246 goto illegal_op;
8247 store_reg(s, rn, addr);
8248 } else {
8249 tcg_temp_free_i32(addr);
8253 break;
8254 case 5:
8256 op = (insn >> 21) & 0xf;
8257 if (op == 6) {
8258 /* Halfword pack. */
8259 tmp = load_reg(s, rn);
8260 tmp2 = load_reg(s, rm);
8261 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
8262 if (insn & (1 << 5)) {
8263 /* pkhtb */
8264 if (shift == 0)
8265 shift = 31;
8266 tcg_gen_sari_i32(tmp2, tmp2, shift);
8267 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
8268 tcg_gen_ext16u_i32(tmp2, tmp2);
8269 } else {
8270 /* pkhbt */
8271 if (shift)
8272 tcg_gen_shli_i32(tmp2, tmp2, shift);
8273 tcg_gen_ext16u_i32(tmp, tmp);
8274 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
8276 tcg_gen_or_i32(tmp, tmp, tmp2);
8277 tcg_temp_free_i32(tmp2);
8278 store_reg(s, rd, tmp);
8279 } else {
8280 /* Data processing register constant shift. */
8281 if (rn == 15) {
8282 tmp = tcg_temp_new_i32();
8283 tcg_gen_movi_i32(tmp, 0);
8284 } else {
8285 tmp = load_reg(s, rn);
8287 tmp2 = load_reg(s, rm);
8289 shiftop = (insn >> 4) & 3;
8290 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
8291 conds = (insn & (1 << 20)) != 0;
8292 logic_cc = (conds && thumb2_logic_op(op));
8293 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
8294 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
8295 goto illegal_op;
8296 tcg_temp_free_i32(tmp2);
8297 if (rd != 15) {
8298 store_reg(s, rd, tmp);
8299 } else {
8300 tcg_temp_free_i32(tmp);
8303 break;
8304 case 13: /* Misc data processing. */
8305 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
8306 if (op < 4 && (insn & 0xf000) != 0xf000)
8307 goto illegal_op;
8308 switch (op) {
8309 case 0: /* Register controlled shift. */
8310 tmp = load_reg(s, rn);
8311 tmp2 = load_reg(s, rm);
8312 if ((insn & 0x70) != 0)
8313 goto illegal_op;
8314 op = (insn >> 21) & 3;
8315 logic_cc = (insn & (1 << 20)) != 0;
8316 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
8317 if (logic_cc)
8318 gen_logic_CC(tmp);
8319 store_reg_bx(env, s, rd, tmp);
8320 break;
8321 case 1: /* Sign/zero extend. */
8322 tmp = load_reg(s, rm);
8323 shift = (insn >> 4) & 3;
8324 /* ??? In many cases it's not necessary to do a
8325 rotate, a shift is sufficient. */
8326 if (shift != 0)
8327 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
8328 op = (insn >> 20) & 7;
8329 switch (op) {
8330 case 0: gen_sxth(tmp); break;
8331 case 1: gen_uxth(tmp); break;
8332 case 2: gen_sxtb16(tmp); break;
8333 case 3: gen_uxtb16(tmp); break;
8334 case 4: gen_sxtb(tmp); break;
8335 case 5: gen_uxtb(tmp); break;
8336 default: goto illegal_op;
8338 if (rn != 15) {
8339 tmp2 = load_reg(s, rn);
8340 if ((op >> 1) == 1) {
8341 gen_add16(tmp, tmp2);
8342 } else {
8343 tcg_gen_add_i32(tmp, tmp, tmp2);
8344 tcg_temp_free_i32(tmp2);
8347 store_reg(s, rd, tmp);
8348 break;
8349 case 2: /* SIMD add/subtract. */
8350 op = (insn >> 20) & 7;
8351 shift = (insn >> 4) & 7;
8352 if ((op & 3) == 3 || (shift & 3) == 3)
8353 goto illegal_op;
8354 tmp = load_reg(s, rn);
8355 tmp2 = load_reg(s, rm);
8356 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
8357 tcg_temp_free_i32(tmp2);
8358 store_reg(s, rd, tmp);
8359 break;
8360 case 3: /* Other data processing. */
8361 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
8362 if (op < 4) {
8363 /* Saturating add/subtract. */
8364 tmp = load_reg(s, rn);
8365 tmp2 = load_reg(s, rm);
8366 if (op & 1)
8367 gen_helper_double_saturate(tmp, cpu_env, tmp);
8368 if (op & 2)
8369 gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);
8370 else
8371 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
8372 tcg_temp_free_i32(tmp2);
8373 } else {
8374 tmp = load_reg(s, rn);
8375 switch (op) {
8376 case 0x0a: /* rbit */
8377 gen_helper_rbit(tmp, tmp);
8378 break;
8379 case 0x08: /* rev */
8380 tcg_gen_bswap32_i32(tmp, tmp);
8381 break;
8382 case 0x09: /* rev16 */
8383 gen_rev16(tmp);
8384 break;
8385 case 0x0b: /* revsh */
8386 gen_revsh(tmp);
8387 break;
8388 case 0x10: /* sel */
8389 tmp2 = load_reg(s, rm);
8390 tmp3 = tcg_temp_new_i32();
8391 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
8392 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
8393 tcg_temp_free_i32(tmp3);
8394 tcg_temp_free_i32(tmp2);
8395 break;
8396 case 0x18: /* clz */
8397 gen_helper_clz(tmp, tmp);
8398 break;
8399 default:
8400 goto illegal_op;
8403 store_reg(s, rd, tmp);
8404 break;
8405 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
8406 op = (insn >> 4) & 0xf;
8407 tmp = load_reg(s, rn);
8408 tmp2 = load_reg(s, rm);
8409 switch ((insn >> 20) & 7) {
8410 case 0: /* 32 x 32 -> 32 */
8411 tcg_gen_mul_i32(tmp, tmp, tmp2);
8412 tcg_temp_free_i32(tmp2);
8413 if (rs != 15) {
8414 tmp2 = load_reg(s, rs);
8415 if (op)
8416 tcg_gen_sub_i32(tmp, tmp2, tmp);
8417 else
8418 tcg_gen_add_i32(tmp, tmp, tmp2);
8419 tcg_temp_free_i32(tmp2);
8421 break;
8422 case 1: /* 16 x 16 -> 32 */
8423 gen_mulxy(tmp, tmp2, op & 2, op & 1);
8424 tcg_temp_free_i32(tmp2);
8425 if (rs != 15) {
8426 tmp2 = load_reg(s, rs);
8427 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8428 tcg_temp_free_i32(tmp2);
8430 break;
8431 case 2: /* Dual multiply add. */
8432 case 4: /* Dual multiply subtract. */
8433 if (op)
8434 gen_swap_half(tmp2);
8435 gen_smul_dual(tmp, tmp2);
8436 if (insn & (1 << 22)) {
8437 /* This subtraction cannot overflow. */
8438 tcg_gen_sub_i32(tmp, tmp, tmp2);
8439 } else {
8440 /* This addition cannot overflow 32 bits;
8441 * however it may overflow considered as a signed
8442 * operation, in which case we must set the Q flag.
8444 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8446 tcg_temp_free_i32(tmp2);
8447 if (rs != 15)
8449 tmp2 = load_reg(s, rs);
8450 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8451 tcg_temp_free_i32(tmp2);
8453 break;
8454 case 3: /* 32 * 16 -> 32msb */
8455 if (op)
8456 tcg_gen_sari_i32(tmp2, tmp2, 16);
8457 else
8458 gen_sxth(tmp2);
8459 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8460 tcg_gen_shri_i64(tmp64, tmp64, 16);
8461 tmp = tcg_temp_new_i32();
8462 tcg_gen_trunc_i64_i32(tmp, tmp64);
8463 tcg_temp_free_i64(tmp64);
8464 if (rs != 15)
8466 tmp2 = load_reg(s, rs);
8467 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8468 tcg_temp_free_i32(tmp2);
8470 break;
8471 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
8472 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8473 if (rs != 15) {
8474 tmp = load_reg(s, rs);
8475 if (insn & (1 << 20)) {
8476 tmp64 = gen_addq_msw(tmp64, tmp);
8477 } else {
8478 tmp64 = gen_subq_msw(tmp64, tmp);
8481 if (insn & (1 << 4)) {
8482 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
8484 tcg_gen_shri_i64(tmp64, tmp64, 32);
8485 tmp = tcg_temp_new_i32();
8486 tcg_gen_trunc_i64_i32(tmp, tmp64);
8487 tcg_temp_free_i64(tmp64);
8488 break;
8489 case 7: /* Unsigned sum of absolute differences. */
8490 gen_helper_usad8(tmp, tmp, tmp2);
8491 tcg_temp_free_i32(tmp2);
8492 if (rs != 15) {
8493 tmp2 = load_reg(s, rs);
8494 tcg_gen_add_i32(tmp, tmp, tmp2);
8495 tcg_temp_free_i32(tmp2);
8497 break;
8499 store_reg(s, rd, tmp);
8500 break;
8501 case 6: case 7: /* 64-bit multiply, Divide. */
8502 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
8503 tmp = load_reg(s, rn);
8504 tmp2 = load_reg(s, rm);
8505 if ((op & 0x50) == 0x10) {
8506 /* sdiv, udiv */
8507 if (!arm_feature(env, ARM_FEATURE_THUMB_DIV)) {
8508 goto illegal_op;
8510 if (op & 0x20)
8511 gen_helper_udiv(tmp, tmp, tmp2);
8512 else
8513 gen_helper_sdiv(tmp, tmp, tmp2);
8514 tcg_temp_free_i32(tmp2);
8515 store_reg(s, rd, tmp);
8516 } else if ((op & 0xe) == 0xc) {
8517 /* Dual multiply accumulate long. */
8518 if (op & 1)
8519 gen_swap_half(tmp2);
8520 gen_smul_dual(tmp, tmp2);
8521 if (op & 0x10) {
8522 tcg_gen_sub_i32(tmp, tmp, tmp2);
8523 } else {
8524 tcg_gen_add_i32(tmp, tmp, tmp2);
8526 tcg_temp_free_i32(tmp2);
8527 /* BUGFIX */
8528 tmp64 = tcg_temp_new_i64();
8529 tcg_gen_ext_i32_i64(tmp64, tmp);
8530 tcg_temp_free_i32(tmp);
8531 gen_addq(s, tmp64, rs, rd);
8532 gen_storeq_reg(s, rs, rd, tmp64);
8533 tcg_temp_free_i64(tmp64);
8534 } else {
8535 if (op & 0x20) {
8536 /* Unsigned 64-bit multiply */
8537 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
8538 } else {
8539 if (op & 8) {
8540 /* smlalxy */
8541 gen_mulxy(tmp, tmp2, op & 2, op & 1);
8542 tcg_temp_free_i32(tmp2);
8543 tmp64 = tcg_temp_new_i64();
8544 tcg_gen_ext_i32_i64(tmp64, tmp);
8545 tcg_temp_free_i32(tmp);
8546 } else {
8547 /* Signed 64-bit multiply */
8548 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8551 if (op & 4) {
8552 /* umaal */
8553 gen_addq_lo(s, tmp64, rs);
8554 gen_addq_lo(s, tmp64, rd);
8555 } else if (op & 0x40) {
8556 /* 64-bit accumulate. */
8557 gen_addq(s, tmp64, rs, rd);
8559 gen_storeq_reg(s, rs, rd, tmp64);
8560 tcg_temp_free_i64(tmp64);
8562 break;
8564 break;
8565 case 6: case 7: case 14: case 15:
8566 /* Coprocessor. */
8567 if (((insn >> 24) & 3) == 3) {
8568 /* Translate into the equivalent ARM encoding. */
8569 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
8570 if (disas_neon_data_insn(env, s, insn))
8571 goto illegal_op;
8572 } else {
8573 if (insn & (1 << 28))
8574 goto illegal_op;
8575 if (disas_coproc_insn (env, s, insn))
8576 goto illegal_op;
8578 break;
8579 case 8: case 9: case 10: case 11:
8580 if (insn & (1 << 15)) {
8581 /* Branches, misc control. */
8582 if (insn & 0x5000) {
8583 /* Unconditional branch. */
8584 /* signextend(hw1[10:0]) -> offset[:12]. */
8585 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
8586 /* hw1[10:0] -> offset[11:1]. */
8587 offset |= (insn & 0x7ff) << 1;
8588 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
8589 offset[24:22] already have the same value because of the
8590 sign extension above. */
8591 offset ^= ((~insn) & (1 << 13)) << 10;
8592 offset ^= ((~insn) & (1 << 11)) << 11;
8594 if (insn & (1 << 14)) {
8595 /* Branch and link. */
8596 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
8599 offset += s->pc;
8600 if (insn & (1 << 12)) {
8601 /* b/bl */
8602 gen_jmp(s, offset);
8603 } else {
8604 /* blx */
8605 offset &= ~(uint32_t)2;
8606 /* thumb2 bx, no need to check */
8607 gen_bx_im(s, offset);
8609 } else if (((insn >> 23) & 7) == 7) {
8610 /* Misc control */
8611 if (insn & (1 << 13))
8612 goto illegal_op;
8614 if (insn & (1 << 26)) {
8615 /* Secure monitor call (v6Z) */
8616 goto illegal_op; /* not implemented. */
8617 } else {
8618 op = (insn >> 20) & 7;
8619 switch (op) {
8620 case 0: /* msr cpsr. */
8621 if (IS_M(env)) {
8622 tmp = load_reg(s, rn);
8623 addr = tcg_const_i32(insn & 0xff);
8624 gen_helper_v7m_msr(cpu_env, addr, tmp);
8625 tcg_temp_free_i32(addr);
8626 tcg_temp_free_i32(tmp);
8627 gen_lookup_tb(s);
8628 break;
8630 /* fall through */
8631 case 1: /* msr spsr. */
8632 if (IS_M(env))
8633 goto illegal_op;
8634 tmp = load_reg(s, rn);
8635 if (gen_set_psr(s,
8636 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
8637 op == 1, tmp))
8638 goto illegal_op;
8639 break;
8640 case 2: /* cps, nop-hint. */
8641 if (((insn >> 8) & 7) == 0) {
8642 gen_nop_hint(s, insn & 0xff);
8644 /* Implemented as NOP in user mode. */
8645 if (IS_USER(s))
8646 break;
8647 offset = 0;
8648 imm = 0;
8649 if (insn & (1 << 10)) {
8650 if (insn & (1 << 7))
8651 offset |= CPSR_A;
8652 if (insn & (1 << 6))
8653 offset |= CPSR_I;
8654 if (insn & (1 << 5))
8655 offset |= CPSR_F;
8656 if (insn & (1 << 9))
8657 imm = CPSR_A | CPSR_I | CPSR_F;
8659 if (insn & (1 << 8)) {
8660 offset |= 0x1f;
8661 imm |= (insn & 0x1f);
8663 if (offset) {
8664 gen_set_psr_im(s, offset, 0, imm);
8666 break;
8667 case 3: /* Special control operations. */
8668 ARCH(7);
8669 op = (insn >> 4) & 0xf;
8670 switch (op) {
8671 case 2: /* clrex */
8672 gen_clrex(s);
8673 break;
8674 case 4: /* dsb */
8675 case 5: /* dmb */
8676 case 6: /* isb */
8677 /* These execute as NOPs. */
8678 break;
8679 default:
8680 goto illegal_op;
8682 break;
8683 case 4: /* bxj */
8684 /* Trivial implementation equivalent to bx. */
8685 tmp = load_reg(s, rn);
8686 gen_bx(s, tmp);
8687 break;
8688 case 5: /* Exception return. */
8689 if (IS_USER(s)) {
8690 goto illegal_op;
8692 if (rn != 14 || rd != 15) {
8693 goto illegal_op;
8695 tmp = load_reg(s, rn);
8696 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
8697 gen_exception_return(s, tmp);
8698 break;
8699 case 6: /* mrs cpsr. */
8700 tmp = tcg_temp_new_i32();
8701 if (IS_M(env)) {
8702 addr = tcg_const_i32(insn & 0xff);
8703 gen_helper_v7m_mrs(tmp, cpu_env, addr);
8704 tcg_temp_free_i32(addr);
8705 } else {
8706 gen_helper_cpsr_read(tmp, cpu_env);
8708 store_reg(s, rd, tmp);
8709 break;
8710 case 7: /* mrs spsr. */
8711 /* Not accessible in user mode. */
8712 if (IS_USER(s) || IS_M(env))
8713 goto illegal_op;
8714 tmp = load_cpu_field(spsr);
8715 store_reg(s, rd, tmp);
8716 break;
8719 } else {
8720 /* Conditional branch. */
8721 op = (insn >> 22) & 0xf;
8722 /* Generate a conditional jump to next instruction. */
8723 s->condlabel = gen_new_label();
8724 gen_test_cc(op ^ 1, s->condlabel);
8725 s->condjmp = 1;
8727 /* offset[11:1] = insn[10:0] */
8728 offset = (insn & 0x7ff) << 1;
8729 /* offset[17:12] = insn[21:16]. */
8730 offset |= (insn & 0x003f0000) >> 4;
8731 /* offset[31:20] = insn[26]. */
8732 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
8733 /* offset[18] = insn[13]. */
8734 offset |= (insn & (1 << 13)) << 5;
8735 /* offset[19] = insn[11]. */
8736 offset |= (insn & (1 << 11)) << 8;
8738 /* jump to the offset */
8739 gen_jmp(s, s->pc + offset);
8741 } else {
8742 /* Data processing immediate. */
8743 if (insn & (1 << 25)) {
8744 if (insn & (1 << 24)) {
8745 if (insn & (1 << 20))
8746 goto illegal_op;
8747 /* Bitfield/Saturate. */
8748 op = (insn >> 21) & 7;
8749 imm = insn & 0x1f;
8750 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
8751 if (rn == 15) {
8752 tmp = tcg_temp_new_i32();
8753 tcg_gen_movi_i32(tmp, 0);
8754 } else {
8755 tmp = load_reg(s, rn);
8757 switch (op) {
8758 case 2: /* Signed bitfield extract. */
8759 imm++;
8760 if (shift + imm > 32)
8761 goto illegal_op;
8762 if (imm < 32)
8763 gen_sbfx(tmp, shift, imm);
8764 break;
8765 case 6: /* Unsigned bitfield extract. */
8766 imm++;
8767 if (shift + imm > 32)
8768 goto illegal_op;
8769 if (imm < 32)
8770 gen_ubfx(tmp, shift, (1u << imm) - 1);
8771 break;
8772 case 3: /* Bitfield insert/clear. */
8773 if (imm < shift)
8774 goto illegal_op;
8775 imm = imm + 1 - shift;
8776 if (imm != 32) {
8777 tmp2 = load_reg(s, rd);
8778 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, imm);
8779 tcg_temp_free_i32(tmp2);
8781 break;
8782 case 7:
8783 goto illegal_op;
8784 default: /* Saturate. */
8785 if (shift) {
8786 if (op & 1)
8787 tcg_gen_sari_i32(tmp, tmp, shift);
8788 else
8789 tcg_gen_shli_i32(tmp, tmp, shift);
8791 tmp2 = tcg_const_i32(imm);
8792 if (op & 4) {
8793 /* Unsigned. */
8794 if ((op & 1) && shift == 0)
8795 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
8796 else
8797 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
8798 } else {
8799 /* Signed. */
8800 if ((op & 1) && shift == 0)
8801 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
8802 else
8803 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
8805 tcg_temp_free_i32(tmp2);
8806 break;
8808 store_reg(s, rd, tmp);
8809 } else {
8810 imm = ((insn & 0x04000000) >> 15)
8811 | ((insn & 0x7000) >> 4) | (insn & 0xff);
8812 if (insn & (1 << 22)) {
8813 /* 16-bit immediate. */
8814 imm |= (insn >> 4) & 0xf000;
8815 if (insn & (1 << 23)) {
8816 /* movt */
8817 tmp = load_reg(s, rd);
8818 tcg_gen_ext16u_i32(tmp, tmp);
8819 tcg_gen_ori_i32(tmp, tmp, imm << 16);
8820 } else {
8821 /* movw */
8822 tmp = tcg_temp_new_i32();
8823 tcg_gen_movi_i32(tmp, imm);
8825 } else {
8826 /* Add/sub 12-bit immediate. */
8827 if (rn == 15) {
8828 offset = s->pc & ~(uint32_t)3;
8829 if (insn & (1 << 23))
8830 offset -= imm;
8831 else
8832 offset += imm;
8833 tmp = tcg_temp_new_i32();
8834 tcg_gen_movi_i32(tmp, offset);
8835 } else {
8836 tmp = load_reg(s, rn);
8837 if (insn & (1 << 23))
8838 tcg_gen_subi_i32(tmp, tmp, imm);
8839 else
8840 tcg_gen_addi_i32(tmp, tmp, imm);
8843 store_reg(s, rd, tmp);
8845 } else {
8846 int shifter_out = 0;
8847 /* modified 12-bit immediate. */
8848 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
8849 imm = (insn & 0xff);
8850 switch (shift) {
8851 case 0: /* XY */
8852 /* Nothing to do. */
8853 break;
8854 case 1: /* 00XY00XY */
8855 imm |= imm << 16;
8856 break;
8857 case 2: /* XY00XY00 */
8858 imm |= imm << 16;
8859 imm <<= 8;
8860 break;
8861 case 3: /* XYXYXYXY */
8862 imm |= imm << 16;
8863 imm |= imm << 8;
8864 break;
8865 default: /* Rotated constant. */
8866 shift = (shift << 1) | (imm >> 7);
8867 imm |= 0x80;
8868 imm = imm << (32 - shift);
8869 shifter_out = 1;
8870 break;
8872 tmp2 = tcg_temp_new_i32();
8873 tcg_gen_movi_i32(tmp2, imm);
8874 rn = (insn >> 16) & 0xf;
8875 if (rn == 15) {
8876 tmp = tcg_temp_new_i32();
8877 tcg_gen_movi_i32(tmp, 0);
8878 } else {
8879 tmp = load_reg(s, rn);
8881 op = (insn >> 21) & 0xf;
8882 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
8883 shifter_out, tmp, tmp2))
8884 goto illegal_op;
8885 tcg_temp_free_i32(tmp2);
8886 rd = (insn >> 8) & 0xf;
8887 if (rd != 15) {
8888 store_reg(s, rd, tmp);
8889 } else {
8890 tcg_temp_free_i32(tmp);
8894 break;
8895 case 12: /* Load/store single data item. */
8897 int postinc = 0;
8898 int writeback = 0;
8899 int user;
8900 if ((insn & 0x01100000) == 0x01000000) {
8901 if (disas_neon_ls_insn(env, s, insn))
8902 goto illegal_op;
8903 break;
8905 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
8906 if (rs == 15) {
8907 if (!(insn & (1 << 20))) {
8908 goto illegal_op;
8910 if (op != 2) {
8911 /* Byte or halfword load space with dest == r15 : memory hints.
8912 * Catch them early so we don't emit pointless addressing code.
8913 * This space is a mix of:
8914 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
8915 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
8916 * cores)
8917 * unallocated hints, which must be treated as NOPs
8918 * UNPREDICTABLE space, which we NOP or UNDEF depending on
8919 * which is easiest for the decoding logic
8920 * Some space which must UNDEF
8922 int op1 = (insn >> 23) & 3;
8923 int op2 = (insn >> 6) & 0x3f;
8924 if (op & 2) {
8925 goto illegal_op;
8927 if (rn == 15) {
8928 /* UNPREDICTABLE, unallocated hint or
8929 * PLD/PLDW/PLI (literal)
8931 return 0;
8933 if (op1 & 1) {
8934 return 0; /* PLD/PLDW/PLI or unallocated hint */
8936 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
8937 return 0; /* PLD/PLDW/PLI or unallocated hint */
8939 /* UNDEF space, or an UNPREDICTABLE */
8940 return 1;
8943 user = IS_USER(s);
8944 if (rn == 15) {
8945 addr = tcg_temp_new_i32();
8946 /* PC relative. */
8947 /* s->pc has already been incremented by 4. */
8948 imm = s->pc & 0xfffffffc;
8949 if (insn & (1 << 23))
8950 imm += insn & 0xfff;
8951 else
8952 imm -= insn & 0xfff;
8953 tcg_gen_movi_i32(addr, imm);
8954 } else {
8955 addr = load_reg(s, rn);
8956 if (insn & (1 << 23)) {
8957 /* Positive offset. */
8958 imm = insn & 0xfff;
8959 tcg_gen_addi_i32(addr, addr, imm);
8960 } else {
8961 imm = insn & 0xff;
8962 switch ((insn >> 8) & 0xf) {
8963 case 0x0: /* Shifted Register. */
8964 shift = (insn >> 4) & 0xf;
8965 if (shift > 3) {
8966 tcg_temp_free_i32(addr);
8967 goto illegal_op;
8969 tmp = load_reg(s, rm);
8970 if (shift)
8971 tcg_gen_shli_i32(tmp, tmp, shift);
8972 tcg_gen_add_i32(addr, addr, tmp);
8973 tcg_temp_free_i32(tmp);
8974 break;
8975 case 0xc: /* Negative offset. */
8976 tcg_gen_addi_i32(addr, addr, -imm);
8977 break;
8978 case 0xe: /* User privilege. */
8979 tcg_gen_addi_i32(addr, addr, imm);
8980 user = 1;
8981 break;
8982 case 0x9: /* Post-decrement. */
8983 imm = -imm;
8984 /* Fall through. */
8985 case 0xb: /* Post-increment. */
8986 postinc = 1;
8987 writeback = 1;
8988 break;
8989 case 0xd: /* Pre-decrement. */
8990 imm = -imm;
8991 /* Fall through. */
8992 case 0xf: /* Pre-increment. */
8993 tcg_gen_addi_i32(addr, addr, imm);
8994 writeback = 1;
8995 break;
8996 default:
8997 tcg_temp_free_i32(addr);
8998 goto illegal_op;
9002 if (insn & (1 << 20)) {
9003 /* Load. */
9004 switch (op) {
9005 case 0: tmp = gen_ld8u(addr, user); break;
9006 case 4: tmp = gen_ld8s(addr, user); break;
9007 case 1: tmp = gen_ld16u(addr, user); break;
9008 case 5: tmp = gen_ld16s(addr, user); break;
9009 case 2: tmp = gen_ld32(addr, user); break;
9010 default:
9011 tcg_temp_free_i32(addr);
9012 goto illegal_op;
9014 if (rs == 15) {
9015 gen_bx(s, tmp);
9016 } else {
9017 store_reg(s, rs, tmp);
9019 } else {
9020 /* Store. */
9021 tmp = load_reg(s, rs);
9022 switch (op) {
9023 case 0: gen_st8(tmp, addr, user); break;
9024 case 1: gen_st16(tmp, addr, user); break;
9025 case 2: gen_st32(tmp, addr, user); break;
9026 default:
9027 tcg_temp_free_i32(addr);
9028 goto illegal_op;
9031 if (postinc)
9032 tcg_gen_addi_i32(addr, addr, imm);
9033 if (writeback) {
9034 store_reg(s, rn, addr);
9035 } else {
9036 tcg_temp_free_i32(addr);
9039 break;
9040 default:
9041 goto illegal_op;
9043 return 0;
9044 illegal_op:
9045 return 1;
9048 static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
9050 uint32_t val, insn, op, rm, rn, rd, shift, cond;
9051 int32_t offset;
9052 int i;
9053 TCGv tmp;
9054 TCGv tmp2;
9055 TCGv addr;
9057 if (s->condexec_mask) {
9058 cond = s->condexec_cond;
9059 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
9060 s->condlabel = gen_new_label();
9061 gen_test_cc(cond ^ 1, s->condlabel);
9062 s->condjmp = 1;
9066 insn = arm_lduw_code(env, s->pc, s->bswap_code);
9067 s->pc += 2;
9069 switch (insn >> 12) {
9070 case 0: case 1:
9072 rd = insn & 7;
9073 op = (insn >> 11) & 3;
9074 if (op == 3) {
9075 /* add/subtract */
9076 rn = (insn >> 3) & 7;
9077 tmp = load_reg(s, rn);
9078 if (insn & (1 << 10)) {
9079 /* immediate */
9080 tmp2 = tcg_temp_new_i32();
9081 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
9082 } else {
9083 /* reg */
9084 rm = (insn >> 6) & 7;
9085 tmp2 = load_reg(s, rm);
9087 if (insn & (1 << 9)) {
9088 if (s->condexec_mask)
9089 tcg_gen_sub_i32(tmp, tmp, tmp2);
9090 else
9091 gen_sub_CC(tmp, tmp, tmp2);
9092 } else {
9093 if (s->condexec_mask)
9094 tcg_gen_add_i32(tmp, tmp, tmp2);
9095 else
9096 gen_add_CC(tmp, tmp, tmp2);
9098 tcg_temp_free_i32(tmp2);
9099 store_reg(s, rd, tmp);
9100 } else {
9101 /* shift immediate */
9102 rm = (insn >> 3) & 7;
9103 shift = (insn >> 6) & 0x1f;
9104 tmp = load_reg(s, rm);
9105 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
9106 if (!s->condexec_mask)
9107 gen_logic_CC(tmp);
9108 store_reg(s, rd, tmp);
9110 break;
9111 case 2: case 3:
9112 /* arithmetic large immediate */
9113 op = (insn >> 11) & 3;
9114 rd = (insn >> 8) & 0x7;
9115 if (op == 0) { /* mov */
9116 tmp = tcg_temp_new_i32();
9117 tcg_gen_movi_i32(tmp, insn & 0xff);
9118 if (!s->condexec_mask)
9119 gen_logic_CC(tmp);
9120 store_reg(s, rd, tmp);
9121 } else {
9122 tmp = load_reg(s, rd);
9123 tmp2 = tcg_temp_new_i32();
9124 tcg_gen_movi_i32(tmp2, insn & 0xff);
9125 switch (op) {
9126 case 1: /* cmp */
9127 gen_sub_CC(tmp, tmp, tmp2);
9128 tcg_temp_free_i32(tmp);
9129 tcg_temp_free_i32(tmp2);
9130 break;
9131 case 2: /* add */
9132 if (s->condexec_mask)
9133 tcg_gen_add_i32(tmp, tmp, tmp2);
9134 else
9135 gen_add_CC(tmp, tmp, tmp2);
9136 tcg_temp_free_i32(tmp2);
9137 store_reg(s, rd, tmp);
9138 break;
9139 case 3: /* sub */
9140 if (s->condexec_mask)
9141 tcg_gen_sub_i32(tmp, tmp, tmp2);
9142 else
9143 gen_sub_CC(tmp, tmp, tmp2);
9144 tcg_temp_free_i32(tmp2);
9145 store_reg(s, rd, tmp);
9146 break;
9149 break;
9150 case 4:
9151 if (insn & (1 << 11)) {
9152 rd = (insn >> 8) & 7;
9153 /* load pc-relative. Bit 1 of PC is ignored. */
9154 val = s->pc + 2 + ((insn & 0xff) * 4);
9155 val &= ~(uint32_t)2;
9156 addr = tcg_temp_new_i32();
9157 tcg_gen_movi_i32(addr, val);
9158 tmp = gen_ld32(addr, IS_USER(s));
9159 tcg_temp_free_i32(addr);
9160 store_reg(s, rd, tmp);
9161 break;
9163 if (insn & (1 << 10)) {
9164 /* data processing extended or blx */
9165 rd = (insn & 7) | ((insn >> 4) & 8);
9166 rm = (insn >> 3) & 0xf;
9167 op = (insn >> 8) & 3;
9168 switch (op) {
9169 case 0: /* add */
9170 tmp = load_reg(s, rd);
9171 tmp2 = load_reg(s, rm);
9172 tcg_gen_add_i32(tmp, tmp, tmp2);
9173 tcg_temp_free_i32(tmp2);
9174 store_reg(s, rd, tmp);
9175 break;
9176 case 1: /* cmp */
9177 tmp = load_reg(s, rd);
9178 tmp2 = load_reg(s, rm);
9179 gen_sub_CC(tmp, tmp, tmp2);
9180 tcg_temp_free_i32(tmp2);
9181 tcg_temp_free_i32(tmp);
9182 break;
9183 case 2: /* mov/cpy */
9184 tmp = load_reg(s, rm);
9185 store_reg(s, rd, tmp);
9186 break;
9187 case 3:/* branch [and link] exchange thumb register */
9188 tmp = load_reg(s, rm);
9189 if (insn & (1 << 7)) {
9190 ARCH(5);
9191 val = (uint32_t)s->pc | 1;
9192 tmp2 = tcg_temp_new_i32();
9193 tcg_gen_movi_i32(tmp2, val);
9194 store_reg(s, 14, tmp2);
9196 /* already thumb, no need to check */
9197 gen_bx(s, tmp);
9198 break;
9200 break;
9203 /* data processing register */
9204 rd = insn & 7;
9205 rm = (insn >> 3) & 7;
9206 op = (insn >> 6) & 0xf;
9207 if (op == 2 || op == 3 || op == 4 || op == 7) {
9208 /* the shift/rotate ops want the operands backwards */
9209 val = rm;
9210 rm = rd;
9211 rd = val;
9212 val = 1;
9213 } else {
9214 val = 0;
9217 if (op == 9) { /* neg */
9218 tmp = tcg_temp_new_i32();
9219 tcg_gen_movi_i32(tmp, 0);
9220 } else if (op != 0xf) { /* mvn doesn't read its first operand */
9221 tmp = load_reg(s, rd);
9222 } else {
9223 TCGV_UNUSED(tmp);
9226 tmp2 = load_reg(s, rm);
9227 switch (op) {
9228 case 0x0: /* and */
9229 tcg_gen_and_i32(tmp, tmp, tmp2);
9230 if (!s->condexec_mask)
9231 gen_logic_CC(tmp);
9232 break;
9233 case 0x1: /* eor */
9234 tcg_gen_xor_i32(tmp, tmp, tmp2);
9235 if (!s->condexec_mask)
9236 gen_logic_CC(tmp);
9237 break;
9238 case 0x2: /* lsl */
9239 if (s->condexec_mask) {
9240 gen_shl(tmp2, tmp2, tmp);
9241 } else {
9242 gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
9243 gen_logic_CC(tmp2);
9245 break;
9246 case 0x3: /* lsr */
9247 if (s->condexec_mask) {
9248 gen_shr(tmp2, tmp2, tmp);
9249 } else {
9250 gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
9251 gen_logic_CC(tmp2);
9253 break;
9254 case 0x4: /* asr */
9255 if (s->condexec_mask) {
9256 gen_sar(tmp2, tmp2, tmp);
9257 } else {
9258 gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
9259 gen_logic_CC(tmp2);
9261 break;
9262 case 0x5: /* adc */
9263 if (s->condexec_mask) {
9264 gen_adc(tmp, tmp2);
9265 } else {
9266 gen_adc_CC(tmp, tmp, tmp2);
9268 break;
9269 case 0x6: /* sbc */
9270 if (s->condexec_mask)
9271 gen_sub_carry(tmp, tmp, tmp2);
9272 else
9273 gen_helper_sbc_cc(tmp, cpu_env, tmp, tmp2);
9274 break;
9275 case 0x7: /* ror */
9276 if (s->condexec_mask) {
9277 tcg_gen_andi_i32(tmp, tmp, 0x1f);
9278 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
9279 } else {
9280 gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);
9281 gen_logic_CC(tmp2);
9283 break;
9284 case 0x8: /* tst */
9285 tcg_gen_and_i32(tmp, tmp, tmp2);
9286 gen_logic_CC(tmp);
9287 rd = 16;
9288 break;
9289 case 0x9: /* neg */
9290 if (s->condexec_mask)
9291 tcg_gen_neg_i32(tmp, tmp2);
9292 else
9293 gen_sub_CC(tmp, tmp, tmp2);
9294 break;
9295 case 0xa: /* cmp */
9296 gen_sub_CC(tmp, tmp, tmp2);
9297 rd = 16;
9298 break;
9299 case 0xb: /* cmn */
9300 gen_add_CC(tmp, tmp, tmp2);
9301 rd = 16;
9302 break;
9303 case 0xc: /* orr */
9304 tcg_gen_or_i32(tmp, tmp, tmp2);
9305 if (!s->condexec_mask)
9306 gen_logic_CC(tmp);
9307 break;
9308 case 0xd: /* mul */
9309 tcg_gen_mul_i32(tmp, tmp, tmp2);
9310 if (!s->condexec_mask)
9311 gen_logic_CC(tmp);
9312 break;
9313 case 0xe: /* bic */
9314 tcg_gen_andc_i32(tmp, tmp, tmp2);
9315 if (!s->condexec_mask)
9316 gen_logic_CC(tmp);
9317 break;
9318 case 0xf: /* mvn */
9319 tcg_gen_not_i32(tmp2, tmp2);
9320 if (!s->condexec_mask)
9321 gen_logic_CC(tmp2);
9322 val = 1;
9323 rm = rd;
9324 break;
9326 if (rd != 16) {
9327 if (val) {
9328 store_reg(s, rm, tmp2);
9329 if (op != 0xf)
9330 tcg_temp_free_i32(tmp);
9331 } else {
9332 store_reg(s, rd, tmp);
9333 tcg_temp_free_i32(tmp2);
9335 } else {
9336 tcg_temp_free_i32(tmp);
9337 tcg_temp_free_i32(tmp2);
9339 break;
9341 case 5:
9342 /* load/store register offset. */
9343 rd = insn & 7;
9344 rn = (insn >> 3) & 7;
9345 rm = (insn >> 6) & 7;
9346 op = (insn >> 9) & 7;
9347 addr = load_reg(s, rn);
9348 tmp = load_reg(s, rm);
9349 tcg_gen_add_i32(addr, addr, tmp);
9350 tcg_temp_free_i32(tmp);
9352 if (op < 3) /* store */
9353 tmp = load_reg(s, rd);
9355 switch (op) {
9356 case 0: /* str */
9357 gen_st32(tmp, addr, IS_USER(s));
9358 break;
9359 case 1: /* strh */
9360 gen_st16(tmp, addr, IS_USER(s));
9361 break;
9362 case 2: /* strb */
9363 gen_st8(tmp, addr, IS_USER(s));
9364 break;
9365 case 3: /* ldrsb */
9366 tmp = gen_ld8s(addr, IS_USER(s));
9367 break;
9368 case 4: /* ldr */
9369 tmp = gen_ld32(addr, IS_USER(s));
9370 break;
9371 case 5: /* ldrh */
9372 tmp = gen_ld16u(addr, IS_USER(s));
9373 break;
9374 case 6: /* ldrb */
9375 tmp = gen_ld8u(addr, IS_USER(s));
9376 break;
9377 case 7: /* ldrsh */
9378 tmp = gen_ld16s(addr, IS_USER(s));
9379 break;
9381 if (op >= 3) /* load */
9382 store_reg(s, rd, tmp);
9383 tcg_temp_free_i32(addr);
9384 break;
9386 case 6:
9387 /* load/store word immediate offset */
9388 rd = insn & 7;
9389 rn = (insn >> 3) & 7;
9390 addr = load_reg(s, rn);
9391 val = (insn >> 4) & 0x7c;
9392 tcg_gen_addi_i32(addr, addr, val);
9394 if (insn & (1 << 11)) {
9395 /* load */
9396 tmp = gen_ld32(addr, IS_USER(s));
9397 store_reg(s, rd, tmp);
9398 } else {
9399 /* store */
9400 tmp = load_reg(s, rd);
9401 gen_st32(tmp, addr, IS_USER(s));
9403 tcg_temp_free_i32(addr);
9404 break;
9406 case 7:
9407 /* load/store byte immediate offset */
9408 rd = insn & 7;
9409 rn = (insn >> 3) & 7;
9410 addr = load_reg(s, rn);
9411 val = (insn >> 6) & 0x1f;
9412 tcg_gen_addi_i32(addr, addr, val);
9414 if (insn & (1 << 11)) {
9415 /* load */
9416 tmp = gen_ld8u(addr, IS_USER(s));
9417 store_reg(s, rd, tmp);
9418 } else {
9419 /* store */
9420 tmp = load_reg(s, rd);
9421 gen_st8(tmp, addr, IS_USER(s));
9423 tcg_temp_free_i32(addr);
9424 break;
9426 case 8:
9427 /* load/store halfword immediate offset */
9428 rd = insn & 7;
9429 rn = (insn >> 3) & 7;
9430 addr = load_reg(s, rn);
9431 val = (insn >> 5) & 0x3e;
9432 tcg_gen_addi_i32(addr, addr, val);
9434 if (insn & (1 << 11)) {
9435 /* load */
9436 tmp = gen_ld16u(addr, IS_USER(s));
9437 store_reg(s, rd, tmp);
9438 } else {
9439 /* store */
9440 tmp = load_reg(s, rd);
9441 gen_st16(tmp, addr, IS_USER(s));
9443 tcg_temp_free_i32(addr);
9444 break;
9446 case 9:
9447 /* load/store from stack */
9448 rd = (insn >> 8) & 7;
9449 addr = load_reg(s, 13);
9450 val = (insn & 0xff) * 4;
9451 tcg_gen_addi_i32(addr, addr, val);
9453 if (insn & (1 << 11)) {
9454 /* load */
9455 tmp = gen_ld32(addr, IS_USER(s));
9456 store_reg(s, rd, tmp);
9457 } else {
9458 /* store */
9459 tmp = load_reg(s, rd);
9460 gen_st32(tmp, addr, IS_USER(s));
9462 tcg_temp_free_i32(addr);
9463 break;
9465 case 10:
9466 /* add to high reg */
9467 rd = (insn >> 8) & 7;
9468 if (insn & (1 << 11)) {
9469 /* SP */
9470 tmp = load_reg(s, 13);
9471 } else {
9472 /* PC. bit 1 is ignored. */
9473 tmp = tcg_temp_new_i32();
9474 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
9476 val = (insn & 0xff) * 4;
9477 tcg_gen_addi_i32(tmp, tmp, val);
9478 store_reg(s, rd, tmp);
9479 break;
9481 case 11:
9482 /* misc */
9483 op = (insn >> 8) & 0xf;
9484 switch (op) {
9485 case 0:
9486 /* adjust stack pointer */
9487 tmp = load_reg(s, 13);
9488 val = (insn & 0x7f) * 4;
9489 if (insn & (1 << 7))
9490 val = -(int32_t)val;
9491 tcg_gen_addi_i32(tmp, tmp, val);
9492 store_reg(s, 13, tmp);
9493 break;
9495 case 2: /* sign/zero extend. */
9496 ARCH(6);
9497 rd = insn & 7;
9498 rm = (insn >> 3) & 7;
9499 tmp = load_reg(s, rm);
9500 switch ((insn >> 6) & 3) {
9501 case 0: gen_sxth(tmp); break;
9502 case 1: gen_sxtb(tmp); break;
9503 case 2: gen_uxth(tmp); break;
9504 case 3: gen_uxtb(tmp); break;
9506 store_reg(s, rd, tmp);
9507 break;
9508 case 4: case 5: case 0xc: case 0xd:
9509 /* push/pop */
9510 addr = load_reg(s, 13);
9511 if (insn & (1 << 8))
9512 offset = 4;
9513 else
9514 offset = 0;
9515 for (i = 0; i < 8; i++) {
9516 if (insn & (1 << i))
9517 offset += 4;
9519 if ((insn & (1 << 11)) == 0) {
9520 tcg_gen_addi_i32(addr, addr, -offset);
9522 for (i = 0; i < 8; i++) {
9523 if (insn & (1 << i)) {
9524 if (insn & (1 << 11)) {
9525 /* pop */
9526 tmp = gen_ld32(addr, IS_USER(s));
9527 store_reg(s, i, tmp);
9528 } else {
9529 /* push */
9530 tmp = load_reg(s, i);
9531 gen_st32(tmp, addr, IS_USER(s));
9533 /* advance to the next address. */
9534 tcg_gen_addi_i32(addr, addr, 4);
9537 TCGV_UNUSED(tmp);
9538 if (insn & (1 << 8)) {
9539 if (insn & (1 << 11)) {
9540 /* pop pc */
9541 tmp = gen_ld32(addr, IS_USER(s));
9542 /* don't set the pc until the rest of the instruction
9543 has completed */
9544 } else {
9545 /* push lr */
9546 tmp = load_reg(s, 14);
9547 gen_st32(tmp, addr, IS_USER(s));
9549 tcg_gen_addi_i32(addr, addr, 4);
9551 if ((insn & (1 << 11)) == 0) {
9552 tcg_gen_addi_i32(addr, addr, -offset);
9554 /* write back the new stack pointer */
9555 store_reg(s, 13, addr);
9556 /* set the new PC value */
9557 if ((insn & 0x0900) == 0x0900) {
9558 store_reg_from_load(env, s, 15, tmp);
9560 break;
9562 case 1: case 3: case 9: case 11: /* czb */
9563 rm = insn & 7;
9564 tmp = load_reg(s, rm);
9565 s->condlabel = gen_new_label();
9566 s->condjmp = 1;
9567 if (insn & (1 << 11))
9568 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
9569 else
9570 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
9571 tcg_temp_free_i32(tmp);
9572 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
9573 val = (uint32_t)s->pc + 2;
9574 val += offset;
9575 gen_jmp(s, val);
9576 break;
9578 case 15: /* IT, nop-hint. */
9579 if ((insn & 0xf) == 0) {
9580 gen_nop_hint(s, (insn >> 4) & 0xf);
9581 break;
9583 /* If Then. */
9584 s->condexec_cond = (insn >> 4) & 0xe;
9585 s->condexec_mask = insn & 0x1f;
9586 /* No actual code generated for this insn, just setup state. */
9587 break;
9589 case 0xe: /* bkpt */
9590 ARCH(5);
9591 gen_exception_insn(s, 2, EXCP_BKPT);
9592 break;
9594 case 0xa: /* rev */
9595 ARCH(6);
9596 rn = (insn >> 3) & 0x7;
9597 rd = insn & 0x7;
9598 tmp = load_reg(s, rn);
9599 switch ((insn >> 6) & 3) {
9600 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
9601 case 1: gen_rev16(tmp); break;
9602 case 3: gen_revsh(tmp); break;
9603 default: goto illegal_op;
9605 store_reg(s, rd, tmp);
9606 break;
9608 case 6:
9609 switch ((insn >> 5) & 7) {
9610 case 2:
9611 /* setend */
9612 ARCH(6);
9613 if (((insn >> 3) & 1) != s->bswap_code) {
9614 /* Dynamic endianness switching not implemented. */
9615 goto illegal_op;
9617 break;
9618 case 3:
9619 /* cps */
9620 ARCH(6);
9621 if (IS_USER(s)) {
9622 break;
9624 if (IS_M(env)) {
9625 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
9626 /* FAULTMASK */
9627 if (insn & 1) {
9628 addr = tcg_const_i32(19);
9629 gen_helper_v7m_msr(cpu_env, addr, tmp);
9630 tcg_temp_free_i32(addr);
9632 /* PRIMASK */
9633 if (insn & 2) {
9634 addr = tcg_const_i32(16);
9635 gen_helper_v7m_msr(cpu_env, addr, tmp);
9636 tcg_temp_free_i32(addr);
9638 tcg_temp_free_i32(tmp);
9639 gen_lookup_tb(s);
9640 } else {
9641 if (insn & (1 << 4)) {
9642 shift = CPSR_A | CPSR_I | CPSR_F;
9643 } else {
9644 shift = 0;
9646 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
9648 break;
9649 default:
9650 goto undef;
9652 break;
9654 default:
9655 goto undef;
9657 break;
9659 case 12:
9661 /* load/store multiple */
9662 TCGv loaded_var;
9663 TCGV_UNUSED(loaded_var);
9664 rn = (insn >> 8) & 0x7;
9665 addr = load_reg(s, rn);
9666 for (i = 0; i < 8; i++) {
9667 if (insn & (1 << i)) {
9668 if (insn & (1 << 11)) {
9669 /* load */
9670 tmp = gen_ld32(addr, IS_USER(s));
9671 if (i == rn) {
9672 loaded_var = tmp;
9673 } else {
9674 store_reg(s, i, tmp);
9676 } else {
9677 /* store */
9678 tmp = load_reg(s, i);
9679 gen_st32(tmp, addr, IS_USER(s));
9681 /* advance to the next address */
9682 tcg_gen_addi_i32(addr, addr, 4);
9685 if ((insn & (1 << rn)) == 0) {
9686 /* base reg not in list: base register writeback */
9687 store_reg(s, rn, addr);
9688 } else {
9689 /* base reg in list: if load, complete it now */
9690 if (insn & (1 << 11)) {
9691 store_reg(s, rn, loaded_var);
9693 tcg_temp_free_i32(addr);
9695 break;
9697 case 13:
9698 /* conditional branch or swi */
9699 cond = (insn >> 8) & 0xf;
9700 if (cond == 0xe)
9701 goto undef;
9703 if (cond == 0xf) {
9704 /* swi */
9705 gen_set_pc_im(s->pc);
9706 s->is_jmp = DISAS_SWI;
9707 break;
9709 /* generate a conditional jump to next instruction */
9710 s->condlabel = gen_new_label();
9711 gen_test_cc(cond ^ 1, s->condlabel);
9712 s->condjmp = 1;
9714 /* jump to the offset */
9715 val = (uint32_t)s->pc + 2;
9716 offset = ((int32_t)insn << 24) >> 24;
9717 val += offset << 1;
9718 gen_jmp(s, val);
9719 break;
9721 case 14:
9722 if (insn & (1 << 11)) {
9723 if (disas_thumb2_insn(env, s, insn))
9724 goto undef32;
9725 break;
9727 /* unconditional branch */
9728 val = (uint32_t)s->pc;
9729 offset = ((int32_t)insn << 21) >> 21;
9730 val += (offset << 1) + 2;
9731 gen_jmp(s, val);
9732 break;
9734 case 15:
9735 if (disas_thumb2_insn(env, s, insn))
9736 goto undef32;
9737 break;
9739 return;
9740 undef32:
9741 gen_exception_insn(s, 4, EXCP_UDEF);
9742 return;
9743 illegal_op:
9744 undef:
9745 gen_exception_insn(s, 2, EXCP_UDEF);
9748 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
9749 basic block 'tb'. If search_pc is TRUE, also generate PC
9750 information for each intermediate instruction. */
9751 static inline void gen_intermediate_code_internal(CPUARMState *env,
9752 TranslationBlock *tb,
9753 int search_pc)
9755 DisasContext dc1, *dc = &dc1;
9756 CPUBreakpoint *bp;
9757 uint16_t *gen_opc_end;
9758 int j, lj;
9759 target_ulong pc_start;
9760 uint32_t next_page_start;
9761 int num_insns;
9762 int max_insns;
9764 /* generate intermediate code */
9765 pc_start = tb->pc;
9767 dc->tb = tb;
9769 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
9771 dc->is_jmp = DISAS_NEXT;
9772 dc->pc = pc_start;
9773 dc->singlestep_enabled = env->singlestep_enabled;
9774 dc->condjmp = 0;
9775 dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
9776 dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags);
9777 dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
9778 dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
9779 #if !defined(CONFIG_USER_ONLY)
9780 dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
9781 #endif
9782 dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
9783 dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
9784 dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
9785 cpu_F0s = tcg_temp_new_i32();
9786 cpu_F1s = tcg_temp_new_i32();
9787 cpu_F0d = tcg_temp_new_i64();
9788 cpu_F1d = tcg_temp_new_i64();
9789 cpu_V0 = cpu_F0d;
9790 cpu_V1 = cpu_F1d;
9791 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
9792 cpu_M0 = tcg_temp_new_i64();
9793 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
9794 lj = -1;
9795 num_insns = 0;
9796 max_insns = tb->cflags & CF_COUNT_MASK;
9797 if (max_insns == 0)
9798 max_insns = CF_COUNT_MASK;
9800 gen_icount_start();
9802 tcg_clear_temp_count();
9804 /* A note on handling of the condexec (IT) bits:
9806 * We want to avoid the overhead of having to write the updated condexec
9807 * bits back to the CPUARMState for every instruction in an IT block. So:
9808 * (1) if the condexec bits are not already zero then we write
9809 * zero back into the CPUARMState now. This avoids complications trying
9810 * to do it at the end of the block. (For example if we don't do this
9811 * it's hard to identify whether we can safely skip writing condexec
9812 * at the end of the TB, which we definitely want to do for the case
9813 * where a TB doesn't do anything with the IT state at all.)
9814 * (2) if we are going to leave the TB then we call gen_set_condexec()
9815 * which will write the correct value into CPUARMState if zero is wrong.
9816 * This is done both for leaving the TB at the end, and for leaving
9817 * it because of an exception we know will happen, which is done in
9818 * gen_exception_insn(). The latter is necessary because we need to
9819 * leave the TB with the PC/IT state just prior to execution of the
9820 * instruction which caused the exception.
9821 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
9822 * then the CPUARMState will be wrong and we need to reset it.
9823 * This is handled in the same way as restoration of the
9824 * PC in these situations: we will be called again with search_pc=1
9825 * and generate a mapping of the condexec bits for each PC in
9826 * gen_opc_condexec_bits[]. restore_state_to_opc() then uses
9827 * this to restore the condexec bits.
9829 * Note that there are no instructions which can read the condexec
9830 * bits, and none which can write non-static values to them, so
9831 * we don't need to care about whether CPUARMState is correct in the
9832 * middle of a TB.
9835 /* Reset the conditional execution bits immediately. This avoids
9836 complications trying to do it at the end of the block. */
9837 if (dc->condexec_mask || dc->condexec_cond)
9839 TCGv tmp = tcg_temp_new_i32();
9840 tcg_gen_movi_i32(tmp, 0);
9841 store_cpu_field(tmp, condexec_bits);
9843 do {
9844 #ifdef CONFIG_USER_ONLY
9845 /* Intercept jump to the magic kernel page. */
9846 if (dc->pc >= 0xffff0000) {
9847 /* We always get here via a jump, so know we are not in a
9848 conditional execution block. */
9849 gen_exception(EXCP_KERNEL_TRAP);
9850 dc->is_jmp = DISAS_UPDATE;
9851 break;
9853 #else
9854 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
9855 /* We always get here via a jump, so know we are not in a
9856 conditional execution block. */
9857 gen_exception(EXCP_EXCEPTION_EXIT);
9858 dc->is_jmp = DISAS_UPDATE;
9859 break;
9861 #endif
9863 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
9864 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
9865 if (bp->pc == dc->pc) {
9866 gen_exception_insn(dc, 0, EXCP_DEBUG);
9867 /* Advance PC so that clearing the breakpoint will
9868 invalidate this TB. */
9869 dc->pc += 2;
9870 goto done_generating;
9871 break;
9875 if (search_pc) {
9876 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
9877 if (lj < j) {
9878 lj++;
9879 while (lj < j)
9880 tcg_ctx.gen_opc_instr_start[lj++] = 0;
9882 tcg_ctx.gen_opc_pc[lj] = dc->pc;
9883 gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
9884 tcg_ctx.gen_opc_instr_start[lj] = 1;
9885 tcg_ctx.gen_opc_icount[lj] = num_insns;
9888 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
9889 gen_io_start();
9891 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
9892 tcg_gen_debug_insn_start(dc->pc);
9895 if (dc->thumb) {
9896 disas_thumb_insn(env, dc);
9897 if (dc->condexec_mask) {
9898 dc->condexec_cond = (dc->condexec_cond & 0xe)
9899 | ((dc->condexec_mask >> 4) & 1);
9900 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
9901 if (dc->condexec_mask == 0) {
9902 dc->condexec_cond = 0;
9905 } else {
9906 disas_arm_insn(env, dc);
9909 if (dc->condjmp && !dc->is_jmp) {
9910 gen_set_label(dc->condlabel);
9911 dc->condjmp = 0;
9914 if (tcg_check_temp_count()) {
9915 fprintf(stderr, "TCG temporary leak before %08x\n", dc->pc);
9918 /* Translation stops when a conditional branch is encountered.
9919 * Otherwise the subsequent code could get translated several times.
9920 * Also stop translation when a page boundary is reached. This
9921 * ensures prefetch aborts occur at the right place. */
9922 num_insns ++;
9923 } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
9924 !env->singlestep_enabled &&
9925 !singlestep &&
9926 dc->pc < next_page_start &&
9927 num_insns < max_insns);
9929 if (tb->cflags & CF_LAST_IO) {
9930 if (dc->condjmp) {
9931 /* FIXME: This can theoretically happen with self-modifying
9932 code. */
9933 cpu_abort(env, "IO on conditional branch instruction");
9935 gen_io_end();
9938 /* At this stage dc->condjmp will only be set when the skipped
9939 instruction was a conditional branch or trap, and the PC has
9940 already been written. */
9941 if (unlikely(env->singlestep_enabled)) {
9942 /* Make sure the pc is updated, and raise a debug exception. */
9943 if (dc->condjmp) {
9944 gen_set_condexec(dc);
9945 if (dc->is_jmp == DISAS_SWI) {
9946 gen_exception(EXCP_SWI);
9947 } else {
9948 gen_exception(EXCP_DEBUG);
9950 gen_set_label(dc->condlabel);
9952 if (dc->condjmp || !dc->is_jmp) {
9953 gen_set_pc_im(dc->pc);
9954 dc->condjmp = 0;
9956 gen_set_condexec(dc);
9957 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
9958 gen_exception(EXCP_SWI);
9959 } else {
9960 /* FIXME: Single stepping a WFI insn will not halt
9961 the CPU. */
9962 gen_exception(EXCP_DEBUG);
9964 } else {
9965 /* While branches must always occur at the end of an IT block,
9966 there are a few other things that can cause us to terminate
9967 the TB in the middle of an IT block:
9968 - Exception generating instructions (bkpt, swi, undefined).
9969 - Page boundaries.
9970 - Hardware watchpoints.
9971 Hardware breakpoints have already been handled and skip this code.
9973 gen_set_condexec(dc);
9974 switch(dc->is_jmp) {
9975 case DISAS_NEXT:
9976 gen_goto_tb(dc, 1, dc->pc);
9977 break;
9978 default:
9979 case DISAS_JUMP:
9980 case DISAS_UPDATE:
9981 /* indicate that the hash table must be used to find the next TB */
9982 tcg_gen_exit_tb(0);
9983 break;
9984 case DISAS_TB_JUMP:
9985 /* nothing more to generate */
9986 break;
9987 case DISAS_WFI:
9988 gen_helper_wfi(cpu_env);
9989 break;
9990 case DISAS_SWI:
9991 gen_exception(EXCP_SWI);
9992 break;
9994 if (dc->condjmp) {
9995 gen_set_label(dc->condlabel);
9996 gen_set_condexec(dc);
9997 gen_goto_tb(dc, 1, dc->pc);
9998 dc->condjmp = 0;
10002 done_generating:
10003 gen_icount_end(tb, num_insns);
10004 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
10006 #ifdef DEBUG_DISAS
10007 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
10008 qemu_log("----------------\n");
10009 qemu_log("IN: %s\n", lookup_symbol(pc_start));
10010 log_target_disas(env, pc_start, dc->pc - pc_start,
10011 dc->thumb | (dc->bswap_code << 1));
10012 qemu_log("\n");
10014 #endif
10015 if (search_pc) {
10016 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
10017 lj++;
10018 while (lj <= j)
10019 tcg_ctx.gen_opc_instr_start[lj++] = 0;
10020 } else {
10021 tb->size = dc->pc - pc_start;
10022 tb->icount = num_insns;
10026 void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
10028 gen_intermediate_code_internal(env, tb, 0);
10031 void gen_intermediate_code_pc(CPUARMState *env, TranslationBlock *tb)
10033 gen_intermediate_code_internal(env, tb, 1);
10036 static const char *cpu_mode_names[16] = {
10037 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
10038 "???", "???", "???", "und", "???", "???", "???", "sys"
10041 void cpu_dump_state(CPUARMState *env, FILE *f, fprintf_function cpu_fprintf,
10042 int flags)
10044 int i;
10045 uint32_t psr;
10047 for(i=0;i<16;i++) {
10048 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
10049 if ((i % 4) == 3)
10050 cpu_fprintf(f, "\n");
10051 else
10052 cpu_fprintf(f, " ");
10054 psr = cpsr_read(env);
10055 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
10056 psr,
10057 psr & (1 << 31) ? 'N' : '-',
10058 psr & (1 << 30) ? 'Z' : '-',
10059 psr & (1 << 29) ? 'C' : '-',
10060 psr & (1 << 28) ? 'V' : '-',
10061 psr & CPSR_T ? 'T' : 'A',
10062 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
10064 if (flags & CPU_DUMP_FPU) {
10065 int numvfpregs = 0;
10066 if (arm_feature(env, ARM_FEATURE_VFP)) {
10067 numvfpregs += 16;
10069 if (arm_feature(env, ARM_FEATURE_VFP3)) {
10070 numvfpregs += 16;
10072 for (i = 0; i < numvfpregs; i++) {
10073 uint64_t v = float64_val(env->vfp.regs[i]);
10074 cpu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
10075 i * 2, (uint32_t)v,
10076 i * 2 + 1, (uint32_t)(v >> 32),
10077 i, v);
10079 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
10083 void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos)
10085 env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
10086 env->condexec_bits = gen_opc_condexec_bits[pc_pos];