target-arm: Handle UNDEF and UNPREDICTABLE cases for VLDM, VSTM
[qemu.git] / target-arm / translate.c
blob7acb498277c2d2da639de3f5b7f9c34a1ad16031
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.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 condtional execution bits. */
57 int condexec_mask;
58 int condexec_cond;
59 struct TranslationBlock *tb;
60 int singlestep_enabled;
61 int thumb;
62 #if !defined(CONFIG_USER_ONLY)
63 int user;
64 #endif
65 int vfp_enabled;
66 int vec_len;
67 int vec_stride;
68 } DisasContext;
70 static uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE];
72 #if defined(CONFIG_USER_ONLY)
73 #define IS_USER(s) 1
74 #else
75 #define IS_USER(s) (s->user)
76 #endif
78 /* These instructions trap after executing, so defer them until after the
79 conditional executions state has been updated. */
80 #define DISAS_WFI 4
81 #define DISAS_SWI 5
83 static TCGv_ptr cpu_env;
84 /* We reuse the same 64-bit temporaries for efficiency. */
85 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
86 static TCGv_i32 cpu_R[16];
87 static TCGv_i32 cpu_exclusive_addr;
88 static TCGv_i32 cpu_exclusive_val;
89 static TCGv_i32 cpu_exclusive_high;
90 #ifdef CONFIG_USER_ONLY
91 static TCGv_i32 cpu_exclusive_test;
92 static TCGv_i32 cpu_exclusive_info;
93 #endif
95 /* FIXME: These should be removed. */
96 static TCGv cpu_F0s, cpu_F1s;
97 static TCGv_i64 cpu_F0d, cpu_F1d;
99 #include "gen-icount.h"
101 static const char *regnames[] =
102 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
103 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
105 /* initialize TCG globals. */
106 void arm_translate_init(void)
108 int i;
110 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
112 for (i = 0; i < 16; i++) {
113 cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
114 offsetof(CPUState, regs[i]),
115 regnames[i]);
117 cpu_exclusive_addr = tcg_global_mem_new_i32(TCG_AREG0,
118 offsetof(CPUState, exclusive_addr), "exclusive_addr");
119 cpu_exclusive_val = tcg_global_mem_new_i32(TCG_AREG0,
120 offsetof(CPUState, exclusive_val), "exclusive_val");
121 cpu_exclusive_high = tcg_global_mem_new_i32(TCG_AREG0,
122 offsetof(CPUState, exclusive_high), "exclusive_high");
123 #ifdef CONFIG_USER_ONLY
124 cpu_exclusive_test = tcg_global_mem_new_i32(TCG_AREG0,
125 offsetof(CPUState, exclusive_test), "exclusive_test");
126 cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0,
127 offsetof(CPUState, exclusive_info), "exclusive_info");
128 #endif
130 #define GEN_HELPER 2
131 #include "helper.h"
134 static inline TCGv load_cpu_offset(int offset)
136 TCGv tmp = tcg_temp_new_i32();
137 tcg_gen_ld_i32(tmp, cpu_env, offset);
138 return tmp;
141 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
143 static inline void store_cpu_offset(TCGv var, int offset)
145 tcg_gen_st_i32(var, cpu_env, offset);
146 tcg_temp_free_i32(var);
149 #define store_cpu_field(var, name) \
150 store_cpu_offset(var, offsetof(CPUState, name))
152 /* Set a variable to the value of a CPU register. */
153 static void load_reg_var(DisasContext *s, TCGv var, int reg)
155 if (reg == 15) {
156 uint32_t addr;
157 /* normaly, since we updated PC, we need only to add one insn */
158 if (s->thumb)
159 addr = (long)s->pc + 2;
160 else
161 addr = (long)s->pc + 4;
162 tcg_gen_movi_i32(var, addr);
163 } else {
164 tcg_gen_mov_i32(var, cpu_R[reg]);
168 /* Create a new temporary and set it to the value of a CPU register. */
169 static inline TCGv load_reg(DisasContext *s, int reg)
171 TCGv tmp = tcg_temp_new_i32();
172 load_reg_var(s, tmp, reg);
173 return tmp;
176 /* Set a CPU register. The source must be a temporary and will be
177 marked as dead. */
178 static void store_reg(DisasContext *s, int reg, TCGv var)
180 if (reg == 15) {
181 tcg_gen_andi_i32(var, var, ~1);
182 s->is_jmp = DISAS_JUMP;
184 tcg_gen_mov_i32(cpu_R[reg], var);
185 tcg_temp_free_i32(var);
188 /* Value extensions. */
189 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
190 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
191 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
192 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
194 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
195 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
198 static inline void gen_set_cpsr(TCGv var, uint32_t mask)
200 TCGv tmp_mask = tcg_const_i32(mask);
201 gen_helper_cpsr_write(var, tmp_mask);
202 tcg_temp_free_i32(tmp_mask);
204 /* Set NZCV flags from the high 4 bits of var. */
205 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
207 static void gen_exception(int excp)
209 TCGv tmp = tcg_temp_new_i32();
210 tcg_gen_movi_i32(tmp, excp);
211 gen_helper_exception(tmp);
212 tcg_temp_free_i32(tmp);
215 static void gen_smul_dual(TCGv a, TCGv b)
217 TCGv tmp1 = tcg_temp_new_i32();
218 TCGv tmp2 = tcg_temp_new_i32();
219 tcg_gen_ext16s_i32(tmp1, a);
220 tcg_gen_ext16s_i32(tmp2, b);
221 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
222 tcg_temp_free_i32(tmp2);
223 tcg_gen_sari_i32(a, a, 16);
224 tcg_gen_sari_i32(b, b, 16);
225 tcg_gen_mul_i32(b, b, a);
226 tcg_gen_mov_i32(a, tmp1);
227 tcg_temp_free_i32(tmp1);
230 /* Byteswap each halfword. */
231 static void gen_rev16(TCGv var)
233 TCGv tmp = tcg_temp_new_i32();
234 tcg_gen_shri_i32(tmp, var, 8);
235 tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
236 tcg_gen_shli_i32(var, var, 8);
237 tcg_gen_andi_i32(var, var, 0xff00ff00);
238 tcg_gen_or_i32(var, var, tmp);
239 tcg_temp_free_i32(tmp);
242 /* Byteswap low halfword and sign extend. */
243 static void gen_revsh(TCGv var)
245 tcg_gen_ext16u_i32(var, var);
246 tcg_gen_bswap16_i32(var, var);
247 tcg_gen_ext16s_i32(var, var);
250 /* Unsigned bitfield extract. */
251 static void gen_ubfx(TCGv var, int shift, uint32_t mask)
253 if (shift)
254 tcg_gen_shri_i32(var, var, shift);
255 tcg_gen_andi_i32(var, var, mask);
258 /* Signed bitfield extract. */
259 static void gen_sbfx(TCGv var, int shift, int width)
261 uint32_t signbit;
263 if (shift)
264 tcg_gen_sari_i32(var, var, shift);
265 if (shift + width < 32) {
266 signbit = 1u << (width - 1);
267 tcg_gen_andi_i32(var, var, (1u << width) - 1);
268 tcg_gen_xori_i32(var, var, signbit);
269 tcg_gen_subi_i32(var, var, signbit);
273 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
274 static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
276 tcg_gen_andi_i32(val, val, mask);
277 tcg_gen_shli_i32(val, val, shift);
278 tcg_gen_andi_i32(base, base, ~(mask << shift));
279 tcg_gen_or_i32(dest, base, val);
282 /* Return (b << 32) + a. Mark inputs as dead */
283 static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv b)
285 TCGv_i64 tmp64 = tcg_temp_new_i64();
287 tcg_gen_extu_i32_i64(tmp64, b);
288 tcg_temp_free_i32(b);
289 tcg_gen_shli_i64(tmp64, tmp64, 32);
290 tcg_gen_add_i64(a, tmp64, a);
292 tcg_temp_free_i64(tmp64);
293 return a;
296 /* Return (b << 32) - a. Mark inputs as dead. */
297 static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv b)
299 TCGv_i64 tmp64 = tcg_temp_new_i64();
301 tcg_gen_extu_i32_i64(tmp64, b);
302 tcg_temp_free_i32(b);
303 tcg_gen_shli_i64(tmp64, tmp64, 32);
304 tcg_gen_sub_i64(a, tmp64, a);
306 tcg_temp_free_i64(tmp64);
307 return a;
310 /* FIXME: Most targets have native widening multiplication.
311 It would be good to use that instead of a full wide multiply. */
312 /* 32x32->64 multiply. Marks inputs as dead. */
313 static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b)
315 TCGv_i64 tmp1 = tcg_temp_new_i64();
316 TCGv_i64 tmp2 = tcg_temp_new_i64();
318 tcg_gen_extu_i32_i64(tmp1, a);
319 tcg_temp_free_i32(a);
320 tcg_gen_extu_i32_i64(tmp2, b);
321 tcg_temp_free_i32(b);
322 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
323 tcg_temp_free_i64(tmp2);
324 return tmp1;
327 static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
329 TCGv_i64 tmp1 = tcg_temp_new_i64();
330 TCGv_i64 tmp2 = tcg_temp_new_i64();
332 tcg_gen_ext_i32_i64(tmp1, a);
333 tcg_temp_free_i32(a);
334 tcg_gen_ext_i32_i64(tmp2, b);
335 tcg_temp_free_i32(b);
336 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
337 tcg_temp_free_i64(tmp2);
338 return tmp1;
341 /* Swap low and high halfwords. */
342 static void gen_swap_half(TCGv var)
344 TCGv tmp = tcg_temp_new_i32();
345 tcg_gen_shri_i32(tmp, var, 16);
346 tcg_gen_shli_i32(var, var, 16);
347 tcg_gen_or_i32(var, var, tmp);
348 tcg_temp_free_i32(tmp);
351 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
352 tmp = (t0 ^ t1) & 0x8000;
353 t0 &= ~0x8000;
354 t1 &= ~0x8000;
355 t0 = (t0 + t1) ^ tmp;
358 static void gen_add16(TCGv t0, TCGv t1)
360 TCGv tmp = tcg_temp_new_i32();
361 tcg_gen_xor_i32(tmp, t0, t1);
362 tcg_gen_andi_i32(tmp, tmp, 0x8000);
363 tcg_gen_andi_i32(t0, t0, ~0x8000);
364 tcg_gen_andi_i32(t1, t1, ~0x8000);
365 tcg_gen_add_i32(t0, t0, t1);
366 tcg_gen_xor_i32(t0, t0, tmp);
367 tcg_temp_free_i32(tmp);
368 tcg_temp_free_i32(t1);
371 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
373 /* Set CF to the top bit of var. */
374 static void gen_set_CF_bit31(TCGv var)
376 TCGv tmp = tcg_temp_new_i32();
377 tcg_gen_shri_i32(tmp, var, 31);
378 gen_set_CF(tmp);
379 tcg_temp_free_i32(tmp);
382 /* Set N and Z flags from var. */
383 static inline void gen_logic_CC(TCGv var)
385 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF));
386 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF));
389 /* T0 += T1 + CF. */
390 static void gen_adc(TCGv t0, TCGv t1)
392 TCGv tmp;
393 tcg_gen_add_i32(t0, t0, t1);
394 tmp = load_cpu_field(CF);
395 tcg_gen_add_i32(t0, t0, tmp);
396 tcg_temp_free_i32(tmp);
399 /* dest = T0 + T1 + CF. */
400 static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
402 TCGv tmp;
403 tcg_gen_add_i32(dest, t0, t1);
404 tmp = load_cpu_field(CF);
405 tcg_gen_add_i32(dest, dest, tmp);
406 tcg_temp_free_i32(tmp);
409 /* dest = T0 - T1 + CF - 1. */
410 static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
412 TCGv tmp;
413 tcg_gen_sub_i32(dest, t0, t1);
414 tmp = load_cpu_field(CF);
415 tcg_gen_add_i32(dest, dest, tmp);
416 tcg_gen_subi_i32(dest, dest, 1);
417 tcg_temp_free_i32(tmp);
420 /* FIXME: Implement this natively. */
421 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
423 static void shifter_out_im(TCGv var, int shift)
425 TCGv tmp = tcg_temp_new_i32();
426 if (shift == 0) {
427 tcg_gen_andi_i32(tmp, var, 1);
428 } else {
429 tcg_gen_shri_i32(tmp, var, shift);
430 if (shift != 31)
431 tcg_gen_andi_i32(tmp, tmp, 1);
433 gen_set_CF(tmp);
434 tcg_temp_free_i32(tmp);
437 /* Shift by immediate. Includes special handling for shift == 0. */
438 static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
440 switch (shiftop) {
441 case 0: /* LSL */
442 if (shift != 0) {
443 if (flags)
444 shifter_out_im(var, 32 - shift);
445 tcg_gen_shli_i32(var, var, shift);
447 break;
448 case 1: /* LSR */
449 if (shift == 0) {
450 if (flags) {
451 tcg_gen_shri_i32(var, var, 31);
452 gen_set_CF(var);
454 tcg_gen_movi_i32(var, 0);
455 } else {
456 if (flags)
457 shifter_out_im(var, shift - 1);
458 tcg_gen_shri_i32(var, var, shift);
460 break;
461 case 2: /* ASR */
462 if (shift == 0)
463 shift = 32;
464 if (flags)
465 shifter_out_im(var, shift - 1);
466 if (shift == 32)
467 shift = 31;
468 tcg_gen_sari_i32(var, var, shift);
469 break;
470 case 3: /* ROR/RRX */
471 if (shift != 0) {
472 if (flags)
473 shifter_out_im(var, shift - 1);
474 tcg_gen_rotri_i32(var, var, shift); break;
475 } else {
476 TCGv tmp = load_cpu_field(CF);
477 if (flags)
478 shifter_out_im(var, 0);
479 tcg_gen_shri_i32(var, var, 1);
480 tcg_gen_shli_i32(tmp, tmp, 31);
481 tcg_gen_or_i32(var, var, tmp);
482 tcg_temp_free_i32(tmp);
487 static inline void gen_arm_shift_reg(TCGv var, int shiftop,
488 TCGv shift, int flags)
490 if (flags) {
491 switch (shiftop) {
492 case 0: gen_helper_shl_cc(var, var, shift); break;
493 case 1: gen_helper_shr_cc(var, var, shift); break;
494 case 2: gen_helper_sar_cc(var, var, shift); break;
495 case 3: gen_helper_ror_cc(var, var, shift); break;
497 } else {
498 switch (shiftop) {
499 case 0: gen_helper_shl(var, var, shift); break;
500 case 1: gen_helper_shr(var, var, shift); break;
501 case 2: gen_helper_sar(var, var, shift); break;
502 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
503 tcg_gen_rotr_i32(var, var, shift); break;
506 tcg_temp_free_i32(shift);
509 #define PAS_OP(pfx) \
510 switch (op2) { \
511 case 0: gen_pas_helper(glue(pfx,add16)); break; \
512 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
513 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
514 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
515 case 4: gen_pas_helper(glue(pfx,add8)); break; \
516 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
518 static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
520 TCGv_ptr tmp;
522 switch (op1) {
523 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
524 case 1:
525 tmp = tcg_temp_new_ptr();
526 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
527 PAS_OP(s)
528 tcg_temp_free_ptr(tmp);
529 break;
530 case 5:
531 tmp = tcg_temp_new_ptr();
532 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
533 PAS_OP(u)
534 tcg_temp_free_ptr(tmp);
535 break;
536 #undef gen_pas_helper
537 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
538 case 2:
539 PAS_OP(q);
540 break;
541 case 3:
542 PAS_OP(sh);
543 break;
544 case 6:
545 PAS_OP(uq);
546 break;
547 case 7:
548 PAS_OP(uh);
549 break;
550 #undef gen_pas_helper
553 #undef PAS_OP
555 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
556 #define PAS_OP(pfx) \
557 switch (op1) { \
558 case 0: gen_pas_helper(glue(pfx,add8)); break; \
559 case 1: gen_pas_helper(glue(pfx,add16)); break; \
560 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
561 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
562 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
563 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
565 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
567 TCGv_ptr tmp;
569 switch (op2) {
570 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
571 case 0:
572 tmp = tcg_temp_new_ptr();
573 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
574 PAS_OP(s)
575 tcg_temp_free_ptr(tmp);
576 break;
577 case 4:
578 tmp = tcg_temp_new_ptr();
579 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
580 PAS_OP(u)
581 tcg_temp_free_ptr(tmp);
582 break;
583 #undef gen_pas_helper
584 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
585 case 1:
586 PAS_OP(q);
587 break;
588 case 2:
589 PAS_OP(sh);
590 break;
591 case 5:
592 PAS_OP(uq);
593 break;
594 case 6:
595 PAS_OP(uh);
596 break;
597 #undef gen_pas_helper
600 #undef PAS_OP
602 static void gen_test_cc(int cc, int label)
604 TCGv tmp;
605 TCGv tmp2;
606 int inv;
608 switch (cc) {
609 case 0: /* eq: Z */
610 tmp = load_cpu_field(ZF);
611 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
612 break;
613 case 1: /* ne: !Z */
614 tmp = load_cpu_field(ZF);
615 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
616 break;
617 case 2: /* cs: C */
618 tmp = load_cpu_field(CF);
619 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
620 break;
621 case 3: /* cc: !C */
622 tmp = load_cpu_field(CF);
623 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
624 break;
625 case 4: /* mi: N */
626 tmp = load_cpu_field(NF);
627 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
628 break;
629 case 5: /* pl: !N */
630 tmp = load_cpu_field(NF);
631 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
632 break;
633 case 6: /* vs: V */
634 tmp = load_cpu_field(VF);
635 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
636 break;
637 case 7: /* vc: !V */
638 tmp = load_cpu_field(VF);
639 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
640 break;
641 case 8: /* hi: C && !Z */
642 inv = gen_new_label();
643 tmp = load_cpu_field(CF);
644 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
645 tcg_temp_free_i32(tmp);
646 tmp = load_cpu_field(ZF);
647 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
648 gen_set_label(inv);
649 break;
650 case 9: /* ls: !C || Z */
651 tmp = load_cpu_field(CF);
652 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
653 tcg_temp_free_i32(tmp);
654 tmp = load_cpu_field(ZF);
655 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
656 break;
657 case 10: /* ge: N == V -> N ^ V == 0 */
658 tmp = load_cpu_field(VF);
659 tmp2 = load_cpu_field(NF);
660 tcg_gen_xor_i32(tmp, tmp, tmp2);
661 tcg_temp_free_i32(tmp2);
662 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
663 break;
664 case 11: /* lt: N != V -> N ^ V != 0 */
665 tmp = load_cpu_field(VF);
666 tmp2 = load_cpu_field(NF);
667 tcg_gen_xor_i32(tmp, tmp, tmp2);
668 tcg_temp_free_i32(tmp2);
669 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
670 break;
671 case 12: /* gt: !Z && N == V */
672 inv = gen_new_label();
673 tmp = load_cpu_field(ZF);
674 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
675 tcg_temp_free_i32(tmp);
676 tmp = load_cpu_field(VF);
677 tmp2 = load_cpu_field(NF);
678 tcg_gen_xor_i32(tmp, tmp, tmp2);
679 tcg_temp_free_i32(tmp2);
680 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
681 gen_set_label(inv);
682 break;
683 case 13: /* le: Z || N != V */
684 tmp = load_cpu_field(ZF);
685 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
686 tcg_temp_free_i32(tmp);
687 tmp = load_cpu_field(VF);
688 tmp2 = load_cpu_field(NF);
689 tcg_gen_xor_i32(tmp, tmp, tmp2);
690 tcg_temp_free_i32(tmp2);
691 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
692 break;
693 default:
694 fprintf(stderr, "Bad condition code 0x%x\n", cc);
695 abort();
697 tcg_temp_free_i32(tmp);
700 static const uint8_t table_logic_cc[16] = {
701 1, /* and */
702 1, /* xor */
703 0, /* sub */
704 0, /* rsb */
705 0, /* add */
706 0, /* adc */
707 0, /* sbc */
708 0, /* rsc */
709 1, /* andl */
710 1, /* xorl */
711 0, /* cmp */
712 0, /* cmn */
713 1, /* orr */
714 1, /* mov */
715 1, /* bic */
716 1, /* mvn */
719 /* Set PC and Thumb state from an immediate address. */
720 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
722 TCGv tmp;
724 s->is_jmp = DISAS_UPDATE;
725 if (s->thumb != (addr & 1)) {
726 tmp = tcg_temp_new_i32();
727 tcg_gen_movi_i32(tmp, addr & 1);
728 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
729 tcg_temp_free_i32(tmp);
731 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
734 /* Set PC and Thumb state from var. var is marked as dead. */
735 static inline void gen_bx(DisasContext *s, TCGv var)
737 s->is_jmp = DISAS_UPDATE;
738 tcg_gen_andi_i32(cpu_R[15], var, ~1);
739 tcg_gen_andi_i32(var, var, 1);
740 store_cpu_field(var, thumb);
743 /* Variant of store_reg which uses branch&exchange logic when storing
744 to r15 in ARM architecture v7 and above. The source must be a temporary
745 and will be marked as dead. */
746 static inline void store_reg_bx(CPUState *env, DisasContext *s,
747 int reg, TCGv var)
749 if (reg == 15 && ENABLE_ARCH_7) {
750 gen_bx(s, var);
751 } else {
752 store_reg(s, reg, var);
756 /* Variant of store_reg which uses branch&exchange logic when storing
757 * to r15 in ARM architecture v5T and above. This is used for storing
758 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
759 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
760 static inline void store_reg_from_load(CPUState *env, DisasContext *s,
761 int reg, TCGv var)
763 if (reg == 15 && ENABLE_ARCH_5) {
764 gen_bx(s, var);
765 } else {
766 store_reg(s, reg, var);
770 static inline TCGv gen_ld8s(TCGv addr, int index)
772 TCGv tmp = tcg_temp_new_i32();
773 tcg_gen_qemu_ld8s(tmp, addr, index);
774 return tmp;
776 static inline TCGv gen_ld8u(TCGv addr, int index)
778 TCGv tmp = tcg_temp_new_i32();
779 tcg_gen_qemu_ld8u(tmp, addr, index);
780 return tmp;
782 static inline TCGv gen_ld16s(TCGv addr, int index)
784 TCGv tmp = tcg_temp_new_i32();
785 tcg_gen_qemu_ld16s(tmp, addr, index);
786 return tmp;
788 static inline TCGv gen_ld16u(TCGv addr, int index)
790 TCGv tmp = tcg_temp_new_i32();
791 tcg_gen_qemu_ld16u(tmp, addr, index);
792 return tmp;
794 static inline TCGv gen_ld32(TCGv addr, int index)
796 TCGv tmp = tcg_temp_new_i32();
797 tcg_gen_qemu_ld32u(tmp, addr, index);
798 return tmp;
800 static inline TCGv_i64 gen_ld64(TCGv addr, int index)
802 TCGv_i64 tmp = tcg_temp_new_i64();
803 tcg_gen_qemu_ld64(tmp, addr, index);
804 return tmp;
806 static inline void gen_st8(TCGv val, TCGv addr, int index)
808 tcg_gen_qemu_st8(val, addr, index);
809 tcg_temp_free_i32(val);
811 static inline void gen_st16(TCGv val, TCGv addr, int index)
813 tcg_gen_qemu_st16(val, addr, index);
814 tcg_temp_free_i32(val);
816 static inline void gen_st32(TCGv val, TCGv addr, int index)
818 tcg_gen_qemu_st32(val, addr, index);
819 tcg_temp_free_i32(val);
821 static inline void gen_st64(TCGv_i64 val, TCGv addr, int index)
823 tcg_gen_qemu_st64(val, addr, index);
824 tcg_temp_free_i64(val);
827 static inline void gen_set_pc_im(uint32_t val)
829 tcg_gen_movi_i32(cpu_R[15], val);
832 /* Force a TB lookup after an instruction that changes the CPU state. */
833 static inline void gen_lookup_tb(DisasContext *s)
835 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
836 s->is_jmp = DISAS_UPDATE;
839 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
840 TCGv var)
842 int val, rm, shift, shiftop;
843 TCGv offset;
845 if (!(insn & (1 << 25))) {
846 /* immediate */
847 val = insn & 0xfff;
848 if (!(insn & (1 << 23)))
849 val = -val;
850 if (val != 0)
851 tcg_gen_addi_i32(var, var, val);
852 } else {
853 /* shift/register */
854 rm = (insn) & 0xf;
855 shift = (insn >> 7) & 0x1f;
856 shiftop = (insn >> 5) & 3;
857 offset = load_reg(s, rm);
858 gen_arm_shift_im(offset, shiftop, shift, 0);
859 if (!(insn & (1 << 23)))
860 tcg_gen_sub_i32(var, var, offset);
861 else
862 tcg_gen_add_i32(var, var, offset);
863 tcg_temp_free_i32(offset);
867 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
868 int extra, TCGv var)
870 int val, rm;
871 TCGv offset;
873 if (insn & (1 << 22)) {
874 /* immediate */
875 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
876 if (!(insn & (1 << 23)))
877 val = -val;
878 val += extra;
879 if (val != 0)
880 tcg_gen_addi_i32(var, var, val);
881 } else {
882 /* register */
883 if (extra)
884 tcg_gen_addi_i32(var, var, extra);
885 rm = (insn) & 0xf;
886 offset = load_reg(s, rm);
887 if (!(insn & (1 << 23)))
888 tcg_gen_sub_i32(var, var, offset);
889 else
890 tcg_gen_add_i32(var, var, offset);
891 tcg_temp_free_i32(offset);
895 static TCGv_ptr get_fpstatus_ptr(int neon)
897 TCGv_ptr statusptr = tcg_temp_new_ptr();
898 int offset;
899 if (neon) {
900 offset = offsetof(CPUState, vfp.standard_fp_status);
901 } else {
902 offset = offsetof(CPUState, vfp.fp_status);
904 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
905 return statusptr;
908 #define VFP_OP2(name) \
909 static inline void gen_vfp_##name(int dp) \
911 TCGv_ptr fpst = get_fpstatus_ptr(0); \
912 if (dp) { \
913 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, fpst); \
914 } else { \
915 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, fpst); \
917 tcg_temp_free_ptr(fpst); \
920 VFP_OP2(add)
921 VFP_OP2(sub)
922 VFP_OP2(mul)
923 VFP_OP2(div)
925 #undef VFP_OP2
927 static inline void gen_vfp_F1_mul(int dp)
929 /* Like gen_vfp_mul() but put result in F1 */
930 TCGv_ptr fpst = get_fpstatus_ptr(0);
931 if (dp) {
932 gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, fpst);
933 } else {
934 gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, fpst);
936 tcg_temp_free_ptr(fpst);
939 static inline void gen_vfp_F1_neg(int dp)
941 /* Like gen_vfp_neg() but put result in F1 */
942 if (dp) {
943 gen_helper_vfp_negd(cpu_F1d, cpu_F0d);
944 } else {
945 gen_helper_vfp_negs(cpu_F1s, cpu_F0s);
949 static inline void gen_vfp_abs(int dp)
951 if (dp)
952 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
953 else
954 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
957 static inline void gen_vfp_neg(int dp)
959 if (dp)
960 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
961 else
962 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
965 static inline void gen_vfp_sqrt(int dp)
967 if (dp)
968 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
969 else
970 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
973 static inline void gen_vfp_cmp(int dp)
975 if (dp)
976 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
977 else
978 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
981 static inline void gen_vfp_cmpe(int dp)
983 if (dp)
984 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
985 else
986 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
989 static inline void gen_vfp_F1_ld0(int dp)
991 if (dp)
992 tcg_gen_movi_i64(cpu_F1d, 0);
993 else
994 tcg_gen_movi_i32(cpu_F1s, 0);
997 #define VFP_GEN_ITOF(name) \
998 static inline void gen_vfp_##name(int dp, int neon) \
1000 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1001 if (dp) { \
1002 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
1003 } else { \
1004 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1006 tcg_temp_free_ptr(statusptr); \
1009 VFP_GEN_ITOF(uito)
1010 VFP_GEN_ITOF(sito)
1011 #undef VFP_GEN_ITOF
1013 #define VFP_GEN_FTOI(name) \
1014 static inline void gen_vfp_##name(int dp, int neon) \
1016 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1017 if (dp) { \
1018 gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
1019 } else { \
1020 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1022 tcg_temp_free_ptr(statusptr); \
1025 VFP_GEN_FTOI(toui)
1026 VFP_GEN_FTOI(touiz)
1027 VFP_GEN_FTOI(tosi)
1028 VFP_GEN_FTOI(tosiz)
1029 #undef VFP_GEN_FTOI
1031 #define VFP_GEN_FIX(name) \
1032 static inline void gen_vfp_##name(int dp, int shift, int neon) \
1034 TCGv tmp_shift = tcg_const_i32(shift); \
1035 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1036 if (dp) { \
1037 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, statusptr); \
1038 } else { \
1039 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, statusptr); \
1041 tcg_temp_free_i32(tmp_shift); \
1042 tcg_temp_free_ptr(statusptr); \
1044 VFP_GEN_FIX(tosh)
1045 VFP_GEN_FIX(tosl)
1046 VFP_GEN_FIX(touh)
1047 VFP_GEN_FIX(toul)
1048 VFP_GEN_FIX(shto)
1049 VFP_GEN_FIX(slto)
1050 VFP_GEN_FIX(uhto)
1051 VFP_GEN_FIX(ulto)
1052 #undef VFP_GEN_FIX
1054 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv addr)
1056 if (dp)
1057 tcg_gen_qemu_ld64(cpu_F0d, addr, IS_USER(s));
1058 else
1059 tcg_gen_qemu_ld32u(cpu_F0s, addr, IS_USER(s));
1062 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv addr)
1064 if (dp)
1065 tcg_gen_qemu_st64(cpu_F0d, addr, IS_USER(s));
1066 else
1067 tcg_gen_qemu_st32(cpu_F0s, addr, IS_USER(s));
1070 static inline long
1071 vfp_reg_offset (int dp, int reg)
1073 if (dp)
1074 return offsetof(CPUARMState, vfp.regs[reg]);
1075 else if (reg & 1) {
1076 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1077 + offsetof(CPU_DoubleU, l.upper);
1078 } else {
1079 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1080 + offsetof(CPU_DoubleU, l.lower);
1084 /* Return the offset of a 32-bit piece of a NEON register.
1085 zero is the least significant end of the register. */
1086 static inline long
1087 neon_reg_offset (int reg, int n)
1089 int sreg;
1090 sreg = reg * 2 + n;
1091 return vfp_reg_offset(0, sreg);
1094 static TCGv neon_load_reg(int reg, int pass)
1096 TCGv tmp = tcg_temp_new_i32();
1097 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1098 return tmp;
1101 static void neon_store_reg(int reg, int pass, TCGv var)
1103 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1104 tcg_temp_free_i32(var);
1107 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1109 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1112 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1114 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1117 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1118 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1119 #define tcg_gen_st_f32 tcg_gen_st_i32
1120 #define tcg_gen_st_f64 tcg_gen_st_i64
1122 static inline void gen_mov_F0_vreg(int dp, int reg)
1124 if (dp)
1125 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1126 else
1127 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1130 static inline void gen_mov_F1_vreg(int dp, int reg)
1132 if (dp)
1133 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1134 else
1135 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1138 static inline void gen_mov_vreg_F0(int dp, int reg)
1140 if (dp)
1141 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1142 else
1143 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1146 #define ARM_CP_RW_BIT (1 << 20)
1148 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1150 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1153 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1155 tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1158 static inline TCGv iwmmxt_load_creg(int reg)
1160 TCGv var = tcg_temp_new_i32();
1161 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1162 return var;
1165 static inline void iwmmxt_store_creg(int reg, TCGv var)
1167 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1168 tcg_temp_free_i32(var);
1171 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1173 iwmmxt_store_reg(cpu_M0, rn);
1176 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1178 iwmmxt_load_reg(cpu_M0, rn);
1181 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1183 iwmmxt_load_reg(cpu_V1, rn);
1184 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1187 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1189 iwmmxt_load_reg(cpu_V1, rn);
1190 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1193 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1195 iwmmxt_load_reg(cpu_V1, rn);
1196 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1199 #define IWMMXT_OP(name) \
1200 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1202 iwmmxt_load_reg(cpu_V1, rn); \
1203 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1206 #define IWMMXT_OP_ENV(name) \
1207 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1209 iwmmxt_load_reg(cpu_V1, rn); \
1210 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1213 #define IWMMXT_OP_ENV_SIZE(name) \
1214 IWMMXT_OP_ENV(name##b) \
1215 IWMMXT_OP_ENV(name##w) \
1216 IWMMXT_OP_ENV(name##l)
1218 #define IWMMXT_OP_ENV1(name) \
1219 static inline void gen_op_iwmmxt_##name##_M0(void) \
1221 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1224 IWMMXT_OP(maddsq)
1225 IWMMXT_OP(madduq)
1226 IWMMXT_OP(sadb)
1227 IWMMXT_OP(sadw)
1228 IWMMXT_OP(mulslw)
1229 IWMMXT_OP(mulshw)
1230 IWMMXT_OP(mululw)
1231 IWMMXT_OP(muluhw)
1232 IWMMXT_OP(macsw)
1233 IWMMXT_OP(macuw)
1235 IWMMXT_OP_ENV_SIZE(unpackl)
1236 IWMMXT_OP_ENV_SIZE(unpackh)
1238 IWMMXT_OP_ENV1(unpacklub)
1239 IWMMXT_OP_ENV1(unpackluw)
1240 IWMMXT_OP_ENV1(unpacklul)
1241 IWMMXT_OP_ENV1(unpackhub)
1242 IWMMXT_OP_ENV1(unpackhuw)
1243 IWMMXT_OP_ENV1(unpackhul)
1244 IWMMXT_OP_ENV1(unpacklsb)
1245 IWMMXT_OP_ENV1(unpacklsw)
1246 IWMMXT_OP_ENV1(unpacklsl)
1247 IWMMXT_OP_ENV1(unpackhsb)
1248 IWMMXT_OP_ENV1(unpackhsw)
1249 IWMMXT_OP_ENV1(unpackhsl)
1251 IWMMXT_OP_ENV_SIZE(cmpeq)
1252 IWMMXT_OP_ENV_SIZE(cmpgtu)
1253 IWMMXT_OP_ENV_SIZE(cmpgts)
1255 IWMMXT_OP_ENV_SIZE(mins)
1256 IWMMXT_OP_ENV_SIZE(minu)
1257 IWMMXT_OP_ENV_SIZE(maxs)
1258 IWMMXT_OP_ENV_SIZE(maxu)
1260 IWMMXT_OP_ENV_SIZE(subn)
1261 IWMMXT_OP_ENV_SIZE(addn)
1262 IWMMXT_OP_ENV_SIZE(subu)
1263 IWMMXT_OP_ENV_SIZE(addu)
1264 IWMMXT_OP_ENV_SIZE(subs)
1265 IWMMXT_OP_ENV_SIZE(adds)
1267 IWMMXT_OP_ENV(avgb0)
1268 IWMMXT_OP_ENV(avgb1)
1269 IWMMXT_OP_ENV(avgw0)
1270 IWMMXT_OP_ENV(avgw1)
1272 IWMMXT_OP(msadb)
1274 IWMMXT_OP_ENV(packuw)
1275 IWMMXT_OP_ENV(packul)
1276 IWMMXT_OP_ENV(packuq)
1277 IWMMXT_OP_ENV(packsw)
1278 IWMMXT_OP_ENV(packsl)
1279 IWMMXT_OP_ENV(packsq)
1281 static void gen_op_iwmmxt_set_mup(void)
1283 TCGv tmp;
1284 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1285 tcg_gen_ori_i32(tmp, tmp, 2);
1286 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1289 static void gen_op_iwmmxt_set_cup(void)
1291 TCGv tmp;
1292 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1293 tcg_gen_ori_i32(tmp, tmp, 1);
1294 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1297 static void gen_op_iwmmxt_setpsr_nz(void)
1299 TCGv tmp = tcg_temp_new_i32();
1300 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1301 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1304 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1306 iwmmxt_load_reg(cpu_V1, rn);
1307 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1308 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1311 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn, TCGv dest)
1313 int rd;
1314 uint32_t offset;
1315 TCGv tmp;
1317 rd = (insn >> 16) & 0xf;
1318 tmp = load_reg(s, rd);
1320 offset = (insn & 0xff) << ((insn >> 7) & 2);
1321 if (insn & (1 << 24)) {
1322 /* Pre indexed */
1323 if (insn & (1 << 23))
1324 tcg_gen_addi_i32(tmp, tmp, offset);
1325 else
1326 tcg_gen_addi_i32(tmp, tmp, -offset);
1327 tcg_gen_mov_i32(dest, tmp);
1328 if (insn & (1 << 21))
1329 store_reg(s, rd, tmp);
1330 else
1331 tcg_temp_free_i32(tmp);
1332 } else if (insn & (1 << 21)) {
1333 /* Post indexed */
1334 tcg_gen_mov_i32(dest, tmp);
1335 if (insn & (1 << 23))
1336 tcg_gen_addi_i32(tmp, tmp, offset);
1337 else
1338 tcg_gen_addi_i32(tmp, tmp, -offset);
1339 store_reg(s, rd, tmp);
1340 } else if (!(insn & (1 << 23)))
1341 return 1;
1342 return 0;
1345 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv dest)
1347 int rd = (insn >> 0) & 0xf;
1348 TCGv tmp;
1350 if (insn & (1 << 8)) {
1351 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1352 return 1;
1353 } else {
1354 tmp = iwmmxt_load_creg(rd);
1356 } else {
1357 tmp = tcg_temp_new_i32();
1358 iwmmxt_load_reg(cpu_V0, rd);
1359 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
1361 tcg_gen_andi_i32(tmp, tmp, mask);
1362 tcg_gen_mov_i32(dest, tmp);
1363 tcg_temp_free_i32(tmp);
1364 return 0;
1367 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
1368 (ie. an undefined instruction). */
1369 static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1371 int rd, wrd;
1372 int rdhi, rdlo, rd0, rd1, i;
1373 TCGv addr;
1374 TCGv tmp, tmp2, tmp3;
1376 if ((insn & 0x0e000e00) == 0x0c000000) {
1377 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1378 wrd = insn & 0xf;
1379 rdlo = (insn >> 12) & 0xf;
1380 rdhi = (insn >> 16) & 0xf;
1381 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1382 iwmmxt_load_reg(cpu_V0, wrd);
1383 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
1384 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1385 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
1386 } else { /* TMCRR */
1387 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1388 iwmmxt_store_reg(cpu_V0, wrd);
1389 gen_op_iwmmxt_set_mup();
1391 return 0;
1394 wrd = (insn >> 12) & 0xf;
1395 addr = tcg_temp_new_i32();
1396 if (gen_iwmmxt_address(s, insn, addr)) {
1397 tcg_temp_free_i32(addr);
1398 return 1;
1400 if (insn & ARM_CP_RW_BIT) {
1401 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1402 tmp = tcg_temp_new_i32();
1403 tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s));
1404 iwmmxt_store_creg(wrd, tmp);
1405 } else {
1406 i = 1;
1407 if (insn & (1 << 8)) {
1408 if (insn & (1 << 22)) { /* WLDRD */
1409 tcg_gen_qemu_ld64(cpu_M0, addr, IS_USER(s));
1410 i = 0;
1411 } else { /* WLDRW wRd */
1412 tmp = gen_ld32(addr, IS_USER(s));
1414 } else {
1415 if (insn & (1 << 22)) { /* WLDRH */
1416 tmp = gen_ld16u(addr, IS_USER(s));
1417 } else { /* WLDRB */
1418 tmp = gen_ld8u(addr, IS_USER(s));
1421 if (i) {
1422 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1423 tcg_temp_free_i32(tmp);
1425 gen_op_iwmmxt_movq_wRn_M0(wrd);
1427 } else {
1428 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1429 tmp = iwmmxt_load_creg(wrd);
1430 gen_st32(tmp, addr, IS_USER(s));
1431 } else {
1432 gen_op_iwmmxt_movq_M0_wRn(wrd);
1433 tmp = tcg_temp_new_i32();
1434 if (insn & (1 << 8)) {
1435 if (insn & (1 << 22)) { /* WSTRD */
1436 tcg_temp_free_i32(tmp);
1437 tcg_gen_qemu_st64(cpu_M0, addr, IS_USER(s));
1438 } else { /* WSTRW wRd */
1439 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1440 gen_st32(tmp, addr, IS_USER(s));
1442 } else {
1443 if (insn & (1 << 22)) { /* WSTRH */
1444 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1445 gen_st16(tmp, addr, IS_USER(s));
1446 } else { /* WSTRB */
1447 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1448 gen_st8(tmp, addr, IS_USER(s));
1453 tcg_temp_free_i32(addr);
1454 return 0;
1457 if ((insn & 0x0f000000) != 0x0e000000)
1458 return 1;
1460 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1461 case 0x000: /* WOR */
1462 wrd = (insn >> 12) & 0xf;
1463 rd0 = (insn >> 0) & 0xf;
1464 rd1 = (insn >> 16) & 0xf;
1465 gen_op_iwmmxt_movq_M0_wRn(rd0);
1466 gen_op_iwmmxt_orq_M0_wRn(rd1);
1467 gen_op_iwmmxt_setpsr_nz();
1468 gen_op_iwmmxt_movq_wRn_M0(wrd);
1469 gen_op_iwmmxt_set_mup();
1470 gen_op_iwmmxt_set_cup();
1471 break;
1472 case 0x011: /* TMCR */
1473 if (insn & 0xf)
1474 return 1;
1475 rd = (insn >> 12) & 0xf;
1476 wrd = (insn >> 16) & 0xf;
1477 switch (wrd) {
1478 case ARM_IWMMXT_wCID:
1479 case ARM_IWMMXT_wCASF:
1480 break;
1481 case ARM_IWMMXT_wCon:
1482 gen_op_iwmmxt_set_cup();
1483 /* Fall through. */
1484 case ARM_IWMMXT_wCSSF:
1485 tmp = iwmmxt_load_creg(wrd);
1486 tmp2 = load_reg(s, rd);
1487 tcg_gen_andc_i32(tmp, tmp, tmp2);
1488 tcg_temp_free_i32(tmp2);
1489 iwmmxt_store_creg(wrd, tmp);
1490 break;
1491 case ARM_IWMMXT_wCGR0:
1492 case ARM_IWMMXT_wCGR1:
1493 case ARM_IWMMXT_wCGR2:
1494 case ARM_IWMMXT_wCGR3:
1495 gen_op_iwmmxt_set_cup();
1496 tmp = load_reg(s, rd);
1497 iwmmxt_store_creg(wrd, tmp);
1498 break;
1499 default:
1500 return 1;
1502 break;
1503 case 0x100: /* WXOR */
1504 wrd = (insn >> 12) & 0xf;
1505 rd0 = (insn >> 0) & 0xf;
1506 rd1 = (insn >> 16) & 0xf;
1507 gen_op_iwmmxt_movq_M0_wRn(rd0);
1508 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1509 gen_op_iwmmxt_setpsr_nz();
1510 gen_op_iwmmxt_movq_wRn_M0(wrd);
1511 gen_op_iwmmxt_set_mup();
1512 gen_op_iwmmxt_set_cup();
1513 break;
1514 case 0x111: /* TMRC */
1515 if (insn & 0xf)
1516 return 1;
1517 rd = (insn >> 12) & 0xf;
1518 wrd = (insn >> 16) & 0xf;
1519 tmp = iwmmxt_load_creg(wrd);
1520 store_reg(s, rd, tmp);
1521 break;
1522 case 0x300: /* WANDN */
1523 wrd = (insn >> 12) & 0xf;
1524 rd0 = (insn >> 0) & 0xf;
1525 rd1 = (insn >> 16) & 0xf;
1526 gen_op_iwmmxt_movq_M0_wRn(rd0);
1527 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1528 gen_op_iwmmxt_andq_M0_wRn(rd1);
1529 gen_op_iwmmxt_setpsr_nz();
1530 gen_op_iwmmxt_movq_wRn_M0(wrd);
1531 gen_op_iwmmxt_set_mup();
1532 gen_op_iwmmxt_set_cup();
1533 break;
1534 case 0x200: /* WAND */
1535 wrd = (insn >> 12) & 0xf;
1536 rd0 = (insn >> 0) & 0xf;
1537 rd1 = (insn >> 16) & 0xf;
1538 gen_op_iwmmxt_movq_M0_wRn(rd0);
1539 gen_op_iwmmxt_andq_M0_wRn(rd1);
1540 gen_op_iwmmxt_setpsr_nz();
1541 gen_op_iwmmxt_movq_wRn_M0(wrd);
1542 gen_op_iwmmxt_set_mup();
1543 gen_op_iwmmxt_set_cup();
1544 break;
1545 case 0x810: case 0xa10: /* WMADD */
1546 wrd = (insn >> 12) & 0xf;
1547 rd0 = (insn >> 0) & 0xf;
1548 rd1 = (insn >> 16) & 0xf;
1549 gen_op_iwmmxt_movq_M0_wRn(rd0);
1550 if (insn & (1 << 21))
1551 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1552 else
1553 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1554 gen_op_iwmmxt_movq_wRn_M0(wrd);
1555 gen_op_iwmmxt_set_mup();
1556 break;
1557 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1558 wrd = (insn >> 12) & 0xf;
1559 rd0 = (insn >> 16) & 0xf;
1560 rd1 = (insn >> 0) & 0xf;
1561 gen_op_iwmmxt_movq_M0_wRn(rd0);
1562 switch ((insn >> 22) & 3) {
1563 case 0:
1564 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1565 break;
1566 case 1:
1567 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1568 break;
1569 case 2:
1570 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1571 break;
1572 case 3:
1573 return 1;
1575 gen_op_iwmmxt_movq_wRn_M0(wrd);
1576 gen_op_iwmmxt_set_mup();
1577 gen_op_iwmmxt_set_cup();
1578 break;
1579 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1580 wrd = (insn >> 12) & 0xf;
1581 rd0 = (insn >> 16) & 0xf;
1582 rd1 = (insn >> 0) & 0xf;
1583 gen_op_iwmmxt_movq_M0_wRn(rd0);
1584 switch ((insn >> 22) & 3) {
1585 case 0:
1586 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1587 break;
1588 case 1:
1589 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1590 break;
1591 case 2:
1592 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1593 break;
1594 case 3:
1595 return 1;
1597 gen_op_iwmmxt_movq_wRn_M0(wrd);
1598 gen_op_iwmmxt_set_mup();
1599 gen_op_iwmmxt_set_cup();
1600 break;
1601 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1602 wrd = (insn >> 12) & 0xf;
1603 rd0 = (insn >> 16) & 0xf;
1604 rd1 = (insn >> 0) & 0xf;
1605 gen_op_iwmmxt_movq_M0_wRn(rd0);
1606 if (insn & (1 << 22))
1607 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1608 else
1609 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1610 if (!(insn & (1 << 20)))
1611 gen_op_iwmmxt_addl_M0_wRn(wrd);
1612 gen_op_iwmmxt_movq_wRn_M0(wrd);
1613 gen_op_iwmmxt_set_mup();
1614 break;
1615 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1616 wrd = (insn >> 12) & 0xf;
1617 rd0 = (insn >> 16) & 0xf;
1618 rd1 = (insn >> 0) & 0xf;
1619 gen_op_iwmmxt_movq_M0_wRn(rd0);
1620 if (insn & (1 << 21)) {
1621 if (insn & (1 << 20))
1622 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1623 else
1624 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1625 } else {
1626 if (insn & (1 << 20))
1627 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1628 else
1629 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1631 gen_op_iwmmxt_movq_wRn_M0(wrd);
1632 gen_op_iwmmxt_set_mup();
1633 break;
1634 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1635 wrd = (insn >> 12) & 0xf;
1636 rd0 = (insn >> 16) & 0xf;
1637 rd1 = (insn >> 0) & 0xf;
1638 gen_op_iwmmxt_movq_M0_wRn(rd0);
1639 if (insn & (1 << 21))
1640 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1641 else
1642 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1643 if (!(insn & (1 << 20))) {
1644 iwmmxt_load_reg(cpu_V1, wrd);
1645 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1647 gen_op_iwmmxt_movq_wRn_M0(wrd);
1648 gen_op_iwmmxt_set_mup();
1649 break;
1650 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1651 wrd = (insn >> 12) & 0xf;
1652 rd0 = (insn >> 16) & 0xf;
1653 rd1 = (insn >> 0) & 0xf;
1654 gen_op_iwmmxt_movq_M0_wRn(rd0);
1655 switch ((insn >> 22) & 3) {
1656 case 0:
1657 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1658 break;
1659 case 1:
1660 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1661 break;
1662 case 2:
1663 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1664 break;
1665 case 3:
1666 return 1;
1668 gen_op_iwmmxt_movq_wRn_M0(wrd);
1669 gen_op_iwmmxt_set_mup();
1670 gen_op_iwmmxt_set_cup();
1671 break;
1672 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1673 wrd = (insn >> 12) & 0xf;
1674 rd0 = (insn >> 16) & 0xf;
1675 rd1 = (insn >> 0) & 0xf;
1676 gen_op_iwmmxt_movq_M0_wRn(rd0);
1677 if (insn & (1 << 22)) {
1678 if (insn & (1 << 20))
1679 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1680 else
1681 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1682 } else {
1683 if (insn & (1 << 20))
1684 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1685 else
1686 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1688 gen_op_iwmmxt_movq_wRn_M0(wrd);
1689 gen_op_iwmmxt_set_mup();
1690 gen_op_iwmmxt_set_cup();
1691 break;
1692 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1693 wrd = (insn >> 12) & 0xf;
1694 rd0 = (insn >> 16) & 0xf;
1695 rd1 = (insn >> 0) & 0xf;
1696 gen_op_iwmmxt_movq_M0_wRn(rd0);
1697 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1698 tcg_gen_andi_i32(tmp, tmp, 7);
1699 iwmmxt_load_reg(cpu_V1, rd1);
1700 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
1701 tcg_temp_free_i32(tmp);
1702 gen_op_iwmmxt_movq_wRn_M0(wrd);
1703 gen_op_iwmmxt_set_mup();
1704 break;
1705 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1706 if (((insn >> 6) & 3) == 3)
1707 return 1;
1708 rd = (insn >> 12) & 0xf;
1709 wrd = (insn >> 16) & 0xf;
1710 tmp = load_reg(s, rd);
1711 gen_op_iwmmxt_movq_M0_wRn(wrd);
1712 switch ((insn >> 6) & 3) {
1713 case 0:
1714 tmp2 = tcg_const_i32(0xff);
1715 tmp3 = tcg_const_i32((insn & 7) << 3);
1716 break;
1717 case 1:
1718 tmp2 = tcg_const_i32(0xffff);
1719 tmp3 = tcg_const_i32((insn & 3) << 4);
1720 break;
1721 case 2:
1722 tmp2 = tcg_const_i32(0xffffffff);
1723 tmp3 = tcg_const_i32((insn & 1) << 5);
1724 break;
1725 default:
1726 TCGV_UNUSED(tmp2);
1727 TCGV_UNUSED(tmp3);
1729 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
1730 tcg_temp_free(tmp3);
1731 tcg_temp_free(tmp2);
1732 tcg_temp_free_i32(tmp);
1733 gen_op_iwmmxt_movq_wRn_M0(wrd);
1734 gen_op_iwmmxt_set_mup();
1735 break;
1736 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1737 rd = (insn >> 12) & 0xf;
1738 wrd = (insn >> 16) & 0xf;
1739 if (rd == 15 || ((insn >> 22) & 3) == 3)
1740 return 1;
1741 gen_op_iwmmxt_movq_M0_wRn(wrd);
1742 tmp = tcg_temp_new_i32();
1743 switch ((insn >> 22) & 3) {
1744 case 0:
1745 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
1746 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1747 if (insn & 8) {
1748 tcg_gen_ext8s_i32(tmp, tmp);
1749 } else {
1750 tcg_gen_andi_i32(tmp, tmp, 0xff);
1752 break;
1753 case 1:
1754 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
1755 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1756 if (insn & 8) {
1757 tcg_gen_ext16s_i32(tmp, tmp);
1758 } else {
1759 tcg_gen_andi_i32(tmp, tmp, 0xffff);
1761 break;
1762 case 2:
1763 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
1764 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1765 break;
1767 store_reg(s, rd, tmp);
1768 break;
1769 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1770 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1771 return 1;
1772 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1773 switch ((insn >> 22) & 3) {
1774 case 0:
1775 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
1776 break;
1777 case 1:
1778 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
1779 break;
1780 case 2:
1781 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
1782 break;
1784 tcg_gen_shli_i32(tmp, tmp, 28);
1785 gen_set_nzcv(tmp);
1786 tcg_temp_free_i32(tmp);
1787 break;
1788 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1789 if (((insn >> 6) & 3) == 3)
1790 return 1;
1791 rd = (insn >> 12) & 0xf;
1792 wrd = (insn >> 16) & 0xf;
1793 tmp = load_reg(s, rd);
1794 switch ((insn >> 6) & 3) {
1795 case 0:
1796 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
1797 break;
1798 case 1:
1799 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
1800 break;
1801 case 2:
1802 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
1803 break;
1805 tcg_temp_free_i32(tmp);
1806 gen_op_iwmmxt_movq_wRn_M0(wrd);
1807 gen_op_iwmmxt_set_mup();
1808 break;
1809 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1810 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1811 return 1;
1812 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1813 tmp2 = tcg_temp_new_i32();
1814 tcg_gen_mov_i32(tmp2, tmp);
1815 switch ((insn >> 22) & 3) {
1816 case 0:
1817 for (i = 0; i < 7; i ++) {
1818 tcg_gen_shli_i32(tmp2, tmp2, 4);
1819 tcg_gen_and_i32(tmp, tmp, tmp2);
1821 break;
1822 case 1:
1823 for (i = 0; i < 3; i ++) {
1824 tcg_gen_shli_i32(tmp2, tmp2, 8);
1825 tcg_gen_and_i32(tmp, tmp, tmp2);
1827 break;
1828 case 2:
1829 tcg_gen_shli_i32(tmp2, tmp2, 16);
1830 tcg_gen_and_i32(tmp, tmp, tmp2);
1831 break;
1833 gen_set_nzcv(tmp);
1834 tcg_temp_free_i32(tmp2);
1835 tcg_temp_free_i32(tmp);
1836 break;
1837 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1838 wrd = (insn >> 12) & 0xf;
1839 rd0 = (insn >> 16) & 0xf;
1840 gen_op_iwmmxt_movq_M0_wRn(rd0);
1841 switch ((insn >> 22) & 3) {
1842 case 0:
1843 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1844 break;
1845 case 1:
1846 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1847 break;
1848 case 2:
1849 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1850 break;
1851 case 3:
1852 return 1;
1854 gen_op_iwmmxt_movq_wRn_M0(wrd);
1855 gen_op_iwmmxt_set_mup();
1856 break;
1857 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1858 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1859 return 1;
1860 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1861 tmp2 = tcg_temp_new_i32();
1862 tcg_gen_mov_i32(tmp2, tmp);
1863 switch ((insn >> 22) & 3) {
1864 case 0:
1865 for (i = 0; i < 7; i ++) {
1866 tcg_gen_shli_i32(tmp2, tmp2, 4);
1867 tcg_gen_or_i32(tmp, tmp, tmp2);
1869 break;
1870 case 1:
1871 for (i = 0; i < 3; i ++) {
1872 tcg_gen_shli_i32(tmp2, tmp2, 8);
1873 tcg_gen_or_i32(tmp, tmp, tmp2);
1875 break;
1876 case 2:
1877 tcg_gen_shli_i32(tmp2, tmp2, 16);
1878 tcg_gen_or_i32(tmp, tmp, tmp2);
1879 break;
1881 gen_set_nzcv(tmp);
1882 tcg_temp_free_i32(tmp2);
1883 tcg_temp_free_i32(tmp);
1884 break;
1885 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1886 rd = (insn >> 12) & 0xf;
1887 rd0 = (insn >> 16) & 0xf;
1888 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
1889 return 1;
1890 gen_op_iwmmxt_movq_M0_wRn(rd0);
1891 tmp = tcg_temp_new_i32();
1892 switch ((insn >> 22) & 3) {
1893 case 0:
1894 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
1895 break;
1896 case 1:
1897 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
1898 break;
1899 case 2:
1900 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
1901 break;
1903 store_reg(s, rd, tmp);
1904 break;
1905 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1906 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1907 wrd = (insn >> 12) & 0xf;
1908 rd0 = (insn >> 16) & 0xf;
1909 rd1 = (insn >> 0) & 0xf;
1910 gen_op_iwmmxt_movq_M0_wRn(rd0);
1911 switch ((insn >> 22) & 3) {
1912 case 0:
1913 if (insn & (1 << 21))
1914 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1915 else
1916 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1917 break;
1918 case 1:
1919 if (insn & (1 << 21))
1920 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1921 else
1922 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
1923 break;
1924 case 2:
1925 if (insn & (1 << 21))
1926 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
1927 else
1928 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
1929 break;
1930 case 3:
1931 return 1;
1933 gen_op_iwmmxt_movq_wRn_M0(wrd);
1934 gen_op_iwmmxt_set_mup();
1935 gen_op_iwmmxt_set_cup();
1936 break;
1937 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1938 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1939 wrd = (insn >> 12) & 0xf;
1940 rd0 = (insn >> 16) & 0xf;
1941 gen_op_iwmmxt_movq_M0_wRn(rd0);
1942 switch ((insn >> 22) & 3) {
1943 case 0:
1944 if (insn & (1 << 21))
1945 gen_op_iwmmxt_unpacklsb_M0();
1946 else
1947 gen_op_iwmmxt_unpacklub_M0();
1948 break;
1949 case 1:
1950 if (insn & (1 << 21))
1951 gen_op_iwmmxt_unpacklsw_M0();
1952 else
1953 gen_op_iwmmxt_unpackluw_M0();
1954 break;
1955 case 2:
1956 if (insn & (1 << 21))
1957 gen_op_iwmmxt_unpacklsl_M0();
1958 else
1959 gen_op_iwmmxt_unpacklul_M0();
1960 break;
1961 case 3:
1962 return 1;
1964 gen_op_iwmmxt_movq_wRn_M0(wrd);
1965 gen_op_iwmmxt_set_mup();
1966 gen_op_iwmmxt_set_cup();
1967 break;
1968 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
1969 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1970 wrd = (insn >> 12) & 0xf;
1971 rd0 = (insn >> 16) & 0xf;
1972 gen_op_iwmmxt_movq_M0_wRn(rd0);
1973 switch ((insn >> 22) & 3) {
1974 case 0:
1975 if (insn & (1 << 21))
1976 gen_op_iwmmxt_unpackhsb_M0();
1977 else
1978 gen_op_iwmmxt_unpackhub_M0();
1979 break;
1980 case 1:
1981 if (insn & (1 << 21))
1982 gen_op_iwmmxt_unpackhsw_M0();
1983 else
1984 gen_op_iwmmxt_unpackhuw_M0();
1985 break;
1986 case 2:
1987 if (insn & (1 << 21))
1988 gen_op_iwmmxt_unpackhsl_M0();
1989 else
1990 gen_op_iwmmxt_unpackhul_M0();
1991 break;
1992 case 3:
1993 return 1;
1995 gen_op_iwmmxt_movq_wRn_M0(wrd);
1996 gen_op_iwmmxt_set_mup();
1997 gen_op_iwmmxt_set_cup();
1998 break;
1999 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2000 case 0x214: case 0x614: case 0xa14: case 0xe14:
2001 if (((insn >> 22) & 3) == 0)
2002 return 1;
2003 wrd = (insn >> 12) & 0xf;
2004 rd0 = (insn >> 16) & 0xf;
2005 gen_op_iwmmxt_movq_M0_wRn(rd0);
2006 tmp = tcg_temp_new_i32();
2007 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2008 tcg_temp_free_i32(tmp);
2009 return 1;
2011 switch ((insn >> 22) & 3) {
2012 case 1:
2013 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
2014 break;
2015 case 2:
2016 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
2017 break;
2018 case 3:
2019 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
2020 break;
2022 tcg_temp_free_i32(tmp);
2023 gen_op_iwmmxt_movq_wRn_M0(wrd);
2024 gen_op_iwmmxt_set_mup();
2025 gen_op_iwmmxt_set_cup();
2026 break;
2027 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2028 case 0x014: case 0x414: case 0x814: case 0xc14:
2029 if (((insn >> 22) & 3) == 0)
2030 return 1;
2031 wrd = (insn >> 12) & 0xf;
2032 rd0 = (insn >> 16) & 0xf;
2033 gen_op_iwmmxt_movq_M0_wRn(rd0);
2034 tmp = tcg_temp_new_i32();
2035 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2036 tcg_temp_free_i32(tmp);
2037 return 1;
2039 switch ((insn >> 22) & 3) {
2040 case 1:
2041 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2042 break;
2043 case 2:
2044 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2045 break;
2046 case 3:
2047 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2048 break;
2050 tcg_temp_free_i32(tmp);
2051 gen_op_iwmmxt_movq_wRn_M0(wrd);
2052 gen_op_iwmmxt_set_mup();
2053 gen_op_iwmmxt_set_cup();
2054 break;
2055 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2056 case 0x114: case 0x514: case 0x914: case 0xd14:
2057 if (((insn >> 22) & 3) == 0)
2058 return 1;
2059 wrd = (insn >> 12) & 0xf;
2060 rd0 = (insn >> 16) & 0xf;
2061 gen_op_iwmmxt_movq_M0_wRn(rd0);
2062 tmp = tcg_temp_new_i32();
2063 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2064 tcg_temp_free_i32(tmp);
2065 return 1;
2067 switch ((insn >> 22) & 3) {
2068 case 1:
2069 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2070 break;
2071 case 2:
2072 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2073 break;
2074 case 3:
2075 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2076 break;
2078 tcg_temp_free_i32(tmp);
2079 gen_op_iwmmxt_movq_wRn_M0(wrd);
2080 gen_op_iwmmxt_set_mup();
2081 gen_op_iwmmxt_set_cup();
2082 break;
2083 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2084 case 0x314: case 0x714: case 0xb14: case 0xf14:
2085 if (((insn >> 22) & 3) == 0)
2086 return 1;
2087 wrd = (insn >> 12) & 0xf;
2088 rd0 = (insn >> 16) & 0xf;
2089 gen_op_iwmmxt_movq_M0_wRn(rd0);
2090 tmp = tcg_temp_new_i32();
2091 switch ((insn >> 22) & 3) {
2092 case 1:
2093 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2094 tcg_temp_free_i32(tmp);
2095 return 1;
2097 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2098 break;
2099 case 2:
2100 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2101 tcg_temp_free_i32(tmp);
2102 return 1;
2104 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2105 break;
2106 case 3:
2107 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2108 tcg_temp_free_i32(tmp);
2109 return 1;
2111 gen_helper_iwmmxt_rorq(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 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2120 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2121 wrd = (insn >> 12) & 0xf;
2122 rd0 = (insn >> 16) & 0xf;
2123 rd1 = (insn >> 0) & 0xf;
2124 gen_op_iwmmxt_movq_M0_wRn(rd0);
2125 switch ((insn >> 22) & 3) {
2126 case 0:
2127 if (insn & (1 << 21))
2128 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2129 else
2130 gen_op_iwmmxt_minub_M0_wRn(rd1);
2131 break;
2132 case 1:
2133 if (insn & (1 << 21))
2134 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2135 else
2136 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2137 break;
2138 case 2:
2139 if (insn & (1 << 21))
2140 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2141 else
2142 gen_op_iwmmxt_minul_M0_wRn(rd1);
2143 break;
2144 case 3:
2145 return 1;
2147 gen_op_iwmmxt_movq_wRn_M0(wrd);
2148 gen_op_iwmmxt_set_mup();
2149 break;
2150 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2151 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2152 wrd = (insn >> 12) & 0xf;
2153 rd0 = (insn >> 16) & 0xf;
2154 rd1 = (insn >> 0) & 0xf;
2155 gen_op_iwmmxt_movq_M0_wRn(rd0);
2156 switch ((insn >> 22) & 3) {
2157 case 0:
2158 if (insn & (1 << 21))
2159 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2160 else
2161 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2162 break;
2163 case 1:
2164 if (insn & (1 << 21))
2165 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2166 else
2167 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2168 break;
2169 case 2:
2170 if (insn & (1 << 21))
2171 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2172 else
2173 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2174 break;
2175 case 3:
2176 return 1;
2178 gen_op_iwmmxt_movq_wRn_M0(wrd);
2179 gen_op_iwmmxt_set_mup();
2180 break;
2181 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2182 case 0x402: case 0x502: case 0x602: case 0x702:
2183 wrd = (insn >> 12) & 0xf;
2184 rd0 = (insn >> 16) & 0xf;
2185 rd1 = (insn >> 0) & 0xf;
2186 gen_op_iwmmxt_movq_M0_wRn(rd0);
2187 tmp = tcg_const_i32((insn >> 20) & 3);
2188 iwmmxt_load_reg(cpu_V1, rd1);
2189 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2190 tcg_temp_free(tmp);
2191 gen_op_iwmmxt_movq_wRn_M0(wrd);
2192 gen_op_iwmmxt_set_mup();
2193 break;
2194 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2195 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2196 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2197 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2198 wrd = (insn >> 12) & 0xf;
2199 rd0 = (insn >> 16) & 0xf;
2200 rd1 = (insn >> 0) & 0xf;
2201 gen_op_iwmmxt_movq_M0_wRn(rd0);
2202 switch ((insn >> 20) & 0xf) {
2203 case 0x0:
2204 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2205 break;
2206 case 0x1:
2207 gen_op_iwmmxt_subub_M0_wRn(rd1);
2208 break;
2209 case 0x3:
2210 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2211 break;
2212 case 0x4:
2213 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2214 break;
2215 case 0x5:
2216 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2217 break;
2218 case 0x7:
2219 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2220 break;
2221 case 0x8:
2222 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2223 break;
2224 case 0x9:
2225 gen_op_iwmmxt_subul_M0_wRn(rd1);
2226 break;
2227 case 0xb:
2228 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2229 break;
2230 default:
2231 return 1;
2233 gen_op_iwmmxt_movq_wRn_M0(wrd);
2234 gen_op_iwmmxt_set_mup();
2235 gen_op_iwmmxt_set_cup();
2236 break;
2237 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2238 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2239 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2240 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2241 wrd = (insn >> 12) & 0xf;
2242 rd0 = (insn >> 16) & 0xf;
2243 gen_op_iwmmxt_movq_M0_wRn(rd0);
2244 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2245 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2246 tcg_temp_free(tmp);
2247 gen_op_iwmmxt_movq_wRn_M0(wrd);
2248 gen_op_iwmmxt_set_mup();
2249 gen_op_iwmmxt_set_cup();
2250 break;
2251 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2252 case 0x418: case 0x518: case 0x618: case 0x718:
2253 case 0x818: case 0x918: case 0xa18: case 0xb18:
2254 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2255 wrd = (insn >> 12) & 0xf;
2256 rd0 = (insn >> 16) & 0xf;
2257 rd1 = (insn >> 0) & 0xf;
2258 gen_op_iwmmxt_movq_M0_wRn(rd0);
2259 switch ((insn >> 20) & 0xf) {
2260 case 0x0:
2261 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2262 break;
2263 case 0x1:
2264 gen_op_iwmmxt_addub_M0_wRn(rd1);
2265 break;
2266 case 0x3:
2267 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2268 break;
2269 case 0x4:
2270 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2271 break;
2272 case 0x5:
2273 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2274 break;
2275 case 0x7:
2276 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2277 break;
2278 case 0x8:
2279 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2280 break;
2281 case 0x9:
2282 gen_op_iwmmxt_addul_M0_wRn(rd1);
2283 break;
2284 case 0xb:
2285 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2286 break;
2287 default:
2288 return 1;
2290 gen_op_iwmmxt_movq_wRn_M0(wrd);
2291 gen_op_iwmmxt_set_mup();
2292 gen_op_iwmmxt_set_cup();
2293 break;
2294 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2295 case 0x408: case 0x508: case 0x608: case 0x708:
2296 case 0x808: case 0x908: case 0xa08: case 0xb08:
2297 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2298 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2299 return 1;
2300 wrd = (insn >> 12) & 0xf;
2301 rd0 = (insn >> 16) & 0xf;
2302 rd1 = (insn >> 0) & 0xf;
2303 gen_op_iwmmxt_movq_M0_wRn(rd0);
2304 switch ((insn >> 22) & 3) {
2305 case 1:
2306 if (insn & (1 << 21))
2307 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2308 else
2309 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2310 break;
2311 case 2:
2312 if (insn & (1 << 21))
2313 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2314 else
2315 gen_op_iwmmxt_packul_M0_wRn(rd1);
2316 break;
2317 case 3:
2318 if (insn & (1 << 21))
2319 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2320 else
2321 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2322 break;
2324 gen_op_iwmmxt_movq_wRn_M0(wrd);
2325 gen_op_iwmmxt_set_mup();
2326 gen_op_iwmmxt_set_cup();
2327 break;
2328 case 0x201: case 0x203: case 0x205: case 0x207:
2329 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2330 case 0x211: case 0x213: case 0x215: case 0x217:
2331 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2332 wrd = (insn >> 5) & 0xf;
2333 rd0 = (insn >> 12) & 0xf;
2334 rd1 = (insn >> 0) & 0xf;
2335 if (rd0 == 0xf || rd1 == 0xf)
2336 return 1;
2337 gen_op_iwmmxt_movq_M0_wRn(wrd);
2338 tmp = load_reg(s, rd0);
2339 tmp2 = load_reg(s, rd1);
2340 switch ((insn >> 16) & 0xf) {
2341 case 0x0: /* TMIA */
2342 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2343 break;
2344 case 0x8: /* TMIAPH */
2345 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2346 break;
2347 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2348 if (insn & (1 << 16))
2349 tcg_gen_shri_i32(tmp, tmp, 16);
2350 if (insn & (1 << 17))
2351 tcg_gen_shri_i32(tmp2, tmp2, 16);
2352 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2353 break;
2354 default:
2355 tcg_temp_free_i32(tmp2);
2356 tcg_temp_free_i32(tmp);
2357 return 1;
2359 tcg_temp_free_i32(tmp2);
2360 tcg_temp_free_i32(tmp);
2361 gen_op_iwmmxt_movq_wRn_M0(wrd);
2362 gen_op_iwmmxt_set_mup();
2363 break;
2364 default:
2365 return 1;
2368 return 0;
2371 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
2372 (ie. an undefined instruction). */
2373 static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2375 int acc, rd0, rd1, rdhi, rdlo;
2376 TCGv tmp, tmp2;
2378 if ((insn & 0x0ff00f10) == 0x0e200010) {
2379 /* Multiply with Internal Accumulate Format */
2380 rd0 = (insn >> 12) & 0xf;
2381 rd1 = insn & 0xf;
2382 acc = (insn >> 5) & 7;
2384 if (acc != 0)
2385 return 1;
2387 tmp = load_reg(s, rd0);
2388 tmp2 = load_reg(s, rd1);
2389 switch ((insn >> 16) & 0xf) {
2390 case 0x0: /* MIA */
2391 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2392 break;
2393 case 0x8: /* MIAPH */
2394 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2395 break;
2396 case 0xc: /* MIABB */
2397 case 0xd: /* MIABT */
2398 case 0xe: /* MIATB */
2399 case 0xf: /* MIATT */
2400 if (insn & (1 << 16))
2401 tcg_gen_shri_i32(tmp, tmp, 16);
2402 if (insn & (1 << 17))
2403 tcg_gen_shri_i32(tmp2, tmp2, 16);
2404 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2405 break;
2406 default:
2407 return 1;
2409 tcg_temp_free_i32(tmp2);
2410 tcg_temp_free_i32(tmp);
2412 gen_op_iwmmxt_movq_wRn_M0(acc);
2413 return 0;
2416 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2417 /* Internal Accumulator Access Format */
2418 rdhi = (insn >> 16) & 0xf;
2419 rdlo = (insn >> 12) & 0xf;
2420 acc = insn & 7;
2422 if (acc != 0)
2423 return 1;
2425 if (insn & ARM_CP_RW_BIT) { /* MRA */
2426 iwmmxt_load_reg(cpu_V0, acc);
2427 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
2428 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
2429 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
2430 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2431 } else { /* MAR */
2432 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2433 iwmmxt_store_reg(cpu_V0, acc);
2435 return 0;
2438 return 1;
2441 /* Disassemble system coprocessor instruction. Return nonzero if
2442 instruction is not defined. */
2443 static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2445 TCGv tmp, tmp2;
2446 uint32_t rd = (insn >> 12) & 0xf;
2447 uint32_t cp = (insn >> 8) & 0xf;
2448 if (IS_USER(s)) {
2449 return 1;
2452 if (insn & ARM_CP_RW_BIT) {
2453 if (!env->cp[cp].cp_read)
2454 return 1;
2455 gen_set_pc_im(s->pc);
2456 tmp = tcg_temp_new_i32();
2457 tmp2 = tcg_const_i32(insn);
2458 gen_helper_get_cp(tmp, cpu_env, tmp2);
2459 tcg_temp_free(tmp2);
2460 store_reg(s, rd, tmp);
2461 } else {
2462 if (!env->cp[cp].cp_write)
2463 return 1;
2464 gen_set_pc_im(s->pc);
2465 tmp = load_reg(s, rd);
2466 tmp2 = tcg_const_i32(insn);
2467 gen_helper_set_cp(cpu_env, tmp2, tmp);
2468 tcg_temp_free(tmp2);
2469 tcg_temp_free_i32(tmp);
2471 return 0;
2474 static int cp15_user_ok(CPUState *env, uint32_t insn)
2476 int cpn = (insn >> 16) & 0xf;
2477 int cpm = insn & 0xf;
2478 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2480 if (arm_feature(env, ARM_FEATURE_V7) && cpn == 9) {
2481 /* Performance monitor registers fall into three categories:
2482 * (a) always UNDEF in usermode
2483 * (b) UNDEF only if PMUSERENR.EN is 0
2484 * (c) always read OK and UNDEF on write (PMUSERENR only)
2486 if ((cpm == 12 && (op < 6)) ||
2487 (cpm == 13 && (op < 3))) {
2488 return env->cp15.c9_pmuserenr;
2489 } else if (cpm == 14 && op == 0 && (insn & ARM_CP_RW_BIT)) {
2490 /* PMUSERENR, read only */
2491 return 1;
2493 return 0;
2496 if (cpn == 13 && cpm == 0) {
2497 /* TLS register. */
2498 if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2499 return 1;
2501 return 0;
2504 static int cp15_tls_load_store(CPUState *env, DisasContext *s, uint32_t insn, uint32_t rd)
2506 TCGv tmp;
2507 int cpn = (insn >> 16) & 0xf;
2508 int cpm = insn & 0xf;
2509 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2511 if (!arm_feature(env, ARM_FEATURE_V6K))
2512 return 0;
2514 if (!(cpn == 13 && cpm == 0))
2515 return 0;
2517 if (insn & ARM_CP_RW_BIT) {
2518 switch (op) {
2519 case 2:
2520 tmp = load_cpu_field(cp15.c13_tls1);
2521 break;
2522 case 3:
2523 tmp = load_cpu_field(cp15.c13_tls2);
2524 break;
2525 case 4:
2526 tmp = load_cpu_field(cp15.c13_tls3);
2527 break;
2528 default:
2529 return 0;
2531 store_reg(s, rd, tmp);
2533 } else {
2534 tmp = load_reg(s, rd);
2535 switch (op) {
2536 case 2:
2537 store_cpu_field(tmp, cp15.c13_tls1);
2538 break;
2539 case 3:
2540 store_cpu_field(tmp, cp15.c13_tls2);
2541 break;
2542 case 4:
2543 store_cpu_field(tmp, cp15.c13_tls3);
2544 break;
2545 default:
2546 tcg_temp_free_i32(tmp);
2547 return 0;
2550 return 1;
2553 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2554 instruction is not defined. */
2555 static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2557 uint32_t rd;
2558 TCGv tmp, tmp2;
2560 /* M profile cores use memory mapped registers instead of cp15. */
2561 if (arm_feature(env, ARM_FEATURE_M))
2562 return 1;
2564 if ((insn & (1 << 25)) == 0) {
2565 if (insn & (1 << 20)) {
2566 /* mrrc */
2567 return 1;
2569 /* mcrr. Used for block cache operations, so implement as no-op. */
2570 return 0;
2572 if ((insn & (1 << 4)) == 0) {
2573 /* cdp */
2574 return 1;
2576 /* We special case a number of cp15 instructions which were used
2577 * for things which are real instructions in ARMv7. This allows
2578 * them to work in linux-user mode which doesn't provide functional
2579 * get_cp15/set_cp15 helpers, and is more efficient anyway.
2581 switch ((insn & 0x0fff0fff)) {
2582 case 0x0e070f90:
2583 /* 0,c7,c0,4: Standard v6 WFI (also used in some pre-v6 cores).
2584 * In v7, this must NOP.
2586 if (IS_USER(s)) {
2587 return 1;
2589 if (!arm_feature(env, ARM_FEATURE_V7)) {
2590 /* Wait for interrupt. */
2591 gen_set_pc_im(s->pc);
2592 s->is_jmp = DISAS_WFI;
2594 return 0;
2595 case 0x0e070f58:
2596 /* 0,c7,c8,2: Not all pre-v6 cores implemented this WFI,
2597 * so this is slightly over-broad.
2599 if (!IS_USER(s) && !arm_feature(env, ARM_FEATURE_V6)) {
2600 /* Wait for interrupt. */
2601 gen_set_pc_im(s->pc);
2602 s->is_jmp = DISAS_WFI;
2603 return 0;
2605 /* Otherwise continue to handle via helper function.
2606 * In particular, on v7 and some v6 cores this is one of
2607 * the VA-PA registers.
2609 break;
2610 case 0x0e070f3d:
2611 /* 0,c7,c13,1: prefetch-by-MVA in v6, NOP in v7 */
2612 if (arm_feature(env, ARM_FEATURE_V6)) {
2613 return IS_USER(s) ? 1 : 0;
2615 break;
2616 case 0x0e070f95: /* 0,c7,c5,4 : ISB */
2617 case 0x0e070f9a: /* 0,c7,c10,4: DSB */
2618 case 0x0e070fba: /* 0,c7,c10,5: DMB */
2619 /* Barriers in both v6 and v7 */
2620 if (arm_feature(env, ARM_FEATURE_V6)) {
2621 return 0;
2623 break;
2624 default:
2625 break;
2628 if (IS_USER(s) && !cp15_user_ok(env, insn)) {
2629 return 1;
2632 rd = (insn >> 12) & 0xf;
2634 if (cp15_tls_load_store(env, s, insn, rd))
2635 return 0;
2637 tmp2 = tcg_const_i32(insn);
2638 if (insn & ARM_CP_RW_BIT) {
2639 tmp = tcg_temp_new_i32();
2640 gen_helper_get_cp15(tmp, cpu_env, tmp2);
2641 /* If the destination register is r15 then sets condition codes. */
2642 if (rd != 15)
2643 store_reg(s, rd, tmp);
2644 else
2645 tcg_temp_free_i32(tmp);
2646 } else {
2647 tmp = load_reg(s, rd);
2648 gen_helper_set_cp15(cpu_env, tmp2, tmp);
2649 tcg_temp_free_i32(tmp);
2650 /* Normally we would always end the TB here, but Linux
2651 * arch/arm/mach-pxa/sleep.S expects two instructions following
2652 * an MMU enable to execute from cache. Imitate this behaviour. */
2653 if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2654 (insn & 0x0fff0fff) != 0x0e010f10)
2655 gen_lookup_tb(s);
2657 tcg_temp_free_i32(tmp2);
2658 return 0;
2661 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2662 #define VFP_SREG(insn, bigbit, smallbit) \
2663 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2664 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2665 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2666 reg = (((insn) >> (bigbit)) & 0x0f) \
2667 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2668 } else { \
2669 if (insn & (1 << (smallbit))) \
2670 return 1; \
2671 reg = ((insn) >> (bigbit)) & 0x0f; \
2672 }} while (0)
2674 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2675 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2676 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2677 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2678 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2679 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2681 /* Move between integer and VFP cores. */
2682 static TCGv gen_vfp_mrs(void)
2684 TCGv tmp = tcg_temp_new_i32();
2685 tcg_gen_mov_i32(tmp, cpu_F0s);
2686 return tmp;
2689 static void gen_vfp_msr(TCGv tmp)
2691 tcg_gen_mov_i32(cpu_F0s, tmp);
2692 tcg_temp_free_i32(tmp);
2695 static void gen_neon_dup_u8(TCGv var, int shift)
2697 TCGv tmp = tcg_temp_new_i32();
2698 if (shift)
2699 tcg_gen_shri_i32(var, var, shift);
2700 tcg_gen_ext8u_i32(var, var);
2701 tcg_gen_shli_i32(tmp, var, 8);
2702 tcg_gen_or_i32(var, var, tmp);
2703 tcg_gen_shli_i32(tmp, var, 16);
2704 tcg_gen_or_i32(var, var, tmp);
2705 tcg_temp_free_i32(tmp);
2708 static void gen_neon_dup_low16(TCGv var)
2710 TCGv tmp = tcg_temp_new_i32();
2711 tcg_gen_ext16u_i32(var, var);
2712 tcg_gen_shli_i32(tmp, var, 16);
2713 tcg_gen_or_i32(var, var, tmp);
2714 tcg_temp_free_i32(tmp);
2717 static void gen_neon_dup_high16(TCGv var)
2719 TCGv tmp = tcg_temp_new_i32();
2720 tcg_gen_andi_i32(var, var, 0xffff0000);
2721 tcg_gen_shri_i32(tmp, var, 16);
2722 tcg_gen_or_i32(var, var, tmp);
2723 tcg_temp_free_i32(tmp);
2726 static TCGv gen_load_and_replicate(DisasContext *s, TCGv addr, int size)
2728 /* Load a single Neon element and replicate into a 32 bit TCG reg */
2729 TCGv tmp;
2730 switch (size) {
2731 case 0:
2732 tmp = gen_ld8u(addr, IS_USER(s));
2733 gen_neon_dup_u8(tmp, 0);
2734 break;
2735 case 1:
2736 tmp = gen_ld16u(addr, IS_USER(s));
2737 gen_neon_dup_low16(tmp);
2738 break;
2739 case 2:
2740 tmp = gen_ld32(addr, IS_USER(s));
2741 break;
2742 default: /* Avoid compiler warnings. */
2743 abort();
2745 return tmp;
2748 /* Disassemble a VFP instruction. Returns nonzero if an error occurred
2749 (ie. an undefined instruction). */
2750 static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2752 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2753 int dp, veclen;
2754 TCGv addr;
2755 TCGv tmp;
2756 TCGv tmp2;
2758 if (!arm_feature(env, ARM_FEATURE_VFP))
2759 return 1;
2761 if (!s->vfp_enabled) {
2762 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2763 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2764 return 1;
2765 rn = (insn >> 16) & 0xf;
2766 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2767 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2768 return 1;
2770 dp = ((insn & 0xf00) == 0xb00);
2771 switch ((insn >> 24) & 0xf) {
2772 case 0xe:
2773 if (insn & (1 << 4)) {
2774 /* single register transfer */
2775 rd = (insn >> 12) & 0xf;
2776 if (dp) {
2777 int size;
2778 int pass;
2780 VFP_DREG_N(rn, insn);
2781 if (insn & 0xf)
2782 return 1;
2783 if (insn & 0x00c00060
2784 && !arm_feature(env, ARM_FEATURE_NEON))
2785 return 1;
2787 pass = (insn >> 21) & 1;
2788 if (insn & (1 << 22)) {
2789 size = 0;
2790 offset = ((insn >> 5) & 3) * 8;
2791 } else if (insn & (1 << 5)) {
2792 size = 1;
2793 offset = (insn & (1 << 6)) ? 16 : 0;
2794 } else {
2795 size = 2;
2796 offset = 0;
2798 if (insn & ARM_CP_RW_BIT) {
2799 /* vfp->arm */
2800 tmp = neon_load_reg(rn, pass);
2801 switch (size) {
2802 case 0:
2803 if (offset)
2804 tcg_gen_shri_i32(tmp, tmp, offset);
2805 if (insn & (1 << 23))
2806 gen_uxtb(tmp);
2807 else
2808 gen_sxtb(tmp);
2809 break;
2810 case 1:
2811 if (insn & (1 << 23)) {
2812 if (offset) {
2813 tcg_gen_shri_i32(tmp, tmp, 16);
2814 } else {
2815 gen_uxth(tmp);
2817 } else {
2818 if (offset) {
2819 tcg_gen_sari_i32(tmp, tmp, 16);
2820 } else {
2821 gen_sxth(tmp);
2824 break;
2825 case 2:
2826 break;
2828 store_reg(s, rd, tmp);
2829 } else {
2830 /* arm->vfp */
2831 tmp = load_reg(s, rd);
2832 if (insn & (1 << 23)) {
2833 /* VDUP */
2834 if (size == 0) {
2835 gen_neon_dup_u8(tmp, 0);
2836 } else if (size == 1) {
2837 gen_neon_dup_low16(tmp);
2839 for (n = 0; n <= pass * 2; n++) {
2840 tmp2 = tcg_temp_new_i32();
2841 tcg_gen_mov_i32(tmp2, tmp);
2842 neon_store_reg(rn, n, tmp2);
2844 neon_store_reg(rn, n, tmp);
2845 } else {
2846 /* VMOV */
2847 switch (size) {
2848 case 0:
2849 tmp2 = neon_load_reg(rn, pass);
2850 gen_bfi(tmp, tmp2, tmp, offset, 0xff);
2851 tcg_temp_free_i32(tmp2);
2852 break;
2853 case 1:
2854 tmp2 = neon_load_reg(rn, pass);
2855 gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
2856 tcg_temp_free_i32(tmp2);
2857 break;
2858 case 2:
2859 break;
2861 neon_store_reg(rn, pass, tmp);
2864 } else { /* !dp */
2865 if ((insn & 0x6f) != 0x00)
2866 return 1;
2867 rn = VFP_SREG_N(insn);
2868 if (insn & ARM_CP_RW_BIT) {
2869 /* vfp->arm */
2870 if (insn & (1 << 21)) {
2871 /* system register */
2872 rn >>= 1;
2874 switch (rn) {
2875 case ARM_VFP_FPSID:
2876 /* VFP2 allows access to FSID from userspace.
2877 VFP3 restricts all id registers to privileged
2878 accesses. */
2879 if (IS_USER(s)
2880 && arm_feature(env, ARM_FEATURE_VFP3))
2881 return 1;
2882 tmp = load_cpu_field(vfp.xregs[rn]);
2883 break;
2884 case ARM_VFP_FPEXC:
2885 if (IS_USER(s))
2886 return 1;
2887 tmp = load_cpu_field(vfp.xregs[rn]);
2888 break;
2889 case ARM_VFP_FPINST:
2890 case ARM_VFP_FPINST2:
2891 /* Not present in VFP3. */
2892 if (IS_USER(s)
2893 || arm_feature(env, ARM_FEATURE_VFP3))
2894 return 1;
2895 tmp = load_cpu_field(vfp.xregs[rn]);
2896 break;
2897 case ARM_VFP_FPSCR:
2898 if (rd == 15) {
2899 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2900 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2901 } else {
2902 tmp = tcg_temp_new_i32();
2903 gen_helper_vfp_get_fpscr(tmp, cpu_env);
2905 break;
2906 case ARM_VFP_MVFR0:
2907 case ARM_VFP_MVFR1:
2908 if (IS_USER(s)
2909 || !arm_feature(env, ARM_FEATURE_VFP3))
2910 return 1;
2911 tmp = load_cpu_field(vfp.xregs[rn]);
2912 break;
2913 default:
2914 return 1;
2916 } else {
2917 gen_mov_F0_vreg(0, rn);
2918 tmp = gen_vfp_mrs();
2920 if (rd == 15) {
2921 /* Set the 4 flag bits in the CPSR. */
2922 gen_set_nzcv(tmp);
2923 tcg_temp_free_i32(tmp);
2924 } else {
2925 store_reg(s, rd, tmp);
2927 } else {
2928 /* arm->vfp */
2929 tmp = load_reg(s, rd);
2930 if (insn & (1 << 21)) {
2931 rn >>= 1;
2932 /* system register */
2933 switch (rn) {
2934 case ARM_VFP_FPSID:
2935 case ARM_VFP_MVFR0:
2936 case ARM_VFP_MVFR1:
2937 /* Writes are ignored. */
2938 break;
2939 case ARM_VFP_FPSCR:
2940 gen_helper_vfp_set_fpscr(cpu_env, tmp);
2941 tcg_temp_free_i32(tmp);
2942 gen_lookup_tb(s);
2943 break;
2944 case ARM_VFP_FPEXC:
2945 if (IS_USER(s))
2946 return 1;
2947 /* TODO: VFP subarchitecture support.
2948 * For now, keep the EN bit only */
2949 tcg_gen_andi_i32(tmp, tmp, 1 << 30);
2950 store_cpu_field(tmp, vfp.xregs[rn]);
2951 gen_lookup_tb(s);
2952 break;
2953 case ARM_VFP_FPINST:
2954 case ARM_VFP_FPINST2:
2955 store_cpu_field(tmp, vfp.xregs[rn]);
2956 break;
2957 default:
2958 return 1;
2960 } else {
2961 gen_vfp_msr(tmp);
2962 gen_mov_vreg_F0(0, rn);
2966 } else {
2967 /* data processing */
2968 /* The opcode is in bits 23, 21, 20 and 6. */
2969 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2970 if (dp) {
2971 if (op == 15) {
2972 /* rn is opcode */
2973 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2974 } else {
2975 /* rn is register number */
2976 VFP_DREG_N(rn, insn);
2979 if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18))) {
2980 /* Integer or single precision destination. */
2981 rd = VFP_SREG_D(insn);
2982 } else {
2983 VFP_DREG_D(rd, insn);
2985 if (op == 15 &&
2986 (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14))) {
2987 /* VCVT from int is always from S reg regardless of dp bit.
2988 * VCVT with immediate frac_bits has same format as SREG_M
2990 rm = VFP_SREG_M(insn);
2991 } else {
2992 VFP_DREG_M(rm, insn);
2994 } else {
2995 rn = VFP_SREG_N(insn);
2996 if (op == 15 && rn == 15) {
2997 /* Double precision destination. */
2998 VFP_DREG_D(rd, insn);
2999 } else {
3000 rd = VFP_SREG_D(insn);
3002 /* NB that we implicitly rely on the encoding for the frac_bits
3003 * in VCVT of fixed to float being the same as that of an SREG_M
3005 rm = VFP_SREG_M(insn);
3008 veclen = s->vec_len;
3009 if (op == 15 && rn > 3)
3010 veclen = 0;
3012 /* Shut up compiler warnings. */
3013 delta_m = 0;
3014 delta_d = 0;
3015 bank_mask = 0;
3017 if (veclen > 0) {
3018 if (dp)
3019 bank_mask = 0xc;
3020 else
3021 bank_mask = 0x18;
3023 /* Figure out what type of vector operation this is. */
3024 if ((rd & bank_mask) == 0) {
3025 /* scalar */
3026 veclen = 0;
3027 } else {
3028 if (dp)
3029 delta_d = (s->vec_stride >> 1) + 1;
3030 else
3031 delta_d = s->vec_stride + 1;
3033 if ((rm & bank_mask) == 0) {
3034 /* mixed scalar/vector */
3035 delta_m = 0;
3036 } else {
3037 /* vector */
3038 delta_m = delta_d;
3043 /* Load the initial operands. */
3044 if (op == 15) {
3045 switch (rn) {
3046 case 16:
3047 case 17:
3048 /* Integer source */
3049 gen_mov_F0_vreg(0, rm);
3050 break;
3051 case 8:
3052 case 9:
3053 /* Compare */
3054 gen_mov_F0_vreg(dp, rd);
3055 gen_mov_F1_vreg(dp, rm);
3056 break;
3057 case 10:
3058 case 11:
3059 /* Compare with zero */
3060 gen_mov_F0_vreg(dp, rd);
3061 gen_vfp_F1_ld0(dp);
3062 break;
3063 case 20:
3064 case 21:
3065 case 22:
3066 case 23:
3067 case 28:
3068 case 29:
3069 case 30:
3070 case 31:
3071 /* Source and destination the same. */
3072 gen_mov_F0_vreg(dp, rd);
3073 break;
3074 default:
3075 /* One source operand. */
3076 gen_mov_F0_vreg(dp, rm);
3077 break;
3079 } else {
3080 /* Two source operands. */
3081 gen_mov_F0_vreg(dp, rn);
3082 gen_mov_F1_vreg(dp, rm);
3085 for (;;) {
3086 /* Perform the calculation. */
3087 switch (op) {
3088 case 0: /* VMLA: fd + (fn * fm) */
3089 /* Note that order of inputs to the add matters for NaNs */
3090 gen_vfp_F1_mul(dp);
3091 gen_mov_F0_vreg(dp, rd);
3092 gen_vfp_add(dp);
3093 break;
3094 case 1: /* VMLS: fd + -(fn * fm) */
3095 gen_vfp_mul(dp);
3096 gen_vfp_F1_neg(dp);
3097 gen_mov_F0_vreg(dp, rd);
3098 gen_vfp_add(dp);
3099 break;
3100 case 2: /* VNMLS: -fd + (fn * fm) */
3101 /* Note that it isn't valid to replace (-A + B) with (B - A)
3102 * or similar plausible looking simplifications
3103 * because this will give wrong results for NaNs.
3105 gen_vfp_F1_mul(dp);
3106 gen_mov_F0_vreg(dp, rd);
3107 gen_vfp_neg(dp);
3108 gen_vfp_add(dp);
3109 break;
3110 case 3: /* VNMLA: -fd + -(fn * fm) */
3111 gen_vfp_mul(dp);
3112 gen_vfp_F1_neg(dp);
3113 gen_mov_F0_vreg(dp, rd);
3114 gen_vfp_neg(dp);
3115 gen_vfp_add(dp);
3116 break;
3117 case 4: /* mul: fn * fm */
3118 gen_vfp_mul(dp);
3119 break;
3120 case 5: /* nmul: -(fn * fm) */
3121 gen_vfp_mul(dp);
3122 gen_vfp_neg(dp);
3123 break;
3124 case 6: /* add: fn + fm */
3125 gen_vfp_add(dp);
3126 break;
3127 case 7: /* sub: fn - fm */
3128 gen_vfp_sub(dp);
3129 break;
3130 case 8: /* div: fn / fm */
3131 gen_vfp_div(dp);
3132 break;
3133 case 14: /* fconst */
3134 if (!arm_feature(env, ARM_FEATURE_VFP3))
3135 return 1;
3137 n = (insn << 12) & 0x80000000;
3138 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3139 if (dp) {
3140 if (i & 0x40)
3141 i |= 0x3f80;
3142 else
3143 i |= 0x4000;
3144 n |= i << 16;
3145 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3146 } else {
3147 if (i & 0x40)
3148 i |= 0x780;
3149 else
3150 i |= 0x800;
3151 n |= i << 19;
3152 tcg_gen_movi_i32(cpu_F0s, n);
3154 break;
3155 case 15: /* extension space */
3156 switch (rn) {
3157 case 0: /* cpy */
3158 /* no-op */
3159 break;
3160 case 1: /* abs */
3161 gen_vfp_abs(dp);
3162 break;
3163 case 2: /* neg */
3164 gen_vfp_neg(dp);
3165 break;
3166 case 3: /* sqrt */
3167 gen_vfp_sqrt(dp);
3168 break;
3169 case 4: /* vcvtb.f32.f16 */
3170 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3171 return 1;
3172 tmp = gen_vfp_mrs();
3173 tcg_gen_ext16u_i32(tmp, tmp);
3174 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3175 tcg_temp_free_i32(tmp);
3176 break;
3177 case 5: /* vcvtt.f32.f16 */
3178 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3179 return 1;
3180 tmp = gen_vfp_mrs();
3181 tcg_gen_shri_i32(tmp, tmp, 16);
3182 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3183 tcg_temp_free_i32(tmp);
3184 break;
3185 case 6: /* vcvtb.f16.f32 */
3186 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3187 return 1;
3188 tmp = tcg_temp_new_i32();
3189 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3190 gen_mov_F0_vreg(0, rd);
3191 tmp2 = gen_vfp_mrs();
3192 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3193 tcg_gen_or_i32(tmp, tmp, tmp2);
3194 tcg_temp_free_i32(tmp2);
3195 gen_vfp_msr(tmp);
3196 break;
3197 case 7: /* vcvtt.f16.f32 */
3198 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3199 return 1;
3200 tmp = tcg_temp_new_i32();
3201 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3202 tcg_gen_shli_i32(tmp, tmp, 16);
3203 gen_mov_F0_vreg(0, rd);
3204 tmp2 = gen_vfp_mrs();
3205 tcg_gen_ext16u_i32(tmp2, tmp2);
3206 tcg_gen_or_i32(tmp, tmp, tmp2);
3207 tcg_temp_free_i32(tmp2);
3208 gen_vfp_msr(tmp);
3209 break;
3210 case 8: /* cmp */
3211 gen_vfp_cmp(dp);
3212 break;
3213 case 9: /* cmpe */
3214 gen_vfp_cmpe(dp);
3215 break;
3216 case 10: /* cmpz */
3217 gen_vfp_cmp(dp);
3218 break;
3219 case 11: /* cmpez */
3220 gen_vfp_F1_ld0(dp);
3221 gen_vfp_cmpe(dp);
3222 break;
3223 case 15: /* single<->double conversion */
3224 if (dp)
3225 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3226 else
3227 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3228 break;
3229 case 16: /* fuito */
3230 gen_vfp_uito(dp, 0);
3231 break;
3232 case 17: /* fsito */
3233 gen_vfp_sito(dp, 0);
3234 break;
3235 case 20: /* fshto */
3236 if (!arm_feature(env, ARM_FEATURE_VFP3))
3237 return 1;
3238 gen_vfp_shto(dp, 16 - rm, 0);
3239 break;
3240 case 21: /* fslto */
3241 if (!arm_feature(env, ARM_FEATURE_VFP3))
3242 return 1;
3243 gen_vfp_slto(dp, 32 - rm, 0);
3244 break;
3245 case 22: /* fuhto */
3246 if (!arm_feature(env, ARM_FEATURE_VFP3))
3247 return 1;
3248 gen_vfp_uhto(dp, 16 - rm, 0);
3249 break;
3250 case 23: /* fulto */
3251 if (!arm_feature(env, ARM_FEATURE_VFP3))
3252 return 1;
3253 gen_vfp_ulto(dp, 32 - rm, 0);
3254 break;
3255 case 24: /* ftoui */
3256 gen_vfp_toui(dp, 0);
3257 break;
3258 case 25: /* ftouiz */
3259 gen_vfp_touiz(dp, 0);
3260 break;
3261 case 26: /* ftosi */
3262 gen_vfp_tosi(dp, 0);
3263 break;
3264 case 27: /* ftosiz */
3265 gen_vfp_tosiz(dp, 0);
3266 break;
3267 case 28: /* ftosh */
3268 if (!arm_feature(env, ARM_FEATURE_VFP3))
3269 return 1;
3270 gen_vfp_tosh(dp, 16 - rm, 0);
3271 break;
3272 case 29: /* ftosl */
3273 if (!arm_feature(env, ARM_FEATURE_VFP3))
3274 return 1;
3275 gen_vfp_tosl(dp, 32 - rm, 0);
3276 break;
3277 case 30: /* ftouh */
3278 if (!arm_feature(env, ARM_FEATURE_VFP3))
3279 return 1;
3280 gen_vfp_touh(dp, 16 - rm, 0);
3281 break;
3282 case 31: /* ftoul */
3283 if (!arm_feature(env, ARM_FEATURE_VFP3))
3284 return 1;
3285 gen_vfp_toul(dp, 32 - rm, 0);
3286 break;
3287 default: /* undefined */
3288 printf ("rn:%d\n", rn);
3289 return 1;
3291 break;
3292 default: /* undefined */
3293 printf ("op:%d\n", op);
3294 return 1;
3297 /* Write back the result. */
3298 if (op == 15 && (rn >= 8 && rn <= 11))
3299 ; /* Comparison, do nothing. */
3300 else if (op == 15 && dp && ((rn & 0x1c) == 0x18))
3301 /* VCVT double to int: always integer result. */
3302 gen_mov_vreg_F0(0, rd);
3303 else if (op == 15 && rn == 15)
3304 /* conversion */
3305 gen_mov_vreg_F0(!dp, rd);
3306 else
3307 gen_mov_vreg_F0(dp, rd);
3309 /* break out of the loop if we have finished */
3310 if (veclen == 0)
3311 break;
3313 if (op == 15 && delta_m == 0) {
3314 /* single source one-many */
3315 while (veclen--) {
3316 rd = ((rd + delta_d) & (bank_mask - 1))
3317 | (rd & bank_mask);
3318 gen_mov_vreg_F0(dp, rd);
3320 break;
3322 /* Setup the next operands. */
3323 veclen--;
3324 rd = ((rd + delta_d) & (bank_mask - 1))
3325 | (rd & bank_mask);
3327 if (op == 15) {
3328 /* One source operand. */
3329 rm = ((rm + delta_m) & (bank_mask - 1))
3330 | (rm & bank_mask);
3331 gen_mov_F0_vreg(dp, rm);
3332 } else {
3333 /* Two source operands. */
3334 rn = ((rn + delta_d) & (bank_mask - 1))
3335 | (rn & bank_mask);
3336 gen_mov_F0_vreg(dp, rn);
3337 if (delta_m) {
3338 rm = ((rm + delta_m) & (bank_mask - 1))
3339 | (rm & bank_mask);
3340 gen_mov_F1_vreg(dp, rm);
3345 break;
3346 case 0xc:
3347 case 0xd:
3348 if ((insn & 0x03e00000) == 0x00400000) {
3349 /* two-register transfer */
3350 rn = (insn >> 16) & 0xf;
3351 rd = (insn >> 12) & 0xf;
3352 if (dp) {
3353 VFP_DREG_M(rm, insn);
3354 } else {
3355 rm = VFP_SREG_M(insn);
3358 if (insn & ARM_CP_RW_BIT) {
3359 /* vfp->arm */
3360 if (dp) {
3361 gen_mov_F0_vreg(0, rm * 2);
3362 tmp = gen_vfp_mrs();
3363 store_reg(s, rd, tmp);
3364 gen_mov_F0_vreg(0, rm * 2 + 1);
3365 tmp = gen_vfp_mrs();
3366 store_reg(s, rn, tmp);
3367 } else {
3368 gen_mov_F0_vreg(0, rm);
3369 tmp = gen_vfp_mrs();
3370 store_reg(s, rd, tmp);
3371 gen_mov_F0_vreg(0, rm + 1);
3372 tmp = gen_vfp_mrs();
3373 store_reg(s, rn, tmp);
3375 } else {
3376 /* arm->vfp */
3377 if (dp) {
3378 tmp = load_reg(s, rd);
3379 gen_vfp_msr(tmp);
3380 gen_mov_vreg_F0(0, rm * 2);
3381 tmp = load_reg(s, rn);
3382 gen_vfp_msr(tmp);
3383 gen_mov_vreg_F0(0, rm * 2 + 1);
3384 } else {
3385 tmp = load_reg(s, rd);
3386 gen_vfp_msr(tmp);
3387 gen_mov_vreg_F0(0, rm);
3388 tmp = load_reg(s, rn);
3389 gen_vfp_msr(tmp);
3390 gen_mov_vreg_F0(0, rm + 1);
3393 } else {
3394 /* Load/store */
3395 rn = (insn >> 16) & 0xf;
3396 if (dp)
3397 VFP_DREG_D(rd, insn);
3398 else
3399 rd = VFP_SREG_D(insn);
3400 if ((insn & 0x01200000) == 0x01000000) {
3401 /* Single load/store */
3402 offset = (insn & 0xff) << 2;
3403 if ((insn & (1 << 23)) == 0)
3404 offset = -offset;
3405 if (s->thumb && rn == 15) {
3406 /* This is actually UNPREDICTABLE */
3407 addr = tcg_temp_new_i32();
3408 tcg_gen_movi_i32(addr, s->pc & ~2);
3409 } else {
3410 addr = load_reg(s, rn);
3412 tcg_gen_addi_i32(addr, addr, offset);
3413 if (insn & (1 << 20)) {
3414 gen_vfp_ld(s, dp, addr);
3415 gen_mov_vreg_F0(dp, rd);
3416 } else {
3417 gen_mov_F0_vreg(dp, rd);
3418 gen_vfp_st(s, dp, addr);
3420 tcg_temp_free_i32(addr);
3421 } else {
3422 /* load/store multiple */
3423 int w = insn & (1 << 21);
3424 if (dp)
3425 n = (insn >> 1) & 0x7f;
3426 else
3427 n = insn & 0xff;
3429 if (w && !(((insn >> 23) ^ (insn >> 24)) & 1)) {
3430 /* P == U , W == 1 => UNDEF */
3431 return 1;
3433 if (n == 0 || (rd + n) > 32 || (dp && n > 16)) {
3434 /* UNPREDICTABLE cases for bad immediates: we choose to
3435 * UNDEF to avoid generating huge numbers of TCG ops
3437 return 1;
3439 if (rn == 15 && w) {
3440 /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
3441 return 1;
3444 if (s->thumb && rn == 15) {
3445 /* This is actually UNPREDICTABLE */
3446 addr = tcg_temp_new_i32();
3447 tcg_gen_movi_i32(addr, s->pc & ~2);
3448 } else {
3449 addr = load_reg(s, rn);
3451 if (insn & (1 << 24)) /* pre-decrement */
3452 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
3454 if (dp)
3455 offset = 8;
3456 else
3457 offset = 4;
3458 for (i = 0; i < n; i++) {
3459 if (insn & ARM_CP_RW_BIT) {
3460 /* load */
3461 gen_vfp_ld(s, dp, addr);
3462 gen_mov_vreg_F0(dp, rd + i);
3463 } else {
3464 /* store */
3465 gen_mov_F0_vreg(dp, rd + i);
3466 gen_vfp_st(s, dp, addr);
3468 tcg_gen_addi_i32(addr, addr, offset);
3470 if (w) {
3471 /* writeback */
3472 if (insn & (1 << 24))
3473 offset = -offset * n;
3474 else if (dp && (insn & 1))
3475 offset = 4;
3476 else
3477 offset = 0;
3479 if (offset != 0)
3480 tcg_gen_addi_i32(addr, addr, offset);
3481 store_reg(s, rn, addr);
3482 } else {
3483 tcg_temp_free_i32(addr);
3487 break;
3488 default:
3489 /* Should never happen. */
3490 return 1;
3492 return 0;
3495 static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3497 TranslationBlock *tb;
3499 tb = s->tb;
3500 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3501 tcg_gen_goto_tb(n);
3502 gen_set_pc_im(dest);
3503 tcg_gen_exit_tb((tcg_target_long)tb + n);
3504 } else {
3505 gen_set_pc_im(dest);
3506 tcg_gen_exit_tb(0);
3510 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3512 if (unlikely(s->singlestep_enabled)) {
3513 /* An indirect jump so that we still trigger the debug exception. */
3514 if (s->thumb)
3515 dest |= 1;
3516 gen_bx_im(s, dest);
3517 } else {
3518 gen_goto_tb(s, 0, dest);
3519 s->is_jmp = DISAS_TB_JUMP;
3523 static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3525 if (x)
3526 tcg_gen_sari_i32(t0, t0, 16);
3527 else
3528 gen_sxth(t0);
3529 if (y)
3530 tcg_gen_sari_i32(t1, t1, 16);
3531 else
3532 gen_sxth(t1);
3533 tcg_gen_mul_i32(t0, t0, t1);
3536 /* Return the mask of PSR bits set by a MSR instruction. */
3537 static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3538 uint32_t mask;
3540 mask = 0;
3541 if (flags & (1 << 0))
3542 mask |= 0xff;
3543 if (flags & (1 << 1))
3544 mask |= 0xff00;
3545 if (flags & (1 << 2))
3546 mask |= 0xff0000;
3547 if (flags & (1 << 3))
3548 mask |= 0xff000000;
3550 /* Mask out undefined bits. */
3551 mask &= ~CPSR_RESERVED;
3552 if (!arm_feature(env, ARM_FEATURE_V4T))
3553 mask &= ~CPSR_T;
3554 if (!arm_feature(env, ARM_FEATURE_V5))
3555 mask &= ~CPSR_Q; /* V5TE in reality*/
3556 if (!arm_feature(env, ARM_FEATURE_V6))
3557 mask &= ~(CPSR_E | CPSR_GE);
3558 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3559 mask &= ~CPSR_IT;
3560 /* Mask out execution state bits. */
3561 if (!spsr)
3562 mask &= ~CPSR_EXEC;
3563 /* Mask out privileged bits. */
3564 if (IS_USER(s))
3565 mask &= CPSR_USER;
3566 return mask;
3569 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3570 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0)
3572 TCGv tmp;
3573 if (spsr) {
3574 /* ??? This is also undefined in system mode. */
3575 if (IS_USER(s))
3576 return 1;
3578 tmp = load_cpu_field(spsr);
3579 tcg_gen_andi_i32(tmp, tmp, ~mask);
3580 tcg_gen_andi_i32(t0, t0, mask);
3581 tcg_gen_or_i32(tmp, tmp, t0);
3582 store_cpu_field(tmp, spsr);
3583 } else {
3584 gen_set_cpsr(t0, mask);
3586 tcg_temp_free_i32(t0);
3587 gen_lookup_tb(s);
3588 return 0;
3591 /* Returns nonzero if access to the PSR is not permitted. */
3592 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3594 TCGv tmp;
3595 tmp = tcg_temp_new_i32();
3596 tcg_gen_movi_i32(tmp, val);
3597 return gen_set_psr(s, mask, spsr, tmp);
3600 /* Generate an old-style exception return. Marks pc as dead. */
3601 static void gen_exception_return(DisasContext *s, TCGv pc)
3603 TCGv tmp;
3604 store_reg(s, 15, pc);
3605 tmp = load_cpu_field(spsr);
3606 gen_set_cpsr(tmp, 0xffffffff);
3607 tcg_temp_free_i32(tmp);
3608 s->is_jmp = DISAS_UPDATE;
3611 /* Generate a v6 exception return. Marks both values as dead. */
3612 static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3614 gen_set_cpsr(cpsr, 0xffffffff);
3615 tcg_temp_free_i32(cpsr);
3616 store_reg(s, 15, pc);
3617 s->is_jmp = DISAS_UPDATE;
3620 static inline void
3621 gen_set_condexec (DisasContext *s)
3623 if (s->condexec_mask) {
3624 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3625 TCGv tmp = tcg_temp_new_i32();
3626 tcg_gen_movi_i32(tmp, val);
3627 store_cpu_field(tmp, condexec_bits);
3631 static void gen_exception_insn(DisasContext *s, int offset, int excp)
3633 gen_set_condexec(s);
3634 gen_set_pc_im(s->pc - offset);
3635 gen_exception(excp);
3636 s->is_jmp = DISAS_JUMP;
3639 static void gen_nop_hint(DisasContext *s, int val)
3641 switch (val) {
3642 case 3: /* wfi */
3643 gen_set_pc_im(s->pc);
3644 s->is_jmp = DISAS_WFI;
3645 break;
3646 case 2: /* wfe */
3647 case 4: /* sev */
3648 /* TODO: Implement SEV and WFE. May help SMP performance. */
3649 default: /* nop */
3650 break;
3654 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3656 static inline void gen_neon_add(int size, TCGv t0, TCGv t1)
3658 switch (size) {
3659 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
3660 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
3661 case 2: tcg_gen_add_i32(t0, t0, t1); break;
3662 default: abort();
3666 static inline void gen_neon_rsb(int size, TCGv t0, TCGv t1)
3668 switch (size) {
3669 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
3670 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
3671 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
3672 default: return;
3676 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3677 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3678 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3679 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3680 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3682 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3683 switch ((size << 1) | u) { \
3684 case 0: \
3685 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3686 break; \
3687 case 1: \
3688 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3689 break; \
3690 case 2: \
3691 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3692 break; \
3693 case 3: \
3694 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3695 break; \
3696 case 4: \
3697 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3698 break; \
3699 case 5: \
3700 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3701 break; \
3702 default: return 1; \
3703 }} while (0)
3705 #define GEN_NEON_INTEGER_OP(name) do { \
3706 switch ((size << 1) | u) { \
3707 case 0: \
3708 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3709 break; \
3710 case 1: \
3711 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3712 break; \
3713 case 2: \
3714 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3715 break; \
3716 case 3: \
3717 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3718 break; \
3719 case 4: \
3720 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3721 break; \
3722 case 5: \
3723 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3724 break; \
3725 default: return 1; \
3726 }} while (0)
3728 static TCGv neon_load_scratch(int scratch)
3730 TCGv tmp = tcg_temp_new_i32();
3731 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3732 return tmp;
3735 static void neon_store_scratch(int scratch, TCGv var)
3737 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3738 tcg_temp_free_i32(var);
3741 static inline TCGv neon_get_scalar(int size, int reg)
3743 TCGv tmp;
3744 if (size == 1) {
3745 tmp = neon_load_reg(reg & 7, reg >> 4);
3746 if (reg & 8) {
3747 gen_neon_dup_high16(tmp);
3748 } else {
3749 gen_neon_dup_low16(tmp);
3751 } else {
3752 tmp = neon_load_reg(reg & 15, reg >> 4);
3754 return tmp;
3757 static int gen_neon_unzip(int rd, int rm, int size, int q)
3759 TCGv tmp, tmp2;
3760 if (!q && size == 2) {
3761 return 1;
3763 tmp = tcg_const_i32(rd);
3764 tmp2 = tcg_const_i32(rm);
3765 if (q) {
3766 switch (size) {
3767 case 0:
3768 gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
3769 break;
3770 case 1:
3771 gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
3772 break;
3773 case 2:
3774 gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
3775 break;
3776 default:
3777 abort();
3779 } else {
3780 switch (size) {
3781 case 0:
3782 gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
3783 break;
3784 case 1:
3785 gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
3786 break;
3787 default:
3788 abort();
3791 tcg_temp_free_i32(tmp);
3792 tcg_temp_free_i32(tmp2);
3793 return 0;
3796 static int gen_neon_zip(int rd, int rm, int size, int q)
3798 TCGv tmp, tmp2;
3799 if (!q && size == 2) {
3800 return 1;
3802 tmp = tcg_const_i32(rd);
3803 tmp2 = tcg_const_i32(rm);
3804 if (q) {
3805 switch (size) {
3806 case 0:
3807 gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
3808 break;
3809 case 1:
3810 gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
3811 break;
3812 case 2:
3813 gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
3814 break;
3815 default:
3816 abort();
3818 } else {
3819 switch (size) {
3820 case 0:
3821 gen_helper_neon_zip8(cpu_env, tmp, tmp2);
3822 break;
3823 case 1:
3824 gen_helper_neon_zip16(cpu_env, tmp, tmp2);
3825 break;
3826 default:
3827 abort();
3830 tcg_temp_free_i32(tmp);
3831 tcg_temp_free_i32(tmp2);
3832 return 0;
3835 static void gen_neon_trn_u8(TCGv t0, TCGv t1)
3837 TCGv rd, tmp;
3839 rd = tcg_temp_new_i32();
3840 tmp = tcg_temp_new_i32();
3842 tcg_gen_shli_i32(rd, t0, 8);
3843 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3844 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3845 tcg_gen_or_i32(rd, rd, tmp);
3847 tcg_gen_shri_i32(t1, t1, 8);
3848 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3849 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3850 tcg_gen_or_i32(t1, t1, tmp);
3851 tcg_gen_mov_i32(t0, rd);
3853 tcg_temp_free_i32(tmp);
3854 tcg_temp_free_i32(rd);
3857 static void gen_neon_trn_u16(TCGv t0, TCGv t1)
3859 TCGv rd, tmp;
3861 rd = tcg_temp_new_i32();
3862 tmp = tcg_temp_new_i32();
3864 tcg_gen_shli_i32(rd, t0, 16);
3865 tcg_gen_andi_i32(tmp, t1, 0xffff);
3866 tcg_gen_or_i32(rd, rd, tmp);
3867 tcg_gen_shri_i32(t1, t1, 16);
3868 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3869 tcg_gen_or_i32(t1, t1, tmp);
3870 tcg_gen_mov_i32(t0, rd);
3872 tcg_temp_free_i32(tmp);
3873 tcg_temp_free_i32(rd);
3877 static struct {
3878 int nregs;
3879 int interleave;
3880 int spacing;
3881 } neon_ls_element_type[11] = {
3882 {4, 4, 1},
3883 {4, 4, 2},
3884 {4, 1, 1},
3885 {4, 2, 1},
3886 {3, 3, 1},
3887 {3, 3, 2},
3888 {3, 1, 1},
3889 {1, 1, 1},
3890 {2, 2, 1},
3891 {2, 2, 2},
3892 {2, 1, 1}
3895 /* Translate a NEON load/store element instruction. Return nonzero if the
3896 instruction is invalid. */
3897 static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3899 int rd, rn, rm;
3900 int op;
3901 int nregs;
3902 int interleave;
3903 int spacing;
3904 int stride;
3905 int size;
3906 int reg;
3907 int pass;
3908 int load;
3909 int shift;
3910 int n;
3911 TCGv addr;
3912 TCGv tmp;
3913 TCGv tmp2;
3914 TCGv_i64 tmp64;
3916 if (!s->vfp_enabled)
3917 return 1;
3918 VFP_DREG_D(rd, insn);
3919 rn = (insn >> 16) & 0xf;
3920 rm = insn & 0xf;
3921 load = (insn & (1 << 21)) != 0;
3922 if ((insn & (1 << 23)) == 0) {
3923 /* Load store all elements. */
3924 op = (insn >> 8) & 0xf;
3925 size = (insn >> 6) & 3;
3926 if (op > 10)
3927 return 1;
3928 /* Catch UNDEF cases for bad values of align field */
3929 switch (op & 0xc) {
3930 case 4:
3931 if (((insn >> 5) & 1) == 1) {
3932 return 1;
3934 break;
3935 case 8:
3936 if (((insn >> 4) & 3) == 3) {
3937 return 1;
3939 break;
3940 default:
3941 break;
3943 nregs = neon_ls_element_type[op].nregs;
3944 interleave = neon_ls_element_type[op].interleave;
3945 spacing = neon_ls_element_type[op].spacing;
3946 if (size == 3 && (interleave | spacing) != 1)
3947 return 1;
3948 addr = tcg_temp_new_i32();
3949 load_reg_var(s, addr, rn);
3950 stride = (1 << size) * interleave;
3951 for (reg = 0; reg < nregs; reg++) {
3952 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3953 load_reg_var(s, addr, rn);
3954 tcg_gen_addi_i32(addr, addr, (1 << size) * reg);
3955 } else if (interleave == 2 && nregs == 4 && reg == 2) {
3956 load_reg_var(s, addr, rn);
3957 tcg_gen_addi_i32(addr, addr, 1 << size);
3959 if (size == 3) {
3960 if (load) {
3961 tmp64 = gen_ld64(addr, IS_USER(s));
3962 neon_store_reg64(tmp64, rd);
3963 tcg_temp_free_i64(tmp64);
3964 } else {
3965 tmp64 = tcg_temp_new_i64();
3966 neon_load_reg64(tmp64, rd);
3967 gen_st64(tmp64, addr, IS_USER(s));
3969 tcg_gen_addi_i32(addr, addr, stride);
3970 } else {
3971 for (pass = 0; pass < 2; pass++) {
3972 if (size == 2) {
3973 if (load) {
3974 tmp = gen_ld32(addr, IS_USER(s));
3975 neon_store_reg(rd, pass, tmp);
3976 } else {
3977 tmp = neon_load_reg(rd, pass);
3978 gen_st32(tmp, addr, IS_USER(s));
3980 tcg_gen_addi_i32(addr, addr, stride);
3981 } else if (size == 1) {
3982 if (load) {
3983 tmp = gen_ld16u(addr, IS_USER(s));
3984 tcg_gen_addi_i32(addr, addr, stride);
3985 tmp2 = gen_ld16u(addr, IS_USER(s));
3986 tcg_gen_addi_i32(addr, addr, stride);
3987 tcg_gen_shli_i32(tmp2, tmp2, 16);
3988 tcg_gen_or_i32(tmp, tmp, tmp2);
3989 tcg_temp_free_i32(tmp2);
3990 neon_store_reg(rd, pass, tmp);
3991 } else {
3992 tmp = neon_load_reg(rd, pass);
3993 tmp2 = tcg_temp_new_i32();
3994 tcg_gen_shri_i32(tmp2, tmp, 16);
3995 gen_st16(tmp, addr, IS_USER(s));
3996 tcg_gen_addi_i32(addr, addr, stride);
3997 gen_st16(tmp2, addr, IS_USER(s));
3998 tcg_gen_addi_i32(addr, addr, stride);
4000 } else /* size == 0 */ {
4001 if (load) {
4002 TCGV_UNUSED(tmp2);
4003 for (n = 0; n < 4; n++) {
4004 tmp = gen_ld8u(addr, IS_USER(s));
4005 tcg_gen_addi_i32(addr, addr, stride);
4006 if (n == 0) {
4007 tmp2 = tmp;
4008 } else {
4009 tcg_gen_shli_i32(tmp, tmp, n * 8);
4010 tcg_gen_or_i32(tmp2, tmp2, tmp);
4011 tcg_temp_free_i32(tmp);
4014 neon_store_reg(rd, pass, tmp2);
4015 } else {
4016 tmp2 = neon_load_reg(rd, pass);
4017 for (n = 0; n < 4; n++) {
4018 tmp = tcg_temp_new_i32();
4019 if (n == 0) {
4020 tcg_gen_mov_i32(tmp, tmp2);
4021 } else {
4022 tcg_gen_shri_i32(tmp, tmp2, n * 8);
4024 gen_st8(tmp, addr, IS_USER(s));
4025 tcg_gen_addi_i32(addr, addr, stride);
4027 tcg_temp_free_i32(tmp2);
4032 rd += spacing;
4034 tcg_temp_free_i32(addr);
4035 stride = nregs * 8;
4036 } else {
4037 size = (insn >> 10) & 3;
4038 if (size == 3) {
4039 /* Load single element to all lanes. */
4040 int a = (insn >> 4) & 1;
4041 if (!load) {
4042 return 1;
4044 size = (insn >> 6) & 3;
4045 nregs = ((insn >> 8) & 3) + 1;
4047 if (size == 3) {
4048 if (nregs != 4 || a == 0) {
4049 return 1;
4051 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
4052 size = 2;
4054 if (nregs == 1 && a == 1 && size == 0) {
4055 return 1;
4057 if (nregs == 3 && a == 1) {
4058 return 1;
4060 addr = tcg_temp_new_i32();
4061 load_reg_var(s, addr, rn);
4062 if (nregs == 1) {
4063 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */
4064 tmp = gen_load_and_replicate(s, addr, size);
4065 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4066 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4067 if (insn & (1 << 5)) {
4068 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 0));
4069 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 1));
4071 tcg_temp_free_i32(tmp);
4072 } else {
4073 /* VLD2/3/4 to all lanes: bit 5 indicates register stride */
4074 stride = (insn & (1 << 5)) ? 2 : 1;
4075 for (reg = 0; reg < nregs; reg++) {
4076 tmp = gen_load_and_replicate(s, addr, size);
4077 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4078 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4079 tcg_temp_free_i32(tmp);
4080 tcg_gen_addi_i32(addr, addr, 1 << size);
4081 rd += stride;
4084 tcg_temp_free_i32(addr);
4085 stride = (1 << size) * nregs;
4086 } else {
4087 /* Single element. */
4088 int idx = (insn >> 4) & 0xf;
4089 pass = (insn >> 7) & 1;
4090 switch (size) {
4091 case 0:
4092 shift = ((insn >> 5) & 3) * 8;
4093 stride = 1;
4094 break;
4095 case 1:
4096 shift = ((insn >> 6) & 1) * 16;
4097 stride = (insn & (1 << 5)) ? 2 : 1;
4098 break;
4099 case 2:
4100 shift = 0;
4101 stride = (insn & (1 << 6)) ? 2 : 1;
4102 break;
4103 default:
4104 abort();
4106 nregs = ((insn >> 8) & 3) + 1;
4107 /* Catch the UNDEF cases. This is unavoidably a bit messy. */
4108 switch (nregs) {
4109 case 1:
4110 if (((idx & (1 << size)) != 0) ||
4111 (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
4112 return 1;
4114 break;
4115 case 3:
4116 if ((idx & 1) != 0) {
4117 return 1;
4119 /* fall through */
4120 case 2:
4121 if (size == 2 && (idx & 2) != 0) {
4122 return 1;
4124 break;
4125 case 4:
4126 if ((size == 2) && ((idx & 3) == 3)) {
4127 return 1;
4129 break;
4130 default:
4131 abort();
4133 if ((rd + stride * (nregs - 1)) > 31) {
4134 /* Attempts to write off the end of the register file
4135 * are UNPREDICTABLE; we choose to UNDEF because otherwise
4136 * the neon_load_reg() would write off the end of the array.
4138 return 1;
4140 addr = tcg_temp_new_i32();
4141 load_reg_var(s, addr, rn);
4142 for (reg = 0; reg < nregs; reg++) {
4143 if (load) {
4144 switch (size) {
4145 case 0:
4146 tmp = gen_ld8u(addr, IS_USER(s));
4147 break;
4148 case 1:
4149 tmp = gen_ld16u(addr, IS_USER(s));
4150 break;
4151 case 2:
4152 tmp = gen_ld32(addr, IS_USER(s));
4153 break;
4154 default: /* Avoid compiler warnings. */
4155 abort();
4157 if (size != 2) {
4158 tmp2 = neon_load_reg(rd, pass);
4159 gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
4160 tcg_temp_free_i32(tmp2);
4162 neon_store_reg(rd, pass, tmp);
4163 } else { /* Store */
4164 tmp = neon_load_reg(rd, pass);
4165 if (shift)
4166 tcg_gen_shri_i32(tmp, tmp, shift);
4167 switch (size) {
4168 case 0:
4169 gen_st8(tmp, addr, IS_USER(s));
4170 break;
4171 case 1:
4172 gen_st16(tmp, addr, IS_USER(s));
4173 break;
4174 case 2:
4175 gen_st32(tmp, addr, IS_USER(s));
4176 break;
4179 rd += stride;
4180 tcg_gen_addi_i32(addr, addr, 1 << size);
4182 tcg_temp_free_i32(addr);
4183 stride = nregs * (1 << size);
4186 if (rm != 15) {
4187 TCGv base;
4189 base = load_reg(s, rn);
4190 if (rm == 13) {
4191 tcg_gen_addi_i32(base, base, stride);
4192 } else {
4193 TCGv index;
4194 index = load_reg(s, rm);
4195 tcg_gen_add_i32(base, base, index);
4196 tcg_temp_free_i32(index);
4198 store_reg(s, rn, base);
4200 return 0;
4203 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4204 static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
4206 tcg_gen_and_i32(t, t, c);
4207 tcg_gen_andc_i32(f, f, c);
4208 tcg_gen_or_i32(dest, t, f);
4211 static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
4213 switch (size) {
4214 case 0: gen_helper_neon_narrow_u8(dest, src); break;
4215 case 1: gen_helper_neon_narrow_u16(dest, src); break;
4216 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
4217 default: abort();
4221 static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
4223 switch (size) {
4224 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
4225 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
4226 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
4227 default: abort();
4231 static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
4233 switch (size) {
4234 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
4235 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
4236 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
4237 default: abort();
4241 static inline void gen_neon_unarrow_sats(int size, TCGv dest, TCGv_i64 src)
4243 switch (size) {
4244 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
4245 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
4246 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
4247 default: abort();
4251 static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
4252 int q, int u)
4254 if (q) {
4255 if (u) {
4256 switch (size) {
4257 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4258 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4259 default: abort();
4261 } else {
4262 switch (size) {
4263 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
4264 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
4265 default: abort();
4268 } else {
4269 if (u) {
4270 switch (size) {
4271 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
4272 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
4273 default: abort();
4275 } else {
4276 switch (size) {
4277 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
4278 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
4279 default: abort();
4285 static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
4287 if (u) {
4288 switch (size) {
4289 case 0: gen_helper_neon_widen_u8(dest, src); break;
4290 case 1: gen_helper_neon_widen_u16(dest, src); break;
4291 case 2: tcg_gen_extu_i32_i64(dest, src); break;
4292 default: abort();
4294 } else {
4295 switch (size) {
4296 case 0: gen_helper_neon_widen_s8(dest, src); break;
4297 case 1: gen_helper_neon_widen_s16(dest, src); break;
4298 case 2: tcg_gen_ext_i32_i64(dest, src); break;
4299 default: abort();
4302 tcg_temp_free_i32(src);
4305 static inline void gen_neon_addl(int size)
4307 switch (size) {
4308 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4309 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4310 case 2: tcg_gen_add_i64(CPU_V001); break;
4311 default: abort();
4315 static inline void gen_neon_subl(int size)
4317 switch (size) {
4318 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4319 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4320 case 2: tcg_gen_sub_i64(CPU_V001); break;
4321 default: abort();
4325 static inline void gen_neon_negl(TCGv_i64 var, int size)
4327 switch (size) {
4328 case 0: gen_helper_neon_negl_u16(var, var); break;
4329 case 1: gen_helper_neon_negl_u32(var, var); break;
4330 case 2: gen_helper_neon_negl_u64(var, var); break;
4331 default: abort();
4335 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4337 switch (size) {
4338 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4339 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4340 default: abort();
4344 static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
4346 TCGv_i64 tmp;
4348 switch ((size << 1) | u) {
4349 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4350 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4351 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4352 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4353 case 4:
4354 tmp = gen_muls_i64_i32(a, b);
4355 tcg_gen_mov_i64(dest, tmp);
4356 tcg_temp_free_i64(tmp);
4357 break;
4358 case 5:
4359 tmp = gen_mulu_i64_i32(a, b);
4360 tcg_gen_mov_i64(dest, tmp);
4361 tcg_temp_free_i64(tmp);
4362 break;
4363 default: abort();
4366 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
4367 Don't forget to clean them now. */
4368 if (size < 2) {
4369 tcg_temp_free_i32(a);
4370 tcg_temp_free_i32(b);
4374 static void gen_neon_narrow_op(int op, int u, int size, TCGv dest, TCGv_i64 src)
4376 if (op) {
4377 if (u) {
4378 gen_neon_unarrow_sats(size, dest, src);
4379 } else {
4380 gen_neon_narrow(size, dest, src);
4382 } else {
4383 if (u) {
4384 gen_neon_narrow_satu(size, dest, src);
4385 } else {
4386 gen_neon_narrow_sats(size, dest, src);
4391 /* Symbolic constants for op fields for Neon 3-register same-length.
4392 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
4393 * table A7-9.
4395 #define NEON_3R_VHADD 0
4396 #define NEON_3R_VQADD 1
4397 #define NEON_3R_VRHADD 2
4398 #define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
4399 #define NEON_3R_VHSUB 4
4400 #define NEON_3R_VQSUB 5
4401 #define NEON_3R_VCGT 6
4402 #define NEON_3R_VCGE 7
4403 #define NEON_3R_VSHL 8
4404 #define NEON_3R_VQSHL 9
4405 #define NEON_3R_VRSHL 10
4406 #define NEON_3R_VQRSHL 11
4407 #define NEON_3R_VMAX 12
4408 #define NEON_3R_VMIN 13
4409 #define NEON_3R_VABD 14
4410 #define NEON_3R_VABA 15
4411 #define NEON_3R_VADD_VSUB 16
4412 #define NEON_3R_VTST_VCEQ 17
4413 #define NEON_3R_VML 18 /* VMLA, VMLAL, VMLS, VMLSL */
4414 #define NEON_3R_VMUL 19
4415 #define NEON_3R_VPMAX 20
4416 #define NEON_3R_VPMIN 21
4417 #define NEON_3R_VQDMULH_VQRDMULH 22
4418 #define NEON_3R_VPADD 23
4419 #define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
4420 #define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
4421 #define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
4422 #define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
4423 #define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
4424 #define NEON_3R_VRECPS_VRSQRTS 31 /* float VRECPS, VRSQRTS */
4426 static const uint8_t neon_3r_sizes[] = {
4427 [NEON_3R_VHADD] = 0x7,
4428 [NEON_3R_VQADD] = 0xf,
4429 [NEON_3R_VRHADD] = 0x7,
4430 [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
4431 [NEON_3R_VHSUB] = 0x7,
4432 [NEON_3R_VQSUB] = 0xf,
4433 [NEON_3R_VCGT] = 0x7,
4434 [NEON_3R_VCGE] = 0x7,
4435 [NEON_3R_VSHL] = 0xf,
4436 [NEON_3R_VQSHL] = 0xf,
4437 [NEON_3R_VRSHL] = 0xf,
4438 [NEON_3R_VQRSHL] = 0xf,
4439 [NEON_3R_VMAX] = 0x7,
4440 [NEON_3R_VMIN] = 0x7,
4441 [NEON_3R_VABD] = 0x7,
4442 [NEON_3R_VABA] = 0x7,
4443 [NEON_3R_VADD_VSUB] = 0xf,
4444 [NEON_3R_VTST_VCEQ] = 0x7,
4445 [NEON_3R_VML] = 0x7,
4446 [NEON_3R_VMUL] = 0x7,
4447 [NEON_3R_VPMAX] = 0x7,
4448 [NEON_3R_VPMIN] = 0x7,
4449 [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
4450 [NEON_3R_VPADD] = 0x7,
4451 [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
4452 [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
4453 [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
4454 [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
4455 [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
4456 [NEON_3R_VRECPS_VRSQRTS] = 0x5, /* size bit 1 encodes op */
4459 /* Symbolic constants for op fields for Neon 2-register miscellaneous.
4460 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
4461 * table A7-13.
4463 #define NEON_2RM_VREV64 0
4464 #define NEON_2RM_VREV32 1
4465 #define NEON_2RM_VREV16 2
4466 #define NEON_2RM_VPADDL 4
4467 #define NEON_2RM_VPADDL_U 5
4468 #define NEON_2RM_VCLS 8
4469 #define NEON_2RM_VCLZ 9
4470 #define NEON_2RM_VCNT 10
4471 #define NEON_2RM_VMVN 11
4472 #define NEON_2RM_VPADAL 12
4473 #define NEON_2RM_VPADAL_U 13
4474 #define NEON_2RM_VQABS 14
4475 #define NEON_2RM_VQNEG 15
4476 #define NEON_2RM_VCGT0 16
4477 #define NEON_2RM_VCGE0 17
4478 #define NEON_2RM_VCEQ0 18
4479 #define NEON_2RM_VCLE0 19
4480 #define NEON_2RM_VCLT0 20
4481 #define NEON_2RM_VABS 22
4482 #define NEON_2RM_VNEG 23
4483 #define NEON_2RM_VCGT0_F 24
4484 #define NEON_2RM_VCGE0_F 25
4485 #define NEON_2RM_VCEQ0_F 26
4486 #define NEON_2RM_VCLE0_F 27
4487 #define NEON_2RM_VCLT0_F 28
4488 #define NEON_2RM_VABS_F 30
4489 #define NEON_2RM_VNEG_F 31
4490 #define NEON_2RM_VSWP 32
4491 #define NEON_2RM_VTRN 33
4492 #define NEON_2RM_VUZP 34
4493 #define NEON_2RM_VZIP 35
4494 #define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
4495 #define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
4496 #define NEON_2RM_VSHLL 38
4497 #define NEON_2RM_VCVT_F16_F32 44
4498 #define NEON_2RM_VCVT_F32_F16 46
4499 #define NEON_2RM_VRECPE 56
4500 #define NEON_2RM_VRSQRTE 57
4501 #define NEON_2RM_VRECPE_F 58
4502 #define NEON_2RM_VRSQRTE_F 59
4503 #define NEON_2RM_VCVT_FS 60
4504 #define NEON_2RM_VCVT_FU 61
4505 #define NEON_2RM_VCVT_SF 62
4506 #define NEON_2RM_VCVT_UF 63
4508 static int neon_2rm_is_float_op(int op)
4510 /* Return true if this neon 2reg-misc op is float-to-float */
4511 return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
4512 op >= NEON_2RM_VRECPE_F);
4515 /* Each entry in this array has bit n set if the insn allows
4516 * size value n (otherwise it will UNDEF). Since unallocated
4517 * op values will have no bits set they always UNDEF.
4519 static const uint8_t neon_2rm_sizes[] = {
4520 [NEON_2RM_VREV64] = 0x7,
4521 [NEON_2RM_VREV32] = 0x3,
4522 [NEON_2RM_VREV16] = 0x1,
4523 [NEON_2RM_VPADDL] = 0x7,
4524 [NEON_2RM_VPADDL_U] = 0x7,
4525 [NEON_2RM_VCLS] = 0x7,
4526 [NEON_2RM_VCLZ] = 0x7,
4527 [NEON_2RM_VCNT] = 0x1,
4528 [NEON_2RM_VMVN] = 0x1,
4529 [NEON_2RM_VPADAL] = 0x7,
4530 [NEON_2RM_VPADAL_U] = 0x7,
4531 [NEON_2RM_VQABS] = 0x7,
4532 [NEON_2RM_VQNEG] = 0x7,
4533 [NEON_2RM_VCGT0] = 0x7,
4534 [NEON_2RM_VCGE0] = 0x7,
4535 [NEON_2RM_VCEQ0] = 0x7,
4536 [NEON_2RM_VCLE0] = 0x7,
4537 [NEON_2RM_VCLT0] = 0x7,
4538 [NEON_2RM_VABS] = 0x7,
4539 [NEON_2RM_VNEG] = 0x7,
4540 [NEON_2RM_VCGT0_F] = 0x4,
4541 [NEON_2RM_VCGE0_F] = 0x4,
4542 [NEON_2RM_VCEQ0_F] = 0x4,
4543 [NEON_2RM_VCLE0_F] = 0x4,
4544 [NEON_2RM_VCLT0_F] = 0x4,
4545 [NEON_2RM_VABS_F] = 0x4,
4546 [NEON_2RM_VNEG_F] = 0x4,
4547 [NEON_2RM_VSWP] = 0x1,
4548 [NEON_2RM_VTRN] = 0x7,
4549 [NEON_2RM_VUZP] = 0x7,
4550 [NEON_2RM_VZIP] = 0x7,
4551 [NEON_2RM_VMOVN] = 0x7,
4552 [NEON_2RM_VQMOVN] = 0x7,
4553 [NEON_2RM_VSHLL] = 0x7,
4554 [NEON_2RM_VCVT_F16_F32] = 0x2,
4555 [NEON_2RM_VCVT_F32_F16] = 0x2,
4556 [NEON_2RM_VRECPE] = 0x4,
4557 [NEON_2RM_VRSQRTE] = 0x4,
4558 [NEON_2RM_VRECPE_F] = 0x4,
4559 [NEON_2RM_VRSQRTE_F] = 0x4,
4560 [NEON_2RM_VCVT_FS] = 0x4,
4561 [NEON_2RM_VCVT_FU] = 0x4,
4562 [NEON_2RM_VCVT_SF] = 0x4,
4563 [NEON_2RM_VCVT_UF] = 0x4,
4566 /* Translate a NEON data processing instruction. Return nonzero if the
4567 instruction is invalid.
4568 We process data in a mixture of 32-bit and 64-bit chunks.
4569 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4571 static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4573 int op;
4574 int q;
4575 int rd, rn, rm;
4576 int size;
4577 int shift;
4578 int pass;
4579 int count;
4580 int pairwise;
4581 int u;
4582 uint32_t imm, mask;
4583 TCGv tmp, tmp2, tmp3, tmp4, tmp5;
4584 TCGv_i64 tmp64;
4586 if (!s->vfp_enabled)
4587 return 1;
4588 q = (insn & (1 << 6)) != 0;
4589 u = (insn >> 24) & 1;
4590 VFP_DREG_D(rd, insn);
4591 VFP_DREG_N(rn, insn);
4592 VFP_DREG_M(rm, insn);
4593 size = (insn >> 20) & 3;
4594 if ((insn & (1 << 23)) == 0) {
4595 /* Three register same length. */
4596 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4597 /* Catch invalid op and bad size combinations: UNDEF */
4598 if ((neon_3r_sizes[op] & (1 << size)) == 0) {
4599 return 1;
4601 /* All insns of this form UNDEF for either this condition or the
4602 * superset of cases "Q==1"; we catch the latter later.
4604 if (q && ((rd | rn | rm) & 1)) {
4605 return 1;
4607 if (size == 3 && op != NEON_3R_LOGIC) {
4608 /* 64-bit element instructions. */
4609 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4610 neon_load_reg64(cpu_V0, rn + pass);
4611 neon_load_reg64(cpu_V1, rm + pass);
4612 switch (op) {
4613 case NEON_3R_VQADD:
4614 if (u) {
4615 gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
4616 cpu_V0, cpu_V1);
4617 } else {
4618 gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
4619 cpu_V0, cpu_V1);
4621 break;
4622 case NEON_3R_VQSUB:
4623 if (u) {
4624 gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
4625 cpu_V0, cpu_V1);
4626 } else {
4627 gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
4628 cpu_V0, cpu_V1);
4630 break;
4631 case NEON_3R_VSHL:
4632 if (u) {
4633 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4634 } else {
4635 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4637 break;
4638 case NEON_3R_VQSHL:
4639 if (u) {
4640 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4641 cpu_V1, cpu_V0);
4642 } else {
4643 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
4644 cpu_V1, cpu_V0);
4646 break;
4647 case NEON_3R_VRSHL:
4648 if (u) {
4649 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4650 } else {
4651 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4653 break;
4654 case NEON_3R_VQRSHL:
4655 if (u) {
4656 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4657 cpu_V1, cpu_V0);
4658 } else {
4659 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4660 cpu_V1, cpu_V0);
4662 break;
4663 case NEON_3R_VADD_VSUB:
4664 if (u) {
4665 tcg_gen_sub_i64(CPU_V001);
4666 } else {
4667 tcg_gen_add_i64(CPU_V001);
4669 break;
4670 default:
4671 abort();
4673 neon_store_reg64(cpu_V0, rd + pass);
4675 return 0;
4677 pairwise = 0;
4678 switch (op) {
4679 case NEON_3R_VSHL:
4680 case NEON_3R_VQSHL:
4681 case NEON_3R_VRSHL:
4682 case NEON_3R_VQRSHL:
4684 int rtmp;
4685 /* Shift instruction operands are reversed. */
4686 rtmp = rn;
4687 rn = rm;
4688 rm = rtmp;
4690 break;
4691 case NEON_3R_VPADD:
4692 if (u) {
4693 return 1;
4695 /* Fall through */
4696 case NEON_3R_VPMAX:
4697 case NEON_3R_VPMIN:
4698 pairwise = 1;
4699 break;
4700 case NEON_3R_FLOAT_ARITH:
4701 pairwise = (u && size < 2); /* if VPADD (float) */
4702 break;
4703 case NEON_3R_FLOAT_MINMAX:
4704 pairwise = u; /* if VPMIN/VPMAX (float) */
4705 break;
4706 case NEON_3R_FLOAT_CMP:
4707 if (!u && size) {
4708 /* no encoding for U=0 C=1x */
4709 return 1;
4711 break;
4712 case NEON_3R_FLOAT_ACMP:
4713 if (!u) {
4714 return 1;
4716 break;
4717 case NEON_3R_VRECPS_VRSQRTS:
4718 if (u) {
4719 return 1;
4721 break;
4722 case NEON_3R_VMUL:
4723 if (u && (size != 0)) {
4724 /* UNDEF on invalid size for polynomial subcase */
4725 return 1;
4727 break;
4728 default:
4729 break;
4732 if (pairwise && q) {
4733 /* All the pairwise insns UNDEF if Q is set */
4734 return 1;
4737 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4739 if (pairwise) {
4740 /* Pairwise. */
4741 if (pass < 1) {
4742 tmp = neon_load_reg(rn, 0);
4743 tmp2 = neon_load_reg(rn, 1);
4744 } else {
4745 tmp = neon_load_reg(rm, 0);
4746 tmp2 = neon_load_reg(rm, 1);
4748 } else {
4749 /* Elementwise. */
4750 tmp = neon_load_reg(rn, pass);
4751 tmp2 = neon_load_reg(rm, pass);
4753 switch (op) {
4754 case NEON_3R_VHADD:
4755 GEN_NEON_INTEGER_OP(hadd);
4756 break;
4757 case NEON_3R_VQADD:
4758 GEN_NEON_INTEGER_OP_ENV(qadd);
4759 break;
4760 case NEON_3R_VRHADD:
4761 GEN_NEON_INTEGER_OP(rhadd);
4762 break;
4763 case NEON_3R_LOGIC: /* Logic ops. */
4764 switch ((u << 2) | size) {
4765 case 0: /* VAND */
4766 tcg_gen_and_i32(tmp, tmp, tmp2);
4767 break;
4768 case 1: /* BIC */
4769 tcg_gen_andc_i32(tmp, tmp, tmp2);
4770 break;
4771 case 2: /* VORR */
4772 tcg_gen_or_i32(tmp, tmp, tmp2);
4773 break;
4774 case 3: /* VORN */
4775 tcg_gen_orc_i32(tmp, tmp, tmp2);
4776 break;
4777 case 4: /* VEOR */
4778 tcg_gen_xor_i32(tmp, tmp, tmp2);
4779 break;
4780 case 5: /* VBSL */
4781 tmp3 = neon_load_reg(rd, pass);
4782 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
4783 tcg_temp_free_i32(tmp3);
4784 break;
4785 case 6: /* VBIT */
4786 tmp3 = neon_load_reg(rd, pass);
4787 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
4788 tcg_temp_free_i32(tmp3);
4789 break;
4790 case 7: /* VBIF */
4791 tmp3 = neon_load_reg(rd, pass);
4792 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
4793 tcg_temp_free_i32(tmp3);
4794 break;
4796 break;
4797 case NEON_3R_VHSUB:
4798 GEN_NEON_INTEGER_OP(hsub);
4799 break;
4800 case NEON_3R_VQSUB:
4801 GEN_NEON_INTEGER_OP_ENV(qsub);
4802 break;
4803 case NEON_3R_VCGT:
4804 GEN_NEON_INTEGER_OP(cgt);
4805 break;
4806 case NEON_3R_VCGE:
4807 GEN_NEON_INTEGER_OP(cge);
4808 break;
4809 case NEON_3R_VSHL:
4810 GEN_NEON_INTEGER_OP(shl);
4811 break;
4812 case NEON_3R_VQSHL:
4813 GEN_NEON_INTEGER_OP_ENV(qshl);
4814 break;
4815 case NEON_3R_VRSHL:
4816 GEN_NEON_INTEGER_OP(rshl);
4817 break;
4818 case NEON_3R_VQRSHL:
4819 GEN_NEON_INTEGER_OP_ENV(qrshl);
4820 break;
4821 case NEON_3R_VMAX:
4822 GEN_NEON_INTEGER_OP(max);
4823 break;
4824 case NEON_3R_VMIN:
4825 GEN_NEON_INTEGER_OP(min);
4826 break;
4827 case NEON_3R_VABD:
4828 GEN_NEON_INTEGER_OP(abd);
4829 break;
4830 case NEON_3R_VABA:
4831 GEN_NEON_INTEGER_OP(abd);
4832 tcg_temp_free_i32(tmp2);
4833 tmp2 = neon_load_reg(rd, pass);
4834 gen_neon_add(size, tmp, tmp2);
4835 break;
4836 case NEON_3R_VADD_VSUB:
4837 if (!u) { /* VADD */
4838 gen_neon_add(size, tmp, tmp2);
4839 } else { /* VSUB */
4840 switch (size) {
4841 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
4842 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
4843 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
4844 default: abort();
4847 break;
4848 case NEON_3R_VTST_VCEQ:
4849 if (!u) { /* VTST */
4850 switch (size) {
4851 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
4852 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
4853 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
4854 default: abort();
4856 } else { /* VCEQ */
4857 switch (size) {
4858 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
4859 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
4860 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
4861 default: abort();
4864 break;
4865 case NEON_3R_VML: /* VMLA, VMLAL, VMLS,VMLSL */
4866 switch (size) {
4867 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4868 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4869 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4870 default: abort();
4872 tcg_temp_free_i32(tmp2);
4873 tmp2 = neon_load_reg(rd, pass);
4874 if (u) { /* VMLS */
4875 gen_neon_rsb(size, tmp, tmp2);
4876 } else { /* VMLA */
4877 gen_neon_add(size, tmp, tmp2);
4879 break;
4880 case NEON_3R_VMUL:
4881 if (u) { /* polynomial */
4882 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
4883 } else { /* Integer */
4884 switch (size) {
4885 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4886 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4887 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4888 default: abort();
4891 break;
4892 case NEON_3R_VPMAX:
4893 GEN_NEON_INTEGER_OP(pmax);
4894 break;
4895 case NEON_3R_VPMIN:
4896 GEN_NEON_INTEGER_OP(pmin);
4897 break;
4898 case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
4899 if (!u) { /* VQDMULH */
4900 switch (size) {
4901 case 1:
4902 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
4903 break;
4904 case 2:
4905 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
4906 break;
4907 default: abort();
4909 } else { /* VQRDMULH */
4910 switch (size) {
4911 case 1:
4912 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
4913 break;
4914 case 2:
4915 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
4916 break;
4917 default: abort();
4920 break;
4921 case NEON_3R_VPADD:
4922 switch (size) {
4923 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
4924 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
4925 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
4926 default: abort();
4928 break;
4929 case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
4931 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
4932 switch ((u << 2) | size) {
4933 case 0: /* VADD */
4934 case 4: /* VPADD */
4935 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
4936 break;
4937 case 2: /* VSUB */
4938 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
4939 break;
4940 case 6: /* VABD */
4941 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
4942 break;
4943 default:
4944 abort();
4946 tcg_temp_free_ptr(fpstatus);
4947 break;
4949 case NEON_3R_FLOAT_MULTIPLY:
4951 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
4952 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
4953 if (!u) {
4954 tcg_temp_free_i32(tmp2);
4955 tmp2 = neon_load_reg(rd, pass);
4956 if (size == 0) {
4957 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
4958 } else {
4959 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
4962 tcg_temp_free_ptr(fpstatus);
4963 break;
4965 case NEON_3R_FLOAT_CMP:
4967 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
4968 if (!u) {
4969 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
4970 } else {
4971 if (size == 0) {
4972 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
4973 } else {
4974 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
4977 tcg_temp_free_ptr(fpstatus);
4978 break;
4980 case NEON_3R_FLOAT_ACMP:
4982 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
4983 if (size == 0) {
4984 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
4985 } else {
4986 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
4988 tcg_temp_free_ptr(fpstatus);
4989 break;
4991 case NEON_3R_FLOAT_MINMAX:
4993 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
4994 if (size == 0) {
4995 gen_helper_neon_max_f32(tmp, tmp, tmp2, fpstatus);
4996 } else {
4997 gen_helper_neon_min_f32(tmp, tmp, tmp2, fpstatus);
4999 tcg_temp_free_ptr(fpstatus);
5000 break;
5002 case NEON_3R_VRECPS_VRSQRTS:
5003 if (size == 0)
5004 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
5005 else
5006 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
5007 break;
5008 default:
5009 abort();
5011 tcg_temp_free_i32(tmp2);
5013 /* Save the result. For elementwise operations we can put it
5014 straight into the destination register. For pairwise operations
5015 we have to be careful to avoid clobbering the source operands. */
5016 if (pairwise && rd == rm) {
5017 neon_store_scratch(pass, tmp);
5018 } else {
5019 neon_store_reg(rd, pass, tmp);
5022 } /* for pass */
5023 if (pairwise && rd == rm) {
5024 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5025 tmp = neon_load_scratch(pass);
5026 neon_store_reg(rd, pass, tmp);
5029 /* End of 3 register same size operations. */
5030 } else if (insn & (1 << 4)) {
5031 if ((insn & 0x00380080) != 0) {
5032 /* Two registers and shift. */
5033 op = (insn >> 8) & 0xf;
5034 if (insn & (1 << 7)) {
5035 /* 64-bit shift. */
5036 if (op > 7) {
5037 return 1;
5039 size = 3;
5040 } else {
5041 size = 2;
5042 while ((insn & (1 << (size + 19))) == 0)
5043 size--;
5045 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
5046 /* To avoid excessive dumplication of ops we implement shift
5047 by immediate using the variable shift operations. */
5048 if (op < 8) {
5049 /* Shift by immediate:
5050 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
5051 if (q && ((rd | rm) & 1)) {
5052 return 1;
5054 if (!u && (op == 4 || op == 6)) {
5055 return 1;
5057 /* Right shifts are encoded as N - shift, where N is the
5058 element size in bits. */
5059 if (op <= 4)
5060 shift = shift - (1 << (size + 3));
5061 if (size == 3) {
5062 count = q + 1;
5063 } else {
5064 count = q ? 4: 2;
5066 switch (size) {
5067 case 0:
5068 imm = (uint8_t) shift;
5069 imm |= imm << 8;
5070 imm |= imm << 16;
5071 break;
5072 case 1:
5073 imm = (uint16_t) shift;
5074 imm |= imm << 16;
5075 break;
5076 case 2:
5077 case 3:
5078 imm = shift;
5079 break;
5080 default:
5081 abort();
5084 for (pass = 0; pass < count; pass++) {
5085 if (size == 3) {
5086 neon_load_reg64(cpu_V0, rm + pass);
5087 tcg_gen_movi_i64(cpu_V1, imm);
5088 switch (op) {
5089 case 0: /* VSHR */
5090 case 1: /* VSRA */
5091 if (u)
5092 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
5093 else
5094 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
5095 break;
5096 case 2: /* VRSHR */
5097 case 3: /* VRSRA */
5098 if (u)
5099 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
5100 else
5101 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
5102 break;
5103 case 4: /* VSRI */
5104 case 5: /* VSHL, VSLI */
5105 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
5106 break;
5107 case 6: /* VQSHLU */
5108 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
5109 cpu_V0, cpu_V1);
5110 break;
5111 case 7: /* VQSHL */
5112 if (u) {
5113 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
5114 cpu_V0, cpu_V1);
5115 } else {
5116 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
5117 cpu_V0, cpu_V1);
5119 break;
5121 if (op == 1 || op == 3) {
5122 /* Accumulate. */
5123 neon_load_reg64(cpu_V1, rd + pass);
5124 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
5125 } else if (op == 4 || (op == 5 && u)) {
5126 /* Insert */
5127 neon_load_reg64(cpu_V1, rd + pass);
5128 uint64_t mask;
5129 if (shift < -63 || shift > 63) {
5130 mask = 0;
5131 } else {
5132 if (op == 4) {
5133 mask = 0xffffffffffffffffull >> -shift;
5134 } else {
5135 mask = 0xffffffffffffffffull << shift;
5138 tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask);
5139 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5141 neon_store_reg64(cpu_V0, rd + pass);
5142 } else { /* size < 3 */
5143 /* Operands in T0 and T1. */
5144 tmp = neon_load_reg(rm, pass);
5145 tmp2 = tcg_temp_new_i32();
5146 tcg_gen_movi_i32(tmp2, imm);
5147 switch (op) {
5148 case 0: /* VSHR */
5149 case 1: /* VSRA */
5150 GEN_NEON_INTEGER_OP(shl);
5151 break;
5152 case 2: /* VRSHR */
5153 case 3: /* VRSRA */
5154 GEN_NEON_INTEGER_OP(rshl);
5155 break;
5156 case 4: /* VSRI */
5157 case 5: /* VSHL, VSLI */
5158 switch (size) {
5159 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
5160 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
5161 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
5162 default: abort();
5164 break;
5165 case 6: /* VQSHLU */
5166 switch (size) {
5167 case 0:
5168 gen_helper_neon_qshlu_s8(tmp, cpu_env,
5169 tmp, tmp2);
5170 break;
5171 case 1:
5172 gen_helper_neon_qshlu_s16(tmp, cpu_env,
5173 tmp, tmp2);
5174 break;
5175 case 2:
5176 gen_helper_neon_qshlu_s32(tmp, cpu_env,
5177 tmp, tmp2);
5178 break;
5179 default:
5180 abort();
5182 break;
5183 case 7: /* VQSHL */
5184 GEN_NEON_INTEGER_OP_ENV(qshl);
5185 break;
5187 tcg_temp_free_i32(tmp2);
5189 if (op == 1 || op == 3) {
5190 /* Accumulate. */
5191 tmp2 = neon_load_reg(rd, pass);
5192 gen_neon_add(size, tmp, tmp2);
5193 tcg_temp_free_i32(tmp2);
5194 } else if (op == 4 || (op == 5 && u)) {
5195 /* Insert */
5196 switch (size) {
5197 case 0:
5198 if (op == 4)
5199 mask = 0xff >> -shift;
5200 else
5201 mask = (uint8_t)(0xff << shift);
5202 mask |= mask << 8;
5203 mask |= mask << 16;
5204 break;
5205 case 1:
5206 if (op == 4)
5207 mask = 0xffff >> -shift;
5208 else
5209 mask = (uint16_t)(0xffff << shift);
5210 mask |= mask << 16;
5211 break;
5212 case 2:
5213 if (shift < -31 || shift > 31) {
5214 mask = 0;
5215 } else {
5216 if (op == 4)
5217 mask = 0xffffffffu >> -shift;
5218 else
5219 mask = 0xffffffffu << shift;
5221 break;
5222 default:
5223 abort();
5225 tmp2 = neon_load_reg(rd, pass);
5226 tcg_gen_andi_i32(tmp, tmp, mask);
5227 tcg_gen_andi_i32(tmp2, tmp2, ~mask);
5228 tcg_gen_or_i32(tmp, tmp, tmp2);
5229 tcg_temp_free_i32(tmp2);
5231 neon_store_reg(rd, pass, tmp);
5233 } /* for pass */
5234 } else if (op < 10) {
5235 /* Shift by immediate and narrow:
5236 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
5237 int input_unsigned = (op == 8) ? !u : u;
5238 if (rm & 1) {
5239 return 1;
5241 shift = shift - (1 << (size + 3));
5242 size++;
5243 if (size == 3) {
5244 tmp64 = tcg_const_i64(shift);
5245 neon_load_reg64(cpu_V0, rm);
5246 neon_load_reg64(cpu_V1, rm + 1);
5247 for (pass = 0; pass < 2; pass++) {
5248 TCGv_i64 in;
5249 if (pass == 0) {
5250 in = cpu_V0;
5251 } else {
5252 in = cpu_V1;
5254 if (q) {
5255 if (input_unsigned) {
5256 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
5257 } else {
5258 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
5260 } else {
5261 if (input_unsigned) {
5262 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
5263 } else {
5264 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
5267 tmp = tcg_temp_new_i32();
5268 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5269 neon_store_reg(rd, pass, tmp);
5270 } /* for pass */
5271 tcg_temp_free_i64(tmp64);
5272 } else {
5273 if (size == 1) {
5274 imm = (uint16_t)shift;
5275 imm |= imm << 16;
5276 } else {
5277 /* size == 2 */
5278 imm = (uint32_t)shift;
5280 tmp2 = tcg_const_i32(imm);
5281 tmp4 = neon_load_reg(rm + 1, 0);
5282 tmp5 = neon_load_reg(rm + 1, 1);
5283 for (pass = 0; pass < 2; pass++) {
5284 if (pass == 0) {
5285 tmp = neon_load_reg(rm, 0);
5286 } else {
5287 tmp = tmp4;
5289 gen_neon_shift_narrow(size, tmp, tmp2, q,
5290 input_unsigned);
5291 if (pass == 0) {
5292 tmp3 = neon_load_reg(rm, 1);
5293 } else {
5294 tmp3 = tmp5;
5296 gen_neon_shift_narrow(size, tmp3, tmp2, q,
5297 input_unsigned);
5298 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
5299 tcg_temp_free_i32(tmp);
5300 tcg_temp_free_i32(tmp3);
5301 tmp = tcg_temp_new_i32();
5302 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5303 neon_store_reg(rd, pass, tmp);
5304 } /* for pass */
5305 tcg_temp_free_i32(tmp2);
5307 } else if (op == 10) {
5308 /* VSHLL, VMOVL */
5309 if (q || (rd & 1)) {
5310 return 1;
5312 tmp = neon_load_reg(rm, 0);
5313 tmp2 = neon_load_reg(rm, 1);
5314 for (pass = 0; pass < 2; pass++) {
5315 if (pass == 1)
5316 tmp = tmp2;
5318 gen_neon_widen(cpu_V0, tmp, size, u);
5320 if (shift != 0) {
5321 /* The shift is less than the width of the source
5322 type, so we can just shift the whole register. */
5323 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
5324 /* Widen the result of shift: we need to clear
5325 * the potential overflow bits resulting from
5326 * left bits of the narrow input appearing as
5327 * right bits of left the neighbour narrow
5328 * input. */
5329 if (size < 2 || !u) {
5330 uint64_t imm64;
5331 if (size == 0) {
5332 imm = (0xffu >> (8 - shift));
5333 imm |= imm << 16;
5334 } else if (size == 1) {
5335 imm = 0xffff >> (16 - shift);
5336 } else {
5337 /* size == 2 */
5338 imm = 0xffffffff >> (32 - shift);
5340 if (size < 2) {
5341 imm64 = imm | (((uint64_t)imm) << 32);
5342 } else {
5343 imm64 = imm;
5345 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
5348 neon_store_reg64(cpu_V0, rd + pass);
5350 } else if (op >= 14) {
5351 /* VCVT fixed-point. */
5352 if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
5353 return 1;
5355 /* We have already masked out the must-be-1 top bit of imm6,
5356 * hence this 32-shift where the ARM ARM has 64-imm6.
5358 shift = 32 - shift;
5359 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5360 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
5361 if (!(op & 1)) {
5362 if (u)
5363 gen_vfp_ulto(0, shift, 1);
5364 else
5365 gen_vfp_slto(0, shift, 1);
5366 } else {
5367 if (u)
5368 gen_vfp_toul(0, shift, 1);
5369 else
5370 gen_vfp_tosl(0, shift, 1);
5372 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
5374 } else {
5375 return 1;
5377 } else { /* (insn & 0x00380080) == 0 */
5378 int invert;
5379 if (q && (rd & 1)) {
5380 return 1;
5383 op = (insn >> 8) & 0xf;
5384 /* One register and immediate. */
5385 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
5386 invert = (insn & (1 << 5)) != 0;
5387 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
5388 * We choose to not special-case this and will behave as if a
5389 * valid constant encoding of 0 had been given.
5391 switch (op) {
5392 case 0: case 1:
5393 /* no-op */
5394 break;
5395 case 2: case 3:
5396 imm <<= 8;
5397 break;
5398 case 4: case 5:
5399 imm <<= 16;
5400 break;
5401 case 6: case 7:
5402 imm <<= 24;
5403 break;
5404 case 8: case 9:
5405 imm |= imm << 16;
5406 break;
5407 case 10: case 11:
5408 imm = (imm << 8) | (imm << 24);
5409 break;
5410 case 12:
5411 imm = (imm << 8) | 0xff;
5412 break;
5413 case 13:
5414 imm = (imm << 16) | 0xffff;
5415 break;
5416 case 14:
5417 imm |= (imm << 8) | (imm << 16) | (imm << 24);
5418 if (invert)
5419 imm = ~imm;
5420 break;
5421 case 15:
5422 if (invert) {
5423 return 1;
5425 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
5426 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
5427 break;
5429 if (invert)
5430 imm = ~imm;
5432 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5433 if (op & 1 && op < 12) {
5434 tmp = neon_load_reg(rd, pass);
5435 if (invert) {
5436 /* The immediate value has already been inverted, so
5437 BIC becomes AND. */
5438 tcg_gen_andi_i32(tmp, tmp, imm);
5439 } else {
5440 tcg_gen_ori_i32(tmp, tmp, imm);
5442 } else {
5443 /* VMOV, VMVN. */
5444 tmp = tcg_temp_new_i32();
5445 if (op == 14 && invert) {
5446 int n;
5447 uint32_t val;
5448 val = 0;
5449 for (n = 0; n < 4; n++) {
5450 if (imm & (1 << (n + (pass & 1) * 4)))
5451 val |= 0xff << (n * 8);
5453 tcg_gen_movi_i32(tmp, val);
5454 } else {
5455 tcg_gen_movi_i32(tmp, imm);
5458 neon_store_reg(rd, pass, tmp);
5461 } else { /* (insn & 0x00800010 == 0x00800000) */
5462 if (size != 3) {
5463 op = (insn >> 8) & 0xf;
5464 if ((insn & (1 << 6)) == 0) {
5465 /* Three registers of different lengths. */
5466 int src1_wide;
5467 int src2_wide;
5468 int prewiden;
5469 /* undefreq: bit 0 : UNDEF if size != 0
5470 * bit 1 : UNDEF if size == 0
5471 * bit 2 : UNDEF if U == 1
5472 * Note that [1:0] set implies 'always UNDEF'
5474 int undefreq;
5475 /* prewiden, src1_wide, src2_wide, undefreq */
5476 static const int neon_3reg_wide[16][4] = {
5477 {1, 0, 0, 0}, /* VADDL */
5478 {1, 1, 0, 0}, /* VADDW */
5479 {1, 0, 0, 0}, /* VSUBL */
5480 {1, 1, 0, 0}, /* VSUBW */
5481 {0, 1, 1, 0}, /* VADDHN */
5482 {0, 0, 0, 0}, /* VABAL */
5483 {0, 1, 1, 0}, /* VSUBHN */
5484 {0, 0, 0, 0}, /* VABDL */
5485 {0, 0, 0, 0}, /* VMLAL */
5486 {0, 0, 0, 6}, /* VQDMLAL */
5487 {0, 0, 0, 0}, /* VMLSL */
5488 {0, 0, 0, 6}, /* VQDMLSL */
5489 {0, 0, 0, 0}, /* Integer VMULL */
5490 {0, 0, 0, 2}, /* VQDMULL */
5491 {0, 0, 0, 5}, /* Polynomial VMULL */
5492 {0, 0, 0, 3}, /* Reserved: always UNDEF */
5495 prewiden = neon_3reg_wide[op][0];
5496 src1_wide = neon_3reg_wide[op][1];
5497 src2_wide = neon_3reg_wide[op][2];
5498 undefreq = neon_3reg_wide[op][3];
5500 if (((undefreq & 1) && (size != 0)) ||
5501 ((undefreq & 2) && (size == 0)) ||
5502 ((undefreq & 4) && u)) {
5503 return 1;
5505 if ((src1_wide && (rn & 1)) ||
5506 (src2_wide && (rm & 1)) ||
5507 (!src2_wide && (rd & 1))) {
5508 return 1;
5511 /* Avoid overlapping operands. Wide source operands are
5512 always aligned so will never overlap with wide
5513 destinations in problematic ways. */
5514 if (rd == rm && !src2_wide) {
5515 tmp = neon_load_reg(rm, 1);
5516 neon_store_scratch(2, tmp);
5517 } else if (rd == rn && !src1_wide) {
5518 tmp = neon_load_reg(rn, 1);
5519 neon_store_scratch(2, tmp);
5521 TCGV_UNUSED(tmp3);
5522 for (pass = 0; pass < 2; pass++) {
5523 if (src1_wide) {
5524 neon_load_reg64(cpu_V0, rn + pass);
5525 TCGV_UNUSED(tmp);
5526 } else {
5527 if (pass == 1 && rd == rn) {
5528 tmp = neon_load_scratch(2);
5529 } else {
5530 tmp = neon_load_reg(rn, pass);
5532 if (prewiden) {
5533 gen_neon_widen(cpu_V0, tmp, size, u);
5536 if (src2_wide) {
5537 neon_load_reg64(cpu_V1, rm + pass);
5538 TCGV_UNUSED(tmp2);
5539 } else {
5540 if (pass == 1 && rd == rm) {
5541 tmp2 = neon_load_scratch(2);
5542 } else {
5543 tmp2 = neon_load_reg(rm, pass);
5545 if (prewiden) {
5546 gen_neon_widen(cpu_V1, tmp2, size, u);
5549 switch (op) {
5550 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5551 gen_neon_addl(size);
5552 break;
5553 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
5554 gen_neon_subl(size);
5555 break;
5556 case 5: case 7: /* VABAL, VABDL */
5557 switch ((size << 1) | u) {
5558 case 0:
5559 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
5560 break;
5561 case 1:
5562 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
5563 break;
5564 case 2:
5565 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
5566 break;
5567 case 3:
5568 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
5569 break;
5570 case 4:
5571 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
5572 break;
5573 case 5:
5574 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
5575 break;
5576 default: abort();
5578 tcg_temp_free_i32(tmp2);
5579 tcg_temp_free_i32(tmp);
5580 break;
5581 case 8: case 9: case 10: case 11: case 12: case 13:
5582 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5583 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5584 break;
5585 case 14: /* Polynomial VMULL */
5586 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
5587 tcg_temp_free_i32(tmp2);
5588 tcg_temp_free_i32(tmp);
5589 break;
5590 default: /* 15 is RESERVED: caught earlier */
5591 abort();
5593 if (op == 13) {
5594 /* VQDMULL */
5595 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5596 neon_store_reg64(cpu_V0, rd + pass);
5597 } else if (op == 5 || (op >= 8 && op <= 11)) {
5598 /* Accumulate. */
5599 neon_load_reg64(cpu_V1, rd + pass);
5600 switch (op) {
5601 case 10: /* VMLSL */
5602 gen_neon_negl(cpu_V0, size);
5603 /* Fall through */
5604 case 5: case 8: /* VABAL, VMLAL */
5605 gen_neon_addl(size);
5606 break;
5607 case 9: case 11: /* VQDMLAL, VQDMLSL */
5608 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5609 if (op == 11) {
5610 gen_neon_negl(cpu_V0, size);
5612 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5613 break;
5614 default:
5615 abort();
5617 neon_store_reg64(cpu_V0, rd + pass);
5618 } else if (op == 4 || op == 6) {
5619 /* Narrowing operation. */
5620 tmp = tcg_temp_new_i32();
5621 if (!u) {
5622 switch (size) {
5623 case 0:
5624 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
5625 break;
5626 case 1:
5627 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
5628 break;
5629 case 2:
5630 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5631 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5632 break;
5633 default: abort();
5635 } else {
5636 switch (size) {
5637 case 0:
5638 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
5639 break;
5640 case 1:
5641 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
5642 break;
5643 case 2:
5644 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
5645 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5646 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5647 break;
5648 default: abort();
5651 if (pass == 0) {
5652 tmp3 = tmp;
5653 } else {
5654 neon_store_reg(rd, 0, tmp3);
5655 neon_store_reg(rd, 1, tmp);
5657 } else {
5658 /* Write back the result. */
5659 neon_store_reg64(cpu_V0, rd + pass);
5662 } else {
5663 /* Two registers and a scalar. NB that for ops of this form
5664 * the ARM ARM labels bit 24 as Q, but it is in our variable
5665 * 'u', not 'q'.
5667 if (size == 0) {
5668 return 1;
5670 switch (op) {
5671 case 1: /* Float VMLA scalar */
5672 case 5: /* Floating point VMLS scalar */
5673 case 9: /* Floating point VMUL scalar */
5674 if (size == 1) {
5675 return 1;
5677 /* fall through */
5678 case 0: /* Integer VMLA scalar */
5679 case 4: /* Integer VMLS scalar */
5680 case 8: /* Integer VMUL scalar */
5681 case 12: /* VQDMULH scalar */
5682 case 13: /* VQRDMULH scalar */
5683 if (u && ((rd | rn) & 1)) {
5684 return 1;
5686 tmp = neon_get_scalar(size, rm);
5687 neon_store_scratch(0, tmp);
5688 for (pass = 0; pass < (u ? 4 : 2); pass++) {
5689 tmp = neon_load_scratch(0);
5690 tmp2 = neon_load_reg(rn, pass);
5691 if (op == 12) {
5692 if (size == 1) {
5693 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5694 } else {
5695 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5697 } else if (op == 13) {
5698 if (size == 1) {
5699 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5700 } else {
5701 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5703 } else if (op & 1) {
5704 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5705 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
5706 tcg_temp_free_ptr(fpstatus);
5707 } else {
5708 switch (size) {
5709 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5710 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5711 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5712 default: abort();
5715 tcg_temp_free_i32(tmp2);
5716 if (op < 8) {
5717 /* Accumulate. */
5718 tmp2 = neon_load_reg(rd, pass);
5719 switch (op) {
5720 case 0:
5721 gen_neon_add(size, tmp, tmp2);
5722 break;
5723 case 1:
5725 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5726 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5727 tcg_temp_free_ptr(fpstatus);
5728 break;
5730 case 4:
5731 gen_neon_rsb(size, tmp, tmp2);
5732 break;
5733 case 5:
5735 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5736 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
5737 tcg_temp_free_ptr(fpstatus);
5738 break;
5740 default:
5741 abort();
5743 tcg_temp_free_i32(tmp2);
5745 neon_store_reg(rd, pass, tmp);
5747 break;
5748 case 3: /* VQDMLAL scalar */
5749 case 7: /* VQDMLSL scalar */
5750 case 11: /* VQDMULL scalar */
5751 if (u == 1) {
5752 return 1;
5754 /* fall through */
5755 case 2: /* VMLAL sclar */
5756 case 6: /* VMLSL scalar */
5757 case 10: /* VMULL scalar */
5758 if (rd & 1) {
5759 return 1;
5761 tmp2 = neon_get_scalar(size, rm);
5762 /* We need a copy of tmp2 because gen_neon_mull
5763 * deletes it during pass 0. */
5764 tmp4 = tcg_temp_new_i32();
5765 tcg_gen_mov_i32(tmp4, tmp2);
5766 tmp3 = neon_load_reg(rn, 1);
5768 for (pass = 0; pass < 2; pass++) {
5769 if (pass == 0) {
5770 tmp = neon_load_reg(rn, 0);
5771 } else {
5772 tmp = tmp3;
5773 tmp2 = tmp4;
5775 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5776 if (op != 11) {
5777 neon_load_reg64(cpu_V1, rd + pass);
5779 switch (op) {
5780 case 6:
5781 gen_neon_negl(cpu_V0, size);
5782 /* Fall through */
5783 case 2:
5784 gen_neon_addl(size);
5785 break;
5786 case 3: case 7:
5787 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5788 if (op == 7) {
5789 gen_neon_negl(cpu_V0, size);
5791 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5792 break;
5793 case 10:
5794 /* no-op */
5795 break;
5796 case 11:
5797 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5798 break;
5799 default:
5800 abort();
5802 neon_store_reg64(cpu_V0, rd + pass);
5806 break;
5807 default: /* 14 and 15 are RESERVED */
5808 return 1;
5811 } else { /* size == 3 */
5812 if (!u) {
5813 /* Extract. */
5814 imm = (insn >> 8) & 0xf;
5816 if (imm > 7 && !q)
5817 return 1;
5819 if (q && ((rd | rn | rm) & 1)) {
5820 return 1;
5823 if (imm == 0) {
5824 neon_load_reg64(cpu_V0, rn);
5825 if (q) {
5826 neon_load_reg64(cpu_V1, rn + 1);
5828 } else if (imm == 8) {
5829 neon_load_reg64(cpu_V0, rn + 1);
5830 if (q) {
5831 neon_load_reg64(cpu_V1, rm);
5833 } else if (q) {
5834 tmp64 = tcg_temp_new_i64();
5835 if (imm < 8) {
5836 neon_load_reg64(cpu_V0, rn);
5837 neon_load_reg64(tmp64, rn + 1);
5838 } else {
5839 neon_load_reg64(cpu_V0, rn + 1);
5840 neon_load_reg64(tmp64, rm);
5842 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5843 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
5844 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5845 if (imm < 8) {
5846 neon_load_reg64(cpu_V1, rm);
5847 } else {
5848 neon_load_reg64(cpu_V1, rm + 1);
5849 imm -= 8;
5851 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5852 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
5853 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
5854 tcg_temp_free_i64(tmp64);
5855 } else {
5856 /* BUGFIX */
5857 neon_load_reg64(cpu_V0, rn);
5858 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
5859 neon_load_reg64(cpu_V1, rm);
5860 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5861 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5863 neon_store_reg64(cpu_V0, rd);
5864 if (q) {
5865 neon_store_reg64(cpu_V1, rd + 1);
5867 } else if ((insn & (1 << 11)) == 0) {
5868 /* Two register misc. */
5869 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5870 size = (insn >> 18) & 3;
5871 /* UNDEF for unknown op values and bad op-size combinations */
5872 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
5873 return 1;
5875 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
5876 q && ((rm | rd) & 1)) {
5877 return 1;
5879 switch (op) {
5880 case NEON_2RM_VREV64:
5881 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5882 tmp = neon_load_reg(rm, pass * 2);
5883 tmp2 = neon_load_reg(rm, pass * 2 + 1);
5884 switch (size) {
5885 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5886 case 1: gen_swap_half(tmp); break;
5887 case 2: /* no-op */ break;
5888 default: abort();
5890 neon_store_reg(rd, pass * 2 + 1, tmp);
5891 if (size == 2) {
5892 neon_store_reg(rd, pass * 2, tmp2);
5893 } else {
5894 switch (size) {
5895 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
5896 case 1: gen_swap_half(tmp2); break;
5897 default: abort();
5899 neon_store_reg(rd, pass * 2, tmp2);
5902 break;
5903 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
5904 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
5905 for (pass = 0; pass < q + 1; pass++) {
5906 tmp = neon_load_reg(rm, pass * 2);
5907 gen_neon_widen(cpu_V0, tmp, size, op & 1);
5908 tmp = neon_load_reg(rm, pass * 2 + 1);
5909 gen_neon_widen(cpu_V1, tmp, size, op & 1);
5910 switch (size) {
5911 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5912 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5913 case 2: tcg_gen_add_i64(CPU_V001); break;
5914 default: abort();
5916 if (op >= NEON_2RM_VPADAL) {
5917 /* Accumulate. */
5918 neon_load_reg64(cpu_V1, rd + pass);
5919 gen_neon_addl(size);
5921 neon_store_reg64(cpu_V0, rd + pass);
5923 break;
5924 case NEON_2RM_VTRN:
5925 if (size == 2) {
5926 int n;
5927 for (n = 0; n < (q ? 4 : 2); n += 2) {
5928 tmp = neon_load_reg(rm, n);
5929 tmp2 = neon_load_reg(rd, n + 1);
5930 neon_store_reg(rm, n, tmp2);
5931 neon_store_reg(rd, n + 1, tmp);
5933 } else {
5934 goto elementwise;
5936 break;
5937 case NEON_2RM_VUZP:
5938 if (gen_neon_unzip(rd, rm, size, q)) {
5939 return 1;
5941 break;
5942 case NEON_2RM_VZIP:
5943 if (gen_neon_zip(rd, rm, size, q)) {
5944 return 1;
5946 break;
5947 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
5948 /* also VQMOVUN; op field and mnemonics don't line up */
5949 if (rm & 1) {
5950 return 1;
5952 TCGV_UNUSED(tmp2);
5953 for (pass = 0; pass < 2; pass++) {
5954 neon_load_reg64(cpu_V0, rm + pass);
5955 tmp = tcg_temp_new_i32();
5956 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
5957 tmp, cpu_V0);
5958 if (pass == 0) {
5959 tmp2 = tmp;
5960 } else {
5961 neon_store_reg(rd, 0, tmp2);
5962 neon_store_reg(rd, 1, tmp);
5965 break;
5966 case NEON_2RM_VSHLL:
5967 if (q || (rd & 1)) {
5968 return 1;
5970 tmp = neon_load_reg(rm, 0);
5971 tmp2 = neon_load_reg(rm, 1);
5972 for (pass = 0; pass < 2; pass++) {
5973 if (pass == 1)
5974 tmp = tmp2;
5975 gen_neon_widen(cpu_V0, tmp, size, 1);
5976 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
5977 neon_store_reg64(cpu_V0, rd + pass);
5979 break;
5980 case NEON_2RM_VCVT_F16_F32:
5981 if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
5982 q || (rm & 1)) {
5983 return 1;
5985 tmp = tcg_temp_new_i32();
5986 tmp2 = tcg_temp_new_i32();
5987 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
5988 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5989 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
5990 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
5991 tcg_gen_shli_i32(tmp2, tmp2, 16);
5992 tcg_gen_or_i32(tmp2, tmp2, tmp);
5993 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
5994 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5995 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
5996 neon_store_reg(rd, 0, tmp2);
5997 tmp2 = tcg_temp_new_i32();
5998 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
5999 tcg_gen_shli_i32(tmp2, tmp2, 16);
6000 tcg_gen_or_i32(tmp2, tmp2, tmp);
6001 neon_store_reg(rd, 1, tmp2);
6002 tcg_temp_free_i32(tmp);
6003 break;
6004 case NEON_2RM_VCVT_F32_F16:
6005 if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
6006 q || (rd & 1)) {
6007 return 1;
6009 tmp3 = tcg_temp_new_i32();
6010 tmp = neon_load_reg(rm, 0);
6011 tmp2 = neon_load_reg(rm, 1);
6012 tcg_gen_ext16u_i32(tmp3, tmp);
6013 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6014 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
6015 tcg_gen_shri_i32(tmp3, tmp, 16);
6016 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6017 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
6018 tcg_temp_free_i32(tmp);
6019 tcg_gen_ext16u_i32(tmp3, tmp2);
6020 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6021 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
6022 tcg_gen_shri_i32(tmp3, tmp2, 16);
6023 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6024 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
6025 tcg_temp_free_i32(tmp2);
6026 tcg_temp_free_i32(tmp3);
6027 break;
6028 default:
6029 elementwise:
6030 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6031 if (neon_2rm_is_float_op(op)) {
6032 tcg_gen_ld_f32(cpu_F0s, cpu_env,
6033 neon_reg_offset(rm, pass));
6034 TCGV_UNUSED(tmp);
6035 } else {
6036 tmp = neon_load_reg(rm, pass);
6038 switch (op) {
6039 case NEON_2RM_VREV32:
6040 switch (size) {
6041 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6042 case 1: gen_swap_half(tmp); break;
6043 default: abort();
6045 break;
6046 case NEON_2RM_VREV16:
6047 gen_rev16(tmp);
6048 break;
6049 case NEON_2RM_VCLS:
6050 switch (size) {
6051 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
6052 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
6053 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
6054 default: abort();
6056 break;
6057 case NEON_2RM_VCLZ:
6058 switch (size) {
6059 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
6060 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
6061 case 2: gen_helper_clz(tmp, tmp); break;
6062 default: abort();
6064 break;
6065 case NEON_2RM_VCNT:
6066 gen_helper_neon_cnt_u8(tmp, tmp);
6067 break;
6068 case NEON_2RM_VMVN:
6069 tcg_gen_not_i32(tmp, tmp);
6070 break;
6071 case NEON_2RM_VQABS:
6072 switch (size) {
6073 case 0:
6074 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
6075 break;
6076 case 1:
6077 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
6078 break;
6079 case 2:
6080 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
6081 break;
6082 default: abort();
6084 break;
6085 case NEON_2RM_VQNEG:
6086 switch (size) {
6087 case 0:
6088 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
6089 break;
6090 case 1:
6091 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
6092 break;
6093 case 2:
6094 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
6095 break;
6096 default: abort();
6098 break;
6099 case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
6100 tmp2 = tcg_const_i32(0);
6101 switch(size) {
6102 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
6103 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
6104 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
6105 default: abort();
6107 tcg_temp_free(tmp2);
6108 if (op == NEON_2RM_VCLE0) {
6109 tcg_gen_not_i32(tmp, tmp);
6111 break;
6112 case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
6113 tmp2 = tcg_const_i32(0);
6114 switch(size) {
6115 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
6116 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
6117 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
6118 default: abort();
6120 tcg_temp_free(tmp2);
6121 if (op == NEON_2RM_VCLT0) {
6122 tcg_gen_not_i32(tmp, tmp);
6124 break;
6125 case NEON_2RM_VCEQ0:
6126 tmp2 = tcg_const_i32(0);
6127 switch(size) {
6128 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
6129 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
6130 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
6131 default: abort();
6133 tcg_temp_free(tmp2);
6134 break;
6135 case NEON_2RM_VABS:
6136 switch(size) {
6137 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
6138 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
6139 case 2: tcg_gen_abs_i32(tmp, tmp); break;
6140 default: abort();
6142 break;
6143 case NEON_2RM_VNEG:
6144 tmp2 = tcg_const_i32(0);
6145 gen_neon_rsb(size, tmp, tmp2);
6146 tcg_temp_free(tmp2);
6147 break;
6148 case NEON_2RM_VCGT0_F:
6150 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6151 tmp2 = tcg_const_i32(0);
6152 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
6153 tcg_temp_free(tmp2);
6154 tcg_temp_free_ptr(fpstatus);
6155 break;
6157 case NEON_2RM_VCGE0_F:
6159 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6160 tmp2 = tcg_const_i32(0);
6161 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
6162 tcg_temp_free(tmp2);
6163 tcg_temp_free_ptr(fpstatus);
6164 break;
6166 case NEON_2RM_VCEQ0_F:
6168 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6169 tmp2 = tcg_const_i32(0);
6170 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
6171 tcg_temp_free(tmp2);
6172 tcg_temp_free_ptr(fpstatus);
6173 break;
6175 case NEON_2RM_VCLE0_F:
6177 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6178 tmp2 = tcg_const_i32(0);
6179 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
6180 tcg_temp_free(tmp2);
6181 tcg_temp_free_ptr(fpstatus);
6182 break;
6184 case NEON_2RM_VCLT0_F:
6186 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6187 tmp2 = tcg_const_i32(0);
6188 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
6189 tcg_temp_free(tmp2);
6190 tcg_temp_free_ptr(fpstatus);
6191 break;
6193 case NEON_2RM_VABS_F:
6194 gen_vfp_abs(0);
6195 break;
6196 case NEON_2RM_VNEG_F:
6197 gen_vfp_neg(0);
6198 break;
6199 case NEON_2RM_VSWP:
6200 tmp2 = neon_load_reg(rd, pass);
6201 neon_store_reg(rm, pass, tmp2);
6202 break;
6203 case NEON_2RM_VTRN:
6204 tmp2 = neon_load_reg(rd, pass);
6205 switch (size) {
6206 case 0: gen_neon_trn_u8(tmp, tmp2); break;
6207 case 1: gen_neon_trn_u16(tmp, tmp2); break;
6208 default: abort();
6210 neon_store_reg(rm, pass, tmp2);
6211 break;
6212 case NEON_2RM_VRECPE:
6213 gen_helper_recpe_u32(tmp, tmp, cpu_env);
6214 break;
6215 case NEON_2RM_VRSQRTE:
6216 gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
6217 break;
6218 case NEON_2RM_VRECPE_F:
6219 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
6220 break;
6221 case NEON_2RM_VRSQRTE_F:
6222 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
6223 break;
6224 case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
6225 gen_vfp_sito(0, 1);
6226 break;
6227 case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
6228 gen_vfp_uito(0, 1);
6229 break;
6230 case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
6231 gen_vfp_tosiz(0, 1);
6232 break;
6233 case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
6234 gen_vfp_touiz(0, 1);
6235 break;
6236 default:
6237 /* Reserved op values were caught by the
6238 * neon_2rm_sizes[] check earlier.
6240 abort();
6242 if (neon_2rm_is_float_op(op)) {
6243 tcg_gen_st_f32(cpu_F0s, cpu_env,
6244 neon_reg_offset(rd, pass));
6245 } else {
6246 neon_store_reg(rd, pass, tmp);
6249 break;
6251 } else if ((insn & (1 << 10)) == 0) {
6252 /* VTBL, VTBX. */
6253 int n = ((insn >> 8) & 3) + 1;
6254 if ((rn + n) > 32) {
6255 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
6256 * helper function running off the end of the register file.
6258 return 1;
6260 n <<= 3;
6261 if (insn & (1 << 6)) {
6262 tmp = neon_load_reg(rd, 0);
6263 } else {
6264 tmp = tcg_temp_new_i32();
6265 tcg_gen_movi_i32(tmp, 0);
6267 tmp2 = neon_load_reg(rm, 0);
6268 tmp4 = tcg_const_i32(rn);
6269 tmp5 = tcg_const_i32(n);
6270 gen_helper_neon_tbl(tmp2, tmp2, tmp, tmp4, tmp5);
6271 tcg_temp_free_i32(tmp);
6272 if (insn & (1 << 6)) {
6273 tmp = neon_load_reg(rd, 1);
6274 } else {
6275 tmp = tcg_temp_new_i32();
6276 tcg_gen_movi_i32(tmp, 0);
6278 tmp3 = neon_load_reg(rm, 1);
6279 gen_helper_neon_tbl(tmp3, tmp3, tmp, tmp4, tmp5);
6280 tcg_temp_free_i32(tmp5);
6281 tcg_temp_free_i32(tmp4);
6282 neon_store_reg(rd, 0, tmp2);
6283 neon_store_reg(rd, 1, tmp3);
6284 tcg_temp_free_i32(tmp);
6285 } else if ((insn & 0x380) == 0) {
6286 /* VDUP */
6287 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
6288 return 1;
6290 if (insn & (1 << 19)) {
6291 tmp = neon_load_reg(rm, 1);
6292 } else {
6293 tmp = neon_load_reg(rm, 0);
6295 if (insn & (1 << 16)) {
6296 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
6297 } else if (insn & (1 << 17)) {
6298 if ((insn >> 18) & 1)
6299 gen_neon_dup_high16(tmp);
6300 else
6301 gen_neon_dup_low16(tmp);
6303 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6304 tmp2 = tcg_temp_new_i32();
6305 tcg_gen_mov_i32(tmp2, tmp);
6306 neon_store_reg(rd, pass, tmp2);
6308 tcg_temp_free_i32(tmp);
6309 } else {
6310 return 1;
6314 return 0;
6317 static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
6319 int crn = (insn >> 16) & 0xf;
6320 int crm = insn & 0xf;
6321 int op1 = (insn >> 21) & 7;
6322 int op2 = (insn >> 5) & 7;
6323 int rt = (insn >> 12) & 0xf;
6324 TCGv tmp;
6326 /* Minimal set of debug registers, since we don't support debug */
6327 if (op1 == 0 && crn == 0 && op2 == 0) {
6328 switch (crm) {
6329 case 0:
6330 /* DBGDIDR: just RAZ. In particular this means the
6331 * "debug architecture version" bits will read as
6332 * a reserved value, which should cause Linux to
6333 * not try to use the debug hardware.
6335 tmp = tcg_const_i32(0);
6336 store_reg(s, rt, tmp);
6337 return 0;
6338 case 1:
6339 case 2:
6340 /* DBGDRAR and DBGDSAR: v7 only. Always RAZ since we
6341 * don't implement memory mapped debug components
6343 if (ENABLE_ARCH_7) {
6344 tmp = tcg_const_i32(0);
6345 store_reg(s, rt, tmp);
6346 return 0;
6348 break;
6349 default:
6350 break;
6354 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
6355 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
6356 /* TEECR */
6357 if (IS_USER(s))
6358 return 1;
6359 tmp = load_cpu_field(teecr);
6360 store_reg(s, rt, tmp);
6361 return 0;
6363 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
6364 /* TEEHBR */
6365 if (IS_USER(s) && (env->teecr & 1))
6366 return 1;
6367 tmp = load_cpu_field(teehbr);
6368 store_reg(s, rt, tmp);
6369 return 0;
6372 fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
6373 op1, crn, crm, op2);
6374 return 1;
6377 static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
6379 int crn = (insn >> 16) & 0xf;
6380 int crm = insn & 0xf;
6381 int op1 = (insn >> 21) & 7;
6382 int op2 = (insn >> 5) & 7;
6383 int rt = (insn >> 12) & 0xf;
6384 TCGv tmp;
6386 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
6387 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
6388 /* TEECR */
6389 if (IS_USER(s))
6390 return 1;
6391 tmp = load_reg(s, rt);
6392 gen_helper_set_teecr(cpu_env, tmp);
6393 tcg_temp_free_i32(tmp);
6394 return 0;
6396 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
6397 /* TEEHBR */
6398 if (IS_USER(s) && (env->teecr & 1))
6399 return 1;
6400 tmp = load_reg(s, rt);
6401 store_cpu_field(tmp, teehbr);
6402 return 0;
6405 fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
6406 op1, crn, crm, op2);
6407 return 1;
6410 static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
6412 int cpnum;
6414 cpnum = (insn >> 8) & 0xf;
6415 if (arm_feature(env, ARM_FEATURE_XSCALE)
6416 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
6417 return 1;
6419 switch (cpnum) {
6420 case 0:
6421 case 1:
6422 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
6423 return disas_iwmmxt_insn(env, s, insn);
6424 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
6425 return disas_dsp_insn(env, s, insn);
6427 return 1;
6428 case 10:
6429 case 11:
6430 return disas_vfp_insn (env, s, insn);
6431 case 14:
6432 /* Coprocessors 7-15 are architecturally reserved by ARM.
6433 Unfortunately Intel decided to ignore this. */
6434 if (arm_feature(env, ARM_FEATURE_XSCALE))
6435 goto board;
6436 if (insn & (1 << 20))
6437 return disas_cp14_read(env, s, insn);
6438 else
6439 return disas_cp14_write(env, s, insn);
6440 case 15:
6441 return disas_cp15_insn (env, s, insn);
6442 default:
6443 board:
6444 /* Unknown coprocessor. See if the board has hooked it. */
6445 return disas_cp_insn (env, s, insn);
6450 /* Store a 64-bit value to a register pair. Clobbers val. */
6451 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
6453 TCGv tmp;
6454 tmp = tcg_temp_new_i32();
6455 tcg_gen_trunc_i64_i32(tmp, val);
6456 store_reg(s, rlow, tmp);
6457 tmp = tcg_temp_new_i32();
6458 tcg_gen_shri_i64(val, val, 32);
6459 tcg_gen_trunc_i64_i32(tmp, val);
6460 store_reg(s, rhigh, tmp);
6463 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
6464 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
6466 TCGv_i64 tmp;
6467 TCGv tmp2;
6469 /* Load value and extend to 64 bits. */
6470 tmp = tcg_temp_new_i64();
6471 tmp2 = load_reg(s, rlow);
6472 tcg_gen_extu_i32_i64(tmp, tmp2);
6473 tcg_temp_free_i32(tmp2);
6474 tcg_gen_add_i64(val, val, tmp);
6475 tcg_temp_free_i64(tmp);
6478 /* load and add a 64-bit value from a register pair. */
6479 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
6481 TCGv_i64 tmp;
6482 TCGv tmpl;
6483 TCGv tmph;
6485 /* Load 64-bit value rd:rn. */
6486 tmpl = load_reg(s, rlow);
6487 tmph = load_reg(s, rhigh);
6488 tmp = tcg_temp_new_i64();
6489 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
6490 tcg_temp_free_i32(tmpl);
6491 tcg_temp_free_i32(tmph);
6492 tcg_gen_add_i64(val, val, tmp);
6493 tcg_temp_free_i64(tmp);
6496 /* Set N and Z flags from a 64-bit value. */
6497 static void gen_logicq_cc(TCGv_i64 val)
6499 TCGv tmp = tcg_temp_new_i32();
6500 gen_helper_logicq_cc(tmp, val);
6501 gen_logic_CC(tmp);
6502 tcg_temp_free_i32(tmp);
6505 /* Load/Store exclusive instructions are implemented by remembering
6506 the value/address loaded, and seeing if these are the same
6507 when the store is performed. This should be is sufficient to implement
6508 the architecturally mandated semantics, and avoids having to monitor
6509 regular stores.
6511 In system emulation mode only one CPU will be running at once, so
6512 this sequence is effectively atomic. In user emulation mode we
6513 throw an exception and handle the atomic operation elsewhere. */
6514 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
6515 TCGv addr, int size)
6517 TCGv tmp;
6519 switch (size) {
6520 case 0:
6521 tmp = gen_ld8u(addr, IS_USER(s));
6522 break;
6523 case 1:
6524 tmp = gen_ld16u(addr, IS_USER(s));
6525 break;
6526 case 2:
6527 case 3:
6528 tmp = gen_ld32(addr, IS_USER(s));
6529 break;
6530 default:
6531 abort();
6533 tcg_gen_mov_i32(cpu_exclusive_val, tmp);
6534 store_reg(s, rt, tmp);
6535 if (size == 3) {
6536 TCGv tmp2 = tcg_temp_new_i32();
6537 tcg_gen_addi_i32(tmp2, addr, 4);
6538 tmp = gen_ld32(tmp2, IS_USER(s));
6539 tcg_temp_free_i32(tmp2);
6540 tcg_gen_mov_i32(cpu_exclusive_high, tmp);
6541 store_reg(s, rt2, tmp);
6543 tcg_gen_mov_i32(cpu_exclusive_addr, addr);
6546 static void gen_clrex(DisasContext *s)
6548 tcg_gen_movi_i32(cpu_exclusive_addr, -1);
6551 #ifdef CONFIG_USER_ONLY
6552 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
6553 TCGv addr, int size)
6555 tcg_gen_mov_i32(cpu_exclusive_test, addr);
6556 tcg_gen_movi_i32(cpu_exclusive_info,
6557 size | (rd << 4) | (rt << 8) | (rt2 << 12));
6558 gen_exception_insn(s, 4, EXCP_STREX);
6560 #else
6561 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
6562 TCGv addr, int size)
6564 TCGv tmp;
6565 int done_label;
6566 int fail_label;
6568 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
6569 [addr] = {Rt};
6570 {Rd} = 0;
6571 } else {
6572 {Rd} = 1;
6573 } */
6574 fail_label = gen_new_label();
6575 done_label = gen_new_label();
6576 tcg_gen_brcond_i32(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
6577 switch (size) {
6578 case 0:
6579 tmp = gen_ld8u(addr, IS_USER(s));
6580 break;
6581 case 1:
6582 tmp = gen_ld16u(addr, IS_USER(s));
6583 break;
6584 case 2:
6585 case 3:
6586 tmp = gen_ld32(addr, IS_USER(s));
6587 break;
6588 default:
6589 abort();
6591 tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label);
6592 tcg_temp_free_i32(tmp);
6593 if (size == 3) {
6594 TCGv tmp2 = tcg_temp_new_i32();
6595 tcg_gen_addi_i32(tmp2, addr, 4);
6596 tmp = gen_ld32(tmp2, IS_USER(s));
6597 tcg_temp_free_i32(tmp2);
6598 tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_high, fail_label);
6599 tcg_temp_free_i32(tmp);
6601 tmp = load_reg(s, rt);
6602 switch (size) {
6603 case 0:
6604 gen_st8(tmp, addr, IS_USER(s));
6605 break;
6606 case 1:
6607 gen_st16(tmp, addr, IS_USER(s));
6608 break;
6609 case 2:
6610 case 3:
6611 gen_st32(tmp, addr, IS_USER(s));
6612 break;
6613 default:
6614 abort();
6616 if (size == 3) {
6617 tcg_gen_addi_i32(addr, addr, 4);
6618 tmp = load_reg(s, rt2);
6619 gen_st32(tmp, addr, IS_USER(s));
6621 tcg_gen_movi_i32(cpu_R[rd], 0);
6622 tcg_gen_br(done_label);
6623 gen_set_label(fail_label);
6624 tcg_gen_movi_i32(cpu_R[rd], 1);
6625 gen_set_label(done_label);
6626 tcg_gen_movi_i32(cpu_exclusive_addr, -1);
6628 #endif
6630 static void disas_arm_insn(CPUState * env, DisasContext *s)
6632 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
6633 TCGv tmp;
6634 TCGv tmp2;
6635 TCGv tmp3;
6636 TCGv addr;
6637 TCGv_i64 tmp64;
6639 insn = ldl_code(s->pc);
6640 s->pc += 4;
6642 /* M variants do not implement ARM mode. */
6643 if (IS_M(env))
6644 goto illegal_op;
6645 cond = insn >> 28;
6646 if (cond == 0xf){
6647 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
6648 * choose to UNDEF. In ARMv5 and above the space is used
6649 * for miscellaneous unconditional instructions.
6651 ARCH(5);
6653 /* Unconditional instructions. */
6654 if (((insn >> 25) & 7) == 1) {
6655 /* NEON Data processing. */
6656 if (!arm_feature(env, ARM_FEATURE_NEON))
6657 goto illegal_op;
6659 if (disas_neon_data_insn(env, s, insn))
6660 goto illegal_op;
6661 return;
6663 if ((insn & 0x0f100000) == 0x04000000) {
6664 /* NEON load/store. */
6665 if (!arm_feature(env, ARM_FEATURE_NEON))
6666 goto illegal_op;
6668 if (disas_neon_ls_insn(env, s, insn))
6669 goto illegal_op;
6670 return;
6672 if (((insn & 0x0f30f000) == 0x0510f000) ||
6673 ((insn & 0x0f30f010) == 0x0710f000)) {
6674 if ((insn & (1 << 22)) == 0) {
6675 /* PLDW; v7MP */
6676 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
6677 goto illegal_op;
6680 /* Otherwise PLD; v5TE+ */
6681 ARCH(5TE);
6682 return;
6684 if (((insn & 0x0f70f000) == 0x0450f000) ||
6685 ((insn & 0x0f70f010) == 0x0650f000)) {
6686 ARCH(7);
6687 return; /* PLI; V7 */
6689 if (((insn & 0x0f700000) == 0x04100000) ||
6690 ((insn & 0x0f700010) == 0x06100000)) {
6691 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
6692 goto illegal_op;
6694 return; /* v7MP: Unallocated memory hint: must NOP */
6697 if ((insn & 0x0ffffdff) == 0x01010000) {
6698 ARCH(6);
6699 /* setend */
6700 if (insn & (1 << 9)) {
6701 /* BE8 mode not implemented. */
6702 goto illegal_op;
6704 return;
6705 } else if ((insn & 0x0fffff00) == 0x057ff000) {
6706 switch ((insn >> 4) & 0xf) {
6707 case 1: /* clrex */
6708 ARCH(6K);
6709 gen_clrex(s);
6710 return;
6711 case 4: /* dsb */
6712 case 5: /* dmb */
6713 case 6: /* isb */
6714 ARCH(7);
6715 /* We don't emulate caches so these are a no-op. */
6716 return;
6717 default:
6718 goto illegal_op;
6720 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
6721 /* srs */
6722 int32_t offset;
6723 if (IS_USER(s))
6724 goto illegal_op;
6725 ARCH(6);
6726 op1 = (insn & 0x1f);
6727 addr = tcg_temp_new_i32();
6728 tmp = tcg_const_i32(op1);
6729 gen_helper_get_r13_banked(addr, cpu_env, tmp);
6730 tcg_temp_free_i32(tmp);
6731 i = (insn >> 23) & 3;
6732 switch (i) {
6733 case 0: offset = -4; break; /* DA */
6734 case 1: offset = 0; break; /* IA */
6735 case 2: offset = -8; break; /* DB */
6736 case 3: offset = 4; break; /* IB */
6737 default: abort();
6739 if (offset)
6740 tcg_gen_addi_i32(addr, addr, offset);
6741 tmp = load_reg(s, 14);
6742 gen_st32(tmp, addr, 0);
6743 tmp = load_cpu_field(spsr);
6744 tcg_gen_addi_i32(addr, addr, 4);
6745 gen_st32(tmp, addr, 0);
6746 if (insn & (1 << 21)) {
6747 /* Base writeback. */
6748 switch (i) {
6749 case 0: offset = -8; break;
6750 case 1: offset = 4; break;
6751 case 2: offset = -4; break;
6752 case 3: offset = 0; break;
6753 default: abort();
6755 if (offset)
6756 tcg_gen_addi_i32(addr, addr, offset);
6757 tmp = tcg_const_i32(op1);
6758 gen_helper_set_r13_banked(cpu_env, tmp, addr);
6759 tcg_temp_free_i32(tmp);
6760 tcg_temp_free_i32(addr);
6761 } else {
6762 tcg_temp_free_i32(addr);
6764 return;
6765 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
6766 /* rfe */
6767 int32_t offset;
6768 if (IS_USER(s))
6769 goto illegal_op;
6770 ARCH(6);
6771 rn = (insn >> 16) & 0xf;
6772 addr = load_reg(s, rn);
6773 i = (insn >> 23) & 3;
6774 switch (i) {
6775 case 0: offset = -4; break; /* DA */
6776 case 1: offset = 0; break; /* IA */
6777 case 2: offset = -8; break; /* DB */
6778 case 3: offset = 4; break; /* IB */
6779 default: abort();
6781 if (offset)
6782 tcg_gen_addi_i32(addr, addr, offset);
6783 /* Load PC into tmp and CPSR into tmp2. */
6784 tmp = gen_ld32(addr, 0);
6785 tcg_gen_addi_i32(addr, addr, 4);
6786 tmp2 = gen_ld32(addr, 0);
6787 if (insn & (1 << 21)) {
6788 /* Base writeback. */
6789 switch (i) {
6790 case 0: offset = -8; break;
6791 case 1: offset = 4; break;
6792 case 2: offset = -4; break;
6793 case 3: offset = 0; break;
6794 default: abort();
6796 if (offset)
6797 tcg_gen_addi_i32(addr, addr, offset);
6798 store_reg(s, rn, addr);
6799 } else {
6800 tcg_temp_free_i32(addr);
6802 gen_rfe(s, tmp, tmp2);
6803 return;
6804 } else if ((insn & 0x0e000000) == 0x0a000000) {
6805 /* branch link and change to thumb (blx <offset>) */
6806 int32_t offset;
6808 val = (uint32_t)s->pc;
6809 tmp = tcg_temp_new_i32();
6810 tcg_gen_movi_i32(tmp, val);
6811 store_reg(s, 14, tmp);
6812 /* Sign-extend the 24-bit offset */
6813 offset = (((int32_t)insn) << 8) >> 8;
6814 /* offset * 4 + bit24 * 2 + (thumb bit) */
6815 val += (offset << 2) | ((insn >> 23) & 2) | 1;
6816 /* pipeline offset */
6817 val += 4;
6818 /* protected by ARCH(5); above, near the start of uncond block */
6819 gen_bx_im(s, val);
6820 return;
6821 } else if ((insn & 0x0e000f00) == 0x0c000100) {
6822 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
6823 /* iWMMXt register transfer. */
6824 if (env->cp15.c15_cpar & (1 << 1))
6825 if (!disas_iwmmxt_insn(env, s, insn))
6826 return;
6828 } else if ((insn & 0x0fe00000) == 0x0c400000) {
6829 /* Coprocessor double register transfer. */
6830 ARCH(5TE);
6831 } else if ((insn & 0x0f000010) == 0x0e000010) {
6832 /* Additional coprocessor register transfer. */
6833 } else if ((insn & 0x0ff10020) == 0x01000000) {
6834 uint32_t mask;
6835 uint32_t val;
6836 /* cps (privileged) */
6837 if (IS_USER(s))
6838 return;
6839 mask = val = 0;
6840 if (insn & (1 << 19)) {
6841 if (insn & (1 << 8))
6842 mask |= CPSR_A;
6843 if (insn & (1 << 7))
6844 mask |= CPSR_I;
6845 if (insn & (1 << 6))
6846 mask |= CPSR_F;
6847 if (insn & (1 << 18))
6848 val |= mask;
6850 if (insn & (1 << 17)) {
6851 mask |= CPSR_M;
6852 val |= (insn & 0x1f);
6854 if (mask) {
6855 gen_set_psr_im(s, mask, 0, val);
6857 return;
6859 goto illegal_op;
6861 if (cond != 0xe) {
6862 /* if not always execute, we generate a conditional jump to
6863 next instruction */
6864 s->condlabel = gen_new_label();
6865 gen_test_cc(cond ^ 1, s->condlabel);
6866 s->condjmp = 1;
6868 if ((insn & 0x0f900000) == 0x03000000) {
6869 if ((insn & (1 << 21)) == 0) {
6870 ARCH(6T2);
6871 rd = (insn >> 12) & 0xf;
6872 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
6873 if ((insn & (1 << 22)) == 0) {
6874 /* MOVW */
6875 tmp = tcg_temp_new_i32();
6876 tcg_gen_movi_i32(tmp, val);
6877 } else {
6878 /* MOVT */
6879 tmp = load_reg(s, rd);
6880 tcg_gen_ext16u_i32(tmp, tmp);
6881 tcg_gen_ori_i32(tmp, tmp, val << 16);
6883 store_reg(s, rd, tmp);
6884 } else {
6885 if (((insn >> 12) & 0xf) != 0xf)
6886 goto illegal_op;
6887 if (((insn >> 16) & 0xf) == 0) {
6888 gen_nop_hint(s, insn & 0xff);
6889 } else {
6890 /* CPSR = immediate */
6891 val = insn & 0xff;
6892 shift = ((insn >> 8) & 0xf) * 2;
6893 if (shift)
6894 val = (val >> shift) | (val << (32 - shift));
6895 i = ((insn & (1 << 22)) != 0);
6896 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
6897 goto illegal_op;
6900 } else if ((insn & 0x0f900000) == 0x01000000
6901 && (insn & 0x00000090) != 0x00000090) {
6902 /* miscellaneous instructions */
6903 op1 = (insn >> 21) & 3;
6904 sh = (insn >> 4) & 0xf;
6905 rm = insn & 0xf;
6906 switch (sh) {
6907 case 0x0: /* move program status register */
6908 if (op1 & 1) {
6909 /* PSR = reg */
6910 tmp = load_reg(s, rm);
6911 i = ((op1 & 2) != 0);
6912 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
6913 goto illegal_op;
6914 } else {
6915 /* reg = PSR */
6916 rd = (insn >> 12) & 0xf;
6917 if (op1 & 2) {
6918 if (IS_USER(s))
6919 goto illegal_op;
6920 tmp = load_cpu_field(spsr);
6921 } else {
6922 tmp = tcg_temp_new_i32();
6923 gen_helper_cpsr_read(tmp);
6925 store_reg(s, rd, tmp);
6927 break;
6928 case 0x1:
6929 if (op1 == 1) {
6930 /* branch/exchange thumb (bx). */
6931 ARCH(4T);
6932 tmp = load_reg(s, rm);
6933 gen_bx(s, tmp);
6934 } else if (op1 == 3) {
6935 /* clz */
6936 ARCH(5);
6937 rd = (insn >> 12) & 0xf;
6938 tmp = load_reg(s, rm);
6939 gen_helper_clz(tmp, tmp);
6940 store_reg(s, rd, tmp);
6941 } else {
6942 goto illegal_op;
6944 break;
6945 case 0x2:
6946 if (op1 == 1) {
6947 ARCH(5J); /* bxj */
6948 /* Trivial implementation equivalent to bx. */
6949 tmp = load_reg(s, rm);
6950 gen_bx(s, tmp);
6951 } else {
6952 goto illegal_op;
6954 break;
6955 case 0x3:
6956 if (op1 != 1)
6957 goto illegal_op;
6959 ARCH(5);
6960 /* branch link/exchange thumb (blx) */
6961 tmp = load_reg(s, rm);
6962 tmp2 = tcg_temp_new_i32();
6963 tcg_gen_movi_i32(tmp2, s->pc);
6964 store_reg(s, 14, tmp2);
6965 gen_bx(s, tmp);
6966 break;
6967 case 0x5: /* saturating add/subtract */
6968 ARCH(5TE);
6969 rd = (insn >> 12) & 0xf;
6970 rn = (insn >> 16) & 0xf;
6971 tmp = load_reg(s, rm);
6972 tmp2 = load_reg(s, rn);
6973 if (op1 & 2)
6974 gen_helper_double_saturate(tmp2, tmp2);
6975 if (op1 & 1)
6976 gen_helper_sub_saturate(tmp, tmp, tmp2);
6977 else
6978 gen_helper_add_saturate(tmp, tmp, tmp2);
6979 tcg_temp_free_i32(tmp2);
6980 store_reg(s, rd, tmp);
6981 break;
6982 case 7:
6983 /* SMC instruction (op1 == 3)
6984 and undefined instructions (op1 == 0 || op1 == 2)
6985 will trap */
6986 if (op1 != 1) {
6987 goto illegal_op;
6989 /* bkpt */
6990 ARCH(5);
6991 gen_exception_insn(s, 4, EXCP_BKPT);
6992 break;
6993 case 0x8: /* signed multiply */
6994 case 0xa:
6995 case 0xc:
6996 case 0xe:
6997 ARCH(5TE);
6998 rs = (insn >> 8) & 0xf;
6999 rn = (insn >> 12) & 0xf;
7000 rd = (insn >> 16) & 0xf;
7001 if (op1 == 1) {
7002 /* (32 * 16) >> 16 */
7003 tmp = load_reg(s, rm);
7004 tmp2 = load_reg(s, rs);
7005 if (sh & 4)
7006 tcg_gen_sari_i32(tmp2, tmp2, 16);
7007 else
7008 gen_sxth(tmp2);
7009 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7010 tcg_gen_shri_i64(tmp64, tmp64, 16);
7011 tmp = tcg_temp_new_i32();
7012 tcg_gen_trunc_i64_i32(tmp, tmp64);
7013 tcg_temp_free_i64(tmp64);
7014 if ((sh & 2) == 0) {
7015 tmp2 = load_reg(s, rn);
7016 gen_helper_add_setq(tmp, tmp, tmp2);
7017 tcg_temp_free_i32(tmp2);
7019 store_reg(s, rd, tmp);
7020 } else {
7021 /* 16 * 16 */
7022 tmp = load_reg(s, rm);
7023 tmp2 = load_reg(s, rs);
7024 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
7025 tcg_temp_free_i32(tmp2);
7026 if (op1 == 2) {
7027 tmp64 = tcg_temp_new_i64();
7028 tcg_gen_ext_i32_i64(tmp64, tmp);
7029 tcg_temp_free_i32(tmp);
7030 gen_addq(s, tmp64, rn, rd);
7031 gen_storeq_reg(s, rn, rd, tmp64);
7032 tcg_temp_free_i64(tmp64);
7033 } else {
7034 if (op1 == 0) {
7035 tmp2 = load_reg(s, rn);
7036 gen_helper_add_setq(tmp, tmp, tmp2);
7037 tcg_temp_free_i32(tmp2);
7039 store_reg(s, rd, tmp);
7042 break;
7043 default:
7044 goto illegal_op;
7046 } else if (((insn & 0x0e000000) == 0 &&
7047 (insn & 0x00000090) != 0x90) ||
7048 ((insn & 0x0e000000) == (1 << 25))) {
7049 int set_cc, logic_cc, shiftop;
7051 op1 = (insn >> 21) & 0xf;
7052 set_cc = (insn >> 20) & 1;
7053 logic_cc = table_logic_cc[op1] & set_cc;
7055 /* data processing instruction */
7056 if (insn & (1 << 25)) {
7057 /* immediate operand */
7058 val = insn & 0xff;
7059 shift = ((insn >> 8) & 0xf) * 2;
7060 if (shift) {
7061 val = (val >> shift) | (val << (32 - shift));
7063 tmp2 = tcg_temp_new_i32();
7064 tcg_gen_movi_i32(tmp2, val);
7065 if (logic_cc && shift) {
7066 gen_set_CF_bit31(tmp2);
7068 } else {
7069 /* register */
7070 rm = (insn) & 0xf;
7071 tmp2 = load_reg(s, rm);
7072 shiftop = (insn >> 5) & 3;
7073 if (!(insn & (1 << 4))) {
7074 shift = (insn >> 7) & 0x1f;
7075 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
7076 } else {
7077 rs = (insn >> 8) & 0xf;
7078 tmp = load_reg(s, rs);
7079 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
7082 if (op1 != 0x0f && op1 != 0x0d) {
7083 rn = (insn >> 16) & 0xf;
7084 tmp = load_reg(s, rn);
7085 } else {
7086 TCGV_UNUSED(tmp);
7088 rd = (insn >> 12) & 0xf;
7089 switch(op1) {
7090 case 0x00:
7091 tcg_gen_and_i32(tmp, tmp, tmp2);
7092 if (logic_cc) {
7093 gen_logic_CC(tmp);
7095 store_reg_bx(env, s, rd, tmp);
7096 break;
7097 case 0x01:
7098 tcg_gen_xor_i32(tmp, tmp, tmp2);
7099 if (logic_cc) {
7100 gen_logic_CC(tmp);
7102 store_reg_bx(env, s, rd, tmp);
7103 break;
7104 case 0x02:
7105 if (set_cc && rd == 15) {
7106 /* SUBS r15, ... is used for exception return. */
7107 if (IS_USER(s)) {
7108 goto illegal_op;
7110 gen_helper_sub_cc(tmp, tmp, tmp2);
7111 gen_exception_return(s, tmp);
7112 } else {
7113 if (set_cc) {
7114 gen_helper_sub_cc(tmp, tmp, tmp2);
7115 } else {
7116 tcg_gen_sub_i32(tmp, tmp, tmp2);
7118 store_reg_bx(env, s, rd, tmp);
7120 break;
7121 case 0x03:
7122 if (set_cc) {
7123 gen_helper_sub_cc(tmp, tmp2, tmp);
7124 } else {
7125 tcg_gen_sub_i32(tmp, tmp2, tmp);
7127 store_reg_bx(env, s, rd, tmp);
7128 break;
7129 case 0x04:
7130 if (set_cc) {
7131 gen_helper_add_cc(tmp, tmp, tmp2);
7132 } else {
7133 tcg_gen_add_i32(tmp, tmp, tmp2);
7135 store_reg_bx(env, s, rd, tmp);
7136 break;
7137 case 0x05:
7138 if (set_cc) {
7139 gen_helper_adc_cc(tmp, tmp, tmp2);
7140 } else {
7141 gen_add_carry(tmp, tmp, tmp2);
7143 store_reg_bx(env, s, rd, tmp);
7144 break;
7145 case 0x06:
7146 if (set_cc) {
7147 gen_helper_sbc_cc(tmp, tmp, tmp2);
7148 } else {
7149 gen_sub_carry(tmp, tmp, tmp2);
7151 store_reg_bx(env, s, rd, tmp);
7152 break;
7153 case 0x07:
7154 if (set_cc) {
7155 gen_helper_sbc_cc(tmp, tmp2, tmp);
7156 } else {
7157 gen_sub_carry(tmp, tmp2, tmp);
7159 store_reg_bx(env, s, rd, tmp);
7160 break;
7161 case 0x08:
7162 if (set_cc) {
7163 tcg_gen_and_i32(tmp, tmp, tmp2);
7164 gen_logic_CC(tmp);
7166 tcg_temp_free_i32(tmp);
7167 break;
7168 case 0x09:
7169 if (set_cc) {
7170 tcg_gen_xor_i32(tmp, tmp, tmp2);
7171 gen_logic_CC(tmp);
7173 tcg_temp_free_i32(tmp);
7174 break;
7175 case 0x0a:
7176 if (set_cc) {
7177 gen_helper_sub_cc(tmp, tmp, tmp2);
7179 tcg_temp_free_i32(tmp);
7180 break;
7181 case 0x0b:
7182 if (set_cc) {
7183 gen_helper_add_cc(tmp, tmp, tmp2);
7185 tcg_temp_free_i32(tmp);
7186 break;
7187 case 0x0c:
7188 tcg_gen_or_i32(tmp, tmp, tmp2);
7189 if (logic_cc) {
7190 gen_logic_CC(tmp);
7192 store_reg_bx(env, s, rd, tmp);
7193 break;
7194 case 0x0d:
7195 if (logic_cc && rd == 15) {
7196 /* MOVS r15, ... is used for exception return. */
7197 if (IS_USER(s)) {
7198 goto illegal_op;
7200 gen_exception_return(s, tmp2);
7201 } else {
7202 if (logic_cc) {
7203 gen_logic_CC(tmp2);
7205 store_reg_bx(env, s, rd, tmp2);
7207 break;
7208 case 0x0e:
7209 tcg_gen_andc_i32(tmp, tmp, tmp2);
7210 if (logic_cc) {
7211 gen_logic_CC(tmp);
7213 store_reg_bx(env, s, rd, tmp);
7214 break;
7215 default:
7216 case 0x0f:
7217 tcg_gen_not_i32(tmp2, tmp2);
7218 if (logic_cc) {
7219 gen_logic_CC(tmp2);
7221 store_reg_bx(env, s, rd, tmp2);
7222 break;
7224 if (op1 != 0x0f && op1 != 0x0d) {
7225 tcg_temp_free_i32(tmp2);
7227 } else {
7228 /* other instructions */
7229 op1 = (insn >> 24) & 0xf;
7230 switch(op1) {
7231 case 0x0:
7232 case 0x1:
7233 /* multiplies, extra load/stores */
7234 sh = (insn >> 5) & 3;
7235 if (sh == 0) {
7236 if (op1 == 0x0) {
7237 rd = (insn >> 16) & 0xf;
7238 rn = (insn >> 12) & 0xf;
7239 rs = (insn >> 8) & 0xf;
7240 rm = (insn) & 0xf;
7241 op1 = (insn >> 20) & 0xf;
7242 switch (op1) {
7243 case 0: case 1: case 2: case 3: case 6:
7244 /* 32 bit mul */
7245 tmp = load_reg(s, rs);
7246 tmp2 = load_reg(s, rm);
7247 tcg_gen_mul_i32(tmp, tmp, tmp2);
7248 tcg_temp_free_i32(tmp2);
7249 if (insn & (1 << 22)) {
7250 /* Subtract (mls) */
7251 ARCH(6T2);
7252 tmp2 = load_reg(s, rn);
7253 tcg_gen_sub_i32(tmp, tmp2, tmp);
7254 tcg_temp_free_i32(tmp2);
7255 } else if (insn & (1 << 21)) {
7256 /* Add */
7257 tmp2 = load_reg(s, rn);
7258 tcg_gen_add_i32(tmp, tmp, tmp2);
7259 tcg_temp_free_i32(tmp2);
7261 if (insn & (1 << 20))
7262 gen_logic_CC(tmp);
7263 store_reg(s, rd, tmp);
7264 break;
7265 case 4:
7266 /* 64 bit mul double accumulate (UMAAL) */
7267 ARCH(6);
7268 tmp = load_reg(s, rs);
7269 tmp2 = load_reg(s, rm);
7270 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7271 gen_addq_lo(s, tmp64, rn);
7272 gen_addq_lo(s, tmp64, rd);
7273 gen_storeq_reg(s, rn, rd, tmp64);
7274 tcg_temp_free_i64(tmp64);
7275 break;
7276 case 8: case 9: case 10: case 11:
7277 case 12: case 13: case 14: case 15:
7278 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
7279 tmp = load_reg(s, rs);
7280 tmp2 = load_reg(s, rm);
7281 if (insn & (1 << 22)) {
7282 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7283 } else {
7284 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7286 if (insn & (1 << 21)) { /* mult accumulate */
7287 gen_addq(s, tmp64, rn, rd);
7289 if (insn & (1 << 20)) {
7290 gen_logicq_cc(tmp64);
7292 gen_storeq_reg(s, rn, rd, tmp64);
7293 tcg_temp_free_i64(tmp64);
7294 break;
7295 default:
7296 goto illegal_op;
7298 } else {
7299 rn = (insn >> 16) & 0xf;
7300 rd = (insn >> 12) & 0xf;
7301 if (insn & (1 << 23)) {
7302 /* load/store exclusive */
7303 op1 = (insn >> 21) & 0x3;
7304 if (op1)
7305 ARCH(6K);
7306 else
7307 ARCH(6);
7308 addr = tcg_temp_local_new_i32();
7309 load_reg_var(s, addr, rn);
7310 if (insn & (1 << 20)) {
7311 switch (op1) {
7312 case 0: /* ldrex */
7313 gen_load_exclusive(s, rd, 15, addr, 2);
7314 break;
7315 case 1: /* ldrexd */
7316 gen_load_exclusive(s, rd, rd + 1, addr, 3);
7317 break;
7318 case 2: /* ldrexb */
7319 gen_load_exclusive(s, rd, 15, addr, 0);
7320 break;
7321 case 3: /* ldrexh */
7322 gen_load_exclusive(s, rd, 15, addr, 1);
7323 break;
7324 default:
7325 abort();
7327 } else {
7328 rm = insn & 0xf;
7329 switch (op1) {
7330 case 0: /* strex */
7331 gen_store_exclusive(s, rd, rm, 15, addr, 2);
7332 break;
7333 case 1: /* strexd */
7334 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
7335 break;
7336 case 2: /* strexb */
7337 gen_store_exclusive(s, rd, rm, 15, addr, 0);
7338 break;
7339 case 3: /* strexh */
7340 gen_store_exclusive(s, rd, rm, 15, addr, 1);
7341 break;
7342 default:
7343 abort();
7346 tcg_temp_free(addr);
7347 } else {
7348 /* SWP instruction */
7349 rm = (insn) & 0xf;
7351 /* ??? This is not really atomic. However we know
7352 we never have multiple CPUs running in parallel,
7353 so it is good enough. */
7354 addr = load_reg(s, rn);
7355 tmp = load_reg(s, rm);
7356 if (insn & (1 << 22)) {
7357 tmp2 = gen_ld8u(addr, IS_USER(s));
7358 gen_st8(tmp, addr, IS_USER(s));
7359 } else {
7360 tmp2 = gen_ld32(addr, IS_USER(s));
7361 gen_st32(tmp, addr, IS_USER(s));
7363 tcg_temp_free_i32(addr);
7364 store_reg(s, rd, tmp2);
7367 } else {
7368 int address_offset;
7369 int load;
7370 /* Misc load/store */
7371 rn = (insn >> 16) & 0xf;
7372 rd = (insn >> 12) & 0xf;
7373 addr = load_reg(s, rn);
7374 if (insn & (1 << 24))
7375 gen_add_datah_offset(s, insn, 0, addr);
7376 address_offset = 0;
7377 if (insn & (1 << 20)) {
7378 /* load */
7379 switch(sh) {
7380 case 1:
7381 tmp = gen_ld16u(addr, IS_USER(s));
7382 break;
7383 case 2:
7384 tmp = gen_ld8s(addr, IS_USER(s));
7385 break;
7386 default:
7387 case 3:
7388 tmp = gen_ld16s(addr, IS_USER(s));
7389 break;
7391 load = 1;
7392 } else if (sh & 2) {
7393 ARCH(5TE);
7394 /* doubleword */
7395 if (sh & 1) {
7396 /* store */
7397 tmp = load_reg(s, rd);
7398 gen_st32(tmp, addr, IS_USER(s));
7399 tcg_gen_addi_i32(addr, addr, 4);
7400 tmp = load_reg(s, rd + 1);
7401 gen_st32(tmp, addr, IS_USER(s));
7402 load = 0;
7403 } else {
7404 /* load */
7405 tmp = gen_ld32(addr, IS_USER(s));
7406 store_reg(s, rd, tmp);
7407 tcg_gen_addi_i32(addr, addr, 4);
7408 tmp = gen_ld32(addr, IS_USER(s));
7409 rd++;
7410 load = 1;
7412 address_offset = -4;
7413 } else {
7414 /* store */
7415 tmp = load_reg(s, rd);
7416 gen_st16(tmp, addr, IS_USER(s));
7417 load = 0;
7419 /* Perform base writeback before the loaded value to
7420 ensure correct behavior with overlapping index registers.
7421 ldrd with base writeback is is undefined if the
7422 destination and index registers overlap. */
7423 if (!(insn & (1 << 24))) {
7424 gen_add_datah_offset(s, insn, address_offset, addr);
7425 store_reg(s, rn, addr);
7426 } else if (insn & (1 << 21)) {
7427 if (address_offset)
7428 tcg_gen_addi_i32(addr, addr, address_offset);
7429 store_reg(s, rn, addr);
7430 } else {
7431 tcg_temp_free_i32(addr);
7433 if (load) {
7434 /* Complete the load. */
7435 store_reg(s, rd, tmp);
7438 break;
7439 case 0x4:
7440 case 0x5:
7441 goto do_ldst;
7442 case 0x6:
7443 case 0x7:
7444 if (insn & (1 << 4)) {
7445 ARCH(6);
7446 /* Armv6 Media instructions. */
7447 rm = insn & 0xf;
7448 rn = (insn >> 16) & 0xf;
7449 rd = (insn >> 12) & 0xf;
7450 rs = (insn >> 8) & 0xf;
7451 switch ((insn >> 23) & 3) {
7452 case 0: /* Parallel add/subtract. */
7453 op1 = (insn >> 20) & 7;
7454 tmp = load_reg(s, rn);
7455 tmp2 = load_reg(s, rm);
7456 sh = (insn >> 5) & 7;
7457 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
7458 goto illegal_op;
7459 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
7460 tcg_temp_free_i32(tmp2);
7461 store_reg(s, rd, tmp);
7462 break;
7463 case 1:
7464 if ((insn & 0x00700020) == 0) {
7465 /* Halfword pack. */
7466 tmp = load_reg(s, rn);
7467 tmp2 = load_reg(s, rm);
7468 shift = (insn >> 7) & 0x1f;
7469 if (insn & (1 << 6)) {
7470 /* pkhtb */
7471 if (shift == 0)
7472 shift = 31;
7473 tcg_gen_sari_i32(tmp2, tmp2, shift);
7474 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
7475 tcg_gen_ext16u_i32(tmp2, tmp2);
7476 } else {
7477 /* pkhbt */
7478 if (shift)
7479 tcg_gen_shli_i32(tmp2, tmp2, shift);
7480 tcg_gen_ext16u_i32(tmp, tmp);
7481 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
7483 tcg_gen_or_i32(tmp, tmp, tmp2);
7484 tcg_temp_free_i32(tmp2);
7485 store_reg(s, rd, tmp);
7486 } else if ((insn & 0x00200020) == 0x00200000) {
7487 /* [us]sat */
7488 tmp = load_reg(s, rm);
7489 shift = (insn >> 7) & 0x1f;
7490 if (insn & (1 << 6)) {
7491 if (shift == 0)
7492 shift = 31;
7493 tcg_gen_sari_i32(tmp, tmp, shift);
7494 } else {
7495 tcg_gen_shli_i32(tmp, tmp, shift);
7497 sh = (insn >> 16) & 0x1f;
7498 tmp2 = tcg_const_i32(sh);
7499 if (insn & (1 << 22))
7500 gen_helper_usat(tmp, tmp, tmp2);
7501 else
7502 gen_helper_ssat(tmp, tmp, tmp2);
7503 tcg_temp_free_i32(tmp2);
7504 store_reg(s, rd, tmp);
7505 } else if ((insn & 0x00300fe0) == 0x00200f20) {
7506 /* [us]sat16 */
7507 tmp = load_reg(s, rm);
7508 sh = (insn >> 16) & 0x1f;
7509 tmp2 = tcg_const_i32(sh);
7510 if (insn & (1 << 22))
7511 gen_helper_usat16(tmp, tmp, tmp2);
7512 else
7513 gen_helper_ssat16(tmp, tmp, tmp2);
7514 tcg_temp_free_i32(tmp2);
7515 store_reg(s, rd, tmp);
7516 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
7517 /* Select bytes. */
7518 tmp = load_reg(s, rn);
7519 tmp2 = load_reg(s, rm);
7520 tmp3 = tcg_temp_new_i32();
7521 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
7522 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7523 tcg_temp_free_i32(tmp3);
7524 tcg_temp_free_i32(tmp2);
7525 store_reg(s, rd, tmp);
7526 } else if ((insn & 0x000003e0) == 0x00000060) {
7527 tmp = load_reg(s, rm);
7528 shift = (insn >> 10) & 3;
7529 /* ??? In many cases it's not necessary to do a
7530 rotate, a shift is sufficient. */
7531 if (shift != 0)
7532 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
7533 op1 = (insn >> 20) & 7;
7534 switch (op1) {
7535 case 0: gen_sxtb16(tmp); break;
7536 case 2: gen_sxtb(tmp); break;
7537 case 3: gen_sxth(tmp); break;
7538 case 4: gen_uxtb16(tmp); break;
7539 case 6: gen_uxtb(tmp); break;
7540 case 7: gen_uxth(tmp); break;
7541 default: goto illegal_op;
7543 if (rn != 15) {
7544 tmp2 = load_reg(s, rn);
7545 if ((op1 & 3) == 0) {
7546 gen_add16(tmp, tmp2);
7547 } else {
7548 tcg_gen_add_i32(tmp, tmp, tmp2);
7549 tcg_temp_free_i32(tmp2);
7552 store_reg(s, rd, tmp);
7553 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
7554 /* rev */
7555 tmp = load_reg(s, rm);
7556 if (insn & (1 << 22)) {
7557 if (insn & (1 << 7)) {
7558 gen_revsh(tmp);
7559 } else {
7560 ARCH(6T2);
7561 gen_helper_rbit(tmp, tmp);
7563 } else {
7564 if (insn & (1 << 7))
7565 gen_rev16(tmp);
7566 else
7567 tcg_gen_bswap32_i32(tmp, tmp);
7569 store_reg(s, rd, tmp);
7570 } else {
7571 goto illegal_op;
7573 break;
7574 case 2: /* Multiplies (Type 3). */
7575 tmp = load_reg(s, rm);
7576 tmp2 = load_reg(s, rs);
7577 if (insn & (1 << 20)) {
7578 /* Signed multiply most significant [accumulate].
7579 (SMMUL, SMMLA, SMMLS) */
7580 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7582 if (rd != 15) {
7583 tmp = load_reg(s, rd);
7584 if (insn & (1 << 6)) {
7585 tmp64 = gen_subq_msw(tmp64, tmp);
7586 } else {
7587 tmp64 = gen_addq_msw(tmp64, tmp);
7590 if (insn & (1 << 5)) {
7591 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
7593 tcg_gen_shri_i64(tmp64, tmp64, 32);
7594 tmp = tcg_temp_new_i32();
7595 tcg_gen_trunc_i64_i32(tmp, tmp64);
7596 tcg_temp_free_i64(tmp64);
7597 store_reg(s, rn, tmp);
7598 } else {
7599 if (insn & (1 << 5))
7600 gen_swap_half(tmp2);
7601 gen_smul_dual(tmp, tmp2);
7602 if (insn & (1 << 6)) {
7603 /* This subtraction cannot overflow. */
7604 tcg_gen_sub_i32(tmp, tmp, tmp2);
7605 } else {
7606 /* This addition cannot overflow 32 bits;
7607 * however it may overflow considered as a signed
7608 * operation, in which case we must set the Q flag.
7610 gen_helper_add_setq(tmp, tmp, tmp2);
7612 tcg_temp_free_i32(tmp2);
7613 if (insn & (1 << 22)) {
7614 /* smlald, smlsld */
7615 tmp64 = tcg_temp_new_i64();
7616 tcg_gen_ext_i32_i64(tmp64, tmp);
7617 tcg_temp_free_i32(tmp);
7618 gen_addq(s, tmp64, rd, rn);
7619 gen_storeq_reg(s, rd, rn, tmp64);
7620 tcg_temp_free_i64(tmp64);
7621 } else {
7622 /* smuad, smusd, smlad, smlsd */
7623 if (rd != 15)
7625 tmp2 = load_reg(s, rd);
7626 gen_helper_add_setq(tmp, tmp, tmp2);
7627 tcg_temp_free_i32(tmp2);
7629 store_reg(s, rn, tmp);
7632 break;
7633 case 3:
7634 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
7635 switch (op1) {
7636 case 0: /* Unsigned sum of absolute differences. */
7637 ARCH(6);
7638 tmp = load_reg(s, rm);
7639 tmp2 = load_reg(s, rs);
7640 gen_helper_usad8(tmp, tmp, tmp2);
7641 tcg_temp_free_i32(tmp2);
7642 if (rd != 15) {
7643 tmp2 = load_reg(s, rd);
7644 tcg_gen_add_i32(tmp, tmp, tmp2);
7645 tcg_temp_free_i32(tmp2);
7647 store_reg(s, rn, tmp);
7648 break;
7649 case 0x20: case 0x24: case 0x28: case 0x2c:
7650 /* Bitfield insert/clear. */
7651 ARCH(6T2);
7652 shift = (insn >> 7) & 0x1f;
7653 i = (insn >> 16) & 0x1f;
7654 i = i + 1 - shift;
7655 if (rm == 15) {
7656 tmp = tcg_temp_new_i32();
7657 tcg_gen_movi_i32(tmp, 0);
7658 } else {
7659 tmp = load_reg(s, rm);
7661 if (i != 32) {
7662 tmp2 = load_reg(s, rd);
7663 gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
7664 tcg_temp_free_i32(tmp2);
7666 store_reg(s, rd, tmp);
7667 break;
7668 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
7669 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
7670 ARCH(6T2);
7671 tmp = load_reg(s, rm);
7672 shift = (insn >> 7) & 0x1f;
7673 i = ((insn >> 16) & 0x1f) + 1;
7674 if (shift + i > 32)
7675 goto illegal_op;
7676 if (i < 32) {
7677 if (op1 & 0x20) {
7678 gen_ubfx(tmp, shift, (1u << i) - 1);
7679 } else {
7680 gen_sbfx(tmp, shift, i);
7683 store_reg(s, rd, tmp);
7684 break;
7685 default:
7686 goto illegal_op;
7688 break;
7690 break;
7692 do_ldst:
7693 /* Check for undefined extension instructions
7694 * per the ARM Bible IE:
7695 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
7697 sh = (0xf << 20) | (0xf << 4);
7698 if (op1 == 0x7 && ((insn & sh) == sh))
7700 goto illegal_op;
7702 /* load/store byte/word */
7703 rn = (insn >> 16) & 0xf;
7704 rd = (insn >> 12) & 0xf;
7705 tmp2 = load_reg(s, rn);
7706 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
7707 if (insn & (1 << 24))
7708 gen_add_data_offset(s, insn, tmp2);
7709 if (insn & (1 << 20)) {
7710 /* load */
7711 if (insn & (1 << 22)) {
7712 tmp = gen_ld8u(tmp2, i);
7713 } else {
7714 tmp = gen_ld32(tmp2, i);
7716 } else {
7717 /* store */
7718 tmp = load_reg(s, rd);
7719 if (insn & (1 << 22))
7720 gen_st8(tmp, tmp2, i);
7721 else
7722 gen_st32(tmp, tmp2, i);
7724 if (!(insn & (1 << 24))) {
7725 gen_add_data_offset(s, insn, tmp2);
7726 store_reg(s, rn, tmp2);
7727 } else if (insn & (1 << 21)) {
7728 store_reg(s, rn, tmp2);
7729 } else {
7730 tcg_temp_free_i32(tmp2);
7732 if (insn & (1 << 20)) {
7733 /* Complete the load. */
7734 store_reg_from_load(env, s, rd, tmp);
7736 break;
7737 case 0x08:
7738 case 0x09:
7740 int j, n, user, loaded_base;
7741 TCGv loaded_var;
7742 /* load/store multiple words */
7743 /* XXX: store correct base if write back */
7744 user = 0;
7745 if (insn & (1 << 22)) {
7746 if (IS_USER(s))
7747 goto illegal_op; /* only usable in supervisor mode */
7749 if ((insn & (1 << 15)) == 0)
7750 user = 1;
7752 rn = (insn >> 16) & 0xf;
7753 addr = load_reg(s, rn);
7755 /* compute total size */
7756 loaded_base = 0;
7757 TCGV_UNUSED(loaded_var);
7758 n = 0;
7759 for(i=0;i<16;i++) {
7760 if (insn & (1 << i))
7761 n++;
7763 /* XXX: test invalid n == 0 case ? */
7764 if (insn & (1 << 23)) {
7765 if (insn & (1 << 24)) {
7766 /* pre increment */
7767 tcg_gen_addi_i32(addr, addr, 4);
7768 } else {
7769 /* post increment */
7771 } else {
7772 if (insn & (1 << 24)) {
7773 /* pre decrement */
7774 tcg_gen_addi_i32(addr, addr, -(n * 4));
7775 } else {
7776 /* post decrement */
7777 if (n != 1)
7778 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7781 j = 0;
7782 for(i=0;i<16;i++) {
7783 if (insn & (1 << i)) {
7784 if (insn & (1 << 20)) {
7785 /* load */
7786 tmp = gen_ld32(addr, IS_USER(s));
7787 if (user) {
7788 tmp2 = tcg_const_i32(i);
7789 gen_helper_set_user_reg(tmp2, tmp);
7790 tcg_temp_free_i32(tmp2);
7791 tcg_temp_free_i32(tmp);
7792 } else if (i == rn) {
7793 loaded_var = tmp;
7794 loaded_base = 1;
7795 } else {
7796 store_reg_from_load(env, s, i, tmp);
7798 } else {
7799 /* store */
7800 if (i == 15) {
7801 /* special case: r15 = PC + 8 */
7802 val = (long)s->pc + 4;
7803 tmp = tcg_temp_new_i32();
7804 tcg_gen_movi_i32(tmp, val);
7805 } else if (user) {
7806 tmp = tcg_temp_new_i32();
7807 tmp2 = tcg_const_i32(i);
7808 gen_helper_get_user_reg(tmp, tmp2);
7809 tcg_temp_free_i32(tmp2);
7810 } else {
7811 tmp = load_reg(s, i);
7813 gen_st32(tmp, addr, IS_USER(s));
7815 j++;
7816 /* no need to add after the last transfer */
7817 if (j != n)
7818 tcg_gen_addi_i32(addr, addr, 4);
7821 if (insn & (1 << 21)) {
7822 /* write back */
7823 if (insn & (1 << 23)) {
7824 if (insn & (1 << 24)) {
7825 /* pre increment */
7826 } else {
7827 /* post increment */
7828 tcg_gen_addi_i32(addr, addr, 4);
7830 } else {
7831 if (insn & (1 << 24)) {
7832 /* pre decrement */
7833 if (n != 1)
7834 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7835 } else {
7836 /* post decrement */
7837 tcg_gen_addi_i32(addr, addr, -(n * 4));
7840 store_reg(s, rn, addr);
7841 } else {
7842 tcg_temp_free_i32(addr);
7844 if (loaded_base) {
7845 store_reg(s, rn, loaded_var);
7847 if ((insn & (1 << 22)) && !user) {
7848 /* Restore CPSR from SPSR. */
7849 tmp = load_cpu_field(spsr);
7850 gen_set_cpsr(tmp, 0xffffffff);
7851 tcg_temp_free_i32(tmp);
7852 s->is_jmp = DISAS_UPDATE;
7855 break;
7856 case 0xa:
7857 case 0xb:
7859 int32_t offset;
7861 /* branch (and link) */
7862 val = (int32_t)s->pc;
7863 if (insn & (1 << 24)) {
7864 tmp = tcg_temp_new_i32();
7865 tcg_gen_movi_i32(tmp, val);
7866 store_reg(s, 14, tmp);
7868 offset = (((int32_t)insn << 8) >> 8);
7869 val += (offset << 2) + 4;
7870 gen_jmp(s, val);
7872 break;
7873 case 0xc:
7874 case 0xd:
7875 case 0xe:
7876 /* Coprocessor. */
7877 if (disas_coproc_insn(env, s, insn))
7878 goto illegal_op;
7879 break;
7880 case 0xf:
7881 /* swi */
7882 gen_set_pc_im(s->pc);
7883 s->is_jmp = DISAS_SWI;
7884 break;
7885 default:
7886 illegal_op:
7887 gen_exception_insn(s, 4, EXCP_UDEF);
7888 break;
7893 /* Return true if this is a Thumb-2 logical op. */
7894 static int
7895 thumb2_logic_op(int op)
7897 return (op < 8);
7900 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7901 then set condition code flags based on the result of the operation.
7902 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7903 to the high bit of T1.
7904 Returns zero if the opcode is valid. */
7906 static int
7907 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCGv t0, TCGv t1)
7909 int logic_cc;
7911 logic_cc = 0;
7912 switch (op) {
7913 case 0: /* and */
7914 tcg_gen_and_i32(t0, t0, t1);
7915 logic_cc = conds;
7916 break;
7917 case 1: /* bic */
7918 tcg_gen_andc_i32(t0, t0, t1);
7919 logic_cc = conds;
7920 break;
7921 case 2: /* orr */
7922 tcg_gen_or_i32(t0, t0, t1);
7923 logic_cc = conds;
7924 break;
7925 case 3: /* orn */
7926 tcg_gen_orc_i32(t0, t0, t1);
7927 logic_cc = conds;
7928 break;
7929 case 4: /* eor */
7930 tcg_gen_xor_i32(t0, t0, t1);
7931 logic_cc = conds;
7932 break;
7933 case 8: /* add */
7934 if (conds)
7935 gen_helper_add_cc(t0, t0, t1);
7936 else
7937 tcg_gen_add_i32(t0, t0, t1);
7938 break;
7939 case 10: /* adc */
7940 if (conds)
7941 gen_helper_adc_cc(t0, t0, t1);
7942 else
7943 gen_adc(t0, t1);
7944 break;
7945 case 11: /* sbc */
7946 if (conds)
7947 gen_helper_sbc_cc(t0, t0, t1);
7948 else
7949 gen_sub_carry(t0, t0, t1);
7950 break;
7951 case 13: /* sub */
7952 if (conds)
7953 gen_helper_sub_cc(t0, t0, t1);
7954 else
7955 tcg_gen_sub_i32(t0, t0, t1);
7956 break;
7957 case 14: /* rsb */
7958 if (conds)
7959 gen_helper_sub_cc(t0, t1, t0);
7960 else
7961 tcg_gen_sub_i32(t0, t1, t0);
7962 break;
7963 default: /* 5, 6, 7, 9, 12, 15. */
7964 return 1;
7966 if (logic_cc) {
7967 gen_logic_CC(t0);
7968 if (shifter_out)
7969 gen_set_CF_bit31(t1);
7971 return 0;
7974 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7975 is not legal. */
7976 static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7978 uint32_t insn, imm, shift, offset;
7979 uint32_t rd, rn, rm, rs;
7980 TCGv tmp;
7981 TCGv tmp2;
7982 TCGv tmp3;
7983 TCGv addr;
7984 TCGv_i64 tmp64;
7985 int op;
7986 int shiftop;
7987 int conds;
7988 int logic_cc;
7990 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
7991 || arm_feature (env, ARM_FEATURE_M))) {
7992 /* Thumb-1 cores may need to treat bl and blx as a pair of
7993 16-bit instructions to get correct prefetch abort behavior. */
7994 insn = insn_hw1;
7995 if ((insn & (1 << 12)) == 0) {
7996 ARCH(5);
7997 /* Second half of blx. */
7998 offset = ((insn & 0x7ff) << 1);
7999 tmp = load_reg(s, 14);
8000 tcg_gen_addi_i32(tmp, tmp, offset);
8001 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
8003 tmp2 = tcg_temp_new_i32();
8004 tcg_gen_movi_i32(tmp2, s->pc | 1);
8005 store_reg(s, 14, tmp2);
8006 gen_bx(s, tmp);
8007 return 0;
8009 if (insn & (1 << 11)) {
8010 /* Second half of bl. */
8011 offset = ((insn & 0x7ff) << 1) | 1;
8012 tmp = load_reg(s, 14);
8013 tcg_gen_addi_i32(tmp, tmp, offset);
8015 tmp2 = tcg_temp_new_i32();
8016 tcg_gen_movi_i32(tmp2, s->pc | 1);
8017 store_reg(s, 14, tmp2);
8018 gen_bx(s, tmp);
8019 return 0;
8021 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
8022 /* Instruction spans a page boundary. Implement it as two
8023 16-bit instructions in case the second half causes an
8024 prefetch abort. */
8025 offset = ((int32_t)insn << 21) >> 9;
8026 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
8027 return 0;
8029 /* Fall through to 32-bit decode. */
8032 insn = lduw_code(s->pc);
8033 s->pc += 2;
8034 insn |= (uint32_t)insn_hw1 << 16;
8036 if ((insn & 0xf800e800) != 0xf000e800) {
8037 ARCH(6T2);
8040 rn = (insn >> 16) & 0xf;
8041 rs = (insn >> 12) & 0xf;
8042 rd = (insn >> 8) & 0xf;
8043 rm = insn & 0xf;
8044 switch ((insn >> 25) & 0xf) {
8045 case 0: case 1: case 2: case 3:
8046 /* 16-bit instructions. Should never happen. */
8047 abort();
8048 case 4:
8049 if (insn & (1 << 22)) {
8050 /* Other load/store, table branch. */
8051 if (insn & 0x01200000) {
8052 /* Load/store doubleword. */
8053 if (rn == 15) {
8054 addr = tcg_temp_new_i32();
8055 tcg_gen_movi_i32(addr, s->pc & ~3);
8056 } else {
8057 addr = load_reg(s, rn);
8059 offset = (insn & 0xff) * 4;
8060 if ((insn & (1 << 23)) == 0)
8061 offset = -offset;
8062 if (insn & (1 << 24)) {
8063 tcg_gen_addi_i32(addr, addr, offset);
8064 offset = 0;
8066 if (insn & (1 << 20)) {
8067 /* ldrd */
8068 tmp = gen_ld32(addr, IS_USER(s));
8069 store_reg(s, rs, tmp);
8070 tcg_gen_addi_i32(addr, addr, 4);
8071 tmp = gen_ld32(addr, IS_USER(s));
8072 store_reg(s, rd, tmp);
8073 } else {
8074 /* strd */
8075 tmp = load_reg(s, rs);
8076 gen_st32(tmp, addr, IS_USER(s));
8077 tcg_gen_addi_i32(addr, addr, 4);
8078 tmp = load_reg(s, rd);
8079 gen_st32(tmp, addr, IS_USER(s));
8081 if (insn & (1 << 21)) {
8082 /* Base writeback. */
8083 if (rn == 15)
8084 goto illegal_op;
8085 tcg_gen_addi_i32(addr, addr, offset - 4);
8086 store_reg(s, rn, addr);
8087 } else {
8088 tcg_temp_free_i32(addr);
8090 } else if ((insn & (1 << 23)) == 0) {
8091 /* Load/store exclusive word. */
8092 addr = tcg_temp_local_new();
8093 load_reg_var(s, addr, rn);
8094 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
8095 if (insn & (1 << 20)) {
8096 gen_load_exclusive(s, rs, 15, addr, 2);
8097 } else {
8098 gen_store_exclusive(s, rd, rs, 15, addr, 2);
8100 tcg_temp_free(addr);
8101 } else if ((insn & (1 << 6)) == 0) {
8102 /* Table Branch. */
8103 if (rn == 15) {
8104 addr = tcg_temp_new_i32();
8105 tcg_gen_movi_i32(addr, s->pc);
8106 } else {
8107 addr = load_reg(s, rn);
8109 tmp = load_reg(s, rm);
8110 tcg_gen_add_i32(addr, addr, tmp);
8111 if (insn & (1 << 4)) {
8112 /* tbh */
8113 tcg_gen_add_i32(addr, addr, tmp);
8114 tcg_temp_free_i32(tmp);
8115 tmp = gen_ld16u(addr, IS_USER(s));
8116 } else { /* tbb */
8117 tcg_temp_free_i32(tmp);
8118 tmp = gen_ld8u(addr, IS_USER(s));
8120 tcg_temp_free_i32(addr);
8121 tcg_gen_shli_i32(tmp, tmp, 1);
8122 tcg_gen_addi_i32(tmp, tmp, s->pc);
8123 store_reg(s, 15, tmp);
8124 } else {
8125 /* Load/store exclusive byte/halfword/doubleword. */
8126 ARCH(7);
8127 op = (insn >> 4) & 0x3;
8128 if (op == 2) {
8129 goto illegal_op;
8131 addr = tcg_temp_local_new();
8132 load_reg_var(s, addr, rn);
8133 if (insn & (1 << 20)) {
8134 gen_load_exclusive(s, rs, rd, addr, op);
8135 } else {
8136 gen_store_exclusive(s, rm, rs, rd, addr, op);
8138 tcg_temp_free(addr);
8140 } else {
8141 /* Load/store multiple, RFE, SRS. */
8142 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
8143 /* Not available in user mode. */
8144 if (IS_USER(s))
8145 goto illegal_op;
8146 if (insn & (1 << 20)) {
8147 /* rfe */
8148 addr = load_reg(s, rn);
8149 if ((insn & (1 << 24)) == 0)
8150 tcg_gen_addi_i32(addr, addr, -8);
8151 /* Load PC into tmp and CPSR into tmp2. */
8152 tmp = gen_ld32(addr, 0);
8153 tcg_gen_addi_i32(addr, addr, 4);
8154 tmp2 = gen_ld32(addr, 0);
8155 if (insn & (1 << 21)) {
8156 /* Base writeback. */
8157 if (insn & (1 << 24)) {
8158 tcg_gen_addi_i32(addr, addr, 4);
8159 } else {
8160 tcg_gen_addi_i32(addr, addr, -4);
8162 store_reg(s, rn, addr);
8163 } else {
8164 tcg_temp_free_i32(addr);
8166 gen_rfe(s, tmp, tmp2);
8167 } else {
8168 /* srs */
8169 op = (insn & 0x1f);
8170 addr = tcg_temp_new_i32();
8171 tmp = tcg_const_i32(op);
8172 gen_helper_get_r13_banked(addr, cpu_env, tmp);
8173 tcg_temp_free_i32(tmp);
8174 if ((insn & (1 << 24)) == 0) {
8175 tcg_gen_addi_i32(addr, addr, -8);
8177 tmp = load_reg(s, 14);
8178 gen_st32(tmp, addr, 0);
8179 tcg_gen_addi_i32(addr, addr, 4);
8180 tmp = tcg_temp_new_i32();
8181 gen_helper_cpsr_read(tmp);
8182 gen_st32(tmp, addr, 0);
8183 if (insn & (1 << 21)) {
8184 if ((insn & (1 << 24)) == 0) {
8185 tcg_gen_addi_i32(addr, addr, -4);
8186 } else {
8187 tcg_gen_addi_i32(addr, addr, 4);
8189 tmp = tcg_const_i32(op);
8190 gen_helper_set_r13_banked(cpu_env, tmp, addr);
8191 tcg_temp_free_i32(tmp);
8192 } else {
8193 tcg_temp_free_i32(addr);
8196 } else {
8197 int i, loaded_base = 0;
8198 TCGv loaded_var;
8199 /* Load/store multiple. */
8200 addr = load_reg(s, rn);
8201 offset = 0;
8202 for (i = 0; i < 16; i++) {
8203 if (insn & (1 << i))
8204 offset += 4;
8206 if (insn & (1 << 24)) {
8207 tcg_gen_addi_i32(addr, addr, -offset);
8210 TCGV_UNUSED(loaded_var);
8211 for (i = 0; i < 16; i++) {
8212 if ((insn & (1 << i)) == 0)
8213 continue;
8214 if (insn & (1 << 20)) {
8215 /* Load. */
8216 tmp = gen_ld32(addr, IS_USER(s));
8217 if (i == 15) {
8218 gen_bx(s, tmp);
8219 } else if (i == rn) {
8220 loaded_var = tmp;
8221 loaded_base = 1;
8222 } else {
8223 store_reg(s, i, tmp);
8225 } else {
8226 /* Store. */
8227 tmp = load_reg(s, i);
8228 gen_st32(tmp, addr, IS_USER(s));
8230 tcg_gen_addi_i32(addr, addr, 4);
8232 if (loaded_base) {
8233 store_reg(s, rn, loaded_var);
8235 if (insn & (1 << 21)) {
8236 /* Base register writeback. */
8237 if (insn & (1 << 24)) {
8238 tcg_gen_addi_i32(addr, addr, -offset);
8240 /* Fault if writeback register is in register list. */
8241 if (insn & (1 << rn))
8242 goto illegal_op;
8243 store_reg(s, rn, addr);
8244 } else {
8245 tcg_temp_free_i32(addr);
8249 break;
8250 case 5:
8252 op = (insn >> 21) & 0xf;
8253 if (op == 6) {
8254 /* Halfword pack. */
8255 tmp = load_reg(s, rn);
8256 tmp2 = load_reg(s, rm);
8257 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
8258 if (insn & (1 << 5)) {
8259 /* pkhtb */
8260 if (shift == 0)
8261 shift = 31;
8262 tcg_gen_sari_i32(tmp2, tmp2, shift);
8263 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
8264 tcg_gen_ext16u_i32(tmp2, tmp2);
8265 } else {
8266 /* pkhbt */
8267 if (shift)
8268 tcg_gen_shli_i32(tmp2, tmp2, shift);
8269 tcg_gen_ext16u_i32(tmp, tmp);
8270 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
8272 tcg_gen_or_i32(tmp, tmp, tmp2);
8273 tcg_temp_free_i32(tmp2);
8274 store_reg(s, rd, tmp);
8275 } else {
8276 /* Data processing register constant shift. */
8277 if (rn == 15) {
8278 tmp = tcg_temp_new_i32();
8279 tcg_gen_movi_i32(tmp, 0);
8280 } else {
8281 tmp = load_reg(s, rn);
8283 tmp2 = load_reg(s, rm);
8285 shiftop = (insn >> 4) & 3;
8286 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
8287 conds = (insn & (1 << 20)) != 0;
8288 logic_cc = (conds && thumb2_logic_op(op));
8289 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
8290 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
8291 goto illegal_op;
8292 tcg_temp_free_i32(tmp2);
8293 if (rd != 15) {
8294 store_reg(s, rd, tmp);
8295 } else {
8296 tcg_temp_free_i32(tmp);
8299 break;
8300 case 13: /* Misc data processing. */
8301 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
8302 if (op < 4 && (insn & 0xf000) != 0xf000)
8303 goto illegal_op;
8304 switch (op) {
8305 case 0: /* Register controlled shift. */
8306 tmp = load_reg(s, rn);
8307 tmp2 = load_reg(s, rm);
8308 if ((insn & 0x70) != 0)
8309 goto illegal_op;
8310 op = (insn >> 21) & 3;
8311 logic_cc = (insn & (1 << 20)) != 0;
8312 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
8313 if (logic_cc)
8314 gen_logic_CC(tmp);
8315 store_reg_bx(env, s, rd, tmp);
8316 break;
8317 case 1: /* Sign/zero extend. */
8318 tmp = load_reg(s, rm);
8319 shift = (insn >> 4) & 3;
8320 /* ??? In many cases it's not necessary to do a
8321 rotate, a shift is sufficient. */
8322 if (shift != 0)
8323 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
8324 op = (insn >> 20) & 7;
8325 switch (op) {
8326 case 0: gen_sxth(tmp); break;
8327 case 1: gen_uxth(tmp); break;
8328 case 2: gen_sxtb16(tmp); break;
8329 case 3: gen_uxtb16(tmp); break;
8330 case 4: gen_sxtb(tmp); break;
8331 case 5: gen_uxtb(tmp); break;
8332 default: goto illegal_op;
8334 if (rn != 15) {
8335 tmp2 = load_reg(s, rn);
8336 if ((op >> 1) == 1) {
8337 gen_add16(tmp, tmp2);
8338 } else {
8339 tcg_gen_add_i32(tmp, tmp, tmp2);
8340 tcg_temp_free_i32(tmp2);
8343 store_reg(s, rd, tmp);
8344 break;
8345 case 2: /* SIMD add/subtract. */
8346 op = (insn >> 20) & 7;
8347 shift = (insn >> 4) & 7;
8348 if ((op & 3) == 3 || (shift & 3) == 3)
8349 goto illegal_op;
8350 tmp = load_reg(s, rn);
8351 tmp2 = load_reg(s, rm);
8352 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
8353 tcg_temp_free_i32(tmp2);
8354 store_reg(s, rd, tmp);
8355 break;
8356 case 3: /* Other data processing. */
8357 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
8358 if (op < 4) {
8359 /* Saturating add/subtract. */
8360 tmp = load_reg(s, rn);
8361 tmp2 = load_reg(s, rm);
8362 if (op & 1)
8363 gen_helper_double_saturate(tmp, tmp);
8364 if (op & 2)
8365 gen_helper_sub_saturate(tmp, tmp2, tmp);
8366 else
8367 gen_helper_add_saturate(tmp, tmp, tmp2);
8368 tcg_temp_free_i32(tmp2);
8369 } else {
8370 tmp = load_reg(s, rn);
8371 switch (op) {
8372 case 0x0a: /* rbit */
8373 gen_helper_rbit(tmp, tmp);
8374 break;
8375 case 0x08: /* rev */
8376 tcg_gen_bswap32_i32(tmp, tmp);
8377 break;
8378 case 0x09: /* rev16 */
8379 gen_rev16(tmp);
8380 break;
8381 case 0x0b: /* revsh */
8382 gen_revsh(tmp);
8383 break;
8384 case 0x10: /* sel */
8385 tmp2 = load_reg(s, rm);
8386 tmp3 = tcg_temp_new_i32();
8387 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
8388 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
8389 tcg_temp_free_i32(tmp3);
8390 tcg_temp_free_i32(tmp2);
8391 break;
8392 case 0x18: /* clz */
8393 gen_helper_clz(tmp, tmp);
8394 break;
8395 default:
8396 goto illegal_op;
8399 store_reg(s, rd, tmp);
8400 break;
8401 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
8402 op = (insn >> 4) & 0xf;
8403 tmp = load_reg(s, rn);
8404 tmp2 = load_reg(s, rm);
8405 switch ((insn >> 20) & 7) {
8406 case 0: /* 32 x 32 -> 32 */
8407 tcg_gen_mul_i32(tmp, tmp, tmp2);
8408 tcg_temp_free_i32(tmp2);
8409 if (rs != 15) {
8410 tmp2 = load_reg(s, rs);
8411 if (op)
8412 tcg_gen_sub_i32(tmp, tmp2, tmp);
8413 else
8414 tcg_gen_add_i32(tmp, tmp, tmp2);
8415 tcg_temp_free_i32(tmp2);
8417 break;
8418 case 1: /* 16 x 16 -> 32 */
8419 gen_mulxy(tmp, tmp2, op & 2, op & 1);
8420 tcg_temp_free_i32(tmp2);
8421 if (rs != 15) {
8422 tmp2 = load_reg(s, rs);
8423 gen_helper_add_setq(tmp, tmp, tmp2);
8424 tcg_temp_free_i32(tmp2);
8426 break;
8427 case 2: /* Dual multiply add. */
8428 case 4: /* Dual multiply subtract. */
8429 if (op)
8430 gen_swap_half(tmp2);
8431 gen_smul_dual(tmp, tmp2);
8432 if (insn & (1 << 22)) {
8433 /* This subtraction cannot overflow. */
8434 tcg_gen_sub_i32(tmp, tmp, tmp2);
8435 } else {
8436 /* This addition cannot overflow 32 bits;
8437 * however it may overflow considered as a signed
8438 * operation, in which case we must set the Q flag.
8440 gen_helper_add_setq(tmp, tmp, tmp2);
8442 tcg_temp_free_i32(tmp2);
8443 if (rs != 15)
8445 tmp2 = load_reg(s, rs);
8446 gen_helper_add_setq(tmp, tmp, tmp2);
8447 tcg_temp_free_i32(tmp2);
8449 break;
8450 case 3: /* 32 * 16 -> 32msb */
8451 if (op)
8452 tcg_gen_sari_i32(tmp2, tmp2, 16);
8453 else
8454 gen_sxth(tmp2);
8455 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8456 tcg_gen_shri_i64(tmp64, tmp64, 16);
8457 tmp = tcg_temp_new_i32();
8458 tcg_gen_trunc_i64_i32(tmp, tmp64);
8459 tcg_temp_free_i64(tmp64);
8460 if (rs != 15)
8462 tmp2 = load_reg(s, rs);
8463 gen_helper_add_setq(tmp, tmp, tmp2);
8464 tcg_temp_free_i32(tmp2);
8466 break;
8467 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
8468 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8469 if (rs != 15) {
8470 tmp = load_reg(s, rs);
8471 if (insn & (1 << 20)) {
8472 tmp64 = gen_addq_msw(tmp64, tmp);
8473 } else {
8474 tmp64 = gen_subq_msw(tmp64, tmp);
8477 if (insn & (1 << 4)) {
8478 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
8480 tcg_gen_shri_i64(tmp64, tmp64, 32);
8481 tmp = tcg_temp_new_i32();
8482 tcg_gen_trunc_i64_i32(tmp, tmp64);
8483 tcg_temp_free_i64(tmp64);
8484 break;
8485 case 7: /* Unsigned sum of absolute differences. */
8486 gen_helper_usad8(tmp, tmp, tmp2);
8487 tcg_temp_free_i32(tmp2);
8488 if (rs != 15) {
8489 tmp2 = load_reg(s, rs);
8490 tcg_gen_add_i32(tmp, tmp, tmp2);
8491 tcg_temp_free_i32(tmp2);
8493 break;
8495 store_reg(s, rd, tmp);
8496 break;
8497 case 6: case 7: /* 64-bit multiply, Divide. */
8498 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
8499 tmp = load_reg(s, rn);
8500 tmp2 = load_reg(s, rm);
8501 if ((op & 0x50) == 0x10) {
8502 /* sdiv, udiv */
8503 if (!arm_feature(env, ARM_FEATURE_DIV))
8504 goto illegal_op;
8505 if (op & 0x20)
8506 gen_helper_udiv(tmp, tmp, tmp2);
8507 else
8508 gen_helper_sdiv(tmp, tmp, tmp2);
8509 tcg_temp_free_i32(tmp2);
8510 store_reg(s, rd, tmp);
8511 } else if ((op & 0xe) == 0xc) {
8512 /* Dual multiply accumulate long. */
8513 if (op & 1)
8514 gen_swap_half(tmp2);
8515 gen_smul_dual(tmp, tmp2);
8516 if (op & 0x10) {
8517 tcg_gen_sub_i32(tmp, tmp, tmp2);
8518 } else {
8519 tcg_gen_add_i32(tmp, tmp, tmp2);
8521 tcg_temp_free_i32(tmp2);
8522 /* BUGFIX */
8523 tmp64 = tcg_temp_new_i64();
8524 tcg_gen_ext_i32_i64(tmp64, tmp);
8525 tcg_temp_free_i32(tmp);
8526 gen_addq(s, tmp64, rs, rd);
8527 gen_storeq_reg(s, rs, rd, tmp64);
8528 tcg_temp_free_i64(tmp64);
8529 } else {
8530 if (op & 0x20) {
8531 /* Unsigned 64-bit multiply */
8532 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
8533 } else {
8534 if (op & 8) {
8535 /* smlalxy */
8536 gen_mulxy(tmp, tmp2, op & 2, op & 1);
8537 tcg_temp_free_i32(tmp2);
8538 tmp64 = tcg_temp_new_i64();
8539 tcg_gen_ext_i32_i64(tmp64, tmp);
8540 tcg_temp_free_i32(tmp);
8541 } else {
8542 /* Signed 64-bit multiply */
8543 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8546 if (op & 4) {
8547 /* umaal */
8548 gen_addq_lo(s, tmp64, rs);
8549 gen_addq_lo(s, tmp64, rd);
8550 } else if (op & 0x40) {
8551 /* 64-bit accumulate. */
8552 gen_addq(s, tmp64, rs, rd);
8554 gen_storeq_reg(s, rs, rd, tmp64);
8555 tcg_temp_free_i64(tmp64);
8557 break;
8559 break;
8560 case 6: case 7: case 14: case 15:
8561 /* Coprocessor. */
8562 if (((insn >> 24) & 3) == 3) {
8563 /* Translate into the equivalent ARM encoding. */
8564 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
8565 if (disas_neon_data_insn(env, s, insn))
8566 goto illegal_op;
8567 } else {
8568 if (insn & (1 << 28))
8569 goto illegal_op;
8570 if (disas_coproc_insn (env, s, insn))
8571 goto illegal_op;
8573 break;
8574 case 8: case 9: case 10: case 11:
8575 if (insn & (1 << 15)) {
8576 /* Branches, misc control. */
8577 if (insn & 0x5000) {
8578 /* Unconditional branch. */
8579 /* signextend(hw1[10:0]) -> offset[:12]. */
8580 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
8581 /* hw1[10:0] -> offset[11:1]. */
8582 offset |= (insn & 0x7ff) << 1;
8583 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
8584 offset[24:22] already have the same value because of the
8585 sign extension above. */
8586 offset ^= ((~insn) & (1 << 13)) << 10;
8587 offset ^= ((~insn) & (1 << 11)) << 11;
8589 if (insn & (1 << 14)) {
8590 /* Branch and link. */
8591 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
8594 offset += s->pc;
8595 if (insn & (1 << 12)) {
8596 /* b/bl */
8597 gen_jmp(s, offset);
8598 } else {
8599 /* blx */
8600 offset &= ~(uint32_t)2;
8601 /* thumb2 bx, no need to check */
8602 gen_bx_im(s, offset);
8604 } else if (((insn >> 23) & 7) == 7) {
8605 /* Misc control */
8606 if (insn & (1 << 13))
8607 goto illegal_op;
8609 if (insn & (1 << 26)) {
8610 /* Secure monitor call (v6Z) */
8611 goto illegal_op; /* not implemented. */
8612 } else {
8613 op = (insn >> 20) & 7;
8614 switch (op) {
8615 case 0: /* msr cpsr. */
8616 if (IS_M(env)) {
8617 tmp = load_reg(s, rn);
8618 addr = tcg_const_i32(insn & 0xff);
8619 gen_helper_v7m_msr(cpu_env, addr, tmp);
8620 tcg_temp_free_i32(addr);
8621 tcg_temp_free_i32(tmp);
8622 gen_lookup_tb(s);
8623 break;
8625 /* fall through */
8626 case 1: /* msr spsr. */
8627 if (IS_M(env))
8628 goto illegal_op;
8629 tmp = load_reg(s, rn);
8630 if (gen_set_psr(s,
8631 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
8632 op == 1, tmp))
8633 goto illegal_op;
8634 break;
8635 case 2: /* cps, nop-hint. */
8636 if (((insn >> 8) & 7) == 0) {
8637 gen_nop_hint(s, insn & 0xff);
8639 /* Implemented as NOP in user mode. */
8640 if (IS_USER(s))
8641 break;
8642 offset = 0;
8643 imm = 0;
8644 if (insn & (1 << 10)) {
8645 if (insn & (1 << 7))
8646 offset |= CPSR_A;
8647 if (insn & (1 << 6))
8648 offset |= CPSR_I;
8649 if (insn & (1 << 5))
8650 offset |= CPSR_F;
8651 if (insn & (1 << 9))
8652 imm = CPSR_A | CPSR_I | CPSR_F;
8654 if (insn & (1 << 8)) {
8655 offset |= 0x1f;
8656 imm |= (insn & 0x1f);
8658 if (offset) {
8659 gen_set_psr_im(s, offset, 0, imm);
8661 break;
8662 case 3: /* Special control operations. */
8663 ARCH(7);
8664 op = (insn >> 4) & 0xf;
8665 switch (op) {
8666 case 2: /* clrex */
8667 gen_clrex(s);
8668 break;
8669 case 4: /* dsb */
8670 case 5: /* dmb */
8671 case 6: /* isb */
8672 /* These execute as NOPs. */
8673 break;
8674 default:
8675 goto illegal_op;
8677 break;
8678 case 4: /* bxj */
8679 /* Trivial implementation equivalent to bx. */
8680 tmp = load_reg(s, rn);
8681 gen_bx(s, tmp);
8682 break;
8683 case 5: /* Exception return. */
8684 if (IS_USER(s)) {
8685 goto illegal_op;
8687 if (rn != 14 || rd != 15) {
8688 goto illegal_op;
8690 tmp = load_reg(s, rn);
8691 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
8692 gen_exception_return(s, tmp);
8693 break;
8694 case 6: /* mrs cpsr. */
8695 tmp = tcg_temp_new_i32();
8696 if (IS_M(env)) {
8697 addr = tcg_const_i32(insn & 0xff);
8698 gen_helper_v7m_mrs(tmp, cpu_env, addr);
8699 tcg_temp_free_i32(addr);
8700 } else {
8701 gen_helper_cpsr_read(tmp);
8703 store_reg(s, rd, tmp);
8704 break;
8705 case 7: /* mrs spsr. */
8706 /* Not accessible in user mode. */
8707 if (IS_USER(s) || IS_M(env))
8708 goto illegal_op;
8709 tmp = load_cpu_field(spsr);
8710 store_reg(s, rd, tmp);
8711 break;
8714 } else {
8715 /* Conditional branch. */
8716 op = (insn >> 22) & 0xf;
8717 /* Generate a conditional jump to next instruction. */
8718 s->condlabel = gen_new_label();
8719 gen_test_cc(op ^ 1, s->condlabel);
8720 s->condjmp = 1;
8722 /* offset[11:1] = insn[10:0] */
8723 offset = (insn & 0x7ff) << 1;
8724 /* offset[17:12] = insn[21:16]. */
8725 offset |= (insn & 0x003f0000) >> 4;
8726 /* offset[31:20] = insn[26]. */
8727 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
8728 /* offset[18] = insn[13]. */
8729 offset |= (insn & (1 << 13)) << 5;
8730 /* offset[19] = insn[11]. */
8731 offset |= (insn & (1 << 11)) << 8;
8733 /* jump to the offset */
8734 gen_jmp(s, s->pc + offset);
8736 } else {
8737 /* Data processing immediate. */
8738 if (insn & (1 << 25)) {
8739 if (insn & (1 << 24)) {
8740 if (insn & (1 << 20))
8741 goto illegal_op;
8742 /* Bitfield/Saturate. */
8743 op = (insn >> 21) & 7;
8744 imm = insn & 0x1f;
8745 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
8746 if (rn == 15) {
8747 tmp = tcg_temp_new_i32();
8748 tcg_gen_movi_i32(tmp, 0);
8749 } else {
8750 tmp = load_reg(s, rn);
8752 switch (op) {
8753 case 2: /* Signed bitfield extract. */
8754 imm++;
8755 if (shift + imm > 32)
8756 goto illegal_op;
8757 if (imm < 32)
8758 gen_sbfx(tmp, shift, imm);
8759 break;
8760 case 6: /* Unsigned bitfield extract. */
8761 imm++;
8762 if (shift + imm > 32)
8763 goto illegal_op;
8764 if (imm < 32)
8765 gen_ubfx(tmp, shift, (1u << imm) - 1);
8766 break;
8767 case 3: /* Bitfield insert/clear. */
8768 if (imm < shift)
8769 goto illegal_op;
8770 imm = imm + 1 - shift;
8771 if (imm != 32) {
8772 tmp2 = load_reg(s, rd);
8773 gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
8774 tcg_temp_free_i32(tmp2);
8776 break;
8777 case 7:
8778 goto illegal_op;
8779 default: /* Saturate. */
8780 if (shift) {
8781 if (op & 1)
8782 tcg_gen_sari_i32(tmp, tmp, shift);
8783 else
8784 tcg_gen_shli_i32(tmp, tmp, shift);
8786 tmp2 = tcg_const_i32(imm);
8787 if (op & 4) {
8788 /* Unsigned. */
8789 if ((op & 1) && shift == 0)
8790 gen_helper_usat16(tmp, tmp, tmp2);
8791 else
8792 gen_helper_usat(tmp, tmp, tmp2);
8793 } else {
8794 /* Signed. */
8795 if ((op & 1) && shift == 0)
8796 gen_helper_ssat16(tmp, tmp, tmp2);
8797 else
8798 gen_helper_ssat(tmp, tmp, tmp2);
8800 tcg_temp_free_i32(tmp2);
8801 break;
8803 store_reg(s, rd, tmp);
8804 } else {
8805 imm = ((insn & 0x04000000) >> 15)
8806 | ((insn & 0x7000) >> 4) | (insn & 0xff);
8807 if (insn & (1 << 22)) {
8808 /* 16-bit immediate. */
8809 imm |= (insn >> 4) & 0xf000;
8810 if (insn & (1 << 23)) {
8811 /* movt */
8812 tmp = load_reg(s, rd);
8813 tcg_gen_ext16u_i32(tmp, tmp);
8814 tcg_gen_ori_i32(tmp, tmp, imm << 16);
8815 } else {
8816 /* movw */
8817 tmp = tcg_temp_new_i32();
8818 tcg_gen_movi_i32(tmp, imm);
8820 } else {
8821 /* Add/sub 12-bit immediate. */
8822 if (rn == 15) {
8823 offset = s->pc & ~(uint32_t)3;
8824 if (insn & (1 << 23))
8825 offset -= imm;
8826 else
8827 offset += imm;
8828 tmp = tcg_temp_new_i32();
8829 tcg_gen_movi_i32(tmp, offset);
8830 } else {
8831 tmp = load_reg(s, rn);
8832 if (insn & (1 << 23))
8833 tcg_gen_subi_i32(tmp, tmp, imm);
8834 else
8835 tcg_gen_addi_i32(tmp, tmp, imm);
8838 store_reg(s, rd, tmp);
8840 } else {
8841 int shifter_out = 0;
8842 /* modified 12-bit immediate. */
8843 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
8844 imm = (insn & 0xff);
8845 switch (shift) {
8846 case 0: /* XY */
8847 /* Nothing to do. */
8848 break;
8849 case 1: /* 00XY00XY */
8850 imm |= imm << 16;
8851 break;
8852 case 2: /* XY00XY00 */
8853 imm |= imm << 16;
8854 imm <<= 8;
8855 break;
8856 case 3: /* XYXYXYXY */
8857 imm |= imm << 16;
8858 imm |= imm << 8;
8859 break;
8860 default: /* Rotated constant. */
8861 shift = (shift << 1) | (imm >> 7);
8862 imm |= 0x80;
8863 imm = imm << (32 - shift);
8864 shifter_out = 1;
8865 break;
8867 tmp2 = tcg_temp_new_i32();
8868 tcg_gen_movi_i32(tmp2, imm);
8869 rn = (insn >> 16) & 0xf;
8870 if (rn == 15) {
8871 tmp = tcg_temp_new_i32();
8872 tcg_gen_movi_i32(tmp, 0);
8873 } else {
8874 tmp = load_reg(s, rn);
8876 op = (insn >> 21) & 0xf;
8877 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
8878 shifter_out, tmp, tmp2))
8879 goto illegal_op;
8880 tcg_temp_free_i32(tmp2);
8881 rd = (insn >> 8) & 0xf;
8882 if (rd != 15) {
8883 store_reg(s, rd, tmp);
8884 } else {
8885 tcg_temp_free_i32(tmp);
8889 break;
8890 case 12: /* Load/store single data item. */
8892 int postinc = 0;
8893 int writeback = 0;
8894 int user;
8895 if ((insn & 0x01100000) == 0x01000000) {
8896 if (disas_neon_ls_insn(env, s, insn))
8897 goto illegal_op;
8898 break;
8900 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
8901 if (rs == 15) {
8902 if (!(insn & (1 << 20))) {
8903 goto illegal_op;
8905 if (op != 2) {
8906 /* Byte or halfword load space with dest == r15 : memory hints.
8907 * Catch them early so we don't emit pointless addressing code.
8908 * This space is a mix of:
8909 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
8910 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
8911 * cores)
8912 * unallocated hints, which must be treated as NOPs
8913 * UNPREDICTABLE space, which we NOP or UNDEF depending on
8914 * which is easiest for the decoding logic
8915 * Some space which must UNDEF
8917 int op1 = (insn >> 23) & 3;
8918 int op2 = (insn >> 6) & 0x3f;
8919 if (op & 2) {
8920 goto illegal_op;
8922 if (rn == 15) {
8923 /* UNPREDICTABLE or unallocated hint */
8924 return 0;
8926 if (op1 & 1) {
8927 return 0; /* PLD* or unallocated hint */
8929 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
8930 return 0; /* PLD* or unallocated hint */
8932 /* UNDEF space, or an UNPREDICTABLE */
8933 return 1;
8936 user = IS_USER(s);
8937 if (rn == 15) {
8938 addr = tcg_temp_new_i32();
8939 /* PC relative. */
8940 /* s->pc has already been incremented by 4. */
8941 imm = s->pc & 0xfffffffc;
8942 if (insn & (1 << 23))
8943 imm += insn & 0xfff;
8944 else
8945 imm -= insn & 0xfff;
8946 tcg_gen_movi_i32(addr, imm);
8947 } else {
8948 addr = load_reg(s, rn);
8949 if (insn & (1 << 23)) {
8950 /* Positive offset. */
8951 imm = insn & 0xfff;
8952 tcg_gen_addi_i32(addr, addr, imm);
8953 } else {
8954 imm = insn & 0xff;
8955 switch ((insn >> 8) & 0xf) {
8956 case 0x0: /* Shifted Register. */
8957 shift = (insn >> 4) & 0xf;
8958 if (shift > 3) {
8959 tcg_temp_free_i32(addr);
8960 goto illegal_op;
8962 tmp = load_reg(s, rm);
8963 if (shift)
8964 tcg_gen_shli_i32(tmp, tmp, shift);
8965 tcg_gen_add_i32(addr, addr, tmp);
8966 tcg_temp_free_i32(tmp);
8967 break;
8968 case 0xc: /* Negative offset. */
8969 tcg_gen_addi_i32(addr, addr, -imm);
8970 break;
8971 case 0xe: /* User privilege. */
8972 tcg_gen_addi_i32(addr, addr, imm);
8973 user = 1;
8974 break;
8975 case 0x9: /* Post-decrement. */
8976 imm = -imm;
8977 /* Fall through. */
8978 case 0xb: /* Post-increment. */
8979 postinc = 1;
8980 writeback = 1;
8981 break;
8982 case 0xd: /* Pre-decrement. */
8983 imm = -imm;
8984 /* Fall through. */
8985 case 0xf: /* Pre-increment. */
8986 tcg_gen_addi_i32(addr, addr, imm);
8987 writeback = 1;
8988 break;
8989 default:
8990 tcg_temp_free_i32(addr);
8991 goto illegal_op;
8995 if (insn & (1 << 20)) {
8996 /* Load. */
8997 switch (op) {
8998 case 0: tmp = gen_ld8u(addr, user); break;
8999 case 4: tmp = gen_ld8s(addr, user); break;
9000 case 1: tmp = gen_ld16u(addr, user); break;
9001 case 5: tmp = gen_ld16s(addr, user); break;
9002 case 2: tmp = gen_ld32(addr, user); break;
9003 default:
9004 tcg_temp_free_i32(addr);
9005 goto illegal_op;
9007 if (rs == 15) {
9008 gen_bx(s, tmp);
9009 } else {
9010 store_reg(s, rs, tmp);
9012 } else {
9013 /* Store. */
9014 tmp = load_reg(s, rs);
9015 switch (op) {
9016 case 0: gen_st8(tmp, addr, user); break;
9017 case 1: gen_st16(tmp, addr, user); break;
9018 case 2: gen_st32(tmp, addr, user); break;
9019 default:
9020 tcg_temp_free_i32(addr);
9021 goto illegal_op;
9024 if (postinc)
9025 tcg_gen_addi_i32(addr, addr, imm);
9026 if (writeback) {
9027 store_reg(s, rn, addr);
9028 } else {
9029 tcg_temp_free_i32(addr);
9032 break;
9033 default:
9034 goto illegal_op;
9036 return 0;
9037 illegal_op:
9038 return 1;
9041 static void disas_thumb_insn(CPUState *env, DisasContext *s)
9043 uint32_t val, insn, op, rm, rn, rd, shift, cond;
9044 int32_t offset;
9045 int i;
9046 TCGv tmp;
9047 TCGv tmp2;
9048 TCGv addr;
9050 if (s->condexec_mask) {
9051 cond = s->condexec_cond;
9052 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
9053 s->condlabel = gen_new_label();
9054 gen_test_cc(cond ^ 1, s->condlabel);
9055 s->condjmp = 1;
9059 insn = lduw_code(s->pc);
9060 s->pc += 2;
9062 switch (insn >> 12) {
9063 case 0: case 1:
9065 rd = insn & 7;
9066 op = (insn >> 11) & 3;
9067 if (op == 3) {
9068 /* add/subtract */
9069 rn = (insn >> 3) & 7;
9070 tmp = load_reg(s, rn);
9071 if (insn & (1 << 10)) {
9072 /* immediate */
9073 tmp2 = tcg_temp_new_i32();
9074 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
9075 } else {
9076 /* reg */
9077 rm = (insn >> 6) & 7;
9078 tmp2 = load_reg(s, rm);
9080 if (insn & (1 << 9)) {
9081 if (s->condexec_mask)
9082 tcg_gen_sub_i32(tmp, tmp, tmp2);
9083 else
9084 gen_helper_sub_cc(tmp, tmp, tmp2);
9085 } else {
9086 if (s->condexec_mask)
9087 tcg_gen_add_i32(tmp, tmp, tmp2);
9088 else
9089 gen_helper_add_cc(tmp, tmp, tmp2);
9091 tcg_temp_free_i32(tmp2);
9092 store_reg(s, rd, tmp);
9093 } else {
9094 /* shift immediate */
9095 rm = (insn >> 3) & 7;
9096 shift = (insn >> 6) & 0x1f;
9097 tmp = load_reg(s, rm);
9098 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
9099 if (!s->condexec_mask)
9100 gen_logic_CC(tmp);
9101 store_reg(s, rd, tmp);
9103 break;
9104 case 2: case 3:
9105 /* arithmetic large immediate */
9106 op = (insn >> 11) & 3;
9107 rd = (insn >> 8) & 0x7;
9108 if (op == 0) { /* mov */
9109 tmp = tcg_temp_new_i32();
9110 tcg_gen_movi_i32(tmp, insn & 0xff);
9111 if (!s->condexec_mask)
9112 gen_logic_CC(tmp);
9113 store_reg(s, rd, tmp);
9114 } else {
9115 tmp = load_reg(s, rd);
9116 tmp2 = tcg_temp_new_i32();
9117 tcg_gen_movi_i32(tmp2, insn & 0xff);
9118 switch (op) {
9119 case 1: /* cmp */
9120 gen_helper_sub_cc(tmp, tmp, tmp2);
9121 tcg_temp_free_i32(tmp);
9122 tcg_temp_free_i32(tmp2);
9123 break;
9124 case 2: /* add */
9125 if (s->condexec_mask)
9126 tcg_gen_add_i32(tmp, tmp, tmp2);
9127 else
9128 gen_helper_add_cc(tmp, tmp, tmp2);
9129 tcg_temp_free_i32(tmp2);
9130 store_reg(s, rd, tmp);
9131 break;
9132 case 3: /* sub */
9133 if (s->condexec_mask)
9134 tcg_gen_sub_i32(tmp, tmp, tmp2);
9135 else
9136 gen_helper_sub_cc(tmp, tmp, tmp2);
9137 tcg_temp_free_i32(tmp2);
9138 store_reg(s, rd, tmp);
9139 break;
9142 break;
9143 case 4:
9144 if (insn & (1 << 11)) {
9145 rd = (insn >> 8) & 7;
9146 /* load pc-relative. Bit 1 of PC is ignored. */
9147 val = s->pc + 2 + ((insn & 0xff) * 4);
9148 val &= ~(uint32_t)2;
9149 addr = tcg_temp_new_i32();
9150 tcg_gen_movi_i32(addr, val);
9151 tmp = gen_ld32(addr, IS_USER(s));
9152 tcg_temp_free_i32(addr);
9153 store_reg(s, rd, tmp);
9154 break;
9156 if (insn & (1 << 10)) {
9157 /* data processing extended or blx */
9158 rd = (insn & 7) | ((insn >> 4) & 8);
9159 rm = (insn >> 3) & 0xf;
9160 op = (insn >> 8) & 3;
9161 switch (op) {
9162 case 0: /* add */
9163 tmp = load_reg(s, rd);
9164 tmp2 = load_reg(s, rm);
9165 tcg_gen_add_i32(tmp, tmp, tmp2);
9166 tcg_temp_free_i32(tmp2);
9167 store_reg(s, rd, tmp);
9168 break;
9169 case 1: /* cmp */
9170 tmp = load_reg(s, rd);
9171 tmp2 = load_reg(s, rm);
9172 gen_helper_sub_cc(tmp, tmp, tmp2);
9173 tcg_temp_free_i32(tmp2);
9174 tcg_temp_free_i32(tmp);
9175 break;
9176 case 2: /* mov/cpy */
9177 tmp = load_reg(s, rm);
9178 store_reg(s, rd, tmp);
9179 break;
9180 case 3:/* branch [and link] exchange thumb register */
9181 tmp = load_reg(s, rm);
9182 if (insn & (1 << 7)) {
9183 ARCH(5);
9184 val = (uint32_t)s->pc | 1;
9185 tmp2 = tcg_temp_new_i32();
9186 tcg_gen_movi_i32(tmp2, val);
9187 store_reg(s, 14, tmp2);
9189 /* already thumb, no need to check */
9190 gen_bx(s, tmp);
9191 break;
9193 break;
9196 /* data processing register */
9197 rd = insn & 7;
9198 rm = (insn >> 3) & 7;
9199 op = (insn >> 6) & 0xf;
9200 if (op == 2 || op == 3 || op == 4 || op == 7) {
9201 /* the shift/rotate ops want the operands backwards */
9202 val = rm;
9203 rm = rd;
9204 rd = val;
9205 val = 1;
9206 } else {
9207 val = 0;
9210 if (op == 9) { /* neg */
9211 tmp = tcg_temp_new_i32();
9212 tcg_gen_movi_i32(tmp, 0);
9213 } else if (op != 0xf) { /* mvn doesn't read its first operand */
9214 tmp = load_reg(s, rd);
9215 } else {
9216 TCGV_UNUSED(tmp);
9219 tmp2 = load_reg(s, rm);
9220 switch (op) {
9221 case 0x0: /* and */
9222 tcg_gen_and_i32(tmp, tmp, tmp2);
9223 if (!s->condexec_mask)
9224 gen_logic_CC(tmp);
9225 break;
9226 case 0x1: /* eor */
9227 tcg_gen_xor_i32(tmp, tmp, tmp2);
9228 if (!s->condexec_mask)
9229 gen_logic_CC(tmp);
9230 break;
9231 case 0x2: /* lsl */
9232 if (s->condexec_mask) {
9233 gen_helper_shl(tmp2, tmp2, tmp);
9234 } else {
9235 gen_helper_shl_cc(tmp2, tmp2, tmp);
9236 gen_logic_CC(tmp2);
9238 break;
9239 case 0x3: /* lsr */
9240 if (s->condexec_mask) {
9241 gen_helper_shr(tmp2, tmp2, tmp);
9242 } else {
9243 gen_helper_shr_cc(tmp2, tmp2, tmp);
9244 gen_logic_CC(tmp2);
9246 break;
9247 case 0x4: /* asr */
9248 if (s->condexec_mask) {
9249 gen_helper_sar(tmp2, tmp2, tmp);
9250 } else {
9251 gen_helper_sar_cc(tmp2, tmp2, tmp);
9252 gen_logic_CC(tmp2);
9254 break;
9255 case 0x5: /* adc */
9256 if (s->condexec_mask)
9257 gen_adc(tmp, tmp2);
9258 else
9259 gen_helper_adc_cc(tmp, tmp, tmp2);
9260 break;
9261 case 0x6: /* sbc */
9262 if (s->condexec_mask)
9263 gen_sub_carry(tmp, tmp, tmp2);
9264 else
9265 gen_helper_sbc_cc(tmp, tmp, tmp2);
9266 break;
9267 case 0x7: /* ror */
9268 if (s->condexec_mask) {
9269 tcg_gen_andi_i32(tmp, tmp, 0x1f);
9270 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
9271 } else {
9272 gen_helper_ror_cc(tmp2, tmp2, tmp);
9273 gen_logic_CC(tmp2);
9275 break;
9276 case 0x8: /* tst */
9277 tcg_gen_and_i32(tmp, tmp, tmp2);
9278 gen_logic_CC(tmp);
9279 rd = 16;
9280 break;
9281 case 0x9: /* neg */
9282 if (s->condexec_mask)
9283 tcg_gen_neg_i32(tmp, tmp2);
9284 else
9285 gen_helper_sub_cc(tmp, tmp, tmp2);
9286 break;
9287 case 0xa: /* cmp */
9288 gen_helper_sub_cc(tmp, tmp, tmp2);
9289 rd = 16;
9290 break;
9291 case 0xb: /* cmn */
9292 gen_helper_add_cc(tmp, tmp, tmp2);
9293 rd = 16;
9294 break;
9295 case 0xc: /* orr */
9296 tcg_gen_or_i32(tmp, tmp, tmp2);
9297 if (!s->condexec_mask)
9298 gen_logic_CC(tmp);
9299 break;
9300 case 0xd: /* mul */
9301 tcg_gen_mul_i32(tmp, tmp, tmp2);
9302 if (!s->condexec_mask)
9303 gen_logic_CC(tmp);
9304 break;
9305 case 0xe: /* bic */
9306 tcg_gen_andc_i32(tmp, tmp, tmp2);
9307 if (!s->condexec_mask)
9308 gen_logic_CC(tmp);
9309 break;
9310 case 0xf: /* mvn */
9311 tcg_gen_not_i32(tmp2, tmp2);
9312 if (!s->condexec_mask)
9313 gen_logic_CC(tmp2);
9314 val = 1;
9315 rm = rd;
9316 break;
9318 if (rd != 16) {
9319 if (val) {
9320 store_reg(s, rm, tmp2);
9321 if (op != 0xf)
9322 tcg_temp_free_i32(tmp);
9323 } else {
9324 store_reg(s, rd, tmp);
9325 tcg_temp_free_i32(tmp2);
9327 } else {
9328 tcg_temp_free_i32(tmp);
9329 tcg_temp_free_i32(tmp2);
9331 break;
9333 case 5:
9334 /* load/store register offset. */
9335 rd = insn & 7;
9336 rn = (insn >> 3) & 7;
9337 rm = (insn >> 6) & 7;
9338 op = (insn >> 9) & 7;
9339 addr = load_reg(s, rn);
9340 tmp = load_reg(s, rm);
9341 tcg_gen_add_i32(addr, addr, tmp);
9342 tcg_temp_free_i32(tmp);
9344 if (op < 3) /* store */
9345 tmp = load_reg(s, rd);
9347 switch (op) {
9348 case 0: /* str */
9349 gen_st32(tmp, addr, IS_USER(s));
9350 break;
9351 case 1: /* strh */
9352 gen_st16(tmp, addr, IS_USER(s));
9353 break;
9354 case 2: /* strb */
9355 gen_st8(tmp, addr, IS_USER(s));
9356 break;
9357 case 3: /* ldrsb */
9358 tmp = gen_ld8s(addr, IS_USER(s));
9359 break;
9360 case 4: /* ldr */
9361 tmp = gen_ld32(addr, IS_USER(s));
9362 break;
9363 case 5: /* ldrh */
9364 tmp = gen_ld16u(addr, IS_USER(s));
9365 break;
9366 case 6: /* ldrb */
9367 tmp = gen_ld8u(addr, IS_USER(s));
9368 break;
9369 case 7: /* ldrsh */
9370 tmp = gen_ld16s(addr, IS_USER(s));
9371 break;
9373 if (op >= 3) /* load */
9374 store_reg(s, rd, tmp);
9375 tcg_temp_free_i32(addr);
9376 break;
9378 case 6:
9379 /* load/store word immediate offset */
9380 rd = insn & 7;
9381 rn = (insn >> 3) & 7;
9382 addr = load_reg(s, rn);
9383 val = (insn >> 4) & 0x7c;
9384 tcg_gen_addi_i32(addr, addr, val);
9386 if (insn & (1 << 11)) {
9387 /* load */
9388 tmp = gen_ld32(addr, IS_USER(s));
9389 store_reg(s, rd, tmp);
9390 } else {
9391 /* store */
9392 tmp = load_reg(s, rd);
9393 gen_st32(tmp, addr, IS_USER(s));
9395 tcg_temp_free_i32(addr);
9396 break;
9398 case 7:
9399 /* load/store byte immediate offset */
9400 rd = insn & 7;
9401 rn = (insn >> 3) & 7;
9402 addr = load_reg(s, rn);
9403 val = (insn >> 6) & 0x1f;
9404 tcg_gen_addi_i32(addr, addr, val);
9406 if (insn & (1 << 11)) {
9407 /* load */
9408 tmp = gen_ld8u(addr, IS_USER(s));
9409 store_reg(s, rd, tmp);
9410 } else {
9411 /* store */
9412 tmp = load_reg(s, rd);
9413 gen_st8(tmp, addr, IS_USER(s));
9415 tcg_temp_free_i32(addr);
9416 break;
9418 case 8:
9419 /* load/store halfword immediate offset */
9420 rd = insn & 7;
9421 rn = (insn >> 3) & 7;
9422 addr = load_reg(s, rn);
9423 val = (insn >> 5) & 0x3e;
9424 tcg_gen_addi_i32(addr, addr, val);
9426 if (insn & (1 << 11)) {
9427 /* load */
9428 tmp = gen_ld16u(addr, IS_USER(s));
9429 store_reg(s, rd, tmp);
9430 } else {
9431 /* store */
9432 tmp = load_reg(s, rd);
9433 gen_st16(tmp, addr, IS_USER(s));
9435 tcg_temp_free_i32(addr);
9436 break;
9438 case 9:
9439 /* load/store from stack */
9440 rd = (insn >> 8) & 7;
9441 addr = load_reg(s, 13);
9442 val = (insn & 0xff) * 4;
9443 tcg_gen_addi_i32(addr, addr, val);
9445 if (insn & (1 << 11)) {
9446 /* load */
9447 tmp = gen_ld32(addr, IS_USER(s));
9448 store_reg(s, rd, tmp);
9449 } else {
9450 /* store */
9451 tmp = load_reg(s, rd);
9452 gen_st32(tmp, addr, IS_USER(s));
9454 tcg_temp_free_i32(addr);
9455 break;
9457 case 10:
9458 /* add to high reg */
9459 rd = (insn >> 8) & 7;
9460 if (insn & (1 << 11)) {
9461 /* SP */
9462 tmp = load_reg(s, 13);
9463 } else {
9464 /* PC. bit 1 is ignored. */
9465 tmp = tcg_temp_new_i32();
9466 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
9468 val = (insn & 0xff) * 4;
9469 tcg_gen_addi_i32(tmp, tmp, val);
9470 store_reg(s, rd, tmp);
9471 break;
9473 case 11:
9474 /* misc */
9475 op = (insn >> 8) & 0xf;
9476 switch (op) {
9477 case 0:
9478 /* adjust stack pointer */
9479 tmp = load_reg(s, 13);
9480 val = (insn & 0x7f) * 4;
9481 if (insn & (1 << 7))
9482 val = -(int32_t)val;
9483 tcg_gen_addi_i32(tmp, tmp, val);
9484 store_reg(s, 13, tmp);
9485 break;
9487 case 2: /* sign/zero extend. */
9488 ARCH(6);
9489 rd = insn & 7;
9490 rm = (insn >> 3) & 7;
9491 tmp = load_reg(s, rm);
9492 switch ((insn >> 6) & 3) {
9493 case 0: gen_sxth(tmp); break;
9494 case 1: gen_sxtb(tmp); break;
9495 case 2: gen_uxth(tmp); break;
9496 case 3: gen_uxtb(tmp); break;
9498 store_reg(s, rd, tmp);
9499 break;
9500 case 4: case 5: case 0xc: case 0xd:
9501 /* push/pop */
9502 addr = load_reg(s, 13);
9503 if (insn & (1 << 8))
9504 offset = 4;
9505 else
9506 offset = 0;
9507 for (i = 0; i < 8; i++) {
9508 if (insn & (1 << i))
9509 offset += 4;
9511 if ((insn & (1 << 11)) == 0) {
9512 tcg_gen_addi_i32(addr, addr, -offset);
9514 for (i = 0; i < 8; i++) {
9515 if (insn & (1 << i)) {
9516 if (insn & (1 << 11)) {
9517 /* pop */
9518 tmp = gen_ld32(addr, IS_USER(s));
9519 store_reg(s, i, tmp);
9520 } else {
9521 /* push */
9522 tmp = load_reg(s, i);
9523 gen_st32(tmp, addr, IS_USER(s));
9525 /* advance to the next address. */
9526 tcg_gen_addi_i32(addr, addr, 4);
9529 TCGV_UNUSED(tmp);
9530 if (insn & (1 << 8)) {
9531 if (insn & (1 << 11)) {
9532 /* pop pc */
9533 tmp = gen_ld32(addr, IS_USER(s));
9534 /* don't set the pc until the rest of the instruction
9535 has completed */
9536 } else {
9537 /* push lr */
9538 tmp = load_reg(s, 14);
9539 gen_st32(tmp, addr, IS_USER(s));
9541 tcg_gen_addi_i32(addr, addr, 4);
9543 if ((insn & (1 << 11)) == 0) {
9544 tcg_gen_addi_i32(addr, addr, -offset);
9546 /* write back the new stack pointer */
9547 store_reg(s, 13, addr);
9548 /* set the new PC value */
9549 if ((insn & 0x0900) == 0x0900) {
9550 store_reg_from_load(env, s, 15, tmp);
9552 break;
9554 case 1: case 3: case 9: case 11: /* czb */
9555 rm = insn & 7;
9556 tmp = load_reg(s, rm);
9557 s->condlabel = gen_new_label();
9558 s->condjmp = 1;
9559 if (insn & (1 << 11))
9560 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
9561 else
9562 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
9563 tcg_temp_free_i32(tmp);
9564 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
9565 val = (uint32_t)s->pc + 2;
9566 val += offset;
9567 gen_jmp(s, val);
9568 break;
9570 case 15: /* IT, nop-hint. */
9571 if ((insn & 0xf) == 0) {
9572 gen_nop_hint(s, (insn >> 4) & 0xf);
9573 break;
9575 /* If Then. */
9576 s->condexec_cond = (insn >> 4) & 0xe;
9577 s->condexec_mask = insn & 0x1f;
9578 /* No actual code generated for this insn, just setup state. */
9579 break;
9581 case 0xe: /* bkpt */
9582 ARCH(5);
9583 gen_exception_insn(s, 2, EXCP_BKPT);
9584 break;
9586 case 0xa: /* rev */
9587 ARCH(6);
9588 rn = (insn >> 3) & 0x7;
9589 rd = insn & 0x7;
9590 tmp = load_reg(s, rn);
9591 switch ((insn >> 6) & 3) {
9592 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
9593 case 1: gen_rev16(tmp); break;
9594 case 3: gen_revsh(tmp); break;
9595 default: goto illegal_op;
9597 store_reg(s, rd, tmp);
9598 break;
9600 case 6: /* cps */
9601 ARCH(6);
9602 if (IS_USER(s))
9603 break;
9604 if (IS_M(env)) {
9605 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
9606 /* PRIMASK */
9607 if (insn & 1) {
9608 addr = tcg_const_i32(16);
9609 gen_helper_v7m_msr(cpu_env, addr, tmp);
9610 tcg_temp_free_i32(addr);
9612 /* FAULTMASK */
9613 if (insn & 2) {
9614 addr = tcg_const_i32(17);
9615 gen_helper_v7m_msr(cpu_env, addr, tmp);
9616 tcg_temp_free_i32(addr);
9618 tcg_temp_free_i32(tmp);
9619 gen_lookup_tb(s);
9620 } else {
9621 if (insn & (1 << 4))
9622 shift = CPSR_A | CPSR_I | CPSR_F;
9623 else
9624 shift = 0;
9625 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
9627 break;
9629 default:
9630 goto undef;
9632 break;
9634 case 12:
9636 /* load/store multiple */
9637 TCGv loaded_var;
9638 TCGV_UNUSED(loaded_var);
9639 rn = (insn >> 8) & 0x7;
9640 addr = load_reg(s, rn);
9641 for (i = 0; i < 8; i++) {
9642 if (insn & (1 << i)) {
9643 if (insn & (1 << 11)) {
9644 /* load */
9645 tmp = gen_ld32(addr, IS_USER(s));
9646 if (i == rn) {
9647 loaded_var = tmp;
9648 } else {
9649 store_reg(s, i, tmp);
9651 } else {
9652 /* store */
9653 tmp = load_reg(s, i);
9654 gen_st32(tmp, addr, IS_USER(s));
9656 /* advance to the next address */
9657 tcg_gen_addi_i32(addr, addr, 4);
9660 if ((insn & (1 << rn)) == 0) {
9661 /* base reg not in list: base register writeback */
9662 store_reg(s, rn, addr);
9663 } else {
9664 /* base reg in list: if load, complete it now */
9665 if (insn & (1 << 11)) {
9666 store_reg(s, rn, loaded_var);
9668 tcg_temp_free_i32(addr);
9670 break;
9672 case 13:
9673 /* conditional branch or swi */
9674 cond = (insn >> 8) & 0xf;
9675 if (cond == 0xe)
9676 goto undef;
9678 if (cond == 0xf) {
9679 /* swi */
9680 gen_set_pc_im(s->pc);
9681 s->is_jmp = DISAS_SWI;
9682 break;
9684 /* generate a conditional jump to next instruction */
9685 s->condlabel = gen_new_label();
9686 gen_test_cc(cond ^ 1, s->condlabel);
9687 s->condjmp = 1;
9689 /* jump to the offset */
9690 val = (uint32_t)s->pc + 2;
9691 offset = ((int32_t)insn << 24) >> 24;
9692 val += offset << 1;
9693 gen_jmp(s, val);
9694 break;
9696 case 14:
9697 if (insn & (1 << 11)) {
9698 if (disas_thumb2_insn(env, s, insn))
9699 goto undef32;
9700 break;
9702 /* unconditional branch */
9703 val = (uint32_t)s->pc;
9704 offset = ((int32_t)insn << 21) >> 21;
9705 val += (offset << 1) + 2;
9706 gen_jmp(s, val);
9707 break;
9709 case 15:
9710 if (disas_thumb2_insn(env, s, insn))
9711 goto undef32;
9712 break;
9714 return;
9715 undef32:
9716 gen_exception_insn(s, 4, EXCP_UDEF);
9717 return;
9718 illegal_op:
9719 undef:
9720 gen_exception_insn(s, 2, EXCP_UDEF);
9723 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
9724 basic block 'tb'. If search_pc is TRUE, also generate PC
9725 information for each intermediate instruction. */
9726 static inline void gen_intermediate_code_internal(CPUState *env,
9727 TranslationBlock *tb,
9728 int search_pc)
9730 DisasContext dc1, *dc = &dc1;
9731 CPUBreakpoint *bp;
9732 uint16_t *gen_opc_end;
9733 int j, lj;
9734 target_ulong pc_start;
9735 uint32_t next_page_start;
9736 int num_insns;
9737 int max_insns;
9739 /* generate intermediate code */
9740 pc_start = tb->pc;
9742 dc->tb = tb;
9744 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
9746 dc->is_jmp = DISAS_NEXT;
9747 dc->pc = pc_start;
9748 dc->singlestep_enabled = env->singlestep_enabled;
9749 dc->condjmp = 0;
9750 dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
9751 dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
9752 dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
9753 #if !defined(CONFIG_USER_ONLY)
9754 dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
9755 #endif
9756 dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
9757 dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
9758 dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
9759 cpu_F0s = tcg_temp_new_i32();
9760 cpu_F1s = tcg_temp_new_i32();
9761 cpu_F0d = tcg_temp_new_i64();
9762 cpu_F1d = tcg_temp_new_i64();
9763 cpu_V0 = cpu_F0d;
9764 cpu_V1 = cpu_F1d;
9765 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
9766 cpu_M0 = tcg_temp_new_i64();
9767 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
9768 lj = -1;
9769 num_insns = 0;
9770 max_insns = tb->cflags & CF_COUNT_MASK;
9771 if (max_insns == 0)
9772 max_insns = CF_COUNT_MASK;
9774 gen_icount_start();
9776 tcg_clear_temp_count();
9778 /* A note on handling of the condexec (IT) bits:
9780 * We want to avoid the overhead of having to write the updated condexec
9781 * bits back to the CPUState for every instruction in an IT block. So:
9782 * (1) if the condexec bits are not already zero then we write
9783 * zero back into the CPUState now. This avoids complications trying
9784 * to do it at the end of the block. (For example if we don't do this
9785 * it's hard to identify whether we can safely skip writing condexec
9786 * at the end of the TB, which we definitely want to do for the case
9787 * where a TB doesn't do anything with the IT state at all.)
9788 * (2) if we are going to leave the TB then we call gen_set_condexec()
9789 * which will write the correct value into CPUState if zero is wrong.
9790 * This is done both for leaving the TB at the end, and for leaving
9791 * it because of an exception we know will happen, which is done in
9792 * gen_exception_insn(). The latter is necessary because we need to
9793 * leave the TB with the PC/IT state just prior to execution of the
9794 * instruction which caused the exception.
9795 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
9796 * then the CPUState will be wrong and we need to reset it.
9797 * This is handled in the same way as restoration of the
9798 * PC in these situations: we will be called again with search_pc=1
9799 * and generate a mapping of the condexec bits for each PC in
9800 * gen_opc_condexec_bits[]. restore_state_to_opc() then uses
9801 * this to restore the condexec bits.
9803 * Note that there are no instructions which can read the condexec
9804 * bits, and none which can write non-static values to them, so
9805 * we don't need to care about whether CPUState is correct in the
9806 * middle of a TB.
9809 /* Reset the conditional execution bits immediately. This avoids
9810 complications trying to do it at the end of the block. */
9811 if (dc->condexec_mask || dc->condexec_cond)
9813 TCGv tmp = tcg_temp_new_i32();
9814 tcg_gen_movi_i32(tmp, 0);
9815 store_cpu_field(tmp, condexec_bits);
9817 do {
9818 #ifdef CONFIG_USER_ONLY
9819 /* Intercept jump to the magic kernel page. */
9820 if (dc->pc >= 0xffff0000) {
9821 /* We always get here via a jump, so know we are not in a
9822 conditional execution block. */
9823 gen_exception(EXCP_KERNEL_TRAP);
9824 dc->is_jmp = DISAS_UPDATE;
9825 break;
9827 #else
9828 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
9829 /* We always get here via a jump, so know we are not in a
9830 conditional execution block. */
9831 gen_exception(EXCP_EXCEPTION_EXIT);
9832 dc->is_jmp = DISAS_UPDATE;
9833 break;
9835 #endif
9837 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
9838 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
9839 if (bp->pc == dc->pc) {
9840 gen_exception_insn(dc, 0, EXCP_DEBUG);
9841 /* Advance PC so that clearing the breakpoint will
9842 invalidate this TB. */
9843 dc->pc += 2;
9844 goto done_generating;
9845 break;
9849 if (search_pc) {
9850 j = gen_opc_ptr - gen_opc_buf;
9851 if (lj < j) {
9852 lj++;
9853 while (lj < j)
9854 gen_opc_instr_start[lj++] = 0;
9856 gen_opc_pc[lj] = dc->pc;
9857 gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
9858 gen_opc_instr_start[lj] = 1;
9859 gen_opc_icount[lj] = num_insns;
9862 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
9863 gen_io_start();
9865 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
9866 tcg_gen_debug_insn_start(dc->pc);
9869 if (dc->thumb) {
9870 disas_thumb_insn(env, dc);
9871 if (dc->condexec_mask) {
9872 dc->condexec_cond = (dc->condexec_cond & 0xe)
9873 | ((dc->condexec_mask >> 4) & 1);
9874 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
9875 if (dc->condexec_mask == 0) {
9876 dc->condexec_cond = 0;
9879 } else {
9880 disas_arm_insn(env, dc);
9883 if (dc->condjmp && !dc->is_jmp) {
9884 gen_set_label(dc->condlabel);
9885 dc->condjmp = 0;
9888 if (tcg_check_temp_count()) {
9889 fprintf(stderr, "TCG temporary leak before %08x\n", dc->pc);
9892 /* Translation stops when a conditional branch is encountered.
9893 * Otherwise the subsequent code could get translated several times.
9894 * Also stop translation when a page boundary is reached. This
9895 * ensures prefetch aborts occur at the right place. */
9896 num_insns ++;
9897 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
9898 !env->singlestep_enabled &&
9899 !singlestep &&
9900 dc->pc < next_page_start &&
9901 num_insns < max_insns);
9903 if (tb->cflags & CF_LAST_IO) {
9904 if (dc->condjmp) {
9905 /* FIXME: This can theoretically happen with self-modifying
9906 code. */
9907 cpu_abort(env, "IO on conditional branch instruction");
9909 gen_io_end();
9912 /* At this stage dc->condjmp will only be set when the skipped
9913 instruction was a conditional branch or trap, and the PC has
9914 already been written. */
9915 if (unlikely(env->singlestep_enabled)) {
9916 /* Make sure the pc is updated, and raise a debug exception. */
9917 if (dc->condjmp) {
9918 gen_set_condexec(dc);
9919 if (dc->is_jmp == DISAS_SWI) {
9920 gen_exception(EXCP_SWI);
9921 } else {
9922 gen_exception(EXCP_DEBUG);
9924 gen_set_label(dc->condlabel);
9926 if (dc->condjmp || !dc->is_jmp) {
9927 gen_set_pc_im(dc->pc);
9928 dc->condjmp = 0;
9930 gen_set_condexec(dc);
9931 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
9932 gen_exception(EXCP_SWI);
9933 } else {
9934 /* FIXME: Single stepping a WFI insn will not halt
9935 the CPU. */
9936 gen_exception(EXCP_DEBUG);
9938 } else {
9939 /* While branches must always occur at the end of an IT block,
9940 there are a few other things that can cause us to terminate
9941 the TB in the middel of an IT block:
9942 - Exception generating instructions (bkpt, swi, undefined).
9943 - Page boundaries.
9944 - Hardware watchpoints.
9945 Hardware breakpoints have already been handled and skip this code.
9947 gen_set_condexec(dc);
9948 switch(dc->is_jmp) {
9949 case DISAS_NEXT:
9950 gen_goto_tb(dc, 1, dc->pc);
9951 break;
9952 default:
9953 case DISAS_JUMP:
9954 case DISAS_UPDATE:
9955 /* indicate that the hash table must be used to find the next TB */
9956 tcg_gen_exit_tb(0);
9957 break;
9958 case DISAS_TB_JUMP:
9959 /* nothing more to generate */
9960 break;
9961 case DISAS_WFI:
9962 gen_helper_wfi();
9963 break;
9964 case DISAS_SWI:
9965 gen_exception(EXCP_SWI);
9966 break;
9968 if (dc->condjmp) {
9969 gen_set_label(dc->condlabel);
9970 gen_set_condexec(dc);
9971 gen_goto_tb(dc, 1, dc->pc);
9972 dc->condjmp = 0;
9976 done_generating:
9977 gen_icount_end(tb, num_insns);
9978 *gen_opc_ptr = INDEX_op_end;
9980 #ifdef DEBUG_DISAS
9981 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9982 qemu_log("----------------\n");
9983 qemu_log("IN: %s\n", lookup_symbol(pc_start));
9984 log_target_disas(pc_start, dc->pc - pc_start, dc->thumb);
9985 qemu_log("\n");
9987 #endif
9988 if (search_pc) {
9989 j = gen_opc_ptr - gen_opc_buf;
9990 lj++;
9991 while (lj <= j)
9992 gen_opc_instr_start[lj++] = 0;
9993 } else {
9994 tb->size = dc->pc - pc_start;
9995 tb->icount = num_insns;
9999 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
10001 gen_intermediate_code_internal(env, tb, 0);
10004 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
10006 gen_intermediate_code_internal(env, tb, 1);
10009 static const char *cpu_mode_names[16] = {
10010 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
10011 "???", "???", "???", "und", "???", "???", "???", "sys"
10014 void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
10015 int flags)
10017 int i;
10018 #if 0
10019 union {
10020 uint32_t i;
10021 float s;
10022 } s0, s1;
10023 CPU_DoubleU d;
10024 /* ??? This assumes float64 and double have the same layout.
10025 Oh well, it's only debug dumps. */
10026 union {
10027 float64 f64;
10028 double d;
10029 } d0;
10030 #endif
10031 uint32_t psr;
10033 for(i=0;i<16;i++) {
10034 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
10035 if ((i % 4) == 3)
10036 cpu_fprintf(f, "\n");
10037 else
10038 cpu_fprintf(f, " ");
10040 psr = cpsr_read(env);
10041 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
10042 psr,
10043 psr & (1 << 31) ? 'N' : '-',
10044 psr & (1 << 30) ? 'Z' : '-',
10045 psr & (1 << 29) ? 'C' : '-',
10046 psr & (1 << 28) ? 'V' : '-',
10047 psr & CPSR_T ? 'T' : 'A',
10048 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
10050 #if 0
10051 for (i = 0; i < 16; i++) {
10052 d.d = env->vfp.regs[i];
10053 s0.i = d.l.lower;
10054 s1.i = d.l.upper;
10055 d0.f64 = d.d;
10056 cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
10057 i * 2, (int)s0.i, s0.s,
10058 i * 2 + 1, (int)s1.i, s1.s,
10059 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
10060 d0.d);
10062 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
10063 #endif
10066 void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
10068 env->regs[15] = gen_opc_pc[pc_pos];
10069 env->condexec_bits = gen_opc_condexec_bits[pc_pos];