target-arm: Don't generate code specific to current CPU mode for SRS
[qemu.git] / target-arm / translate.c
blobee19d7631d3245a4da473970f137cfb94847f827
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 "exec-all.h"
29 #include "disas.h"
30 #include "tcg-op.h"
31 #include "qemu-log.h"
33 #include "helpers.h"
34 #define GEN_HELPER 1
35 #include "helpers.h"
37 #define ENABLE_ARCH_5J 0
38 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
39 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
40 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
41 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
43 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
45 /* internal defines */
46 typedef struct DisasContext {
47 target_ulong pc;
48 int is_jmp;
49 /* Nonzero if this instruction has been conditionally skipped. */
50 int condjmp;
51 /* The label that will be jumped to when the instruction is skipped. */
52 int condlabel;
53 /* Thumb-2 condtional execution bits. */
54 int condexec_mask;
55 int condexec_cond;
56 struct TranslationBlock *tb;
57 int singlestep_enabled;
58 int thumb;
59 #if !defined(CONFIG_USER_ONLY)
60 int user;
61 #endif
62 } DisasContext;
64 #if defined(CONFIG_USER_ONLY)
65 #define IS_USER(s) 1
66 #else
67 #define IS_USER(s) (s->user)
68 #endif
70 /* These instructions trap after executing, so defer them until after the
71 conditional executions state has been updated. */
72 #define DISAS_WFI 4
73 #define DISAS_SWI 5
75 static TCGv_ptr cpu_env;
76 /* We reuse the same 64-bit temporaries for efficiency. */
77 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
78 static TCGv_i32 cpu_R[16];
79 static TCGv_i32 cpu_exclusive_addr;
80 static TCGv_i32 cpu_exclusive_val;
81 static TCGv_i32 cpu_exclusive_high;
82 #ifdef CONFIG_USER_ONLY
83 static TCGv_i32 cpu_exclusive_test;
84 static TCGv_i32 cpu_exclusive_info;
85 #endif
87 /* FIXME: These should be removed. */
88 static TCGv cpu_F0s, cpu_F1s;
89 static TCGv_i64 cpu_F0d, cpu_F1d;
91 #include "gen-icount.h"
93 static const char *regnames[] =
94 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
95 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
97 /* initialize TCG globals. */
98 void arm_translate_init(void)
100 int i;
102 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
104 for (i = 0; i < 16; i++) {
105 cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
106 offsetof(CPUState, regs[i]),
107 regnames[i]);
109 cpu_exclusive_addr = tcg_global_mem_new_i32(TCG_AREG0,
110 offsetof(CPUState, exclusive_addr), "exclusive_addr");
111 cpu_exclusive_val = tcg_global_mem_new_i32(TCG_AREG0,
112 offsetof(CPUState, exclusive_val), "exclusive_val");
113 cpu_exclusive_high = tcg_global_mem_new_i32(TCG_AREG0,
114 offsetof(CPUState, exclusive_high), "exclusive_high");
115 #ifdef CONFIG_USER_ONLY
116 cpu_exclusive_test = tcg_global_mem_new_i32(TCG_AREG0,
117 offsetof(CPUState, exclusive_test), "exclusive_test");
118 cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0,
119 offsetof(CPUState, exclusive_info), "exclusive_info");
120 #endif
122 #define GEN_HELPER 2
123 #include "helpers.h"
126 static int num_temps;
128 /* Allocate a temporary variable. */
129 static TCGv_i32 new_tmp(void)
131 num_temps++;
132 return tcg_temp_new_i32();
135 /* Release a temporary variable. */
136 static void dead_tmp(TCGv tmp)
138 tcg_temp_free(tmp);
139 num_temps--;
142 static inline TCGv load_cpu_offset(int offset)
144 TCGv tmp = new_tmp();
145 tcg_gen_ld_i32(tmp, cpu_env, offset);
146 return tmp;
149 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
151 static inline void store_cpu_offset(TCGv var, int offset)
153 tcg_gen_st_i32(var, cpu_env, offset);
154 dead_tmp(var);
157 #define store_cpu_field(var, name) \
158 store_cpu_offset(var, offsetof(CPUState, name))
160 /* Set a variable to the value of a CPU register. */
161 static void load_reg_var(DisasContext *s, TCGv var, int reg)
163 if (reg == 15) {
164 uint32_t addr;
165 /* normaly, since we updated PC, we need only to add one insn */
166 if (s->thumb)
167 addr = (long)s->pc + 2;
168 else
169 addr = (long)s->pc + 4;
170 tcg_gen_movi_i32(var, addr);
171 } else {
172 tcg_gen_mov_i32(var, cpu_R[reg]);
176 /* Create a new temporary and set it to the value of a CPU register. */
177 static inline TCGv load_reg(DisasContext *s, int reg)
179 TCGv tmp = new_tmp();
180 load_reg_var(s, tmp, reg);
181 return tmp;
184 /* Set a CPU register. The source must be a temporary and will be
185 marked as dead. */
186 static void store_reg(DisasContext *s, int reg, TCGv var)
188 if (reg == 15) {
189 tcg_gen_andi_i32(var, var, ~1);
190 s->is_jmp = DISAS_JUMP;
192 tcg_gen_mov_i32(cpu_R[reg], var);
193 dead_tmp(var);
196 /* Value extensions. */
197 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
198 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
199 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
200 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
202 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
203 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
206 static inline void gen_set_cpsr(TCGv var, uint32_t mask)
208 TCGv tmp_mask = tcg_const_i32(mask);
209 gen_helper_cpsr_write(var, tmp_mask);
210 tcg_temp_free_i32(tmp_mask);
212 /* Set NZCV flags from the high 4 bits of var. */
213 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
215 static void gen_exception(int excp)
217 TCGv tmp = new_tmp();
218 tcg_gen_movi_i32(tmp, excp);
219 gen_helper_exception(tmp);
220 dead_tmp(tmp);
223 static void gen_smul_dual(TCGv a, TCGv b)
225 TCGv tmp1 = new_tmp();
226 TCGv tmp2 = new_tmp();
227 tcg_gen_ext16s_i32(tmp1, a);
228 tcg_gen_ext16s_i32(tmp2, b);
229 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
230 dead_tmp(tmp2);
231 tcg_gen_sari_i32(a, a, 16);
232 tcg_gen_sari_i32(b, b, 16);
233 tcg_gen_mul_i32(b, b, a);
234 tcg_gen_mov_i32(a, tmp1);
235 dead_tmp(tmp1);
238 /* Byteswap each halfword. */
239 static void gen_rev16(TCGv var)
241 TCGv tmp = new_tmp();
242 tcg_gen_shri_i32(tmp, var, 8);
243 tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
244 tcg_gen_shli_i32(var, var, 8);
245 tcg_gen_andi_i32(var, var, 0xff00ff00);
246 tcg_gen_or_i32(var, var, tmp);
247 dead_tmp(tmp);
250 /* Byteswap low halfword and sign extend. */
251 static void gen_revsh(TCGv var)
253 tcg_gen_ext16u_i32(var, var);
254 tcg_gen_bswap16_i32(var, var);
255 tcg_gen_ext16s_i32(var, var);
258 /* Unsigned bitfield extract. */
259 static void gen_ubfx(TCGv var, int shift, uint32_t mask)
261 if (shift)
262 tcg_gen_shri_i32(var, var, shift);
263 tcg_gen_andi_i32(var, var, mask);
266 /* Signed bitfield extract. */
267 static void gen_sbfx(TCGv var, int shift, int width)
269 uint32_t signbit;
271 if (shift)
272 tcg_gen_sari_i32(var, var, shift);
273 if (shift + width < 32) {
274 signbit = 1u << (width - 1);
275 tcg_gen_andi_i32(var, var, (1u << width) - 1);
276 tcg_gen_xori_i32(var, var, signbit);
277 tcg_gen_subi_i32(var, var, signbit);
281 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
282 static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
284 tcg_gen_andi_i32(val, val, mask);
285 tcg_gen_shli_i32(val, val, shift);
286 tcg_gen_andi_i32(base, base, ~(mask << shift));
287 tcg_gen_or_i32(dest, base, val);
290 /* Return (b << 32) + a. Mark inputs as dead */
291 static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv b)
293 TCGv_i64 tmp64 = tcg_temp_new_i64();
295 tcg_gen_extu_i32_i64(tmp64, b);
296 dead_tmp(b);
297 tcg_gen_shli_i64(tmp64, tmp64, 32);
298 tcg_gen_add_i64(a, tmp64, a);
300 tcg_temp_free_i64(tmp64);
301 return a;
304 /* Return (b << 32) - a. Mark inputs as dead. */
305 static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv b)
307 TCGv_i64 tmp64 = tcg_temp_new_i64();
309 tcg_gen_extu_i32_i64(tmp64, b);
310 dead_tmp(b);
311 tcg_gen_shli_i64(tmp64, tmp64, 32);
312 tcg_gen_sub_i64(a, tmp64, a);
314 tcg_temp_free_i64(tmp64);
315 return a;
318 /* FIXME: Most targets have native widening multiplication.
319 It would be good to use that instead of a full wide multiply. */
320 /* 32x32->64 multiply. Marks inputs as dead. */
321 static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b)
323 TCGv_i64 tmp1 = tcg_temp_new_i64();
324 TCGv_i64 tmp2 = tcg_temp_new_i64();
326 tcg_gen_extu_i32_i64(tmp1, a);
327 dead_tmp(a);
328 tcg_gen_extu_i32_i64(tmp2, b);
329 dead_tmp(b);
330 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
331 tcg_temp_free_i64(tmp2);
332 return tmp1;
335 static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
337 TCGv_i64 tmp1 = tcg_temp_new_i64();
338 TCGv_i64 tmp2 = tcg_temp_new_i64();
340 tcg_gen_ext_i32_i64(tmp1, a);
341 dead_tmp(a);
342 tcg_gen_ext_i32_i64(tmp2, b);
343 dead_tmp(b);
344 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
345 tcg_temp_free_i64(tmp2);
346 return tmp1;
349 /* Swap low and high halfwords. */
350 static void gen_swap_half(TCGv var)
352 TCGv tmp = new_tmp();
353 tcg_gen_shri_i32(tmp, var, 16);
354 tcg_gen_shli_i32(var, var, 16);
355 tcg_gen_or_i32(var, var, tmp);
356 dead_tmp(tmp);
359 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
360 tmp = (t0 ^ t1) & 0x8000;
361 t0 &= ~0x8000;
362 t1 &= ~0x8000;
363 t0 = (t0 + t1) ^ tmp;
366 static void gen_add16(TCGv t0, TCGv t1)
368 TCGv tmp = new_tmp();
369 tcg_gen_xor_i32(tmp, t0, t1);
370 tcg_gen_andi_i32(tmp, tmp, 0x8000);
371 tcg_gen_andi_i32(t0, t0, ~0x8000);
372 tcg_gen_andi_i32(t1, t1, ~0x8000);
373 tcg_gen_add_i32(t0, t0, t1);
374 tcg_gen_xor_i32(t0, t0, tmp);
375 dead_tmp(tmp);
376 dead_tmp(t1);
379 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
381 /* Set CF to the top bit of var. */
382 static void gen_set_CF_bit31(TCGv var)
384 TCGv tmp = new_tmp();
385 tcg_gen_shri_i32(tmp, var, 31);
386 gen_set_CF(tmp);
387 dead_tmp(tmp);
390 /* Set N and Z flags from var. */
391 static inline void gen_logic_CC(TCGv var)
393 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF));
394 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF));
397 /* T0 += T1 + CF. */
398 static void gen_adc(TCGv t0, TCGv t1)
400 TCGv tmp;
401 tcg_gen_add_i32(t0, t0, t1);
402 tmp = load_cpu_field(CF);
403 tcg_gen_add_i32(t0, t0, tmp);
404 dead_tmp(tmp);
407 /* dest = T0 + T1 + CF. */
408 static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
410 TCGv tmp;
411 tcg_gen_add_i32(dest, t0, t1);
412 tmp = load_cpu_field(CF);
413 tcg_gen_add_i32(dest, dest, tmp);
414 dead_tmp(tmp);
417 /* dest = T0 - T1 + CF - 1. */
418 static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
420 TCGv tmp;
421 tcg_gen_sub_i32(dest, t0, t1);
422 tmp = load_cpu_field(CF);
423 tcg_gen_add_i32(dest, dest, tmp);
424 tcg_gen_subi_i32(dest, dest, 1);
425 dead_tmp(tmp);
428 /* FIXME: Implement this natively. */
429 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
431 static void shifter_out_im(TCGv var, int shift)
433 TCGv tmp = new_tmp();
434 if (shift == 0) {
435 tcg_gen_andi_i32(tmp, var, 1);
436 } else {
437 tcg_gen_shri_i32(tmp, var, shift);
438 if (shift != 31)
439 tcg_gen_andi_i32(tmp, tmp, 1);
441 gen_set_CF(tmp);
442 dead_tmp(tmp);
445 /* Shift by immediate. Includes special handling for shift == 0. */
446 static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
448 switch (shiftop) {
449 case 0: /* LSL */
450 if (shift != 0) {
451 if (flags)
452 shifter_out_im(var, 32 - shift);
453 tcg_gen_shli_i32(var, var, shift);
455 break;
456 case 1: /* LSR */
457 if (shift == 0) {
458 if (flags) {
459 tcg_gen_shri_i32(var, var, 31);
460 gen_set_CF(var);
462 tcg_gen_movi_i32(var, 0);
463 } else {
464 if (flags)
465 shifter_out_im(var, shift - 1);
466 tcg_gen_shri_i32(var, var, shift);
468 break;
469 case 2: /* ASR */
470 if (shift == 0)
471 shift = 32;
472 if (flags)
473 shifter_out_im(var, shift - 1);
474 if (shift == 32)
475 shift = 31;
476 tcg_gen_sari_i32(var, var, shift);
477 break;
478 case 3: /* ROR/RRX */
479 if (shift != 0) {
480 if (flags)
481 shifter_out_im(var, shift - 1);
482 tcg_gen_rotri_i32(var, var, shift); break;
483 } else {
484 TCGv tmp = load_cpu_field(CF);
485 if (flags)
486 shifter_out_im(var, 0);
487 tcg_gen_shri_i32(var, var, 1);
488 tcg_gen_shli_i32(tmp, tmp, 31);
489 tcg_gen_or_i32(var, var, tmp);
490 dead_tmp(tmp);
495 static inline void gen_arm_shift_reg(TCGv var, int shiftop,
496 TCGv shift, int flags)
498 if (flags) {
499 switch (shiftop) {
500 case 0: gen_helper_shl_cc(var, var, shift); break;
501 case 1: gen_helper_shr_cc(var, var, shift); break;
502 case 2: gen_helper_sar_cc(var, var, shift); break;
503 case 3: gen_helper_ror_cc(var, var, shift); break;
505 } else {
506 switch (shiftop) {
507 case 0: gen_helper_shl(var, var, shift); break;
508 case 1: gen_helper_shr(var, var, shift); break;
509 case 2: gen_helper_sar(var, var, shift); break;
510 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
511 tcg_gen_rotr_i32(var, var, shift); break;
514 dead_tmp(shift);
517 #define PAS_OP(pfx) \
518 switch (op2) { \
519 case 0: gen_pas_helper(glue(pfx,add16)); break; \
520 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
521 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
522 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
523 case 4: gen_pas_helper(glue(pfx,add8)); break; \
524 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
526 static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
528 TCGv_ptr tmp;
530 switch (op1) {
531 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
532 case 1:
533 tmp = tcg_temp_new_ptr();
534 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
535 PAS_OP(s)
536 tcg_temp_free_ptr(tmp);
537 break;
538 case 5:
539 tmp = tcg_temp_new_ptr();
540 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
541 PAS_OP(u)
542 tcg_temp_free_ptr(tmp);
543 break;
544 #undef gen_pas_helper
545 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
546 case 2:
547 PAS_OP(q);
548 break;
549 case 3:
550 PAS_OP(sh);
551 break;
552 case 6:
553 PAS_OP(uq);
554 break;
555 case 7:
556 PAS_OP(uh);
557 break;
558 #undef gen_pas_helper
561 #undef PAS_OP
563 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
564 #define PAS_OP(pfx) \
565 switch (op1) { \
566 case 0: gen_pas_helper(glue(pfx,add8)); break; \
567 case 1: gen_pas_helper(glue(pfx,add16)); break; \
568 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
569 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
570 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
571 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
573 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
575 TCGv_ptr tmp;
577 switch (op2) {
578 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
579 case 0:
580 tmp = tcg_temp_new_ptr();
581 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
582 PAS_OP(s)
583 tcg_temp_free_ptr(tmp);
584 break;
585 case 4:
586 tmp = tcg_temp_new_ptr();
587 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
588 PAS_OP(u)
589 tcg_temp_free_ptr(tmp);
590 break;
591 #undef gen_pas_helper
592 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
593 case 1:
594 PAS_OP(q);
595 break;
596 case 2:
597 PAS_OP(sh);
598 break;
599 case 5:
600 PAS_OP(uq);
601 break;
602 case 6:
603 PAS_OP(uh);
604 break;
605 #undef gen_pas_helper
608 #undef PAS_OP
610 static void gen_test_cc(int cc, int label)
612 TCGv tmp;
613 TCGv tmp2;
614 int inv;
616 switch (cc) {
617 case 0: /* eq: Z */
618 tmp = load_cpu_field(ZF);
619 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
620 break;
621 case 1: /* ne: !Z */
622 tmp = load_cpu_field(ZF);
623 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
624 break;
625 case 2: /* cs: C */
626 tmp = load_cpu_field(CF);
627 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
628 break;
629 case 3: /* cc: !C */
630 tmp = load_cpu_field(CF);
631 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
632 break;
633 case 4: /* mi: N */
634 tmp = load_cpu_field(NF);
635 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
636 break;
637 case 5: /* pl: !N */
638 tmp = load_cpu_field(NF);
639 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
640 break;
641 case 6: /* vs: V */
642 tmp = load_cpu_field(VF);
643 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
644 break;
645 case 7: /* vc: !V */
646 tmp = load_cpu_field(VF);
647 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
648 break;
649 case 8: /* hi: C && !Z */
650 inv = gen_new_label();
651 tmp = load_cpu_field(CF);
652 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
653 dead_tmp(tmp);
654 tmp = load_cpu_field(ZF);
655 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
656 gen_set_label(inv);
657 break;
658 case 9: /* ls: !C || Z */
659 tmp = load_cpu_field(CF);
660 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
661 dead_tmp(tmp);
662 tmp = load_cpu_field(ZF);
663 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
664 break;
665 case 10: /* ge: N == V -> N ^ V == 0 */
666 tmp = load_cpu_field(VF);
667 tmp2 = load_cpu_field(NF);
668 tcg_gen_xor_i32(tmp, tmp, tmp2);
669 dead_tmp(tmp2);
670 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
671 break;
672 case 11: /* lt: N != V -> N ^ V != 0 */
673 tmp = load_cpu_field(VF);
674 tmp2 = load_cpu_field(NF);
675 tcg_gen_xor_i32(tmp, tmp, tmp2);
676 dead_tmp(tmp2);
677 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
678 break;
679 case 12: /* gt: !Z && N == V */
680 inv = gen_new_label();
681 tmp = load_cpu_field(ZF);
682 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
683 dead_tmp(tmp);
684 tmp = load_cpu_field(VF);
685 tmp2 = load_cpu_field(NF);
686 tcg_gen_xor_i32(tmp, tmp, tmp2);
687 dead_tmp(tmp2);
688 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
689 gen_set_label(inv);
690 break;
691 case 13: /* le: Z || N != V */
692 tmp = load_cpu_field(ZF);
693 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
694 dead_tmp(tmp);
695 tmp = load_cpu_field(VF);
696 tmp2 = load_cpu_field(NF);
697 tcg_gen_xor_i32(tmp, tmp, tmp2);
698 dead_tmp(tmp2);
699 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
700 break;
701 default:
702 fprintf(stderr, "Bad condition code 0x%x\n", cc);
703 abort();
705 dead_tmp(tmp);
708 static const uint8_t table_logic_cc[16] = {
709 1, /* and */
710 1, /* xor */
711 0, /* sub */
712 0, /* rsb */
713 0, /* add */
714 0, /* adc */
715 0, /* sbc */
716 0, /* rsc */
717 1, /* andl */
718 1, /* xorl */
719 0, /* cmp */
720 0, /* cmn */
721 1, /* orr */
722 1, /* mov */
723 1, /* bic */
724 1, /* mvn */
727 /* Set PC and Thumb state from an immediate address. */
728 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
730 TCGv tmp;
732 s->is_jmp = DISAS_UPDATE;
733 if (s->thumb != (addr & 1)) {
734 tmp = new_tmp();
735 tcg_gen_movi_i32(tmp, addr & 1);
736 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
737 dead_tmp(tmp);
739 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
742 /* Set PC and Thumb state from var. var is marked as dead. */
743 static inline void gen_bx(DisasContext *s, TCGv var)
745 s->is_jmp = DISAS_UPDATE;
746 tcg_gen_andi_i32(cpu_R[15], var, ~1);
747 tcg_gen_andi_i32(var, var, 1);
748 store_cpu_field(var, thumb);
751 /* Variant of store_reg which uses branch&exchange logic when storing
752 to r15 in ARM architecture v7 and above. The source must be a temporary
753 and will be marked as dead. */
754 static inline void store_reg_bx(CPUState *env, DisasContext *s,
755 int reg, TCGv var)
757 if (reg == 15 && ENABLE_ARCH_7) {
758 gen_bx(s, var);
759 } else {
760 store_reg(s, reg, var);
764 static inline TCGv gen_ld8s(TCGv addr, int index)
766 TCGv tmp = new_tmp();
767 tcg_gen_qemu_ld8s(tmp, addr, index);
768 return tmp;
770 static inline TCGv gen_ld8u(TCGv addr, int index)
772 TCGv tmp = new_tmp();
773 tcg_gen_qemu_ld8u(tmp, addr, index);
774 return tmp;
776 static inline TCGv gen_ld16s(TCGv addr, int index)
778 TCGv tmp = new_tmp();
779 tcg_gen_qemu_ld16s(tmp, addr, index);
780 return tmp;
782 static inline TCGv gen_ld16u(TCGv addr, int index)
784 TCGv tmp = new_tmp();
785 tcg_gen_qemu_ld16u(tmp, addr, index);
786 return tmp;
788 static inline TCGv gen_ld32(TCGv addr, int index)
790 TCGv tmp = new_tmp();
791 tcg_gen_qemu_ld32u(tmp, addr, index);
792 return tmp;
794 static inline TCGv_i64 gen_ld64(TCGv addr, int index)
796 TCGv_i64 tmp = tcg_temp_new_i64();
797 tcg_gen_qemu_ld64(tmp, addr, index);
798 return tmp;
800 static inline void gen_st8(TCGv val, TCGv addr, int index)
802 tcg_gen_qemu_st8(val, addr, index);
803 dead_tmp(val);
805 static inline void gen_st16(TCGv val, TCGv addr, int index)
807 tcg_gen_qemu_st16(val, addr, index);
808 dead_tmp(val);
810 static inline void gen_st32(TCGv val, TCGv addr, int index)
812 tcg_gen_qemu_st32(val, addr, index);
813 dead_tmp(val);
815 static inline void gen_st64(TCGv_i64 val, TCGv addr, int index)
817 tcg_gen_qemu_st64(val, addr, index);
818 tcg_temp_free_i64(val);
821 static inline void gen_set_pc_im(uint32_t val)
823 tcg_gen_movi_i32(cpu_R[15], val);
826 /* Force a TB lookup after an instruction that changes the CPU state. */
827 static inline void gen_lookup_tb(DisasContext *s)
829 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
830 s->is_jmp = DISAS_UPDATE;
833 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
834 TCGv var)
836 int val, rm, shift, shiftop;
837 TCGv offset;
839 if (!(insn & (1 << 25))) {
840 /* immediate */
841 val = insn & 0xfff;
842 if (!(insn & (1 << 23)))
843 val = -val;
844 if (val != 0)
845 tcg_gen_addi_i32(var, var, val);
846 } else {
847 /* shift/register */
848 rm = (insn) & 0xf;
849 shift = (insn >> 7) & 0x1f;
850 shiftop = (insn >> 5) & 3;
851 offset = load_reg(s, rm);
852 gen_arm_shift_im(offset, shiftop, shift, 0);
853 if (!(insn & (1 << 23)))
854 tcg_gen_sub_i32(var, var, offset);
855 else
856 tcg_gen_add_i32(var, var, offset);
857 dead_tmp(offset);
861 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
862 int extra, TCGv var)
864 int val, rm;
865 TCGv offset;
867 if (insn & (1 << 22)) {
868 /* immediate */
869 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
870 if (!(insn & (1 << 23)))
871 val = -val;
872 val += extra;
873 if (val != 0)
874 tcg_gen_addi_i32(var, var, val);
875 } else {
876 /* register */
877 if (extra)
878 tcg_gen_addi_i32(var, var, extra);
879 rm = (insn) & 0xf;
880 offset = load_reg(s, rm);
881 if (!(insn & (1 << 23)))
882 tcg_gen_sub_i32(var, var, offset);
883 else
884 tcg_gen_add_i32(var, var, offset);
885 dead_tmp(offset);
889 #define VFP_OP2(name) \
890 static inline void gen_vfp_##name(int dp) \
892 if (dp) \
893 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
894 else \
895 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
898 VFP_OP2(add)
899 VFP_OP2(sub)
900 VFP_OP2(mul)
901 VFP_OP2(div)
903 #undef VFP_OP2
905 static inline void gen_vfp_abs(int dp)
907 if (dp)
908 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
909 else
910 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
913 static inline void gen_vfp_neg(int dp)
915 if (dp)
916 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
917 else
918 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
921 static inline void gen_vfp_sqrt(int dp)
923 if (dp)
924 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
925 else
926 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
929 static inline void gen_vfp_cmp(int dp)
931 if (dp)
932 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
933 else
934 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
937 static inline void gen_vfp_cmpe(int dp)
939 if (dp)
940 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
941 else
942 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
945 static inline void gen_vfp_F1_ld0(int dp)
947 if (dp)
948 tcg_gen_movi_i64(cpu_F1d, 0);
949 else
950 tcg_gen_movi_i32(cpu_F1s, 0);
953 static inline void gen_vfp_uito(int dp)
955 if (dp)
956 gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
957 else
958 gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
961 static inline void gen_vfp_sito(int dp)
963 if (dp)
964 gen_helper_vfp_sitod(cpu_F0d, cpu_F0s, cpu_env);
965 else
966 gen_helper_vfp_sitos(cpu_F0s, cpu_F0s, cpu_env);
969 static inline void gen_vfp_toui(int dp)
971 if (dp)
972 gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env);
973 else
974 gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env);
977 static inline void gen_vfp_touiz(int dp)
979 if (dp)
980 gen_helper_vfp_touizd(cpu_F0s, cpu_F0d, cpu_env);
981 else
982 gen_helper_vfp_touizs(cpu_F0s, cpu_F0s, cpu_env);
985 static inline void gen_vfp_tosi(int dp)
987 if (dp)
988 gen_helper_vfp_tosid(cpu_F0s, cpu_F0d, cpu_env);
989 else
990 gen_helper_vfp_tosis(cpu_F0s, cpu_F0s, cpu_env);
993 static inline void gen_vfp_tosiz(int dp)
995 if (dp)
996 gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env);
997 else
998 gen_helper_vfp_tosizs(cpu_F0s, cpu_F0s, cpu_env);
1001 #define VFP_GEN_FIX(name) \
1002 static inline void gen_vfp_##name(int dp, int shift) \
1004 TCGv tmp_shift = tcg_const_i32(shift); \
1005 if (dp) \
1006 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, cpu_env);\
1007 else \
1008 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, cpu_env);\
1009 tcg_temp_free_i32(tmp_shift); \
1011 VFP_GEN_FIX(tosh)
1012 VFP_GEN_FIX(tosl)
1013 VFP_GEN_FIX(touh)
1014 VFP_GEN_FIX(toul)
1015 VFP_GEN_FIX(shto)
1016 VFP_GEN_FIX(slto)
1017 VFP_GEN_FIX(uhto)
1018 VFP_GEN_FIX(ulto)
1019 #undef VFP_GEN_FIX
1021 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv addr)
1023 if (dp)
1024 tcg_gen_qemu_ld64(cpu_F0d, addr, IS_USER(s));
1025 else
1026 tcg_gen_qemu_ld32u(cpu_F0s, addr, IS_USER(s));
1029 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv addr)
1031 if (dp)
1032 tcg_gen_qemu_st64(cpu_F0d, addr, IS_USER(s));
1033 else
1034 tcg_gen_qemu_st32(cpu_F0s, addr, IS_USER(s));
1037 static inline long
1038 vfp_reg_offset (int dp, int reg)
1040 if (dp)
1041 return offsetof(CPUARMState, vfp.regs[reg]);
1042 else if (reg & 1) {
1043 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1044 + offsetof(CPU_DoubleU, l.upper);
1045 } else {
1046 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1047 + offsetof(CPU_DoubleU, l.lower);
1051 /* Return the offset of a 32-bit piece of a NEON register.
1052 zero is the least significant end of the register. */
1053 static inline long
1054 neon_reg_offset (int reg, int n)
1056 int sreg;
1057 sreg = reg * 2 + n;
1058 return vfp_reg_offset(0, sreg);
1061 static TCGv neon_load_reg(int reg, int pass)
1063 TCGv tmp = new_tmp();
1064 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1065 return tmp;
1068 static void neon_store_reg(int reg, int pass, TCGv var)
1070 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1071 dead_tmp(var);
1074 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1076 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1079 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1081 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1084 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1085 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1086 #define tcg_gen_st_f32 tcg_gen_st_i32
1087 #define tcg_gen_st_f64 tcg_gen_st_i64
1089 static inline void gen_mov_F0_vreg(int dp, int reg)
1091 if (dp)
1092 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1093 else
1094 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1097 static inline void gen_mov_F1_vreg(int dp, int reg)
1099 if (dp)
1100 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1101 else
1102 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1105 static inline void gen_mov_vreg_F0(int dp, int reg)
1107 if (dp)
1108 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1109 else
1110 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1113 #define ARM_CP_RW_BIT (1 << 20)
1115 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1117 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1120 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1122 tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1125 static inline TCGv iwmmxt_load_creg(int reg)
1127 TCGv var = new_tmp();
1128 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1129 return var;
1132 static inline void iwmmxt_store_creg(int reg, TCGv var)
1134 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1135 dead_tmp(var);
1138 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1140 iwmmxt_store_reg(cpu_M0, rn);
1143 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1145 iwmmxt_load_reg(cpu_M0, rn);
1148 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1150 iwmmxt_load_reg(cpu_V1, rn);
1151 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1154 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1156 iwmmxt_load_reg(cpu_V1, rn);
1157 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1160 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1162 iwmmxt_load_reg(cpu_V1, rn);
1163 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1166 #define IWMMXT_OP(name) \
1167 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1169 iwmmxt_load_reg(cpu_V1, rn); \
1170 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1173 #define IWMMXT_OP_ENV(name) \
1174 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1176 iwmmxt_load_reg(cpu_V1, rn); \
1177 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1180 #define IWMMXT_OP_ENV_SIZE(name) \
1181 IWMMXT_OP_ENV(name##b) \
1182 IWMMXT_OP_ENV(name##w) \
1183 IWMMXT_OP_ENV(name##l)
1185 #define IWMMXT_OP_ENV1(name) \
1186 static inline void gen_op_iwmmxt_##name##_M0(void) \
1188 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1191 IWMMXT_OP(maddsq)
1192 IWMMXT_OP(madduq)
1193 IWMMXT_OP(sadb)
1194 IWMMXT_OP(sadw)
1195 IWMMXT_OP(mulslw)
1196 IWMMXT_OP(mulshw)
1197 IWMMXT_OP(mululw)
1198 IWMMXT_OP(muluhw)
1199 IWMMXT_OP(macsw)
1200 IWMMXT_OP(macuw)
1202 IWMMXT_OP_ENV_SIZE(unpackl)
1203 IWMMXT_OP_ENV_SIZE(unpackh)
1205 IWMMXT_OP_ENV1(unpacklub)
1206 IWMMXT_OP_ENV1(unpackluw)
1207 IWMMXT_OP_ENV1(unpacklul)
1208 IWMMXT_OP_ENV1(unpackhub)
1209 IWMMXT_OP_ENV1(unpackhuw)
1210 IWMMXT_OP_ENV1(unpackhul)
1211 IWMMXT_OP_ENV1(unpacklsb)
1212 IWMMXT_OP_ENV1(unpacklsw)
1213 IWMMXT_OP_ENV1(unpacklsl)
1214 IWMMXT_OP_ENV1(unpackhsb)
1215 IWMMXT_OP_ENV1(unpackhsw)
1216 IWMMXT_OP_ENV1(unpackhsl)
1218 IWMMXT_OP_ENV_SIZE(cmpeq)
1219 IWMMXT_OP_ENV_SIZE(cmpgtu)
1220 IWMMXT_OP_ENV_SIZE(cmpgts)
1222 IWMMXT_OP_ENV_SIZE(mins)
1223 IWMMXT_OP_ENV_SIZE(minu)
1224 IWMMXT_OP_ENV_SIZE(maxs)
1225 IWMMXT_OP_ENV_SIZE(maxu)
1227 IWMMXT_OP_ENV_SIZE(subn)
1228 IWMMXT_OP_ENV_SIZE(addn)
1229 IWMMXT_OP_ENV_SIZE(subu)
1230 IWMMXT_OP_ENV_SIZE(addu)
1231 IWMMXT_OP_ENV_SIZE(subs)
1232 IWMMXT_OP_ENV_SIZE(adds)
1234 IWMMXT_OP_ENV(avgb0)
1235 IWMMXT_OP_ENV(avgb1)
1236 IWMMXT_OP_ENV(avgw0)
1237 IWMMXT_OP_ENV(avgw1)
1239 IWMMXT_OP(msadb)
1241 IWMMXT_OP_ENV(packuw)
1242 IWMMXT_OP_ENV(packul)
1243 IWMMXT_OP_ENV(packuq)
1244 IWMMXT_OP_ENV(packsw)
1245 IWMMXT_OP_ENV(packsl)
1246 IWMMXT_OP_ENV(packsq)
1248 static void gen_op_iwmmxt_set_mup(void)
1250 TCGv tmp;
1251 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1252 tcg_gen_ori_i32(tmp, tmp, 2);
1253 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1256 static void gen_op_iwmmxt_set_cup(void)
1258 TCGv tmp;
1259 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1260 tcg_gen_ori_i32(tmp, tmp, 1);
1261 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1264 static void gen_op_iwmmxt_setpsr_nz(void)
1266 TCGv tmp = new_tmp();
1267 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1268 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1271 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1273 iwmmxt_load_reg(cpu_V1, rn);
1274 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1275 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1278 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn, TCGv dest)
1280 int rd;
1281 uint32_t offset;
1282 TCGv tmp;
1284 rd = (insn >> 16) & 0xf;
1285 tmp = load_reg(s, rd);
1287 offset = (insn & 0xff) << ((insn >> 7) & 2);
1288 if (insn & (1 << 24)) {
1289 /* Pre indexed */
1290 if (insn & (1 << 23))
1291 tcg_gen_addi_i32(tmp, tmp, offset);
1292 else
1293 tcg_gen_addi_i32(tmp, tmp, -offset);
1294 tcg_gen_mov_i32(dest, tmp);
1295 if (insn & (1 << 21))
1296 store_reg(s, rd, tmp);
1297 else
1298 dead_tmp(tmp);
1299 } else if (insn & (1 << 21)) {
1300 /* Post indexed */
1301 tcg_gen_mov_i32(dest, tmp);
1302 if (insn & (1 << 23))
1303 tcg_gen_addi_i32(tmp, tmp, offset);
1304 else
1305 tcg_gen_addi_i32(tmp, tmp, -offset);
1306 store_reg(s, rd, tmp);
1307 } else if (!(insn & (1 << 23)))
1308 return 1;
1309 return 0;
1312 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv dest)
1314 int rd = (insn >> 0) & 0xf;
1315 TCGv tmp;
1317 if (insn & (1 << 8)) {
1318 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1319 return 1;
1320 } else {
1321 tmp = iwmmxt_load_creg(rd);
1323 } else {
1324 tmp = new_tmp();
1325 iwmmxt_load_reg(cpu_V0, rd);
1326 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
1328 tcg_gen_andi_i32(tmp, tmp, mask);
1329 tcg_gen_mov_i32(dest, tmp);
1330 dead_tmp(tmp);
1331 return 0;
1334 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1335 (ie. an undefined instruction). */
1336 static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1338 int rd, wrd;
1339 int rdhi, rdlo, rd0, rd1, i;
1340 TCGv addr;
1341 TCGv tmp, tmp2, tmp3;
1343 if ((insn & 0x0e000e00) == 0x0c000000) {
1344 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1345 wrd = insn & 0xf;
1346 rdlo = (insn >> 12) & 0xf;
1347 rdhi = (insn >> 16) & 0xf;
1348 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1349 iwmmxt_load_reg(cpu_V0, wrd);
1350 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
1351 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1352 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
1353 } else { /* TMCRR */
1354 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1355 iwmmxt_store_reg(cpu_V0, wrd);
1356 gen_op_iwmmxt_set_mup();
1358 return 0;
1361 wrd = (insn >> 12) & 0xf;
1362 addr = new_tmp();
1363 if (gen_iwmmxt_address(s, insn, addr)) {
1364 dead_tmp(addr);
1365 return 1;
1367 if (insn & ARM_CP_RW_BIT) {
1368 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1369 tmp = new_tmp();
1370 tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s));
1371 iwmmxt_store_creg(wrd, tmp);
1372 } else {
1373 i = 1;
1374 if (insn & (1 << 8)) {
1375 if (insn & (1 << 22)) { /* WLDRD */
1376 tcg_gen_qemu_ld64(cpu_M0, addr, IS_USER(s));
1377 i = 0;
1378 } else { /* WLDRW wRd */
1379 tmp = gen_ld32(addr, IS_USER(s));
1381 } else {
1382 if (insn & (1 << 22)) { /* WLDRH */
1383 tmp = gen_ld16u(addr, IS_USER(s));
1384 } else { /* WLDRB */
1385 tmp = gen_ld8u(addr, IS_USER(s));
1388 if (i) {
1389 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1390 dead_tmp(tmp);
1392 gen_op_iwmmxt_movq_wRn_M0(wrd);
1394 } else {
1395 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1396 tmp = iwmmxt_load_creg(wrd);
1397 gen_st32(tmp, addr, IS_USER(s));
1398 } else {
1399 gen_op_iwmmxt_movq_M0_wRn(wrd);
1400 tmp = new_tmp();
1401 if (insn & (1 << 8)) {
1402 if (insn & (1 << 22)) { /* WSTRD */
1403 dead_tmp(tmp);
1404 tcg_gen_qemu_st64(cpu_M0, addr, IS_USER(s));
1405 } else { /* WSTRW wRd */
1406 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1407 gen_st32(tmp, addr, IS_USER(s));
1409 } else {
1410 if (insn & (1 << 22)) { /* WSTRH */
1411 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1412 gen_st16(tmp, addr, IS_USER(s));
1413 } else { /* WSTRB */
1414 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1415 gen_st8(tmp, addr, IS_USER(s));
1420 dead_tmp(addr);
1421 return 0;
1424 if ((insn & 0x0f000000) != 0x0e000000)
1425 return 1;
1427 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1428 case 0x000: /* WOR */
1429 wrd = (insn >> 12) & 0xf;
1430 rd0 = (insn >> 0) & 0xf;
1431 rd1 = (insn >> 16) & 0xf;
1432 gen_op_iwmmxt_movq_M0_wRn(rd0);
1433 gen_op_iwmmxt_orq_M0_wRn(rd1);
1434 gen_op_iwmmxt_setpsr_nz();
1435 gen_op_iwmmxt_movq_wRn_M0(wrd);
1436 gen_op_iwmmxt_set_mup();
1437 gen_op_iwmmxt_set_cup();
1438 break;
1439 case 0x011: /* TMCR */
1440 if (insn & 0xf)
1441 return 1;
1442 rd = (insn >> 12) & 0xf;
1443 wrd = (insn >> 16) & 0xf;
1444 switch (wrd) {
1445 case ARM_IWMMXT_wCID:
1446 case ARM_IWMMXT_wCASF:
1447 break;
1448 case ARM_IWMMXT_wCon:
1449 gen_op_iwmmxt_set_cup();
1450 /* Fall through. */
1451 case ARM_IWMMXT_wCSSF:
1452 tmp = iwmmxt_load_creg(wrd);
1453 tmp2 = load_reg(s, rd);
1454 tcg_gen_andc_i32(tmp, tmp, tmp2);
1455 dead_tmp(tmp2);
1456 iwmmxt_store_creg(wrd, tmp);
1457 break;
1458 case ARM_IWMMXT_wCGR0:
1459 case ARM_IWMMXT_wCGR1:
1460 case ARM_IWMMXT_wCGR2:
1461 case ARM_IWMMXT_wCGR3:
1462 gen_op_iwmmxt_set_cup();
1463 tmp = load_reg(s, rd);
1464 iwmmxt_store_creg(wrd, tmp);
1465 break;
1466 default:
1467 return 1;
1469 break;
1470 case 0x100: /* WXOR */
1471 wrd = (insn >> 12) & 0xf;
1472 rd0 = (insn >> 0) & 0xf;
1473 rd1 = (insn >> 16) & 0xf;
1474 gen_op_iwmmxt_movq_M0_wRn(rd0);
1475 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1476 gen_op_iwmmxt_setpsr_nz();
1477 gen_op_iwmmxt_movq_wRn_M0(wrd);
1478 gen_op_iwmmxt_set_mup();
1479 gen_op_iwmmxt_set_cup();
1480 break;
1481 case 0x111: /* TMRC */
1482 if (insn & 0xf)
1483 return 1;
1484 rd = (insn >> 12) & 0xf;
1485 wrd = (insn >> 16) & 0xf;
1486 tmp = iwmmxt_load_creg(wrd);
1487 store_reg(s, rd, tmp);
1488 break;
1489 case 0x300: /* WANDN */
1490 wrd = (insn >> 12) & 0xf;
1491 rd0 = (insn >> 0) & 0xf;
1492 rd1 = (insn >> 16) & 0xf;
1493 gen_op_iwmmxt_movq_M0_wRn(rd0);
1494 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1495 gen_op_iwmmxt_andq_M0_wRn(rd1);
1496 gen_op_iwmmxt_setpsr_nz();
1497 gen_op_iwmmxt_movq_wRn_M0(wrd);
1498 gen_op_iwmmxt_set_mup();
1499 gen_op_iwmmxt_set_cup();
1500 break;
1501 case 0x200: /* WAND */
1502 wrd = (insn >> 12) & 0xf;
1503 rd0 = (insn >> 0) & 0xf;
1504 rd1 = (insn >> 16) & 0xf;
1505 gen_op_iwmmxt_movq_M0_wRn(rd0);
1506 gen_op_iwmmxt_andq_M0_wRn(rd1);
1507 gen_op_iwmmxt_setpsr_nz();
1508 gen_op_iwmmxt_movq_wRn_M0(wrd);
1509 gen_op_iwmmxt_set_mup();
1510 gen_op_iwmmxt_set_cup();
1511 break;
1512 case 0x810: case 0xa10: /* WMADD */
1513 wrd = (insn >> 12) & 0xf;
1514 rd0 = (insn >> 0) & 0xf;
1515 rd1 = (insn >> 16) & 0xf;
1516 gen_op_iwmmxt_movq_M0_wRn(rd0);
1517 if (insn & (1 << 21))
1518 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1519 else
1520 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1521 gen_op_iwmmxt_movq_wRn_M0(wrd);
1522 gen_op_iwmmxt_set_mup();
1523 break;
1524 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1525 wrd = (insn >> 12) & 0xf;
1526 rd0 = (insn >> 16) & 0xf;
1527 rd1 = (insn >> 0) & 0xf;
1528 gen_op_iwmmxt_movq_M0_wRn(rd0);
1529 switch ((insn >> 22) & 3) {
1530 case 0:
1531 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1532 break;
1533 case 1:
1534 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1535 break;
1536 case 2:
1537 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1538 break;
1539 case 3:
1540 return 1;
1542 gen_op_iwmmxt_movq_wRn_M0(wrd);
1543 gen_op_iwmmxt_set_mup();
1544 gen_op_iwmmxt_set_cup();
1545 break;
1546 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1547 wrd = (insn >> 12) & 0xf;
1548 rd0 = (insn >> 16) & 0xf;
1549 rd1 = (insn >> 0) & 0xf;
1550 gen_op_iwmmxt_movq_M0_wRn(rd0);
1551 switch ((insn >> 22) & 3) {
1552 case 0:
1553 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1554 break;
1555 case 1:
1556 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1557 break;
1558 case 2:
1559 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1560 break;
1561 case 3:
1562 return 1;
1564 gen_op_iwmmxt_movq_wRn_M0(wrd);
1565 gen_op_iwmmxt_set_mup();
1566 gen_op_iwmmxt_set_cup();
1567 break;
1568 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1569 wrd = (insn >> 12) & 0xf;
1570 rd0 = (insn >> 16) & 0xf;
1571 rd1 = (insn >> 0) & 0xf;
1572 gen_op_iwmmxt_movq_M0_wRn(rd0);
1573 if (insn & (1 << 22))
1574 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1575 else
1576 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1577 if (!(insn & (1 << 20)))
1578 gen_op_iwmmxt_addl_M0_wRn(wrd);
1579 gen_op_iwmmxt_movq_wRn_M0(wrd);
1580 gen_op_iwmmxt_set_mup();
1581 break;
1582 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1583 wrd = (insn >> 12) & 0xf;
1584 rd0 = (insn >> 16) & 0xf;
1585 rd1 = (insn >> 0) & 0xf;
1586 gen_op_iwmmxt_movq_M0_wRn(rd0);
1587 if (insn & (1 << 21)) {
1588 if (insn & (1 << 20))
1589 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1590 else
1591 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1592 } else {
1593 if (insn & (1 << 20))
1594 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1595 else
1596 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1598 gen_op_iwmmxt_movq_wRn_M0(wrd);
1599 gen_op_iwmmxt_set_mup();
1600 break;
1601 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
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 << 21))
1607 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1608 else
1609 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1610 if (!(insn & (1 << 20))) {
1611 iwmmxt_load_reg(cpu_V1, wrd);
1612 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1614 gen_op_iwmmxt_movq_wRn_M0(wrd);
1615 gen_op_iwmmxt_set_mup();
1616 break;
1617 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1618 wrd = (insn >> 12) & 0xf;
1619 rd0 = (insn >> 16) & 0xf;
1620 rd1 = (insn >> 0) & 0xf;
1621 gen_op_iwmmxt_movq_M0_wRn(rd0);
1622 switch ((insn >> 22) & 3) {
1623 case 0:
1624 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1625 break;
1626 case 1:
1627 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1628 break;
1629 case 2:
1630 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1631 break;
1632 case 3:
1633 return 1;
1635 gen_op_iwmmxt_movq_wRn_M0(wrd);
1636 gen_op_iwmmxt_set_mup();
1637 gen_op_iwmmxt_set_cup();
1638 break;
1639 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1640 wrd = (insn >> 12) & 0xf;
1641 rd0 = (insn >> 16) & 0xf;
1642 rd1 = (insn >> 0) & 0xf;
1643 gen_op_iwmmxt_movq_M0_wRn(rd0);
1644 if (insn & (1 << 22)) {
1645 if (insn & (1 << 20))
1646 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1647 else
1648 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1649 } else {
1650 if (insn & (1 << 20))
1651 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1652 else
1653 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1655 gen_op_iwmmxt_movq_wRn_M0(wrd);
1656 gen_op_iwmmxt_set_mup();
1657 gen_op_iwmmxt_set_cup();
1658 break;
1659 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1660 wrd = (insn >> 12) & 0xf;
1661 rd0 = (insn >> 16) & 0xf;
1662 rd1 = (insn >> 0) & 0xf;
1663 gen_op_iwmmxt_movq_M0_wRn(rd0);
1664 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1665 tcg_gen_andi_i32(tmp, tmp, 7);
1666 iwmmxt_load_reg(cpu_V1, rd1);
1667 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
1668 dead_tmp(tmp);
1669 gen_op_iwmmxt_movq_wRn_M0(wrd);
1670 gen_op_iwmmxt_set_mup();
1671 break;
1672 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1673 if (((insn >> 6) & 3) == 3)
1674 return 1;
1675 rd = (insn >> 12) & 0xf;
1676 wrd = (insn >> 16) & 0xf;
1677 tmp = load_reg(s, rd);
1678 gen_op_iwmmxt_movq_M0_wRn(wrd);
1679 switch ((insn >> 6) & 3) {
1680 case 0:
1681 tmp2 = tcg_const_i32(0xff);
1682 tmp3 = tcg_const_i32((insn & 7) << 3);
1683 break;
1684 case 1:
1685 tmp2 = tcg_const_i32(0xffff);
1686 tmp3 = tcg_const_i32((insn & 3) << 4);
1687 break;
1688 case 2:
1689 tmp2 = tcg_const_i32(0xffffffff);
1690 tmp3 = tcg_const_i32((insn & 1) << 5);
1691 break;
1692 default:
1693 TCGV_UNUSED(tmp2);
1694 TCGV_UNUSED(tmp3);
1696 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
1697 tcg_temp_free(tmp3);
1698 tcg_temp_free(tmp2);
1699 dead_tmp(tmp);
1700 gen_op_iwmmxt_movq_wRn_M0(wrd);
1701 gen_op_iwmmxt_set_mup();
1702 break;
1703 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1704 rd = (insn >> 12) & 0xf;
1705 wrd = (insn >> 16) & 0xf;
1706 if (rd == 15 || ((insn >> 22) & 3) == 3)
1707 return 1;
1708 gen_op_iwmmxt_movq_M0_wRn(wrd);
1709 tmp = new_tmp();
1710 switch ((insn >> 22) & 3) {
1711 case 0:
1712 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
1713 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1714 if (insn & 8) {
1715 tcg_gen_ext8s_i32(tmp, tmp);
1716 } else {
1717 tcg_gen_andi_i32(tmp, tmp, 0xff);
1719 break;
1720 case 1:
1721 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
1722 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1723 if (insn & 8) {
1724 tcg_gen_ext16s_i32(tmp, tmp);
1725 } else {
1726 tcg_gen_andi_i32(tmp, tmp, 0xffff);
1728 break;
1729 case 2:
1730 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
1731 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1732 break;
1734 store_reg(s, rd, tmp);
1735 break;
1736 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1737 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1738 return 1;
1739 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1740 switch ((insn >> 22) & 3) {
1741 case 0:
1742 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
1743 break;
1744 case 1:
1745 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
1746 break;
1747 case 2:
1748 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
1749 break;
1751 tcg_gen_shli_i32(tmp, tmp, 28);
1752 gen_set_nzcv(tmp);
1753 dead_tmp(tmp);
1754 break;
1755 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1756 if (((insn >> 6) & 3) == 3)
1757 return 1;
1758 rd = (insn >> 12) & 0xf;
1759 wrd = (insn >> 16) & 0xf;
1760 tmp = load_reg(s, rd);
1761 switch ((insn >> 6) & 3) {
1762 case 0:
1763 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
1764 break;
1765 case 1:
1766 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
1767 break;
1768 case 2:
1769 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
1770 break;
1772 dead_tmp(tmp);
1773 gen_op_iwmmxt_movq_wRn_M0(wrd);
1774 gen_op_iwmmxt_set_mup();
1775 break;
1776 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1777 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1778 return 1;
1779 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1780 tmp2 = new_tmp();
1781 tcg_gen_mov_i32(tmp2, tmp);
1782 switch ((insn >> 22) & 3) {
1783 case 0:
1784 for (i = 0; i < 7; i ++) {
1785 tcg_gen_shli_i32(tmp2, tmp2, 4);
1786 tcg_gen_and_i32(tmp, tmp, tmp2);
1788 break;
1789 case 1:
1790 for (i = 0; i < 3; i ++) {
1791 tcg_gen_shli_i32(tmp2, tmp2, 8);
1792 tcg_gen_and_i32(tmp, tmp, tmp2);
1794 break;
1795 case 2:
1796 tcg_gen_shli_i32(tmp2, tmp2, 16);
1797 tcg_gen_and_i32(tmp, tmp, tmp2);
1798 break;
1800 gen_set_nzcv(tmp);
1801 dead_tmp(tmp2);
1802 dead_tmp(tmp);
1803 break;
1804 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1805 wrd = (insn >> 12) & 0xf;
1806 rd0 = (insn >> 16) & 0xf;
1807 gen_op_iwmmxt_movq_M0_wRn(rd0);
1808 switch ((insn >> 22) & 3) {
1809 case 0:
1810 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1811 break;
1812 case 1:
1813 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1814 break;
1815 case 2:
1816 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1817 break;
1818 case 3:
1819 return 1;
1821 gen_op_iwmmxt_movq_wRn_M0(wrd);
1822 gen_op_iwmmxt_set_mup();
1823 break;
1824 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1825 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1826 return 1;
1827 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1828 tmp2 = new_tmp();
1829 tcg_gen_mov_i32(tmp2, tmp);
1830 switch ((insn >> 22) & 3) {
1831 case 0:
1832 for (i = 0; i < 7; i ++) {
1833 tcg_gen_shli_i32(tmp2, tmp2, 4);
1834 tcg_gen_or_i32(tmp, tmp, tmp2);
1836 break;
1837 case 1:
1838 for (i = 0; i < 3; i ++) {
1839 tcg_gen_shli_i32(tmp2, tmp2, 8);
1840 tcg_gen_or_i32(tmp, tmp, tmp2);
1842 break;
1843 case 2:
1844 tcg_gen_shli_i32(tmp2, tmp2, 16);
1845 tcg_gen_or_i32(tmp, tmp, tmp2);
1846 break;
1848 gen_set_nzcv(tmp);
1849 dead_tmp(tmp2);
1850 dead_tmp(tmp);
1851 break;
1852 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1853 rd = (insn >> 12) & 0xf;
1854 rd0 = (insn >> 16) & 0xf;
1855 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
1856 return 1;
1857 gen_op_iwmmxt_movq_M0_wRn(rd0);
1858 tmp = new_tmp();
1859 switch ((insn >> 22) & 3) {
1860 case 0:
1861 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
1862 break;
1863 case 1:
1864 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
1865 break;
1866 case 2:
1867 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
1868 break;
1870 store_reg(s, rd, tmp);
1871 break;
1872 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1873 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1874 wrd = (insn >> 12) & 0xf;
1875 rd0 = (insn >> 16) & 0xf;
1876 rd1 = (insn >> 0) & 0xf;
1877 gen_op_iwmmxt_movq_M0_wRn(rd0);
1878 switch ((insn >> 22) & 3) {
1879 case 0:
1880 if (insn & (1 << 21))
1881 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1882 else
1883 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1884 break;
1885 case 1:
1886 if (insn & (1 << 21))
1887 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1888 else
1889 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
1890 break;
1891 case 2:
1892 if (insn & (1 << 21))
1893 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
1894 else
1895 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
1896 break;
1897 case 3:
1898 return 1;
1900 gen_op_iwmmxt_movq_wRn_M0(wrd);
1901 gen_op_iwmmxt_set_mup();
1902 gen_op_iwmmxt_set_cup();
1903 break;
1904 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1905 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1906 wrd = (insn >> 12) & 0xf;
1907 rd0 = (insn >> 16) & 0xf;
1908 gen_op_iwmmxt_movq_M0_wRn(rd0);
1909 switch ((insn >> 22) & 3) {
1910 case 0:
1911 if (insn & (1 << 21))
1912 gen_op_iwmmxt_unpacklsb_M0();
1913 else
1914 gen_op_iwmmxt_unpacklub_M0();
1915 break;
1916 case 1:
1917 if (insn & (1 << 21))
1918 gen_op_iwmmxt_unpacklsw_M0();
1919 else
1920 gen_op_iwmmxt_unpackluw_M0();
1921 break;
1922 case 2:
1923 if (insn & (1 << 21))
1924 gen_op_iwmmxt_unpacklsl_M0();
1925 else
1926 gen_op_iwmmxt_unpacklul_M0();
1927 break;
1928 case 3:
1929 return 1;
1931 gen_op_iwmmxt_movq_wRn_M0(wrd);
1932 gen_op_iwmmxt_set_mup();
1933 gen_op_iwmmxt_set_cup();
1934 break;
1935 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
1936 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1937 wrd = (insn >> 12) & 0xf;
1938 rd0 = (insn >> 16) & 0xf;
1939 gen_op_iwmmxt_movq_M0_wRn(rd0);
1940 switch ((insn >> 22) & 3) {
1941 case 0:
1942 if (insn & (1 << 21))
1943 gen_op_iwmmxt_unpackhsb_M0();
1944 else
1945 gen_op_iwmmxt_unpackhub_M0();
1946 break;
1947 case 1:
1948 if (insn & (1 << 21))
1949 gen_op_iwmmxt_unpackhsw_M0();
1950 else
1951 gen_op_iwmmxt_unpackhuw_M0();
1952 break;
1953 case 2:
1954 if (insn & (1 << 21))
1955 gen_op_iwmmxt_unpackhsl_M0();
1956 else
1957 gen_op_iwmmxt_unpackhul_M0();
1958 break;
1959 case 3:
1960 return 1;
1962 gen_op_iwmmxt_movq_wRn_M0(wrd);
1963 gen_op_iwmmxt_set_mup();
1964 gen_op_iwmmxt_set_cup();
1965 break;
1966 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
1967 case 0x214: case 0x614: case 0xa14: case 0xe14:
1968 if (((insn >> 22) & 3) == 0)
1969 return 1;
1970 wrd = (insn >> 12) & 0xf;
1971 rd0 = (insn >> 16) & 0xf;
1972 gen_op_iwmmxt_movq_M0_wRn(rd0);
1973 tmp = new_tmp();
1974 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
1975 dead_tmp(tmp);
1976 return 1;
1978 switch ((insn >> 22) & 3) {
1979 case 1:
1980 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
1981 break;
1982 case 2:
1983 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
1984 break;
1985 case 3:
1986 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
1987 break;
1989 dead_tmp(tmp);
1990 gen_op_iwmmxt_movq_wRn_M0(wrd);
1991 gen_op_iwmmxt_set_mup();
1992 gen_op_iwmmxt_set_cup();
1993 break;
1994 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
1995 case 0x014: case 0x414: case 0x814: case 0xc14:
1996 if (((insn >> 22) & 3) == 0)
1997 return 1;
1998 wrd = (insn >> 12) & 0xf;
1999 rd0 = (insn >> 16) & 0xf;
2000 gen_op_iwmmxt_movq_M0_wRn(rd0);
2001 tmp = new_tmp();
2002 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2003 dead_tmp(tmp);
2004 return 1;
2006 switch ((insn >> 22) & 3) {
2007 case 1:
2008 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2009 break;
2010 case 2:
2011 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2012 break;
2013 case 3:
2014 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2015 break;
2017 dead_tmp(tmp);
2018 gen_op_iwmmxt_movq_wRn_M0(wrd);
2019 gen_op_iwmmxt_set_mup();
2020 gen_op_iwmmxt_set_cup();
2021 break;
2022 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2023 case 0x114: case 0x514: case 0x914: case 0xd14:
2024 if (((insn >> 22) & 3) == 0)
2025 return 1;
2026 wrd = (insn >> 12) & 0xf;
2027 rd0 = (insn >> 16) & 0xf;
2028 gen_op_iwmmxt_movq_M0_wRn(rd0);
2029 tmp = new_tmp();
2030 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2031 dead_tmp(tmp);
2032 return 1;
2034 switch ((insn >> 22) & 3) {
2035 case 1:
2036 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2037 break;
2038 case 2:
2039 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2040 break;
2041 case 3:
2042 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2043 break;
2045 dead_tmp(tmp);
2046 gen_op_iwmmxt_movq_wRn_M0(wrd);
2047 gen_op_iwmmxt_set_mup();
2048 gen_op_iwmmxt_set_cup();
2049 break;
2050 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2051 case 0x314: case 0x714: case 0xb14: case 0xf14:
2052 if (((insn >> 22) & 3) == 0)
2053 return 1;
2054 wrd = (insn >> 12) & 0xf;
2055 rd0 = (insn >> 16) & 0xf;
2056 gen_op_iwmmxt_movq_M0_wRn(rd0);
2057 tmp = new_tmp();
2058 switch ((insn >> 22) & 3) {
2059 case 1:
2060 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2061 dead_tmp(tmp);
2062 return 1;
2064 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2065 break;
2066 case 2:
2067 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2068 dead_tmp(tmp);
2069 return 1;
2071 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2072 break;
2073 case 3:
2074 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2075 dead_tmp(tmp);
2076 return 1;
2078 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2079 break;
2081 dead_tmp(tmp);
2082 gen_op_iwmmxt_movq_wRn_M0(wrd);
2083 gen_op_iwmmxt_set_mup();
2084 gen_op_iwmmxt_set_cup();
2085 break;
2086 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2087 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2088 wrd = (insn >> 12) & 0xf;
2089 rd0 = (insn >> 16) & 0xf;
2090 rd1 = (insn >> 0) & 0xf;
2091 gen_op_iwmmxt_movq_M0_wRn(rd0);
2092 switch ((insn >> 22) & 3) {
2093 case 0:
2094 if (insn & (1 << 21))
2095 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2096 else
2097 gen_op_iwmmxt_minub_M0_wRn(rd1);
2098 break;
2099 case 1:
2100 if (insn & (1 << 21))
2101 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2102 else
2103 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2104 break;
2105 case 2:
2106 if (insn & (1 << 21))
2107 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2108 else
2109 gen_op_iwmmxt_minul_M0_wRn(rd1);
2110 break;
2111 case 3:
2112 return 1;
2114 gen_op_iwmmxt_movq_wRn_M0(wrd);
2115 gen_op_iwmmxt_set_mup();
2116 break;
2117 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2118 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2119 wrd = (insn >> 12) & 0xf;
2120 rd0 = (insn >> 16) & 0xf;
2121 rd1 = (insn >> 0) & 0xf;
2122 gen_op_iwmmxt_movq_M0_wRn(rd0);
2123 switch ((insn >> 22) & 3) {
2124 case 0:
2125 if (insn & (1 << 21))
2126 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2127 else
2128 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2129 break;
2130 case 1:
2131 if (insn & (1 << 21))
2132 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2133 else
2134 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2135 break;
2136 case 2:
2137 if (insn & (1 << 21))
2138 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2139 else
2140 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2141 break;
2142 case 3:
2143 return 1;
2145 gen_op_iwmmxt_movq_wRn_M0(wrd);
2146 gen_op_iwmmxt_set_mup();
2147 break;
2148 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2149 case 0x402: case 0x502: case 0x602: case 0x702:
2150 wrd = (insn >> 12) & 0xf;
2151 rd0 = (insn >> 16) & 0xf;
2152 rd1 = (insn >> 0) & 0xf;
2153 gen_op_iwmmxt_movq_M0_wRn(rd0);
2154 tmp = tcg_const_i32((insn >> 20) & 3);
2155 iwmmxt_load_reg(cpu_V1, rd1);
2156 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2157 tcg_temp_free(tmp);
2158 gen_op_iwmmxt_movq_wRn_M0(wrd);
2159 gen_op_iwmmxt_set_mup();
2160 break;
2161 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2162 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2163 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2164 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2165 wrd = (insn >> 12) & 0xf;
2166 rd0 = (insn >> 16) & 0xf;
2167 rd1 = (insn >> 0) & 0xf;
2168 gen_op_iwmmxt_movq_M0_wRn(rd0);
2169 switch ((insn >> 20) & 0xf) {
2170 case 0x0:
2171 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2172 break;
2173 case 0x1:
2174 gen_op_iwmmxt_subub_M0_wRn(rd1);
2175 break;
2176 case 0x3:
2177 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2178 break;
2179 case 0x4:
2180 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2181 break;
2182 case 0x5:
2183 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2184 break;
2185 case 0x7:
2186 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2187 break;
2188 case 0x8:
2189 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2190 break;
2191 case 0x9:
2192 gen_op_iwmmxt_subul_M0_wRn(rd1);
2193 break;
2194 case 0xb:
2195 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2196 break;
2197 default:
2198 return 1;
2200 gen_op_iwmmxt_movq_wRn_M0(wrd);
2201 gen_op_iwmmxt_set_mup();
2202 gen_op_iwmmxt_set_cup();
2203 break;
2204 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2205 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2206 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2207 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2208 wrd = (insn >> 12) & 0xf;
2209 rd0 = (insn >> 16) & 0xf;
2210 gen_op_iwmmxt_movq_M0_wRn(rd0);
2211 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2212 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2213 tcg_temp_free(tmp);
2214 gen_op_iwmmxt_movq_wRn_M0(wrd);
2215 gen_op_iwmmxt_set_mup();
2216 gen_op_iwmmxt_set_cup();
2217 break;
2218 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2219 case 0x418: case 0x518: case 0x618: case 0x718:
2220 case 0x818: case 0x918: case 0xa18: case 0xb18:
2221 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2222 wrd = (insn >> 12) & 0xf;
2223 rd0 = (insn >> 16) & 0xf;
2224 rd1 = (insn >> 0) & 0xf;
2225 gen_op_iwmmxt_movq_M0_wRn(rd0);
2226 switch ((insn >> 20) & 0xf) {
2227 case 0x0:
2228 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2229 break;
2230 case 0x1:
2231 gen_op_iwmmxt_addub_M0_wRn(rd1);
2232 break;
2233 case 0x3:
2234 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2235 break;
2236 case 0x4:
2237 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2238 break;
2239 case 0x5:
2240 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2241 break;
2242 case 0x7:
2243 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2244 break;
2245 case 0x8:
2246 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2247 break;
2248 case 0x9:
2249 gen_op_iwmmxt_addul_M0_wRn(rd1);
2250 break;
2251 case 0xb:
2252 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2253 break;
2254 default:
2255 return 1;
2257 gen_op_iwmmxt_movq_wRn_M0(wrd);
2258 gen_op_iwmmxt_set_mup();
2259 gen_op_iwmmxt_set_cup();
2260 break;
2261 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2262 case 0x408: case 0x508: case 0x608: case 0x708:
2263 case 0x808: case 0x908: case 0xa08: case 0xb08:
2264 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2265 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2266 return 1;
2267 wrd = (insn >> 12) & 0xf;
2268 rd0 = (insn >> 16) & 0xf;
2269 rd1 = (insn >> 0) & 0xf;
2270 gen_op_iwmmxt_movq_M0_wRn(rd0);
2271 switch ((insn >> 22) & 3) {
2272 case 1:
2273 if (insn & (1 << 21))
2274 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2275 else
2276 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2277 break;
2278 case 2:
2279 if (insn & (1 << 21))
2280 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2281 else
2282 gen_op_iwmmxt_packul_M0_wRn(rd1);
2283 break;
2284 case 3:
2285 if (insn & (1 << 21))
2286 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2287 else
2288 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2289 break;
2291 gen_op_iwmmxt_movq_wRn_M0(wrd);
2292 gen_op_iwmmxt_set_mup();
2293 gen_op_iwmmxt_set_cup();
2294 break;
2295 case 0x201: case 0x203: case 0x205: case 0x207:
2296 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2297 case 0x211: case 0x213: case 0x215: case 0x217:
2298 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2299 wrd = (insn >> 5) & 0xf;
2300 rd0 = (insn >> 12) & 0xf;
2301 rd1 = (insn >> 0) & 0xf;
2302 if (rd0 == 0xf || rd1 == 0xf)
2303 return 1;
2304 gen_op_iwmmxt_movq_M0_wRn(wrd);
2305 tmp = load_reg(s, rd0);
2306 tmp2 = load_reg(s, rd1);
2307 switch ((insn >> 16) & 0xf) {
2308 case 0x0: /* TMIA */
2309 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2310 break;
2311 case 0x8: /* TMIAPH */
2312 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2313 break;
2314 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2315 if (insn & (1 << 16))
2316 tcg_gen_shri_i32(tmp, tmp, 16);
2317 if (insn & (1 << 17))
2318 tcg_gen_shri_i32(tmp2, tmp2, 16);
2319 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2320 break;
2321 default:
2322 dead_tmp(tmp2);
2323 dead_tmp(tmp);
2324 return 1;
2326 dead_tmp(tmp2);
2327 dead_tmp(tmp);
2328 gen_op_iwmmxt_movq_wRn_M0(wrd);
2329 gen_op_iwmmxt_set_mup();
2330 break;
2331 default:
2332 return 1;
2335 return 0;
2338 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2339 (ie. an undefined instruction). */
2340 static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2342 int acc, rd0, rd1, rdhi, rdlo;
2343 TCGv tmp, tmp2;
2345 if ((insn & 0x0ff00f10) == 0x0e200010) {
2346 /* Multiply with Internal Accumulate Format */
2347 rd0 = (insn >> 12) & 0xf;
2348 rd1 = insn & 0xf;
2349 acc = (insn >> 5) & 7;
2351 if (acc != 0)
2352 return 1;
2354 tmp = load_reg(s, rd0);
2355 tmp2 = load_reg(s, rd1);
2356 switch ((insn >> 16) & 0xf) {
2357 case 0x0: /* MIA */
2358 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2359 break;
2360 case 0x8: /* MIAPH */
2361 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2362 break;
2363 case 0xc: /* MIABB */
2364 case 0xd: /* MIABT */
2365 case 0xe: /* MIATB */
2366 case 0xf: /* MIATT */
2367 if (insn & (1 << 16))
2368 tcg_gen_shri_i32(tmp, tmp, 16);
2369 if (insn & (1 << 17))
2370 tcg_gen_shri_i32(tmp2, tmp2, 16);
2371 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2372 break;
2373 default:
2374 return 1;
2376 dead_tmp(tmp2);
2377 dead_tmp(tmp);
2379 gen_op_iwmmxt_movq_wRn_M0(acc);
2380 return 0;
2383 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2384 /* Internal Accumulator Access Format */
2385 rdhi = (insn >> 16) & 0xf;
2386 rdlo = (insn >> 12) & 0xf;
2387 acc = insn & 7;
2389 if (acc != 0)
2390 return 1;
2392 if (insn & ARM_CP_RW_BIT) { /* MRA */
2393 iwmmxt_load_reg(cpu_V0, acc);
2394 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
2395 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
2396 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
2397 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2398 } else { /* MAR */
2399 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2400 iwmmxt_store_reg(cpu_V0, acc);
2402 return 0;
2405 return 1;
2408 /* Disassemble system coprocessor instruction. Return nonzero if
2409 instruction is not defined. */
2410 static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2412 TCGv tmp, tmp2;
2413 uint32_t rd = (insn >> 12) & 0xf;
2414 uint32_t cp = (insn >> 8) & 0xf;
2415 if (IS_USER(s)) {
2416 return 1;
2419 if (insn & ARM_CP_RW_BIT) {
2420 if (!env->cp[cp].cp_read)
2421 return 1;
2422 gen_set_pc_im(s->pc);
2423 tmp = new_tmp();
2424 tmp2 = tcg_const_i32(insn);
2425 gen_helper_get_cp(tmp, cpu_env, tmp2);
2426 tcg_temp_free(tmp2);
2427 store_reg(s, rd, tmp);
2428 } else {
2429 if (!env->cp[cp].cp_write)
2430 return 1;
2431 gen_set_pc_im(s->pc);
2432 tmp = load_reg(s, rd);
2433 tmp2 = tcg_const_i32(insn);
2434 gen_helper_set_cp(cpu_env, tmp2, tmp);
2435 tcg_temp_free(tmp2);
2436 dead_tmp(tmp);
2438 return 0;
2441 static int cp15_user_ok(uint32_t insn)
2443 int cpn = (insn >> 16) & 0xf;
2444 int cpm = insn & 0xf;
2445 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2447 if (cpn == 13 && cpm == 0) {
2448 /* TLS register. */
2449 if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2450 return 1;
2452 if (cpn == 7) {
2453 /* ISB, DSB, DMB. */
2454 if ((cpm == 5 && op == 4)
2455 || (cpm == 10 && (op == 4 || op == 5)))
2456 return 1;
2458 return 0;
2461 static int cp15_tls_load_store(CPUState *env, DisasContext *s, uint32_t insn, uint32_t rd)
2463 TCGv tmp;
2464 int cpn = (insn >> 16) & 0xf;
2465 int cpm = insn & 0xf;
2466 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2468 if (!arm_feature(env, ARM_FEATURE_V6K))
2469 return 0;
2471 if (!(cpn == 13 && cpm == 0))
2472 return 0;
2474 if (insn & ARM_CP_RW_BIT) {
2475 switch (op) {
2476 case 2:
2477 tmp = load_cpu_field(cp15.c13_tls1);
2478 break;
2479 case 3:
2480 tmp = load_cpu_field(cp15.c13_tls2);
2481 break;
2482 case 4:
2483 tmp = load_cpu_field(cp15.c13_tls3);
2484 break;
2485 default:
2486 return 0;
2488 store_reg(s, rd, tmp);
2490 } else {
2491 tmp = load_reg(s, rd);
2492 switch (op) {
2493 case 2:
2494 store_cpu_field(tmp, cp15.c13_tls1);
2495 break;
2496 case 3:
2497 store_cpu_field(tmp, cp15.c13_tls2);
2498 break;
2499 case 4:
2500 store_cpu_field(tmp, cp15.c13_tls3);
2501 break;
2502 default:
2503 dead_tmp(tmp);
2504 return 0;
2507 return 1;
2510 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2511 instruction is not defined. */
2512 static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2514 uint32_t rd;
2515 TCGv tmp, tmp2;
2517 /* M profile cores use memory mapped registers instead of cp15. */
2518 if (arm_feature(env, ARM_FEATURE_M))
2519 return 1;
2521 if ((insn & (1 << 25)) == 0) {
2522 if (insn & (1 << 20)) {
2523 /* mrrc */
2524 return 1;
2526 /* mcrr. Used for block cache operations, so implement as no-op. */
2527 return 0;
2529 if ((insn & (1 << 4)) == 0) {
2530 /* cdp */
2531 return 1;
2533 if (IS_USER(s) && !cp15_user_ok(insn)) {
2534 return 1;
2536 if ((insn & 0x0fff0fff) == 0x0e070f90
2537 || (insn & 0x0fff0fff) == 0x0e070f58) {
2538 /* Wait for interrupt. */
2539 gen_set_pc_im(s->pc);
2540 s->is_jmp = DISAS_WFI;
2541 return 0;
2543 rd = (insn >> 12) & 0xf;
2545 if (cp15_tls_load_store(env, s, insn, rd))
2546 return 0;
2548 tmp2 = tcg_const_i32(insn);
2549 if (insn & ARM_CP_RW_BIT) {
2550 tmp = new_tmp();
2551 gen_helper_get_cp15(tmp, cpu_env, tmp2);
2552 /* If the destination register is r15 then sets condition codes. */
2553 if (rd != 15)
2554 store_reg(s, rd, tmp);
2555 else
2556 dead_tmp(tmp);
2557 } else {
2558 tmp = load_reg(s, rd);
2559 gen_helper_set_cp15(cpu_env, tmp2, tmp);
2560 dead_tmp(tmp);
2561 /* Normally we would always end the TB here, but Linux
2562 * arch/arm/mach-pxa/sleep.S expects two instructions following
2563 * an MMU enable to execute from cache. Imitate this behaviour. */
2564 if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2565 (insn & 0x0fff0fff) != 0x0e010f10)
2566 gen_lookup_tb(s);
2568 tcg_temp_free_i32(tmp2);
2569 return 0;
2572 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2573 #define VFP_SREG(insn, bigbit, smallbit) \
2574 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2575 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2576 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2577 reg = (((insn) >> (bigbit)) & 0x0f) \
2578 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2579 } else { \
2580 if (insn & (1 << (smallbit))) \
2581 return 1; \
2582 reg = ((insn) >> (bigbit)) & 0x0f; \
2583 }} while (0)
2585 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2586 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2587 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2588 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2589 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2590 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2592 /* Move between integer and VFP cores. */
2593 static TCGv gen_vfp_mrs(void)
2595 TCGv tmp = new_tmp();
2596 tcg_gen_mov_i32(tmp, cpu_F0s);
2597 return tmp;
2600 static void gen_vfp_msr(TCGv tmp)
2602 tcg_gen_mov_i32(cpu_F0s, tmp);
2603 dead_tmp(tmp);
2606 static inline int
2607 vfp_enabled(CPUState * env)
2609 return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
2612 static void gen_neon_dup_u8(TCGv var, int shift)
2614 TCGv tmp = new_tmp();
2615 if (shift)
2616 tcg_gen_shri_i32(var, var, shift);
2617 tcg_gen_ext8u_i32(var, var);
2618 tcg_gen_shli_i32(tmp, var, 8);
2619 tcg_gen_or_i32(var, var, tmp);
2620 tcg_gen_shli_i32(tmp, var, 16);
2621 tcg_gen_or_i32(var, var, tmp);
2622 dead_tmp(tmp);
2625 static void gen_neon_dup_low16(TCGv var)
2627 TCGv tmp = new_tmp();
2628 tcg_gen_ext16u_i32(var, var);
2629 tcg_gen_shli_i32(tmp, var, 16);
2630 tcg_gen_or_i32(var, var, tmp);
2631 dead_tmp(tmp);
2634 static void gen_neon_dup_high16(TCGv var)
2636 TCGv tmp = new_tmp();
2637 tcg_gen_andi_i32(var, var, 0xffff0000);
2638 tcg_gen_shri_i32(tmp, var, 16);
2639 tcg_gen_or_i32(var, var, tmp);
2640 dead_tmp(tmp);
2643 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2644 (ie. an undefined instruction). */
2645 static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2647 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2648 int dp, veclen;
2649 TCGv addr;
2650 TCGv tmp;
2651 TCGv tmp2;
2653 if (!arm_feature(env, ARM_FEATURE_VFP))
2654 return 1;
2656 if (!vfp_enabled(env)) {
2657 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2658 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2659 return 1;
2660 rn = (insn >> 16) & 0xf;
2661 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2662 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2663 return 1;
2665 dp = ((insn & 0xf00) == 0xb00);
2666 switch ((insn >> 24) & 0xf) {
2667 case 0xe:
2668 if (insn & (1 << 4)) {
2669 /* single register transfer */
2670 rd = (insn >> 12) & 0xf;
2671 if (dp) {
2672 int size;
2673 int pass;
2675 VFP_DREG_N(rn, insn);
2676 if (insn & 0xf)
2677 return 1;
2678 if (insn & 0x00c00060
2679 && !arm_feature(env, ARM_FEATURE_NEON))
2680 return 1;
2682 pass = (insn >> 21) & 1;
2683 if (insn & (1 << 22)) {
2684 size = 0;
2685 offset = ((insn >> 5) & 3) * 8;
2686 } else if (insn & (1 << 5)) {
2687 size = 1;
2688 offset = (insn & (1 << 6)) ? 16 : 0;
2689 } else {
2690 size = 2;
2691 offset = 0;
2693 if (insn & ARM_CP_RW_BIT) {
2694 /* vfp->arm */
2695 tmp = neon_load_reg(rn, pass);
2696 switch (size) {
2697 case 0:
2698 if (offset)
2699 tcg_gen_shri_i32(tmp, tmp, offset);
2700 if (insn & (1 << 23))
2701 gen_uxtb(tmp);
2702 else
2703 gen_sxtb(tmp);
2704 break;
2705 case 1:
2706 if (insn & (1 << 23)) {
2707 if (offset) {
2708 tcg_gen_shri_i32(tmp, tmp, 16);
2709 } else {
2710 gen_uxth(tmp);
2712 } else {
2713 if (offset) {
2714 tcg_gen_sari_i32(tmp, tmp, 16);
2715 } else {
2716 gen_sxth(tmp);
2719 break;
2720 case 2:
2721 break;
2723 store_reg(s, rd, tmp);
2724 } else {
2725 /* arm->vfp */
2726 tmp = load_reg(s, rd);
2727 if (insn & (1 << 23)) {
2728 /* VDUP */
2729 if (size == 0) {
2730 gen_neon_dup_u8(tmp, 0);
2731 } else if (size == 1) {
2732 gen_neon_dup_low16(tmp);
2734 for (n = 0; n <= pass * 2; n++) {
2735 tmp2 = new_tmp();
2736 tcg_gen_mov_i32(tmp2, tmp);
2737 neon_store_reg(rn, n, tmp2);
2739 neon_store_reg(rn, n, tmp);
2740 } else {
2741 /* VMOV */
2742 switch (size) {
2743 case 0:
2744 tmp2 = neon_load_reg(rn, pass);
2745 gen_bfi(tmp, tmp2, tmp, offset, 0xff);
2746 dead_tmp(tmp2);
2747 break;
2748 case 1:
2749 tmp2 = neon_load_reg(rn, pass);
2750 gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
2751 dead_tmp(tmp2);
2752 break;
2753 case 2:
2754 break;
2756 neon_store_reg(rn, pass, tmp);
2759 } else { /* !dp */
2760 if ((insn & 0x6f) != 0x00)
2761 return 1;
2762 rn = VFP_SREG_N(insn);
2763 if (insn & ARM_CP_RW_BIT) {
2764 /* vfp->arm */
2765 if (insn & (1 << 21)) {
2766 /* system register */
2767 rn >>= 1;
2769 switch (rn) {
2770 case ARM_VFP_FPSID:
2771 /* VFP2 allows access to FSID from userspace.
2772 VFP3 restricts all id registers to privileged
2773 accesses. */
2774 if (IS_USER(s)
2775 && arm_feature(env, ARM_FEATURE_VFP3))
2776 return 1;
2777 tmp = load_cpu_field(vfp.xregs[rn]);
2778 break;
2779 case ARM_VFP_FPEXC:
2780 if (IS_USER(s))
2781 return 1;
2782 tmp = load_cpu_field(vfp.xregs[rn]);
2783 break;
2784 case ARM_VFP_FPINST:
2785 case ARM_VFP_FPINST2:
2786 /* Not present in VFP3. */
2787 if (IS_USER(s)
2788 || arm_feature(env, ARM_FEATURE_VFP3))
2789 return 1;
2790 tmp = load_cpu_field(vfp.xregs[rn]);
2791 break;
2792 case ARM_VFP_FPSCR:
2793 if (rd == 15) {
2794 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2795 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2796 } else {
2797 tmp = new_tmp();
2798 gen_helper_vfp_get_fpscr(tmp, cpu_env);
2800 break;
2801 case ARM_VFP_MVFR0:
2802 case ARM_VFP_MVFR1:
2803 if (IS_USER(s)
2804 || !arm_feature(env, ARM_FEATURE_VFP3))
2805 return 1;
2806 tmp = load_cpu_field(vfp.xregs[rn]);
2807 break;
2808 default:
2809 return 1;
2811 } else {
2812 gen_mov_F0_vreg(0, rn);
2813 tmp = gen_vfp_mrs();
2815 if (rd == 15) {
2816 /* Set the 4 flag bits in the CPSR. */
2817 gen_set_nzcv(tmp);
2818 dead_tmp(tmp);
2819 } else {
2820 store_reg(s, rd, tmp);
2822 } else {
2823 /* arm->vfp */
2824 tmp = load_reg(s, rd);
2825 if (insn & (1 << 21)) {
2826 rn >>= 1;
2827 /* system register */
2828 switch (rn) {
2829 case ARM_VFP_FPSID:
2830 case ARM_VFP_MVFR0:
2831 case ARM_VFP_MVFR1:
2832 /* Writes are ignored. */
2833 break;
2834 case ARM_VFP_FPSCR:
2835 gen_helper_vfp_set_fpscr(cpu_env, tmp);
2836 dead_tmp(tmp);
2837 gen_lookup_tb(s);
2838 break;
2839 case ARM_VFP_FPEXC:
2840 if (IS_USER(s))
2841 return 1;
2842 /* TODO: VFP subarchitecture support.
2843 * For now, keep the EN bit only */
2844 tcg_gen_andi_i32(tmp, tmp, 1 << 30);
2845 store_cpu_field(tmp, vfp.xregs[rn]);
2846 gen_lookup_tb(s);
2847 break;
2848 case ARM_VFP_FPINST:
2849 case ARM_VFP_FPINST2:
2850 store_cpu_field(tmp, vfp.xregs[rn]);
2851 break;
2852 default:
2853 return 1;
2855 } else {
2856 gen_vfp_msr(tmp);
2857 gen_mov_vreg_F0(0, rn);
2861 } else {
2862 /* data processing */
2863 /* The opcode is in bits 23, 21, 20 and 6. */
2864 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2865 if (dp) {
2866 if (op == 15) {
2867 /* rn is opcode */
2868 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2869 } else {
2870 /* rn is register number */
2871 VFP_DREG_N(rn, insn);
2874 if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18))) {
2875 /* Integer or single precision destination. */
2876 rd = VFP_SREG_D(insn);
2877 } else {
2878 VFP_DREG_D(rd, insn);
2880 if (op == 15 &&
2881 (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14))) {
2882 /* VCVT from int is always from S reg regardless of dp bit.
2883 * VCVT with immediate frac_bits has same format as SREG_M
2885 rm = VFP_SREG_M(insn);
2886 } else {
2887 VFP_DREG_M(rm, insn);
2889 } else {
2890 rn = VFP_SREG_N(insn);
2891 if (op == 15 && rn == 15) {
2892 /* Double precision destination. */
2893 VFP_DREG_D(rd, insn);
2894 } else {
2895 rd = VFP_SREG_D(insn);
2897 /* NB that we implicitly rely on the encoding for the frac_bits
2898 * in VCVT of fixed to float being the same as that of an SREG_M
2900 rm = VFP_SREG_M(insn);
2903 veclen = env->vfp.vec_len;
2904 if (op == 15 && rn > 3)
2905 veclen = 0;
2907 /* Shut up compiler warnings. */
2908 delta_m = 0;
2909 delta_d = 0;
2910 bank_mask = 0;
2912 if (veclen > 0) {
2913 if (dp)
2914 bank_mask = 0xc;
2915 else
2916 bank_mask = 0x18;
2918 /* Figure out what type of vector operation this is. */
2919 if ((rd & bank_mask) == 0) {
2920 /* scalar */
2921 veclen = 0;
2922 } else {
2923 if (dp)
2924 delta_d = (env->vfp.vec_stride >> 1) + 1;
2925 else
2926 delta_d = env->vfp.vec_stride + 1;
2928 if ((rm & bank_mask) == 0) {
2929 /* mixed scalar/vector */
2930 delta_m = 0;
2931 } else {
2932 /* vector */
2933 delta_m = delta_d;
2938 /* Load the initial operands. */
2939 if (op == 15) {
2940 switch (rn) {
2941 case 16:
2942 case 17:
2943 /* Integer source */
2944 gen_mov_F0_vreg(0, rm);
2945 break;
2946 case 8:
2947 case 9:
2948 /* Compare */
2949 gen_mov_F0_vreg(dp, rd);
2950 gen_mov_F1_vreg(dp, rm);
2951 break;
2952 case 10:
2953 case 11:
2954 /* Compare with zero */
2955 gen_mov_F0_vreg(dp, rd);
2956 gen_vfp_F1_ld0(dp);
2957 break;
2958 case 20:
2959 case 21:
2960 case 22:
2961 case 23:
2962 case 28:
2963 case 29:
2964 case 30:
2965 case 31:
2966 /* Source and destination the same. */
2967 gen_mov_F0_vreg(dp, rd);
2968 break;
2969 default:
2970 /* One source operand. */
2971 gen_mov_F0_vreg(dp, rm);
2972 break;
2974 } else {
2975 /* Two source operands. */
2976 gen_mov_F0_vreg(dp, rn);
2977 gen_mov_F1_vreg(dp, rm);
2980 for (;;) {
2981 /* Perform the calculation. */
2982 switch (op) {
2983 case 0: /* mac: fd + (fn * fm) */
2984 gen_vfp_mul(dp);
2985 gen_mov_F1_vreg(dp, rd);
2986 gen_vfp_add(dp);
2987 break;
2988 case 1: /* nmac: fd - (fn * fm) */
2989 gen_vfp_mul(dp);
2990 gen_vfp_neg(dp);
2991 gen_mov_F1_vreg(dp, rd);
2992 gen_vfp_add(dp);
2993 break;
2994 case 2: /* msc: -fd + (fn * fm) */
2995 gen_vfp_mul(dp);
2996 gen_mov_F1_vreg(dp, rd);
2997 gen_vfp_sub(dp);
2998 break;
2999 case 3: /* nmsc: -fd - (fn * fm) */
3000 gen_vfp_mul(dp);
3001 gen_vfp_neg(dp);
3002 gen_mov_F1_vreg(dp, rd);
3003 gen_vfp_sub(dp);
3004 break;
3005 case 4: /* mul: fn * fm */
3006 gen_vfp_mul(dp);
3007 break;
3008 case 5: /* nmul: -(fn * fm) */
3009 gen_vfp_mul(dp);
3010 gen_vfp_neg(dp);
3011 break;
3012 case 6: /* add: fn + fm */
3013 gen_vfp_add(dp);
3014 break;
3015 case 7: /* sub: fn - fm */
3016 gen_vfp_sub(dp);
3017 break;
3018 case 8: /* div: fn / fm */
3019 gen_vfp_div(dp);
3020 break;
3021 case 14: /* fconst */
3022 if (!arm_feature(env, ARM_FEATURE_VFP3))
3023 return 1;
3025 n = (insn << 12) & 0x80000000;
3026 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3027 if (dp) {
3028 if (i & 0x40)
3029 i |= 0x3f80;
3030 else
3031 i |= 0x4000;
3032 n |= i << 16;
3033 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3034 } else {
3035 if (i & 0x40)
3036 i |= 0x780;
3037 else
3038 i |= 0x800;
3039 n |= i << 19;
3040 tcg_gen_movi_i32(cpu_F0s, n);
3042 break;
3043 case 15: /* extension space */
3044 switch (rn) {
3045 case 0: /* cpy */
3046 /* no-op */
3047 break;
3048 case 1: /* abs */
3049 gen_vfp_abs(dp);
3050 break;
3051 case 2: /* neg */
3052 gen_vfp_neg(dp);
3053 break;
3054 case 3: /* sqrt */
3055 gen_vfp_sqrt(dp);
3056 break;
3057 case 4: /* vcvtb.f32.f16 */
3058 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3059 return 1;
3060 tmp = gen_vfp_mrs();
3061 tcg_gen_ext16u_i32(tmp, tmp);
3062 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3063 dead_tmp(tmp);
3064 break;
3065 case 5: /* vcvtt.f32.f16 */
3066 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3067 return 1;
3068 tmp = gen_vfp_mrs();
3069 tcg_gen_shri_i32(tmp, tmp, 16);
3070 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3071 dead_tmp(tmp);
3072 break;
3073 case 6: /* vcvtb.f16.f32 */
3074 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3075 return 1;
3076 tmp = new_tmp();
3077 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3078 gen_mov_F0_vreg(0, rd);
3079 tmp2 = gen_vfp_mrs();
3080 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3081 tcg_gen_or_i32(tmp, tmp, tmp2);
3082 dead_tmp(tmp2);
3083 gen_vfp_msr(tmp);
3084 break;
3085 case 7: /* vcvtt.f16.f32 */
3086 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3087 return 1;
3088 tmp = new_tmp();
3089 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3090 tcg_gen_shli_i32(tmp, tmp, 16);
3091 gen_mov_F0_vreg(0, rd);
3092 tmp2 = gen_vfp_mrs();
3093 tcg_gen_ext16u_i32(tmp2, tmp2);
3094 tcg_gen_or_i32(tmp, tmp, tmp2);
3095 dead_tmp(tmp2);
3096 gen_vfp_msr(tmp);
3097 break;
3098 case 8: /* cmp */
3099 gen_vfp_cmp(dp);
3100 break;
3101 case 9: /* cmpe */
3102 gen_vfp_cmpe(dp);
3103 break;
3104 case 10: /* cmpz */
3105 gen_vfp_cmp(dp);
3106 break;
3107 case 11: /* cmpez */
3108 gen_vfp_F1_ld0(dp);
3109 gen_vfp_cmpe(dp);
3110 break;
3111 case 15: /* single<->double conversion */
3112 if (dp)
3113 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3114 else
3115 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3116 break;
3117 case 16: /* fuito */
3118 gen_vfp_uito(dp);
3119 break;
3120 case 17: /* fsito */
3121 gen_vfp_sito(dp);
3122 break;
3123 case 20: /* fshto */
3124 if (!arm_feature(env, ARM_FEATURE_VFP3))
3125 return 1;
3126 gen_vfp_shto(dp, 16 - rm);
3127 break;
3128 case 21: /* fslto */
3129 if (!arm_feature(env, ARM_FEATURE_VFP3))
3130 return 1;
3131 gen_vfp_slto(dp, 32 - rm);
3132 break;
3133 case 22: /* fuhto */
3134 if (!arm_feature(env, ARM_FEATURE_VFP3))
3135 return 1;
3136 gen_vfp_uhto(dp, 16 - rm);
3137 break;
3138 case 23: /* fulto */
3139 if (!arm_feature(env, ARM_FEATURE_VFP3))
3140 return 1;
3141 gen_vfp_ulto(dp, 32 - rm);
3142 break;
3143 case 24: /* ftoui */
3144 gen_vfp_toui(dp);
3145 break;
3146 case 25: /* ftouiz */
3147 gen_vfp_touiz(dp);
3148 break;
3149 case 26: /* ftosi */
3150 gen_vfp_tosi(dp);
3151 break;
3152 case 27: /* ftosiz */
3153 gen_vfp_tosiz(dp);
3154 break;
3155 case 28: /* ftosh */
3156 if (!arm_feature(env, ARM_FEATURE_VFP3))
3157 return 1;
3158 gen_vfp_tosh(dp, 16 - rm);
3159 break;
3160 case 29: /* ftosl */
3161 if (!arm_feature(env, ARM_FEATURE_VFP3))
3162 return 1;
3163 gen_vfp_tosl(dp, 32 - rm);
3164 break;
3165 case 30: /* ftouh */
3166 if (!arm_feature(env, ARM_FEATURE_VFP3))
3167 return 1;
3168 gen_vfp_touh(dp, 16 - rm);
3169 break;
3170 case 31: /* ftoul */
3171 if (!arm_feature(env, ARM_FEATURE_VFP3))
3172 return 1;
3173 gen_vfp_toul(dp, 32 - rm);
3174 break;
3175 default: /* undefined */
3176 printf ("rn:%d\n", rn);
3177 return 1;
3179 break;
3180 default: /* undefined */
3181 printf ("op:%d\n", op);
3182 return 1;
3185 /* Write back the result. */
3186 if (op == 15 && (rn >= 8 && rn <= 11))
3187 ; /* Comparison, do nothing. */
3188 else if (op == 15 && dp && ((rn & 0x1c) == 0x18))
3189 /* VCVT double to int: always integer result. */
3190 gen_mov_vreg_F0(0, rd);
3191 else if (op == 15 && rn == 15)
3192 /* conversion */
3193 gen_mov_vreg_F0(!dp, rd);
3194 else
3195 gen_mov_vreg_F0(dp, rd);
3197 /* break out of the loop if we have finished */
3198 if (veclen == 0)
3199 break;
3201 if (op == 15 && delta_m == 0) {
3202 /* single source one-many */
3203 while (veclen--) {
3204 rd = ((rd + delta_d) & (bank_mask - 1))
3205 | (rd & bank_mask);
3206 gen_mov_vreg_F0(dp, rd);
3208 break;
3210 /* Setup the next operands. */
3211 veclen--;
3212 rd = ((rd + delta_d) & (bank_mask - 1))
3213 | (rd & bank_mask);
3215 if (op == 15) {
3216 /* One source operand. */
3217 rm = ((rm + delta_m) & (bank_mask - 1))
3218 | (rm & bank_mask);
3219 gen_mov_F0_vreg(dp, rm);
3220 } else {
3221 /* Two source operands. */
3222 rn = ((rn + delta_d) & (bank_mask - 1))
3223 | (rn & bank_mask);
3224 gen_mov_F0_vreg(dp, rn);
3225 if (delta_m) {
3226 rm = ((rm + delta_m) & (bank_mask - 1))
3227 | (rm & bank_mask);
3228 gen_mov_F1_vreg(dp, rm);
3233 break;
3234 case 0xc:
3235 case 0xd:
3236 if (dp && (insn & 0x03e00000) == 0x00400000) {
3237 /* two-register transfer */
3238 rn = (insn >> 16) & 0xf;
3239 rd = (insn >> 12) & 0xf;
3240 if (dp) {
3241 VFP_DREG_M(rm, insn);
3242 } else {
3243 rm = VFP_SREG_M(insn);
3246 if (insn & ARM_CP_RW_BIT) {
3247 /* vfp->arm */
3248 if (dp) {
3249 gen_mov_F0_vreg(0, rm * 2);
3250 tmp = gen_vfp_mrs();
3251 store_reg(s, rd, tmp);
3252 gen_mov_F0_vreg(0, rm * 2 + 1);
3253 tmp = gen_vfp_mrs();
3254 store_reg(s, rn, tmp);
3255 } else {
3256 gen_mov_F0_vreg(0, rm);
3257 tmp = gen_vfp_mrs();
3258 store_reg(s, rn, tmp);
3259 gen_mov_F0_vreg(0, rm + 1);
3260 tmp = gen_vfp_mrs();
3261 store_reg(s, rd, tmp);
3263 } else {
3264 /* arm->vfp */
3265 if (dp) {
3266 tmp = load_reg(s, rd);
3267 gen_vfp_msr(tmp);
3268 gen_mov_vreg_F0(0, rm * 2);
3269 tmp = load_reg(s, rn);
3270 gen_vfp_msr(tmp);
3271 gen_mov_vreg_F0(0, rm * 2 + 1);
3272 } else {
3273 tmp = load_reg(s, rn);
3274 gen_vfp_msr(tmp);
3275 gen_mov_vreg_F0(0, rm);
3276 tmp = load_reg(s, rd);
3277 gen_vfp_msr(tmp);
3278 gen_mov_vreg_F0(0, rm + 1);
3281 } else {
3282 /* Load/store */
3283 rn = (insn >> 16) & 0xf;
3284 if (dp)
3285 VFP_DREG_D(rd, insn);
3286 else
3287 rd = VFP_SREG_D(insn);
3288 if (s->thumb && rn == 15) {
3289 addr = new_tmp();
3290 tcg_gen_movi_i32(addr, s->pc & ~2);
3291 } else {
3292 addr = load_reg(s, rn);
3294 if ((insn & 0x01200000) == 0x01000000) {
3295 /* Single load/store */
3296 offset = (insn & 0xff) << 2;
3297 if ((insn & (1 << 23)) == 0)
3298 offset = -offset;
3299 tcg_gen_addi_i32(addr, addr, offset);
3300 if (insn & (1 << 20)) {
3301 gen_vfp_ld(s, dp, addr);
3302 gen_mov_vreg_F0(dp, rd);
3303 } else {
3304 gen_mov_F0_vreg(dp, rd);
3305 gen_vfp_st(s, dp, addr);
3307 dead_tmp(addr);
3308 } else {
3309 /* load/store multiple */
3310 if (dp)
3311 n = (insn >> 1) & 0x7f;
3312 else
3313 n = insn & 0xff;
3315 if (insn & (1 << 24)) /* pre-decrement */
3316 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
3318 if (dp)
3319 offset = 8;
3320 else
3321 offset = 4;
3322 for (i = 0; i < n; i++) {
3323 if (insn & ARM_CP_RW_BIT) {
3324 /* load */
3325 gen_vfp_ld(s, dp, addr);
3326 gen_mov_vreg_F0(dp, rd + i);
3327 } else {
3328 /* store */
3329 gen_mov_F0_vreg(dp, rd + i);
3330 gen_vfp_st(s, dp, addr);
3332 tcg_gen_addi_i32(addr, addr, offset);
3334 if (insn & (1 << 21)) {
3335 /* writeback */
3336 if (insn & (1 << 24))
3337 offset = -offset * n;
3338 else if (dp && (insn & 1))
3339 offset = 4;
3340 else
3341 offset = 0;
3343 if (offset != 0)
3344 tcg_gen_addi_i32(addr, addr, offset);
3345 store_reg(s, rn, addr);
3346 } else {
3347 dead_tmp(addr);
3351 break;
3352 default:
3353 /* Should never happen. */
3354 return 1;
3356 return 0;
3359 static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3361 TranslationBlock *tb;
3363 tb = s->tb;
3364 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3365 tcg_gen_goto_tb(n);
3366 gen_set_pc_im(dest);
3367 tcg_gen_exit_tb((long)tb + n);
3368 } else {
3369 gen_set_pc_im(dest);
3370 tcg_gen_exit_tb(0);
3374 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3376 if (unlikely(s->singlestep_enabled)) {
3377 /* An indirect jump so that we still trigger the debug exception. */
3378 if (s->thumb)
3379 dest |= 1;
3380 gen_bx_im(s, dest);
3381 } else {
3382 gen_goto_tb(s, 0, dest);
3383 s->is_jmp = DISAS_TB_JUMP;
3387 static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3389 if (x)
3390 tcg_gen_sari_i32(t0, t0, 16);
3391 else
3392 gen_sxth(t0);
3393 if (y)
3394 tcg_gen_sari_i32(t1, t1, 16);
3395 else
3396 gen_sxth(t1);
3397 tcg_gen_mul_i32(t0, t0, t1);
3400 /* Return the mask of PSR bits set by a MSR instruction. */
3401 static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3402 uint32_t mask;
3404 mask = 0;
3405 if (flags & (1 << 0))
3406 mask |= 0xff;
3407 if (flags & (1 << 1))
3408 mask |= 0xff00;
3409 if (flags & (1 << 2))
3410 mask |= 0xff0000;
3411 if (flags & (1 << 3))
3412 mask |= 0xff000000;
3414 /* Mask out undefined bits. */
3415 mask &= ~CPSR_RESERVED;
3416 if (!arm_feature(env, ARM_FEATURE_V6))
3417 mask &= ~(CPSR_E | CPSR_GE);
3418 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3419 mask &= ~CPSR_IT;
3420 /* Mask out execution state bits. */
3421 if (!spsr)
3422 mask &= ~CPSR_EXEC;
3423 /* Mask out privileged bits. */
3424 if (IS_USER(s))
3425 mask &= CPSR_USER;
3426 return mask;
3429 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3430 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0)
3432 TCGv tmp;
3433 if (spsr) {
3434 /* ??? This is also undefined in system mode. */
3435 if (IS_USER(s))
3436 return 1;
3438 tmp = load_cpu_field(spsr);
3439 tcg_gen_andi_i32(tmp, tmp, ~mask);
3440 tcg_gen_andi_i32(t0, t0, mask);
3441 tcg_gen_or_i32(tmp, tmp, t0);
3442 store_cpu_field(tmp, spsr);
3443 } else {
3444 gen_set_cpsr(t0, mask);
3446 dead_tmp(t0);
3447 gen_lookup_tb(s);
3448 return 0;
3451 /* Returns nonzero if access to the PSR is not permitted. */
3452 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3454 TCGv tmp;
3455 tmp = new_tmp();
3456 tcg_gen_movi_i32(tmp, val);
3457 return gen_set_psr(s, mask, spsr, tmp);
3460 /* Generate an old-style exception return. Marks pc as dead. */
3461 static void gen_exception_return(DisasContext *s, TCGv pc)
3463 TCGv tmp;
3464 store_reg(s, 15, pc);
3465 tmp = load_cpu_field(spsr);
3466 gen_set_cpsr(tmp, 0xffffffff);
3467 dead_tmp(tmp);
3468 s->is_jmp = DISAS_UPDATE;
3471 /* Generate a v6 exception return. Marks both values as dead. */
3472 static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3474 gen_set_cpsr(cpsr, 0xffffffff);
3475 dead_tmp(cpsr);
3476 store_reg(s, 15, pc);
3477 s->is_jmp = DISAS_UPDATE;
3480 static inline void
3481 gen_set_condexec (DisasContext *s)
3483 if (s->condexec_mask) {
3484 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3485 TCGv tmp = new_tmp();
3486 tcg_gen_movi_i32(tmp, val);
3487 store_cpu_field(tmp, condexec_bits);
3491 static void gen_nop_hint(DisasContext *s, int val)
3493 switch (val) {
3494 case 3: /* wfi */
3495 gen_set_pc_im(s->pc);
3496 s->is_jmp = DISAS_WFI;
3497 break;
3498 case 2: /* wfe */
3499 case 4: /* sev */
3500 /* TODO: Implement SEV and WFE. May help SMP performance. */
3501 default: /* nop */
3502 break;
3506 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3508 static inline int gen_neon_add(int size, TCGv t0, TCGv t1)
3510 switch (size) {
3511 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
3512 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
3513 case 2: tcg_gen_add_i32(t0, t0, t1); break;
3514 default: return 1;
3516 return 0;
3519 static inline void gen_neon_rsb(int size, TCGv t0, TCGv t1)
3521 switch (size) {
3522 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
3523 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
3524 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
3525 default: return;
3529 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3530 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3531 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3532 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3533 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3535 /* FIXME: This is wrong. They set the wrong overflow bit. */
3536 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3537 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3538 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3539 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3541 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3542 switch ((size << 1) | u) { \
3543 case 0: \
3544 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3545 break; \
3546 case 1: \
3547 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3548 break; \
3549 case 2: \
3550 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3551 break; \
3552 case 3: \
3553 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3554 break; \
3555 case 4: \
3556 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3557 break; \
3558 case 5: \
3559 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3560 break; \
3561 default: return 1; \
3562 }} while (0)
3564 #define GEN_NEON_INTEGER_OP(name) do { \
3565 switch ((size << 1) | u) { \
3566 case 0: \
3567 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3568 break; \
3569 case 1: \
3570 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3571 break; \
3572 case 2: \
3573 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3574 break; \
3575 case 3: \
3576 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3577 break; \
3578 case 4: \
3579 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3580 break; \
3581 case 5: \
3582 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3583 break; \
3584 default: return 1; \
3585 }} while (0)
3587 static TCGv neon_load_scratch(int scratch)
3589 TCGv tmp = new_tmp();
3590 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3591 return tmp;
3594 static void neon_store_scratch(int scratch, TCGv var)
3596 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3597 dead_tmp(var);
3600 static inline TCGv neon_get_scalar(int size, int reg)
3602 TCGv tmp;
3603 if (size == 1) {
3604 tmp = neon_load_reg(reg >> 1, reg & 1);
3605 } else {
3606 tmp = neon_load_reg(reg >> 2, (reg >> 1) & 1);
3607 if (reg & 1) {
3608 gen_neon_dup_low16(tmp);
3609 } else {
3610 gen_neon_dup_high16(tmp);
3613 return tmp;
3616 static void gen_neon_unzip_u8(TCGv t0, TCGv t1)
3618 TCGv rd, rm, tmp;
3620 rd = new_tmp();
3621 rm = new_tmp();
3622 tmp = new_tmp();
3624 tcg_gen_andi_i32(rd, t0, 0xff);
3625 tcg_gen_shri_i32(tmp, t0, 8);
3626 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3627 tcg_gen_or_i32(rd, rd, tmp);
3628 tcg_gen_shli_i32(tmp, t1, 16);
3629 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3630 tcg_gen_or_i32(rd, rd, tmp);
3631 tcg_gen_shli_i32(tmp, t1, 8);
3632 tcg_gen_andi_i32(tmp, tmp, 0xff000000);
3633 tcg_gen_or_i32(rd, rd, tmp);
3635 tcg_gen_shri_i32(rm, t0, 8);
3636 tcg_gen_andi_i32(rm, rm, 0xff);
3637 tcg_gen_shri_i32(tmp, t0, 16);
3638 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3639 tcg_gen_or_i32(rm, rm, tmp);
3640 tcg_gen_shli_i32(tmp, t1, 8);
3641 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3642 tcg_gen_or_i32(rm, rm, tmp);
3643 tcg_gen_andi_i32(tmp, t1, 0xff000000);
3644 tcg_gen_or_i32(t1, rm, tmp);
3645 tcg_gen_mov_i32(t0, rd);
3647 dead_tmp(tmp);
3648 dead_tmp(rm);
3649 dead_tmp(rd);
3652 static void gen_neon_zip_u8(TCGv t0, TCGv t1)
3654 TCGv rd, rm, tmp;
3656 rd = new_tmp();
3657 rm = new_tmp();
3658 tmp = new_tmp();
3660 tcg_gen_andi_i32(rd, t0, 0xff);
3661 tcg_gen_shli_i32(tmp, t1, 8);
3662 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3663 tcg_gen_or_i32(rd, rd, tmp);
3664 tcg_gen_shli_i32(tmp, t0, 16);
3665 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3666 tcg_gen_or_i32(rd, rd, tmp);
3667 tcg_gen_shli_i32(tmp, t1, 24);
3668 tcg_gen_andi_i32(tmp, tmp, 0xff000000);
3669 tcg_gen_or_i32(rd, rd, tmp);
3671 tcg_gen_andi_i32(rm, t1, 0xff000000);
3672 tcg_gen_shri_i32(tmp, t0, 8);
3673 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3674 tcg_gen_or_i32(rm, rm, tmp);
3675 tcg_gen_shri_i32(tmp, t1, 8);
3676 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3677 tcg_gen_or_i32(rm, rm, tmp);
3678 tcg_gen_shri_i32(tmp, t0, 16);
3679 tcg_gen_andi_i32(tmp, tmp, 0xff);
3680 tcg_gen_or_i32(t1, rm, tmp);
3681 tcg_gen_mov_i32(t0, rd);
3683 dead_tmp(tmp);
3684 dead_tmp(rm);
3685 dead_tmp(rd);
3688 static void gen_neon_zip_u16(TCGv t0, TCGv t1)
3690 TCGv tmp, tmp2;
3692 tmp = new_tmp();
3693 tmp2 = new_tmp();
3695 tcg_gen_andi_i32(tmp, t0, 0xffff);
3696 tcg_gen_shli_i32(tmp2, t1, 16);
3697 tcg_gen_or_i32(tmp, tmp, tmp2);
3698 tcg_gen_andi_i32(t1, t1, 0xffff0000);
3699 tcg_gen_shri_i32(tmp2, t0, 16);
3700 tcg_gen_or_i32(t1, t1, tmp2);
3701 tcg_gen_mov_i32(t0, tmp);
3703 dead_tmp(tmp2);
3704 dead_tmp(tmp);
3707 static void gen_neon_unzip(int reg, int q, int tmp, int size)
3709 int n;
3710 TCGv t0, t1;
3712 for (n = 0; n < q + 1; n += 2) {
3713 t0 = neon_load_reg(reg, n);
3714 t1 = neon_load_reg(reg, n + 1);
3715 switch (size) {
3716 case 0: gen_neon_unzip_u8(t0, t1); break;
3717 case 1: gen_neon_zip_u16(t0, t1); break; /* zip and unzip are the same. */
3718 case 2: /* no-op */; break;
3719 default: abort();
3721 neon_store_scratch(tmp + n, t0);
3722 neon_store_scratch(tmp + n + 1, t1);
3726 static void gen_neon_trn_u8(TCGv t0, TCGv t1)
3728 TCGv rd, tmp;
3730 rd = new_tmp();
3731 tmp = new_tmp();
3733 tcg_gen_shli_i32(rd, t0, 8);
3734 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3735 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3736 tcg_gen_or_i32(rd, rd, tmp);
3738 tcg_gen_shri_i32(t1, t1, 8);
3739 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3740 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3741 tcg_gen_or_i32(t1, t1, tmp);
3742 tcg_gen_mov_i32(t0, rd);
3744 dead_tmp(tmp);
3745 dead_tmp(rd);
3748 static void gen_neon_trn_u16(TCGv t0, TCGv t1)
3750 TCGv rd, tmp;
3752 rd = new_tmp();
3753 tmp = new_tmp();
3755 tcg_gen_shli_i32(rd, t0, 16);
3756 tcg_gen_andi_i32(tmp, t1, 0xffff);
3757 tcg_gen_or_i32(rd, rd, tmp);
3758 tcg_gen_shri_i32(t1, t1, 16);
3759 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3760 tcg_gen_or_i32(t1, t1, tmp);
3761 tcg_gen_mov_i32(t0, rd);
3763 dead_tmp(tmp);
3764 dead_tmp(rd);
3768 static struct {
3769 int nregs;
3770 int interleave;
3771 int spacing;
3772 } neon_ls_element_type[11] = {
3773 {4, 4, 1},
3774 {4, 4, 2},
3775 {4, 1, 1},
3776 {4, 2, 1},
3777 {3, 3, 1},
3778 {3, 3, 2},
3779 {3, 1, 1},
3780 {1, 1, 1},
3781 {2, 2, 1},
3782 {2, 2, 2},
3783 {2, 1, 1}
3786 /* Translate a NEON load/store element instruction. Return nonzero if the
3787 instruction is invalid. */
3788 static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3790 int rd, rn, rm;
3791 int op;
3792 int nregs;
3793 int interleave;
3794 int spacing;
3795 int stride;
3796 int size;
3797 int reg;
3798 int pass;
3799 int load;
3800 int shift;
3801 int n;
3802 TCGv addr;
3803 TCGv tmp;
3804 TCGv tmp2;
3805 TCGv_i64 tmp64;
3807 if (!vfp_enabled(env))
3808 return 1;
3809 VFP_DREG_D(rd, insn);
3810 rn = (insn >> 16) & 0xf;
3811 rm = insn & 0xf;
3812 load = (insn & (1 << 21)) != 0;
3813 addr = new_tmp();
3814 if ((insn & (1 << 23)) == 0) {
3815 /* Load store all elements. */
3816 op = (insn >> 8) & 0xf;
3817 size = (insn >> 6) & 3;
3818 if (op > 10)
3819 return 1;
3820 nregs = neon_ls_element_type[op].nregs;
3821 interleave = neon_ls_element_type[op].interleave;
3822 spacing = neon_ls_element_type[op].spacing;
3823 if (size == 3 && (interleave | spacing) != 1)
3824 return 1;
3825 load_reg_var(s, addr, rn);
3826 stride = (1 << size) * interleave;
3827 for (reg = 0; reg < nregs; reg++) {
3828 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3829 load_reg_var(s, addr, rn);
3830 tcg_gen_addi_i32(addr, addr, (1 << size) * reg);
3831 } else if (interleave == 2 && nregs == 4 && reg == 2) {
3832 load_reg_var(s, addr, rn);
3833 tcg_gen_addi_i32(addr, addr, 1 << size);
3835 if (size == 3) {
3836 if (load) {
3837 tmp64 = gen_ld64(addr, IS_USER(s));
3838 neon_store_reg64(tmp64, rd);
3839 tcg_temp_free_i64(tmp64);
3840 } else {
3841 tmp64 = tcg_temp_new_i64();
3842 neon_load_reg64(tmp64, rd);
3843 gen_st64(tmp64, addr, IS_USER(s));
3845 tcg_gen_addi_i32(addr, addr, stride);
3846 } else {
3847 for (pass = 0; pass < 2; pass++) {
3848 if (size == 2) {
3849 if (load) {
3850 tmp = gen_ld32(addr, IS_USER(s));
3851 neon_store_reg(rd, pass, tmp);
3852 } else {
3853 tmp = neon_load_reg(rd, pass);
3854 gen_st32(tmp, addr, IS_USER(s));
3856 tcg_gen_addi_i32(addr, addr, stride);
3857 } else if (size == 1) {
3858 if (load) {
3859 tmp = gen_ld16u(addr, IS_USER(s));
3860 tcg_gen_addi_i32(addr, addr, stride);
3861 tmp2 = gen_ld16u(addr, IS_USER(s));
3862 tcg_gen_addi_i32(addr, addr, stride);
3863 tcg_gen_shli_i32(tmp2, tmp2, 16);
3864 tcg_gen_or_i32(tmp, tmp, tmp2);
3865 dead_tmp(tmp2);
3866 neon_store_reg(rd, pass, tmp);
3867 } else {
3868 tmp = neon_load_reg(rd, pass);
3869 tmp2 = new_tmp();
3870 tcg_gen_shri_i32(tmp2, tmp, 16);
3871 gen_st16(tmp, addr, IS_USER(s));
3872 tcg_gen_addi_i32(addr, addr, stride);
3873 gen_st16(tmp2, addr, IS_USER(s));
3874 tcg_gen_addi_i32(addr, addr, stride);
3876 } else /* size == 0 */ {
3877 if (load) {
3878 TCGV_UNUSED(tmp2);
3879 for (n = 0; n < 4; n++) {
3880 tmp = gen_ld8u(addr, IS_USER(s));
3881 tcg_gen_addi_i32(addr, addr, stride);
3882 if (n == 0) {
3883 tmp2 = tmp;
3884 } else {
3885 tcg_gen_shli_i32(tmp, tmp, n * 8);
3886 tcg_gen_or_i32(tmp2, tmp2, tmp);
3887 dead_tmp(tmp);
3890 neon_store_reg(rd, pass, tmp2);
3891 } else {
3892 tmp2 = neon_load_reg(rd, pass);
3893 for (n = 0; n < 4; n++) {
3894 tmp = new_tmp();
3895 if (n == 0) {
3896 tcg_gen_mov_i32(tmp, tmp2);
3897 } else {
3898 tcg_gen_shri_i32(tmp, tmp2, n * 8);
3900 gen_st8(tmp, addr, IS_USER(s));
3901 tcg_gen_addi_i32(addr, addr, stride);
3903 dead_tmp(tmp2);
3908 rd += spacing;
3910 stride = nregs * 8;
3911 } else {
3912 size = (insn >> 10) & 3;
3913 if (size == 3) {
3914 /* Load single element to all lanes. */
3915 if (!load)
3916 return 1;
3917 size = (insn >> 6) & 3;
3918 nregs = ((insn >> 8) & 3) + 1;
3919 stride = (insn & (1 << 5)) ? 2 : 1;
3920 load_reg_var(s, addr, rn);
3921 for (reg = 0; reg < nregs; reg++) {
3922 switch (size) {
3923 case 0:
3924 tmp = gen_ld8u(addr, IS_USER(s));
3925 gen_neon_dup_u8(tmp, 0);
3926 break;
3927 case 1:
3928 tmp = gen_ld16u(addr, IS_USER(s));
3929 gen_neon_dup_low16(tmp);
3930 break;
3931 case 2:
3932 tmp = gen_ld32(addr, IS_USER(s));
3933 break;
3934 case 3:
3935 return 1;
3936 default: /* Avoid compiler warnings. */
3937 abort();
3939 tcg_gen_addi_i32(addr, addr, 1 << size);
3940 tmp2 = new_tmp();
3941 tcg_gen_mov_i32(tmp2, tmp);
3942 neon_store_reg(rd, 0, tmp2);
3943 neon_store_reg(rd, 1, tmp);
3944 rd += stride;
3946 stride = (1 << size) * nregs;
3947 } else {
3948 /* Single element. */
3949 pass = (insn >> 7) & 1;
3950 switch (size) {
3951 case 0:
3952 shift = ((insn >> 5) & 3) * 8;
3953 stride = 1;
3954 break;
3955 case 1:
3956 shift = ((insn >> 6) & 1) * 16;
3957 stride = (insn & (1 << 5)) ? 2 : 1;
3958 break;
3959 case 2:
3960 shift = 0;
3961 stride = (insn & (1 << 6)) ? 2 : 1;
3962 break;
3963 default:
3964 abort();
3966 nregs = ((insn >> 8) & 3) + 1;
3967 load_reg_var(s, addr, rn);
3968 for (reg = 0; reg < nregs; reg++) {
3969 if (load) {
3970 switch (size) {
3971 case 0:
3972 tmp = gen_ld8u(addr, IS_USER(s));
3973 break;
3974 case 1:
3975 tmp = gen_ld16u(addr, IS_USER(s));
3976 break;
3977 case 2:
3978 tmp = gen_ld32(addr, IS_USER(s));
3979 break;
3980 default: /* Avoid compiler warnings. */
3981 abort();
3983 if (size != 2) {
3984 tmp2 = neon_load_reg(rd, pass);
3985 gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
3986 dead_tmp(tmp2);
3988 neon_store_reg(rd, pass, tmp);
3989 } else { /* Store */
3990 tmp = neon_load_reg(rd, pass);
3991 if (shift)
3992 tcg_gen_shri_i32(tmp, tmp, shift);
3993 switch (size) {
3994 case 0:
3995 gen_st8(tmp, addr, IS_USER(s));
3996 break;
3997 case 1:
3998 gen_st16(tmp, addr, IS_USER(s));
3999 break;
4000 case 2:
4001 gen_st32(tmp, addr, IS_USER(s));
4002 break;
4005 rd += stride;
4006 tcg_gen_addi_i32(addr, addr, 1 << size);
4008 stride = nregs * (1 << size);
4011 dead_tmp(addr);
4012 if (rm != 15) {
4013 TCGv base;
4015 base = load_reg(s, rn);
4016 if (rm == 13) {
4017 tcg_gen_addi_i32(base, base, stride);
4018 } else {
4019 TCGv index;
4020 index = load_reg(s, rm);
4021 tcg_gen_add_i32(base, base, index);
4022 dead_tmp(index);
4024 store_reg(s, rn, base);
4026 return 0;
4029 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4030 static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
4032 tcg_gen_and_i32(t, t, c);
4033 tcg_gen_andc_i32(f, f, c);
4034 tcg_gen_or_i32(dest, t, f);
4037 static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
4039 switch (size) {
4040 case 0: gen_helper_neon_narrow_u8(dest, src); break;
4041 case 1: gen_helper_neon_narrow_u16(dest, src); break;
4042 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
4043 default: abort();
4047 static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
4049 switch (size) {
4050 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
4051 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
4052 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
4053 default: abort();
4057 static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
4059 switch (size) {
4060 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
4061 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
4062 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
4063 default: abort();
4067 static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
4068 int q, int u)
4070 if (q) {
4071 if (u) {
4072 switch (size) {
4073 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4074 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4075 default: abort();
4077 } else {
4078 switch (size) {
4079 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
4080 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
4081 default: abort();
4084 } else {
4085 if (u) {
4086 switch (size) {
4087 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4088 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4089 default: abort();
4091 } else {
4092 switch (size) {
4093 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
4094 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
4095 default: abort();
4101 static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
4103 if (u) {
4104 switch (size) {
4105 case 0: gen_helper_neon_widen_u8(dest, src); break;
4106 case 1: gen_helper_neon_widen_u16(dest, src); break;
4107 case 2: tcg_gen_extu_i32_i64(dest, src); break;
4108 default: abort();
4110 } else {
4111 switch (size) {
4112 case 0: gen_helper_neon_widen_s8(dest, src); break;
4113 case 1: gen_helper_neon_widen_s16(dest, src); break;
4114 case 2: tcg_gen_ext_i32_i64(dest, src); break;
4115 default: abort();
4118 dead_tmp(src);
4121 static inline void gen_neon_addl(int size)
4123 switch (size) {
4124 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4125 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4126 case 2: tcg_gen_add_i64(CPU_V001); break;
4127 default: abort();
4131 static inline void gen_neon_subl(int size)
4133 switch (size) {
4134 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4135 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4136 case 2: tcg_gen_sub_i64(CPU_V001); break;
4137 default: abort();
4141 static inline void gen_neon_negl(TCGv_i64 var, int size)
4143 switch (size) {
4144 case 0: gen_helper_neon_negl_u16(var, var); break;
4145 case 1: gen_helper_neon_negl_u32(var, var); break;
4146 case 2: gen_helper_neon_negl_u64(var, var); break;
4147 default: abort();
4151 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4153 switch (size) {
4154 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4155 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4156 default: abort();
4160 static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
4162 TCGv_i64 tmp;
4164 switch ((size << 1) | u) {
4165 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4166 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4167 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4168 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4169 case 4:
4170 tmp = gen_muls_i64_i32(a, b);
4171 tcg_gen_mov_i64(dest, tmp);
4172 break;
4173 case 5:
4174 tmp = gen_mulu_i64_i32(a, b);
4175 tcg_gen_mov_i64(dest, tmp);
4176 break;
4177 default: abort();
4181 /* Translate a NEON data processing instruction. Return nonzero if the
4182 instruction is invalid.
4183 We process data in a mixture of 32-bit and 64-bit chunks.
4184 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4186 static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4188 int op;
4189 int q;
4190 int rd, rn, rm;
4191 int size;
4192 int shift;
4193 int pass;
4194 int count;
4195 int pairwise;
4196 int u;
4197 int n;
4198 uint32_t imm, mask;
4199 TCGv tmp, tmp2, tmp3, tmp4, tmp5;
4200 TCGv_i64 tmp64;
4202 if (!vfp_enabled(env))
4203 return 1;
4204 q = (insn & (1 << 6)) != 0;
4205 u = (insn >> 24) & 1;
4206 VFP_DREG_D(rd, insn);
4207 VFP_DREG_N(rn, insn);
4208 VFP_DREG_M(rm, insn);
4209 size = (insn >> 20) & 3;
4210 if ((insn & (1 << 23)) == 0) {
4211 /* Three register same length. */
4212 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4213 if (size == 3 && (op == 1 || op == 5 || op == 8 || op == 9
4214 || op == 10 || op == 11 || op == 16)) {
4215 /* 64-bit element instructions. */
4216 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4217 neon_load_reg64(cpu_V0, rn + pass);
4218 neon_load_reg64(cpu_V1, rm + pass);
4219 switch (op) {
4220 case 1: /* VQADD */
4221 if (u) {
4222 gen_helper_neon_add_saturate_u64(CPU_V001);
4223 } else {
4224 gen_helper_neon_add_saturate_s64(CPU_V001);
4226 break;
4227 case 5: /* VQSUB */
4228 if (u) {
4229 gen_helper_neon_sub_saturate_u64(CPU_V001);
4230 } else {
4231 gen_helper_neon_sub_saturate_s64(CPU_V001);
4233 break;
4234 case 8: /* VSHL */
4235 if (u) {
4236 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4237 } else {
4238 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4240 break;
4241 case 9: /* VQSHL */
4242 if (u) {
4243 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4244 cpu_V1, cpu_V0);
4245 } else {
4246 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
4247 cpu_V1, cpu_V0);
4249 break;
4250 case 10: /* VRSHL */
4251 if (u) {
4252 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4253 } else {
4254 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4256 break;
4257 case 11: /* VQRSHL */
4258 if (u) {
4259 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4260 cpu_V1, cpu_V0);
4261 } else {
4262 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4263 cpu_V1, cpu_V0);
4265 break;
4266 case 16:
4267 if (u) {
4268 tcg_gen_sub_i64(CPU_V001);
4269 } else {
4270 tcg_gen_add_i64(CPU_V001);
4272 break;
4273 default:
4274 abort();
4276 neon_store_reg64(cpu_V0, rd + pass);
4278 return 0;
4280 switch (op) {
4281 case 8: /* VSHL */
4282 case 9: /* VQSHL */
4283 case 10: /* VRSHL */
4284 case 11: /* VQRSHL */
4286 int rtmp;
4287 /* Shift instruction operands are reversed. */
4288 rtmp = rn;
4289 rn = rm;
4290 rm = rtmp;
4291 pairwise = 0;
4293 break;
4294 case 20: /* VPMAX */
4295 case 21: /* VPMIN */
4296 case 23: /* VPADD */
4297 pairwise = 1;
4298 break;
4299 case 26: /* VPADD (float) */
4300 pairwise = (u && size < 2);
4301 break;
4302 case 30: /* VPMIN/VPMAX (float) */
4303 pairwise = u;
4304 break;
4305 default:
4306 pairwise = 0;
4307 break;
4310 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4312 if (pairwise) {
4313 /* Pairwise. */
4314 if (q)
4315 n = (pass & 1) * 2;
4316 else
4317 n = 0;
4318 if (pass < q + 1) {
4319 tmp = neon_load_reg(rn, n);
4320 tmp2 = neon_load_reg(rn, n + 1);
4321 } else {
4322 tmp = neon_load_reg(rm, n);
4323 tmp2 = neon_load_reg(rm, n + 1);
4325 } else {
4326 /* Elementwise. */
4327 tmp = neon_load_reg(rn, pass);
4328 tmp2 = neon_load_reg(rm, pass);
4330 switch (op) {
4331 case 0: /* VHADD */
4332 GEN_NEON_INTEGER_OP(hadd);
4333 break;
4334 case 1: /* VQADD */
4335 GEN_NEON_INTEGER_OP_ENV(qadd);
4336 break;
4337 case 2: /* VRHADD */
4338 GEN_NEON_INTEGER_OP(rhadd);
4339 break;
4340 case 3: /* Logic ops. */
4341 switch ((u << 2) | size) {
4342 case 0: /* VAND */
4343 tcg_gen_and_i32(tmp, tmp, tmp2);
4344 break;
4345 case 1: /* BIC */
4346 tcg_gen_andc_i32(tmp, tmp, tmp2);
4347 break;
4348 case 2: /* VORR */
4349 tcg_gen_or_i32(tmp, tmp, tmp2);
4350 break;
4351 case 3: /* VORN */
4352 tcg_gen_orc_i32(tmp, tmp, tmp2);
4353 break;
4354 case 4: /* VEOR */
4355 tcg_gen_xor_i32(tmp, tmp, tmp2);
4356 break;
4357 case 5: /* VBSL */
4358 tmp3 = neon_load_reg(rd, pass);
4359 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
4360 dead_tmp(tmp3);
4361 break;
4362 case 6: /* VBIT */
4363 tmp3 = neon_load_reg(rd, pass);
4364 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
4365 dead_tmp(tmp3);
4366 break;
4367 case 7: /* VBIF */
4368 tmp3 = neon_load_reg(rd, pass);
4369 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
4370 dead_tmp(tmp3);
4371 break;
4373 break;
4374 case 4: /* VHSUB */
4375 GEN_NEON_INTEGER_OP(hsub);
4376 break;
4377 case 5: /* VQSUB */
4378 GEN_NEON_INTEGER_OP_ENV(qsub);
4379 break;
4380 case 6: /* VCGT */
4381 GEN_NEON_INTEGER_OP(cgt);
4382 break;
4383 case 7: /* VCGE */
4384 GEN_NEON_INTEGER_OP(cge);
4385 break;
4386 case 8: /* VSHL */
4387 GEN_NEON_INTEGER_OP(shl);
4388 break;
4389 case 9: /* VQSHL */
4390 GEN_NEON_INTEGER_OP_ENV(qshl);
4391 break;
4392 case 10: /* VRSHL */
4393 GEN_NEON_INTEGER_OP(rshl);
4394 break;
4395 case 11: /* VQRSHL */
4396 GEN_NEON_INTEGER_OP_ENV(qrshl);
4397 break;
4398 case 12: /* VMAX */
4399 GEN_NEON_INTEGER_OP(max);
4400 break;
4401 case 13: /* VMIN */
4402 GEN_NEON_INTEGER_OP(min);
4403 break;
4404 case 14: /* VABD */
4405 GEN_NEON_INTEGER_OP(abd);
4406 break;
4407 case 15: /* VABA */
4408 GEN_NEON_INTEGER_OP(abd);
4409 dead_tmp(tmp2);
4410 tmp2 = neon_load_reg(rd, pass);
4411 gen_neon_add(size, tmp, tmp2);
4412 break;
4413 case 16:
4414 if (!u) { /* VADD */
4415 if (gen_neon_add(size, tmp, tmp2))
4416 return 1;
4417 } else { /* VSUB */
4418 switch (size) {
4419 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
4420 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
4421 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
4422 default: return 1;
4425 break;
4426 case 17:
4427 if (!u) { /* VTST */
4428 switch (size) {
4429 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
4430 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
4431 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
4432 default: return 1;
4434 } else { /* VCEQ */
4435 switch (size) {
4436 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
4437 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
4438 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
4439 default: return 1;
4442 break;
4443 case 18: /* Multiply. */
4444 switch (size) {
4445 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4446 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4447 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4448 default: return 1;
4450 dead_tmp(tmp2);
4451 tmp2 = neon_load_reg(rd, pass);
4452 if (u) { /* VMLS */
4453 gen_neon_rsb(size, tmp, tmp2);
4454 } else { /* VMLA */
4455 gen_neon_add(size, tmp, tmp2);
4457 break;
4458 case 19: /* VMUL */
4459 if (u) { /* polynomial */
4460 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
4461 } else { /* Integer */
4462 switch (size) {
4463 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4464 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4465 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4466 default: return 1;
4469 break;
4470 case 20: /* VPMAX */
4471 GEN_NEON_INTEGER_OP(pmax);
4472 break;
4473 case 21: /* VPMIN */
4474 GEN_NEON_INTEGER_OP(pmin);
4475 break;
4476 case 22: /* Hultiply high. */
4477 if (!u) { /* VQDMULH */
4478 switch (size) {
4479 case 1: gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4480 case 2: gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4481 default: return 1;
4483 } else { /* VQRDHMUL */
4484 switch (size) {
4485 case 1: gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4486 case 2: gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4487 default: return 1;
4490 break;
4491 case 23: /* VPADD */
4492 if (u)
4493 return 1;
4494 switch (size) {
4495 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
4496 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
4497 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
4498 default: return 1;
4500 break;
4501 case 26: /* Floating point arithnetic. */
4502 switch ((u << 2) | size) {
4503 case 0: /* VADD */
4504 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4505 break;
4506 case 2: /* VSUB */
4507 gen_helper_neon_sub_f32(tmp, tmp, tmp2);
4508 break;
4509 case 4: /* VPADD */
4510 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4511 break;
4512 case 6: /* VABD */
4513 gen_helper_neon_abd_f32(tmp, tmp, tmp2);
4514 break;
4515 default:
4516 return 1;
4518 break;
4519 case 27: /* Float multiply. */
4520 gen_helper_neon_mul_f32(tmp, tmp, tmp2);
4521 if (!u) {
4522 dead_tmp(tmp2);
4523 tmp2 = neon_load_reg(rd, pass);
4524 if (size == 0) {
4525 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4526 } else {
4527 gen_helper_neon_sub_f32(tmp, tmp2, tmp);
4530 break;
4531 case 28: /* Float compare. */
4532 if (!u) {
4533 gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
4534 } else {
4535 if (size == 0)
4536 gen_helper_neon_cge_f32(tmp, tmp, tmp2);
4537 else
4538 gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
4540 break;
4541 case 29: /* Float compare absolute. */
4542 if (!u)
4543 return 1;
4544 if (size == 0)
4545 gen_helper_neon_acge_f32(tmp, tmp, tmp2);
4546 else
4547 gen_helper_neon_acgt_f32(tmp, tmp, tmp2);
4548 break;
4549 case 30: /* Float min/max. */
4550 if (size == 0)
4551 gen_helper_neon_max_f32(tmp, tmp, tmp2);
4552 else
4553 gen_helper_neon_min_f32(tmp, tmp, tmp2);
4554 break;
4555 case 31:
4556 if (size == 0)
4557 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
4558 else
4559 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
4560 break;
4561 default:
4562 abort();
4564 dead_tmp(tmp2);
4566 /* Save the result. For elementwise operations we can put it
4567 straight into the destination register. For pairwise operations
4568 we have to be careful to avoid clobbering the source operands. */
4569 if (pairwise && rd == rm) {
4570 neon_store_scratch(pass, tmp);
4571 } else {
4572 neon_store_reg(rd, pass, tmp);
4575 } /* for pass */
4576 if (pairwise && rd == rm) {
4577 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4578 tmp = neon_load_scratch(pass);
4579 neon_store_reg(rd, pass, tmp);
4582 /* End of 3 register same size operations. */
4583 } else if (insn & (1 << 4)) {
4584 if ((insn & 0x00380080) != 0) {
4585 /* Two registers and shift. */
4586 op = (insn >> 8) & 0xf;
4587 if (insn & (1 << 7)) {
4588 /* 64-bit shift. */
4589 size = 3;
4590 } else {
4591 size = 2;
4592 while ((insn & (1 << (size + 19))) == 0)
4593 size--;
4595 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4596 /* To avoid excessive dumplication of ops we implement shift
4597 by immediate using the variable shift operations. */
4598 if (op < 8) {
4599 /* Shift by immediate:
4600 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4601 /* Right shifts are encoded as N - shift, where N is the
4602 element size in bits. */
4603 if (op <= 4)
4604 shift = shift - (1 << (size + 3));
4605 if (size == 3) {
4606 count = q + 1;
4607 } else {
4608 count = q ? 4: 2;
4610 switch (size) {
4611 case 0:
4612 imm = (uint8_t) shift;
4613 imm |= imm << 8;
4614 imm |= imm << 16;
4615 break;
4616 case 1:
4617 imm = (uint16_t) shift;
4618 imm |= imm << 16;
4619 break;
4620 case 2:
4621 case 3:
4622 imm = shift;
4623 break;
4624 default:
4625 abort();
4628 for (pass = 0; pass < count; pass++) {
4629 if (size == 3) {
4630 neon_load_reg64(cpu_V0, rm + pass);
4631 tcg_gen_movi_i64(cpu_V1, imm);
4632 switch (op) {
4633 case 0: /* VSHR */
4634 case 1: /* VSRA */
4635 if (u)
4636 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4637 else
4638 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
4639 break;
4640 case 2: /* VRSHR */
4641 case 3: /* VRSRA */
4642 if (u)
4643 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
4644 else
4645 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
4646 break;
4647 case 4: /* VSRI */
4648 if (!u)
4649 return 1;
4650 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4651 break;
4652 case 5: /* VSHL, VSLI */
4653 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4654 break;
4655 case 6: /* VQSHLU */
4656 if (u) {
4657 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
4658 cpu_V0, cpu_V1);
4659 } else {
4660 return 1;
4662 break;
4663 case 7: /* VQSHL */
4664 if (u) {
4665 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4666 cpu_V0, cpu_V1);
4667 } else {
4668 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
4669 cpu_V0, cpu_V1);
4671 break;
4673 if (op == 1 || op == 3) {
4674 /* Accumulate. */
4675 neon_load_reg64(cpu_V0, rd + pass);
4676 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
4677 } else if (op == 4 || (op == 5 && u)) {
4678 /* Insert */
4679 cpu_abort(env, "VS[LR]I.64 not implemented");
4681 neon_store_reg64(cpu_V0, rd + pass);
4682 } else { /* size < 3 */
4683 /* Operands in T0 and T1. */
4684 tmp = neon_load_reg(rm, pass);
4685 tmp2 = new_tmp();
4686 tcg_gen_movi_i32(tmp2, imm);
4687 switch (op) {
4688 case 0: /* VSHR */
4689 case 1: /* VSRA */
4690 GEN_NEON_INTEGER_OP(shl);
4691 break;
4692 case 2: /* VRSHR */
4693 case 3: /* VRSRA */
4694 GEN_NEON_INTEGER_OP(rshl);
4695 break;
4696 case 4: /* VSRI */
4697 if (!u)
4698 return 1;
4699 GEN_NEON_INTEGER_OP(shl);
4700 break;
4701 case 5: /* VSHL, VSLI */
4702 switch (size) {
4703 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
4704 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
4705 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
4706 default: return 1;
4708 break;
4709 case 6: /* VQSHLU */
4710 if (!u) {
4711 return 1;
4713 switch (size) {
4714 case 0:
4715 gen_helper_neon_qshlu_s8(tmp, cpu_env,
4716 tmp, tmp2);
4717 break;
4718 case 1:
4719 gen_helper_neon_qshlu_s16(tmp, cpu_env,
4720 tmp, tmp2);
4721 break;
4722 case 2:
4723 gen_helper_neon_qshlu_s32(tmp, cpu_env,
4724 tmp, tmp2);
4725 break;
4726 default:
4727 return 1;
4729 break;
4730 case 7: /* VQSHL */
4731 GEN_NEON_INTEGER_OP_ENV(qshl);
4732 break;
4734 dead_tmp(tmp2);
4736 if (op == 1 || op == 3) {
4737 /* Accumulate. */
4738 tmp2 = neon_load_reg(rd, pass);
4739 gen_neon_add(size, tmp2, tmp);
4740 dead_tmp(tmp2);
4741 } else if (op == 4 || (op == 5 && u)) {
4742 /* Insert */
4743 switch (size) {
4744 case 0:
4745 if (op == 4)
4746 mask = 0xff >> -shift;
4747 else
4748 mask = (uint8_t)(0xff << shift);
4749 mask |= mask << 8;
4750 mask |= mask << 16;
4751 break;
4752 case 1:
4753 if (op == 4)
4754 mask = 0xffff >> -shift;
4755 else
4756 mask = (uint16_t)(0xffff << shift);
4757 mask |= mask << 16;
4758 break;
4759 case 2:
4760 if (shift < -31 || shift > 31) {
4761 mask = 0;
4762 } else {
4763 if (op == 4)
4764 mask = 0xffffffffu >> -shift;
4765 else
4766 mask = 0xffffffffu << shift;
4768 break;
4769 default:
4770 abort();
4772 tmp2 = neon_load_reg(rd, pass);
4773 tcg_gen_andi_i32(tmp, tmp, mask);
4774 tcg_gen_andi_i32(tmp2, tmp2, ~mask);
4775 tcg_gen_or_i32(tmp, tmp, tmp2);
4776 dead_tmp(tmp2);
4778 neon_store_reg(rd, pass, tmp);
4780 } /* for pass */
4781 } else if (op < 10) {
4782 /* Shift by immediate and narrow:
4783 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4784 shift = shift - (1 << (size + 3));
4785 size++;
4786 switch (size) {
4787 case 1:
4788 imm = (uint16_t)shift;
4789 imm |= imm << 16;
4790 tmp2 = tcg_const_i32(imm);
4791 TCGV_UNUSED_I64(tmp64);
4792 break;
4793 case 2:
4794 imm = (uint32_t)shift;
4795 tmp2 = tcg_const_i32(imm);
4796 TCGV_UNUSED_I64(tmp64);
4797 break;
4798 case 3:
4799 tmp64 = tcg_const_i64(shift);
4800 TCGV_UNUSED(tmp2);
4801 break;
4802 default:
4803 abort();
4806 for (pass = 0; pass < 2; pass++) {
4807 if (size == 3) {
4808 neon_load_reg64(cpu_V0, rm + pass);
4809 if (q) {
4810 if (u)
4811 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, tmp64);
4812 else
4813 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, tmp64);
4814 } else {
4815 if (u)
4816 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, tmp64);
4817 else
4818 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, tmp64);
4820 } else {
4821 tmp = neon_load_reg(rm + pass, 0);
4822 gen_neon_shift_narrow(size, tmp, tmp2, q, u);
4823 tmp3 = neon_load_reg(rm + pass, 1);
4824 gen_neon_shift_narrow(size, tmp3, tmp2, q, u);
4825 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
4826 dead_tmp(tmp);
4827 dead_tmp(tmp3);
4829 tmp = new_tmp();
4830 if (op == 8 && !u) {
4831 gen_neon_narrow(size - 1, tmp, cpu_V0);
4832 } else {
4833 if (op == 8)
4834 gen_neon_narrow_sats(size - 1, tmp, cpu_V0);
4835 else
4836 gen_neon_narrow_satu(size - 1, tmp, cpu_V0);
4838 neon_store_reg(rd, pass, tmp);
4839 } /* for pass */
4840 if (size == 3) {
4841 tcg_temp_free_i64(tmp64);
4842 } else {
4843 dead_tmp(tmp2);
4845 } else if (op == 10) {
4846 /* VSHLL */
4847 if (q || size == 3)
4848 return 1;
4849 tmp = neon_load_reg(rm, 0);
4850 tmp2 = neon_load_reg(rm, 1);
4851 for (pass = 0; pass < 2; pass++) {
4852 if (pass == 1)
4853 tmp = tmp2;
4855 gen_neon_widen(cpu_V0, tmp, size, u);
4857 if (shift != 0) {
4858 /* The shift is less than the width of the source
4859 type, so we can just shift the whole register. */
4860 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
4861 if (size < 2 || !u) {
4862 uint64_t imm64;
4863 if (size == 0) {
4864 imm = (0xffu >> (8 - shift));
4865 imm |= imm << 16;
4866 } else {
4867 imm = 0xffff >> (16 - shift);
4869 imm64 = imm | (((uint64_t)imm) << 32);
4870 tcg_gen_andi_i64(cpu_V0, cpu_V0, imm64);
4873 neon_store_reg64(cpu_V0, rd + pass);
4875 } else if (op >= 14) {
4876 /* VCVT fixed-point. */
4877 /* We have already masked out the must-be-1 top bit of imm6,
4878 * hence this 32-shift where the ARM ARM has 64-imm6.
4880 shift = 32 - shift;
4881 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4882 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
4883 if (!(op & 1)) {
4884 if (u)
4885 gen_vfp_ulto(0, shift);
4886 else
4887 gen_vfp_slto(0, shift);
4888 } else {
4889 if (u)
4890 gen_vfp_toul(0, shift);
4891 else
4892 gen_vfp_tosl(0, shift);
4894 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
4896 } else {
4897 return 1;
4899 } else { /* (insn & 0x00380080) == 0 */
4900 int invert;
4902 op = (insn >> 8) & 0xf;
4903 /* One register and immediate. */
4904 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4905 invert = (insn & (1 << 5)) != 0;
4906 switch (op) {
4907 case 0: case 1:
4908 /* no-op */
4909 break;
4910 case 2: case 3:
4911 imm <<= 8;
4912 break;
4913 case 4: case 5:
4914 imm <<= 16;
4915 break;
4916 case 6: case 7:
4917 imm <<= 24;
4918 break;
4919 case 8: case 9:
4920 imm |= imm << 16;
4921 break;
4922 case 10: case 11:
4923 imm = (imm << 8) | (imm << 24);
4924 break;
4925 case 12:
4926 imm = (imm << 8) | 0xff;
4927 break;
4928 case 13:
4929 imm = (imm << 16) | 0xffff;
4930 break;
4931 case 14:
4932 imm |= (imm << 8) | (imm << 16) | (imm << 24);
4933 if (invert)
4934 imm = ~imm;
4935 break;
4936 case 15:
4937 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
4938 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
4939 break;
4941 if (invert)
4942 imm = ~imm;
4944 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4945 if (op & 1 && op < 12) {
4946 tmp = neon_load_reg(rd, pass);
4947 if (invert) {
4948 /* The immediate value has already been inverted, so
4949 BIC becomes AND. */
4950 tcg_gen_andi_i32(tmp, tmp, imm);
4951 } else {
4952 tcg_gen_ori_i32(tmp, tmp, imm);
4954 } else {
4955 /* VMOV, VMVN. */
4956 tmp = new_tmp();
4957 if (op == 14 && invert) {
4958 uint32_t val;
4959 val = 0;
4960 for (n = 0; n < 4; n++) {
4961 if (imm & (1 << (n + (pass & 1) * 4)))
4962 val |= 0xff << (n * 8);
4964 tcg_gen_movi_i32(tmp, val);
4965 } else {
4966 tcg_gen_movi_i32(tmp, imm);
4969 neon_store_reg(rd, pass, tmp);
4972 } else { /* (insn & 0x00800010 == 0x00800000) */
4973 if (size != 3) {
4974 op = (insn >> 8) & 0xf;
4975 if ((insn & (1 << 6)) == 0) {
4976 /* Three registers of different lengths. */
4977 int src1_wide;
4978 int src2_wide;
4979 int prewiden;
4980 /* prewiden, src1_wide, src2_wide */
4981 static const int neon_3reg_wide[16][3] = {
4982 {1, 0, 0}, /* VADDL */
4983 {1, 1, 0}, /* VADDW */
4984 {1, 0, 0}, /* VSUBL */
4985 {1, 1, 0}, /* VSUBW */
4986 {0, 1, 1}, /* VADDHN */
4987 {0, 0, 0}, /* VABAL */
4988 {0, 1, 1}, /* VSUBHN */
4989 {0, 0, 0}, /* VABDL */
4990 {0, 0, 0}, /* VMLAL */
4991 {0, 0, 0}, /* VQDMLAL */
4992 {0, 0, 0}, /* VMLSL */
4993 {0, 0, 0}, /* VQDMLSL */
4994 {0, 0, 0}, /* Integer VMULL */
4995 {0, 0, 0}, /* VQDMULL */
4996 {0, 0, 0} /* Polynomial VMULL */
4999 prewiden = neon_3reg_wide[op][0];
5000 src1_wide = neon_3reg_wide[op][1];
5001 src2_wide = neon_3reg_wide[op][2];
5003 if (size == 0 && (op == 9 || op == 11 || op == 13))
5004 return 1;
5006 /* Avoid overlapping operands. Wide source operands are
5007 always aligned so will never overlap with wide
5008 destinations in problematic ways. */
5009 if (rd == rm && !src2_wide) {
5010 tmp = neon_load_reg(rm, 1);
5011 neon_store_scratch(2, tmp);
5012 } else if (rd == rn && !src1_wide) {
5013 tmp = neon_load_reg(rn, 1);
5014 neon_store_scratch(2, tmp);
5016 TCGV_UNUSED(tmp3);
5017 for (pass = 0; pass < 2; pass++) {
5018 if (src1_wide) {
5019 neon_load_reg64(cpu_V0, rn + pass);
5020 TCGV_UNUSED(tmp);
5021 } else {
5022 if (pass == 1 && rd == rn) {
5023 tmp = neon_load_scratch(2);
5024 } else {
5025 tmp = neon_load_reg(rn, pass);
5027 if (prewiden) {
5028 gen_neon_widen(cpu_V0, tmp, size, u);
5031 if (src2_wide) {
5032 neon_load_reg64(cpu_V1, rm + pass);
5033 TCGV_UNUSED(tmp2);
5034 } else {
5035 if (pass == 1 && rd == rm) {
5036 tmp2 = neon_load_scratch(2);
5037 } else {
5038 tmp2 = neon_load_reg(rm, pass);
5040 if (prewiden) {
5041 gen_neon_widen(cpu_V1, tmp2, size, u);
5044 switch (op) {
5045 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5046 gen_neon_addl(size);
5047 break;
5048 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
5049 gen_neon_subl(size);
5050 break;
5051 case 5: case 7: /* VABAL, VABDL */
5052 switch ((size << 1) | u) {
5053 case 0:
5054 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
5055 break;
5056 case 1:
5057 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
5058 break;
5059 case 2:
5060 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
5061 break;
5062 case 3:
5063 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
5064 break;
5065 case 4:
5066 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
5067 break;
5068 case 5:
5069 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
5070 break;
5071 default: abort();
5073 dead_tmp(tmp2);
5074 dead_tmp(tmp);
5075 break;
5076 case 8: case 9: case 10: case 11: case 12: case 13:
5077 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5078 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5079 dead_tmp(tmp2);
5080 dead_tmp(tmp);
5081 break;
5082 case 14: /* Polynomial VMULL */
5083 cpu_abort(env, "Polynomial VMULL not implemented");
5085 default: /* 15 is RESERVED. */
5086 return 1;
5088 if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
5089 /* Accumulate. */
5090 if (op == 10 || op == 11) {
5091 gen_neon_negl(cpu_V0, size);
5094 if (op != 13) {
5095 neon_load_reg64(cpu_V1, rd + pass);
5098 switch (op) {
5099 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
5100 gen_neon_addl(size);
5101 break;
5102 case 9: case 11: /* VQDMLAL, VQDMLSL */
5103 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5104 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5105 break;
5106 /* Fall through. */
5107 case 13: /* VQDMULL */
5108 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5109 break;
5110 default:
5111 abort();
5113 neon_store_reg64(cpu_V0, rd + pass);
5114 } else if (op == 4 || op == 6) {
5115 /* Narrowing operation. */
5116 tmp = new_tmp();
5117 if (!u) {
5118 switch (size) {
5119 case 0:
5120 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
5121 break;
5122 case 1:
5123 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
5124 break;
5125 case 2:
5126 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5127 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5128 break;
5129 default: abort();
5131 } else {
5132 switch (size) {
5133 case 0:
5134 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
5135 break;
5136 case 1:
5137 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
5138 break;
5139 case 2:
5140 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
5141 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5142 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5143 break;
5144 default: abort();
5147 if (pass == 0) {
5148 tmp3 = tmp;
5149 } else {
5150 neon_store_reg(rd, 0, tmp3);
5151 neon_store_reg(rd, 1, tmp);
5153 } else {
5154 /* Write back the result. */
5155 neon_store_reg64(cpu_V0, rd + pass);
5158 } else {
5159 /* Two registers and a scalar. */
5160 switch (op) {
5161 case 0: /* Integer VMLA scalar */
5162 case 1: /* Float VMLA scalar */
5163 case 4: /* Integer VMLS scalar */
5164 case 5: /* Floating point VMLS scalar */
5165 case 8: /* Integer VMUL scalar */
5166 case 9: /* Floating point VMUL scalar */
5167 case 12: /* VQDMULH scalar */
5168 case 13: /* VQRDMULH scalar */
5169 tmp = neon_get_scalar(size, rm);
5170 neon_store_scratch(0, tmp);
5171 for (pass = 0; pass < (u ? 4 : 2); pass++) {
5172 tmp = neon_load_scratch(0);
5173 tmp2 = neon_load_reg(rn, pass);
5174 if (op == 12) {
5175 if (size == 1) {
5176 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5177 } else {
5178 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5180 } else if (op == 13) {
5181 if (size == 1) {
5182 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5183 } else {
5184 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5186 } else if (op & 1) {
5187 gen_helper_neon_mul_f32(tmp, tmp, tmp2);
5188 } else {
5189 switch (size) {
5190 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5191 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5192 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5193 default: return 1;
5196 dead_tmp(tmp2);
5197 if (op < 8) {
5198 /* Accumulate. */
5199 tmp2 = neon_load_reg(rd, pass);
5200 switch (op) {
5201 case 0:
5202 gen_neon_add(size, tmp, tmp2);
5203 break;
5204 case 1:
5205 gen_helper_neon_add_f32(tmp, tmp, tmp2);
5206 break;
5207 case 4:
5208 gen_neon_rsb(size, tmp, tmp2);
5209 break;
5210 case 5:
5211 gen_helper_neon_sub_f32(tmp, tmp2, tmp);
5212 break;
5213 default:
5214 abort();
5216 dead_tmp(tmp2);
5218 neon_store_reg(rd, pass, tmp);
5220 break;
5221 case 2: /* VMLAL sclar */
5222 case 3: /* VQDMLAL scalar */
5223 case 6: /* VMLSL scalar */
5224 case 7: /* VQDMLSL scalar */
5225 case 10: /* VMULL scalar */
5226 case 11: /* VQDMULL scalar */
5227 if (size == 0 && (op == 3 || op == 7 || op == 11))
5228 return 1;
5230 tmp2 = neon_get_scalar(size, rm);
5231 tmp3 = neon_load_reg(rn, 1);
5233 for (pass = 0; pass < 2; pass++) {
5234 if (pass == 0) {
5235 tmp = neon_load_reg(rn, 0);
5236 } else {
5237 tmp = tmp3;
5239 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5240 dead_tmp(tmp);
5241 if (op == 6 || op == 7) {
5242 gen_neon_negl(cpu_V0, size);
5244 if (op != 11) {
5245 neon_load_reg64(cpu_V1, rd + pass);
5247 switch (op) {
5248 case 2: case 6:
5249 gen_neon_addl(size);
5250 break;
5251 case 3: case 7:
5252 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5253 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5254 break;
5255 case 10:
5256 /* no-op */
5257 break;
5258 case 11:
5259 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5260 break;
5261 default:
5262 abort();
5264 neon_store_reg64(cpu_V0, rd + pass);
5267 dead_tmp(tmp2);
5269 break;
5270 default: /* 14 and 15 are RESERVED */
5271 return 1;
5274 } else { /* size == 3 */
5275 if (!u) {
5276 /* Extract. */
5277 imm = (insn >> 8) & 0xf;
5279 if (imm > 7 && !q)
5280 return 1;
5282 if (imm == 0) {
5283 neon_load_reg64(cpu_V0, rn);
5284 if (q) {
5285 neon_load_reg64(cpu_V1, rn + 1);
5287 } else if (imm == 8) {
5288 neon_load_reg64(cpu_V0, rn + 1);
5289 if (q) {
5290 neon_load_reg64(cpu_V1, rm);
5292 } else if (q) {
5293 tmp64 = tcg_temp_new_i64();
5294 if (imm < 8) {
5295 neon_load_reg64(cpu_V0, rn);
5296 neon_load_reg64(tmp64, rn + 1);
5297 } else {
5298 neon_load_reg64(cpu_V0, rn + 1);
5299 neon_load_reg64(tmp64, rm);
5301 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5302 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
5303 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5304 if (imm < 8) {
5305 neon_load_reg64(cpu_V1, rm);
5306 } else {
5307 neon_load_reg64(cpu_V1, rm + 1);
5308 imm -= 8;
5310 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5311 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
5312 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
5313 tcg_temp_free_i64(tmp64);
5314 } else {
5315 /* BUGFIX */
5316 neon_load_reg64(cpu_V0, rn);
5317 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
5318 neon_load_reg64(cpu_V1, rm);
5319 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5320 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5322 neon_store_reg64(cpu_V0, rd);
5323 if (q) {
5324 neon_store_reg64(cpu_V1, rd + 1);
5326 } else if ((insn & (1 << 11)) == 0) {
5327 /* Two register misc. */
5328 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5329 size = (insn >> 18) & 3;
5330 switch (op) {
5331 case 0: /* VREV64 */
5332 if (size == 3)
5333 return 1;
5334 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5335 tmp = neon_load_reg(rm, pass * 2);
5336 tmp2 = neon_load_reg(rm, pass * 2 + 1);
5337 switch (size) {
5338 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5339 case 1: gen_swap_half(tmp); break;
5340 case 2: /* no-op */ break;
5341 default: abort();
5343 neon_store_reg(rd, pass * 2 + 1, tmp);
5344 if (size == 2) {
5345 neon_store_reg(rd, pass * 2, tmp2);
5346 } else {
5347 switch (size) {
5348 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
5349 case 1: gen_swap_half(tmp2); break;
5350 default: abort();
5352 neon_store_reg(rd, pass * 2, tmp2);
5355 break;
5356 case 4: case 5: /* VPADDL */
5357 case 12: case 13: /* VPADAL */
5358 if (size == 3)
5359 return 1;
5360 for (pass = 0; pass < q + 1; pass++) {
5361 tmp = neon_load_reg(rm, pass * 2);
5362 gen_neon_widen(cpu_V0, tmp, size, op & 1);
5363 tmp = neon_load_reg(rm, pass * 2 + 1);
5364 gen_neon_widen(cpu_V1, tmp, size, op & 1);
5365 switch (size) {
5366 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5367 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5368 case 2: tcg_gen_add_i64(CPU_V001); break;
5369 default: abort();
5371 if (op >= 12) {
5372 /* Accumulate. */
5373 neon_load_reg64(cpu_V1, rd + pass);
5374 gen_neon_addl(size);
5376 neon_store_reg64(cpu_V0, rd + pass);
5378 break;
5379 case 33: /* VTRN */
5380 if (size == 2) {
5381 for (n = 0; n < (q ? 4 : 2); n += 2) {
5382 tmp = neon_load_reg(rm, n);
5383 tmp2 = neon_load_reg(rd, n + 1);
5384 neon_store_reg(rm, n, tmp2);
5385 neon_store_reg(rd, n + 1, tmp);
5387 } else {
5388 goto elementwise;
5390 break;
5391 case 34: /* VUZP */
5392 /* Reg Before After
5393 Rd A3 A2 A1 A0 B2 B0 A2 A0
5394 Rm B3 B2 B1 B0 B3 B1 A3 A1
5396 if (size == 3)
5397 return 1;
5398 gen_neon_unzip(rd, q, 0, size);
5399 gen_neon_unzip(rm, q, 4, size);
5400 if (q) {
5401 static int unzip_order_q[8] =
5402 {0, 2, 4, 6, 1, 3, 5, 7};
5403 for (n = 0; n < 8; n++) {
5404 int reg = (n < 4) ? rd : rm;
5405 tmp = neon_load_scratch(unzip_order_q[n]);
5406 neon_store_reg(reg, n % 4, tmp);
5408 } else {
5409 static int unzip_order[4] =
5410 {0, 4, 1, 5};
5411 for (n = 0; n < 4; n++) {
5412 int reg = (n < 2) ? rd : rm;
5413 tmp = neon_load_scratch(unzip_order[n]);
5414 neon_store_reg(reg, n % 2, tmp);
5417 break;
5418 case 35: /* VZIP */
5419 /* Reg Before After
5420 Rd A3 A2 A1 A0 B1 A1 B0 A0
5421 Rm B3 B2 B1 B0 B3 A3 B2 A2
5423 if (size == 3)
5424 return 1;
5425 count = (q ? 4 : 2);
5426 for (n = 0; n < count; n++) {
5427 tmp = neon_load_reg(rd, n);
5428 tmp2 = neon_load_reg(rd, n);
5429 switch (size) {
5430 case 0: gen_neon_zip_u8(tmp, tmp2); break;
5431 case 1: gen_neon_zip_u16(tmp, tmp2); break;
5432 case 2: /* no-op */; break;
5433 default: abort();
5435 neon_store_scratch(n * 2, tmp);
5436 neon_store_scratch(n * 2 + 1, tmp2);
5438 for (n = 0; n < count * 2; n++) {
5439 int reg = (n < count) ? rd : rm;
5440 tmp = neon_load_scratch(n);
5441 neon_store_reg(reg, n % count, tmp);
5443 break;
5444 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5445 if (size == 3)
5446 return 1;
5447 TCGV_UNUSED(tmp2);
5448 for (pass = 0; pass < 2; pass++) {
5449 neon_load_reg64(cpu_V0, rm + pass);
5450 tmp = new_tmp();
5451 if (op == 36 && q == 0) {
5452 gen_neon_narrow(size, tmp, cpu_V0);
5453 } else if (q) {
5454 gen_neon_narrow_satu(size, tmp, cpu_V0);
5455 } else {
5456 gen_neon_narrow_sats(size, tmp, cpu_V0);
5458 if (pass == 0) {
5459 tmp2 = tmp;
5460 } else {
5461 neon_store_reg(rd, 0, tmp2);
5462 neon_store_reg(rd, 1, tmp);
5465 break;
5466 case 38: /* VSHLL */
5467 if (q || size == 3)
5468 return 1;
5469 tmp = neon_load_reg(rm, 0);
5470 tmp2 = neon_load_reg(rm, 1);
5471 for (pass = 0; pass < 2; pass++) {
5472 if (pass == 1)
5473 tmp = tmp2;
5474 gen_neon_widen(cpu_V0, tmp, size, 1);
5475 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
5476 neon_store_reg64(cpu_V0, rd + pass);
5478 break;
5479 case 44: /* VCVT.F16.F32 */
5480 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
5481 return 1;
5482 tmp = new_tmp();
5483 tmp2 = new_tmp();
5484 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
5485 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5486 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
5487 gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
5488 tcg_gen_shli_i32(tmp2, tmp2, 16);
5489 tcg_gen_or_i32(tmp2, tmp2, tmp);
5490 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
5491 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5492 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
5493 neon_store_reg(rd, 0, tmp2);
5494 tmp2 = new_tmp();
5495 gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
5496 tcg_gen_shli_i32(tmp2, tmp2, 16);
5497 tcg_gen_or_i32(tmp2, tmp2, tmp);
5498 neon_store_reg(rd, 1, tmp2);
5499 dead_tmp(tmp);
5500 break;
5501 case 46: /* VCVT.F32.F16 */
5502 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
5503 return 1;
5504 tmp3 = new_tmp();
5505 tmp = neon_load_reg(rm, 0);
5506 tmp2 = neon_load_reg(rm, 1);
5507 tcg_gen_ext16u_i32(tmp3, tmp);
5508 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5509 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
5510 tcg_gen_shri_i32(tmp3, tmp, 16);
5511 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5512 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
5513 dead_tmp(tmp);
5514 tcg_gen_ext16u_i32(tmp3, tmp2);
5515 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5516 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
5517 tcg_gen_shri_i32(tmp3, tmp2, 16);
5518 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5519 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
5520 dead_tmp(tmp2);
5521 dead_tmp(tmp3);
5522 break;
5523 default:
5524 elementwise:
5525 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5526 if (op == 30 || op == 31 || op >= 58) {
5527 tcg_gen_ld_f32(cpu_F0s, cpu_env,
5528 neon_reg_offset(rm, pass));
5529 TCGV_UNUSED(tmp);
5530 } else {
5531 tmp = neon_load_reg(rm, pass);
5533 switch (op) {
5534 case 1: /* VREV32 */
5535 switch (size) {
5536 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5537 case 1: gen_swap_half(tmp); break;
5538 default: return 1;
5540 break;
5541 case 2: /* VREV16 */
5542 if (size != 0)
5543 return 1;
5544 gen_rev16(tmp);
5545 break;
5546 case 8: /* CLS */
5547 switch (size) {
5548 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
5549 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
5550 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
5551 default: return 1;
5553 break;
5554 case 9: /* CLZ */
5555 switch (size) {
5556 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
5557 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
5558 case 2: gen_helper_clz(tmp, tmp); break;
5559 default: return 1;
5561 break;
5562 case 10: /* CNT */
5563 if (size != 0)
5564 return 1;
5565 gen_helper_neon_cnt_u8(tmp, tmp);
5566 break;
5567 case 11: /* VNOT */
5568 if (size != 0)
5569 return 1;
5570 tcg_gen_not_i32(tmp, tmp);
5571 break;
5572 case 14: /* VQABS */
5573 switch (size) {
5574 case 0: gen_helper_neon_qabs_s8(tmp, cpu_env, tmp); break;
5575 case 1: gen_helper_neon_qabs_s16(tmp, cpu_env, tmp); break;
5576 case 2: gen_helper_neon_qabs_s32(tmp, cpu_env, tmp); break;
5577 default: return 1;
5579 break;
5580 case 15: /* VQNEG */
5581 switch (size) {
5582 case 0: gen_helper_neon_qneg_s8(tmp, cpu_env, tmp); break;
5583 case 1: gen_helper_neon_qneg_s16(tmp, cpu_env, tmp); break;
5584 case 2: gen_helper_neon_qneg_s32(tmp, cpu_env, tmp); break;
5585 default: return 1;
5587 break;
5588 case 16: case 19: /* VCGT #0, VCLE #0 */
5589 tmp2 = tcg_const_i32(0);
5590 switch(size) {
5591 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
5592 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
5593 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
5594 default: return 1;
5596 tcg_temp_free(tmp2);
5597 if (op == 19)
5598 tcg_gen_not_i32(tmp, tmp);
5599 break;
5600 case 17: case 20: /* VCGE #0, VCLT #0 */
5601 tmp2 = tcg_const_i32(0);
5602 switch(size) {
5603 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
5604 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
5605 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
5606 default: return 1;
5608 tcg_temp_free(tmp2);
5609 if (op == 20)
5610 tcg_gen_not_i32(tmp, tmp);
5611 break;
5612 case 18: /* VCEQ #0 */
5613 tmp2 = tcg_const_i32(0);
5614 switch(size) {
5615 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
5616 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
5617 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
5618 default: return 1;
5620 tcg_temp_free(tmp2);
5621 break;
5622 case 22: /* VABS */
5623 switch(size) {
5624 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
5625 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
5626 case 2: tcg_gen_abs_i32(tmp, tmp); break;
5627 default: return 1;
5629 break;
5630 case 23: /* VNEG */
5631 if (size == 3)
5632 return 1;
5633 tmp2 = tcg_const_i32(0);
5634 gen_neon_rsb(size, tmp, tmp2);
5635 tcg_temp_free(tmp2);
5636 break;
5637 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5638 tmp2 = tcg_const_i32(0);
5639 gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
5640 tcg_temp_free(tmp2);
5641 if (op == 27)
5642 tcg_gen_not_i32(tmp, tmp);
5643 break;
5644 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5645 tmp2 = tcg_const_i32(0);
5646 gen_helper_neon_cge_f32(tmp, tmp, tmp2);
5647 tcg_temp_free(tmp2);
5648 if (op == 28)
5649 tcg_gen_not_i32(tmp, tmp);
5650 break;
5651 case 26: /* Float VCEQ #0 */
5652 tmp2 = tcg_const_i32(0);
5653 gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
5654 tcg_temp_free(tmp2);
5655 break;
5656 case 30: /* Float VABS */
5657 gen_vfp_abs(0);
5658 break;
5659 case 31: /* Float VNEG */
5660 gen_vfp_neg(0);
5661 break;
5662 case 32: /* VSWP */
5663 tmp2 = neon_load_reg(rd, pass);
5664 neon_store_reg(rm, pass, tmp2);
5665 break;
5666 case 33: /* VTRN */
5667 tmp2 = neon_load_reg(rd, pass);
5668 switch (size) {
5669 case 0: gen_neon_trn_u8(tmp, tmp2); break;
5670 case 1: gen_neon_trn_u16(tmp, tmp2); break;
5671 case 2: abort();
5672 default: return 1;
5674 neon_store_reg(rm, pass, tmp2);
5675 break;
5676 case 56: /* Integer VRECPE */
5677 gen_helper_recpe_u32(tmp, tmp, cpu_env);
5678 break;
5679 case 57: /* Integer VRSQRTE */
5680 gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
5681 break;
5682 case 58: /* Float VRECPE */
5683 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
5684 break;
5685 case 59: /* Float VRSQRTE */
5686 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
5687 break;
5688 case 60: /* VCVT.F32.S32 */
5689 gen_vfp_sito(0);
5690 break;
5691 case 61: /* VCVT.F32.U32 */
5692 gen_vfp_uito(0);
5693 break;
5694 case 62: /* VCVT.S32.F32 */
5695 gen_vfp_tosiz(0);
5696 break;
5697 case 63: /* VCVT.U32.F32 */
5698 gen_vfp_touiz(0);
5699 break;
5700 default:
5701 /* Reserved: 21, 29, 39-56 */
5702 return 1;
5704 if (op == 30 || op == 31 || op >= 58) {
5705 tcg_gen_st_f32(cpu_F0s, cpu_env,
5706 neon_reg_offset(rd, pass));
5707 } else {
5708 neon_store_reg(rd, pass, tmp);
5711 break;
5713 } else if ((insn & (1 << 10)) == 0) {
5714 /* VTBL, VTBX. */
5715 n = ((insn >> 5) & 0x18) + 8;
5716 if (insn & (1 << 6)) {
5717 tmp = neon_load_reg(rd, 0);
5718 } else {
5719 tmp = new_tmp();
5720 tcg_gen_movi_i32(tmp, 0);
5722 tmp2 = neon_load_reg(rm, 0);
5723 tmp4 = tcg_const_i32(rn);
5724 tmp5 = tcg_const_i32(n);
5725 gen_helper_neon_tbl(tmp2, tmp2, tmp, tmp4, tmp5);
5726 dead_tmp(tmp);
5727 if (insn & (1 << 6)) {
5728 tmp = neon_load_reg(rd, 1);
5729 } else {
5730 tmp = new_tmp();
5731 tcg_gen_movi_i32(tmp, 0);
5733 tmp3 = neon_load_reg(rm, 1);
5734 gen_helper_neon_tbl(tmp3, tmp3, tmp, tmp4, tmp5);
5735 tcg_temp_free_i32(tmp5);
5736 tcg_temp_free_i32(tmp4);
5737 neon_store_reg(rd, 0, tmp2);
5738 neon_store_reg(rd, 1, tmp3);
5739 dead_tmp(tmp);
5740 } else if ((insn & 0x380) == 0) {
5741 /* VDUP */
5742 if (insn & (1 << 19)) {
5743 tmp = neon_load_reg(rm, 1);
5744 } else {
5745 tmp = neon_load_reg(rm, 0);
5747 if (insn & (1 << 16)) {
5748 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
5749 } else if (insn & (1 << 17)) {
5750 if ((insn >> 18) & 1)
5751 gen_neon_dup_high16(tmp);
5752 else
5753 gen_neon_dup_low16(tmp);
5755 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5756 tmp2 = new_tmp();
5757 tcg_gen_mov_i32(tmp2, tmp);
5758 neon_store_reg(rd, pass, tmp2);
5760 dead_tmp(tmp);
5761 } else {
5762 return 1;
5766 return 0;
5769 static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
5771 int crn = (insn >> 16) & 0xf;
5772 int crm = insn & 0xf;
5773 int op1 = (insn >> 21) & 7;
5774 int op2 = (insn >> 5) & 7;
5775 int rt = (insn >> 12) & 0xf;
5776 TCGv tmp;
5778 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5779 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5780 /* TEECR */
5781 if (IS_USER(s))
5782 return 1;
5783 tmp = load_cpu_field(teecr);
5784 store_reg(s, rt, tmp);
5785 return 0;
5787 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5788 /* TEEHBR */
5789 if (IS_USER(s) && (env->teecr & 1))
5790 return 1;
5791 tmp = load_cpu_field(teehbr);
5792 store_reg(s, rt, tmp);
5793 return 0;
5796 fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5797 op1, crn, crm, op2);
5798 return 1;
5801 static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
5803 int crn = (insn >> 16) & 0xf;
5804 int crm = insn & 0xf;
5805 int op1 = (insn >> 21) & 7;
5806 int op2 = (insn >> 5) & 7;
5807 int rt = (insn >> 12) & 0xf;
5808 TCGv tmp;
5810 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5811 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5812 /* TEECR */
5813 if (IS_USER(s))
5814 return 1;
5815 tmp = load_reg(s, rt);
5816 gen_helper_set_teecr(cpu_env, tmp);
5817 dead_tmp(tmp);
5818 return 0;
5820 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5821 /* TEEHBR */
5822 if (IS_USER(s) && (env->teecr & 1))
5823 return 1;
5824 tmp = load_reg(s, rt);
5825 store_cpu_field(tmp, teehbr);
5826 return 0;
5829 fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5830 op1, crn, crm, op2);
5831 return 1;
5834 static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
5836 int cpnum;
5838 cpnum = (insn >> 8) & 0xf;
5839 if (arm_feature(env, ARM_FEATURE_XSCALE)
5840 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
5841 return 1;
5843 switch (cpnum) {
5844 case 0:
5845 case 1:
5846 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5847 return disas_iwmmxt_insn(env, s, insn);
5848 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
5849 return disas_dsp_insn(env, s, insn);
5851 return 1;
5852 case 10:
5853 case 11:
5854 return disas_vfp_insn (env, s, insn);
5855 case 14:
5856 /* Coprocessors 7-15 are architecturally reserved by ARM.
5857 Unfortunately Intel decided to ignore this. */
5858 if (arm_feature(env, ARM_FEATURE_XSCALE))
5859 goto board;
5860 if (insn & (1 << 20))
5861 return disas_cp14_read(env, s, insn);
5862 else
5863 return disas_cp14_write(env, s, insn);
5864 case 15:
5865 return disas_cp15_insn (env, s, insn);
5866 default:
5867 board:
5868 /* Unknown coprocessor. See if the board has hooked it. */
5869 return disas_cp_insn (env, s, insn);
5874 /* Store a 64-bit value to a register pair. Clobbers val. */
5875 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5877 TCGv tmp;
5878 tmp = new_tmp();
5879 tcg_gen_trunc_i64_i32(tmp, val);
5880 store_reg(s, rlow, tmp);
5881 tmp = new_tmp();
5882 tcg_gen_shri_i64(val, val, 32);
5883 tcg_gen_trunc_i64_i32(tmp, val);
5884 store_reg(s, rhigh, tmp);
5887 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5888 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5890 TCGv_i64 tmp;
5891 TCGv tmp2;
5893 /* Load value and extend to 64 bits. */
5894 tmp = tcg_temp_new_i64();
5895 tmp2 = load_reg(s, rlow);
5896 tcg_gen_extu_i32_i64(tmp, tmp2);
5897 dead_tmp(tmp2);
5898 tcg_gen_add_i64(val, val, tmp);
5899 tcg_temp_free_i64(tmp);
5902 /* load and add a 64-bit value from a register pair. */
5903 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5905 TCGv_i64 tmp;
5906 TCGv tmpl;
5907 TCGv tmph;
5909 /* Load 64-bit value rd:rn. */
5910 tmpl = load_reg(s, rlow);
5911 tmph = load_reg(s, rhigh);
5912 tmp = tcg_temp_new_i64();
5913 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
5914 dead_tmp(tmpl);
5915 dead_tmp(tmph);
5916 tcg_gen_add_i64(val, val, tmp);
5917 tcg_temp_free_i64(tmp);
5920 /* Set N and Z flags from a 64-bit value. */
5921 static void gen_logicq_cc(TCGv_i64 val)
5923 TCGv tmp = new_tmp();
5924 gen_helper_logicq_cc(tmp, val);
5925 gen_logic_CC(tmp);
5926 dead_tmp(tmp);
5929 /* Load/Store exclusive instructions are implemented by remembering
5930 the value/address loaded, and seeing if these are the same
5931 when the store is performed. This should be is sufficient to implement
5932 the architecturally mandated semantics, and avoids having to monitor
5933 regular stores.
5935 In system emulation mode only one CPU will be running at once, so
5936 this sequence is effectively atomic. In user emulation mode we
5937 throw an exception and handle the atomic operation elsewhere. */
5938 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
5939 TCGv addr, int size)
5941 TCGv tmp;
5943 switch (size) {
5944 case 0:
5945 tmp = gen_ld8u(addr, IS_USER(s));
5946 break;
5947 case 1:
5948 tmp = gen_ld16u(addr, IS_USER(s));
5949 break;
5950 case 2:
5951 case 3:
5952 tmp = gen_ld32(addr, IS_USER(s));
5953 break;
5954 default:
5955 abort();
5957 tcg_gen_mov_i32(cpu_exclusive_val, tmp);
5958 store_reg(s, rt, tmp);
5959 if (size == 3) {
5960 TCGv tmp2 = new_tmp();
5961 tcg_gen_addi_i32(tmp2, addr, 4);
5962 tmp = gen_ld32(tmp2, IS_USER(s));
5963 dead_tmp(tmp2);
5964 tcg_gen_mov_i32(cpu_exclusive_high, tmp);
5965 store_reg(s, rt2, tmp);
5967 tcg_gen_mov_i32(cpu_exclusive_addr, addr);
5970 static void gen_clrex(DisasContext *s)
5972 tcg_gen_movi_i32(cpu_exclusive_addr, -1);
5975 #ifdef CONFIG_USER_ONLY
5976 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
5977 TCGv addr, int size)
5979 tcg_gen_mov_i32(cpu_exclusive_test, addr);
5980 tcg_gen_movi_i32(cpu_exclusive_info,
5981 size | (rd << 4) | (rt << 8) | (rt2 << 12));
5982 gen_set_condexec(s);
5983 gen_set_pc_im(s->pc - 4);
5984 gen_exception(EXCP_STREX);
5985 s->is_jmp = DISAS_JUMP;
5987 #else
5988 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
5989 TCGv addr, int size)
5991 TCGv tmp;
5992 int done_label;
5993 int fail_label;
5995 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
5996 [addr] = {Rt};
5997 {Rd} = 0;
5998 } else {
5999 {Rd} = 1;
6000 } */
6001 fail_label = gen_new_label();
6002 done_label = gen_new_label();
6003 tcg_gen_brcond_i32(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
6004 switch (size) {
6005 case 0:
6006 tmp = gen_ld8u(addr, IS_USER(s));
6007 break;
6008 case 1:
6009 tmp = gen_ld16u(addr, IS_USER(s));
6010 break;
6011 case 2:
6012 case 3:
6013 tmp = gen_ld32(addr, IS_USER(s));
6014 break;
6015 default:
6016 abort();
6018 tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label);
6019 dead_tmp(tmp);
6020 if (size == 3) {
6021 TCGv tmp2 = new_tmp();
6022 tcg_gen_addi_i32(tmp2, addr, 4);
6023 tmp = gen_ld32(tmp2, IS_USER(s));
6024 dead_tmp(tmp2);
6025 tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_high, fail_label);
6026 dead_tmp(tmp);
6028 tmp = load_reg(s, rt);
6029 switch (size) {
6030 case 0:
6031 gen_st8(tmp, addr, IS_USER(s));
6032 break;
6033 case 1:
6034 gen_st16(tmp, addr, IS_USER(s));
6035 break;
6036 case 2:
6037 case 3:
6038 gen_st32(tmp, addr, IS_USER(s));
6039 break;
6040 default:
6041 abort();
6043 if (size == 3) {
6044 tcg_gen_addi_i32(addr, addr, 4);
6045 tmp = load_reg(s, rt2);
6046 gen_st32(tmp, addr, IS_USER(s));
6048 tcg_gen_movi_i32(cpu_R[rd], 0);
6049 tcg_gen_br(done_label);
6050 gen_set_label(fail_label);
6051 tcg_gen_movi_i32(cpu_R[rd], 1);
6052 gen_set_label(done_label);
6053 tcg_gen_movi_i32(cpu_exclusive_addr, -1);
6055 #endif
6057 static void disas_arm_insn(CPUState * env, DisasContext *s)
6059 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
6060 TCGv tmp;
6061 TCGv tmp2;
6062 TCGv tmp3;
6063 TCGv addr;
6064 TCGv_i64 tmp64;
6066 insn = ldl_code(s->pc);
6067 s->pc += 4;
6069 /* M variants do not implement ARM mode. */
6070 if (IS_M(env))
6071 goto illegal_op;
6072 cond = insn >> 28;
6073 if (cond == 0xf){
6074 /* Unconditional instructions. */
6075 if (((insn >> 25) & 7) == 1) {
6076 /* NEON Data processing. */
6077 if (!arm_feature(env, ARM_FEATURE_NEON))
6078 goto illegal_op;
6080 if (disas_neon_data_insn(env, s, insn))
6081 goto illegal_op;
6082 return;
6084 if ((insn & 0x0f100000) == 0x04000000) {
6085 /* NEON load/store. */
6086 if (!arm_feature(env, ARM_FEATURE_NEON))
6087 goto illegal_op;
6089 if (disas_neon_ls_insn(env, s, insn))
6090 goto illegal_op;
6091 return;
6093 if ((insn & 0x0d70f000) == 0x0550f000)
6094 return; /* PLD */
6095 else if ((insn & 0x0ffffdff) == 0x01010000) {
6096 ARCH(6);
6097 /* setend */
6098 if (insn & (1 << 9)) {
6099 /* BE8 mode not implemented. */
6100 goto illegal_op;
6102 return;
6103 } else if ((insn & 0x0fffff00) == 0x057ff000) {
6104 switch ((insn >> 4) & 0xf) {
6105 case 1: /* clrex */
6106 ARCH(6K);
6107 gen_clrex(s);
6108 return;
6109 case 4: /* dsb */
6110 case 5: /* dmb */
6111 case 6: /* isb */
6112 ARCH(7);
6113 /* We don't emulate caches so these are a no-op. */
6114 return;
6115 default:
6116 goto illegal_op;
6118 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
6119 /* srs */
6120 int32_t offset;
6121 if (IS_USER(s))
6122 goto illegal_op;
6123 ARCH(6);
6124 op1 = (insn & 0x1f);
6125 addr = new_tmp();
6126 tmp = tcg_const_i32(op1);
6127 gen_helper_get_r13_banked(addr, cpu_env, tmp);
6128 tcg_temp_free_i32(tmp);
6129 i = (insn >> 23) & 3;
6130 switch (i) {
6131 case 0: offset = -4; break; /* DA */
6132 case 1: offset = 0; break; /* IA */
6133 case 2: offset = -8; break; /* DB */
6134 case 3: offset = 4; break; /* IB */
6135 default: abort();
6137 if (offset)
6138 tcg_gen_addi_i32(addr, addr, offset);
6139 tmp = load_reg(s, 14);
6140 gen_st32(tmp, addr, 0);
6141 tmp = load_cpu_field(spsr);
6142 tcg_gen_addi_i32(addr, addr, 4);
6143 gen_st32(tmp, addr, 0);
6144 if (insn & (1 << 21)) {
6145 /* Base writeback. */
6146 switch (i) {
6147 case 0: offset = -8; break;
6148 case 1: offset = 4; break;
6149 case 2: offset = -4; break;
6150 case 3: offset = 0; break;
6151 default: abort();
6153 if (offset)
6154 tcg_gen_addi_i32(addr, addr, offset);
6155 tmp = tcg_const_i32(op1);
6156 gen_helper_set_r13_banked(cpu_env, tmp, addr);
6157 tcg_temp_free_i32(tmp);
6158 dead_tmp(addr);
6159 } else {
6160 dead_tmp(addr);
6162 return;
6163 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
6164 /* rfe */
6165 int32_t offset;
6166 if (IS_USER(s))
6167 goto illegal_op;
6168 ARCH(6);
6169 rn = (insn >> 16) & 0xf;
6170 addr = load_reg(s, rn);
6171 i = (insn >> 23) & 3;
6172 switch (i) {
6173 case 0: offset = -4; break; /* DA */
6174 case 1: offset = 0; break; /* IA */
6175 case 2: offset = -8; break; /* DB */
6176 case 3: offset = 4; break; /* IB */
6177 default: abort();
6179 if (offset)
6180 tcg_gen_addi_i32(addr, addr, offset);
6181 /* Load PC into tmp and CPSR into tmp2. */
6182 tmp = gen_ld32(addr, 0);
6183 tcg_gen_addi_i32(addr, addr, 4);
6184 tmp2 = gen_ld32(addr, 0);
6185 if (insn & (1 << 21)) {
6186 /* Base writeback. */
6187 switch (i) {
6188 case 0: offset = -8; break;
6189 case 1: offset = 4; break;
6190 case 2: offset = -4; break;
6191 case 3: offset = 0; break;
6192 default: abort();
6194 if (offset)
6195 tcg_gen_addi_i32(addr, addr, offset);
6196 store_reg(s, rn, addr);
6197 } else {
6198 dead_tmp(addr);
6200 gen_rfe(s, tmp, tmp2);
6201 return;
6202 } else if ((insn & 0x0e000000) == 0x0a000000) {
6203 /* branch link and change to thumb (blx <offset>) */
6204 int32_t offset;
6206 val = (uint32_t)s->pc;
6207 tmp = new_tmp();
6208 tcg_gen_movi_i32(tmp, val);
6209 store_reg(s, 14, tmp);
6210 /* Sign-extend the 24-bit offset */
6211 offset = (((int32_t)insn) << 8) >> 8;
6212 /* offset * 4 + bit24 * 2 + (thumb bit) */
6213 val += (offset << 2) | ((insn >> 23) & 2) | 1;
6214 /* pipeline offset */
6215 val += 4;
6216 gen_bx_im(s, val);
6217 return;
6218 } else if ((insn & 0x0e000f00) == 0x0c000100) {
6219 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
6220 /* iWMMXt register transfer. */
6221 if (env->cp15.c15_cpar & (1 << 1))
6222 if (!disas_iwmmxt_insn(env, s, insn))
6223 return;
6225 } else if ((insn & 0x0fe00000) == 0x0c400000) {
6226 /* Coprocessor double register transfer. */
6227 } else if ((insn & 0x0f000010) == 0x0e000010) {
6228 /* Additional coprocessor register transfer. */
6229 } else if ((insn & 0x0ff10020) == 0x01000000) {
6230 uint32_t mask;
6231 uint32_t val;
6232 /* cps (privileged) */
6233 if (IS_USER(s))
6234 return;
6235 mask = val = 0;
6236 if (insn & (1 << 19)) {
6237 if (insn & (1 << 8))
6238 mask |= CPSR_A;
6239 if (insn & (1 << 7))
6240 mask |= CPSR_I;
6241 if (insn & (1 << 6))
6242 mask |= CPSR_F;
6243 if (insn & (1 << 18))
6244 val |= mask;
6246 if (insn & (1 << 17)) {
6247 mask |= CPSR_M;
6248 val |= (insn & 0x1f);
6250 if (mask) {
6251 gen_set_psr_im(s, mask, 0, val);
6253 return;
6255 goto illegal_op;
6257 if (cond != 0xe) {
6258 /* if not always execute, we generate a conditional jump to
6259 next instruction */
6260 s->condlabel = gen_new_label();
6261 gen_test_cc(cond ^ 1, s->condlabel);
6262 s->condjmp = 1;
6264 if ((insn & 0x0f900000) == 0x03000000) {
6265 if ((insn & (1 << 21)) == 0) {
6266 ARCH(6T2);
6267 rd = (insn >> 12) & 0xf;
6268 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
6269 if ((insn & (1 << 22)) == 0) {
6270 /* MOVW */
6271 tmp = new_tmp();
6272 tcg_gen_movi_i32(tmp, val);
6273 } else {
6274 /* MOVT */
6275 tmp = load_reg(s, rd);
6276 tcg_gen_ext16u_i32(tmp, tmp);
6277 tcg_gen_ori_i32(tmp, tmp, val << 16);
6279 store_reg(s, rd, tmp);
6280 } else {
6281 if (((insn >> 12) & 0xf) != 0xf)
6282 goto illegal_op;
6283 if (((insn >> 16) & 0xf) == 0) {
6284 gen_nop_hint(s, insn & 0xff);
6285 } else {
6286 /* CPSR = immediate */
6287 val = insn & 0xff;
6288 shift = ((insn >> 8) & 0xf) * 2;
6289 if (shift)
6290 val = (val >> shift) | (val << (32 - shift));
6291 i = ((insn & (1 << 22)) != 0);
6292 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
6293 goto illegal_op;
6296 } else if ((insn & 0x0f900000) == 0x01000000
6297 && (insn & 0x00000090) != 0x00000090) {
6298 /* miscellaneous instructions */
6299 op1 = (insn >> 21) & 3;
6300 sh = (insn >> 4) & 0xf;
6301 rm = insn & 0xf;
6302 switch (sh) {
6303 case 0x0: /* move program status register */
6304 if (op1 & 1) {
6305 /* PSR = reg */
6306 tmp = load_reg(s, rm);
6307 i = ((op1 & 2) != 0);
6308 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
6309 goto illegal_op;
6310 } else {
6311 /* reg = PSR */
6312 rd = (insn >> 12) & 0xf;
6313 if (op1 & 2) {
6314 if (IS_USER(s))
6315 goto illegal_op;
6316 tmp = load_cpu_field(spsr);
6317 } else {
6318 tmp = new_tmp();
6319 gen_helper_cpsr_read(tmp);
6321 store_reg(s, rd, tmp);
6323 break;
6324 case 0x1:
6325 if (op1 == 1) {
6326 /* branch/exchange thumb (bx). */
6327 tmp = load_reg(s, rm);
6328 gen_bx(s, tmp);
6329 } else if (op1 == 3) {
6330 /* clz */
6331 rd = (insn >> 12) & 0xf;
6332 tmp = load_reg(s, rm);
6333 gen_helper_clz(tmp, tmp);
6334 store_reg(s, rd, tmp);
6335 } else {
6336 goto illegal_op;
6338 break;
6339 case 0x2:
6340 if (op1 == 1) {
6341 ARCH(5J); /* bxj */
6342 /* Trivial implementation equivalent to bx. */
6343 tmp = load_reg(s, rm);
6344 gen_bx(s, tmp);
6345 } else {
6346 goto illegal_op;
6348 break;
6349 case 0x3:
6350 if (op1 != 1)
6351 goto illegal_op;
6353 /* branch link/exchange thumb (blx) */
6354 tmp = load_reg(s, rm);
6355 tmp2 = new_tmp();
6356 tcg_gen_movi_i32(tmp2, s->pc);
6357 store_reg(s, 14, tmp2);
6358 gen_bx(s, tmp);
6359 break;
6360 case 0x5: /* saturating add/subtract */
6361 rd = (insn >> 12) & 0xf;
6362 rn = (insn >> 16) & 0xf;
6363 tmp = load_reg(s, rm);
6364 tmp2 = load_reg(s, rn);
6365 if (op1 & 2)
6366 gen_helper_double_saturate(tmp2, tmp2);
6367 if (op1 & 1)
6368 gen_helper_sub_saturate(tmp, tmp, tmp2);
6369 else
6370 gen_helper_add_saturate(tmp, tmp, tmp2);
6371 dead_tmp(tmp2);
6372 store_reg(s, rd, tmp);
6373 break;
6374 case 7:
6375 /* SMC instruction (op1 == 3)
6376 and undefined instructions (op1 == 0 || op1 == 2)
6377 will trap */
6378 if (op1 != 1) {
6379 goto illegal_op;
6381 /* bkpt */
6382 gen_set_condexec(s);
6383 gen_set_pc_im(s->pc - 4);
6384 gen_exception(EXCP_BKPT);
6385 s->is_jmp = DISAS_JUMP;
6386 break;
6387 case 0x8: /* signed multiply */
6388 case 0xa:
6389 case 0xc:
6390 case 0xe:
6391 rs = (insn >> 8) & 0xf;
6392 rn = (insn >> 12) & 0xf;
6393 rd = (insn >> 16) & 0xf;
6394 if (op1 == 1) {
6395 /* (32 * 16) >> 16 */
6396 tmp = load_reg(s, rm);
6397 tmp2 = load_reg(s, rs);
6398 if (sh & 4)
6399 tcg_gen_sari_i32(tmp2, tmp2, 16);
6400 else
6401 gen_sxth(tmp2);
6402 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6403 tcg_gen_shri_i64(tmp64, tmp64, 16);
6404 tmp = new_tmp();
6405 tcg_gen_trunc_i64_i32(tmp, tmp64);
6406 tcg_temp_free_i64(tmp64);
6407 if ((sh & 2) == 0) {
6408 tmp2 = load_reg(s, rn);
6409 gen_helper_add_setq(tmp, tmp, tmp2);
6410 dead_tmp(tmp2);
6412 store_reg(s, rd, tmp);
6413 } else {
6414 /* 16 * 16 */
6415 tmp = load_reg(s, rm);
6416 tmp2 = load_reg(s, rs);
6417 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
6418 dead_tmp(tmp2);
6419 if (op1 == 2) {
6420 tmp64 = tcg_temp_new_i64();
6421 tcg_gen_ext_i32_i64(tmp64, tmp);
6422 dead_tmp(tmp);
6423 gen_addq(s, tmp64, rn, rd);
6424 gen_storeq_reg(s, rn, rd, tmp64);
6425 tcg_temp_free_i64(tmp64);
6426 } else {
6427 if (op1 == 0) {
6428 tmp2 = load_reg(s, rn);
6429 gen_helper_add_setq(tmp, tmp, tmp2);
6430 dead_tmp(tmp2);
6432 store_reg(s, rd, tmp);
6435 break;
6436 default:
6437 goto illegal_op;
6439 } else if (((insn & 0x0e000000) == 0 &&
6440 (insn & 0x00000090) != 0x90) ||
6441 ((insn & 0x0e000000) == (1 << 25))) {
6442 int set_cc, logic_cc, shiftop;
6444 op1 = (insn >> 21) & 0xf;
6445 set_cc = (insn >> 20) & 1;
6446 logic_cc = table_logic_cc[op1] & set_cc;
6448 /* data processing instruction */
6449 if (insn & (1 << 25)) {
6450 /* immediate operand */
6451 val = insn & 0xff;
6452 shift = ((insn >> 8) & 0xf) * 2;
6453 if (shift) {
6454 val = (val >> shift) | (val << (32 - shift));
6456 tmp2 = new_tmp();
6457 tcg_gen_movi_i32(tmp2, val);
6458 if (logic_cc && shift) {
6459 gen_set_CF_bit31(tmp2);
6461 } else {
6462 /* register */
6463 rm = (insn) & 0xf;
6464 tmp2 = load_reg(s, rm);
6465 shiftop = (insn >> 5) & 3;
6466 if (!(insn & (1 << 4))) {
6467 shift = (insn >> 7) & 0x1f;
6468 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
6469 } else {
6470 rs = (insn >> 8) & 0xf;
6471 tmp = load_reg(s, rs);
6472 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
6475 if (op1 != 0x0f && op1 != 0x0d) {
6476 rn = (insn >> 16) & 0xf;
6477 tmp = load_reg(s, rn);
6478 } else {
6479 TCGV_UNUSED(tmp);
6481 rd = (insn >> 12) & 0xf;
6482 switch(op1) {
6483 case 0x00:
6484 tcg_gen_and_i32(tmp, tmp, tmp2);
6485 if (logic_cc) {
6486 gen_logic_CC(tmp);
6488 store_reg_bx(env, s, rd, tmp);
6489 break;
6490 case 0x01:
6491 tcg_gen_xor_i32(tmp, tmp, tmp2);
6492 if (logic_cc) {
6493 gen_logic_CC(tmp);
6495 store_reg_bx(env, s, rd, tmp);
6496 break;
6497 case 0x02:
6498 if (set_cc && rd == 15) {
6499 /* SUBS r15, ... is used for exception return. */
6500 if (IS_USER(s)) {
6501 goto illegal_op;
6503 gen_helper_sub_cc(tmp, tmp, tmp2);
6504 gen_exception_return(s, tmp);
6505 } else {
6506 if (set_cc) {
6507 gen_helper_sub_cc(tmp, tmp, tmp2);
6508 } else {
6509 tcg_gen_sub_i32(tmp, tmp, tmp2);
6511 store_reg_bx(env, s, rd, tmp);
6513 break;
6514 case 0x03:
6515 if (set_cc) {
6516 gen_helper_sub_cc(tmp, tmp2, tmp);
6517 } else {
6518 tcg_gen_sub_i32(tmp, tmp2, tmp);
6520 store_reg_bx(env, s, rd, tmp);
6521 break;
6522 case 0x04:
6523 if (set_cc) {
6524 gen_helper_add_cc(tmp, tmp, tmp2);
6525 } else {
6526 tcg_gen_add_i32(tmp, tmp, tmp2);
6528 store_reg_bx(env, s, rd, tmp);
6529 break;
6530 case 0x05:
6531 if (set_cc) {
6532 gen_helper_adc_cc(tmp, tmp, tmp2);
6533 } else {
6534 gen_add_carry(tmp, tmp, tmp2);
6536 store_reg_bx(env, s, rd, tmp);
6537 break;
6538 case 0x06:
6539 if (set_cc) {
6540 gen_helper_sbc_cc(tmp, tmp, tmp2);
6541 } else {
6542 gen_sub_carry(tmp, tmp, tmp2);
6544 store_reg_bx(env, s, rd, tmp);
6545 break;
6546 case 0x07:
6547 if (set_cc) {
6548 gen_helper_sbc_cc(tmp, tmp2, tmp);
6549 } else {
6550 gen_sub_carry(tmp, tmp2, tmp);
6552 store_reg_bx(env, s, rd, tmp);
6553 break;
6554 case 0x08:
6555 if (set_cc) {
6556 tcg_gen_and_i32(tmp, tmp, tmp2);
6557 gen_logic_CC(tmp);
6559 dead_tmp(tmp);
6560 break;
6561 case 0x09:
6562 if (set_cc) {
6563 tcg_gen_xor_i32(tmp, tmp, tmp2);
6564 gen_logic_CC(tmp);
6566 dead_tmp(tmp);
6567 break;
6568 case 0x0a:
6569 if (set_cc) {
6570 gen_helper_sub_cc(tmp, tmp, tmp2);
6572 dead_tmp(tmp);
6573 break;
6574 case 0x0b:
6575 if (set_cc) {
6576 gen_helper_add_cc(tmp, tmp, tmp2);
6578 dead_tmp(tmp);
6579 break;
6580 case 0x0c:
6581 tcg_gen_or_i32(tmp, tmp, tmp2);
6582 if (logic_cc) {
6583 gen_logic_CC(tmp);
6585 store_reg_bx(env, s, rd, tmp);
6586 break;
6587 case 0x0d:
6588 if (logic_cc && rd == 15) {
6589 /* MOVS r15, ... is used for exception return. */
6590 if (IS_USER(s)) {
6591 goto illegal_op;
6593 gen_exception_return(s, tmp2);
6594 } else {
6595 if (logic_cc) {
6596 gen_logic_CC(tmp2);
6598 store_reg_bx(env, s, rd, tmp2);
6600 break;
6601 case 0x0e:
6602 tcg_gen_andc_i32(tmp, tmp, tmp2);
6603 if (logic_cc) {
6604 gen_logic_CC(tmp);
6606 store_reg_bx(env, s, rd, tmp);
6607 break;
6608 default:
6609 case 0x0f:
6610 tcg_gen_not_i32(tmp2, tmp2);
6611 if (logic_cc) {
6612 gen_logic_CC(tmp2);
6614 store_reg_bx(env, s, rd, tmp2);
6615 break;
6617 if (op1 != 0x0f && op1 != 0x0d) {
6618 dead_tmp(tmp2);
6620 } else {
6621 /* other instructions */
6622 op1 = (insn >> 24) & 0xf;
6623 switch(op1) {
6624 case 0x0:
6625 case 0x1:
6626 /* multiplies, extra load/stores */
6627 sh = (insn >> 5) & 3;
6628 if (sh == 0) {
6629 if (op1 == 0x0) {
6630 rd = (insn >> 16) & 0xf;
6631 rn = (insn >> 12) & 0xf;
6632 rs = (insn >> 8) & 0xf;
6633 rm = (insn) & 0xf;
6634 op1 = (insn >> 20) & 0xf;
6635 switch (op1) {
6636 case 0: case 1: case 2: case 3: case 6:
6637 /* 32 bit mul */
6638 tmp = load_reg(s, rs);
6639 tmp2 = load_reg(s, rm);
6640 tcg_gen_mul_i32(tmp, tmp, tmp2);
6641 dead_tmp(tmp2);
6642 if (insn & (1 << 22)) {
6643 /* Subtract (mls) */
6644 ARCH(6T2);
6645 tmp2 = load_reg(s, rn);
6646 tcg_gen_sub_i32(tmp, tmp2, tmp);
6647 dead_tmp(tmp2);
6648 } else if (insn & (1 << 21)) {
6649 /* Add */
6650 tmp2 = load_reg(s, rn);
6651 tcg_gen_add_i32(tmp, tmp, tmp2);
6652 dead_tmp(tmp2);
6654 if (insn & (1 << 20))
6655 gen_logic_CC(tmp);
6656 store_reg(s, rd, tmp);
6657 break;
6658 case 4:
6659 /* 64 bit mul double accumulate (UMAAL) */
6660 ARCH(6);
6661 tmp = load_reg(s, rs);
6662 tmp2 = load_reg(s, rm);
6663 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
6664 gen_addq_lo(s, tmp64, rn);
6665 gen_addq_lo(s, tmp64, rd);
6666 gen_storeq_reg(s, rn, rd, tmp64);
6667 tcg_temp_free_i64(tmp64);
6668 break;
6669 case 8: case 9: case 10: case 11:
6670 case 12: case 13: case 14: case 15:
6671 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
6672 tmp = load_reg(s, rs);
6673 tmp2 = load_reg(s, rm);
6674 if (insn & (1 << 22)) {
6675 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6676 } else {
6677 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
6679 if (insn & (1 << 21)) { /* mult accumulate */
6680 gen_addq(s, tmp64, rn, rd);
6682 if (insn & (1 << 20)) {
6683 gen_logicq_cc(tmp64);
6685 gen_storeq_reg(s, rn, rd, tmp64);
6686 tcg_temp_free_i64(tmp64);
6687 break;
6688 default:
6689 goto illegal_op;
6691 } else {
6692 rn = (insn >> 16) & 0xf;
6693 rd = (insn >> 12) & 0xf;
6694 if (insn & (1 << 23)) {
6695 /* load/store exclusive */
6696 op1 = (insn >> 21) & 0x3;
6697 if (op1)
6698 ARCH(6K);
6699 else
6700 ARCH(6);
6701 addr = tcg_temp_local_new_i32();
6702 load_reg_var(s, addr, rn);
6703 if (insn & (1 << 20)) {
6704 switch (op1) {
6705 case 0: /* ldrex */
6706 gen_load_exclusive(s, rd, 15, addr, 2);
6707 break;
6708 case 1: /* ldrexd */
6709 gen_load_exclusive(s, rd, rd + 1, addr, 3);
6710 break;
6711 case 2: /* ldrexb */
6712 gen_load_exclusive(s, rd, 15, addr, 0);
6713 break;
6714 case 3: /* ldrexh */
6715 gen_load_exclusive(s, rd, 15, addr, 1);
6716 break;
6717 default:
6718 abort();
6720 } else {
6721 rm = insn & 0xf;
6722 switch (op1) {
6723 case 0: /* strex */
6724 gen_store_exclusive(s, rd, rm, 15, addr, 2);
6725 break;
6726 case 1: /* strexd */
6727 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
6728 break;
6729 case 2: /* strexb */
6730 gen_store_exclusive(s, rd, rm, 15, addr, 0);
6731 break;
6732 case 3: /* strexh */
6733 gen_store_exclusive(s, rd, rm, 15, addr, 1);
6734 break;
6735 default:
6736 abort();
6739 tcg_temp_free(addr);
6740 } else {
6741 /* SWP instruction */
6742 rm = (insn) & 0xf;
6744 /* ??? This is not really atomic. However we know
6745 we never have multiple CPUs running in parallel,
6746 so it is good enough. */
6747 addr = load_reg(s, rn);
6748 tmp = load_reg(s, rm);
6749 if (insn & (1 << 22)) {
6750 tmp2 = gen_ld8u(addr, IS_USER(s));
6751 gen_st8(tmp, addr, IS_USER(s));
6752 } else {
6753 tmp2 = gen_ld32(addr, IS_USER(s));
6754 gen_st32(tmp, addr, IS_USER(s));
6756 dead_tmp(addr);
6757 store_reg(s, rd, tmp2);
6760 } else {
6761 int address_offset;
6762 int load;
6763 /* Misc load/store */
6764 rn = (insn >> 16) & 0xf;
6765 rd = (insn >> 12) & 0xf;
6766 addr = load_reg(s, rn);
6767 if (insn & (1 << 24))
6768 gen_add_datah_offset(s, insn, 0, addr);
6769 address_offset = 0;
6770 if (insn & (1 << 20)) {
6771 /* load */
6772 switch(sh) {
6773 case 1:
6774 tmp = gen_ld16u(addr, IS_USER(s));
6775 break;
6776 case 2:
6777 tmp = gen_ld8s(addr, IS_USER(s));
6778 break;
6779 default:
6780 case 3:
6781 tmp = gen_ld16s(addr, IS_USER(s));
6782 break;
6784 load = 1;
6785 } else if (sh & 2) {
6786 /* doubleword */
6787 if (sh & 1) {
6788 /* store */
6789 tmp = load_reg(s, rd);
6790 gen_st32(tmp, addr, IS_USER(s));
6791 tcg_gen_addi_i32(addr, addr, 4);
6792 tmp = load_reg(s, rd + 1);
6793 gen_st32(tmp, addr, IS_USER(s));
6794 load = 0;
6795 } else {
6796 /* load */
6797 tmp = gen_ld32(addr, IS_USER(s));
6798 store_reg(s, rd, tmp);
6799 tcg_gen_addi_i32(addr, addr, 4);
6800 tmp = gen_ld32(addr, IS_USER(s));
6801 rd++;
6802 load = 1;
6804 address_offset = -4;
6805 } else {
6806 /* store */
6807 tmp = load_reg(s, rd);
6808 gen_st16(tmp, addr, IS_USER(s));
6809 load = 0;
6811 /* Perform base writeback before the loaded value to
6812 ensure correct behavior with overlapping index registers.
6813 ldrd with base writeback is is undefined if the
6814 destination and index registers overlap. */
6815 if (!(insn & (1 << 24))) {
6816 gen_add_datah_offset(s, insn, address_offset, addr);
6817 store_reg(s, rn, addr);
6818 } else if (insn & (1 << 21)) {
6819 if (address_offset)
6820 tcg_gen_addi_i32(addr, addr, address_offset);
6821 store_reg(s, rn, addr);
6822 } else {
6823 dead_tmp(addr);
6825 if (load) {
6826 /* Complete the load. */
6827 store_reg(s, rd, tmp);
6830 break;
6831 case 0x4:
6832 case 0x5:
6833 goto do_ldst;
6834 case 0x6:
6835 case 0x7:
6836 if (insn & (1 << 4)) {
6837 ARCH(6);
6838 /* Armv6 Media instructions. */
6839 rm = insn & 0xf;
6840 rn = (insn >> 16) & 0xf;
6841 rd = (insn >> 12) & 0xf;
6842 rs = (insn >> 8) & 0xf;
6843 switch ((insn >> 23) & 3) {
6844 case 0: /* Parallel add/subtract. */
6845 op1 = (insn >> 20) & 7;
6846 tmp = load_reg(s, rn);
6847 tmp2 = load_reg(s, rm);
6848 sh = (insn >> 5) & 7;
6849 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
6850 goto illegal_op;
6851 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
6852 dead_tmp(tmp2);
6853 store_reg(s, rd, tmp);
6854 break;
6855 case 1:
6856 if ((insn & 0x00700020) == 0) {
6857 /* Halfword pack. */
6858 tmp = load_reg(s, rn);
6859 tmp2 = load_reg(s, rm);
6860 shift = (insn >> 7) & 0x1f;
6861 if (insn & (1 << 6)) {
6862 /* pkhtb */
6863 if (shift == 0)
6864 shift = 31;
6865 tcg_gen_sari_i32(tmp2, tmp2, shift);
6866 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
6867 tcg_gen_ext16u_i32(tmp2, tmp2);
6868 } else {
6869 /* pkhbt */
6870 if (shift)
6871 tcg_gen_shli_i32(tmp2, tmp2, shift);
6872 tcg_gen_ext16u_i32(tmp, tmp);
6873 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
6875 tcg_gen_or_i32(tmp, tmp, tmp2);
6876 dead_tmp(tmp2);
6877 store_reg(s, rd, tmp);
6878 } else if ((insn & 0x00200020) == 0x00200000) {
6879 /* [us]sat */
6880 tmp = load_reg(s, rm);
6881 shift = (insn >> 7) & 0x1f;
6882 if (insn & (1 << 6)) {
6883 if (shift == 0)
6884 shift = 31;
6885 tcg_gen_sari_i32(tmp, tmp, shift);
6886 } else {
6887 tcg_gen_shli_i32(tmp, tmp, shift);
6889 sh = (insn >> 16) & 0x1f;
6890 if (sh != 0) {
6891 tmp2 = tcg_const_i32(sh);
6892 if (insn & (1 << 22))
6893 gen_helper_usat(tmp, tmp, tmp2);
6894 else
6895 gen_helper_ssat(tmp, tmp, tmp2);
6896 tcg_temp_free_i32(tmp2);
6898 store_reg(s, rd, tmp);
6899 } else if ((insn & 0x00300fe0) == 0x00200f20) {
6900 /* [us]sat16 */
6901 tmp = load_reg(s, rm);
6902 sh = (insn >> 16) & 0x1f;
6903 if (sh != 0) {
6904 tmp2 = tcg_const_i32(sh);
6905 if (insn & (1 << 22))
6906 gen_helper_usat16(tmp, tmp, tmp2);
6907 else
6908 gen_helper_ssat16(tmp, tmp, tmp2);
6909 tcg_temp_free_i32(tmp2);
6911 store_reg(s, rd, tmp);
6912 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
6913 /* Select bytes. */
6914 tmp = load_reg(s, rn);
6915 tmp2 = load_reg(s, rm);
6916 tmp3 = new_tmp();
6917 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
6918 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
6919 dead_tmp(tmp3);
6920 dead_tmp(tmp2);
6921 store_reg(s, rd, tmp);
6922 } else if ((insn & 0x000003e0) == 0x00000060) {
6923 tmp = load_reg(s, rm);
6924 shift = (insn >> 10) & 3;
6925 /* ??? In many cases it's not neccessary to do a
6926 rotate, a shift is sufficient. */
6927 if (shift != 0)
6928 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
6929 op1 = (insn >> 20) & 7;
6930 switch (op1) {
6931 case 0: gen_sxtb16(tmp); break;
6932 case 2: gen_sxtb(tmp); break;
6933 case 3: gen_sxth(tmp); break;
6934 case 4: gen_uxtb16(tmp); break;
6935 case 6: gen_uxtb(tmp); break;
6936 case 7: gen_uxth(tmp); break;
6937 default: goto illegal_op;
6939 if (rn != 15) {
6940 tmp2 = load_reg(s, rn);
6941 if ((op1 & 3) == 0) {
6942 gen_add16(tmp, tmp2);
6943 } else {
6944 tcg_gen_add_i32(tmp, tmp, tmp2);
6945 dead_tmp(tmp2);
6948 store_reg(s, rd, tmp);
6949 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
6950 /* rev */
6951 tmp = load_reg(s, rm);
6952 if (insn & (1 << 22)) {
6953 if (insn & (1 << 7)) {
6954 gen_revsh(tmp);
6955 } else {
6956 ARCH(6T2);
6957 gen_helper_rbit(tmp, tmp);
6959 } else {
6960 if (insn & (1 << 7))
6961 gen_rev16(tmp);
6962 else
6963 tcg_gen_bswap32_i32(tmp, tmp);
6965 store_reg(s, rd, tmp);
6966 } else {
6967 goto illegal_op;
6969 break;
6970 case 2: /* Multiplies (Type 3). */
6971 tmp = load_reg(s, rm);
6972 tmp2 = load_reg(s, rs);
6973 if (insn & (1 << 20)) {
6974 /* Signed multiply most significant [accumulate].
6975 (SMMUL, SMMLA, SMMLS) */
6976 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6978 if (rd != 15) {
6979 tmp = load_reg(s, rd);
6980 if (insn & (1 << 6)) {
6981 tmp64 = gen_subq_msw(tmp64, tmp);
6982 } else {
6983 tmp64 = gen_addq_msw(tmp64, tmp);
6986 if (insn & (1 << 5)) {
6987 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
6989 tcg_gen_shri_i64(tmp64, tmp64, 32);
6990 tmp = new_tmp();
6991 tcg_gen_trunc_i64_i32(tmp, tmp64);
6992 tcg_temp_free_i64(tmp64);
6993 store_reg(s, rn, tmp);
6994 } else {
6995 if (insn & (1 << 5))
6996 gen_swap_half(tmp2);
6997 gen_smul_dual(tmp, tmp2);
6998 /* This addition cannot overflow. */
6999 if (insn & (1 << 6)) {
7000 tcg_gen_sub_i32(tmp, tmp, tmp2);
7001 } else {
7002 tcg_gen_add_i32(tmp, tmp, tmp2);
7004 dead_tmp(tmp2);
7005 if (insn & (1 << 22)) {
7006 /* smlald, smlsld */
7007 tmp64 = tcg_temp_new_i64();
7008 tcg_gen_ext_i32_i64(tmp64, tmp);
7009 dead_tmp(tmp);
7010 gen_addq(s, tmp64, rd, rn);
7011 gen_storeq_reg(s, rd, rn, tmp64);
7012 tcg_temp_free_i64(tmp64);
7013 } else {
7014 /* smuad, smusd, smlad, smlsd */
7015 if (rd != 15)
7017 tmp2 = load_reg(s, rd);
7018 gen_helper_add_setq(tmp, tmp, tmp2);
7019 dead_tmp(tmp2);
7021 store_reg(s, rn, tmp);
7024 break;
7025 case 3:
7026 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
7027 switch (op1) {
7028 case 0: /* Unsigned sum of absolute differences. */
7029 ARCH(6);
7030 tmp = load_reg(s, rm);
7031 tmp2 = load_reg(s, rs);
7032 gen_helper_usad8(tmp, tmp, tmp2);
7033 dead_tmp(tmp2);
7034 if (rd != 15) {
7035 tmp2 = load_reg(s, rd);
7036 tcg_gen_add_i32(tmp, tmp, tmp2);
7037 dead_tmp(tmp2);
7039 store_reg(s, rn, tmp);
7040 break;
7041 case 0x20: case 0x24: case 0x28: case 0x2c:
7042 /* Bitfield insert/clear. */
7043 ARCH(6T2);
7044 shift = (insn >> 7) & 0x1f;
7045 i = (insn >> 16) & 0x1f;
7046 i = i + 1 - shift;
7047 if (rm == 15) {
7048 tmp = new_tmp();
7049 tcg_gen_movi_i32(tmp, 0);
7050 } else {
7051 tmp = load_reg(s, rm);
7053 if (i != 32) {
7054 tmp2 = load_reg(s, rd);
7055 gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
7056 dead_tmp(tmp2);
7058 store_reg(s, rd, tmp);
7059 break;
7060 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
7061 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
7062 ARCH(6T2);
7063 tmp = load_reg(s, rm);
7064 shift = (insn >> 7) & 0x1f;
7065 i = ((insn >> 16) & 0x1f) + 1;
7066 if (shift + i > 32)
7067 goto illegal_op;
7068 if (i < 32) {
7069 if (op1 & 0x20) {
7070 gen_ubfx(tmp, shift, (1u << i) - 1);
7071 } else {
7072 gen_sbfx(tmp, shift, i);
7075 store_reg(s, rd, tmp);
7076 break;
7077 default:
7078 goto illegal_op;
7080 break;
7082 break;
7084 do_ldst:
7085 /* Check for undefined extension instructions
7086 * per the ARM Bible IE:
7087 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
7089 sh = (0xf << 20) | (0xf << 4);
7090 if (op1 == 0x7 && ((insn & sh) == sh))
7092 goto illegal_op;
7094 /* load/store byte/word */
7095 rn = (insn >> 16) & 0xf;
7096 rd = (insn >> 12) & 0xf;
7097 tmp2 = load_reg(s, rn);
7098 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
7099 if (insn & (1 << 24))
7100 gen_add_data_offset(s, insn, tmp2);
7101 if (insn & (1 << 20)) {
7102 /* load */
7103 if (insn & (1 << 22)) {
7104 tmp = gen_ld8u(tmp2, i);
7105 } else {
7106 tmp = gen_ld32(tmp2, i);
7108 } else {
7109 /* store */
7110 tmp = load_reg(s, rd);
7111 if (insn & (1 << 22))
7112 gen_st8(tmp, tmp2, i);
7113 else
7114 gen_st32(tmp, tmp2, i);
7116 if (!(insn & (1 << 24))) {
7117 gen_add_data_offset(s, insn, tmp2);
7118 store_reg(s, rn, tmp2);
7119 } else if (insn & (1 << 21)) {
7120 store_reg(s, rn, tmp2);
7121 } else {
7122 dead_tmp(tmp2);
7124 if (insn & (1 << 20)) {
7125 /* Complete the load. */
7126 if (rd == 15)
7127 gen_bx(s, tmp);
7128 else
7129 store_reg(s, rd, tmp);
7131 break;
7132 case 0x08:
7133 case 0x09:
7135 int j, n, user, loaded_base;
7136 TCGv loaded_var;
7137 /* load/store multiple words */
7138 /* XXX: store correct base if write back */
7139 user = 0;
7140 if (insn & (1 << 22)) {
7141 if (IS_USER(s))
7142 goto illegal_op; /* only usable in supervisor mode */
7144 if ((insn & (1 << 15)) == 0)
7145 user = 1;
7147 rn = (insn >> 16) & 0xf;
7148 addr = load_reg(s, rn);
7150 /* compute total size */
7151 loaded_base = 0;
7152 TCGV_UNUSED(loaded_var);
7153 n = 0;
7154 for(i=0;i<16;i++) {
7155 if (insn & (1 << i))
7156 n++;
7158 /* XXX: test invalid n == 0 case ? */
7159 if (insn & (1 << 23)) {
7160 if (insn & (1 << 24)) {
7161 /* pre increment */
7162 tcg_gen_addi_i32(addr, addr, 4);
7163 } else {
7164 /* post increment */
7166 } else {
7167 if (insn & (1 << 24)) {
7168 /* pre decrement */
7169 tcg_gen_addi_i32(addr, addr, -(n * 4));
7170 } else {
7171 /* post decrement */
7172 if (n != 1)
7173 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7176 j = 0;
7177 for(i=0;i<16;i++) {
7178 if (insn & (1 << i)) {
7179 if (insn & (1 << 20)) {
7180 /* load */
7181 tmp = gen_ld32(addr, IS_USER(s));
7182 if (i == 15) {
7183 gen_bx(s, tmp);
7184 } else if (user) {
7185 tmp2 = tcg_const_i32(i);
7186 gen_helper_set_user_reg(tmp2, tmp);
7187 tcg_temp_free_i32(tmp2);
7188 dead_tmp(tmp);
7189 } else if (i == rn) {
7190 loaded_var = tmp;
7191 loaded_base = 1;
7192 } else {
7193 store_reg(s, i, tmp);
7195 } else {
7196 /* store */
7197 if (i == 15) {
7198 /* special case: r15 = PC + 8 */
7199 val = (long)s->pc + 4;
7200 tmp = new_tmp();
7201 tcg_gen_movi_i32(tmp, val);
7202 } else if (user) {
7203 tmp = new_tmp();
7204 tmp2 = tcg_const_i32(i);
7205 gen_helper_get_user_reg(tmp, tmp2);
7206 tcg_temp_free_i32(tmp2);
7207 } else {
7208 tmp = load_reg(s, i);
7210 gen_st32(tmp, addr, IS_USER(s));
7212 j++;
7213 /* no need to add after the last transfer */
7214 if (j != n)
7215 tcg_gen_addi_i32(addr, addr, 4);
7218 if (insn & (1 << 21)) {
7219 /* write back */
7220 if (insn & (1 << 23)) {
7221 if (insn & (1 << 24)) {
7222 /* pre increment */
7223 } else {
7224 /* post increment */
7225 tcg_gen_addi_i32(addr, addr, 4);
7227 } else {
7228 if (insn & (1 << 24)) {
7229 /* pre decrement */
7230 if (n != 1)
7231 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7232 } else {
7233 /* post decrement */
7234 tcg_gen_addi_i32(addr, addr, -(n * 4));
7237 store_reg(s, rn, addr);
7238 } else {
7239 dead_tmp(addr);
7241 if (loaded_base) {
7242 store_reg(s, rn, loaded_var);
7244 if ((insn & (1 << 22)) && !user) {
7245 /* Restore CPSR from SPSR. */
7246 tmp = load_cpu_field(spsr);
7247 gen_set_cpsr(tmp, 0xffffffff);
7248 dead_tmp(tmp);
7249 s->is_jmp = DISAS_UPDATE;
7252 break;
7253 case 0xa:
7254 case 0xb:
7256 int32_t offset;
7258 /* branch (and link) */
7259 val = (int32_t)s->pc;
7260 if (insn & (1 << 24)) {
7261 tmp = new_tmp();
7262 tcg_gen_movi_i32(tmp, val);
7263 store_reg(s, 14, tmp);
7265 offset = (((int32_t)insn << 8) >> 8);
7266 val += (offset << 2) + 4;
7267 gen_jmp(s, val);
7269 break;
7270 case 0xc:
7271 case 0xd:
7272 case 0xe:
7273 /* Coprocessor. */
7274 if (disas_coproc_insn(env, s, insn))
7275 goto illegal_op;
7276 break;
7277 case 0xf:
7278 /* swi */
7279 gen_set_pc_im(s->pc);
7280 s->is_jmp = DISAS_SWI;
7281 break;
7282 default:
7283 illegal_op:
7284 gen_set_condexec(s);
7285 gen_set_pc_im(s->pc - 4);
7286 gen_exception(EXCP_UDEF);
7287 s->is_jmp = DISAS_JUMP;
7288 break;
7293 /* Return true if this is a Thumb-2 logical op. */
7294 static int
7295 thumb2_logic_op(int op)
7297 return (op < 8);
7300 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7301 then set condition code flags based on the result of the operation.
7302 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7303 to the high bit of T1.
7304 Returns zero if the opcode is valid. */
7306 static int
7307 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCGv t0, TCGv t1)
7309 int logic_cc;
7311 logic_cc = 0;
7312 switch (op) {
7313 case 0: /* and */
7314 tcg_gen_and_i32(t0, t0, t1);
7315 logic_cc = conds;
7316 break;
7317 case 1: /* bic */
7318 tcg_gen_andc_i32(t0, t0, t1);
7319 logic_cc = conds;
7320 break;
7321 case 2: /* orr */
7322 tcg_gen_or_i32(t0, t0, t1);
7323 logic_cc = conds;
7324 break;
7325 case 3: /* orn */
7326 tcg_gen_not_i32(t1, t1);
7327 tcg_gen_or_i32(t0, t0, t1);
7328 logic_cc = conds;
7329 break;
7330 case 4: /* eor */
7331 tcg_gen_xor_i32(t0, t0, t1);
7332 logic_cc = conds;
7333 break;
7334 case 8: /* add */
7335 if (conds)
7336 gen_helper_add_cc(t0, t0, t1);
7337 else
7338 tcg_gen_add_i32(t0, t0, t1);
7339 break;
7340 case 10: /* adc */
7341 if (conds)
7342 gen_helper_adc_cc(t0, t0, t1);
7343 else
7344 gen_adc(t0, t1);
7345 break;
7346 case 11: /* sbc */
7347 if (conds)
7348 gen_helper_sbc_cc(t0, t0, t1);
7349 else
7350 gen_sub_carry(t0, t0, t1);
7351 break;
7352 case 13: /* sub */
7353 if (conds)
7354 gen_helper_sub_cc(t0, t0, t1);
7355 else
7356 tcg_gen_sub_i32(t0, t0, t1);
7357 break;
7358 case 14: /* rsb */
7359 if (conds)
7360 gen_helper_sub_cc(t0, t1, t0);
7361 else
7362 tcg_gen_sub_i32(t0, t1, t0);
7363 break;
7364 default: /* 5, 6, 7, 9, 12, 15. */
7365 return 1;
7367 if (logic_cc) {
7368 gen_logic_CC(t0);
7369 if (shifter_out)
7370 gen_set_CF_bit31(t1);
7372 return 0;
7375 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7376 is not legal. */
7377 static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7379 uint32_t insn, imm, shift, offset;
7380 uint32_t rd, rn, rm, rs;
7381 TCGv tmp;
7382 TCGv tmp2;
7383 TCGv tmp3;
7384 TCGv addr;
7385 TCGv_i64 tmp64;
7386 int op;
7387 int shiftop;
7388 int conds;
7389 int logic_cc;
7391 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
7392 || arm_feature (env, ARM_FEATURE_M))) {
7393 /* Thumb-1 cores may need to treat bl and blx as a pair of
7394 16-bit instructions to get correct prefetch abort behavior. */
7395 insn = insn_hw1;
7396 if ((insn & (1 << 12)) == 0) {
7397 /* Second half of blx. */
7398 offset = ((insn & 0x7ff) << 1);
7399 tmp = load_reg(s, 14);
7400 tcg_gen_addi_i32(tmp, tmp, offset);
7401 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
7403 tmp2 = new_tmp();
7404 tcg_gen_movi_i32(tmp2, s->pc | 1);
7405 store_reg(s, 14, tmp2);
7406 gen_bx(s, tmp);
7407 return 0;
7409 if (insn & (1 << 11)) {
7410 /* Second half of bl. */
7411 offset = ((insn & 0x7ff) << 1) | 1;
7412 tmp = load_reg(s, 14);
7413 tcg_gen_addi_i32(tmp, tmp, offset);
7415 tmp2 = new_tmp();
7416 tcg_gen_movi_i32(tmp2, s->pc | 1);
7417 store_reg(s, 14, tmp2);
7418 gen_bx(s, tmp);
7419 return 0;
7421 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
7422 /* Instruction spans a page boundary. Implement it as two
7423 16-bit instructions in case the second half causes an
7424 prefetch abort. */
7425 offset = ((int32_t)insn << 21) >> 9;
7426 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
7427 return 0;
7429 /* Fall through to 32-bit decode. */
7432 insn = lduw_code(s->pc);
7433 s->pc += 2;
7434 insn |= (uint32_t)insn_hw1 << 16;
7436 if ((insn & 0xf800e800) != 0xf000e800) {
7437 ARCH(6T2);
7440 rn = (insn >> 16) & 0xf;
7441 rs = (insn >> 12) & 0xf;
7442 rd = (insn >> 8) & 0xf;
7443 rm = insn & 0xf;
7444 switch ((insn >> 25) & 0xf) {
7445 case 0: case 1: case 2: case 3:
7446 /* 16-bit instructions. Should never happen. */
7447 abort();
7448 case 4:
7449 if (insn & (1 << 22)) {
7450 /* Other load/store, table branch. */
7451 if (insn & 0x01200000) {
7452 /* Load/store doubleword. */
7453 if (rn == 15) {
7454 addr = new_tmp();
7455 tcg_gen_movi_i32(addr, s->pc & ~3);
7456 } else {
7457 addr = load_reg(s, rn);
7459 offset = (insn & 0xff) * 4;
7460 if ((insn & (1 << 23)) == 0)
7461 offset = -offset;
7462 if (insn & (1 << 24)) {
7463 tcg_gen_addi_i32(addr, addr, offset);
7464 offset = 0;
7466 if (insn & (1 << 20)) {
7467 /* ldrd */
7468 tmp = gen_ld32(addr, IS_USER(s));
7469 store_reg(s, rs, tmp);
7470 tcg_gen_addi_i32(addr, addr, 4);
7471 tmp = gen_ld32(addr, IS_USER(s));
7472 store_reg(s, rd, tmp);
7473 } else {
7474 /* strd */
7475 tmp = load_reg(s, rs);
7476 gen_st32(tmp, addr, IS_USER(s));
7477 tcg_gen_addi_i32(addr, addr, 4);
7478 tmp = load_reg(s, rd);
7479 gen_st32(tmp, addr, IS_USER(s));
7481 if (insn & (1 << 21)) {
7482 /* Base writeback. */
7483 if (rn == 15)
7484 goto illegal_op;
7485 tcg_gen_addi_i32(addr, addr, offset - 4);
7486 store_reg(s, rn, addr);
7487 } else {
7488 dead_tmp(addr);
7490 } else if ((insn & (1 << 23)) == 0) {
7491 /* Load/store exclusive word. */
7492 addr = tcg_temp_local_new();
7493 load_reg_var(s, addr, rn);
7494 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
7495 if (insn & (1 << 20)) {
7496 gen_load_exclusive(s, rs, 15, addr, 2);
7497 } else {
7498 gen_store_exclusive(s, rd, rs, 15, addr, 2);
7500 tcg_temp_free(addr);
7501 } else if ((insn & (1 << 6)) == 0) {
7502 /* Table Branch. */
7503 if (rn == 15) {
7504 addr = new_tmp();
7505 tcg_gen_movi_i32(addr, s->pc);
7506 } else {
7507 addr = load_reg(s, rn);
7509 tmp = load_reg(s, rm);
7510 tcg_gen_add_i32(addr, addr, tmp);
7511 if (insn & (1 << 4)) {
7512 /* tbh */
7513 tcg_gen_add_i32(addr, addr, tmp);
7514 dead_tmp(tmp);
7515 tmp = gen_ld16u(addr, IS_USER(s));
7516 } else { /* tbb */
7517 dead_tmp(tmp);
7518 tmp = gen_ld8u(addr, IS_USER(s));
7520 dead_tmp(addr);
7521 tcg_gen_shli_i32(tmp, tmp, 1);
7522 tcg_gen_addi_i32(tmp, tmp, s->pc);
7523 store_reg(s, 15, tmp);
7524 } else {
7525 /* Load/store exclusive byte/halfword/doubleword. */
7526 ARCH(7);
7527 op = (insn >> 4) & 0x3;
7528 if (op == 2) {
7529 goto illegal_op;
7531 addr = tcg_temp_local_new();
7532 load_reg_var(s, addr, rn);
7533 if (insn & (1 << 20)) {
7534 gen_load_exclusive(s, rs, rd, addr, op);
7535 } else {
7536 gen_store_exclusive(s, rm, rs, rd, addr, op);
7538 tcg_temp_free(addr);
7540 } else {
7541 /* Load/store multiple, RFE, SRS. */
7542 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
7543 /* Not available in user mode. */
7544 if (IS_USER(s))
7545 goto illegal_op;
7546 if (insn & (1 << 20)) {
7547 /* rfe */
7548 addr = load_reg(s, rn);
7549 if ((insn & (1 << 24)) == 0)
7550 tcg_gen_addi_i32(addr, addr, -8);
7551 /* Load PC into tmp and CPSR into tmp2. */
7552 tmp = gen_ld32(addr, 0);
7553 tcg_gen_addi_i32(addr, addr, 4);
7554 tmp2 = gen_ld32(addr, 0);
7555 if (insn & (1 << 21)) {
7556 /* Base writeback. */
7557 if (insn & (1 << 24)) {
7558 tcg_gen_addi_i32(addr, addr, 4);
7559 } else {
7560 tcg_gen_addi_i32(addr, addr, -4);
7562 store_reg(s, rn, addr);
7563 } else {
7564 dead_tmp(addr);
7566 gen_rfe(s, tmp, tmp2);
7567 } else {
7568 /* srs */
7569 op = (insn & 0x1f);
7570 addr = new_tmp();
7571 tmp = tcg_const_i32(op);
7572 gen_helper_get_r13_banked(addr, cpu_env, tmp);
7573 tcg_temp_free_i32(tmp);
7574 if ((insn & (1 << 24)) == 0) {
7575 tcg_gen_addi_i32(addr, addr, -8);
7577 tmp = load_reg(s, 14);
7578 gen_st32(tmp, addr, 0);
7579 tcg_gen_addi_i32(addr, addr, 4);
7580 tmp = new_tmp();
7581 gen_helper_cpsr_read(tmp);
7582 gen_st32(tmp, addr, 0);
7583 if (insn & (1 << 21)) {
7584 if ((insn & (1 << 24)) == 0) {
7585 tcg_gen_addi_i32(addr, addr, -4);
7586 } else {
7587 tcg_gen_addi_i32(addr, addr, 4);
7589 tmp = tcg_const_i32(op);
7590 gen_helper_set_r13_banked(cpu_env, tmp, addr);
7591 tcg_temp_free_i32(tmp);
7592 } else {
7593 dead_tmp(addr);
7596 } else {
7597 int i;
7598 /* Load/store multiple. */
7599 addr = load_reg(s, rn);
7600 offset = 0;
7601 for (i = 0; i < 16; i++) {
7602 if (insn & (1 << i))
7603 offset += 4;
7605 if (insn & (1 << 24)) {
7606 tcg_gen_addi_i32(addr, addr, -offset);
7609 for (i = 0; i < 16; i++) {
7610 if ((insn & (1 << i)) == 0)
7611 continue;
7612 if (insn & (1 << 20)) {
7613 /* Load. */
7614 tmp = gen_ld32(addr, IS_USER(s));
7615 if (i == 15) {
7616 gen_bx(s, tmp);
7617 } else {
7618 store_reg(s, i, tmp);
7620 } else {
7621 /* Store. */
7622 tmp = load_reg(s, i);
7623 gen_st32(tmp, addr, IS_USER(s));
7625 tcg_gen_addi_i32(addr, addr, 4);
7627 if (insn & (1 << 21)) {
7628 /* Base register writeback. */
7629 if (insn & (1 << 24)) {
7630 tcg_gen_addi_i32(addr, addr, -offset);
7632 /* Fault if writeback register is in register list. */
7633 if (insn & (1 << rn))
7634 goto illegal_op;
7635 store_reg(s, rn, addr);
7636 } else {
7637 dead_tmp(addr);
7641 break;
7642 case 5:
7644 op = (insn >> 21) & 0xf;
7645 if (op == 6) {
7646 /* Halfword pack. */
7647 tmp = load_reg(s, rn);
7648 tmp2 = load_reg(s, rm);
7649 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
7650 if (insn & (1 << 5)) {
7651 /* pkhtb */
7652 if (shift == 0)
7653 shift = 31;
7654 tcg_gen_sari_i32(tmp2, tmp2, shift);
7655 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
7656 tcg_gen_ext16u_i32(tmp2, tmp2);
7657 } else {
7658 /* pkhbt */
7659 if (shift)
7660 tcg_gen_shli_i32(tmp2, tmp2, shift);
7661 tcg_gen_ext16u_i32(tmp, tmp);
7662 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
7664 tcg_gen_or_i32(tmp, tmp, tmp2);
7665 dead_tmp(tmp2);
7666 store_reg(s, rd, tmp);
7667 } else {
7668 /* Data processing register constant shift. */
7669 if (rn == 15) {
7670 tmp = new_tmp();
7671 tcg_gen_movi_i32(tmp, 0);
7672 } else {
7673 tmp = load_reg(s, rn);
7675 tmp2 = load_reg(s, rm);
7677 shiftop = (insn >> 4) & 3;
7678 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7679 conds = (insn & (1 << 20)) != 0;
7680 logic_cc = (conds && thumb2_logic_op(op));
7681 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
7682 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
7683 goto illegal_op;
7684 dead_tmp(tmp2);
7685 if (rd != 15) {
7686 store_reg(s, rd, tmp);
7687 } else {
7688 dead_tmp(tmp);
7691 break;
7692 case 13: /* Misc data processing. */
7693 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
7694 if (op < 4 && (insn & 0xf000) != 0xf000)
7695 goto illegal_op;
7696 switch (op) {
7697 case 0: /* Register controlled shift. */
7698 tmp = load_reg(s, rn);
7699 tmp2 = load_reg(s, rm);
7700 if ((insn & 0x70) != 0)
7701 goto illegal_op;
7702 op = (insn >> 21) & 3;
7703 logic_cc = (insn & (1 << 20)) != 0;
7704 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
7705 if (logic_cc)
7706 gen_logic_CC(tmp);
7707 store_reg_bx(env, s, rd, tmp);
7708 break;
7709 case 1: /* Sign/zero extend. */
7710 tmp = load_reg(s, rm);
7711 shift = (insn >> 4) & 3;
7712 /* ??? In many cases it's not neccessary to do a
7713 rotate, a shift is sufficient. */
7714 if (shift != 0)
7715 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
7716 op = (insn >> 20) & 7;
7717 switch (op) {
7718 case 0: gen_sxth(tmp); break;
7719 case 1: gen_uxth(tmp); break;
7720 case 2: gen_sxtb16(tmp); break;
7721 case 3: gen_uxtb16(tmp); break;
7722 case 4: gen_sxtb(tmp); break;
7723 case 5: gen_uxtb(tmp); break;
7724 default: goto illegal_op;
7726 if (rn != 15) {
7727 tmp2 = load_reg(s, rn);
7728 if ((op >> 1) == 1) {
7729 gen_add16(tmp, tmp2);
7730 } else {
7731 tcg_gen_add_i32(tmp, tmp, tmp2);
7732 dead_tmp(tmp2);
7735 store_reg(s, rd, tmp);
7736 break;
7737 case 2: /* SIMD add/subtract. */
7738 op = (insn >> 20) & 7;
7739 shift = (insn >> 4) & 7;
7740 if ((op & 3) == 3 || (shift & 3) == 3)
7741 goto illegal_op;
7742 tmp = load_reg(s, rn);
7743 tmp2 = load_reg(s, rm);
7744 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7745 dead_tmp(tmp2);
7746 store_reg(s, rd, tmp);
7747 break;
7748 case 3: /* Other data processing. */
7749 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
7750 if (op < 4) {
7751 /* Saturating add/subtract. */
7752 tmp = load_reg(s, rn);
7753 tmp2 = load_reg(s, rm);
7754 if (op & 1)
7755 gen_helper_double_saturate(tmp, tmp);
7756 if (op & 2)
7757 gen_helper_sub_saturate(tmp, tmp2, tmp);
7758 else
7759 gen_helper_add_saturate(tmp, tmp, tmp2);
7760 dead_tmp(tmp2);
7761 } else {
7762 tmp = load_reg(s, rn);
7763 switch (op) {
7764 case 0x0a: /* rbit */
7765 gen_helper_rbit(tmp, tmp);
7766 break;
7767 case 0x08: /* rev */
7768 tcg_gen_bswap32_i32(tmp, tmp);
7769 break;
7770 case 0x09: /* rev16 */
7771 gen_rev16(tmp);
7772 break;
7773 case 0x0b: /* revsh */
7774 gen_revsh(tmp);
7775 break;
7776 case 0x10: /* sel */
7777 tmp2 = load_reg(s, rm);
7778 tmp3 = new_tmp();
7779 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
7780 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7781 dead_tmp(tmp3);
7782 dead_tmp(tmp2);
7783 break;
7784 case 0x18: /* clz */
7785 gen_helper_clz(tmp, tmp);
7786 break;
7787 default:
7788 goto illegal_op;
7791 store_reg(s, rd, tmp);
7792 break;
7793 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7794 op = (insn >> 4) & 0xf;
7795 tmp = load_reg(s, rn);
7796 tmp2 = load_reg(s, rm);
7797 switch ((insn >> 20) & 7) {
7798 case 0: /* 32 x 32 -> 32 */
7799 tcg_gen_mul_i32(tmp, tmp, tmp2);
7800 dead_tmp(tmp2);
7801 if (rs != 15) {
7802 tmp2 = load_reg(s, rs);
7803 if (op)
7804 tcg_gen_sub_i32(tmp, tmp2, tmp);
7805 else
7806 tcg_gen_add_i32(tmp, tmp, tmp2);
7807 dead_tmp(tmp2);
7809 break;
7810 case 1: /* 16 x 16 -> 32 */
7811 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7812 dead_tmp(tmp2);
7813 if (rs != 15) {
7814 tmp2 = load_reg(s, rs);
7815 gen_helper_add_setq(tmp, tmp, tmp2);
7816 dead_tmp(tmp2);
7818 break;
7819 case 2: /* Dual multiply add. */
7820 case 4: /* Dual multiply subtract. */
7821 if (op)
7822 gen_swap_half(tmp2);
7823 gen_smul_dual(tmp, tmp2);
7824 /* This addition cannot overflow. */
7825 if (insn & (1 << 22)) {
7826 tcg_gen_sub_i32(tmp, tmp, tmp2);
7827 } else {
7828 tcg_gen_add_i32(tmp, tmp, tmp2);
7830 dead_tmp(tmp2);
7831 if (rs != 15)
7833 tmp2 = load_reg(s, rs);
7834 gen_helper_add_setq(tmp, tmp, tmp2);
7835 dead_tmp(tmp2);
7837 break;
7838 case 3: /* 32 * 16 -> 32msb */
7839 if (op)
7840 tcg_gen_sari_i32(tmp2, tmp2, 16);
7841 else
7842 gen_sxth(tmp2);
7843 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7844 tcg_gen_shri_i64(tmp64, tmp64, 16);
7845 tmp = new_tmp();
7846 tcg_gen_trunc_i64_i32(tmp, tmp64);
7847 tcg_temp_free_i64(tmp64);
7848 if (rs != 15)
7850 tmp2 = load_reg(s, rs);
7851 gen_helper_add_setq(tmp, tmp, tmp2);
7852 dead_tmp(tmp2);
7854 break;
7855 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
7856 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7857 if (rs != 15) {
7858 tmp = load_reg(s, rs);
7859 if (insn & (1 << 20)) {
7860 tmp64 = gen_addq_msw(tmp64, tmp);
7861 } else {
7862 tmp64 = gen_subq_msw(tmp64, tmp);
7865 if (insn & (1 << 4)) {
7866 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
7868 tcg_gen_shri_i64(tmp64, tmp64, 32);
7869 tmp = new_tmp();
7870 tcg_gen_trunc_i64_i32(tmp, tmp64);
7871 tcg_temp_free_i64(tmp64);
7872 break;
7873 case 7: /* Unsigned sum of absolute differences. */
7874 gen_helper_usad8(tmp, tmp, tmp2);
7875 dead_tmp(tmp2);
7876 if (rs != 15) {
7877 tmp2 = load_reg(s, rs);
7878 tcg_gen_add_i32(tmp, tmp, tmp2);
7879 dead_tmp(tmp2);
7881 break;
7883 store_reg(s, rd, tmp);
7884 break;
7885 case 6: case 7: /* 64-bit multiply, Divide. */
7886 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
7887 tmp = load_reg(s, rn);
7888 tmp2 = load_reg(s, rm);
7889 if ((op & 0x50) == 0x10) {
7890 /* sdiv, udiv */
7891 if (!arm_feature(env, ARM_FEATURE_DIV))
7892 goto illegal_op;
7893 if (op & 0x20)
7894 gen_helper_udiv(tmp, tmp, tmp2);
7895 else
7896 gen_helper_sdiv(tmp, tmp, tmp2);
7897 dead_tmp(tmp2);
7898 store_reg(s, rd, tmp);
7899 } else if ((op & 0xe) == 0xc) {
7900 /* Dual multiply accumulate long. */
7901 if (op & 1)
7902 gen_swap_half(tmp2);
7903 gen_smul_dual(tmp, tmp2);
7904 if (op & 0x10) {
7905 tcg_gen_sub_i32(tmp, tmp, tmp2);
7906 } else {
7907 tcg_gen_add_i32(tmp, tmp, tmp2);
7909 dead_tmp(tmp2);
7910 /* BUGFIX */
7911 tmp64 = tcg_temp_new_i64();
7912 tcg_gen_ext_i32_i64(tmp64, tmp);
7913 dead_tmp(tmp);
7914 gen_addq(s, tmp64, rs, rd);
7915 gen_storeq_reg(s, rs, rd, tmp64);
7916 tcg_temp_free_i64(tmp64);
7917 } else {
7918 if (op & 0x20) {
7919 /* Unsigned 64-bit multiply */
7920 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7921 } else {
7922 if (op & 8) {
7923 /* smlalxy */
7924 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7925 dead_tmp(tmp2);
7926 tmp64 = tcg_temp_new_i64();
7927 tcg_gen_ext_i32_i64(tmp64, tmp);
7928 dead_tmp(tmp);
7929 } else {
7930 /* Signed 64-bit multiply */
7931 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7934 if (op & 4) {
7935 /* umaal */
7936 gen_addq_lo(s, tmp64, rs);
7937 gen_addq_lo(s, tmp64, rd);
7938 } else if (op & 0x40) {
7939 /* 64-bit accumulate. */
7940 gen_addq(s, tmp64, rs, rd);
7942 gen_storeq_reg(s, rs, rd, tmp64);
7943 tcg_temp_free_i64(tmp64);
7945 break;
7947 break;
7948 case 6: case 7: case 14: case 15:
7949 /* Coprocessor. */
7950 if (((insn >> 24) & 3) == 3) {
7951 /* Translate into the equivalent ARM encoding. */
7952 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);
7953 if (disas_neon_data_insn(env, s, insn))
7954 goto illegal_op;
7955 } else {
7956 if (insn & (1 << 28))
7957 goto illegal_op;
7958 if (disas_coproc_insn (env, s, insn))
7959 goto illegal_op;
7961 break;
7962 case 8: case 9: case 10: case 11:
7963 if (insn & (1 << 15)) {
7964 /* Branches, misc control. */
7965 if (insn & 0x5000) {
7966 /* Unconditional branch. */
7967 /* signextend(hw1[10:0]) -> offset[:12]. */
7968 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
7969 /* hw1[10:0] -> offset[11:1]. */
7970 offset |= (insn & 0x7ff) << 1;
7971 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7972 offset[24:22] already have the same value because of the
7973 sign extension above. */
7974 offset ^= ((~insn) & (1 << 13)) << 10;
7975 offset ^= ((~insn) & (1 << 11)) << 11;
7977 if (insn & (1 << 14)) {
7978 /* Branch and link. */
7979 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
7982 offset += s->pc;
7983 if (insn & (1 << 12)) {
7984 /* b/bl */
7985 gen_jmp(s, offset);
7986 } else {
7987 /* blx */
7988 offset &= ~(uint32_t)2;
7989 gen_bx_im(s, offset);
7991 } else if (((insn >> 23) & 7) == 7) {
7992 /* Misc control */
7993 if (insn & (1 << 13))
7994 goto illegal_op;
7996 if (insn & (1 << 26)) {
7997 /* Secure monitor call (v6Z) */
7998 goto illegal_op; /* not implemented. */
7999 } else {
8000 op = (insn >> 20) & 7;
8001 switch (op) {
8002 case 0: /* msr cpsr. */
8003 if (IS_M(env)) {
8004 tmp = load_reg(s, rn);
8005 addr = tcg_const_i32(insn & 0xff);
8006 gen_helper_v7m_msr(cpu_env, addr, tmp);
8007 tcg_temp_free_i32(addr);
8008 dead_tmp(tmp);
8009 gen_lookup_tb(s);
8010 break;
8012 /* fall through */
8013 case 1: /* msr spsr. */
8014 if (IS_M(env))
8015 goto illegal_op;
8016 tmp = load_reg(s, rn);
8017 if (gen_set_psr(s,
8018 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
8019 op == 1, tmp))
8020 goto illegal_op;
8021 break;
8022 case 2: /* cps, nop-hint. */
8023 if (((insn >> 8) & 7) == 0) {
8024 gen_nop_hint(s, insn & 0xff);
8026 /* Implemented as NOP in user mode. */
8027 if (IS_USER(s))
8028 break;
8029 offset = 0;
8030 imm = 0;
8031 if (insn & (1 << 10)) {
8032 if (insn & (1 << 7))
8033 offset |= CPSR_A;
8034 if (insn & (1 << 6))
8035 offset |= CPSR_I;
8036 if (insn & (1 << 5))
8037 offset |= CPSR_F;
8038 if (insn & (1 << 9))
8039 imm = CPSR_A | CPSR_I | CPSR_F;
8041 if (insn & (1 << 8)) {
8042 offset |= 0x1f;
8043 imm |= (insn & 0x1f);
8045 if (offset) {
8046 gen_set_psr_im(s, offset, 0, imm);
8048 break;
8049 case 3: /* Special control operations. */
8050 ARCH(7);
8051 op = (insn >> 4) & 0xf;
8052 switch (op) {
8053 case 2: /* clrex */
8054 gen_clrex(s);
8055 break;
8056 case 4: /* dsb */
8057 case 5: /* dmb */
8058 case 6: /* isb */
8059 /* These execute as NOPs. */
8060 break;
8061 default:
8062 goto illegal_op;
8064 break;
8065 case 4: /* bxj */
8066 /* Trivial implementation equivalent to bx. */
8067 tmp = load_reg(s, rn);
8068 gen_bx(s, tmp);
8069 break;
8070 case 5: /* Exception return. */
8071 if (IS_USER(s)) {
8072 goto illegal_op;
8074 if (rn != 14 || rd != 15) {
8075 goto illegal_op;
8077 tmp = load_reg(s, rn);
8078 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
8079 gen_exception_return(s, tmp);
8080 break;
8081 case 6: /* mrs cpsr. */
8082 tmp = new_tmp();
8083 if (IS_M(env)) {
8084 addr = tcg_const_i32(insn & 0xff);
8085 gen_helper_v7m_mrs(tmp, cpu_env, addr);
8086 tcg_temp_free_i32(addr);
8087 } else {
8088 gen_helper_cpsr_read(tmp);
8090 store_reg(s, rd, tmp);
8091 break;
8092 case 7: /* mrs spsr. */
8093 /* Not accessible in user mode. */
8094 if (IS_USER(s) || IS_M(env))
8095 goto illegal_op;
8096 tmp = load_cpu_field(spsr);
8097 store_reg(s, rd, tmp);
8098 break;
8101 } else {
8102 /* Conditional branch. */
8103 op = (insn >> 22) & 0xf;
8104 /* Generate a conditional jump to next instruction. */
8105 s->condlabel = gen_new_label();
8106 gen_test_cc(op ^ 1, s->condlabel);
8107 s->condjmp = 1;
8109 /* offset[11:1] = insn[10:0] */
8110 offset = (insn & 0x7ff) << 1;
8111 /* offset[17:12] = insn[21:16]. */
8112 offset |= (insn & 0x003f0000) >> 4;
8113 /* offset[31:20] = insn[26]. */
8114 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
8115 /* offset[18] = insn[13]. */
8116 offset |= (insn & (1 << 13)) << 5;
8117 /* offset[19] = insn[11]. */
8118 offset |= (insn & (1 << 11)) << 8;
8120 /* jump to the offset */
8121 gen_jmp(s, s->pc + offset);
8123 } else {
8124 /* Data processing immediate. */
8125 if (insn & (1 << 25)) {
8126 if (insn & (1 << 24)) {
8127 if (insn & (1 << 20))
8128 goto illegal_op;
8129 /* Bitfield/Saturate. */
8130 op = (insn >> 21) & 7;
8131 imm = insn & 0x1f;
8132 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
8133 if (rn == 15) {
8134 tmp = new_tmp();
8135 tcg_gen_movi_i32(tmp, 0);
8136 } else {
8137 tmp = load_reg(s, rn);
8139 switch (op) {
8140 case 2: /* Signed bitfield extract. */
8141 imm++;
8142 if (shift + imm > 32)
8143 goto illegal_op;
8144 if (imm < 32)
8145 gen_sbfx(tmp, shift, imm);
8146 break;
8147 case 6: /* Unsigned bitfield extract. */
8148 imm++;
8149 if (shift + imm > 32)
8150 goto illegal_op;
8151 if (imm < 32)
8152 gen_ubfx(tmp, shift, (1u << imm) - 1);
8153 break;
8154 case 3: /* Bitfield insert/clear. */
8155 if (imm < shift)
8156 goto illegal_op;
8157 imm = imm + 1 - shift;
8158 if (imm != 32) {
8159 tmp2 = load_reg(s, rd);
8160 gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
8161 dead_tmp(tmp2);
8163 break;
8164 case 7:
8165 goto illegal_op;
8166 default: /* Saturate. */
8167 if (shift) {
8168 if (op & 1)
8169 tcg_gen_sari_i32(tmp, tmp, shift);
8170 else
8171 tcg_gen_shli_i32(tmp, tmp, shift);
8173 tmp2 = tcg_const_i32(imm);
8174 if (op & 4) {
8175 /* Unsigned. */
8176 if ((op & 1) && shift == 0)
8177 gen_helper_usat16(tmp, tmp, tmp2);
8178 else
8179 gen_helper_usat(tmp, tmp, tmp2);
8180 } else {
8181 /* Signed. */
8182 if ((op & 1) && shift == 0)
8183 gen_helper_ssat16(tmp, tmp, tmp2);
8184 else
8185 gen_helper_ssat(tmp, tmp, tmp2);
8187 tcg_temp_free_i32(tmp2);
8188 break;
8190 store_reg(s, rd, tmp);
8191 } else {
8192 imm = ((insn & 0x04000000) >> 15)
8193 | ((insn & 0x7000) >> 4) | (insn & 0xff);
8194 if (insn & (1 << 22)) {
8195 /* 16-bit immediate. */
8196 imm |= (insn >> 4) & 0xf000;
8197 if (insn & (1 << 23)) {
8198 /* movt */
8199 tmp = load_reg(s, rd);
8200 tcg_gen_ext16u_i32(tmp, tmp);
8201 tcg_gen_ori_i32(tmp, tmp, imm << 16);
8202 } else {
8203 /* movw */
8204 tmp = new_tmp();
8205 tcg_gen_movi_i32(tmp, imm);
8207 } else {
8208 /* Add/sub 12-bit immediate. */
8209 if (rn == 15) {
8210 offset = s->pc & ~(uint32_t)3;
8211 if (insn & (1 << 23))
8212 offset -= imm;
8213 else
8214 offset += imm;
8215 tmp = new_tmp();
8216 tcg_gen_movi_i32(tmp, offset);
8217 } else {
8218 tmp = load_reg(s, rn);
8219 if (insn & (1 << 23))
8220 tcg_gen_subi_i32(tmp, tmp, imm);
8221 else
8222 tcg_gen_addi_i32(tmp, tmp, imm);
8225 store_reg(s, rd, tmp);
8227 } else {
8228 int shifter_out = 0;
8229 /* modified 12-bit immediate. */
8230 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
8231 imm = (insn & 0xff);
8232 switch (shift) {
8233 case 0: /* XY */
8234 /* Nothing to do. */
8235 break;
8236 case 1: /* 00XY00XY */
8237 imm |= imm << 16;
8238 break;
8239 case 2: /* XY00XY00 */
8240 imm |= imm << 16;
8241 imm <<= 8;
8242 break;
8243 case 3: /* XYXYXYXY */
8244 imm |= imm << 16;
8245 imm |= imm << 8;
8246 break;
8247 default: /* Rotated constant. */
8248 shift = (shift << 1) | (imm >> 7);
8249 imm |= 0x80;
8250 imm = imm << (32 - shift);
8251 shifter_out = 1;
8252 break;
8254 tmp2 = new_tmp();
8255 tcg_gen_movi_i32(tmp2, imm);
8256 rn = (insn >> 16) & 0xf;
8257 if (rn == 15) {
8258 tmp = new_tmp();
8259 tcg_gen_movi_i32(tmp, 0);
8260 } else {
8261 tmp = load_reg(s, rn);
8263 op = (insn >> 21) & 0xf;
8264 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
8265 shifter_out, tmp, tmp2))
8266 goto illegal_op;
8267 dead_tmp(tmp2);
8268 rd = (insn >> 8) & 0xf;
8269 if (rd != 15) {
8270 store_reg(s, rd, tmp);
8271 } else {
8272 dead_tmp(tmp);
8276 break;
8277 case 12: /* Load/store single data item. */
8279 int postinc = 0;
8280 int writeback = 0;
8281 int user;
8282 if ((insn & 0x01100000) == 0x01000000) {
8283 if (disas_neon_ls_insn(env, s, insn))
8284 goto illegal_op;
8285 break;
8287 user = IS_USER(s);
8288 if (rn == 15) {
8289 addr = new_tmp();
8290 /* PC relative. */
8291 /* s->pc has already been incremented by 4. */
8292 imm = s->pc & 0xfffffffc;
8293 if (insn & (1 << 23))
8294 imm += insn & 0xfff;
8295 else
8296 imm -= insn & 0xfff;
8297 tcg_gen_movi_i32(addr, imm);
8298 } else {
8299 addr = load_reg(s, rn);
8300 if (insn & (1 << 23)) {
8301 /* Positive offset. */
8302 imm = insn & 0xfff;
8303 tcg_gen_addi_i32(addr, addr, imm);
8304 } else {
8305 op = (insn >> 8) & 7;
8306 imm = insn & 0xff;
8307 switch (op) {
8308 case 0: case 8: /* Shifted Register. */
8309 shift = (insn >> 4) & 0xf;
8310 if (shift > 3)
8311 goto illegal_op;
8312 tmp = load_reg(s, rm);
8313 if (shift)
8314 tcg_gen_shli_i32(tmp, tmp, shift);
8315 tcg_gen_add_i32(addr, addr, tmp);
8316 dead_tmp(tmp);
8317 break;
8318 case 4: /* Negative offset. */
8319 tcg_gen_addi_i32(addr, addr, -imm);
8320 break;
8321 case 6: /* User privilege. */
8322 tcg_gen_addi_i32(addr, addr, imm);
8323 user = 1;
8324 break;
8325 case 1: /* Post-decrement. */
8326 imm = -imm;
8327 /* Fall through. */
8328 case 3: /* Post-increment. */
8329 postinc = 1;
8330 writeback = 1;
8331 break;
8332 case 5: /* Pre-decrement. */
8333 imm = -imm;
8334 /* Fall through. */
8335 case 7: /* Pre-increment. */
8336 tcg_gen_addi_i32(addr, addr, imm);
8337 writeback = 1;
8338 break;
8339 default:
8340 goto illegal_op;
8344 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
8345 if (insn & (1 << 20)) {
8346 /* Load. */
8347 if (rs == 15 && op != 2) {
8348 if (op & 2)
8349 goto illegal_op;
8350 /* Memory hint. Implemented as NOP. */
8351 } else {
8352 switch (op) {
8353 case 0: tmp = gen_ld8u(addr, user); break;
8354 case 4: tmp = gen_ld8s(addr, user); break;
8355 case 1: tmp = gen_ld16u(addr, user); break;
8356 case 5: tmp = gen_ld16s(addr, user); break;
8357 case 2: tmp = gen_ld32(addr, user); break;
8358 default: goto illegal_op;
8360 if (rs == 15) {
8361 gen_bx(s, tmp);
8362 } else {
8363 store_reg(s, rs, tmp);
8366 } else {
8367 /* Store. */
8368 if (rs == 15)
8369 goto illegal_op;
8370 tmp = load_reg(s, rs);
8371 switch (op) {
8372 case 0: gen_st8(tmp, addr, user); break;
8373 case 1: gen_st16(tmp, addr, user); break;
8374 case 2: gen_st32(tmp, addr, user); break;
8375 default: goto illegal_op;
8378 if (postinc)
8379 tcg_gen_addi_i32(addr, addr, imm);
8380 if (writeback) {
8381 store_reg(s, rn, addr);
8382 } else {
8383 dead_tmp(addr);
8386 break;
8387 default:
8388 goto illegal_op;
8390 return 0;
8391 illegal_op:
8392 return 1;
8395 static void disas_thumb_insn(CPUState *env, DisasContext *s)
8397 uint32_t val, insn, op, rm, rn, rd, shift, cond;
8398 int32_t offset;
8399 int i;
8400 TCGv tmp;
8401 TCGv tmp2;
8402 TCGv addr;
8404 if (s->condexec_mask) {
8405 cond = s->condexec_cond;
8406 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
8407 s->condlabel = gen_new_label();
8408 gen_test_cc(cond ^ 1, s->condlabel);
8409 s->condjmp = 1;
8413 insn = lduw_code(s->pc);
8414 s->pc += 2;
8416 switch (insn >> 12) {
8417 case 0: case 1:
8419 rd = insn & 7;
8420 op = (insn >> 11) & 3;
8421 if (op == 3) {
8422 /* add/subtract */
8423 rn = (insn >> 3) & 7;
8424 tmp = load_reg(s, rn);
8425 if (insn & (1 << 10)) {
8426 /* immediate */
8427 tmp2 = new_tmp();
8428 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
8429 } else {
8430 /* reg */
8431 rm = (insn >> 6) & 7;
8432 tmp2 = load_reg(s, rm);
8434 if (insn & (1 << 9)) {
8435 if (s->condexec_mask)
8436 tcg_gen_sub_i32(tmp, tmp, tmp2);
8437 else
8438 gen_helper_sub_cc(tmp, tmp, tmp2);
8439 } else {
8440 if (s->condexec_mask)
8441 tcg_gen_add_i32(tmp, tmp, tmp2);
8442 else
8443 gen_helper_add_cc(tmp, tmp, tmp2);
8445 dead_tmp(tmp2);
8446 store_reg(s, rd, tmp);
8447 } else {
8448 /* shift immediate */
8449 rm = (insn >> 3) & 7;
8450 shift = (insn >> 6) & 0x1f;
8451 tmp = load_reg(s, rm);
8452 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
8453 if (!s->condexec_mask)
8454 gen_logic_CC(tmp);
8455 store_reg(s, rd, tmp);
8457 break;
8458 case 2: case 3:
8459 /* arithmetic large immediate */
8460 op = (insn >> 11) & 3;
8461 rd = (insn >> 8) & 0x7;
8462 if (op == 0) { /* mov */
8463 tmp = new_tmp();
8464 tcg_gen_movi_i32(tmp, insn & 0xff);
8465 if (!s->condexec_mask)
8466 gen_logic_CC(tmp);
8467 store_reg(s, rd, tmp);
8468 } else {
8469 tmp = load_reg(s, rd);
8470 tmp2 = new_tmp();
8471 tcg_gen_movi_i32(tmp2, insn & 0xff);
8472 switch (op) {
8473 case 1: /* cmp */
8474 gen_helper_sub_cc(tmp, tmp, tmp2);
8475 dead_tmp(tmp);
8476 dead_tmp(tmp2);
8477 break;
8478 case 2: /* add */
8479 if (s->condexec_mask)
8480 tcg_gen_add_i32(tmp, tmp, tmp2);
8481 else
8482 gen_helper_add_cc(tmp, tmp, tmp2);
8483 dead_tmp(tmp2);
8484 store_reg(s, rd, tmp);
8485 break;
8486 case 3: /* sub */
8487 if (s->condexec_mask)
8488 tcg_gen_sub_i32(tmp, tmp, tmp2);
8489 else
8490 gen_helper_sub_cc(tmp, tmp, tmp2);
8491 dead_tmp(tmp2);
8492 store_reg(s, rd, tmp);
8493 break;
8496 break;
8497 case 4:
8498 if (insn & (1 << 11)) {
8499 rd = (insn >> 8) & 7;
8500 /* load pc-relative. Bit 1 of PC is ignored. */
8501 val = s->pc + 2 + ((insn & 0xff) * 4);
8502 val &= ~(uint32_t)2;
8503 addr = new_tmp();
8504 tcg_gen_movi_i32(addr, val);
8505 tmp = gen_ld32(addr, IS_USER(s));
8506 dead_tmp(addr);
8507 store_reg(s, rd, tmp);
8508 break;
8510 if (insn & (1 << 10)) {
8511 /* data processing extended or blx */
8512 rd = (insn & 7) | ((insn >> 4) & 8);
8513 rm = (insn >> 3) & 0xf;
8514 op = (insn >> 8) & 3;
8515 switch (op) {
8516 case 0: /* add */
8517 tmp = load_reg(s, rd);
8518 tmp2 = load_reg(s, rm);
8519 tcg_gen_add_i32(tmp, tmp, tmp2);
8520 dead_tmp(tmp2);
8521 store_reg(s, rd, tmp);
8522 break;
8523 case 1: /* cmp */
8524 tmp = load_reg(s, rd);
8525 tmp2 = load_reg(s, rm);
8526 gen_helper_sub_cc(tmp, tmp, tmp2);
8527 dead_tmp(tmp2);
8528 dead_tmp(tmp);
8529 break;
8530 case 2: /* mov/cpy */
8531 tmp = load_reg(s, rm);
8532 store_reg(s, rd, tmp);
8533 break;
8534 case 3:/* branch [and link] exchange thumb register */
8535 tmp = load_reg(s, rm);
8536 if (insn & (1 << 7)) {
8537 val = (uint32_t)s->pc | 1;
8538 tmp2 = new_tmp();
8539 tcg_gen_movi_i32(tmp2, val);
8540 store_reg(s, 14, tmp2);
8542 gen_bx(s, tmp);
8543 break;
8545 break;
8548 /* data processing register */
8549 rd = insn & 7;
8550 rm = (insn >> 3) & 7;
8551 op = (insn >> 6) & 0xf;
8552 if (op == 2 || op == 3 || op == 4 || op == 7) {
8553 /* the shift/rotate ops want the operands backwards */
8554 val = rm;
8555 rm = rd;
8556 rd = val;
8557 val = 1;
8558 } else {
8559 val = 0;
8562 if (op == 9) { /* neg */
8563 tmp = new_tmp();
8564 tcg_gen_movi_i32(tmp, 0);
8565 } else if (op != 0xf) { /* mvn doesn't read its first operand */
8566 tmp = load_reg(s, rd);
8567 } else {
8568 TCGV_UNUSED(tmp);
8571 tmp2 = load_reg(s, rm);
8572 switch (op) {
8573 case 0x0: /* and */
8574 tcg_gen_and_i32(tmp, tmp, tmp2);
8575 if (!s->condexec_mask)
8576 gen_logic_CC(tmp);
8577 break;
8578 case 0x1: /* eor */
8579 tcg_gen_xor_i32(tmp, tmp, tmp2);
8580 if (!s->condexec_mask)
8581 gen_logic_CC(tmp);
8582 break;
8583 case 0x2: /* lsl */
8584 if (s->condexec_mask) {
8585 gen_helper_shl(tmp2, tmp2, tmp);
8586 } else {
8587 gen_helper_shl_cc(tmp2, tmp2, tmp);
8588 gen_logic_CC(tmp2);
8590 break;
8591 case 0x3: /* lsr */
8592 if (s->condexec_mask) {
8593 gen_helper_shr(tmp2, tmp2, tmp);
8594 } else {
8595 gen_helper_shr_cc(tmp2, tmp2, tmp);
8596 gen_logic_CC(tmp2);
8598 break;
8599 case 0x4: /* asr */
8600 if (s->condexec_mask) {
8601 gen_helper_sar(tmp2, tmp2, tmp);
8602 } else {
8603 gen_helper_sar_cc(tmp2, tmp2, tmp);
8604 gen_logic_CC(tmp2);
8606 break;
8607 case 0x5: /* adc */
8608 if (s->condexec_mask)
8609 gen_adc(tmp, tmp2);
8610 else
8611 gen_helper_adc_cc(tmp, tmp, tmp2);
8612 break;
8613 case 0x6: /* sbc */
8614 if (s->condexec_mask)
8615 gen_sub_carry(tmp, tmp, tmp2);
8616 else
8617 gen_helper_sbc_cc(tmp, tmp, tmp2);
8618 break;
8619 case 0x7: /* ror */
8620 if (s->condexec_mask) {
8621 tcg_gen_andi_i32(tmp, tmp, 0x1f);
8622 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
8623 } else {
8624 gen_helper_ror_cc(tmp2, tmp2, tmp);
8625 gen_logic_CC(tmp2);
8627 break;
8628 case 0x8: /* tst */
8629 tcg_gen_and_i32(tmp, tmp, tmp2);
8630 gen_logic_CC(tmp);
8631 rd = 16;
8632 break;
8633 case 0x9: /* neg */
8634 if (s->condexec_mask)
8635 tcg_gen_neg_i32(tmp, tmp2);
8636 else
8637 gen_helper_sub_cc(tmp, tmp, tmp2);
8638 break;
8639 case 0xa: /* cmp */
8640 gen_helper_sub_cc(tmp, tmp, tmp2);
8641 rd = 16;
8642 break;
8643 case 0xb: /* cmn */
8644 gen_helper_add_cc(tmp, tmp, tmp2);
8645 rd = 16;
8646 break;
8647 case 0xc: /* orr */
8648 tcg_gen_or_i32(tmp, tmp, tmp2);
8649 if (!s->condexec_mask)
8650 gen_logic_CC(tmp);
8651 break;
8652 case 0xd: /* mul */
8653 tcg_gen_mul_i32(tmp, tmp, tmp2);
8654 if (!s->condexec_mask)
8655 gen_logic_CC(tmp);
8656 break;
8657 case 0xe: /* bic */
8658 tcg_gen_andc_i32(tmp, tmp, tmp2);
8659 if (!s->condexec_mask)
8660 gen_logic_CC(tmp);
8661 break;
8662 case 0xf: /* mvn */
8663 tcg_gen_not_i32(tmp2, tmp2);
8664 if (!s->condexec_mask)
8665 gen_logic_CC(tmp2);
8666 val = 1;
8667 rm = rd;
8668 break;
8670 if (rd != 16) {
8671 if (val) {
8672 store_reg(s, rm, tmp2);
8673 if (op != 0xf)
8674 dead_tmp(tmp);
8675 } else {
8676 store_reg(s, rd, tmp);
8677 dead_tmp(tmp2);
8679 } else {
8680 dead_tmp(tmp);
8681 dead_tmp(tmp2);
8683 break;
8685 case 5:
8686 /* load/store register offset. */
8687 rd = insn & 7;
8688 rn = (insn >> 3) & 7;
8689 rm = (insn >> 6) & 7;
8690 op = (insn >> 9) & 7;
8691 addr = load_reg(s, rn);
8692 tmp = load_reg(s, rm);
8693 tcg_gen_add_i32(addr, addr, tmp);
8694 dead_tmp(tmp);
8696 if (op < 3) /* store */
8697 tmp = load_reg(s, rd);
8699 switch (op) {
8700 case 0: /* str */
8701 gen_st32(tmp, addr, IS_USER(s));
8702 break;
8703 case 1: /* strh */
8704 gen_st16(tmp, addr, IS_USER(s));
8705 break;
8706 case 2: /* strb */
8707 gen_st8(tmp, addr, IS_USER(s));
8708 break;
8709 case 3: /* ldrsb */
8710 tmp = gen_ld8s(addr, IS_USER(s));
8711 break;
8712 case 4: /* ldr */
8713 tmp = gen_ld32(addr, IS_USER(s));
8714 break;
8715 case 5: /* ldrh */
8716 tmp = gen_ld16u(addr, IS_USER(s));
8717 break;
8718 case 6: /* ldrb */
8719 tmp = gen_ld8u(addr, IS_USER(s));
8720 break;
8721 case 7: /* ldrsh */
8722 tmp = gen_ld16s(addr, IS_USER(s));
8723 break;
8725 if (op >= 3) /* load */
8726 store_reg(s, rd, tmp);
8727 dead_tmp(addr);
8728 break;
8730 case 6:
8731 /* load/store word immediate offset */
8732 rd = insn & 7;
8733 rn = (insn >> 3) & 7;
8734 addr = load_reg(s, rn);
8735 val = (insn >> 4) & 0x7c;
8736 tcg_gen_addi_i32(addr, addr, val);
8738 if (insn & (1 << 11)) {
8739 /* load */
8740 tmp = gen_ld32(addr, IS_USER(s));
8741 store_reg(s, rd, tmp);
8742 } else {
8743 /* store */
8744 tmp = load_reg(s, rd);
8745 gen_st32(tmp, addr, IS_USER(s));
8747 dead_tmp(addr);
8748 break;
8750 case 7:
8751 /* load/store byte immediate offset */
8752 rd = insn & 7;
8753 rn = (insn >> 3) & 7;
8754 addr = load_reg(s, rn);
8755 val = (insn >> 6) & 0x1f;
8756 tcg_gen_addi_i32(addr, addr, val);
8758 if (insn & (1 << 11)) {
8759 /* load */
8760 tmp = gen_ld8u(addr, IS_USER(s));
8761 store_reg(s, rd, tmp);
8762 } else {
8763 /* store */
8764 tmp = load_reg(s, rd);
8765 gen_st8(tmp, addr, IS_USER(s));
8767 dead_tmp(addr);
8768 break;
8770 case 8:
8771 /* load/store halfword immediate offset */
8772 rd = insn & 7;
8773 rn = (insn >> 3) & 7;
8774 addr = load_reg(s, rn);
8775 val = (insn >> 5) & 0x3e;
8776 tcg_gen_addi_i32(addr, addr, val);
8778 if (insn & (1 << 11)) {
8779 /* load */
8780 tmp = gen_ld16u(addr, IS_USER(s));
8781 store_reg(s, rd, tmp);
8782 } else {
8783 /* store */
8784 tmp = load_reg(s, rd);
8785 gen_st16(tmp, addr, IS_USER(s));
8787 dead_tmp(addr);
8788 break;
8790 case 9:
8791 /* load/store from stack */
8792 rd = (insn >> 8) & 7;
8793 addr = load_reg(s, 13);
8794 val = (insn & 0xff) * 4;
8795 tcg_gen_addi_i32(addr, addr, val);
8797 if (insn & (1 << 11)) {
8798 /* load */
8799 tmp = gen_ld32(addr, IS_USER(s));
8800 store_reg(s, rd, tmp);
8801 } else {
8802 /* store */
8803 tmp = load_reg(s, rd);
8804 gen_st32(tmp, addr, IS_USER(s));
8806 dead_tmp(addr);
8807 break;
8809 case 10:
8810 /* add to high reg */
8811 rd = (insn >> 8) & 7;
8812 if (insn & (1 << 11)) {
8813 /* SP */
8814 tmp = load_reg(s, 13);
8815 } else {
8816 /* PC. bit 1 is ignored. */
8817 tmp = new_tmp();
8818 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
8820 val = (insn & 0xff) * 4;
8821 tcg_gen_addi_i32(tmp, tmp, val);
8822 store_reg(s, rd, tmp);
8823 break;
8825 case 11:
8826 /* misc */
8827 op = (insn >> 8) & 0xf;
8828 switch (op) {
8829 case 0:
8830 /* adjust stack pointer */
8831 tmp = load_reg(s, 13);
8832 val = (insn & 0x7f) * 4;
8833 if (insn & (1 << 7))
8834 val = -(int32_t)val;
8835 tcg_gen_addi_i32(tmp, tmp, val);
8836 store_reg(s, 13, tmp);
8837 break;
8839 case 2: /* sign/zero extend. */
8840 ARCH(6);
8841 rd = insn & 7;
8842 rm = (insn >> 3) & 7;
8843 tmp = load_reg(s, rm);
8844 switch ((insn >> 6) & 3) {
8845 case 0: gen_sxth(tmp); break;
8846 case 1: gen_sxtb(tmp); break;
8847 case 2: gen_uxth(tmp); break;
8848 case 3: gen_uxtb(tmp); break;
8850 store_reg(s, rd, tmp);
8851 break;
8852 case 4: case 5: case 0xc: case 0xd:
8853 /* push/pop */
8854 addr = load_reg(s, 13);
8855 if (insn & (1 << 8))
8856 offset = 4;
8857 else
8858 offset = 0;
8859 for (i = 0; i < 8; i++) {
8860 if (insn & (1 << i))
8861 offset += 4;
8863 if ((insn & (1 << 11)) == 0) {
8864 tcg_gen_addi_i32(addr, addr, -offset);
8866 for (i = 0; i < 8; i++) {
8867 if (insn & (1 << i)) {
8868 if (insn & (1 << 11)) {
8869 /* pop */
8870 tmp = gen_ld32(addr, IS_USER(s));
8871 store_reg(s, i, tmp);
8872 } else {
8873 /* push */
8874 tmp = load_reg(s, i);
8875 gen_st32(tmp, addr, IS_USER(s));
8877 /* advance to the next address. */
8878 tcg_gen_addi_i32(addr, addr, 4);
8881 TCGV_UNUSED(tmp);
8882 if (insn & (1 << 8)) {
8883 if (insn & (1 << 11)) {
8884 /* pop pc */
8885 tmp = gen_ld32(addr, IS_USER(s));
8886 /* don't set the pc until the rest of the instruction
8887 has completed */
8888 } else {
8889 /* push lr */
8890 tmp = load_reg(s, 14);
8891 gen_st32(tmp, addr, IS_USER(s));
8893 tcg_gen_addi_i32(addr, addr, 4);
8895 if ((insn & (1 << 11)) == 0) {
8896 tcg_gen_addi_i32(addr, addr, -offset);
8898 /* write back the new stack pointer */
8899 store_reg(s, 13, addr);
8900 /* set the new PC value */
8901 if ((insn & 0x0900) == 0x0900)
8902 gen_bx(s, tmp);
8903 break;
8905 case 1: case 3: case 9: case 11: /* czb */
8906 rm = insn & 7;
8907 tmp = load_reg(s, rm);
8908 s->condlabel = gen_new_label();
8909 s->condjmp = 1;
8910 if (insn & (1 << 11))
8911 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
8912 else
8913 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
8914 dead_tmp(tmp);
8915 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
8916 val = (uint32_t)s->pc + 2;
8917 val += offset;
8918 gen_jmp(s, val);
8919 break;
8921 case 15: /* IT, nop-hint. */
8922 if ((insn & 0xf) == 0) {
8923 gen_nop_hint(s, (insn >> 4) & 0xf);
8924 break;
8926 /* If Then. */
8927 s->condexec_cond = (insn >> 4) & 0xe;
8928 s->condexec_mask = insn & 0x1f;
8929 /* No actual code generated for this insn, just setup state. */
8930 break;
8932 case 0xe: /* bkpt */
8933 gen_set_condexec(s);
8934 gen_set_pc_im(s->pc - 2);
8935 gen_exception(EXCP_BKPT);
8936 s->is_jmp = DISAS_JUMP;
8937 break;
8939 case 0xa: /* rev */
8940 ARCH(6);
8941 rn = (insn >> 3) & 0x7;
8942 rd = insn & 0x7;
8943 tmp = load_reg(s, rn);
8944 switch ((insn >> 6) & 3) {
8945 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
8946 case 1: gen_rev16(tmp); break;
8947 case 3: gen_revsh(tmp); break;
8948 default: goto illegal_op;
8950 store_reg(s, rd, tmp);
8951 break;
8953 case 6: /* cps */
8954 ARCH(6);
8955 if (IS_USER(s))
8956 break;
8957 if (IS_M(env)) {
8958 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
8959 /* PRIMASK */
8960 if (insn & 1) {
8961 addr = tcg_const_i32(16);
8962 gen_helper_v7m_msr(cpu_env, addr, tmp);
8963 tcg_temp_free_i32(addr);
8965 /* FAULTMASK */
8966 if (insn & 2) {
8967 addr = tcg_const_i32(17);
8968 gen_helper_v7m_msr(cpu_env, addr, tmp);
8969 tcg_temp_free_i32(addr);
8971 tcg_temp_free_i32(tmp);
8972 gen_lookup_tb(s);
8973 } else {
8974 if (insn & (1 << 4))
8975 shift = CPSR_A | CPSR_I | CPSR_F;
8976 else
8977 shift = 0;
8978 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
8980 break;
8982 default:
8983 goto undef;
8985 break;
8987 case 12:
8988 /* load/store multiple */
8989 rn = (insn >> 8) & 0x7;
8990 addr = load_reg(s, rn);
8991 for (i = 0; i < 8; i++) {
8992 if (insn & (1 << i)) {
8993 if (insn & (1 << 11)) {
8994 /* load */
8995 tmp = gen_ld32(addr, IS_USER(s));
8996 store_reg(s, i, tmp);
8997 } else {
8998 /* store */
8999 tmp = load_reg(s, i);
9000 gen_st32(tmp, addr, IS_USER(s));
9002 /* advance to the next address */
9003 tcg_gen_addi_i32(addr, addr, 4);
9006 /* Base register writeback. */
9007 if ((insn & (1 << rn)) == 0) {
9008 store_reg(s, rn, addr);
9009 } else {
9010 dead_tmp(addr);
9012 break;
9014 case 13:
9015 /* conditional branch or swi */
9016 cond = (insn >> 8) & 0xf;
9017 if (cond == 0xe)
9018 goto undef;
9020 if (cond == 0xf) {
9021 /* swi */
9022 gen_set_condexec(s);
9023 gen_set_pc_im(s->pc);
9024 s->is_jmp = DISAS_SWI;
9025 break;
9027 /* generate a conditional jump to next instruction */
9028 s->condlabel = gen_new_label();
9029 gen_test_cc(cond ^ 1, s->condlabel);
9030 s->condjmp = 1;
9032 /* jump to the offset */
9033 val = (uint32_t)s->pc + 2;
9034 offset = ((int32_t)insn << 24) >> 24;
9035 val += offset << 1;
9036 gen_jmp(s, val);
9037 break;
9039 case 14:
9040 if (insn & (1 << 11)) {
9041 if (disas_thumb2_insn(env, s, insn))
9042 goto undef32;
9043 break;
9045 /* unconditional branch */
9046 val = (uint32_t)s->pc;
9047 offset = ((int32_t)insn << 21) >> 21;
9048 val += (offset << 1) + 2;
9049 gen_jmp(s, val);
9050 break;
9052 case 15:
9053 if (disas_thumb2_insn(env, s, insn))
9054 goto undef32;
9055 break;
9057 return;
9058 undef32:
9059 gen_set_condexec(s);
9060 gen_set_pc_im(s->pc - 4);
9061 gen_exception(EXCP_UDEF);
9062 s->is_jmp = DISAS_JUMP;
9063 return;
9064 illegal_op:
9065 undef:
9066 gen_set_condexec(s);
9067 gen_set_pc_im(s->pc - 2);
9068 gen_exception(EXCP_UDEF);
9069 s->is_jmp = DISAS_JUMP;
9072 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
9073 basic block 'tb'. If search_pc is TRUE, also generate PC
9074 information for each intermediate instruction. */
9075 static inline void gen_intermediate_code_internal(CPUState *env,
9076 TranslationBlock *tb,
9077 int search_pc)
9079 DisasContext dc1, *dc = &dc1;
9080 CPUBreakpoint *bp;
9081 uint16_t *gen_opc_end;
9082 int j, lj;
9083 target_ulong pc_start;
9084 uint32_t next_page_start;
9085 int num_insns;
9086 int max_insns;
9088 /* generate intermediate code */
9089 num_temps = 0;
9091 pc_start = tb->pc;
9093 dc->tb = tb;
9095 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
9097 dc->is_jmp = DISAS_NEXT;
9098 dc->pc = pc_start;
9099 dc->singlestep_enabled = env->singlestep_enabled;
9100 dc->condjmp = 0;
9101 dc->thumb = env->thumb;
9102 dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
9103 dc->condexec_cond = env->condexec_bits >> 4;
9104 #if !defined(CONFIG_USER_ONLY)
9105 if (IS_M(env)) {
9106 dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
9107 } else {
9108 dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
9110 #endif
9111 cpu_F0s = tcg_temp_new_i32();
9112 cpu_F1s = tcg_temp_new_i32();
9113 cpu_F0d = tcg_temp_new_i64();
9114 cpu_F1d = tcg_temp_new_i64();
9115 cpu_V0 = cpu_F0d;
9116 cpu_V1 = cpu_F1d;
9117 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
9118 cpu_M0 = tcg_temp_new_i64();
9119 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
9120 lj = -1;
9121 num_insns = 0;
9122 max_insns = tb->cflags & CF_COUNT_MASK;
9123 if (max_insns == 0)
9124 max_insns = CF_COUNT_MASK;
9126 gen_icount_start();
9127 /* Reset the conditional execution bits immediately. This avoids
9128 complications trying to do it at the end of the block. */
9129 if (env->condexec_bits)
9131 TCGv tmp = new_tmp();
9132 tcg_gen_movi_i32(tmp, 0);
9133 store_cpu_field(tmp, condexec_bits);
9135 do {
9136 #ifdef CONFIG_USER_ONLY
9137 /* Intercept jump to the magic kernel page. */
9138 if (dc->pc >= 0xffff0000) {
9139 /* We always get here via a jump, so know we are not in a
9140 conditional execution block. */
9141 gen_exception(EXCP_KERNEL_TRAP);
9142 dc->is_jmp = DISAS_UPDATE;
9143 break;
9145 #else
9146 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
9147 /* We always get here via a jump, so know we are not in a
9148 conditional execution block. */
9149 gen_exception(EXCP_EXCEPTION_EXIT);
9150 dc->is_jmp = DISAS_UPDATE;
9151 break;
9153 #endif
9155 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
9156 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
9157 if (bp->pc == dc->pc) {
9158 gen_set_condexec(dc);
9159 gen_set_pc_im(dc->pc);
9160 gen_exception(EXCP_DEBUG);
9161 dc->is_jmp = DISAS_JUMP;
9162 /* Advance PC so that clearing the breakpoint will
9163 invalidate this TB. */
9164 dc->pc += 2;
9165 goto done_generating;
9166 break;
9170 if (search_pc) {
9171 j = gen_opc_ptr - gen_opc_buf;
9172 if (lj < j) {
9173 lj++;
9174 while (lj < j)
9175 gen_opc_instr_start[lj++] = 0;
9177 gen_opc_pc[lj] = dc->pc;
9178 gen_opc_instr_start[lj] = 1;
9179 gen_opc_icount[lj] = num_insns;
9182 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
9183 gen_io_start();
9185 if (env->thumb) {
9186 disas_thumb_insn(env, dc);
9187 if (dc->condexec_mask) {
9188 dc->condexec_cond = (dc->condexec_cond & 0xe)
9189 | ((dc->condexec_mask >> 4) & 1);
9190 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
9191 if (dc->condexec_mask == 0) {
9192 dc->condexec_cond = 0;
9195 } else {
9196 disas_arm_insn(env, dc);
9198 if (num_temps) {
9199 fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
9200 num_temps = 0;
9203 if (dc->condjmp && !dc->is_jmp) {
9204 gen_set_label(dc->condlabel);
9205 dc->condjmp = 0;
9207 /* Translation stops when a conditional branch is encountered.
9208 * Otherwise the subsequent code could get translated several times.
9209 * Also stop translation when a page boundary is reached. This
9210 * ensures prefetch aborts occur at the right place. */
9211 num_insns ++;
9212 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
9213 !env->singlestep_enabled &&
9214 !singlestep &&
9215 dc->pc < next_page_start &&
9216 num_insns < max_insns);
9218 if (tb->cflags & CF_LAST_IO) {
9219 if (dc->condjmp) {
9220 /* FIXME: This can theoretically happen with self-modifying
9221 code. */
9222 cpu_abort(env, "IO on conditional branch instruction");
9224 gen_io_end();
9227 /* At this stage dc->condjmp will only be set when the skipped
9228 instruction was a conditional branch or trap, and the PC has
9229 already been written. */
9230 if (unlikely(env->singlestep_enabled)) {
9231 /* Make sure the pc is updated, and raise a debug exception. */
9232 if (dc->condjmp) {
9233 gen_set_condexec(dc);
9234 if (dc->is_jmp == DISAS_SWI) {
9235 gen_exception(EXCP_SWI);
9236 } else {
9237 gen_exception(EXCP_DEBUG);
9239 gen_set_label(dc->condlabel);
9241 if (dc->condjmp || !dc->is_jmp) {
9242 gen_set_pc_im(dc->pc);
9243 dc->condjmp = 0;
9245 gen_set_condexec(dc);
9246 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
9247 gen_exception(EXCP_SWI);
9248 } else {
9249 /* FIXME: Single stepping a WFI insn will not halt
9250 the CPU. */
9251 gen_exception(EXCP_DEBUG);
9253 } else {
9254 /* While branches must always occur at the end of an IT block,
9255 there are a few other things that can cause us to terminate
9256 the TB in the middel of an IT block:
9257 - Exception generating instructions (bkpt, swi, undefined).
9258 - Page boundaries.
9259 - Hardware watchpoints.
9260 Hardware breakpoints have already been handled and skip this code.
9262 gen_set_condexec(dc);
9263 switch(dc->is_jmp) {
9264 case DISAS_NEXT:
9265 gen_goto_tb(dc, 1, dc->pc);
9266 break;
9267 default:
9268 case DISAS_JUMP:
9269 case DISAS_UPDATE:
9270 /* indicate that the hash table must be used to find the next TB */
9271 tcg_gen_exit_tb(0);
9272 break;
9273 case DISAS_TB_JUMP:
9274 /* nothing more to generate */
9275 break;
9276 case DISAS_WFI:
9277 gen_helper_wfi();
9278 break;
9279 case DISAS_SWI:
9280 gen_exception(EXCP_SWI);
9281 break;
9283 if (dc->condjmp) {
9284 gen_set_label(dc->condlabel);
9285 gen_set_condexec(dc);
9286 gen_goto_tb(dc, 1, dc->pc);
9287 dc->condjmp = 0;
9291 done_generating:
9292 gen_icount_end(tb, num_insns);
9293 *gen_opc_ptr = INDEX_op_end;
9295 #ifdef DEBUG_DISAS
9296 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9297 qemu_log("----------------\n");
9298 qemu_log("IN: %s\n", lookup_symbol(pc_start));
9299 log_target_disas(pc_start, dc->pc - pc_start, env->thumb);
9300 qemu_log("\n");
9302 #endif
9303 if (search_pc) {
9304 j = gen_opc_ptr - gen_opc_buf;
9305 lj++;
9306 while (lj <= j)
9307 gen_opc_instr_start[lj++] = 0;
9308 } else {
9309 tb->size = dc->pc - pc_start;
9310 tb->icount = num_insns;
9314 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
9316 gen_intermediate_code_internal(env, tb, 0);
9319 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
9321 gen_intermediate_code_internal(env, tb, 1);
9324 static const char *cpu_mode_names[16] = {
9325 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9326 "???", "???", "???", "und", "???", "???", "???", "sys"
9329 void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
9330 int flags)
9332 int i;
9333 #if 0
9334 union {
9335 uint32_t i;
9336 float s;
9337 } s0, s1;
9338 CPU_DoubleU d;
9339 /* ??? This assumes float64 and double have the same layout.
9340 Oh well, it's only debug dumps. */
9341 union {
9342 float64 f64;
9343 double d;
9344 } d0;
9345 #endif
9346 uint32_t psr;
9348 for(i=0;i<16;i++) {
9349 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
9350 if ((i % 4) == 3)
9351 cpu_fprintf(f, "\n");
9352 else
9353 cpu_fprintf(f, " ");
9355 psr = cpsr_read(env);
9356 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
9357 psr,
9358 psr & (1 << 31) ? 'N' : '-',
9359 psr & (1 << 30) ? 'Z' : '-',
9360 psr & (1 << 29) ? 'C' : '-',
9361 psr & (1 << 28) ? 'V' : '-',
9362 psr & CPSR_T ? 'T' : 'A',
9363 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
9365 #if 0
9366 for (i = 0; i < 16; i++) {
9367 d.d = env->vfp.regs[i];
9368 s0.i = d.l.lower;
9369 s1.i = d.l.upper;
9370 d0.f64 = d.d;
9371 cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9372 i * 2, (int)s0.i, s0.s,
9373 i * 2 + 1, (int)s1.i, s1.s,
9374 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
9375 d0.d);
9377 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
9378 #endif
9381 void gen_pc_load(CPUState *env, TranslationBlock *tb,
9382 unsigned long searched_pc, int pc_pos, void *puc)
9384 env->regs[15] = gen_opc_pc[pc_pos];