target-arm: Support v6 barriers in linux-user mode
[qemu.git] / target-arm / translate.c
blobc7961b809711100588bb23cbeea1cae48a138bae
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 (s->thumb && rn == 15) {
3401 addr = tcg_temp_new_i32();
3402 tcg_gen_movi_i32(addr, s->pc & ~2);
3403 } else {
3404 addr = load_reg(s, rn);
3406 if ((insn & 0x01200000) == 0x01000000) {
3407 /* Single load/store */
3408 offset = (insn & 0xff) << 2;
3409 if ((insn & (1 << 23)) == 0)
3410 offset = -offset;
3411 tcg_gen_addi_i32(addr, addr, offset);
3412 if (insn & (1 << 20)) {
3413 gen_vfp_ld(s, dp, addr);
3414 gen_mov_vreg_F0(dp, rd);
3415 } else {
3416 gen_mov_F0_vreg(dp, rd);
3417 gen_vfp_st(s, dp, addr);
3419 tcg_temp_free_i32(addr);
3420 } else {
3421 /* load/store multiple */
3422 if (dp)
3423 n = (insn >> 1) & 0x7f;
3424 else
3425 n = insn & 0xff;
3427 if (insn & (1 << 24)) /* pre-decrement */
3428 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
3430 if (dp)
3431 offset = 8;
3432 else
3433 offset = 4;
3434 for (i = 0; i < n; i++) {
3435 if (insn & ARM_CP_RW_BIT) {
3436 /* load */
3437 gen_vfp_ld(s, dp, addr);
3438 gen_mov_vreg_F0(dp, rd + i);
3439 } else {
3440 /* store */
3441 gen_mov_F0_vreg(dp, rd + i);
3442 gen_vfp_st(s, dp, addr);
3444 tcg_gen_addi_i32(addr, addr, offset);
3446 if (insn & (1 << 21)) {
3447 /* writeback */
3448 if (insn & (1 << 24))
3449 offset = -offset * n;
3450 else if (dp && (insn & 1))
3451 offset = 4;
3452 else
3453 offset = 0;
3455 if (offset != 0)
3456 tcg_gen_addi_i32(addr, addr, offset);
3457 store_reg(s, rn, addr);
3458 } else {
3459 tcg_temp_free_i32(addr);
3463 break;
3464 default:
3465 /* Should never happen. */
3466 return 1;
3468 return 0;
3471 static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3473 TranslationBlock *tb;
3475 tb = s->tb;
3476 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3477 tcg_gen_goto_tb(n);
3478 gen_set_pc_im(dest);
3479 tcg_gen_exit_tb((tcg_target_long)tb + n);
3480 } else {
3481 gen_set_pc_im(dest);
3482 tcg_gen_exit_tb(0);
3486 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3488 if (unlikely(s->singlestep_enabled)) {
3489 /* An indirect jump so that we still trigger the debug exception. */
3490 if (s->thumb)
3491 dest |= 1;
3492 gen_bx_im(s, dest);
3493 } else {
3494 gen_goto_tb(s, 0, dest);
3495 s->is_jmp = DISAS_TB_JUMP;
3499 static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3501 if (x)
3502 tcg_gen_sari_i32(t0, t0, 16);
3503 else
3504 gen_sxth(t0);
3505 if (y)
3506 tcg_gen_sari_i32(t1, t1, 16);
3507 else
3508 gen_sxth(t1);
3509 tcg_gen_mul_i32(t0, t0, t1);
3512 /* Return the mask of PSR bits set by a MSR instruction. */
3513 static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3514 uint32_t mask;
3516 mask = 0;
3517 if (flags & (1 << 0))
3518 mask |= 0xff;
3519 if (flags & (1 << 1))
3520 mask |= 0xff00;
3521 if (flags & (1 << 2))
3522 mask |= 0xff0000;
3523 if (flags & (1 << 3))
3524 mask |= 0xff000000;
3526 /* Mask out undefined bits. */
3527 mask &= ~CPSR_RESERVED;
3528 if (!arm_feature(env, ARM_FEATURE_V4T))
3529 mask &= ~CPSR_T;
3530 if (!arm_feature(env, ARM_FEATURE_V5))
3531 mask &= ~CPSR_Q; /* V5TE in reality*/
3532 if (!arm_feature(env, ARM_FEATURE_V6))
3533 mask &= ~(CPSR_E | CPSR_GE);
3534 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3535 mask &= ~CPSR_IT;
3536 /* Mask out execution state bits. */
3537 if (!spsr)
3538 mask &= ~CPSR_EXEC;
3539 /* Mask out privileged bits. */
3540 if (IS_USER(s))
3541 mask &= CPSR_USER;
3542 return mask;
3545 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3546 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0)
3548 TCGv tmp;
3549 if (spsr) {
3550 /* ??? This is also undefined in system mode. */
3551 if (IS_USER(s))
3552 return 1;
3554 tmp = load_cpu_field(spsr);
3555 tcg_gen_andi_i32(tmp, tmp, ~mask);
3556 tcg_gen_andi_i32(t0, t0, mask);
3557 tcg_gen_or_i32(tmp, tmp, t0);
3558 store_cpu_field(tmp, spsr);
3559 } else {
3560 gen_set_cpsr(t0, mask);
3562 tcg_temp_free_i32(t0);
3563 gen_lookup_tb(s);
3564 return 0;
3567 /* Returns nonzero if access to the PSR is not permitted. */
3568 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3570 TCGv tmp;
3571 tmp = tcg_temp_new_i32();
3572 tcg_gen_movi_i32(tmp, val);
3573 return gen_set_psr(s, mask, spsr, tmp);
3576 /* Generate an old-style exception return. Marks pc as dead. */
3577 static void gen_exception_return(DisasContext *s, TCGv pc)
3579 TCGv tmp;
3580 store_reg(s, 15, pc);
3581 tmp = load_cpu_field(spsr);
3582 gen_set_cpsr(tmp, 0xffffffff);
3583 tcg_temp_free_i32(tmp);
3584 s->is_jmp = DISAS_UPDATE;
3587 /* Generate a v6 exception return. Marks both values as dead. */
3588 static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3590 gen_set_cpsr(cpsr, 0xffffffff);
3591 tcg_temp_free_i32(cpsr);
3592 store_reg(s, 15, pc);
3593 s->is_jmp = DISAS_UPDATE;
3596 static inline void
3597 gen_set_condexec (DisasContext *s)
3599 if (s->condexec_mask) {
3600 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3601 TCGv tmp = tcg_temp_new_i32();
3602 tcg_gen_movi_i32(tmp, val);
3603 store_cpu_field(tmp, condexec_bits);
3607 static void gen_exception_insn(DisasContext *s, int offset, int excp)
3609 gen_set_condexec(s);
3610 gen_set_pc_im(s->pc - offset);
3611 gen_exception(excp);
3612 s->is_jmp = DISAS_JUMP;
3615 static void gen_nop_hint(DisasContext *s, int val)
3617 switch (val) {
3618 case 3: /* wfi */
3619 gen_set_pc_im(s->pc);
3620 s->is_jmp = DISAS_WFI;
3621 break;
3622 case 2: /* wfe */
3623 case 4: /* sev */
3624 /* TODO: Implement SEV and WFE. May help SMP performance. */
3625 default: /* nop */
3626 break;
3630 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3632 static inline void gen_neon_add(int size, TCGv t0, TCGv t1)
3634 switch (size) {
3635 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
3636 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
3637 case 2: tcg_gen_add_i32(t0, t0, t1); break;
3638 default: abort();
3642 static inline void gen_neon_rsb(int size, TCGv t0, TCGv t1)
3644 switch (size) {
3645 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
3646 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
3647 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
3648 default: return;
3652 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3653 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3654 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3655 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3656 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3658 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3659 switch ((size << 1) | u) { \
3660 case 0: \
3661 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3662 break; \
3663 case 1: \
3664 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3665 break; \
3666 case 2: \
3667 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3668 break; \
3669 case 3: \
3670 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3671 break; \
3672 case 4: \
3673 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3674 break; \
3675 case 5: \
3676 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3677 break; \
3678 default: return 1; \
3679 }} while (0)
3681 #define GEN_NEON_INTEGER_OP(name) do { \
3682 switch ((size << 1) | u) { \
3683 case 0: \
3684 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3685 break; \
3686 case 1: \
3687 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3688 break; \
3689 case 2: \
3690 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3691 break; \
3692 case 3: \
3693 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3694 break; \
3695 case 4: \
3696 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3697 break; \
3698 case 5: \
3699 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3700 break; \
3701 default: return 1; \
3702 }} while (0)
3704 static TCGv neon_load_scratch(int scratch)
3706 TCGv tmp = tcg_temp_new_i32();
3707 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3708 return tmp;
3711 static void neon_store_scratch(int scratch, TCGv var)
3713 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3714 tcg_temp_free_i32(var);
3717 static inline TCGv neon_get_scalar(int size, int reg)
3719 TCGv tmp;
3720 if (size == 1) {
3721 tmp = neon_load_reg(reg & 7, reg >> 4);
3722 if (reg & 8) {
3723 gen_neon_dup_high16(tmp);
3724 } else {
3725 gen_neon_dup_low16(tmp);
3727 } else {
3728 tmp = neon_load_reg(reg & 15, reg >> 4);
3730 return tmp;
3733 static int gen_neon_unzip(int rd, int rm, int size, int q)
3735 TCGv tmp, tmp2;
3736 if (!q && size == 2) {
3737 return 1;
3739 tmp = tcg_const_i32(rd);
3740 tmp2 = tcg_const_i32(rm);
3741 if (q) {
3742 switch (size) {
3743 case 0:
3744 gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
3745 break;
3746 case 1:
3747 gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
3748 break;
3749 case 2:
3750 gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
3751 break;
3752 default:
3753 abort();
3755 } else {
3756 switch (size) {
3757 case 0:
3758 gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
3759 break;
3760 case 1:
3761 gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
3762 break;
3763 default:
3764 abort();
3767 tcg_temp_free_i32(tmp);
3768 tcg_temp_free_i32(tmp2);
3769 return 0;
3772 static int gen_neon_zip(int rd, int rm, int size, int q)
3774 TCGv tmp, tmp2;
3775 if (!q && size == 2) {
3776 return 1;
3778 tmp = tcg_const_i32(rd);
3779 tmp2 = tcg_const_i32(rm);
3780 if (q) {
3781 switch (size) {
3782 case 0:
3783 gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
3784 break;
3785 case 1:
3786 gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
3787 break;
3788 case 2:
3789 gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
3790 break;
3791 default:
3792 abort();
3794 } else {
3795 switch (size) {
3796 case 0:
3797 gen_helper_neon_zip8(cpu_env, tmp, tmp2);
3798 break;
3799 case 1:
3800 gen_helper_neon_zip16(cpu_env, tmp, tmp2);
3801 break;
3802 default:
3803 abort();
3806 tcg_temp_free_i32(tmp);
3807 tcg_temp_free_i32(tmp2);
3808 return 0;
3811 static void gen_neon_trn_u8(TCGv t0, TCGv t1)
3813 TCGv rd, tmp;
3815 rd = tcg_temp_new_i32();
3816 tmp = tcg_temp_new_i32();
3818 tcg_gen_shli_i32(rd, t0, 8);
3819 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3820 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3821 tcg_gen_or_i32(rd, rd, tmp);
3823 tcg_gen_shri_i32(t1, t1, 8);
3824 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3825 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3826 tcg_gen_or_i32(t1, t1, tmp);
3827 tcg_gen_mov_i32(t0, rd);
3829 tcg_temp_free_i32(tmp);
3830 tcg_temp_free_i32(rd);
3833 static void gen_neon_trn_u16(TCGv t0, TCGv t1)
3835 TCGv rd, tmp;
3837 rd = tcg_temp_new_i32();
3838 tmp = tcg_temp_new_i32();
3840 tcg_gen_shli_i32(rd, t0, 16);
3841 tcg_gen_andi_i32(tmp, t1, 0xffff);
3842 tcg_gen_or_i32(rd, rd, tmp);
3843 tcg_gen_shri_i32(t1, t1, 16);
3844 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3845 tcg_gen_or_i32(t1, t1, tmp);
3846 tcg_gen_mov_i32(t0, rd);
3848 tcg_temp_free_i32(tmp);
3849 tcg_temp_free_i32(rd);
3853 static struct {
3854 int nregs;
3855 int interleave;
3856 int spacing;
3857 } neon_ls_element_type[11] = {
3858 {4, 4, 1},
3859 {4, 4, 2},
3860 {4, 1, 1},
3861 {4, 2, 1},
3862 {3, 3, 1},
3863 {3, 3, 2},
3864 {3, 1, 1},
3865 {1, 1, 1},
3866 {2, 2, 1},
3867 {2, 2, 2},
3868 {2, 1, 1}
3871 /* Translate a NEON load/store element instruction. Return nonzero if the
3872 instruction is invalid. */
3873 static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3875 int rd, rn, rm;
3876 int op;
3877 int nregs;
3878 int interleave;
3879 int spacing;
3880 int stride;
3881 int size;
3882 int reg;
3883 int pass;
3884 int load;
3885 int shift;
3886 int n;
3887 TCGv addr;
3888 TCGv tmp;
3889 TCGv tmp2;
3890 TCGv_i64 tmp64;
3892 if (!s->vfp_enabled)
3893 return 1;
3894 VFP_DREG_D(rd, insn);
3895 rn = (insn >> 16) & 0xf;
3896 rm = insn & 0xf;
3897 load = (insn & (1 << 21)) != 0;
3898 if ((insn & (1 << 23)) == 0) {
3899 /* Load store all elements. */
3900 op = (insn >> 8) & 0xf;
3901 size = (insn >> 6) & 3;
3902 if (op > 10)
3903 return 1;
3904 /* Catch UNDEF cases for bad values of align field */
3905 switch (op & 0xc) {
3906 case 4:
3907 if (((insn >> 5) & 1) == 1) {
3908 return 1;
3910 break;
3911 case 8:
3912 if (((insn >> 4) & 3) == 3) {
3913 return 1;
3915 break;
3916 default:
3917 break;
3919 nregs = neon_ls_element_type[op].nregs;
3920 interleave = neon_ls_element_type[op].interleave;
3921 spacing = neon_ls_element_type[op].spacing;
3922 if (size == 3 && (interleave | spacing) != 1)
3923 return 1;
3924 addr = tcg_temp_new_i32();
3925 load_reg_var(s, addr, rn);
3926 stride = (1 << size) * interleave;
3927 for (reg = 0; reg < nregs; reg++) {
3928 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3929 load_reg_var(s, addr, rn);
3930 tcg_gen_addi_i32(addr, addr, (1 << size) * reg);
3931 } else if (interleave == 2 && nregs == 4 && reg == 2) {
3932 load_reg_var(s, addr, rn);
3933 tcg_gen_addi_i32(addr, addr, 1 << size);
3935 if (size == 3) {
3936 if (load) {
3937 tmp64 = gen_ld64(addr, IS_USER(s));
3938 neon_store_reg64(tmp64, rd);
3939 tcg_temp_free_i64(tmp64);
3940 } else {
3941 tmp64 = tcg_temp_new_i64();
3942 neon_load_reg64(tmp64, rd);
3943 gen_st64(tmp64, addr, IS_USER(s));
3945 tcg_gen_addi_i32(addr, addr, stride);
3946 } else {
3947 for (pass = 0; pass < 2; pass++) {
3948 if (size == 2) {
3949 if (load) {
3950 tmp = gen_ld32(addr, IS_USER(s));
3951 neon_store_reg(rd, pass, tmp);
3952 } else {
3953 tmp = neon_load_reg(rd, pass);
3954 gen_st32(tmp, addr, IS_USER(s));
3956 tcg_gen_addi_i32(addr, addr, stride);
3957 } else if (size == 1) {
3958 if (load) {
3959 tmp = gen_ld16u(addr, IS_USER(s));
3960 tcg_gen_addi_i32(addr, addr, stride);
3961 tmp2 = gen_ld16u(addr, IS_USER(s));
3962 tcg_gen_addi_i32(addr, addr, stride);
3963 tcg_gen_shli_i32(tmp2, tmp2, 16);
3964 tcg_gen_or_i32(tmp, tmp, tmp2);
3965 tcg_temp_free_i32(tmp2);
3966 neon_store_reg(rd, pass, tmp);
3967 } else {
3968 tmp = neon_load_reg(rd, pass);
3969 tmp2 = tcg_temp_new_i32();
3970 tcg_gen_shri_i32(tmp2, tmp, 16);
3971 gen_st16(tmp, addr, IS_USER(s));
3972 tcg_gen_addi_i32(addr, addr, stride);
3973 gen_st16(tmp2, addr, IS_USER(s));
3974 tcg_gen_addi_i32(addr, addr, stride);
3976 } else /* size == 0 */ {
3977 if (load) {
3978 TCGV_UNUSED(tmp2);
3979 for (n = 0; n < 4; n++) {
3980 tmp = gen_ld8u(addr, IS_USER(s));
3981 tcg_gen_addi_i32(addr, addr, stride);
3982 if (n == 0) {
3983 tmp2 = tmp;
3984 } else {
3985 tcg_gen_shli_i32(tmp, tmp, n * 8);
3986 tcg_gen_or_i32(tmp2, tmp2, tmp);
3987 tcg_temp_free_i32(tmp);
3990 neon_store_reg(rd, pass, tmp2);
3991 } else {
3992 tmp2 = neon_load_reg(rd, pass);
3993 for (n = 0; n < 4; n++) {
3994 tmp = tcg_temp_new_i32();
3995 if (n == 0) {
3996 tcg_gen_mov_i32(tmp, tmp2);
3997 } else {
3998 tcg_gen_shri_i32(tmp, tmp2, n * 8);
4000 gen_st8(tmp, addr, IS_USER(s));
4001 tcg_gen_addi_i32(addr, addr, stride);
4003 tcg_temp_free_i32(tmp2);
4008 rd += spacing;
4010 tcg_temp_free_i32(addr);
4011 stride = nregs * 8;
4012 } else {
4013 size = (insn >> 10) & 3;
4014 if (size == 3) {
4015 /* Load single element to all lanes. */
4016 int a = (insn >> 4) & 1;
4017 if (!load) {
4018 return 1;
4020 size = (insn >> 6) & 3;
4021 nregs = ((insn >> 8) & 3) + 1;
4023 if (size == 3) {
4024 if (nregs != 4 || a == 0) {
4025 return 1;
4027 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
4028 size = 2;
4030 if (nregs == 1 && a == 1 && size == 0) {
4031 return 1;
4033 if (nregs == 3 && a == 1) {
4034 return 1;
4036 addr = tcg_temp_new_i32();
4037 load_reg_var(s, addr, rn);
4038 if (nregs == 1) {
4039 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */
4040 tmp = gen_load_and_replicate(s, addr, size);
4041 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4042 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4043 if (insn & (1 << 5)) {
4044 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 0));
4045 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 1));
4047 tcg_temp_free_i32(tmp);
4048 } else {
4049 /* VLD2/3/4 to all lanes: bit 5 indicates register stride */
4050 stride = (insn & (1 << 5)) ? 2 : 1;
4051 for (reg = 0; reg < nregs; reg++) {
4052 tmp = gen_load_and_replicate(s, addr, size);
4053 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4054 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4055 tcg_temp_free_i32(tmp);
4056 tcg_gen_addi_i32(addr, addr, 1 << size);
4057 rd += stride;
4060 tcg_temp_free_i32(addr);
4061 stride = (1 << size) * nregs;
4062 } else {
4063 /* Single element. */
4064 int idx = (insn >> 4) & 0xf;
4065 pass = (insn >> 7) & 1;
4066 switch (size) {
4067 case 0:
4068 shift = ((insn >> 5) & 3) * 8;
4069 stride = 1;
4070 break;
4071 case 1:
4072 shift = ((insn >> 6) & 1) * 16;
4073 stride = (insn & (1 << 5)) ? 2 : 1;
4074 break;
4075 case 2:
4076 shift = 0;
4077 stride = (insn & (1 << 6)) ? 2 : 1;
4078 break;
4079 default:
4080 abort();
4082 nregs = ((insn >> 8) & 3) + 1;
4083 /* Catch the UNDEF cases. This is unavoidably a bit messy. */
4084 switch (nregs) {
4085 case 1:
4086 if (((idx & (1 << size)) != 0) ||
4087 (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
4088 return 1;
4090 break;
4091 case 3:
4092 if ((idx & 1) != 0) {
4093 return 1;
4095 /* fall through */
4096 case 2:
4097 if (size == 2 && (idx & 2) != 0) {
4098 return 1;
4100 break;
4101 case 4:
4102 if ((size == 2) && ((idx & 3) == 3)) {
4103 return 1;
4105 break;
4106 default:
4107 abort();
4109 if ((rd + stride * (nregs - 1)) > 31) {
4110 /* Attempts to write off the end of the register file
4111 * are UNPREDICTABLE; we choose to UNDEF because otherwise
4112 * the neon_load_reg() would write off the end of the array.
4114 return 1;
4116 addr = tcg_temp_new_i32();
4117 load_reg_var(s, addr, rn);
4118 for (reg = 0; reg < nregs; reg++) {
4119 if (load) {
4120 switch (size) {
4121 case 0:
4122 tmp = gen_ld8u(addr, IS_USER(s));
4123 break;
4124 case 1:
4125 tmp = gen_ld16u(addr, IS_USER(s));
4126 break;
4127 case 2:
4128 tmp = gen_ld32(addr, IS_USER(s));
4129 break;
4130 default: /* Avoid compiler warnings. */
4131 abort();
4133 if (size != 2) {
4134 tmp2 = neon_load_reg(rd, pass);
4135 gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
4136 tcg_temp_free_i32(tmp2);
4138 neon_store_reg(rd, pass, tmp);
4139 } else { /* Store */
4140 tmp = neon_load_reg(rd, pass);
4141 if (shift)
4142 tcg_gen_shri_i32(tmp, tmp, shift);
4143 switch (size) {
4144 case 0:
4145 gen_st8(tmp, addr, IS_USER(s));
4146 break;
4147 case 1:
4148 gen_st16(tmp, addr, IS_USER(s));
4149 break;
4150 case 2:
4151 gen_st32(tmp, addr, IS_USER(s));
4152 break;
4155 rd += stride;
4156 tcg_gen_addi_i32(addr, addr, 1 << size);
4158 tcg_temp_free_i32(addr);
4159 stride = nregs * (1 << size);
4162 if (rm != 15) {
4163 TCGv base;
4165 base = load_reg(s, rn);
4166 if (rm == 13) {
4167 tcg_gen_addi_i32(base, base, stride);
4168 } else {
4169 TCGv index;
4170 index = load_reg(s, rm);
4171 tcg_gen_add_i32(base, base, index);
4172 tcg_temp_free_i32(index);
4174 store_reg(s, rn, base);
4176 return 0;
4179 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4180 static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
4182 tcg_gen_and_i32(t, t, c);
4183 tcg_gen_andc_i32(f, f, c);
4184 tcg_gen_or_i32(dest, t, f);
4187 static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
4189 switch (size) {
4190 case 0: gen_helper_neon_narrow_u8(dest, src); break;
4191 case 1: gen_helper_neon_narrow_u16(dest, src); break;
4192 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
4193 default: abort();
4197 static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
4199 switch (size) {
4200 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
4201 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
4202 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
4203 default: abort();
4207 static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
4209 switch (size) {
4210 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
4211 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
4212 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
4213 default: abort();
4217 static inline void gen_neon_unarrow_sats(int size, TCGv dest, TCGv_i64 src)
4219 switch (size) {
4220 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
4221 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
4222 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
4223 default: abort();
4227 static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
4228 int q, int u)
4230 if (q) {
4231 if (u) {
4232 switch (size) {
4233 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4234 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4235 default: abort();
4237 } else {
4238 switch (size) {
4239 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
4240 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
4241 default: abort();
4244 } else {
4245 if (u) {
4246 switch (size) {
4247 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
4248 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
4249 default: abort();
4251 } else {
4252 switch (size) {
4253 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
4254 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
4255 default: abort();
4261 static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
4263 if (u) {
4264 switch (size) {
4265 case 0: gen_helper_neon_widen_u8(dest, src); break;
4266 case 1: gen_helper_neon_widen_u16(dest, src); break;
4267 case 2: tcg_gen_extu_i32_i64(dest, src); break;
4268 default: abort();
4270 } else {
4271 switch (size) {
4272 case 0: gen_helper_neon_widen_s8(dest, src); break;
4273 case 1: gen_helper_neon_widen_s16(dest, src); break;
4274 case 2: tcg_gen_ext_i32_i64(dest, src); break;
4275 default: abort();
4278 tcg_temp_free_i32(src);
4281 static inline void gen_neon_addl(int size)
4283 switch (size) {
4284 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4285 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4286 case 2: tcg_gen_add_i64(CPU_V001); break;
4287 default: abort();
4291 static inline void gen_neon_subl(int size)
4293 switch (size) {
4294 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4295 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4296 case 2: tcg_gen_sub_i64(CPU_V001); break;
4297 default: abort();
4301 static inline void gen_neon_negl(TCGv_i64 var, int size)
4303 switch (size) {
4304 case 0: gen_helper_neon_negl_u16(var, var); break;
4305 case 1: gen_helper_neon_negl_u32(var, var); break;
4306 case 2: gen_helper_neon_negl_u64(var, var); break;
4307 default: abort();
4311 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4313 switch (size) {
4314 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4315 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4316 default: abort();
4320 static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
4322 TCGv_i64 tmp;
4324 switch ((size << 1) | u) {
4325 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4326 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4327 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4328 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4329 case 4:
4330 tmp = gen_muls_i64_i32(a, b);
4331 tcg_gen_mov_i64(dest, tmp);
4332 tcg_temp_free_i64(tmp);
4333 break;
4334 case 5:
4335 tmp = gen_mulu_i64_i32(a, b);
4336 tcg_gen_mov_i64(dest, tmp);
4337 tcg_temp_free_i64(tmp);
4338 break;
4339 default: abort();
4342 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
4343 Don't forget to clean them now. */
4344 if (size < 2) {
4345 tcg_temp_free_i32(a);
4346 tcg_temp_free_i32(b);
4350 static void gen_neon_narrow_op(int op, int u, int size, TCGv dest, TCGv_i64 src)
4352 if (op) {
4353 if (u) {
4354 gen_neon_unarrow_sats(size, dest, src);
4355 } else {
4356 gen_neon_narrow(size, dest, src);
4358 } else {
4359 if (u) {
4360 gen_neon_narrow_satu(size, dest, src);
4361 } else {
4362 gen_neon_narrow_sats(size, dest, src);
4367 /* Symbolic constants for op fields for Neon 3-register same-length.
4368 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
4369 * table A7-9.
4371 #define NEON_3R_VHADD 0
4372 #define NEON_3R_VQADD 1
4373 #define NEON_3R_VRHADD 2
4374 #define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
4375 #define NEON_3R_VHSUB 4
4376 #define NEON_3R_VQSUB 5
4377 #define NEON_3R_VCGT 6
4378 #define NEON_3R_VCGE 7
4379 #define NEON_3R_VSHL 8
4380 #define NEON_3R_VQSHL 9
4381 #define NEON_3R_VRSHL 10
4382 #define NEON_3R_VQRSHL 11
4383 #define NEON_3R_VMAX 12
4384 #define NEON_3R_VMIN 13
4385 #define NEON_3R_VABD 14
4386 #define NEON_3R_VABA 15
4387 #define NEON_3R_VADD_VSUB 16
4388 #define NEON_3R_VTST_VCEQ 17
4389 #define NEON_3R_VML 18 /* VMLA, VMLAL, VMLS, VMLSL */
4390 #define NEON_3R_VMUL 19
4391 #define NEON_3R_VPMAX 20
4392 #define NEON_3R_VPMIN 21
4393 #define NEON_3R_VQDMULH_VQRDMULH 22
4394 #define NEON_3R_VPADD 23
4395 #define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
4396 #define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
4397 #define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
4398 #define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
4399 #define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
4400 #define NEON_3R_VRECPS_VRSQRTS 31 /* float VRECPS, VRSQRTS */
4402 static const uint8_t neon_3r_sizes[] = {
4403 [NEON_3R_VHADD] = 0x7,
4404 [NEON_3R_VQADD] = 0xf,
4405 [NEON_3R_VRHADD] = 0x7,
4406 [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
4407 [NEON_3R_VHSUB] = 0x7,
4408 [NEON_3R_VQSUB] = 0xf,
4409 [NEON_3R_VCGT] = 0x7,
4410 [NEON_3R_VCGE] = 0x7,
4411 [NEON_3R_VSHL] = 0xf,
4412 [NEON_3R_VQSHL] = 0xf,
4413 [NEON_3R_VRSHL] = 0xf,
4414 [NEON_3R_VQRSHL] = 0xf,
4415 [NEON_3R_VMAX] = 0x7,
4416 [NEON_3R_VMIN] = 0x7,
4417 [NEON_3R_VABD] = 0x7,
4418 [NEON_3R_VABA] = 0x7,
4419 [NEON_3R_VADD_VSUB] = 0xf,
4420 [NEON_3R_VTST_VCEQ] = 0x7,
4421 [NEON_3R_VML] = 0x7,
4422 [NEON_3R_VMUL] = 0x7,
4423 [NEON_3R_VPMAX] = 0x7,
4424 [NEON_3R_VPMIN] = 0x7,
4425 [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
4426 [NEON_3R_VPADD] = 0x7,
4427 [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
4428 [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
4429 [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
4430 [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
4431 [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
4432 [NEON_3R_VRECPS_VRSQRTS] = 0x5, /* size bit 1 encodes op */
4435 /* Symbolic constants for op fields for Neon 2-register miscellaneous.
4436 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
4437 * table A7-13.
4439 #define NEON_2RM_VREV64 0
4440 #define NEON_2RM_VREV32 1
4441 #define NEON_2RM_VREV16 2
4442 #define NEON_2RM_VPADDL 4
4443 #define NEON_2RM_VPADDL_U 5
4444 #define NEON_2RM_VCLS 8
4445 #define NEON_2RM_VCLZ 9
4446 #define NEON_2RM_VCNT 10
4447 #define NEON_2RM_VMVN 11
4448 #define NEON_2RM_VPADAL 12
4449 #define NEON_2RM_VPADAL_U 13
4450 #define NEON_2RM_VQABS 14
4451 #define NEON_2RM_VQNEG 15
4452 #define NEON_2RM_VCGT0 16
4453 #define NEON_2RM_VCGE0 17
4454 #define NEON_2RM_VCEQ0 18
4455 #define NEON_2RM_VCLE0 19
4456 #define NEON_2RM_VCLT0 20
4457 #define NEON_2RM_VABS 22
4458 #define NEON_2RM_VNEG 23
4459 #define NEON_2RM_VCGT0_F 24
4460 #define NEON_2RM_VCGE0_F 25
4461 #define NEON_2RM_VCEQ0_F 26
4462 #define NEON_2RM_VCLE0_F 27
4463 #define NEON_2RM_VCLT0_F 28
4464 #define NEON_2RM_VABS_F 30
4465 #define NEON_2RM_VNEG_F 31
4466 #define NEON_2RM_VSWP 32
4467 #define NEON_2RM_VTRN 33
4468 #define NEON_2RM_VUZP 34
4469 #define NEON_2RM_VZIP 35
4470 #define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
4471 #define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
4472 #define NEON_2RM_VSHLL 38
4473 #define NEON_2RM_VCVT_F16_F32 44
4474 #define NEON_2RM_VCVT_F32_F16 46
4475 #define NEON_2RM_VRECPE 56
4476 #define NEON_2RM_VRSQRTE 57
4477 #define NEON_2RM_VRECPE_F 58
4478 #define NEON_2RM_VRSQRTE_F 59
4479 #define NEON_2RM_VCVT_FS 60
4480 #define NEON_2RM_VCVT_FU 61
4481 #define NEON_2RM_VCVT_SF 62
4482 #define NEON_2RM_VCVT_UF 63
4484 static int neon_2rm_is_float_op(int op)
4486 /* Return true if this neon 2reg-misc op is float-to-float */
4487 return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
4488 op >= NEON_2RM_VRECPE_F);
4491 /* Each entry in this array has bit n set if the insn allows
4492 * size value n (otherwise it will UNDEF). Since unallocated
4493 * op values will have no bits set they always UNDEF.
4495 static const uint8_t neon_2rm_sizes[] = {
4496 [NEON_2RM_VREV64] = 0x7,
4497 [NEON_2RM_VREV32] = 0x3,
4498 [NEON_2RM_VREV16] = 0x1,
4499 [NEON_2RM_VPADDL] = 0x7,
4500 [NEON_2RM_VPADDL_U] = 0x7,
4501 [NEON_2RM_VCLS] = 0x7,
4502 [NEON_2RM_VCLZ] = 0x7,
4503 [NEON_2RM_VCNT] = 0x1,
4504 [NEON_2RM_VMVN] = 0x1,
4505 [NEON_2RM_VPADAL] = 0x7,
4506 [NEON_2RM_VPADAL_U] = 0x7,
4507 [NEON_2RM_VQABS] = 0x7,
4508 [NEON_2RM_VQNEG] = 0x7,
4509 [NEON_2RM_VCGT0] = 0x7,
4510 [NEON_2RM_VCGE0] = 0x7,
4511 [NEON_2RM_VCEQ0] = 0x7,
4512 [NEON_2RM_VCLE0] = 0x7,
4513 [NEON_2RM_VCLT0] = 0x7,
4514 [NEON_2RM_VABS] = 0x7,
4515 [NEON_2RM_VNEG] = 0x7,
4516 [NEON_2RM_VCGT0_F] = 0x4,
4517 [NEON_2RM_VCGE0_F] = 0x4,
4518 [NEON_2RM_VCEQ0_F] = 0x4,
4519 [NEON_2RM_VCLE0_F] = 0x4,
4520 [NEON_2RM_VCLT0_F] = 0x4,
4521 [NEON_2RM_VABS_F] = 0x4,
4522 [NEON_2RM_VNEG_F] = 0x4,
4523 [NEON_2RM_VSWP] = 0x1,
4524 [NEON_2RM_VTRN] = 0x7,
4525 [NEON_2RM_VUZP] = 0x7,
4526 [NEON_2RM_VZIP] = 0x7,
4527 [NEON_2RM_VMOVN] = 0x7,
4528 [NEON_2RM_VQMOVN] = 0x7,
4529 [NEON_2RM_VSHLL] = 0x7,
4530 [NEON_2RM_VCVT_F16_F32] = 0x2,
4531 [NEON_2RM_VCVT_F32_F16] = 0x2,
4532 [NEON_2RM_VRECPE] = 0x4,
4533 [NEON_2RM_VRSQRTE] = 0x4,
4534 [NEON_2RM_VRECPE_F] = 0x4,
4535 [NEON_2RM_VRSQRTE_F] = 0x4,
4536 [NEON_2RM_VCVT_FS] = 0x4,
4537 [NEON_2RM_VCVT_FU] = 0x4,
4538 [NEON_2RM_VCVT_SF] = 0x4,
4539 [NEON_2RM_VCVT_UF] = 0x4,
4542 /* Translate a NEON data processing instruction. Return nonzero if the
4543 instruction is invalid.
4544 We process data in a mixture of 32-bit and 64-bit chunks.
4545 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4547 static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4549 int op;
4550 int q;
4551 int rd, rn, rm;
4552 int size;
4553 int shift;
4554 int pass;
4555 int count;
4556 int pairwise;
4557 int u;
4558 uint32_t imm, mask;
4559 TCGv tmp, tmp2, tmp3, tmp4, tmp5;
4560 TCGv_i64 tmp64;
4562 if (!s->vfp_enabled)
4563 return 1;
4564 q = (insn & (1 << 6)) != 0;
4565 u = (insn >> 24) & 1;
4566 VFP_DREG_D(rd, insn);
4567 VFP_DREG_N(rn, insn);
4568 VFP_DREG_M(rm, insn);
4569 size = (insn >> 20) & 3;
4570 if ((insn & (1 << 23)) == 0) {
4571 /* Three register same length. */
4572 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4573 /* Catch invalid op and bad size combinations: UNDEF */
4574 if ((neon_3r_sizes[op] & (1 << size)) == 0) {
4575 return 1;
4577 /* All insns of this form UNDEF for either this condition or the
4578 * superset of cases "Q==1"; we catch the latter later.
4580 if (q && ((rd | rn | rm) & 1)) {
4581 return 1;
4583 if (size == 3 && op != NEON_3R_LOGIC) {
4584 /* 64-bit element instructions. */
4585 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4586 neon_load_reg64(cpu_V0, rn + pass);
4587 neon_load_reg64(cpu_V1, rm + pass);
4588 switch (op) {
4589 case NEON_3R_VQADD:
4590 if (u) {
4591 gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
4592 cpu_V0, cpu_V1);
4593 } else {
4594 gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
4595 cpu_V0, cpu_V1);
4597 break;
4598 case NEON_3R_VQSUB:
4599 if (u) {
4600 gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
4601 cpu_V0, cpu_V1);
4602 } else {
4603 gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
4604 cpu_V0, cpu_V1);
4606 break;
4607 case NEON_3R_VSHL:
4608 if (u) {
4609 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4610 } else {
4611 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4613 break;
4614 case NEON_3R_VQSHL:
4615 if (u) {
4616 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4617 cpu_V1, cpu_V0);
4618 } else {
4619 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
4620 cpu_V1, cpu_V0);
4622 break;
4623 case NEON_3R_VRSHL:
4624 if (u) {
4625 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4626 } else {
4627 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4629 break;
4630 case NEON_3R_VQRSHL:
4631 if (u) {
4632 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4633 cpu_V1, cpu_V0);
4634 } else {
4635 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4636 cpu_V1, cpu_V0);
4638 break;
4639 case NEON_3R_VADD_VSUB:
4640 if (u) {
4641 tcg_gen_sub_i64(CPU_V001);
4642 } else {
4643 tcg_gen_add_i64(CPU_V001);
4645 break;
4646 default:
4647 abort();
4649 neon_store_reg64(cpu_V0, rd + pass);
4651 return 0;
4653 pairwise = 0;
4654 switch (op) {
4655 case NEON_3R_VSHL:
4656 case NEON_3R_VQSHL:
4657 case NEON_3R_VRSHL:
4658 case NEON_3R_VQRSHL:
4660 int rtmp;
4661 /* Shift instruction operands are reversed. */
4662 rtmp = rn;
4663 rn = rm;
4664 rm = rtmp;
4666 break;
4667 case NEON_3R_VPADD:
4668 if (u) {
4669 return 1;
4671 /* Fall through */
4672 case NEON_3R_VPMAX:
4673 case NEON_3R_VPMIN:
4674 pairwise = 1;
4675 break;
4676 case NEON_3R_FLOAT_ARITH:
4677 pairwise = (u && size < 2); /* if VPADD (float) */
4678 break;
4679 case NEON_3R_FLOAT_MINMAX:
4680 pairwise = u; /* if VPMIN/VPMAX (float) */
4681 break;
4682 case NEON_3R_FLOAT_CMP:
4683 if (!u && size) {
4684 /* no encoding for U=0 C=1x */
4685 return 1;
4687 break;
4688 case NEON_3R_FLOAT_ACMP:
4689 if (!u) {
4690 return 1;
4692 break;
4693 case NEON_3R_VRECPS_VRSQRTS:
4694 if (u) {
4695 return 1;
4697 break;
4698 case NEON_3R_VMUL:
4699 if (u && (size != 0)) {
4700 /* UNDEF on invalid size for polynomial subcase */
4701 return 1;
4703 break;
4704 default:
4705 break;
4708 if (pairwise && q) {
4709 /* All the pairwise insns UNDEF if Q is set */
4710 return 1;
4713 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4715 if (pairwise) {
4716 /* Pairwise. */
4717 if (pass < 1) {
4718 tmp = neon_load_reg(rn, 0);
4719 tmp2 = neon_load_reg(rn, 1);
4720 } else {
4721 tmp = neon_load_reg(rm, 0);
4722 tmp2 = neon_load_reg(rm, 1);
4724 } else {
4725 /* Elementwise. */
4726 tmp = neon_load_reg(rn, pass);
4727 tmp2 = neon_load_reg(rm, pass);
4729 switch (op) {
4730 case NEON_3R_VHADD:
4731 GEN_NEON_INTEGER_OP(hadd);
4732 break;
4733 case NEON_3R_VQADD:
4734 GEN_NEON_INTEGER_OP_ENV(qadd);
4735 break;
4736 case NEON_3R_VRHADD:
4737 GEN_NEON_INTEGER_OP(rhadd);
4738 break;
4739 case NEON_3R_LOGIC: /* Logic ops. */
4740 switch ((u << 2) | size) {
4741 case 0: /* VAND */
4742 tcg_gen_and_i32(tmp, tmp, tmp2);
4743 break;
4744 case 1: /* BIC */
4745 tcg_gen_andc_i32(tmp, tmp, tmp2);
4746 break;
4747 case 2: /* VORR */
4748 tcg_gen_or_i32(tmp, tmp, tmp2);
4749 break;
4750 case 3: /* VORN */
4751 tcg_gen_orc_i32(tmp, tmp, tmp2);
4752 break;
4753 case 4: /* VEOR */
4754 tcg_gen_xor_i32(tmp, tmp, tmp2);
4755 break;
4756 case 5: /* VBSL */
4757 tmp3 = neon_load_reg(rd, pass);
4758 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
4759 tcg_temp_free_i32(tmp3);
4760 break;
4761 case 6: /* VBIT */
4762 tmp3 = neon_load_reg(rd, pass);
4763 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
4764 tcg_temp_free_i32(tmp3);
4765 break;
4766 case 7: /* VBIF */
4767 tmp3 = neon_load_reg(rd, pass);
4768 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
4769 tcg_temp_free_i32(tmp3);
4770 break;
4772 break;
4773 case NEON_3R_VHSUB:
4774 GEN_NEON_INTEGER_OP(hsub);
4775 break;
4776 case NEON_3R_VQSUB:
4777 GEN_NEON_INTEGER_OP_ENV(qsub);
4778 break;
4779 case NEON_3R_VCGT:
4780 GEN_NEON_INTEGER_OP(cgt);
4781 break;
4782 case NEON_3R_VCGE:
4783 GEN_NEON_INTEGER_OP(cge);
4784 break;
4785 case NEON_3R_VSHL:
4786 GEN_NEON_INTEGER_OP(shl);
4787 break;
4788 case NEON_3R_VQSHL:
4789 GEN_NEON_INTEGER_OP_ENV(qshl);
4790 break;
4791 case NEON_3R_VRSHL:
4792 GEN_NEON_INTEGER_OP(rshl);
4793 break;
4794 case NEON_3R_VQRSHL:
4795 GEN_NEON_INTEGER_OP_ENV(qrshl);
4796 break;
4797 case NEON_3R_VMAX:
4798 GEN_NEON_INTEGER_OP(max);
4799 break;
4800 case NEON_3R_VMIN:
4801 GEN_NEON_INTEGER_OP(min);
4802 break;
4803 case NEON_3R_VABD:
4804 GEN_NEON_INTEGER_OP(abd);
4805 break;
4806 case NEON_3R_VABA:
4807 GEN_NEON_INTEGER_OP(abd);
4808 tcg_temp_free_i32(tmp2);
4809 tmp2 = neon_load_reg(rd, pass);
4810 gen_neon_add(size, tmp, tmp2);
4811 break;
4812 case NEON_3R_VADD_VSUB:
4813 if (!u) { /* VADD */
4814 gen_neon_add(size, tmp, tmp2);
4815 } else { /* VSUB */
4816 switch (size) {
4817 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
4818 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
4819 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
4820 default: abort();
4823 break;
4824 case NEON_3R_VTST_VCEQ:
4825 if (!u) { /* VTST */
4826 switch (size) {
4827 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
4828 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
4829 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
4830 default: abort();
4832 } else { /* VCEQ */
4833 switch (size) {
4834 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
4835 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
4836 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
4837 default: abort();
4840 break;
4841 case NEON_3R_VML: /* VMLA, VMLAL, VMLS,VMLSL */
4842 switch (size) {
4843 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4844 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4845 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4846 default: abort();
4848 tcg_temp_free_i32(tmp2);
4849 tmp2 = neon_load_reg(rd, pass);
4850 if (u) { /* VMLS */
4851 gen_neon_rsb(size, tmp, tmp2);
4852 } else { /* VMLA */
4853 gen_neon_add(size, tmp, tmp2);
4855 break;
4856 case NEON_3R_VMUL:
4857 if (u) { /* polynomial */
4858 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
4859 } else { /* Integer */
4860 switch (size) {
4861 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4862 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4863 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4864 default: abort();
4867 break;
4868 case NEON_3R_VPMAX:
4869 GEN_NEON_INTEGER_OP(pmax);
4870 break;
4871 case NEON_3R_VPMIN:
4872 GEN_NEON_INTEGER_OP(pmin);
4873 break;
4874 case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
4875 if (!u) { /* VQDMULH */
4876 switch (size) {
4877 case 1:
4878 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
4879 break;
4880 case 2:
4881 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
4882 break;
4883 default: abort();
4885 } else { /* VQRDMULH */
4886 switch (size) {
4887 case 1:
4888 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
4889 break;
4890 case 2:
4891 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
4892 break;
4893 default: abort();
4896 break;
4897 case NEON_3R_VPADD:
4898 switch (size) {
4899 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
4900 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
4901 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
4902 default: abort();
4904 break;
4905 case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
4907 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
4908 switch ((u << 2) | size) {
4909 case 0: /* VADD */
4910 case 4: /* VPADD */
4911 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
4912 break;
4913 case 2: /* VSUB */
4914 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
4915 break;
4916 case 6: /* VABD */
4917 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
4918 break;
4919 default:
4920 abort();
4922 tcg_temp_free_ptr(fpstatus);
4923 break;
4925 case NEON_3R_FLOAT_MULTIPLY:
4927 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
4928 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
4929 if (!u) {
4930 tcg_temp_free_i32(tmp2);
4931 tmp2 = neon_load_reg(rd, pass);
4932 if (size == 0) {
4933 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
4934 } else {
4935 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
4938 tcg_temp_free_ptr(fpstatus);
4939 break;
4941 case NEON_3R_FLOAT_CMP:
4943 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
4944 if (!u) {
4945 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
4946 } else {
4947 if (size == 0) {
4948 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
4949 } else {
4950 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
4953 tcg_temp_free_ptr(fpstatus);
4954 break;
4956 case NEON_3R_FLOAT_ACMP:
4958 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
4959 if (size == 0) {
4960 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
4961 } else {
4962 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
4964 tcg_temp_free_ptr(fpstatus);
4965 break;
4967 case NEON_3R_FLOAT_MINMAX:
4969 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
4970 if (size == 0) {
4971 gen_helper_neon_max_f32(tmp, tmp, tmp2, fpstatus);
4972 } else {
4973 gen_helper_neon_min_f32(tmp, tmp, tmp2, fpstatus);
4975 tcg_temp_free_ptr(fpstatus);
4976 break;
4978 case NEON_3R_VRECPS_VRSQRTS:
4979 if (size == 0)
4980 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
4981 else
4982 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
4983 break;
4984 default:
4985 abort();
4987 tcg_temp_free_i32(tmp2);
4989 /* Save the result. For elementwise operations we can put it
4990 straight into the destination register. For pairwise operations
4991 we have to be careful to avoid clobbering the source operands. */
4992 if (pairwise && rd == rm) {
4993 neon_store_scratch(pass, tmp);
4994 } else {
4995 neon_store_reg(rd, pass, tmp);
4998 } /* for pass */
4999 if (pairwise && rd == rm) {
5000 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5001 tmp = neon_load_scratch(pass);
5002 neon_store_reg(rd, pass, tmp);
5005 /* End of 3 register same size operations. */
5006 } else if (insn & (1 << 4)) {
5007 if ((insn & 0x00380080) != 0) {
5008 /* Two registers and shift. */
5009 op = (insn >> 8) & 0xf;
5010 if (insn & (1 << 7)) {
5011 /* 64-bit shift. */
5012 if (op > 7) {
5013 return 1;
5015 size = 3;
5016 } else {
5017 size = 2;
5018 while ((insn & (1 << (size + 19))) == 0)
5019 size--;
5021 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
5022 /* To avoid excessive dumplication of ops we implement shift
5023 by immediate using the variable shift operations. */
5024 if (op < 8) {
5025 /* Shift by immediate:
5026 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
5027 if (q && ((rd | rm) & 1)) {
5028 return 1;
5030 if (!u && (op == 4 || op == 6)) {
5031 return 1;
5033 /* Right shifts are encoded as N - shift, where N is the
5034 element size in bits. */
5035 if (op <= 4)
5036 shift = shift - (1 << (size + 3));
5037 if (size == 3) {
5038 count = q + 1;
5039 } else {
5040 count = q ? 4: 2;
5042 switch (size) {
5043 case 0:
5044 imm = (uint8_t) shift;
5045 imm |= imm << 8;
5046 imm |= imm << 16;
5047 break;
5048 case 1:
5049 imm = (uint16_t) shift;
5050 imm |= imm << 16;
5051 break;
5052 case 2:
5053 case 3:
5054 imm = shift;
5055 break;
5056 default:
5057 abort();
5060 for (pass = 0; pass < count; pass++) {
5061 if (size == 3) {
5062 neon_load_reg64(cpu_V0, rm + pass);
5063 tcg_gen_movi_i64(cpu_V1, imm);
5064 switch (op) {
5065 case 0: /* VSHR */
5066 case 1: /* VSRA */
5067 if (u)
5068 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
5069 else
5070 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
5071 break;
5072 case 2: /* VRSHR */
5073 case 3: /* VRSRA */
5074 if (u)
5075 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
5076 else
5077 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
5078 break;
5079 case 4: /* VSRI */
5080 case 5: /* VSHL, VSLI */
5081 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
5082 break;
5083 case 6: /* VQSHLU */
5084 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
5085 cpu_V0, cpu_V1);
5086 break;
5087 case 7: /* VQSHL */
5088 if (u) {
5089 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
5090 cpu_V0, cpu_V1);
5091 } else {
5092 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
5093 cpu_V0, cpu_V1);
5095 break;
5097 if (op == 1 || op == 3) {
5098 /* Accumulate. */
5099 neon_load_reg64(cpu_V1, rd + pass);
5100 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
5101 } else if (op == 4 || (op == 5 && u)) {
5102 /* Insert */
5103 neon_load_reg64(cpu_V1, rd + pass);
5104 uint64_t mask;
5105 if (shift < -63 || shift > 63) {
5106 mask = 0;
5107 } else {
5108 if (op == 4) {
5109 mask = 0xffffffffffffffffull >> -shift;
5110 } else {
5111 mask = 0xffffffffffffffffull << shift;
5114 tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask);
5115 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5117 neon_store_reg64(cpu_V0, rd + pass);
5118 } else { /* size < 3 */
5119 /* Operands in T0 and T1. */
5120 tmp = neon_load_reg(rm, pass);
5121 tmp2 = tcg_temp_new_i32();
5122 tcg_gen_movi_i32(tmp2, imm);
5123 switch (op) {
5124 case 0: /* VSHR */
5125 case 1: /* VSRA */
5126 GEN_NEON_INTEGER_OP(shl);
5127 break;
5128 case 2: /* VRSHR */
5129 case 3: /* VRSRA */
5130 GEN_NEON_INTEGER_OP(rshl);
5131 break;
5132 case 4: /* VSRI */
5133 case 5: /* VSHL, VSLI */
5134 switch (size) {
5135 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
5136 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
5137 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
5138 default: abort();
5140 break;
5141 case 6: /* VQSHLU */
5142 switch (size) {
5143 case 0:
5144 gen_helper_neon_qshlu_s8(tmp, cpu_env,
5145 tmp, tmp2);
5146 break;
5147 case 1:
5148 gen_helper_neon_qshlu_s16(tmp, cpu_env,
5149 tmp, tmp2);
5150 break;
5151 case 2:
5152 gen_helper_neon_qshlu_s32(tmp, cpu_env,
5153 tmp, tmp2);
5154 break;
5155 default:
5156 abort();
5158 break;
5159 case 7: /* VQSHL */
5160 GEN_NEON_INTEGER_OP_ENV(qshl);
5161 break;
5163 tcg_temp_free_i32(tmp2);
5165 if (op == 1 || op == 3) {
5166 /* Accumulate. */
5167 tmp2 = neon_load_reg(rd, pass);
5168 gen_neon_add(size, tmp, tmp2);
5169 tcg_temp_free_i32(tmp2);
5170 } else if (op == 4 || (op == 5 && u)) {
5171 /* Insert */
5172 switch (size) {
5173 case 0:
5174 if (op == 4)
5175 mask = 0xff >> -shift;
5176 else
5177 mask = (uint8_t)(0xff << shift);
5178 mask |= mask << 8;
5179 mask |= mask << 16;
5180 break;
5181 case 1:
5182 if (op == 4)
5183 mask = 0xffff >> -shift;
5184 else
5185 mask = (uint16_t)(0xffff << shift);
5186 mask |= mask << 16;
5187 break;
5188 case 2:
5189 if (shift < -31 || shift > 31) {
5190 mask = 0;
5191 } else {
5192 if (op == 4)
5193 mask = 0xffffffffu >> -shift;
5194 else
5195 mask = 0xffffffffu << shift;
5197 break;
5198 default:
5199 abort();
5201 tmp2 = neon_load_reg(rd, pass);
5202 tcg_gen_andi_i32(tmp, tmp, mask);
5203 tcg_gen_andi_i32(tmp2, tmp2, ~mask);
5204 tcg_gen_or_i32(tmp, tmp, tmp2);
5205 tcg_temp_free_i32(tmp2);
5207 neon_store_reg(rd, pass, tmp);
5209 } /* for pass */
5210 } else if (op < 10) {
5211 /* Shift by immediate and narrow:
5212 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
5213 int input_unsigned = (op == 8) ? !u : u;
5214 if (rm & 1) {
5215 return 1;
5217 shift = shift - (1 << (size + 3));
5218 size++;
5219 if (size == 3) {
5220 tmp64 = tcg_const_i64(shift);
5221 neon_load_reg64(cpu_V0, rm);
5222 neon_load_reg64(cpu_V1, rm + 1);
5223 for (pass = 0; pass < 2; pass++) {
5224 TCGv_i64 in;
5225 if (pass == 0) {
5226 in = cpu_V0;
5227 } else {
5228 in = cpu_V1;
5230 if (q) {
5231 if (input_unsigned) {
5232 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
5233 } else {
5234 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
5236 } else {
5237 if (input_unsigned) {
5238 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
5239 } else {
5240 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
5243 tmp = tcg_temp_new_i32();
5244 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5245 neon_store_reg(rd, pass, tmp);
5246 } /* for pass */
5247 tcg_temp_free_i64(tmp64);
5248 } else {
5249 if (size == 1) {
5250 imm = (uint16_t)shift;
5251 imm |= imm << 16;
5252 } else {
5253 /* size == 2 */
5254 imm = (uint32_t)shift;
5256 tmp2 = tcg_const_i32(imm);
5257 tmp4 = neon_load_reg(rm + 1, 0);
5258 tmp5 = neon_load_reg(rm + 1, 1);
5259 for (pass = 0; pass < 2; pass++) {
5260 if (pass == 0) {
5261 tmp = neon_load_reg(rm, 0);
5262 } else {
5263 tmp = tmp4;
5265 gen_neon_shift_narrow(size, tmp, tmp2, q,
5266 input_unsigned);
5267 if (pass == 0) {
5268 tmp3 = neon_load_reg(rm, 1);
5269 } else {
5270 tmp3 = tmp5;
5272 gen_neon_shift_narrow(size, tmp3, tmp2, q,
5273 input_unsigned);
5274 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
5275 tcg_temp_free_i32(tmp);
5276 tcg_temp_free_i32(tmp3);
5277 tmp = tcg_temp_new_i32();
5278 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5279 neon_store_reg(rd, pass, tmp);
5280 } /* for pass */
5281 tcg_temp_free_i32(tmp2);
5283 } else if (op == 10) {
5284 /* VSHLL, VMOVL */
5285 if (q || (rd & 1)) {
5286 return 1;
5288 tmp = neon_load_reg(rm, 0);
5289 tmp2 = neon_load_reg(rm, 1);
5290 for (pass = 0; pass < 2; pass++) {
5291 if (pass == 1)
5292 tmp = tmp2;
5294 gen_neon_widen(cpu_V0, tmp, size, u);
5296 if (shift != 0) {
5297 /* The shift is less than the width of the source
5298 type, so we can just shift the whole register. */
5299 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
5300 /* Widen the result of shift: we need to clear
5301 * the potential overflow bits resulting from
5302 * left bits of the narrow input appearing as
5303 * right bits of left the neighbour narrow
5304 * input. */
5305 if (size < 2 || !u) {
5306 uint64_t imm64;
5307 if (size == 0) {
5308 imm = (0xffu >> (8 - shift));
5309 imm |= imm << 16;
5310 } else if (size == 1) {
5311 imm = 0xffff >> (16 - shift);
5312 } else {
5313 /* size == 2 */
5314 imm = 0xffffffff >> (32 - shift);
5316 if (size < 2) {
5317 imm64 = imm | (((uint64_t)imm) << 32);
5318 } else {
5319 imm64 = imm;
5321 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
5324 neon_store_reg64(cpu_V0, rd + pass);
5326 } else if (op >= 14) {
5327 /* VCVT fixed-point. */
5328 if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
5329 return 1;
5331 /* We have already masked out the must-be-1 top bit of imm6,
5332 * hence this 32-shift where the ARM ARM has 64-imm6.
5334 shift = 32 - shift;
5335 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5336 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
5337 if (!(op & 1)) {
5338 if (u)
5339 gen_vfp_ulto(0, shift, 1);
5340 else
5341 gen_vfp_slto(0, shift, 1);
5342 } else {
5343 if (u)
5344 gen_vfp_toul(0, shift, 1);
5345 else
5346 gen_vfp_tosl(0, shift, 1);
5348 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
5350 } else {
5351 return 1;
5353 } else { /* (insn & 0x00380080) == 0 */
5354 int invert;
5355 if (q && (rd & 1)) {
5356 return 1;
5359 op = (insn >> 8) & 0xf;
5360 /* One register and immediate. */
5361 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
5362 invert = (insn & (1 << 5)) != 0;
5363 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
5364 * We choose to not special-case this and will behave as if a
5365 * valid constant encoding of 0 had been given.
5367 switch (op) {
5368 case 0: case 1:
5369 /* no-op */
5370 break;
5371 case 2: case 3:
5372 imm <<= 8;
5373 break;
5374 case 4: case 5:
5375 imm <<= 16;
5376 break;
5377 case 6: case 7:
5378 imm <<= 24;
5379 break;
5380 case 8: case 9:
5381 imm |= imm << 16;
5382 break;
5383 case 10: case 11:
5384 imm = (imm << 8) | (imm << 24);
5385 break;
5386 case 12:
5387 imm = (imm << 8) | 0xff;
5388 break;
5389 case 13:
5390 imm = (imm << 16) | 0xffff;
5391 break;
5392 case 14:
5393 imm |= (imm << 8) | (imm << 16) | (imm << 24);
5394 if (invert)
5395 imm = ~imm;
5396 break;
5397 case 15:
5398 if (invert) {
5399 return 1;
5401 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
5402 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
5403 break;
5405 if (invert)
5406 imm = ~imm;
5408 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5409 if (op & 1 && op < 12) {
5410 tmp = neon_load_reg(rd, pass);
5411 if (invert) {
5412 /* The immediate value has already been inverted, so
5413 BIC becomes AND. */
5414 tcg_gen_andi_i32(tmp, tmp, imm);
5415 } else {
5416 tcg_gen_ori_i32(tmp, tmp, imm);
5418 } else {
5419 /* VMOV, VMVN. */
5420 tmp = tcg_temp_new_i32();
5421 if (op == 14 && invert) {
5422 int n;
5423 uint32_t val;
5424 val = 0;
5425 for (n = 0; n < 4; n++) {
5426 if (imm & (1 << (n + (pass & 1) * 4)))
5427 val |= 0xff << (n * 8);
5429 tcg_gen_movi_i32(tmp, val);
5430 } else {
5431 tcg_gen_movi_i32(tmp, imm);
5434 neon_store_reg(rd, pass, tmp);
5437 } else { /* (insn & 0x00800010 == 0x00800000) */
5438 if (size != 3) {
5439 op = (insn >> 8) & 0xf;
5440 if ((insn & (1 << 6)) == 0) {
5441 /* Three registers of different lengths. */
5442 int src1_wide;
5443 int src2_wide;
5444 int prewiden;
5445 /* undefreq: bit 0 : UNDEF if size != 0
5446 * bit 1 : UNDEF if size == 0
5447 * bit 2 : UNDEF if U == 1
5448 * Note that [1:0] set implies 'always UNDEF'
5450 int undefreq;
5451 /* prewiden, src1_wide, src2_wide, undefreq */
5452 static const int neon_3reg_wide[16][4] = {
5453 {1, 0, 0, 0}, /* VADDL */
5454 {1, 1, 0, 0}, /* VADDW */
5455 {1, 0, 0, 0}, /* VSUBL */
5456 {1, 1, 0, 0}, /* VSUBW */
5457 {0, 1, 1, 0}, /* VADDHN */
5458 {0, 0, 0, 0}, /* VABAL */
5459 {0, 1, 1, 0}, /* VSUBHN */
5460 {0, 0, 0, 0}, /* VABDL */
5461 {0, 0, 0, 0}, /* VMLAL */
5462 {0, 0, 0, 6}, /* VQDMLAL */
5463 {0, 0, 0, 0}, /* VMLSL */
5464 {0, 0, 0, 6}, /* VQDMLSL */
5465 {0, 0, 0, 0}, /* Integer VMULL */
5466 {0, 0, 0, 2}, /* VQDMULL */
5467 {0, 0, 0, 5}, /* Polynomial VMULL */
5468 {0, 0, 0, 3}, /* Reserved: always UNDEF */
5471 prewiden = neon_3reg_wide[op][0];
5472 src1_wide = neon_3reg_wide[op][1];
5473 src2_wide = neon_3reg_wide[op][2];
5474 undefreq = neon_3reg_wide[op][3];
5476 if (((undefreq & 1) && (size != 0)) ||
5477 ((undefreq & 2) && (size == 0)) ||
5478 ((undefreq & 4) && u)) {
5479 return 1;
5481 if ((src1_wide && (rn & 1)) ||
5482 (src2_wide && (rm & 1)) ||
5483 (!src2_wide && (rd & 1))) {
5484 return 1;
5487 /* Avoid overlapping operands. Wide source operands are
5488 always aligned so will never overlap with wide
5489 destinations in problematic ways. */
5490 if (rd == rm && !src2_wide) {
5491 tmp = neon_load_reg(rm, 1);
5492 neon_store_scratch(2, tmp);
5493 } else if (rd == rn && !src1_wide) {
5494 tmp = neon_load_reg(rn, 1);
5495 neon_store_scratch(2, tmp);
5497 TCGV_UNUSED(tmp3);
5498 for (pass = 0; pass < 2; pass++) {
5499 if (src1_wide) {
5500 neon_load_reg64(cpu_V0, rn + pass);
5501 TCGV_UNUSED(tmp);
5502 } else {
5503 if (pass == 1 && rd == rn) {
5504 tmp = neon_load_scratch(2);
5505 } else {
5506 tmp = neon_load_reg(rn, pass);
5508 if (prewiden) {
5509 gen_neon_widen(cpu_V0, tmp, size, u);
5512 if (src2_wide) {
5513 neon_load_reg64(cpu_V1, rm + pass);
5514 TCGV_UNUSED(tmp2);
5515 } else {
5516 if (pass == 1 && rd == rm) {
5517 tmp2 = neon_load_scratch(2);
5518 } else {
5519 tmp2 = neon_load_reg(rm, pass);
5521 if (prewiden) {
5522 gen_neon_widen(cpu_V1, tmp2, size, u);
5525 switch (op) {
5526 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5527 gen_neon_addl(size);
5528 break;
5529 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
5530 gen_neon_subl(size);
5531 break;
5532 case 5: case 7: /* VABAL, VABDL */
5533 switch ((size << 1) | u) {
5534 case 0:
5535 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
5536 break;
5537 case 1:
5538 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
5539 break;
5540 case 2:
5541 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
5542 break;
5543 case 3:
5544 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
5545 break;
5546 case 4:
5547 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
5548 break;
5549 case 5:
5550 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
5551 break;
5552 default: abort();
5554 tcg_temp_free_i32(tmp2);
5555 tcg_temp_free_i32(tmp);
5556 break;
5557 case 8: case 9: case 10: case 11: case 12: case 13:
5558 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5559 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5560 break;
5561 case 14: /* Polynomial VMULL */
5562 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
5563 tcg_temp_free_i32(tmp2);
5564 tcg_temp_free_i32(tmp);
5565 break;
5566 default: /* 15 is RESERVED: caught earlier */
5567 abort();
5569 if (op == 13) {
5570 /* VQDMULL */
5571 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5572 neon_store_reg64(cpu_V0, rd + pass);
5573 } else if (op == 5 || (op >= 8 && op <= 11)) {
5574 /* Accumulate. */
5575 neon_load_reg64(cpu_V1, rd + pass);
5576 switch (op) {
5577 case 10: /* VMLSL */
5578 gen_neon_negl(cpu_V0, size);
5579 /* Fall through */
5580 case 5: case 8: /* VABAL, VMLAL */
5581 gen_neon_addl(size);
5582 break;
5583 case 9: case 11: /* VQDMLAL, VQDMLSL */
5584 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5585 if (op == 11) {
5586 gen_neon_negl(cpu_V0, size);
5588 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5589 break;
5590 default:
5591 abort();
5593 neon_store_reg64(cpu_V0, rd + pass);
5594 } else if (op == 4 || op == 6) {
5595 /* Narrowing operation. */
5596 tmp = tcg_temp_new_i32();
5597 if (!u) {
5598 switch (size) {
5599 case 0:
5600 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
5601 break;
5602 case 1:
5603 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
5604 break;
5605 case 2:
5606 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5607 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5608 break;
5609 default: abort();
5611 } else {
5612 switch (size) {
5613 case 0:
5614 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
5615 break;
5616 case 1:
5617 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
5618 break;
5619 case 2:
5620 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
5621 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5622 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5623 break;
5624 default: abort();
5627 if (pass == 0) {
5628 tmp3 = tmp;
5629 } else {
5630 neon_store_reg(rd, 0, tmp3);
5631 neon_store_reg(rd, 1, tmp);
5633 } else {
5634 /* Write back the result. */
5635 neon_store_reg64(cpu_V0, rd + pass);
5638 } else {
5639 /* Two registers and a scalar. NB that for ops of this form
5640 * the ARM ARM labels bit 24 as Q, but it is in our variable
5641 * 'u', not 'q'.
5643 if (size == 0) {
5644 return 1;
5646 switch (op) {
5647 case 1: /* Float VMLA scalar */
5648 case 5: /* Floating point VMLS scalar */
5649 case 9: /* Floating point VMUL scalar */
5650 if (size == 1) {
5651 return 1;
5653 /* fall through */
5654 case 0: /* Integer VMLA scalar */
5655 case 4: /* Integer VMLS scalar */
5656 case 8: /* Integer VMUL scalar */
5657 case 12: /* VQDMULH scalar */
5658 case 13: /* VQRDMULH scalar */
5659 if (u && ((rd | rn) & 1)) {
5660 return 1;
5662 tmp = neon_get_scalar(size, rm);
5663 neon_store_scratch(0, tmp);
5664 for (pass = 0; pass < (u ? 4 : 2); pass++) {
5665 tmp = neon_load_scratch(0);
5666 tmp2 = neon_load_reg(rn, pass);
5667 if (op == 12) {
5668 if (size == 1) {
5669 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5670 } else {
5671 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5673 } else if (op == 13) {
5674 if (size == 1) {
5675 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5676 } else {
5677 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5679 } else if (op & 1) {
5680 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5681 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
5682 tcg_temp_free_ptr(fpstatus);
5683 } else {
5684 switch (size) {
5685 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5686 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5687 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5688 default: abort();
5691 tcg_temp_free_i32(tmp2);
5692 if (op < 8) {
5693 /* Accumulate. */
5694 tmp2 = neon_load_reg(rd, pass);
5695 switch (op) {
5696 case 0:
5697 gen_neon_add(size, tmp, tmp2);
5698 break;
5699 case 1:
5701 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5702 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5703 tcg_temp_free_ptr(fpstatus);
5704 break;
5706 case 4:
5707 gen_neon_rsb(size, tmp, tmp2);
5708 break;
5709 case 5:
5711 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5712 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
5713 tcg_temp_free_ptr(fpstatus);
5714 break;
5716 default:
5717 abort();
5719 tcg_temp_free_i32(tmp2);
5721 neon_store_reg(rd, pass, tmp);
5723 break;
5724 case 3: /* VQDMLAL scalar */
5725 case 7: /* VQDMLSL scalar */
5726 case 11: /* VQDMULL scalar */
5727 if (u == 1) {
5728 return 1;
5730 /* fall through */
5731 case 2: /* VMLAL sclar */
5732 case 6: /* VMLSL scalar */
5733 case 10: /* VMULL scalar */
5734 if (rd & 1) {
5735 return 1;
5737 tmp2 = neon_get_scalar(size, rm);
5738 /* We need a copy of tmp2 because gen_neon_mull
5739 * deletes it during pass 0. */
5740 tmp4 = tcg_temp_new_i32();
5741 tcg_gen_mov_i32(tmp4, tmp2);
5742 tmp3 = neon_load_reg(rn, 1);
5744 for (pass = 0; pass < 2; pass++) {
5745 if (pass == 0) {
5746 tmp = neon_load_reg(rn, 0);
5747 } else {
5748 tmp = tmp3;
5749 tmp2 = tmp4;
5751 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5752 if (op != 11) {
5753 neon_load_reg64(cpu_V1, rd + pass);
5755 switch (op) {
5756 case 6:
5757 gen_neon_negl(cpu_V0, size);
5758 /* Fall through */
5759 case 2:
5760 gen_neon_addl(size);
5761 break;
5762 case 3: case 7:
5763 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5764 if (op == 7) {
5765 gen_neon_negl(cpu_V0, size);
5767 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5768 break;
5769 case 10:
5770 /* no-op */
5771 break;
5772 case 11:
5773 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5774 break;
5775 default:
5776 abort();
5778 neon_store_reg64(cpu_V0, rd + pass);
5782 break;
5783 default: /* 14 and 15 are RESERVED */
5784 return 1;
5787 } else { /* size == 3 */
5788 if (!u) {
5789 /* Extract. */
5790 imm = (insn >> 8) & 0xf;
5792 if (imm > 7 && !q)
5793 return 1;
5795 if (q && ((rd | rn | rm) & 1)) {
5796 return 1;
5799 if (imm == 0) {
5800 neon_load_reg64(cpu_V0, rn);
5801 if (q) {
5802 neon_load_reg64(cpu_V1, rn + 1);
5804 } else if (imm == 8) {
5805 neon_load_reg64(cpu_V0, rn + 1);
5806 if (q) {
5807 neon_load_reg64(cpu_V1, rm);
5809 } else if (q) {
5810 tmp64 = tcg_temp_new_i64();
5811 if (imm < 8) {
5812 neon_load_reg64(cpu_V0, rn);
5813 neon_load_reg64(tmp64, rn + 1);
5814 } else {
5815 neon_load_reg64(cpu_V0, rn + 1);
5816 neon_load_reg64(tmp64, rm);
5818 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5819 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
5820 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5821 if (imm < 8) {
5822 neon_load_reg64(cpu_V1, rm);
5823 } else {
5824 neon_load_reg64(cpu_V1, rm + 1);
5825 imm -= 8;
5827 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5828 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
5829 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
5830 tcg_temp_free_i64(tmp64);
5831 } else {
5832 /* BUGFIX */
5833 neon_load_reg64(cpu_V0, rn);
5834 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
5835 neon_load_reg64(cpu_V1, rm);
5836 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5837 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5839 neon_store_reg64(cpu_V0, rd);
5840 if (q) {
5841 neon_store_reg64(cpu_V1, rd + 1);
5843 } else if ((insn & (1 << 11)) == 0) {
5844 /* Two register misc. */
5845 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5846 size = (insn >> 18) & 3;
5847 /* UNDEF for unknown op values and bad op-size combinations */
5848 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
5849 return 1;
5851 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
5852 q && ((rm | rd) & 1)) {
5853 return 1;
5855 switch (op) {
5856 case NEON_2RM_VREV64:
5857 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5858 tmp = neon_load_reg(rm, pass * 2);
5859 tmp2 = neon_load_reg(rm, pass * 2 + 1);
5860 switch (size) {
5861 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5862 case 1: gen_swap_half(tmp); break;
5863 case 2: /* no-op */ break;
5864 default: abort();
5866 neon_store_reg(rd, pass * 2 + 1, tmp);
5867 if (size == 2) {
5868 neon_store_reg(rd, pass * 2, tmp2);
5869 } else {
5870 switch (size) {
5871 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
5872 case 1: gen_swap_half(tmp2); break;
5873 default: abort();
5875 neon_store_reg(rd, pass * 2, tmp2);
5878 break;
5879 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
5880 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
5881 for (pass = 0; pass < q + 1; pass++) {
5882 tmp = neon_load_reg(rm, pass * 2);
5883 gen_neon_widen(cpu_V0, tmp, size, op & 1);
5884 tmp = neon_load_reg(rm, pass * 2 + 1);
5885 gen_neon_widen(cpu_V1, tmp, size, op & 1);
5886 switch (size) {
5887 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5888 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5889 case 2: tcg_gen_add_i64(CPU_V001); break;
5890 default: abort();
5892 if (op >= NEON_2RM_VPADAL) {
5893 /* Accumulate. */
5894 neon_load_reg64(cpu_V1, rd + pass);
5895 gen_neon_addl(size);
5897 neon_store_reg64(cpu_V0, rd + pass);
5899 break;
5900 case NEON_2RM_VTRN:
5901 if (size == 2) {
5902 int n;
5903 for (n = 0; n < (q ? 4 : 2); n += 2) {
5904 tmp = neon_load_reg(rm, n);
5905 tmp2 = neon_load_reg(rd, n + 1);
5906 neon_store_reg(rm, n, tmp2);
5907 neon_store_reg(rd, n + 1, tmp);
5909 } else {
5910 goto elementwise;
5912 break;
5913 case NEON_2RM_VUZP:
5914 if (gen_neon_unzip(rd, rm, size, q)) {
5915 return 1;
5917 break;
5918 case NEON_2RM_VZIP:
5919 if (gen_neon_zip(rd, rm, size, q)) {
5920 return 1;
5922 break;
5923 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
5924 /* also VQMOVUN; op field and mnemonics don't line up */
5925 if (rm & 1) {
5926 return 1;
5928 TCGV_UNUSED(tmp2);
5929 for (pass = 0; pass < 2; pass++) {
5930 neon_load_reg64(cpu_V0, rm + pass);
5931 tmp = tcg_temp_new_i32();
5932 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
5933 tmp, cpu_V0);
5934 if (pass == 0) {
5935 tmp2 = tmp;
5936 } else {
5937 neon_store_reg(rd, 0, tmp2);
5938 neon_store_reg(rd, 1, tmp);
5941 break;
5942 case NEON_2RM_VSHLL:
5943 if (q || (rd & 1)) {
5944 return 1;
5946 tmp = neon_load_reg(rm, 0);
5947 tmp2 = neon_load_reg(rm, 1);
5948 for (pass = 0; pass < 2; pass++) {
5949 if (pass == 1)
5950 tmp = tmp2;
5951 gen_neon_widen(cpu_V0, tmp, size, 1);
5952 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
5953 neon_store_reg64(cpu_V0, rd + pass);
5955 break;
5956 case NEON_2RM_VCVT_F16_F32:
5957 if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
5958 q || (rm & 1)) {
5959 return 1;
5961 tmp = tcg_temp_new_i32();
5962 tmp2 = tcg_temp_new_i32();
5963 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
5964 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5965 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
5966 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
5967 tcg_gen_shli_i32(tmp2, tmp2, 16);
5968 tcg_gen_or_i32(tmp2, tmp2, tmp);
5969 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
5970 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5971 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
5972 neon_store_reg(rd, 0, tmp2);
5973 tmp2 = tcg_temp_new_i32();
5974 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
5975 tcg_gen_shli_i32(tmp2, tmp2, 16);
5976 tcg_gen_or_i32(tmp2, tmp2, tmp);
5977 neon_store_reg(rd, 1, tmp2);
5978 tcg_temp_free_i32(tmp);
5979 break;
5980 case NEON_2RM_VCVT_F32_F16:
5981 if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
5982 q || (rd & 1)) {
5983 return 1;
5985 tmp3 = tcg_temp_new_i32();
5986 tmp = neon_load_reg(rm, 0);
5987 tmp2 = neon_load_reg(rm, 1);
5988 tcg_gen_ext16u_i32(tmp3, tmp);
5989 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5990 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
5991 tcg_gen_shri_i32(tmp3, tmp, 16);
5992 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5993 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
5994 tcg_temp_free_i32(tmp);
5995 tcg_gen_ext16u_i32(tmp3, tmp2);
5996 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5997 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
5998 tcg_gen_shri_i32(tmp3, tmp2, 16);
5999 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6000 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
6001 tcg_temp_free_i32(tmp2);
6002 tcg_temp_free_i32(tmp3);
6003 break;
6004 default:
6005 elementwise:
6006 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6007 if (neon_2rm_is_float_op(op)) {
6008 tcg_gen_ld_f32(cpu_F0s, cpu_env,
6009 neon_reg_offset(rm, pass));
6010 TCGV_UNUSED(tmp);
6011 } else {
6012 tmp = neon_load_reg(rm, pass);
6014 switch (op) {
6015 case NEON_2RM_VREV32:
6016 switch (size) {
6017 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6018 case 1: gen_swap_half(tmp); break;
6019 default: abort();
6021 break;
6022 case NEON_2RM_VREV16:
6023 gen_rev16(tmp);
6024 break;
6025 case NEON_2RM_VCLS:
6026 switch (size) {
6027 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
6028 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
6029 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
6030 default: abort();
6032 break;
6033 case NEON_2RM_VCLZ:
6034 switch (size) {
6035 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
6036 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
6037 case 2: gen_helper_clz(tmp, tmp); break;
6038 default: abort();
6040 break;
6041 case NEON_2RM_VCNT:
6042 gen_helper_neon_cnt_u8(tmp, tmp);
6043 break;
6044 case NEON_2RM_VMVN:
6045 tcg_gen_not_i32(tmp, tmp);
6046 break;
6047 case NEON_2RM_VQABS:
6048 switch (size) {
6049 case 0:
6050 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
6051 break;
6052 case 1:
6053 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
6054 break;
6055 case 2:
6056 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
6057 break;
6058 default: abort();
6060 break;
6061 case NEON_2RM_VQNEG:
6062 switch (size) {
6063 case 0:
6064 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
6065 break;
6066 case 1:
6067 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
6068 break;
6069 case 2:
6070 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
6071 break;
6072 default: abort();
6074 break;
6075 case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
6076 tmp2 = tcg_const_i32(0);
6077 switch(size) {
6078 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
6079 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
6080 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
6081 default: abort();
6083 tcg_temp_free(tmp2);
6084 if (op == NEON_2RM_VCLE0) {
6085 tcg_gen_not_i32(tmp, tmp);
6087 break;
6088 case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
6089 tmp2 = tcg_const_i32(0);
6090 switch(size) {
6091 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
6092 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
6093 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
6094 default: abort();
6096 tcg_temp_free(tmp2);
6097 if (op == NEON_2RM_VCLT0) {
6098 tcg_gen_not_i32(tmp, tmp);
6100 break;
6101 case NEON_2RM_VCEQ0:
6102 tmp2 = tcg_const_i32(0);
6103 switch(size) {
6104 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
6105 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
6106 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
6107 default: abort();
6109 tcg_temp_free(tmp2);
6110 break;
6111 case NEON_2RM_VABS:
6112 switch(size) {
6113 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
6114 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
6115 case 2: tcg_gen_abs_i32(tmp, tmp); break;
6116 default: abort();
6118 break;
6119 case NEON_2RM_VNEG:
6120 tmp2 = tcg_const_i32(0);
6121 gen_neon_rsb(size, tmp, tmp2);
6122 tcg_temp_free(tmp2);
6123 break;
6124 case NEON_2RM_VCGT0_F:
6126 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6127 tmp2 = tcg_const_i32(0);
6128 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
6129 tcg_temp_free(tmp2);
6130 tcg_temp_free_ptr(fpstatus);
6131 break;
6133 case NEON_2RM_VCGE0_F:
6135 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6136 tmp2 = tcg_const_i32(0);
6137 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
6138 tcg_temp_free(tmp2);
6139 tcg_temp_free_ptr(fpstatus);
6140 break;
6142 case NEON_2RM_VCEQ0_F:
6144 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6145 tmp2 = tcg_const_i32(0);
6146 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
6147 tcg_temp_free(tmp2);
6148 tcg_temp_free_ptr(fpstatus);
6149 break;
6151 case NEON_2RM_VCLE0_F:
6153 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6154 tmp2 = tcg_const_i32(0);
6155 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
6156 tcg_temp_free(tmp2);
6157 tcg_temp_free_ptr(fpstatus);
6158 break;
6160 case NEON_2RM_VCLT0_F:
6162 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6163 tmp2 = tcg_const_i32(0);
6164 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
6165 tcg_temp_free(tmp2);
6166 tcg_temp_free_ptr(fpstatus);
6167 break;
6169 case NEON_2RM_VABS_F:
6170 gen_vfp_abs(0);
6171 break;
6172 case NEON_2RM_VNEG_F:
6173 gen_vfp_neg(0);
6174 break;
6175 case NEON_2RM_VSWP:
6176 tmp2 = neon_load_reg(rd, pass);
6177 neon_store_reg(rm, pass, tmp2);
6178 break;
6179 case NEON_2RM_VTRN:
6180 tmp2 = neon_load_reg(rd, pass);
6181 switch (size) {
6182 case 0: gen_neon_trn_u8(tmp, tmp2); break;
6183 case 1: gen_neon_trn_u16(tmp, tmp2); break;
6184 default: abort();
6186 neon_store_reg(rm, pass, tmp2);
6187 break;
6188 case NEON_2RM_VRECPE:
6189 gen_helper_recpe_u32(tmp, tmp, cpu_env);
6190 break;
6191 case NEON_2RM_VRSQRTE:
6192 gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
6193 break;
6194 case NEON_2RM_VRECPE_F:
6195 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
6196 break;
6197 case NEON_2RM_VRSQRTE_F:
6198 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
6199 break;
6200 case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
6201 gen_vfp_sito(0, 1);
6202 break;
6203 case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
6204 gen_vfp_uito(0, 1);
6205 break;
6206 case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
6207 gen_vfp_tosiz(0, 1);
6208 break;
6209 case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
6210 gen_vfp_touiz(0, 1);
6211 break;
6212 default:
6213 /* Reserved op values were caught by the
6214 * neon_2rm_sizes[] check earlier.
6216 abort();
6218 if (neon_2rm_is_float_op(op)) {
6219 tcg_gen_st_f32(cpu_F0s, cpu_env,
6220 neon_reg_offset(rd, pass));
6221 } else {
6222 neon_store_reg(rd, pass, tmp);
6225 break;
6227 } else if ((insn & (1 << 10)) == 0) {
6228 /* VTBL, VTBX. */
6229 int n = ((insn >> 8) & 3) + 1;
6230 if ((rn + n) > 32) {
6231 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
6232 * helper function running off the end of the register file.
6234 return 1;
6236 n <<= 3;
6237 if (insn & (1 << 6)) {
6238 tmp = neon_load_reg(rd, 0);
6239 } else {
6240 tmp = tcg_temp_new_i32();
6241 tcg_gen_movi_i32(tmp, 0);
6243 tmp2 = neon_load_reg(rm, 0);
6244 tmp4 = tcg_const_i32(rn);
6245 tmp5 = tcg_const_i32(n);
6246 gen_helper_neon_tbl(tmp2, tmp2, tmp, tmp4, tmp5);
6247 tcg_temp_free_i32(tmp);
6248 if (insn & (1 << 6)) {
6249 tmp = neon_load_reg(rd, 1);
6250 } else {
6251 tmp = tcg_temp_new_i32();
6252 tcg_gen_movi_i32(tmp, 0);
6254 tmp3 = neon_load_reg(rm, 1);
6255 gen_helper_neon_tbl(tmp3, tmp3, tmp, tmp4, tmp5);
6256 tcg_temp_free_i32(tmp5);
6257 tcg_temp_free_i32(tmp4);
6258 neon_store_reg(rd, 0, tmp2);
6259 neon_store_reg(rd, 1, tmp3);
6260 tcg_temp_free_i32(tmp);
6261 } else if ((insn & 0x380) == 0) {
6262 /* VDUP */
6263 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
6264 return 1;
6266 if (insn & (1 << 19)) {
6267 tmp = neon_load_reg(rm, 1);
6268 } else {
6269 tmp = neon_load_reg(rm, 0);
6271 if (insn & (1 << 16)) {
6272 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
6273 } else if (insn & (1 << 17)) {
6274 if ((insn >> 18) & 1)
6275 gen_neon_dup_high16(tmp);
6276 else
6277 gen_neon_dup_low16(tmp);
6279 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6280 tmp2 = tcg_temp_new_i32();
6281 tcg_gen_mov_i32(tmp2, tmp);
6282 neon_store_reg(rd, pass, tmp2);
6284 tcg_temp_free_i32(tmp);
6285 } else {
6286 return 1;
6290 return 0;
6293 static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
6295 int crn = (insn >> 16) & 0xf;
6296 int crm = insn & 0xf;
6297 int op1 = (insn >> 21) & 7;
6298 int op2 = (insn >> 5) & 7;
6299 int rt = (insn >> 12) & 0xf;
6300 TCGv tmp;
6302 /* Minimal set of debug registers, since we don't support debug */
6303 if (op1 == 0 && crn == 0 && op2 == 0) {
6304 switch (crm) {
6305 case 0:
6306 /* DBGDIDR: just RAZ. In particular this means the
6307 * "debug architecture version" bits will read as
6308 * a reserved value, which should cause Linux to
6309 * not try to use the debug hardware.
6311 tmp = tcg_const_i32(0);
6312 store_reg(s, rt, tmp);
6313 return 0;
6314 case 1:
6315 case 2:
6316 /* DBGDRAR and DBGDSAR: v7 only. Always RAZ since we
6317 * don't implement memory mapped debug components
6319 if (ENABLE_ARCH_7) {
6320 tmp = tcg_const_i32(0);
6321 store_reg(s, rt, tmp);
6322 return 0;
6324 break;
6325 default:
6326 break;
6330 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
6331 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
6332 /* TEECR */
6333 if (IS_USER(s))
6334 return 1;
6335 tmp = load_cpu_field(teecr);
6336 store_reg(s, rt, tmp);
6337 return 0;
6339 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
6340 /* TEEHBR */
6341 if (IS_USER(s) && (env->teecr & 1))
6342 return 1;
6343 tmp = load_cpu_field(teehbr);
6344 store_reg(s, rt, tmp);
6345 return 0;
6348 fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
6349 op1, crn, crm, op2);
6350 return 1;
6353 static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
6355 int crn = (insn >> 16) & 0xf;
6356 int crm = insn & 0xf;
6357 int op1 = (insn >> 21) & 7;
6358 int op2 = (insn >> 5) & 7;
6359 int rt = (insn >> 12) & 0xf;
6360 TCGv tmp;
6362 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
6363 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
6364 /* TEECR */
6365 if (IS_USER(s))
6366 return 1;
6367 tmp = load_reg(s, rt);
6368 gen_helper_set_teecr(cpu_env, tmp);
6369 tcg_temp_free_i32(tmp);
6370 return 0;
6372 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
6373 /* TEEHBR */
6374 if (IS_USER(s) && (env->teecr & 1))
6375 return 1;
6376 tmp = load_reg(s, rt);
6377 store_cpu_field(tmp, teehbr);
6378 return 0;
6381 fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
6382 op1, crn, crm, op2);
6383 return 1;
6386 static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
6388 int cpnum;
6390 cpnum = (insn >> 8) & 0xf;
6391 if (arm_feature(env, ARM_FEATURE_XSCALE)
6392 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
6393 return 1;
6395 switch (cpnum) {
6396 case 0:
6397 case 1:
6398 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
6399 return disas_iwmmxt_insn(env, s, insn);
6400 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
6401 return disas_dsp_insn(env, s, insn);
6403 return 1;
6404 case 10:
6405 case 11:
6406 return disas_vfp_insn (env, s, insn);
6407 case 14:
6408 /* Coprocessors 7-15 are architecturally reserved by ARM.
6409 Unfortunately Intel decided to ignore this. */
6410 if (arm_feature(env, ARM_FEATURE_XSCALE))
6411 goto board;
6412 if (insn & (1 << 20))
6413 return disas_cp14_read(env, s, insn);
6414 else
6415 return disas_cp14_write(env, s, insn);
6416 case 15:
6417 return disas_cp15_insn (env, s, insn);
6418 default:
6419 board:
6420 /* Unknown coprocessor. See if the board has hooked it. */
6421 return disas_cp_insn (env, s, insn);
6426 /* Store a 64-bit value to a register pair. Clobbers val. */
6427 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
6429 TCGv tmp;
6430 tmp = tcg_temp_new_i32();
6431 tcg_gen_trunc_i64_i32(tmp, val);
6432 store_reg(s, rlow, tmp);
6433 tmp = tcg_temp_new_i32();
6434 tcg_gen_shri_i64(val, val, 32);
6435 tcg_gen_trunc_i64_i32(tmp, val);
6436 store_reg(s, rhigh, tmp);
6439 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
6440 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
6442 TCGv_i64 tmp;
6443 TCGv tmp2;
6445 /* Load value and extend to 64 bits. */
6446 tmp = tcg_temp_new_i64();
6447 tmp2 = load_reg(s, rlow);
6448 tcg_gen_extu_i32_i64(tmp, tmp2);
6449 tcg_temp_free_i32(tmp2);
6450 tcg_gen_add_i64(val, val, tmp);
6451 tcg_temp_free_i64(tmp);
6454 /* load and add a 64-bit value from a register pair. */
6455 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
6457 TCGv_i64 tmp;
6458 TCGv tmpl;
6459 TCGv tmph;
6461 /* Load 64-bit value rd:rn. */
6462 tmpl = load_reg(s, rlow);
6463 tmph = load_reg(s, rhigh);
6464 tmp = tcg_temp_new_i64();
6465 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
6466 tcg_temp_free_i32(tmpl);
6467 tcg_temp_free_i32(tmph);
6468 tcg_gen_add_i64(val, val, tmp);
6469 tcg_temp_free_i64(tmp);
6472 /* Set N and Z flags from a 64-bit value. */
6473 static void gen_logicq_cc(TCGv_i64 val)
6475 TCGv tmp = tcg_temp_new_i32();
6476 gen_helper_logicq_cc(tmp, val);
6477 gen_logic_CC(tmp);
6478 tcg_temp_free_i32(tmp);
6481 /* Load/Store exclusive instructions are implemented by remembering
6482 the value/address loaded, and seeing if these are the same
6483 when the store is performed. This should be is sufficient to implement
6484 the architecturally mandated semantics, and avoids having to monitor
6485 regular stores.
6487 In system emulation mode only one CPU will be running at once, so
6488 this sequence is effectively atomic. In user emulation mode we
6489 throw an exception and handle the atomic operation elsewhere. */
6490 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
6491 TCGv addr, int size)
6493 TCGv tmp;
6495 switch (size) {
6496 case 0:
6497 tmp = gen_ld8u(addr, IS_USER(s));
6498 break;
6499 case 1:
6500 tmp = gen_ld16u(addr, IS_USER(s));
6501 break;
6502 case 2:
6503 case 3:
6504 tmp = gen_ld32(addr, IS_USER(s));
6505 break;
6506 default:
6507 abort();
6509 tcg_gen_mov_i32(cpu_exclusive_val, tmp);
6510 store_reg(s, rt, tmp);
6511 if (size == 3) {
6512 TCGv tmp2 = tcg_temp_new_i32();
6513 tcg_gen_addi_i32(tmp2, addr, 4);
6514 tmp = gen_ld32(tmp2, IS_USER(s));
6515 tcg_temp_free_i32(tmp2);
6516 tcg_gen_mov_i32(cpu_exclusive_high, tmp);
6517 store_reg(s, rt2, tmp);
6519 tcg_gen_mov_i32(cpu_exclusive_addr, addr);
6522 static void gen_clrex(DisasContext *s)
6524 tcg_gen_movi_i32(cpu_exclusive_addr, -1);
6527 #ifdef CONFIG_USER_ONLY
6528 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
6529 TCGv addr, int size)
6531 tcg_gen_mov_i32(cpu_exclusive_test, addr);
6532 tcg_gen_movi_i32(cpu_exclusive_info,
6533 size | (rd << 4) | (rt << 8) | (rt2 << 12));
6534 gen_exception_insn(s, 4, EXCP_STREX);
6536 #else
6537 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
6538 TCGv addr, int size)
6540 TCGv tmp;
6541 int done_label;
6542 int fail_label;
6544 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
6545 [addr] = {Rt};
6546 {Rd} = 0;
6547 } else {
6548 {Rd} = 1;
6549 } */
6550 fail_label = gen_new_label();
6551 done_label = gen_new_label();
6552 tcg_gen_brcond_i32(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
6553 switch (size) {
6554 case 0:
6555 tmp = gen_ld8u(addr, IS_USER(s));
6556 break;
6557 case 1:
6558 tmp = gen_ld16u(addr, IS_USER(s));
6559 break;
6560 case 2:
6561 case 3:
6562 tmp = gen_ld32(addr, IS_USER(s));
6563 break;
6564 default:
6565 abort();
6567 tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label);
6568 tcg_temp_free_i32(tmp);
6569 if (size == 3) {
6570 TCGv tmp2 = tcg_temp_new_i32();
6571 tcg_gen_addi_i32(tmp2, addr, 4);
6572 tmp = gen_ld32(tmp2, IS_USER(s));
6573 tcg_temp_free_i32(tmp2);
6574 tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_high, fail_label);
6575 tcg_temp_free_i32(tmp);
6577 tmp = load_reg(s, rt);
6578 switch (size) {
6579 case 0:
6580 gen_st8(tmp, addr, IS_USER(s));
6581 break;
6582 case 1:
6583 gen_st16(tmp, addr, IS_USER(s));
6584 break;
6585 case 2:
6586 case 3:
6587 gen_st32(tmp, addr, IS_USER(s));
6588 break;
6589 default:
6590 abort();
6592 if (size == 3) {
6593 tcg_gen_addi_i32(addr, addr, 4);
6594 tmp = load_reg(s, rt2);
6595 gen_st32(tmp, addr, IS_USER(s));
6597 tcg_gen_movi_i32(cpu_R[rd], 0);
6598 tcg_gen_br(done_label);
6599 gen_set_label(fail_label);
6600 tcg_gen_movi_i32(cpu_R[rd], 1);
6601 gen_set_label(done_label);
6602 tcg_gen_movi_i32(cpu_exclusive_addr, -1);
6604 #endif
6606 static void disas_arm_insn(CPUState * env, DisasContext *s)
6608 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
6609 TCGv tmp;
6610 TCGv tmp2;
6611 TCGv tmp3;
6612 TCGv addr;
6613 TCGv_i64 tmp64;
6615 insn = ldl_code(s->pc);
6616 s->pc += 4;
6618 /* M variants do not implement ARM mode. */
6619 if (IS_M(env))
6620 goto illegal_op;
6621 cond = insn >> 28;
6622 if (cond == 0xf){
6623 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
6624 * choose to UNDEF. In ARMv5 and above the space is used
6625 * for miscellaneous unconditional instructions.
6627 ARCH(5);
6629 /* Unconditional instructions. */
6630 if (((insn >> 25) & 7) == 1) {
6631 /* NEON Data processing. */
6632 if (!arm_feature(env, ARM_FEATURE_NEON))
6633 goto illegal_op;
6635 if (disas_neon_data_insn(env, s, insn))
6636 goto illegal_op;
6637 return;
6639 if ((insn & 0x0f100000) == 0x04000000) {
6640 /* NEON load/store. */
6641 if (!arm_feature(env, ARM_FEATURE_NEON))
6642 goto illegal_op;
6644 if (disas_neon_ls_insn(env, s, insn))
6645 goto illegal_op;
6646 return;
6648 if (((insn & 0x0f30f000) == 0x0510f000) ||
6649 ((insn & 0x0f30f010) == 0x0710f000)) {
6650 if ((insn & (1 << 22)) == 0) {
6651 /* PLDW; v7MP */
6652 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
6653 goto illegal_op;
6656 /* Otherwise PLD; v5TE+ */
6657 ARCH(5TE);
6658 return;
6660 if (((insn & 0x0f70f000) == 0x0450f000) ||
6661 ((insn & 0x0f70f010) == 0x0650f000)) {
6662 ARCH(7);
6663 return; /* PLI; V7 */
6665 if (((insn & 0x0f700000) == 0x04100000) ||
6666 ((insn & 0x0f700010) == 0x06100000)) {
6667 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
6668 goto illegal_op;
6670 return; /* v7MP: Unallocated memory hint: must NOP */
6673 if ((insn & 0x0ffffdff) == 0x01010000) {
6674 ARCH(6);
6675 /* setend */
6676 if (insn & (1 << 9)) {
6677 /* BE8 mode not implemented. */
6678 goto illegal_op;
6680 return;
6681 } else if ((insn & 0x0fffff00) == 0x057ff000) {
6682 switch ((insn >> 4) & 0xf) {
6683 case 1: /* clrex */
6684 ARCH(6K);
6685 gen_clrex(s);
6686 return;
6687 case 4: /* dsb */
6688 case 5: /* dmb */
6689 case 6: /* isb */
6690 ARCH(7);
6691 /* We don't emulate caches so these are a no-op. */
6692 return;
6693 default:
6694 goto illegal_op;
6696 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
6697 /* srs */
6698 int32_t offset;
6699 if (IS_USER(s))
6700 goto illegal_op;
6701 ARCH(6);
6702 op1 = (insn & 0x1f);
6703 addr = tcg_temp_new_i32();
6704 tmp = tcg_const_i32(op1);
6705 gen_helper_get_r13_banked(addr, cpu_env, tmp);
6706 tcg_temp_free_i32(tmp);
6707 i = (insn >> 23) & 3;
6708 switch (i) {
6709 case 0: offset = -4; break; /* DA */
6710 case 1: offset = 0; break; /* IA */
6711 case 2: offset = -8; break; /* DB */
6712 case 3: offset = 4; break; /* IB */
6713 default: abort();
6715 if (offset)
6716 tcg_gen_addi_i32(addr, addr, offset);
6717 tmp = load_reg(s, 14);
6718 gen_st32(tmp, addr, 0);
6719 tmp = load_cpu_field(spsr);
6720 tcg_gen_addi_i32(addr, addr, 4);
6721 gen_st32(tmp, addr, 0);
6722 if (insn & (1 << 21)) {
6723 /* Base writeback. */
6724 switch (i) {
6725 case 0: offset = -8; break;
6726 case 1: offset = 4; break;
6727 case 2: offset = -4; break;
6728 case 3: offset = 0; break;
6729 default: abort();
6731 if (offset)
6732 tcg_gen_addi_i32(addr, addr, offset);
6733 tmp = tcg_const_i32(op1);
6734 gen_helper_set_r13_banked(cpu_env, tmp, addr);
6735 tcg_temp_free_i32(tmp);
6736 tcg_temp_free_i32(addr);
6737 } else {
6738 tcg_temp_free_i32(addr);
6740 return;
6741 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
6742 /* rfe */
6743 int32_t offset;
6744 if (IS_USER(s))
6745 goto illegal_op;
6746 ARCH(6);
6747 rn = (insn >> 16) & 0xf;
6748 addr = load_reg(s, rn);
6749 i = (insn >> 23) & 3;
6750 switch (i) {
6751 case 0: offset = -4; break; /* DA */
6752 case 1: offset = 0; break; /* IA */
6753 case 2: offset = -8; break; /* DB */
6754 case 3: offset = 4; break; /* IB */
6755 default: abort();
6757 if (offset)
6758 tcg_gen_addi_i32(addr, addr, offset);
6759 /* Load PC into tmp and CPSR into tmp2. */
6760 tmp = gen_ld32(addr, 0);
6761 tcg_gen_addi_i32(addr, addr, 4);
6762 tmp2 = gen_ld32(addr, 0);
6763 if (insn & (1 << 21)) {
6764 /* Base writeback. */
6765 switch (i) {
6766 case 0: offset = -8; break;
6767 case 1: offset = 4; break;
6768 case 2: offset = -4; break;
6769 case 3: offset = 0; break;
6770 default: abort();
6772 if (offset)
6773 tcg_gen_addi_i32(addr, addr, offset);
6774 store_reg(s, rn, addr);
6775 } else {
6776 tcg_temp_free_i32(addr);
6778 gen_rfe(s, tmp, tmp2);
6779 return;
6780 } else if ((insn & 0x0e000000) == 0x0a000000) {
6781 /* branch link and change to thumb (blx <offset>) */
6782 int32_t offset;
6784 val = (uint32_t)s->pc;
6785 tmp = tcg_temp_new_i32();
6786 tcg_gen_movi_i32(tmp, val);
6787 store_reg(s, 14, tmp);
6788 /* Sign-extend the 24-bit offset */
6789 offset = (((int32_t)insn) << 8) >> 8;
6790 /* offset * 4 + bit24 * 2 + (thumb bit) */
6791 val += (offset << 2) | ((insn >> 23) & 2) | 1;
6792 /* pipeline offset */
6793 val += 4;
6794 /* protected by ARCH(5); above, near the start of uncond block */
6795 gen_bx_im(s, val);
6796 return;
6797 } else if ((insn & 0x0e000f00) == 0x0c000100) {
6798 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
6799 /* iWMMXt register transfer. */
6800 if (env->cp15.c15_cpar & (1 << 1))
6801 if (!disas_iwmmxt_insn(env, s, insn))
6802 return;
6804 } else if ((insn & 0x0fe00000) == 0x0c400000) {
6805 /* Coprocessor double register transfer. */
6806 ARCH(5TE);
6807 } else if ((insn & 0x0f000010) == 0x0e000010) {
6808 /* Additional coprocessor register transfer. */
6809 } else if ((insn & 0x0ff10020) == 0x01000000) {
6810 uint32_t mask;
6811 uint32_t val;
6812 /* cps (privileged) */
6813 if (IS_USER(s))
6814 return;
6815 mask = val = 0;
6816 if (insn & (1 << 19)) {
6817 if (insn & (1 << 8))
6818 mask |= CPSR_A;
6819 if (insn & (1 << 7))
6820 mask |= CPSR_I;
6821 if (insn & (1 << 6))
6822 mask |= CPSR_F;
6823 if (insn & (1 << 18))
6824 val |= mask;
6826 if (insn & (1 << 17)) {
6827 mask |= CPSR_M;
6828 val |= (insn & 0x1f);
6830 if (mask) {
6831 gen_set_psr_im(s, mask, 0, val);
6833 return;
6835 goto illegal_op;
6837 if (cond != 0xe) {
6838 /* if not always execute, we generate a conditional jump to
6839 next instruction */
6840 s->condlabel = gen_new_label();
6841 gen_test_cc(cond ^ 1, s->condlabel);
6842 s->condjmp = 1;
6844 if ((insn & 0x0f900000) == 0x03000000) {
6845 if ((insn & (1 << 21)) == 0) {
6846 ARCH(6T2);
6847 rd = (insn >> 12) & 0xf;
6848 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
6849 if ((insn & (1 << 22)) == 0) {
6850 /* MOVW */
6851 tmp = tcg_temp_new_i32();
6852 tcg_gen_movi_i32(tmp, val);
6853 } else {
6854 /* MOVT */
6855 tmp = load_reg(s, rd);
6856 tcg_gen_ext16u_i32(tmp, tmp);
6857 tcg_gen_ori_i32(tmp, tmp, val << 16);
6859 store_reg(s, rd, tmp);
6860 } else {
6861 if (((insn >> 12) & 0xf) != 0xf)
6862 goto illegal_op;
6863 if (((insn >> 16) & 0xf) == 0) {
6864 gen_nop_hint(s, insn & 0xff);
6865 } else {
6866 /* CPSR = immediate */
6867 val = insn & 0xff;
6868 shift = ((insn >> 8) & 0xf) * 2;
6869 if (shift)
6870 val = (val >> shift) | (val << (32 - shift));
6871 i = ((insn & (1 << 22)) != 0);
6872 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
6873 goto illegal_op;
6876 } else if ((insn & 0x0f900000) == 0x01000000
6877 && (insn & 0x00000090) != 0x00000090) {
6878 /* miscellaneous instructions */
6879 op1 = (insn >> 21) & 3;
6880 sh = (insn >> 4) & 0xf;
6881 rm = insn & 0xf;
6882 switch (sh) {
6883 case 0x0: /* move program status register */
6884 if (op1 & 1) {
6885 /* PSR = reg */
6886 tmp = load_reg(s, rm);
6887 i = ((op1 & 2) != 0);
6888 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
6889 goto illegal_op;
6890 } else {
6891 /* reg = PSR */
6892 rd = (insn >> 12) & 0xf;
6893 if (op1 & 2) {
6894 if (IS_USER(s))
6895 goto illegal_op;
6896 tmp = load_cpu_field(spsr);
6897 } else {
6898 tmp = tcg_temp_new_i32();
6899 gen_helper_cpsr_read(tmp);
6901 store_reg(s, rd, tmp);
6903 break;
6904 case 0x1:
6905 if (op1 == 1) {
6906 /* branch/exchange thumb (bx). */
6907 ARCH(4T);
6908 tmp = load_reg(s, rm);
6909 gen_bx(s, tmp);
6910 } else if (op1 == 3) {
6911 /* clz */
6912 ARCH(5);
6913 rd = (insn >> 12) & 0xf;
6914 tmp = load_reg(s, rm);
6915 gen_helper_clz(tmp, tmp);
6916 store_reg(s, rd, tmp);
6917 } else {
6918 goto illegal_op;
6920 break;
6921 case 0x2:
6922 if (op1 == 1) {
6923 ARCH(5J); /* bxj */
6924 /* Trivial implementation equivalent to bx. */
6925 tmp = load_reg(s, rm);
6926 gen_bx(s, tmp);
6927 } else {
6928 goto illegal_op;
6930 break;
6931 case 0x3:
6932 if (op1 != 1)
6933 goto illegal_op;
6935 ARCH(5);
6936 /* branch link/exchange thumb (blx) */
6937 tmp = load_reg(s, rm);
6938 tmp2 = tcg_temp_new_i32();
6939 tcg_gen_movi_i32(tmp2, s->pc);
6940 store_reg(s, 14, tmp2);
6941 gen_bx(s, tmp);
6942 break;
6943 case 0x5: /* saturating add/subtract */
6944 ARCH(5TE);
6945 rd = (insn >> 12) & 0xf;
6946 rn = (insn >> 16) & 0xf;
6947 tmp = load_reg(s, rm);
6948 tmp2 = load_reg(s, rn);
6949 if (op1 & 2)
6950 gen_helper_double_saturate(tmp2, tmp2);
6951 if (op1 & 1)
6952 gen_helper_sub_saturate(tmp, tmp, tmp2);
6953 else
6954 gen_helper_add_saturate(tmp, tmp, tmp2);
6955 tcg_temp_free_i32(tmp2);
6956 store_reg(s, rd, tmp);
6957 break;
6958 case 7:
6959 /* SMC instruction (op1 == 3)
6960 and undefined instructions (op1 == 0 || op1 == 2)
6961 will trap */
6962 if (op1 != 1) {
6963 goto illegal_op;
6965 /* bkpt */
6966 ARCH(5);
6967 gen_exception_insn(s, 4, EXCP_BKPT);
6968 break;
6969 case 0x8: /* signed multiply */
6970 case 0xa:
6971 case 0xc:
6972 case 0xe:
6973 ARCH(5TE);
6974 rs = (insn >> 8) & 0xf;
6975 rn = (insn >> 12) & 0xf;
6976 rd = (insn >> 16) & 0xf;
6977 if (op1 == 1) {
6978 /* (32 * 16) >> 16 */
6979 tmp = load_reg(s, rm);
6980 tmp2 = load_reg(s, rs);
6981 if (sh & 4)
6982 tcg_gen_sari_i32(tmp2, tmp2, 16);
6983 else
6984 gen_sxth(tmp2);
6985 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6986 tcg_gen_shri_i64(tmp64, tmp64, 16);
6987 tmp = tcg_temp_new_i32();
6988 tcg_gen_trunc_i64_i32(tmp, tmp64);
6989 tcg_temp_free_i64(tmp64);
6990 if ((sh & 2) == 0) {
6991 tmp2 = load_reg(s, rn);
6992 gen_helper_add_setq(tmp, tmp, tmp2);
6993 tcg_temp_free_i32(tmp2);
6995 store_reg(s, rd, tmp);
6996 } else {
6997 /* 16 * 16 */
6998 tmp = load_reg(s, rm);
6999 tmp2 = load_reg(s, rs);
7000 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
7001 tcg_temp_free_i32(tmp2);
7002 if (op1 == 2) {
7003 tmp64 = tcg_temp_new_i64();
7004 tcg_gen_ext_i32_i64(tmp64, tmp);
7005 tcg_temp_free_i32(tmp);
7006 gen_addq(s, tmp64, rn, rd);
7007 gen_storeq_reg(s, rn, rd, tmp64);
7008 tcg_temp_free_i64(tmp64);
7009 } else {
7010 if (op1 == 0) {
7011 tmp2 = load_reg(s, rn);
7012 gen_helper_add_setq(tmp, tmp, tmp2);
7013 tcg_temp_free_i32(tmp2);
7015 store_reg(s, rd, tmp);
7018 break;
7019 default:
7020 goto illegal_op;
7022 } else if (((insn & 0x0e000000) == 0 &&
7023 (insn & 0x00000090) != 0x90) ||
7024 ((insn & 0x0e000000) == (1 << 25))) {
7025 int set_cc, logic_cc, shiftop;
7027 op1 = (insn >> 21) & 0xf;
7028 set_cc = (insn >> 20) & 1;
7029 logic_cc = table_logic_cc[op1] & set_cc;
7031 /* data processing instruction */
7032 if (insn & (1 << 25)) {
7033 /* immediate operand */
7034 val = insn & 0xff;
7035 shift = ((insn >> 8) & 0xf) * 2;
7036 if (shift) {
7037 val = (val >> shift) | (val << (32 - shift));
7039 tmp2 = tcg_temp_new_i32();
7040 tcg_gen_movi_i32(tmp2, val);
7041 if (logic_cc && shift) {
7042 gen_set_CF_bit31(tmp2);
7044 } else {
7045 /* register */
7046 rm = (insn) & 0xf;
7047 tmp2 = load_reg(s, rm);
7048 shiftop = (insn >> 5) & 3;
7049 if (!(insn & (1 << 4))) {
7050 shift = (insn >> 7) & 0x1f;
7051 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
7052 } else {
7053 rs = (insn >> 8) & 0xf;
7054 tmp = load_reg(s, rs);
7055 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
7058 if (op1 != 0x0f && op1 != 0x0d) {
7059 rn = (insn >> 16) & 0xf;
7060 tmp = load_reg(s, rn);
7061 } else {
7062 TCGV_UNUSED(tmp);
7064 rd = (insn >> 12) & 0xf;
7065 switch(op1) {
7066 case 0x00:
7067 tcg_gen_and_i32(tmp, tmp, tmp2);
7068 if (logic_cc) {
7069 gen_logic_CC(tmp);
7071 store_reg_bx(env, s, rd, tmp);
7072 break;
7073 case 0x01:
7074 tcg_gen_xor_i32(tmp, tmp, tmp2);
7075 if (logic_cc) {
7076 gen_logic_CC(tmp);
7078 store_reg_bx(env, s, rd, tmp);
7079 break;
7080 case 0x02:
7081 if (set_cc && rd == 15) {
7082 /* SUBS r15, ... is used for exception return. */
7083 if (IS_USER(s)) {
7084 goto illegal_op;
7086 gen_helper_sub_cc(tmp, tmp, tmp2);
7087 gen_exception_return(s, tmp);
7088 } else {
7089 if (set_cc) {
7090 gen_helper_sub_cc(tmp, tmp, tmp2);
7091 } else {
7092 tcg_gen_sub_i32(tmp, tmp, tmp2);
7094 store_reg_bx(env, s, rd, tmp);
7096 break;
7097 case 0x03:
7098 if (set_cc) {
7099 gen_helper_sub_cc(tmp, tmp2, tmp);
7100 } else {
7101 tcg_gen_sub_i32(tmp, tmp2, tmp);
7103 store_reg_bx(env, s, rd, tmp);
7104 break;
7105 case 0x04:
7106 if (set_cc) {
7107 gen_helper_add_cc(tmp, tmp, tmp2);
7108 } else {
7109 tcg_gen_add_i32(tmp, tmp, tmp2);
7111 store_reg_bx(env, s, rd, tmp);
7112 break;
7113 case 0x05:
7114 if (set_cc) {
7115 gen_helper_adc_cc(tmp, tmp, tmp2);
7116 } else {
7117 gen_add_carry(tmp, tmp, tmp2);
7119 store_reg_bx(env, s, rd, tmp);
7120 break;
7121 case 0x06:
7122 if (set_cc) {
7123 gen_helper_sbc_cc(tmp, tmp, tmp2);
7124 } else {
7125 gen_sub_carry(tmp, tmp, tmp2);
7127 store_reg_bx(env, s, rd, tmp);
7128 break;
7129 case 0x07:
7130 if (set_cc) {
7131 gen_helper_sbc_cc(tmp, tmp2, tmp);
7132 } else {
7133 gen_sub_carry(tmp, tmp2, tmp);
7135 store_reg_bx(env, s, rd, tmp);
7136 break;
7137 case 0x08:
7138 if (set_cc) {
7139 tcg_gen_and_i32(tmp, tmp, tmp2);
7140 gen_logic_CC(tmp);
7142 tcg_temp_free_i32(tmp);
7143 break;
7144 case 0x09:
7145 if (set_cc) {
7146 tcg_gen_xor_i32(tmp, tmp, tmp2);
7147 gen_logic_CC(tmp);
7149 tcg_temp_free_i32(tmp);
7150 break;
7151 case 0x0a:
7152 if (set_cc) {
7153 gen_helper_sub_cc(tmp, tmp, tmp2);
7155 tcg_temp_free_i32(tmp);
7156 break;
7157 case 0x0b:
7158 if (set_cc) {
7159 gen_helper_add_cc(tmp, tmp, tmp2);
7161 tcg_temp_free_i32(tmp);
7162 break;
7163 case 0x0c:
7164 tcg_gen_or_i32(tmp, tmp, tmp2);
7165 if (logic_cc) {
7166 gen_logic_CC(tmp);
7168 store_reg_bx(env, s, rd, tmp);
7169 break;
7170 case 0x0d:
7171 if (logic_cc && rd == 15) {
7172 /* MOVS r15, ... is used for exception return. */
7173 if (IS_USER(s)) {
7174 goto illegal_op;
7176 gen_exception_return(s, tmp2);
7177 } else {
7178 if (logic_cc) {
7179 gen_logic_CC(tmp2);
7181 store_reg_bx(env, s, rd, tmp2);
7183 break;
7184 case 0x0e:
7185 tcg_gen_andc_i32(tmp, tmp, tmp2);
7186 if (logic_cc) {
7187 gen_logic_CC(tmp);
7189 store_reg_bx(env, s, rd, tmp);
7190 break;
7191 default:
7192 case 0x0f:
7193 tcg_gen_not_i32(tmp2, tmp2);
7194 if (logic_cc) {
7195 gen_logic_CC(tmp2);
7197 store_reg_bx(env, s, rd, tmp2);
7198 break;
7200 if (op1 != 0x0f && op1 != 0x0d) {
7201 tcg_temp_free_i32(tmp2);
7203 } else {
7204 /* other instructions */
7205 op1 = (insn >> 24) & 0xf;
7206 switch(op1) {
7207 case 0x0:
7208 case 0x1:
7209 /* multiplies, extra load/stores */
7210 sh = (insn >> 5) & 3;
7211 if (sh == 0) {
7212 if (op1 == 0x0) {
7213 rd = (insn >> 16) & 0xf;
7214 rn = (insn >> 12) & 0xf;
7215 rs = (insn >> 8) & 0xf;
7216 rm = (insn) & 0xf;
7217 op1 = (insn >> 20) & 0xf;
7218 switch (op1) {
7219 case 0: case 1: case 2: case 3: case 6:
7220 /* 32 bit mul */
7221 tmp = load_reg(s, rs);
7222 tmp2 = load_reg(s, rm);
7223 tcg_gen_mul_i32(tmp, tmp, tmp2);
7224 tcg_temp_free_i32(tmp2);
7225 if (insn & (1 << 22)) {
7226 /* Subtract (mls) */
7227 ARCH(6T2);
7228 tmp2 = load_reg(s, rn);
7229 tcg_gen_sub_i32(tmp, tmp2, tmp);
7230 tcg_temp_free_i32(tmp2);
7231 } else if (insn & (1 << 21)) {
7232 /* Add */
7233 tmp2 = load_reg(s, rn);
7234 tcg_gen_add_i32(tmp, tmp, tmp2);
7235 tcg_temp_free_i32(tmp2);
7237 if (insn & (1 << 20))
7238 gen_logic_CC(tmp);
7239 store_reg(s, rd, tmp);
7240 break;
7241 case 4:
7242 /* 64 bit mul double accumulate (UMAAL) */
7243 ARCH(6);
7244 tmp = load_reg(s, rs);
7245 tmp2 = load_reg(s, rm);
7246 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7247 gen_addq_lo(s, tmp64, rn);
7248 gen_addq_lo(s, tmp64, rd);
7249 gen_storeq_reg(s, rn, rd, tmp64);
7250 tcg_temp_free_i64(tmp64);
7251 break;
7252 case 8: case 9: case 10: case 11:
7253 case 12: case 13: case 14: case 15:
7254 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
7255 tmp = load_reg(s, rs);
7256 tmp2 = load_reg(s, rm);
7257 if (insn & (1 << 22)) {
7258 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7259 } else {
7260 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7262 if (insn & (1 << 21)) { /* mult accumulate */
7263 gen_addq(s, tmp64, rn, rd);
7265 if (insn & (1 << 20)) {
7266 gen_logicq_cc(tmp64);
7268 gen_storeq_reg(s, rn, rd, tmp64);
7269 tcg_temp_free_i64(tmp64);
7270 break;
7271 default:
7272 goto illegal_op;
7274 } else {
7275 rn = (insn >> 16) & 0xf;
7276 rd = (insn >> 12) & 0xf;
7277 if (insn & (1 << 23)) {
7278 /* load/store exclusive */
7279 op1 = (insn >> 21) & 0x3;
7280 if (op1)
7281 ARCH(6K);
7282 else
7283 ARCH(6);
7284 addr = tcg_temp_local_new_i32();
7285 load_reg_var(s, addr, rn);
7286 if (insn & (1 << 20)) {
7287 switch (op1) {
7288 case 0: /* ldrex */
7289 gen_load_exclusive(s, rd, 15, addr, 2);
7290 break;
7291 case 1: /* ldrexd */
7292 gen_load_exclusive(s, rd, rd + 1, addr, 3);
7293 break;
7294 case 2: /* ldrexb */
7295 gen_load_exclusive(s, rd, 15, addr, 0);
7296 break;
7297 case 3: /* ldrexh */
7298 gen_load_exclusive(s, rd, 15, addr, 1);
7299 break;
7300 default:
7301 abort();
7303 } else {
7304 rm = insn & 0xf;
7305 switch (op1) {
7306 case 0: /* strex */
7307 gen_store_exclusive(s, rd, rm, 15, addr, 2);
7308 break;
7309 case 1: /* strexd */
7310 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
7311 break;
7312 case 2: /* strexb */
7313 gen_store_exclusive(s, rd, rm, 15, addr, 0);
7314 break;
7315 case 3: /* strexh */
7316 gen_store_exclusive(s, rd, rm, 15, addr, 1);
7317 break;
7318 default:
7319 abort();
7322 tcg_temp_free(addr);
7323 } else {
7324 /* SWP instruction */
7325 rm = (insn) & 0xf;
7327 /* ??? This is not really atomic. However we know
7328 we never have multiple CPUs running in parallel,
7329 so it is good enough. */
7330 addr = load_reg(s, rn);
7331 tmp = load_reg(s, rm);
7332 if (insn & (1 << 22)) {
7333 tmp2 = gen_ld8u(addr, IS_USER(s));
7334 gen_st8(tmp, addr, IS_USER(s));
7335 } else {
7336 tmp2 = gen_ld32(addr, IS_USER(s));
7337 gen_st32(tmp, addr, IS_USER(s));
7339 tcg_temp_free_i32(addr);
7340 store_reg(s, rd, tmp2);
7343 } else {
7344 int address_offset;
7345 int load;
7346 /* Misc load/store */
7347 rn = (insn >> 16) & 0xf;
7348 rd = (insn >> 12) & 0xf;
7349 addr = load_reg(s, rn);
7350 if (insn & (1 << 24))
7351 gen_add_datah_offset(s, insn, 0, addr);
7352 address_offset = 0;
7353 if (insn & (1 << 20)) {
7354 /* load */
7355 switch(sh) {
7356 case 1:
7357 tmp = gen_ld16u(addr, IS_USER(s));
7358 break;
7359 case 2:
7360 tmp = gen_ld8s(addr, IS_USER(s));
7361 break;
7362 default:
7363 case 3:
7364 tmp = gen_ld16s(addr, IS_USER(s));
7365 break;
7367 load = 1;
7368 } else if (sh & 2) {
7369 ARCH(5TE);
7370 /* doubleword */
7371 if (sh & 1) {
7372 /* store */
7373 tmp = load_reg(s, rd);
7374 gen_st32(tmp, addr, IS_USER(s));
7375 tcg_gen_addi_i32(addr, addr, 4);
7376 tmp = load_reg(s, rd + 1);
7377 gen_st32(tmp, addr, IS_USER(s));
7378 load = 0;
7379 } else {
7380 /* load */
7381 tmp = gen_ld32(addr, IS_USER(s));
7382 store_reg(s, rd, tmp);
7383 tcg_gen_addi_i32(addr, addr, 4);
7384 tmp = gen_ld32(addr, IS_USER(s));
7385 rd++;
7386 load = 1;
7388 address_offset = -4;
7389 } else {
7390 /* store */
7391 tmp = load_reg(s, rd);
7392 gen_st16(tmp, addr, IS_USER(s));
7393 load = 0;
7395 /* Perform base writeback before the loaded value to
7396 ensure correct behavior with overlapping index registers.
7397 ldrd with base writeback is is undefined if the
7398 destination and index registers overlap. */
7399 if (!(insn & (1 << 24))) {
7400 gen_add_datah_offset(s, insn, address_offset, addr);
7401 store_reg(s, rn, addr);
7402 } else if (insn & (1 << 21)) {
7403 if (address_offset)
7404 tcg_gen_addi_i32(addr, addr, address_offset);
7405 store_reg(s, rn, addr);
7406 } else {
7407 tcg_temp_free_i32(addr);
7409 if (load) {
7410 /* Complete the load. */
7411 store_reg(s, rd, tmp);
7414 break;
7415 case 0x4:
7416 case 0x5:
7417 goto do_ldst;
7418 case 0x6:
7419 case 0x7:
7420 if (insn & (1 << 4)) {
7421 ARCH(6);
7422 /* Armv6 Media instructions. */
7423 rm = insn & 0xf;
7424 rn = (insn >> 16) & 0xf;
7425 rd = (insn >> 12) & 0xf;
7426 rs = (insn >> 8) & 0xf;
7427 switch ((insn >> 23) & 3) {
7428 case 0: /* Parallel add/subtract. */
7429 op1 = (insn >> 20) & 7;
7430 tmp = load_reg(s, rn);
7431 tmp2 = load_reg(s, rm);
7432 sh = (insn >> 5) & 7;
7433 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
7434 goto illegal_op;
7435 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
7436 tcg_temp_free_i32(tmp2);
7437 store_reg(s, rd, tmp);
7438 break;
7439 case 1:
7440 if ((insn & 0x00700020) == 0) {
7441 /* Halfword pack. */
7442 tmp = load_reg(s, rn);
7443 tmp2 = load_reg(s, rm);
7444 shift = (insn >> 7) & 0x1f;
7445 if (insn & (1 << 6)) {
7446 /* pkhtb */
7447 if (shift == 0)
7448 shift = 31;
7449 tcg_gen_sari_i32(tmp2, tmp2, shift);
7450 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
7451 tcg_gen_ext16u_i32(tmp2, tmp2);
7452 } else {
7453 /* pkhbt */
7454 if (shift)
7455 tcg_gen_shli_i32(tmp2, tmp2, shift);
7456 tcg_gen_ext16u_i32(tmp, tmp);
7457 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
7459 tcg_gen_or_i32(tmp, tmp, tmp2);
7460 tcg_temp_free_i32(tmp2);
7461 store_reg(s, rd, tmp);
7462 } else if ((insn & 0x00200020) == 0x00200000) {
7463 /* [us]sat */
7464 tmp = load_reg(s, rm);
7465 shift = (insn >> 7) & 0x1f;
7466 if (insn & (1 << 6)) {
7467 if (shift == 0)
7468 shift = 31;
7469 tcg_gen_sari_i32(tmp, tmp, shift);
7470 } else {
7471 tcg_gen_shli_i32(tmp, tmp, shift);
7473 sh = (insn >> 16) & 0x1f;
7474 tmp2 = tcg_const_i32(sh);
7475 if (insn & (1 << 22))
7476 gen_helper_usat(tmp, tmp, tmp2);
7477 else
7478 gen_helper_ssat(tmp, tmp, tmp2);
7479 tcg_temp_free_i32(tmp2);
7480 store_reg(s, rd, tmp);
7481 } else if ((insn & 0x00300fe0) == 0x00200f20) {
7482 /* [us]sat16 */
7483 tmp = load_reg(s, rm);
7484 sh = (insn >> 16) & 0x1f;
7485 tmp2 = tcg_const_i32(sh);
7486 if (insn & (1 << 22))
7487 gen_helper_usat16(tmp, tmp, tmp2);
7488 else
7489 gen_helper_ssat16(tmp, tmp, tmp2);
7490 tcg_temp_free_i32(tmp2);
7491 store_reg(s, rd, tmp);
7492 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
7493 /* Select bytes. */
7494 tmp = load_reg(s, rn);
7495 tmp2 = load_reg(s, rm);
7496 tmp3 = tcg_temp_new_i32();
7497 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
7498 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7499 tcg_temp_free_i32(tmp3);
7500 tcg_temp_free_i32(tmp2);
7501 store_reg(s, rd, tmp);
7502 } else if ((insn & 0x000003e0) == 0x00000060) {
7503 tmp = load_reg(s, rm);
7504 shift = (insn >> 10) & 3;
7505 /* ??? In many cases it's not necessary to do a
7506 rotate, a shift is sufficient. */
7507 if (shift != 0)
7508 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
7509 op1 = (insn >> 20) & 7;
7510 switch (op1) {
7511 case 0: gen_sxtb16(tmp); break;
7512 case 2: gen_sxtb(tmp); break;
7513 case 3: gen_sxth(tmp); break;
7514 case 4: gen_uxtb16(tmp); break;
7515 case 6: gen_uxtb(tmp); break;
7516 case 7: gen_uxth(tmp); break;
7517 default: goto illegal_op;
7519 if (rn != 15) {
7520 tmp2 = load_reg(s, rn);
7521 if ((op1 & 3) == 0) {
7522 gen_add16(tmp, tmp2);
7523 } else {
7524 tcg_gen_add_i32(tmp, tmp, tmp2);
7525 tcg_temp_free_i32(tmp2);
7528 store_reg(s, rd, tmp);
7529 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
7530 /* rev */
7531 tmp = load_reg(s, rm);
7532 if (insn & (1 << 22)) {
7533 if (insn & (1 << 7)) {
7534 gen_revsh(tmp);
7535 } else {
7536 ARCH(6T2);
7537 gen_helper_rbit(tmp, tmp);
7539 } else {
7540 if (insn & (1 << 7))
7541 gen_rev16(tmp);
7542 else
7543 tcg_gen_bswap32_i32(tmp, tmp);
7545 store_reg(s, rd, tmp);
7546 } else {
7547 goto illegal_op;
7549 break;
7550 case 2: /* Multiplies (Type 3). */
7551 tmp = load_reg(s, rm);
7552 tmp2 = load_reg(s, rs);
7553 if (insn & (1 << 20)) {
7554 /* Signed multiply most significant [accumulate].
7555 (SMMUL, SMMLA, SMMLS) */
7556 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7558 if (rd != 15) {
7559 tmp = load_reg(s, rd);
7560 if (insn & (1 << 6)) {
7561 tmp64 = gen_subq_msw(tmp64, tmp);
7562 } else {
7563 tmp64 = gen_addq_msw(tmp64, tmp);
7566 if (insn & (1 << 5)) {
7567 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
7569 tcg_gen_shri_i64(tmp64, tmp64, 32);
7570 tmp = tcg_temp_new_i32();
7571 tcg_gen_trunc_i64_i32(tmp, tmp64);
7572 tcg_temp_free_i64(tmp64);
7573 store_reg(s, rn, tmp);
7574 } else {
7575 if (insn & (1 << 5))
7576 gen_swap_half(tmp2);
7577 gen_smul_dual(tmp, tmp2);
7578 if (insn & (1 << 6)) {
7579 /* This subtraction cannot overflow. */
7580 tcg_gen_sub_i32(tmp, tmp, tmp2);
7581 } else {
7582 /* This addition cannot overflow 32 bits;
7583 * however it may overflow considered as a signed
7584 * operation, in which case we must set the Q flag.
7586 gen_helper_add_setq(tmp, tmp, tmp2);
7588 tcg_temp_free_i32(tmp2);
7589 if (insn & (1 << 22)) {
7590 /* smlald, smlsld */
7591 tmp64 = tcg_temp_new_i64();
7592 tcg_gen_ext_i32_i64(tmp64, tmp);
7593 tcg_temp_free_i32(tmp);
7594 gen_addq(s, tmp64, rd, rn);
7595 gen_storeq_reg(s, rd, rn, tmp64);
7596 tcg_temp_free_i64(tmp64);
7597 } else {
7598 /* smuad, smusd, smlad, smlsd */
7599 if (rd != 15)
7601 tmp2 = load_reg(s, rd);
7602 gen_helper_add_setq(tmp, tmp, tmp2);
7603 tcg_temp_free_i32(tmp2);
7605 store_reg(s, rn, tmp);
7608 break;
7609 case 3:
7610 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
7611 switch (op1) {
7612 case 0: /* Unsigned sum of absolute differences. */
7613 ARCH(6);
7614 tmp = load_reg(s, rm);
7615 tmp2 = load_reg(s, rs);
7616 gen_helper_usad8(tmp, tmp, tmp2);
7617 tcg_temp_free_i32(tmp2);
7618 if (rd != 15) {
7619 tmp2 = load_reg(s, rd);
7620 tcg_gen_add_i32(tmp, tmp, tmp2);
7621 tcg_temp_free_i32(tmp2);
7623 store_reg(s, rn, tmp);
7624 break;
7625 case 0x20: case 0x24: case 0x28: case 0x2c:
7626 /* Bitfield insert/clear. */
7627 ARCH(6T2);
7628 shift = (insn >> 7) & 0x1f;
7629 i = (insn >> 16) & 0x1f;
7630 i = i + 1 - shift;
7631 if (rm == 15) {
7632 tmp = tcg_temp_new_i32();
7633 tcg_gen_movi_i32(tmp, 0);
7634 } else {
7635 tmp = load_reg(s, rm);
7637 if (i != 32) {
7638 tmp2 = load_reg(s, rd);
7639 gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
7640 tcg_temp_free_i32(tmp2);
7642 store_reg(s, rd, tmp);
7643 break;
7644 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
7645 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
7646 ARCH(6T2);
7647 tmp = load_reg(s, rm);
7648 shift = (insn >> 7) & 0x1f;
7649 i = ((insn >> 16) & 0x1f) + 1;
7650 if (shift + i > 32)
7651 goto illegal_op;
7652 if (i < 32) {
7653 if (op1 & 0x20) {
7654 gen_ubfx(tmp, shift, (1u << i) - 1);
7655 } else {
7656 gen_sbfx(tmp, shift, i);
7659 store_reg(s, rd, tmp);
7660 break;
7661 default:
7662 goto illegal_op;
7664 break;
7666 break;
7668 do_ldst:
7669 /* Check for undefined extension instructions
7670 * per the ARM Bible IE:
7671 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
7673 sh = (0xf << 20) | (0xf << 4);
7674 if (op1 == 0x7 && ((insn & sh) == sh))
7676 goto illegal_op;
7678 /* load/store byte/word */
7679 rn = (insn >> 16) & 0xf;
7680 rd = (insn >> 12) & 0xf;
7681 tmp2 = load_reg(s, rn);
7682 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
7683 if (insn & (1 << 24))
7684 gen_add_data_offset(s, insn, tmp2);
7685 if (insn & (1 << 20)) {
7686 /* load */
7687 if (insn & (1 << 22)) {
7688 tmp = gen_ld8u(tmp2, i);
7689 } else {
7690 tmp = gen_ld32(tmp2, i);
7692 } else {
7693 /* store */
7694 tmp = load_reg(s, rd);
7695 if (insn & (1 << 22))
7696 gen_st8(tmp, tmp2, i);
7697 else
7698 gen_st32(tmp, tmp2, i);
7700 if (!(insn & (1 << 24))) {
7701 gen_add_data_offset(s, insn, tmp2);
7702 store_reg(s, rn, tmp2);
7703 } else if (insn & (1 << 21)) {
7704 store_reg(s, rn, tmp2);
7705 } else {
7706 tcg_temp_free_i32(tmp2);
7708 if (insn & (1 << 20)) {
7709 /* Complete the load. */
7710 store_reg_from_load(env, s, rd, tmp);
7712 break;
7713 case 0x08:
7714 case 0x09:
7716 int j, n, user, loaded_base;
7717 TCGv loaded_var;
7718 /* load/store multiple words */
7719 /* XXX: store correct base if write back */
7720 user = 0;
7721 if (insn & (1 << 22)) {
7722 if (IS_USER(s))
7723 goto illegal_op; /* only usable in supervisor mode */
7725 if ((insn & (1 << 15)) == 0)
7726 user = 1;
7728 rn = (insn >> 16) & 0xf;
7729 addr = load_reg(s, rn);
7731 /* compute total size */
7732 loaded_base = 0;
7733 TCGV_UNUSED(loaded_var);
7734 n = 0;
7735 for(i=0;i<16;i++) {
7736 if (insn & (1 << i))
7737 n++;
7739 /* XXX: test invalid n == 0 case ? */
7740 if (insn & (1 << 23)) {
7741 if (insn & (1 << 24)) {
7742 /* pre increment */
7743 tcg_gen_addi_i32(addr, addr, 4);
7744 } else {
7745 /* post increment */
7747 } else {
7748 if (insn & (1 << 24)) {
7749 /* pre decrement */
7750 tcg_gen_addi_i32(addr, addr, -(n * 4));
7751 } else {
7752 /* post decrement */
7753 if (n != 1)
7754 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7757 j = 0;
7758 for(i=0;i<16;i++) {
7759 if (insn & (1 << i)) {
7760 if (insn & (1 << 20)) {
7761 /* load */
7762 tmp = gen_ld32(addr, IS_USER(s));
7763 if (user) {
7764 tmp2 = tcg_const_i32(i);
7765 gen_helper_set_user_reg(tmp2, tmp);
7766 tcg_temp_free_i32(tmp2);
7767 tcg_temp_free_i32(tmp);
7768 } else if (i == rn) {
7769 loaded_var = tmp;
7770 loaded_base = 1;
7771 } else {
7772 store_reg_from_load(env, s, i, tmp);
7774 } else {
7775 /* store */
7776 if (i == 15) {
7777 /* special case: r15 = PC + 8 */
7778 val = (long)s->pc + 4;
7779 tmp = tcg_temp_new_i32();
7780 tcg_gen_movi_i32(tmp, val);
7781 } else if (user) {
7782 tmp = tcg_temp_new_i32();
7783 tmp2 = tcg_const_i32(i);
7784 gen_helper_get_user_reg(tmp, tmp2);
7785 tcg_temp_free_i32(tmp2);
7786 } else {
7787 tmp = load_reg(s, i);
7789 gen_st32(tmp, addr, IS_USER(s));
7791 j++;
7792 /* no need to add after the last transfer */
7793 if (j != n)
7794 tcg_gen_addi_i32(addr, addr, 4);
7797 if (insn & (1 << 21)) {
7798 /* write back */
7799 if (insn & (1 << 23)) {
7800 if (insn & (1 << 24)) {
7801 /* pre increment */
7802 } else {
7803 /* post increment */
7804 tcg_gen_addi_i32(addr, addr, 4);
7806 } else {
7807 if (insn & (1 << 24)) {
7808 /* pre decrement */
7809 if (n != 1)
7810 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7811 } else {
7812 /* post decrement */
7813 tcg_gen_addi_i32(addr, addr, -(n * 4));
7816 store_reg(s, rn, addr);
7817 } else {
7818 tcg_temp_free_i32(addr);
7820 if (loaded_base) {
7821 store_reg(s, rn, loaded_var);
7823 if ((insn & (1 << 22)) && !user) {
7824 /* Restore CPSR from SPSR. */
7825 tmp = load_cpu_field(spsr);
7826 gen_set_cpsr(tmp, 0xffffffff);
7827 tcg_temp_free_i32(tmp);
7828 s->is_jmp = DISAS_UPDATE;
7831 break;
7832 case 0xa:
7833 case 0xb:
7835 int32_t offset;
7837 /* branch (and link) */
7838 val = (int32_t)s->pc;
7839 if (insn & (1 << 24)) {
7840 tmp = tcg_temp_new_i32();
7841 tcg_gen_movi_i32(tmp, val);
7842 store_reg(s, 14, tmp);
7844 offset = (((int32_t)insn << 8) >> 8);
7845 val += (offset << 2) + 4;
7846 gen_jmp(s, val);
7848 break;
7849 case 0xc:
7850 case 0xd:
7851 case 0xe:
7852 /* Coprocessor. */
7853 if (disas_coproc_insn(env, s, insn))
7854 goto illegal_op;
7855 break;
7856 case 0xf:
7857 /* swi */
7858 gen_set_pc_im(s->pc);
7859 s->is_jmp = DISAS_SWI;
7860 break;
7861 default:
7862 illegal_op:
7863 gen_exception_insn(s, 4, EXCP_UDEF);
7864 break;
7869 /* Return true if this is a Thumb-2 logical op. */
7870 static int
7871 thumb2_logic_op(int op)
7873 return (op < 8);
7876 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7877 then set condition code flags based on the result of the operation.
7878 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7879 to the high bit of T1.
7880 Returns zero if the opcode is valid. */
7882 static int
7883 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCGv t0, TCGv t1)
7885 int logic_cc;
7887 logic_cc = 0;
7888 switch (op) {
7889 case 0: /* and */
7890 tcg_gen_and_i32(t0, t0, t1);
7891 logic_cc = conds;
7892 break;
7893 case 1: /* bic */
7894 tcg_gen_andc_i32(t0, t0, t1);
7895 logic_cc = conds;
7896 break;
7897 case 2: /* orr */
7898 tcg_gen_or_i32(t0, t0, t1);
7899 logic_cc = conds;
7900 break;
7901 case 3: /* orn */
7902 tcg_gen_orc_i32(t0, t0, t1);
7903 logic_cc = conds;
7904 break;
7905 case 4: /* eor */
7906 tcg_gen_xor_i32(t0, t0, t1);
7907 logic_cc = conds;
7908 break;
7909 case 8: /* add */
7910 if (conds)
7911 gen_helper_add_cc(t0, t0, t1);
7912 else
7913 tcg_gen_add_i32(t0, t0, t1);
7914 break;
7915 case 10: /* adc */
7916 if (conds)
7917 gen_helper_adc_cc(t0, t0, t1);
7918 else
7919 gen_adc(t0, t1);
7920 break;
7921 case 11: /* sbc */
7922 if (conds)
7923 gen_helper_sbc_cc(t0, t0, t1);
7924 else
7925 gen_sub_carry(t0, t0, t1);
7926 break;
7927 case 13: /* sub */
7928 if (conds)
7929 gen_helper_sub_cc(t0, t0, t1);
7930 else
7931 tcg_gen_sub_i32(t0, t0, t1);
7932 break;
7933 case 14: /* rsb */
7934 if (conds)
7935 gen_helper_sub_cc(t0, t1, t0);
7936 else
7937 tcg_gen_sub_i32(t0, t1, t0);
7938 break;
7939 default: /* 5, 6, 7, 9, 12, 15. */
7940 return 1;
7942 if (logic_cc) {
7943 gen_logic_CC(t0);
7944 if (shifter_out)
7945 gen_set_CF_bit31(t1);
7947 return 0;
7950 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7951 is not legal. */
7952 static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7954 uint32_t insn, imm, shift, offset;
7955 uint32_t rd, rn, rm, rs;
7956 TCGv tmp;
7957 TCGv tmp2;
7958 TCGv tmp3;
7959 TCGv addr;
7960 TCGv_i64 tmp64;
7961 int op;
7962 int shiftop;
7963 int conds;
7964 int logic_cc;
7966 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
7967 || arm_feature (env, ARM_FEATURE_M))) {
7968 /* Thumb-1 cores may need to treat bl and blx as a pair of
7969 16-bit instructions to get correct prefetch abort behavior. */
7970 insn = insn_hw1;
7971 if ((insn & (1 << 12)) == 0) {
7972 ARCH(5);
7973 /* Second half of blx. */
7974 offset = ((insn & 0x7ff) << 1);
7975 tmp = load_reg(s, 14);
7976 tcg_gen_addi_i32(tmp, tmp, offset);
7977 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
7979 tmp2 = tcg_temp_new_i32();
7980 tcg_gen_movi_i32(tmp2, s->pc | 1);
7981 store_reg(s, 14, tmp2);
7982 gen_bx(s, tmp);
7983 return 0;
7985 if (insn & (1 << 11)) {
7986 /* Second half of bl. */
7987 offset = ((insn & 0x7ff) << 1) | 1;
7988 tmp = load_reg(s, 14);
7989 tcg_gen_addi_i32(tmp, tmp, offset);
7991 tmp2 = tcg_temp_new_i32();
7992 tcg_gen_movi_i32(tmp2, s->pc | 1);
7993 store_reg(s, 14, tmp2);
7994 gen_bx(s, tmp);
7995 return 0;
7997 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
7998 /* Instruction spans a page boundary. Implement it as two
7999 16-bit instructions in case the second half causes an
8000 prefetch abort. */
8001 offset = ((int32_t)insn << 21) >> 9;
8002 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
8003 return 0;
8005 /* Fall through to 32-bit decode. */
8008 insn = lduw_code(s->pc);
8009 s->pc += 2;
8010 insn |= (uint32_t)insn_hw1 << 16;
8012 if ((insn & 0xf800e800) != 0xf000e800) {
8013 ARCH(6T2);
8016 rn = (insn >> 16) & 0xf;
8017 rs = (insn >> 12) & 0xf;
8018 rd = (insn >> 8) & 0xf;
8019 rm = insn & 0xf;
8020 switch ((insn >> 25) & 0xf) {
8021 case 0: case 1: case 2: case 3:
8022 /* 16-bit instructions. Should never happen. */
8023 abort();
8024 case 4:
8025 if (insn & (1 << 22)) {
8026 /* Other load/store, table branch. */
8027 if (insn & 0x01200000) {
8028 /* Load/store doubleword. */
8029 if (rn == 15) {
8030 addr = tcg_temp_new_i32();
8031 tcg_gen_movi_i32(addr, s->pc & ~3);
8032 } else {
8033 addr = load_reg(s, rn);
8035 offset = (insn & 0xff) * 4;
8036 if ((insn & (1 << 23)) == 0)
8037 offset = -offset;
8038 if (insn & (1 << 24)) {
8039 tcg_gen_addi_i32(addr, addr, offset);
8040 offset = 0;
8042 if (insn & (1 << 20)) {
8043 /* ldrd */
8044 tmp = gen_ld32(addr, IS_USER(s));
8045 store_reg(s, rs, tmp);
8046 tcg_gen_addi_i32(addr, addr, 4);
8047 tmp = gen_ld32(addr, IS_USER(s));
8048 store_reg(s, rd, tmp);
8049 } else {
8050 /* strd */
8051 tmp = load_reg(s, rs);
8052 gen_st32(tmp, addr, IS_USER(s));
8053 tcg_gen_addi_i32(addr, addr, 4);
8054 tmp = load_reg(s, rd);
8055 gen_st32(tmp, addr, IS_USER(s));
8057 if (insn & (1 << 21)) {
8058 /* Base writeback. */
8059 if (rn == 15)
8060 goto illegal_op;
8061 tcg_gen_addi_i32(addr, addr, offset - 4);
8062 store_reg(s, rn, addr);
8063 } else {
8064 tcg_temp_free_i32(addr);
8066 } else if ((insn & (1 << 23)) == 0) {
8067 /* Load/store exclusive word. */
8068 addr = tcg_temp_local_new();
8069 load_reg_var(s, addr, rn);
8070 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
8071 if (insn & (1 << 20)) {
8072 gen_load_exclusive(s, rs, 15, addr, 2);
8073 } else {
8074 gen_store_exclusive(s, rd, rs, 15, addr, 2);
8076 tcg_temp_free(addr);
8077 } else if ((insn & (1 << 6)) == 0) {
8078 /* Table Branch. */
8079 if (rn == 15) {
8080 addr = tcg_temp_new_i32();
8081 tcg_gen_movi_i32(addr, s->pc);
8082 } else {
8083 addr = load_reg(s, rn);
8085 tmp = load_reg(s, rm);
8086 tcg_gen_add_i32(addr, addr, tmp);
8087 if (insn & (1 << 4)) {
8088 /* tbh */
8089 tcg_gen_add_i32(addr, addr, tmp);
8090 tcg_temp_free_i32(tmp);
8091 tmp = gen_ld16u(addr, IS_USER(s));
8092 } else { /* tbb */
8093 tcg_temp_free_i32(tmp);
8094 tmp = gen_ld8u(addr, IS_USER(s));
8096 tcg_temp_free_i32(addr);
8097 tcg_gen_shli_i32(tmp, tmp, 1);
8098 tcg_gen_addi_i32(tmp, tmp, s->pc);
8099 store_reg(s, 15, tmp);
8100 } else {
8101 /* Load/store exclusive byte/halfword/doubleword. */
8102 ARCH(7);
8103 op = (insn >> 4) & 0x3;
8104 if (op == 2) {
8105 goto illegal_op;
8107 addr = tcg_temp_local_new();
8108 load_reg_var(s, addr, rn);
8109 if (insn & (1 << 20)) {
8110 gen_load_exclusive(s, rs, rd, addr, op);
8111 } else {
8112 gen_store_exclusive(s, rm, rs, rd, addr, op);
8114 tcg_temp_free(addr);
8116 } else {
8117 /* Load/store multiple, RFE, SRS. */
8118 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
8119 /* Not available in user mode. */
8120 if (IS_USER(s))
8121 goto illegal_op;
8122 if (insn & (1 << 20)) {
8123 /* rfe */
8124 addr = load_reg(s, rn);
8125 if ((insn & (1 << 24)) == 0)
8126 tcg_gen_addi_i32(addr, addr, -8);
8127 /* Load PC into tmp and CPSR into tmp2. */
8128 tmp = gen_ld32(addr, 0);
8129 tcg_gen_addi_i32(addr, addr, 4);
8130 tmp2 = gen_ld32(addr, 0);
8131 if (insn & (1 << 21)) {
8132 /* Base writeback. */
8133 if (insn & (1 << 24)) {
8134 tcg_gen_addi_i32(addr, addr, 4);
8135 } else {
8136 tcg_gen_addi_i32(addr, addr, -4);
8138 store_reg(s, rn, addr);
8139 } else {
8140 tcg_temp_free_i32(addr);
8142 gen_rfe(s, tmp, tmp2);
8143 } else {
8144 /* srs */
8145 op = (insn & 0x1f);
8146 addr = tcg_temp_new_i32();
8147 tmp = tcg_const_i32(op);
8148 gen_helper_get_r13_banked(addr, cpu_env, tmp);
8149 tcg_temp_free_i32(tmp);
8150 if ((insn & (1 << 24)) == 0) {
8151 tcg_gen_addi_i32(addr, addr, -8);
8153 tmp = load_reg(s, 14);
8154 gen_st32(tmp, addr, 0);
8155 tcg_gen_addi_i32(addr, addr, 4);
8156 tmp = tcg_temp_new_i32();
8157 gen_helper_cpsr_read(tmp);
8158 gen_st32(tmp, addr, 0);
8159 if (insn & (1 << 21)) {
8160 if ((insn & (1 << 24)) == 0) {
8161 tcg_gen_addi_i32(addr, addr, -4);
8162 } else {
8163 tcg_gen_addi_i32(addr, addr, 4);
8165 tmp = tcg_const_i32(op);
8166 gen_helper_set_r13_banked(cpu_env, tmp, addr);
8167 tcg_temp_free_i32(tmp);
8168 } else {
8169 tcg_temp_free_i32(addr);
8172 } else {
8173 int i, loaded_base = 0;
8174 TCGv loaded_var;
8175 /* Load/store multiple. */
8176 addr = load_reg(s, rn);
8177 offset = 0;
8178 for (i = 0; i < 16; i++) {
8179 if (insn & (1 << i))
8180 offset += 4;
8182 if (insn & (1 << 24)) {
8183 tcg_gen_addi_i32(addr, addr, -offset);
8186 TCGV_UNUSED(loaded_var);
8187 for (i = 0; i < 16; i++) {
8188 if ((insn & (1 << i)) == 0)
8189 continue;
8190 if (insn & (1 << 20)) {
8191 /* Load. */
8192 tmp = gen_ld32(addr, IS_USER(s));
8193 if (i == 15) {
8194 gen_bx(s, tmp);
8195 } else if (i == rn) {
8196 loaded_var = tmp;
8197 loaded_base = 1;
8198 } else {
8199 store_reg(s, i, tmp);
8201 } else {
8202 /* Store. */
8203 tmp = load_reg(s, i);
8204 gen_st32(tmp, addr, IS_USER(s));
8206 tcg_gen_addi_i32(addr, addr, 4);
8208 if (loaded_base) {
8209 store_reg(s, rn, loaded_var);
8211 if (insn & (1 << 21)) {
8212 /* Base register writeback. */
8213 if (insn & (1 << 24)) {
8214 tcg_gen_addi_i32(addr, addr, -offset);
8216 /* Fault if writeback register is in register list. */
8217 if (insn & (1 << rn))
8218 goto illegal_op;
8219 store_reg(s, rn, addr);
8220 } else {
8221 tcg_temp_free_i32(addr);
8225 break;
8226 case 5:
8228 op = (insn >> 21) & 0xf;
8229 if (op == 6) {
8230 /* Halfword pack. */
8231 tmp = load_reg(s, rn);
8232 tmp2 = load_reg(s, rm);
8233 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
8234 if (insn & (1 << 5)) {
8235 /* pkhtb */
8236 if (shift == 0)
8237 shift = 31;
8238 tcg_gen_sari_i32(tmp2, tmp2, shift);
8239 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
8240 tcg_gen_ext16u_i32(tmp2, tmp2);
8241 } else {
8242 /* pkhbt */
8243 if (shift)
8244 tcg_gen_shli_i32(tmp2, tmp2, shift);
8245 tcg_gen_ext16u_i32(tmp, tmp);
8246 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
8248 tcg_gen_or_i32(tmp, tmp, tmp2);
8249 tcg_temp_free_i32(tmp2);
8250 store_reg(s, rd, tmp);
8251 } else {
8252 /* Data processing register constant shift. */
8253 if (rn == 15) {
8254 tmp = tcg_temp_new_i32();
8255 tcg_gen_movi_i32(tmp, 0);
8256 } else {
8257 tmp = load_reg(s, rn);
8259 tmp2 = load_reg(s, rm);
8261 shiftop = (insn >> 4) & 3;
8262 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
8263 conds = (insn & (1 << 20)) != 0;
8264 logic_cc = (conds && thumb2_logic_op(op));
8265 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
8266 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
8267 goto illegal_op;
8268 tcg_temp_free_i32(tmp2);
8269 if (rd != 15) {
8270 store_reg(s, rd, tmp);
8271 } else {
8272 tcg_temp_free_i32(tmp);
8275 break;
8276 case 13: /* Misc data processing. */
8277 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
8278 if (op < 4 && (insn & 0xf000) != 0xf000)
8279 goto illegal_op;
8280 switch (op) {
8281 case 0: /* Register controlled shift. */
8282 tmp = load_reg(s, rn);
8283 tmp2 = load_reg(s, rm);
8284 if ((insn & 0x70) != 0)
8285 goto illegal_op;
8286 op = (insn >> 21) & 3;
8287 logic_cc = (insn & (1 << 20)) != 0;
8288 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
8289 if (logic_cc)
8290 gen_logic_CC(tmp);
8291 store_reg_bx(env, s, rd, tmp);
8292 break;
8293 case 1: /* Sign/zero extend. */
8294 tmp = load_reg(s, rm);
8295 shift = (insn >> 4) & 3;
8296 /* ??? In many cases it's not necessary to do a
8297 rotate, a shift is sufficient. */
8298 if (shift != 0)
8299 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
8300 op = (insn >> 20) & 7;
8301 switch (op) {
8302 case 0: gen_sxth(tmp); break;
8303 case 1: gen_uxth(tmp); break;
8304 case 2: gen_sxtb16(tmp); break;
8305 case 3: gen_uxtb16(tmp); break;
8306 case 4: gen_sxtb(tmp); break;
8307 case 5: gen_uxtb(tmp); break;
8308 default: goto illegal_op;
8310 if (rn != 15) {
8311 tmp2 = load_reg(s, rn);
8312 if ((op >> 1) == 1) {
8313 gen_add16(tmp, tmp2);
8314 } else {
8315 tcg_gen_add_i32(tmp, tmp, tmp2);
8316 tcg_temp_free_i32(tmp2);
8319 store_reg(s, rd, tmp);
8320 break;
8321 case 2: /* SIMD add/subtract. */
8322 op = (insn >> 20) & 7;
8323 shift = (insn >> 4) & 7;
8324 if ((op & 3) == 3 || (shift & 3) == 3)
8325 goto illegal_op;
8326 tmp = load_reg(s, rn);
8327 tmp2 = load_reg(s, rm);
8328 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
8329 tcg_temp_free_i32(tmp2);
8330 store_reg(s, rd, tmp);
8331 break;
8332 case 3: /* Other data processing. */
8333 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
8334 if (op < 4) {
8335 /* Saturating add/subtract. */
8336 tmp = load_reg(s, rn);
8337 tmp2 = load_reg(s, rm);
8338 if (op & 1)
8339 gen_helper_double_saturate(tmp, tmp);
8340 if (op & 2)
8341 gen_helper_sub_saturate(tmp, tmp2, tmp);
8342 else
8343 gen_helper_add_saturate(tmp, tmp, tmp2);
8344 tcg_temp_free_i32(tmp2);
8345 } else {
8346 tmp = load_reg(s, rn);
8347 switch (op) {
8348 case 0x0a: /* rbit */
8349 gen_helper_rbit(tmp, tmp);
8350 break;
8351 case 0x08: /* rev */
8352 tcg_gen_bswap32_i32(tmp, tmp);
8353 break;
8354 case 0x09: /* rev16 */
8355 gen_rev16(tmp);
8356 break;
8357 case 0x0b: /* revsh */
8358 gen_revsh(tmp);
8359 break;
8360 case 0x10: /* sel */
8361 tmp2 = load_reg(s, rm);
8362 tmp3 = tcg_temp_new_i32();
8363 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
8364 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
8365 tcg_temp_free_i32(tmp3);
8366 tcg_temp_free_i32(tmp2);
8367 break;
8368 case 0x18: /* clz */
8369 gen_helper_clz(tmp, tmp);
8370 break;
8371 default:
8372 goto illegal_op;
8375 store_reg(s, rd, tmp);
8376 break;
8377 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
8378 op = (insn >> 4) & 0xf;
8379 tmp = load_reg(s, rn);
8380 tmp2 = load_reg(s, rm);
8381 switch ((insn >> 20) & 7) {
8382 case 0: /* 32 x 32 -> 32 */
8383 tcg_gen_mul_i32(tmp, tmp, tmp2);
8384 tcg_temp_free_i32(tmp2);
8385 if (rs != 15) {
8386 tmp2 = load_reg(s, rs);
8387 if (op)
8388 tcg_gen_sub_i32(tmp, tmp2, tmp);
8389 else
8390 tcg_gen_add_i32(tmp, tmp, tmp2);
8391 tcg_temp_free_i32(tmp2);
8393 break;
8394 case 1: /* 16 x 16 -> 32 */
8395 gen_mulxy(tmp, tmp2, op & 2, op & 1);
8396 tcg_temp_free_i32(tmp2);
8397 if (rs != 15) {
8398 tmp2 = load_reg(s, rs);
8399 gen_helper_add_setq(tmp, tmp, tmp2);
8400 tcg_temp_free_i32(tmp2);
8402 break;
8403 case 2: /* Dual multiply add. */
8404 case 4: /* Dual multiply subtract. */
8405 if (op)
8406 gen_swap_half(tmp2);
8407 gen_smul_dual(tmp, tmp2);
8408 if (insn & (1 << 22)) {
8409 /* This subtraction cannot overflow. */
8410 tcg_gen_sub_i32(tmp, tmp, tmp2);
8411 } else {
8412 /* This addition cannot overflow 32 bits;
8413 * however it may overflow considered as a signed
8414 * operation, in which case we must set the Q flag.
8416 gen_helper_add_setq(tmp, tmp, tmp2);
8418 tcg_temp_free_i32(tmp2);
8419 if (rs != 15)
8421 tmp2 = load_reg(s, rs);
8422 gen_helper_add_setq(tmp, tmp, tmp2);
8423 tcg_temp_free_i32(tmp2);
8425 break;
8426 case 3: /* 32 * 16 -> 32msb */
8427 if (op)
8428 tcg_gen_sari_i32(tmp2, tmp2, 16);
8429 else
8430 gen_sxth(tmp2);
8431 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8432 tcg_gen_shri_i64(tmp64, tmp64, 16);
8433 tmp = tcg_temp_new_i32();
8434 tcg_gen_trunc_i64_i32(tmp, tmp64);
8435 tcg_temp_free_i64(tmp64);
8436 if (rs != 15)
8438 tmp2 = load_reg(s, rs);
8439 gen_helper_add_setq(tmp, tmp, tmp2);
8440 tcg_temp_free_i32(tmp2);
8442 break;
8443 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
8444 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8445 if (rs != 15) {
8446 tmp = load_reg(s, rs);
8447 if (insn & (1 << 20)) {
8448 tmp64 = gen_addq_msw(tmp64, tmp);
8449 } else {
8450 tmp64 = gen_subq_msw(tmp64, tmp);
8453 if (insn & (1 << 4)) {
8454 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
8456 tcg_gen_shri_i64(tmp64, tmp64, 32);
8457 tmp = tcg_temp_new_i32();
8458 tcg_gen_trunc_i64_i32(tmp, tmp64);
8459 tcg_temp_free_i64(tmp64);
8460 break;
8461 case 7: /* Unsigned sum of absolute differences. */
8462 gen_helper_usad8(tmp, tmp, tmp2);
8463 tcg_temp_free_i32(tmp2);
8464 if (rs != 15) {
8465 tmp2 = load_reg(s, rs);
8466 tcg_gen_add_i32(tmp, tmp, tmp2);
8467 tcg_temp_free_i32(tmp2);
8469 break;
8471 store_reg(s, rd, tmp);
8472 break;
8473 case 6: case 7: /* 64-bit multiply, Divide. */
8474 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
8475 tmp = load_reg(s, rn);
8476 tmp2 = load_reg(s, rm);
8477 if ((op & 0x50) == 0x10) {
8478 /* sdiv, udiv */
8479 if (!arm_feature(env, ARM_FEATURE_DIV))
8480 goto illegal_op;
8481 if (op & 0x20)
8482 gen_helper_udiv(tmp, tmp, tmp2);
8483 else
8484 gen_helper_sdiv(tmp, tmp, tmp2);
8485 tcg_temp_free_i32(tmp2);
8486 store_reg(s, rd, tmp);
8487 } else if ((op & 0xe) == 0xc) {
8488 /* Dual multiply accumulate long. */
8489 if (op & 1)
8490 gen_swap_half(tmp2);
8491 gen_smul_dual(tmp, tmp2);
8492 if (op & 0x10) {
8493 tcg_gen_sub_i32(tmp, tmp, tmp2);
8494 } else {
8495 tcg_gen_add_i32(tmp, tmp, tmp2);
8497 tcg_temp_free_i32(tmp2);
8498 /* BUGFIX */
8499 tmp64 = tcg_temp_new_i64();
8500 tcg_gen_ext_i32_i64(tmp64, tmp);
8501 tcg_temp_free_i32(tmp);
8502 gen_addq(s, tmp64, rs, rd);
8503 gen_storeq_reg(s, rs, rd, tmp64);
8504 tcg_temp_free_i64(tmp64);
8505 } else {
8506 if (op & 0x20) {
8507 /* Unsigned 64-bit multiply */
8508 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
8509 } else {
8510 if (op & 8) {
8511 /* smlalxy */
8512 gen_mulxy(tmp, tmp2, op & 2, op & 1);
8513 tcg_temp_free_i32(tmp2);
8514 tmp64 = tcg_temp_new_i64();
8515 tcg_gen_ext_i32_i64(tmp64, tmp);
8516 tcg_temp_free_i32(tmp);
8517 } else {
8518 /* Signed 64-bit multiply */
8519 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8522 if (op & 4) {
8523 /* umaal */
8524 gen_addq_lo(s, tmp64, rs);
8525 gen_addq_lo(s, tmp64, rd);
8526 } else if (op & 0x40) {
8527 /* 64-bit accumulate. */
8528 gen_addq(s, tmp64, rs, rd);
8530 gen_storeq_reg(s, rs, rd, tmp64);
8531 tcg_temp_free_i64(tmp64);
8533 break;
8535 break;
8536 case 6: case 7: case 14: case 15:
8537 /* Coprocessor. */
8538 if (((insn >> 24) & 3) == 3) {
8539 /* Translate into the equivalent ARM encoding. */
8540 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
8541 if (disas_neon_data_insn(env, s, insn))
8542 goto illegal_op;
8543 } else {
8544 if (insn & (1 << 28))
8545 goto illegal_op;
8546 if (disas_coproc_insn (env, s, insn))
8547 goto illegal_op;
8549 break;
8550 case 8: case 9: case 10: case 11:
8551 if (insn & (1 << 15)) {
8552 /* Branches, misc control. */
8553 if (insn & 0x5000) {
8554 /* Unconditional branch. */
8555 /* signextend(hw1[10:0]) -> offset[:12]. */
8556 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
8557 /* hw1[10:0] -> offset[11:1]. */
8558 offset |= (insn & 0x7ff) << 1;
8559 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
8560 offset[24:22] already have the same value because of the
8561 sign extension above. */
8562 offset ^= ((~insn) & (1 << 13)) << 10;
8563 offset ^= ((~insn) & (1 << 11)) << 11;
8565 if (insn & (1 << 14)) {
8566 /* Branch and link. */
8567 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
8570 offset += s->pc;
8571 if (insn & (1 << 12)) {
8572 /* b/bl */
8573 gen_jmp(s, offset);
8574 } else {
8575 /* blx */
8576 offset &= ~(uint32_t)2;
8577 /* thumb2 bx, no need to check */
8578 gen_bx_im(s, offset);
8580 } else if (((insn >> 23) & 7) == 7) {
8581 /* Misc control */
8582 if (insn & (1 << 13))
8583 goto illegal_op;
8585 if (insn & (1 << 26)) {
8586 /* Secure monitor call (v6Z) */
8587 goto illegal_op; /* not implemented. */
8588 } else {
8589 op = (insn >> 20) & 7;
8590 switch (op) {
8591 case 0: /* msr cpsr. */
8592 if (IS_M(env)) {
8593 tmp = load_reg(s, rn);
8594 addr = tcg_const_i32(insn & 0xff);
8595 gen_helper_v7m_msr(cpu_env, addr, tmp);
8596 tcg_temp_free_i32(addr);
8597 tcg_temp_free_i32(tmp);
8598 gen_lookup_tb(s);
8599 break;
8601 /* fall through */
8602 case 1: /* msr spsr. */
8603 if (IS_M(env))
8604 goto illegal_op;
8605 tmp = load_reg(s, rn);
8606 if (gen_set_psr(s,
8607 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
8608 op == 1, tmp))
8609 goto illegal_op;
8610 break;
8611 case 2: /* cps, nop-hint. */
8612 if (((insn >> 8) & 7) == 0) {
8613 gen_nop_hint(s, insn & 0xff);
8615 /* Implemented as NOP in user mode. */
8616 if (IS_USER(s))
8617 break;
8618 offset = 0;
8619 imm = 0;
8620 if (insn & (1 << 10)) {
8621 if (insn & (1 << 7))
8622 offset |= CPSR_A;
8623 if (insn & (1 << 6))
8624 offset |= CPSR_I;
8625 if (insn & (1 << 5))
8626 offset |= CPSR_F;
8627 if (insn & (1 << 9))
8628 imm = CPSR_A | CPSR_I | CPSR_F;
8630 if (insn & (1 << 8)) {
8631 offset |= 0x1f;
8632 imm |= (insn & 0x1f);
8634 if (offset) {
8635 gen_set_psr_im(s, offset, 0, imm);
8637 break;
8638 case 3: /* Special control operations. */
8639 ARCH(7);
8640 op = (insn >> 4) & 0xf;
8641 switch (op) {
8642 case 2: /* clrex */
8643 gen_clrex(s);
8644 break;
8645 case 4: /* dsb */
8646 case 5: /* dmb */
8647 case 6: /* isb */
8648 /* These execute as NOPs. */
8649 break;
8650 default:
8651 goto illegal_op;
8653 break;
8654 case 4: /* bxj */
8655 /* Trivial implementation equivalent to bx. */
8656 tmp = load_reg(s, rn);
8657 gen_bx(s, tmp);
8658 break;
8659 case 5: /* Exception return. */
8660 if (IS_USER(s)) {
8661 goto illegal_op;
8663 if (rn != 14 || rd != 15) {
8664 goto illegal_op;
8666 tmp = load_reg(s, rn);
8667 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
8668 gen_exception_return(s, tmp);
8669 break;
8670 case 6: /* mrs cpsr. */
8671 tmp = tcg_temp_new_i32();
8672 if (IS_M(env)) {
8673 addr = tcg_const_i32(insn & 0xff);
8674 gen_helper_v7m_mrs(tmp, cpu_env, addr);
8675 tcg_temp_free_i32(addr);
8676 } else {
8677 gen_helper_cpsr_read(tmp);
8679 store_reg(s, rd, tmp);
8680 break;
8681 case 7: /* mrs spsr. */
8682 /* Not accessible in user mode. */
8683 if (IS_USER(s) || IS_M(env))
8684 goto illegal_op;
8685 tmp = load_cpu_field(spsr);
8686 store_reg(s, rd, tmp);
8687 break;
8690 } else {
8691 /* Conditional branch. */
8692 op = (insn >> 22) & 0xf;
8693 /* Generate a conditional jump to next instruction. */
8694 s->condlabel = gen_new_label();
8695 gen_test_cc(op ^ 1, s->condlabel);
8696 s->condjmp = 1;
8698 /* offset[11:1] = insn[10:0] */
8699 offset = (insn & 0x7ff) << 1;
8700 /* offset[17:12] = insn[21:16]. */
8701 offset |= (insn & 0x003f0000) >> 4;
8702 /* offset[31:20] = insn[26]. */
8703 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
8704 /* offset[18] = insn[13]. */
8705 offset |= (insn & (1 << 13)) << 5;
8706 /* offset[19] = insn[11]. */
8707 offset |= (insn & (1 << 11)) << 8;
8709 /* jump to the offset */
8710 gen_jmp(s, s->pc + offset);
8712 } else {
8713 /* Data processing immediate. */
8714 if (insn & (1 << 25)) {
8715 if (insn & (1 << 24)) {
8716 if (insn & (1 << 20))
8717 goto illegal_op;
8718 /* Bitfield/Saturate. */
8719 op = (insn >> 21) & 7;
8720 imm = insn & 0x1f;
8721 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
8722 if (rn == 15) {
8723 tmp = tcg_temp_new_i32();
8724 tcg_gen_movi_i32(tmp, 0);
8725 } else {
8726 tmp = load_reg(s, rn);
8728 switch (op) {
8729 case 2: /* Signed bitfield extract. */
8730 imm++;
8731 if (shift + imm > 32)
8732 goto illegal_op;
8733 if (imm < 32)
8734 gen_sbfx(tmp, shift, imm);
8735 break;
8736 case 6: /* Unsigned bitfield extract. */
8737 imm++;
8738 if (shift + imm > 32)
8739 goto illegal_op;
8740 if (imm < 32)
8741 gen_ubfx(tmp, shift, (1u << imm) - 1);
8742 break;
8743 case 3: /* Bitfield insert/clear. */
8744 if (imm < shift)
8745 goto illegal_op;
8746 imm = imm + 1 - shift;
8747 if (imm != 32) {
8748 tmp2 = load_reg(s, rd);
8749 gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
8750 tcg_temp_free_i32(tmp2);
8752 break;
8753 case 7:
8754 goto illegal_op;
8755 default: /* Saturate. */
8756 if (shift) {
8757 if (op & 1)
8758 tcg_gen_sari_i32(tmp, tmp, shift);
8759 else
8760 tcg_gen_shli_i32(tmp, tmp, shift);
8762 tmp2 = tcg_const_i32(imm);
8763 if (op & 4) {
8764 /* Unsigned. */
8765 if ((op & 1) && shift == 0)
8766 gen_helper_usat16(tmp, tmp, tmp2);
8767 else
8768 gen_helper_usat(tmp, tmp, tmp2);
8769 } else {
8770 /* Signed. */
8771 if ((op & 1) && shift == 0)
8772 gen_helper_ssat16(tmp, tmp, tmp2);
8773 else
8774 gen_helper_ssat(tmp, tmp, tmp2);
8776 tcg_temp_free_i32(tmp2);
8777 break;
8779 store_reg(s, rd, tmp);
8780 } else {
8781 imm = ((insn & 0x04000000) >> 15)
8782 | ((insn & 0x7000) >> 4) | (insn & 0xff);
8783 if (insn & (1 << 22)) {
8784 /* 16-bit immediate. */
8785 imm |= (insn >> 4) & 0xf000;
8786 if (insn & (1 << 23)) {
8787 /* movt */
8788 tmp = load_reg(s, rd);
8789 tcg_gen_ext16u_i32(tmp, tmp);
8790 tcg_gen_ori_i32(tmp, tmp, imm << 16);
8791 } else {
8792 /* movw */
8793 tmp = tcg_temp_new_i32();
8794 tcg_gen_movi_i32(tmp, imm);
8796 } else {
8797 /* Add/sub 12-bit immediate. */
8798 if (rn == 15) {
8799 offset = s->pc & ~(uint32_t)3;
8800 if (insn & (1 << 23))
8801 offset -= imm;
8802 else
8803 offset += imm;
8804 tmp = tcg_temp_new_i32();
8805 tcg_gen_movi_i32(tmp, offset);
8806 } else {
8807 tmp = load_reg(s, rn);
8808 if (insn & (1 << 23))
8809 tcg_gen_subi_i32(tmp, tmp, imm);
8810 else
8811 tcg_gen_addi_i32(tmp, tmp, imm);
8814 store_reg(s, rd, tmp);
8816 } else {
8817 int shifter_out = 0;
8818 /* modified 12-bit immediate. */
8819 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
8820 imm = (insn & 0xff);
8821 switch (shift) {
8822 case 0: /* XY */
8823 /* Nothing to do. */
8824 break;
8825 case 1: /* 00XY00XY */
8826 imm |= imm << 16;
8827 break;
8828 case 2: /* XY00XY00 */
8829 imm |= imm << 16;
8830 imm <<= 8;
8831 break;
8832 case 3: /* XYXYXYXY */
8833 imm |= imm << 16;
8834 imm |= imm << 8;
8835 break;
8836 default: /* Rotated constant. */
8837 shift = (shift << 1) | (imm >> 7);
8838 imm |= 0x80;
8839 imm = imm << (32 - shift);
8840 shifter_out = 1;
8841 break;
8843 tmp2 = tcg_temp_new_i32();
8844 tcg_gen_movi_i32(tmp2, imm);
8845 rn = (insn >> 16) & 0xf;
8846 if (rn == 15) {
8847 tmp = tcg_temp_new_i32();
8848 tcg_gen_movi_i32(tmp, 0);
8849 } else {
8850 tmp = load_reg(s, rn);
8852 op = (insn >> 21) & 0xf;
8853 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
8854 shifter_out, tmp, tmp2))
8855 goto illegal_op;
8856 tcg_temp_free_i32(tmp2);
8857 rd = (insn >> 8) & 0xf;
8858 if (rd != 15) {
8859 store_reg(s, rd, tmp);
8860 } else {
8861 tcg_temp_free_i32(tmp);
8865 break;
8866 case 12: /* Load/store single data item. */
8868 int postinc = 0;
8869 int writeback = 0;
8870 int user;
8871 if ((insn & 0x01100000) == 0x01000000) {
8872 if (disas_neon_ls_insn(env, s, insn))
8873 goto illegal_op;
8874 break;
8876 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
8877 if (rs == 15) {
8878 if (!(insn & (1 << 20))) {
8879 goto illegal_op;
8881 if (op != 2) {
8882 /* Byte or halfword load space with dest == r15 : memory hints.
8883 * Catch them early so we don't emit pointless addressing code.
8884 * This space is a mix of:
8885 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
8886 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
8887 * cores)
8888 * unallocated hints, which must be treated as NOPs
8889 * UNPREDICTABLE space, which we NOP or UNDEF depending on
8890 * which is easiest for the decoding logic
8891 * Some space which must UNDEF
8893 int op1 = (insn >> 23) & 3;
8894 int op2 = (insn >> 6) & 0x3f;
8895 if (op & 2) {
8896 goto illegal_op;
8898 if (rn == 15) {
8899 /* UNPREDICTABLE or unallocated hint */
8900 return 0;
8902 if (op1 & 1) {
8903 return 0; /* PLD* or unallocated hint */
8905 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
8906 return 0; /* PLD* or unallocated hint */
8908 /* UNDEF space, or an UNPREDICTABLE */
8909 return 1;
8912 user = IS_USER(s);
8913 if (rn == 15) {
8914 addr = tcg_temp_new_i32();
8915 /* PC relative. */
8916 /* s->pc has already been incremented by 4. */
8917 imm = s->pc & 0xfffffffc;
8918 if (insn & (1 << 23))
8919 imm += insn & 0xfff;
8920 else
8921 imm -= insn & 0xfff;
8922 tcg_gen_movi_i32(addr, imm);
8923 } else {
8924 addr = load_reg(s, rn);
8925 if (insn & (1 << 23)) {
8926 /* Positive offset. */
8927 imm = insn & 0xfff;
8928 tcg_gen_addi_i32(addr, addr, imm);
8929 } else {
8930 imm = insn & 0xff;
8931 switch ((insn >> 8) & 0xf) {
8932 case 0x0: /* Shifted Register. */
8933 shift = (insn >> 4) & 0xf;
8934 if (shift > 3) {
8935 tcg_temp_free_i32(addr);
8936 goto illegal_op;
8938 tmp = load_reg(s, rm);
8939 if (shift)
8940 tcg_gen_shli_i32(tmp, tmp, shift);
8941 tcg_gen_add_i32(addr, addr, tmp);
8942 tcg_temp_free_i32(tmp);
8943 break;
8944 case 0xc: /* Negative offset. */
8945 tcg_gen_addi_i32(addr, addr, -imm);
8946 break;
8947 case 0xe: /* User privilege. */
8948 tcg_gen_addi_i32(addr, addr, imm);
8949 user = 1;
8950 break;
8951 case 0x9: /* Post-decrement. */
8952 imm = -imm;
8953 /* Fall through. */
8954 case 0xb: /* Post-increment. */
8955 postinc = 1;
8956 writeback = 1;
8957 break;
8958 case 0xd: /* Pre-decrement. */
8959 imm = -imm;
8960 /* Fall through. */
8961 case 0xf: /* Pre-increment. */
8962 tcg_gen_addi_i32(addr, addr, imm);
8963 writeback = 1;
8964 break;
8965 default:
8966 tcg_temp_free_i32(addr);
8967 goto illegal_op;
8971 if (insn & (1 << 20)) {
8972 /* Load. */
8973 switch (op) {
8974 case 0: tmp = gen_ld8u(addr, user); break;
8975 case 4: tmp = gen_ld8s(addr, user); break;
8976 case 1: tmp = gen_ld16u(addr, user); break;
8977 case 5: tmp = gen_ld16s(addr, user); break;
8978 case 2: tmp = gen_ld32(addr, user); break;
8979 default:
8980 tcg_temp_free_i32(addr);
8981 goto illegal_op;
8983 if (rs == 15) {
8984 gen_bx(s, tmp);
8985 } else {
8986 store_reg(s, rs, tmp);
8988 } else {
8989 /* Store. */
8990 tmp = load_reg(s, rs);
8991 switch (op) {
8992 case 0: gen_st8(tmp, addr, user); break;
8993 case 1: gen_st16(tmp, addr, user); break;
8994 case 2: gen_st32(tmp, addr, user); break;
8995 default:
8996 tcg_temp_free_i32(addr);
8997 goto illegal_op;
9000 if (postinc)
9001 tcg_gen_addi_i32(addr, addr, imm);
9002 if (writeback) {
9003 store_reg(s, rn, addr);
9004 } else {
9005 tcg_temp_free_i32(addr);
9008 break;
9009 default:
9010 goto illegal_op;
9012 return 0;
9013 illegal_op:
9014 return 1;
9017 static void disas_thumb_insn(CPUState *env, DisasContext *s)
9019 uint32_t val, insn, op, rm, rn, rd, shift, cond;
9020 int32_t offset;
9021 int i;
9022 TCGv tmp;
9023 TCGv tmp2;
9024 TCGv addr;
9026 if (s->condexec_mask) {
9027 cond = s->condexec_cond;
9028 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
9029 s->condlabel = gen_new_label();
9030 gen_test_cc(cond ^ 1, s->condlabel);
9031 s->condjmp = 1;
9035 insn = lduw_code(s->pc);
9036 s->pc += 2;
9038 switch (insn >> 12) {
9039 case 0: case 1:
9041 rd = insn & 7;
9042 op = (insn >> 11) & 3;
9043 if (op == 3) {
9044 /* add/subtract */
9045 rn = (insn >> 3) & 7;
9046 tmp = load_reg(s, rn);
9047 if (insn & (1 << 10)) {
9048 /* immediate */
9049 tmp2 = tcg_temp_new_i32();
9050 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
9051 } else {
9052 /* reg */
9053 rm = (insn >> 6) & 7;
9054 tmp2 = load_reg(s, rm);
9056 if (insn & (1 << 9)) {
9057 if (s->condexec_mask)
9058 tcg_gen_sub_i32(tmp, tmp, tmp2);
9059 else
9060 gen_helper_sub_cc(tmp, tmp, tmp2);
9061 } else {
9062 if (s->condexec_mask)
9063 tcg_gen_add_i32(tmp, tmp, tmp2);
9064 else
9065 gen_helper_add_cc(tmp, tmp, tmp2);
9067 tcg_temp_free_i32(tmp2);
9068 store_reg(s, rd, tmp);
9069 } else {
9070 /* shift immediate */
9071 rm = (insn >> 3) & 7;
9072 shift = (insn >> 6) & 0x1f;
9073 tmp = load_reg(s, rm);
9074 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
9075 if (!s->condexec_mask)
9076 gen_logic_CC(tmp);
9077 store_reg(s, rd, tmp);
9079 break;
9080 case 2: case 3:
9081 /* arithmetic large immediate */
9082 op = (insn >> 11) & 3;
9083 rd = (insn >> 8) & 0x7;
9084 if (op == 0) { /* mov */
9085 tmp = tcg_temp_new_i32();
9086 tcg_gen_movi_i32(tmp, insn & 0xff);
9087 if (!s->condexec_mask)
9088 gen_logic_CC(tmp);
9089 store_reg(s, rd, tmp);
9090 } else {
9091 tmp = load_reg(s, rd);
9092 tmp2 = tcg_temp_new_i32();
9093 tcg_gen_movi_i32(tmp2, insn & 0xff);
9094 switch (op) {
9095 case 1: /* cmp */
9096 gen_helper_sub_cc(tmp, tmp, tmp2);
9097 tcg_temp_free_i32(tmp);
9098 tcg_temp_free_i32(tmp2);
9099 break;
9100 case 2: /* add */
9101 if (s->condexec_mask)
9102 tcg_gen_add_i32(tmp, tmp, tmp2);
9103 else
9104 gen_helper_add_cc(tmp, tmp, tmp2);
9105 tcg_temp_free_i32(tmp2);
9106 store_reg(s, rd, tmp);
9107 break;
9108 case 3: /* sub */
9109 if (s->condexec_mask)
9110 tcg_gen_sub_i32(tmp, tmp, tmp2);
9111 else
9112 gen_helper_sub_cc(tmp, tmp, tmp2);
9113 tcg_temp_free_i32(tmp2);
9114 store_reg(s, rd, tmp);
9115 break;
9118 break;
9119 case 4:
9120 if (insn & (1 << 11)) {
9121 rd = (insn >> 8) & 7;
9122 /* load pc-relative. Bit 1 of PC is ignored. */
9123 val = s->pc + 2 + ((insn & 0xff) * 4);
9124 val &= ~(uint32_t)2;
9125 addr = tcg_temp_new_i32();
9126 tcg_gen_movi_i32(addr, val);
9127 tmp = gen_ld32(addr, IS_USER(s));
9128 tcg_temp_free_i32(addr);
9129 store_reg(s, rd, tmp);
9130 break;
9132 if (insn & (1 << 10)) {
9133 /* data processing extended or blx */
9134 rd = (insn & 7) | ((insn >> 4) & 8);
9135 rm = (insn >> 3) & 0xf;
9136 op = (insn >> 8) & 3;
9137 switch (op) {
9138 case 0: /* add */
9139 tmp = load_reg(s, rd);
9140 tmp2 = load_reg(s, rm);
9141 tcg_gen_add_i32(tmp, tmp, tmp2);
9142 tcg_temp_free_i32(tmp2);
9143 store_reg(s, rd, tmp);
9144 break;
9145 case 1: /* cmp */
9146 tmp = load_reg(s, rd);
9147 tmp2 = load_reg(s, rm);
9148 gen_helper_sub_cc(tmp, tmp, tmp2);
9149 tcg_temp_free_i32(tmp2);
9150 tcg_temp_free_i32(tmp);
9151 break;
9152 case 2: /* mov/cpy */
9153 tmp = load_reg(s, rm);
9154 store_reg(s, rd, tmp);
9155 break;
9156 case 3:/* branch [and link] exchange thumb register */
9157 tmp = load_reg(s, rm);
9158 if (insn & (1 << 7)) {
9159 ARCH(5);
9160 val = (uint32_t)s->pc | 1;
9161 tmp2 = tcg_temp_new_i32();
9162 tcg_gen_movi_i32(tmp2, val);
9163 store_reg(s, 14, tmp2);
9165 /* already thumb, no need to check */
9166 gen_bx(s, tmp);
9167 break;
9169 break;
9172 /* data processing register */
9173 rd = insn & 7;
9174 rm = (insn >> 3) & 7;
9175 op = (insn >> 6) & 0xf;
9176 if (op == 2 || op == 3 || op == 4 || op == 7) {
9177 /* the shift/rotate ops want the operands backwards */
9178 val = rm;
9179 rm = rd;
9180 rd = val;
9181 val = 1;
9182 } else {
9183 val = 0;
9186 if (op == 9) { /* neg */
9187 tmp = tcg_temp_new_i32();
9188 tcg_gen_movi_i32(tmp, 0);
9189 } else if (op != 0xf) { /* mvn doesn't read its first operand */
9190 tmp = load_reg(s, rd);
9191 } else {
9192 TCGV_UNUSED(tmp);
9195 tmp2 = load_reg(s, rm);
9196 switch (op) {
9197 case 0x0: /* and */
9198 tcg_gen_and_i32(tmp, tmp, tmp2);
9199 if (!s->condexec_mask)
9200 gen_logic_CC(tmp);
9201 break;
9202 case 0x1: /* eor */
9203 tcg_gen_xor_i32(tmp, tmp, tmp2);
9204 if (!s->condexec_mask)
9205 gen_logic_CC(tmp);
9206 break;
9207 case 0x2: /* lsl */
9208 if (s->condexec_mask) {
9209 gen_helper_shl(tmp2, tmp2, tmp);
9210 } else {
9211 gen_helper_shl_cc(tmp2, tmp2, tmp);
9212 gen_logic_CC(tmp2);
9214 break;
9215 case 0x3: /* lsr */
9216 if (s->condexec_mask) {
9217 gen_helper_shr(tmp2, tmp2, tmp);
9218 } else {
9219 gen_helper_shr_cc(tmp2, tmp2, tmp);
9220 gen_logic_CC(tmp2);
9222 break;
9223 case 0x4: /* asr */
9224 if (s->condexec_mask) {
9225 gen_helper_sar(tmp2, tmp2, tmp);
9226 } else {
9227 gen_helper_sar_cc(tmp2, tmp2, tmp);
9228 gen_logic_CC(tmp2);
9230 break;
9231 case 0x5: /* adc */
9232 if (s->condexec_mask)
9233 gen_adc(tmp, tmp2);
9234 else
9235 gen_helper_adc_cc(tmp, tmp, tmp2);
9236 break;
9237 case 0x6: /* sbc */
9238 if (s->condexec_mask)
9239 gen_sub_carry(tmp, tmp, tmp2);
9240 else
9241 gen_helper_sbc_cc(tmp, tmp, tmp2);
9242 break;
9243 case 0x7: /* ror */
9244 if (s->condexec_mask) {
9245 tcg_gen_andi_i32(tmp, tmp, 0x1f);
9246 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
9247 } else {
9248 gen_helper_ror_cc(tmp2, tmp2, tmp);
9249 gen_logic_CC(tmp2);
9251 break;
9252 case 0x8: /* tst */
9253 tcg_gen_and_i32(tmp, tmp, tmp2);
9254 gen_logic_CC(tmp);
9255 rd = 16;
9256 break;
9257 case 0x9: /* neg */
9258 if (s->condexec_mask)
9259 tcg_gen_neg_i32(tmp, tmp2);
9260 else
9261 gen_helper_sub_cc(tmp, tmp, tmp2);
9262 break;
9263 case 0xa: /* cmp */
9264 gen_helper_sub_cc(tmp, tmp, tmp2);
9265 rd = 16;
9266 break;
9267 case 0xb: /* cmn */
9268 gen_helper_add_cc(tmp, tmp, tmp2);
9269 rd = 16;
9270 break;
9271 case 0xc: /* orr */
9272 tcg_gen_or_i32(tmp, tmp, tmp2);
9273 if (!s->condexec_mask)
9274 gen_logic_CC(tmp);
9275 break;
9276 case 0xd: /* mul */
9277 tcg_gen_mul_i32(tmp, tmp, tmp2);
9278 if (!s->condexec_mask)
9279 gen_logic_CC(tmp);
9280 break;
9281 case 0xe: /* bic */
9282 tcg_gen_andc_i32(tmp, tmp, tmp2);
9283 if (!s->condexec_mask)
9284 gen_logic_CC(tmp);
9285 break;
9286 case 0xf: /* mvn */
9287 tcg_gen_not_i32(tmp2, tmp2);
9288 if (!s->condexec_mask)
9289 gen_logic_CC(tmp2);
9290 val = 1;
9291 rm = rd;
9292 break;
9294 if (rd != 16) {
9295 if (val) {
9296 store_reg(s, rm, tmp2);
9297 if (op != 0xf)
9298 tcg_temp_free_i32(tmp);
9299 } else {
9300 store_reg(s, rd, tmp);
9301 tcg_temp_free_i32(tmp2);
9303 } else {
9304 tcg_temp_free_i32(tmp);
9305 tcg_temp_free_i32(tmp2);
9307 break;
9309 case 5:
9310 /* load/store register offset. */
9311 rd = insn & 7;
9312 rn = (insn >> 3) & 7;
9313 rm = (insn >> 6) & 7;
9314 op = (insn >> 9) & 7;
9315 addr = load_reg(s, rn);
9316 tmp = load_reg(s, rm);
9317 tcg_gen_add_i32(addr, addr, tmp);
9318 tcg_temp_free_i32(tmp);
9320 if (op < 3) /* store */
9321 tmp = load_reg(s, rd);
9323 switch (op) {
9324 case 0: /* str */
9325 gen_st32(tmp, addr, IS_USER(s));
9326 break;
9327 case 1: /* strh */
9328 gen_st16(tmp, addr, IS_USER(s));
9329 break;
9330 case 2: /* strb */
9331 gen_st8(tmp, addr, IS_USER(s));
9332 break;
9333 case 3: /* ldrsb */
9334 tmp = gen_ld8s(addr, IS_USER(s));
9335 break;
9336 case 4: /* ldr */
9337 tmp = gen_ld32(addr, IS_USER(s));
9338 break;
9339 case 5: /* ldrh */
9340 tmp = gen_ld16u(addr, IS_USER(s));
9341 break;
9342 case 6: /* ldrb */
9343 tmp = gen_ld8u(addr, IS_USER(s));
9344 break;
9345 case 7: /* ldrsh */
9346 tmp = gen_ld16s(addr, IS_USER(s));
9347 break;
9349 if (op >= 3) /* load */
9350 store_reg(s, rd, tmp);
9351 tcg_temp_free_i32(addr);
9352 break;
9354 case 6:
9355 /* load/store word immediate offset */
9356 rd = insn & 7;
9357 rn = (insn >> 3) & 7;
9358 addr = load_reg(s, rn);
9359 val = (insn >> 4) & 0x7c;
9360 tcg_gen_addi_i32(addr, addr, val);
9362 if (insn & (1 << 11)) {
9363 /* load */
9364 tmp = gen_ld32(addr, IS_USER(s));
9365 store_reg(s, rd, tmp);
9366 } else {
9367 /* store */
9368 tmp = load_reg(s, rd);
9369 gen_st32(tmp, addr, IS_USER(s));
9371 tcg_temp_free_i32(addr);
9372 break;
9374 case 7:
9375 /* load/store byte immediate offset */
9376 rd = insn & 7;
9377 rn = (insn >> 3) & 7;
9378 addr = load_reg(s, rn);
9379 val = (insn >> 6) & 0x1f;
9380 tcg_gen_addi_i32(addr, addr, val);
9382 if (insn & (1 << 11)) {
9383 /* load */
9384 tmp = gen_ld8u(addr, IS_USER(s));
9385 store_reg(s, rd, tmp);
9386 } else {
9387 /* store */
9388 tmp = load_reg(s, rd);
9389 gen_st8(tmp, addr, IS_USER(s));
9391 tcg_temp_free_i32(addr);
9392 break;
9394 case 8:
9395 /* load/store halfword immediate offset */
9396 rd = insn & 7;
9397 rn = (insn >> 3) & 7;
9398 addr = load_reg(s, rn);
9399 val = (insn >> 5) & 0x3e;
9400 tcg_gen_addi_i32(addr, addr, val);
9402 if (insn & (1 << 11)) {
9403 /* load */
9404 tmp = gen_ld16u(addr, IS_USER(s));
9405 store_reg(s, rd, tmp);
9406 } else {
9407 /* store */
9408 tmp = load_reg(s, rd);
9409 gen_st16(tmp, addr, IS_USER(s));
9411 tcg_temp_free_i32(addr);
9412 break;
9414 case 9:
9415 /* load/store from stack */
9416 rd = (insn >> 8) & 7;
9417 addr = load_reg(s, 13);
9418 val = (insn & 0xff) * 4;
9419 tcg_gen_addi_i32(addr, addr, val);
9421 if (insn & (1 << 11)) {
9422 /* load */
9423 tmp = gen_ld32(addr, IS_USER(s));
9424 store_reg(s, rd, tmp);
9425 } else {
9426 /* store */
9427 tmp = load_reg(s, rd);
9428 gen_st32(tmp, addr, IS_USER(s));
9430 tcg_temp_free_i32(addr);
9431 break;
9433 case 10:
9434 /* add to high reg */
9435 rd = (insn >> 8) & 7;
9436 if (insn & (1 << 11)) {
9437 /* SP */
9438 tmp = load_reg(s, 13);
9439 } else {
9440 /* PC. bit 1 is ignored. */
9441 tmp = tcg_temp_new_i32();
9442 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
9444 val = (insn & 0xff) * 4;
9445 tcg_gen_addi_i32(tmp, tmp, val);
9446 store_reg(s, rd, tmp);
9447 break;
9449 case 11:
9450 /* misc */
9451 op = (insn >> 8) & 0xf;
9452 switch (op) {
9453 case 0:
9454 /* adjust stack pointer */
9455 tmp = load_reg(s, 13);
9456 val = (insn & 0x7f) * 4;
9457 if (insn & (1 << 7))
9458 val = -(int32_t)val;
9459 tcg_gen_addi_i32(tmp, tmp, val);
9460 store_reg(s, 13, tmp);
9461 break;
9463 case 2: /* sign/zero extend. */
9464 ARCH(6);
9465 rd = insn & 7;
9466 rm = (insn >> 3) & 7;
9467 tmp = load_reg(s, rm);
9468 switch ((insn >> 6) & 3) {
9469 case 0: gen_sxth(tmp); break;
9470 case 1: gen_sxtb(tmp); break;
9471 case 2: gen_uxth(tmp); break;
9472 case 3: gen_uxtb(tmp); break;
9474 store_reg(s, rd, tmp);
9475 break;
9476 case 4: case 5: case 0xc: case 0xd:
9477 /* push/pop */
9478 addr = load_reg(s, 13);
9479 if (insn & (1 << 8))
9480 offset = 4;
9481 else
9482 offset = 0;
9483 for (i = 0; i < 8; i++) {
9484 if (insn & (1 << i))
9485 offset += 4;
9487 if ((insn & (1 << 11)) == 0) {
9488 tcg_gen_addi_i32(addr, addr, -offset);
9490 for (i = 0; i < 8; i++) {
9491 if (insn & (1 << i)) {
9492 if (insn & (1 << 11)) {
9493 /* pop */
9494 tmp = gen_ld32(addr, IS_USER(s));
9495 store_reg(s, i, tmp);
9496 } else {
9497 /* push */
9498 tmp = load_reg(s, i);
9499 gen_st32(tmp, addr, IS_USER(s));
9501 /* advance to the next address. */
9502 tcg_gen_addi_i32(addr, addr, 4);
9505 TCGV_UNUSED(tmp);
9506 if (insn & (1 << 8)) {
9507 if (insn & (1 << 11)) {
9508 /* pop pc */
9509 tmp = gen_ld32(addr, IS_USER(s));
9510 /* don't set the pc until the rest of the instruction
9511 has completed */
9512 } else {
9513 /* push lr */
9514 tmp = load_reg(s, 14);
9515 gen_st32(tmp, addr, IS_USER(s));
9517 tcg_gen_addi_i32(addr, addr, 4);
9519 if ((insn & (1 << 11)) == 0) {
9520 tcg_gen_addi_i32(addr, addr, -offset);
9522 /* write back the new stack pointer */
9523 store_reg(s, 13, addr);
9524 /* set the new PC value */
9525 if ((insn & 0x0900) == 0x0900) {
9526 store_reg_from_load(env, s, 15, tmp);
9528 break;
9530 case 1: case 3: case 9: case 11: /* czb */
9531 rm = insn & 7;
9532 tmp = load_reg(s, rm);
9533 s->condlabel = gen_new_label();
9534 s->condjmp = 1;
9535 if (insn & (1 << 11))
9536 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
9537 else
9538 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
9539 tcg_temp_free_i32(tmp);
9540 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
9541 val = (uint32_t)s->pc + 2;
9542 val += offset;
9543 gen_jmp(s, val);
9544 break;
9546 case 15: /* IT, nop-hint. */
9547 if ((insn & 0xf) == 0) {
9548 gen_nop_hint(s, (insn >> 4) & 0xf);
9549 break;
9551 /* If Then. */
9552 s->condexec_cond = (insn >> 4) & 0xe;
9553 s->condexec_mask = insn & 0x1f;
9554 /* No actual code generated for this insn, just setup state. */
9555 break;
9557 case 0xe: /* bkpt */
9558 ARCH(5);
9559 gen_exception_insn(s, 2, EXCP_BKPT);
9560 break;
9562 case 0xa: /* rev */
9563 ARCH(6);
9564 rn = (insn >> 3) & 0x7;
9565 rd = insn & 0x7;
9566 tmp = load_reg(s, rn);
9567 switch ((insn >> 6) & 3) {
9568 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
9569 case 1: gen_rev16(tmp); break;
9570 case 3: gen_revsh(tmp); break;
9571 default: goto illegal_op;
9573 store_reg(s, rd, tmp);
9574 break;
9576 case 6: /* cps */
9577 ARCH(6);
9578 if (IS_USER(s))
9579 break;
9580 if (IS_M(env)) {
9581 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
9582 /* PRIMASK */
9583 if (insn & 1) {
9584 addr = tcg_const_i32(16);
9585 gen_helper_v7m_msr(cpu_env, addr, tmp);
9586 tcg_temp_free_i32(addr);
9588 /* FAULTMASK */
9589 if (insn & 2) {
9590 addr = tcg_const_i32(17);
9591 gen_helper_v7m_msr(cpu_env, addr, tmp);
9592 tcg_temp_free_i32(addr);
9594 tcg_temp_free_i32(tmp);
9595 gen_lookup_tb(s);
9596 } else {
9597 if (insn & (1 << 4))
9598 shift = CPSR_A | CPSR_I | CPSR_F;
9599 else
9600 shift = 0;
9601 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
9603 break;
9605 default:
9606 goto undef;
9608 break;
9610 case 12:
9612 /* load/store multiple */
9613 TCGv loaded_var;
9614 TCGV_UNUSED(loaded_var);
9615 rn = (insn >> 8) & 0x7;
9616 addr = load_reg(s, rn);
9617 for (i = 0; i < 8; i++) {
9618 if (insn & (1 << i)) {
9619 if (insn & (1 << 11)) {
9620 /* load */
9621 tmp = gen_ld32(addr, IS_USER(s));
9622 if (i == rn) {
9623 loaded_var = tmp;
9624 } else {
9625 store_reg(s, i, tmp);
9627 } else {
9628 /* store */
9629 tmp = load_reg(s, i);
9630 gen_st32(tmp, addr, IS_USER(s));
9632 /* advance to the next address */
9633 tcg_gen_addi_i32(addr, addr, 4);
9636 if ((insn & (1 << rn)) == 0) {
9637 /* base reg not in list: base register writeback */
9638 store_reg(s, rn, addr);
9639 } else {
9640 /* base reg in list: if load, complete it now */
9641 if (insn & (1 << 11)) {
9642 store_reg(s, rn, loaded_var);
9644 tcg_temp_free_i32(addr);
9646 break;
9648 case 13:
9649 /* conditional branch or swi */
9650 cond = (insn >> 8) & 0xf;
9651 if (cond == 0xe)
9652 goto undef;
9654 if (cond == 0xf) {
9655 /* swi */
9656 gen_set_pc_im(s->pc);
9657 s->is_jmp = DISAS_SWI;
9658 break;
9660 /* generate a conditional jump to next instruction */
9661 s->condlabel = gen_new_label();
9662 gen_test_cc(cond ^ 1, s->condlabel);
9663 s->condjmp = 1;
9665 /* jump to the offset */
9666 val = (uint32_t)s->pc + 2;
9667 offset = ((int32_t)insn << 24) >> 24;
9668 val += offset << 1;
9669 gen_jmp(s, val);
9670 break;
9672 case 14:
9673 if (insn & (1 << 11)) {
9674 if (disas_thumb2_insn(env, s, insn))
9675 goto undef32;
9676 break;
9678 /* unconditional branch */
9679 val = (uint32_t)s->pc;
9680 offset = ((int32_t)insn << 21) >> 21;
9681 val += (offset << 1) + 2;
9682 gen_jmp(s, val);
9683 break;
9685 case 15:
9686 if (disas_thumb2_insn(env, s, insn))
9687 goto undef32;
9688 break;
9690 return;
9691 undef32:
9692 gen_exception_insn(s, 4, EXCP_UDEF);
9693 return;
9694 illegal_op:
9695 undef:
9696 gen_exception_insn(s, 2, EXCP_UDEF);
9699 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
9700 basic block 'tb'. If search_pc is TRUE, also generate PC
9701 information for each intermediate instruction. */
9702 static inline void gen_intermediate_code_internal(CPUState *env,
9703 TranslationBlock *tb,
9704 int search_pc)
9706 DisasContext dc1, *dc = &dc1;
9707 CPUBreakpoint *bp;
9708 uint16_t *gen_opc_end;
9709 int j, lj;
9710 target_ulong pc_start;
9711 uint32_t next_page_start;
9712 int num_insns;
9713 int max_insns;
9715 /* generate intermediate code */
9716 pc_start = tb->pc;
9718 dc->tb = tb;
9720 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
9722 dc->is_jmp = DISAS_NEXT;
9723 dc->pc = pc_start;
9724 dc->singlestep_enabled = env->singlestep_enabled;
9725 dc->condjmp = 0;
9726 dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
9727 dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
9728 dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
9729 #if !defined(CONFIG_USER_ONLY)
9730 dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
9731 #endif
9732 dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
9733 dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
9734 dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
9735 cpu_F0s = tcg_temp_new_i32();
9736 cpu_F1s = tcg_temp_new_i32();
9737 cpu_F0d = tcg_temp_new_i64();
9738 cpu_F1d = tcg_temp_new_i64();
9739 cpu_V0 = cpu_F0d;
9740 cpu_V1 = cpu_F1d;
9741 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
9742 cpu_M0 = tcg_temp_new_i64();
9743 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
9744 lj = -1;
9745 num_insns = 0;
9746 max_insns = tb->cflags & CF_COUNT_MASK;
9747 if (max_insns == 0)
9748 max_insns = CF_COUNT_MASK;
9750 gen_icount_start();
9752 tcg_clear_temp_count();
9754 /* A note on handling of the condexec (IT) bits:
9756 * We want to avoid the overhead of having to write the updated condexec
9757 * bits back to the CPUState for every instruction in an IT block. So:
9758 * (1) if the condexec bits are not already zero then we write
9759 * zero back into the CPUState now. This avoids complications trying
9760 * to do it at the end of the block. (For example if we don't do this
9761 * it's hard to identify whether we can safely skip writing condexec
9762 * at the end of the TB, which we definitely want to do for the case
9763 * where a TB doesn't do anything with the IT state at all.)
9764 * (2) if we are going to leave the TB then we call gen_set_condexec()
9765 * which will write the correct value into CPUState if zero is wrong.
9766 * This is done both for leaving the TB at the end, and for leaving
9767 * it because of an exception we know will happen, which is done in
9768 * gen_exception_insn(). The latter is necessary because we need to
9769 * leave the TB with the PC/IT state just prior to execution of the
9770 * instruction which caused the exception.
9771 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
9772 * then the CPUState will be wrong and we need to reset it.
9773 * This is handled in the same way as restoration of the
9774 * PC in these situations: we will be called again with search_pc=1
9775 * and generate a mapping of the condexec bits for each PC in
9776 * gen_opc_condexec_bits[]. restore_state_to_opc() then uses
9777 * this to restore the condexec bits.
9779 * Note that there are no instructions which can read the condexec
9780 * bits, and none which can write non-static values to them, so
9781 * we don't need to care about whether CPUState is correct in the
9782 * middle of a TB.
9785 /* Reset the conditional execution bits immediately. This avoids
9786 complications trying to do it at the end of the block. */
9787 if (dc->condexec_mask || dc->condexec_cond)
9789 TCGv tmp = tcg_temp_new_i32();
9790 tcg_gen_movi_i32(tmp, 0);
9791 store_cpu_field(tmp, condexec_bits);
9793 do {
9794 #ifdef CONFIG_USER_ONLY
9795 /* Intercept jump to the magic kernel page. */
9796 if (dc->pc >= 0xffff0000) {
9797 /* We always get here via a jump, so know we are not in a
9798 conditional execution block. */
9799 gen_exception(EXCP_KERNEL_TRAP);
9800 dc->is_jmp = DISAS_UPDATE;
9801 break;
9803 #else
9804 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
9805 /* We always get here via a jump, so know we are not in a
9806 conditional execution block. */
9807 gen_exception(EXCP_EXCEPTION_EXIT);
9808 dc->is_jmp = DISAS_UPDATE;
9809 break;
9811 #endif
9813 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
9814 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
9815 if (bp->pc == dc->pc) {
9816 gen_exception_insn(dc, 0, EXCP_DEBUG);
9817 /* Advance PC so that clearing the breakpoint will
9818 invalidate this TB. */
9819 dc->pc += 2;
9820 goto done_generating;
9821 break;
9825 if (search_pc) {
9826 j = gen_opc_ptr - gen_opc_buf;
9827 if (lj < j) {
9828 lj++;
9829 while (lj < j)
9830 gen_opc_instr_start[lj++] = 0;
9832 gen_opc_pc[lj] = dc->pc;
9833 gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
9834 gen_opc_instr_start[lj] = 1;
9835 gen_opc_icount[lj] = num_insns;
9838 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
9839 gen_io_start();
9841 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
9842 tcg_gen_debug_insn_start(dc->pc);
9845 if (dc->thumb) {
9846 disas_thumb_insn(env, dc);
9847 if (dc->condexec_mask) {
9848 dc->condexec_cond = (dc->condexec_cond & 0xe)
9849 | ((dc->condexec_mask >> 4) & 1);
9850 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
9851 if (dc->condexec_mask == 0) {
9852 dc->condexec_cond = 0;
9855 } else {
9856 disas_arm_insn(env, dc);
9859 if (dc->condjmp && !dc->is_jmp) {
9860 gen_set_label(dc->condlabel);
9861 dc->condjmp = 0;
9864 if (tcg_check_temp_count()) {
9865 fprintf(stderr, "TCG temporary leak before %08x\n", dc->pc);
9868 /* Translation stops when a conditional branch is encountered.
9869 * Otherwise the subsequent code could get translated several times.
9870 * Also stop translation when a page boundary is reached. This
9871 * ensures prefetch aborts occur at the right place. */
9872 num_insns ++;
9873 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
9874 !env->singlestep_enabled &&
9875 !singlestep &&
9876 dc->pc < next_page_start &&
9877 num_insns < max_insns);
9879 if (tb->cflags & CF_LAST_IO) {
9880 if (dc->condjmp) {
9881 /* FIXME: This can theoretically happen with self-modifying
9882 code. */
9883 cpu_abort(env, "IO on conditional branch instruction");
9885 gen_io_end();
9888 /* At this stage dc->condjmp will only be set when the skipped
9889 instruction was a conditional branch or trap, and the PC has
9890 already been written. */
9891 if (unlikely(env->singlestep_enabled)) {
9892 /* Make sure the pc is updated, and raise a debug exception. */
9893 if (dc->condjmp) {
9894 gen_set_condexec(dc);
9895 if (dc->is_jmp == DISAS_SWI) {
9896 gen_exception(EXCP_SWI);
9897 } else {
9898 gen_exception(EXCP_DEBUG);
9900 gen_set_label(dc->condlabel);
9902 if (dc->condjmp || !dc->is_jmp) {
9903 gen_set_pc_im(dc->pc);
9904 dc->condjmp = 0;
9906 gen_set_condexec(dc);
9907 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
9908 gen_exception(EXCP_SWI);
9909 } else {
9910 /* FIXME: Single stepping a WFI insn will not halt
9911 the CPU. */
9912 gen_exception(EXCP_DEBUG);
9914 } else {
9915 /* While branches must always occur at the end of an IT block,
9916 there are a few other things that can cause us to terminate
9917 the TB in the middel of an IT block:
9918 - Exception generating instructions (bkpt, swi, undefined).
9919 - Page boundaries.
9920 - Hardware watchpoints.
9921 Hardware breakpoints have already been handled and skip this code.
9923 gen_set_condexec(dc);
9924 switch(dc->is_jmp) {
9925 case DISAS_NEXT:
9926 gen_goto_tb(dc, 1, dc->pc);
9927 break;
9928 default:
9929 case DISAS_JUMP:
9930 case DISAS_UPDATE:
9931 /* indicate that the hash table must be used to find the next TB */
9932 tcg_gen_exit_tb(0);
9933 break;
9934 case DISAS_TB_JUMP:
9935 /* nothing more to generate */
9936 break;
9937 case DISAS_WFI:
9938 gen_helper_wfi();
9939 break;
9940 case DISAS_SWI:
9941 gen_exception(EXCP_SWI);
9942 break;
9944 if (dc->condjmp) {
9945 gen_set_label(dc->condlabel);
9946 gen_set_condexec(dc);
9947 gen_goto_tb(dc, 1, dc->pc);
9948 dc->condjmp = 0;
9952 done_generating:
9953 gen_icount_end(tb, num_insns);
9954 *gen_opc_ptr = INDEX_op_end;
9956 #ifdef DEBUG_DISAS
9957 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9958 qemu_log("----------------\n");
9959 qemu_log("IN: %s\n", lookup_symbol(pc_start));
9960 log_target_disas(pc_start, dc->pc - pc_start, dc->thumb);
9961 qemu_log("\n");
9963 #endif
9964 if (search_pc) {
9965 j = gen_opc_ptr - gen_opc_buf;
9966 lj++;
9967 while (lj <= j)
9968 gen_opc_instr_start[lj++] = 0;
9969 } else {
9970 tb->size = dc->pc - pc_start;
9971 tb->icount = num_insns;
9975 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
9977 gen_intermediate_code_internal(env, tb, 0);
9980 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
9982 gen_intermediate_code_internal(env, tb, 1);
9985 static const char *cpu_mode_names[16] = {
9986 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9987 "???", "???", "???", "und", "???", "???", "???", "sys"
9990 void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
9991 int flags)
9993 int i;
9994 #if 0
9995 union {
9996 uint32_t i;
9997 float s;
9998 } s0, s1;
9999 CPU_DoubleU d;
10000 /* ??? This assumes float64 and double have the same layout.
10001 Oh well, it's only debug dumps. */
10002 union {
10003 float64 f64;
10004 double d;
10005 } d0;
10006 #endif
10007 uint32_t psr;
10009 for(i=0;i<16;i++) {
10010 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
10011 if ((i % 4) == 3)
10012 cpu_fprintf(f, "\n");
10013 else
10014 cpu_fprintf(f, " ");
10016 psr = cpsr_read(env);
10017 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
10018 psr,
10019 psr & (1 << 31) ? 'N' : '-',
10020 psr & (1 << 30) ? 'Z' : '-',
10021 psr & (1 << 29) ? 'C' : '-',
10022 psr & (1 << 28) ? 'V' : '-',
10023 psr & CPSR_T ? 'T' : 'A',
10024 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
10026 #if 0
10027 for (i = 0; i < 16; i++) {
10028 d.d = env->vfp.regs[i];
10029 s0.i = d.l.lower;
10030 s1.i = d.l.upper;
10031 d0.f64 = d.d;
10032 cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
10033 i * 2, (int)s0.i, s0.s,
10034 i * 2 + 1, (int)s1.i, s1.s,
10035 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
10036 d0.d);
10038 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
10039 #endif
10042 void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
10044 env->regs[15] = gen_opc_pc[pc_pos];
10045 env->condexec_bits = gen_opc_condexec_bits[pc_pos];