target-arm: cleanup internal resource leaks
[qemu/aliguori-queue.git] / target-arm / translate.c
blob813f661ca587d016d016bad8de247d98b5b40341
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];
80 /* FIXME: These should be removed. */
81 static TCGv cpu_F0s, cpu_F1s;
82 static TCGv_i64 cpu_F0d, cpu_F1d;
84 #include "gen-icount.h"
86 static const char *regnames[] =
87 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
88 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
90 /* initialize TCG globals. */
91 void arm_translate_init(void)
93 int i;
95 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
97 for (i = 0; i < 16; i++) {
98 cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
99 offsetof(CPUState, regs[i]),
100 regnames[i]);
103 #define GEN_HELPER 2
104 #include "helpers.h"
107 static int num_temps;
109 /* Allocate a temporary variable. */
110 static TCGv_i32 new_tmp(void)
112 num_temps++;
113 return tcg_temp_new_i32();
116 /* Release a temporary variable. */
117 static void dead_tmp(TCGv tmp)
119 tcg_temp_free(tmp);
120 num_temps--;
123 static inline TCGv load_cpu_offset(int offset)
125 TCGv tmp = new_tmp();
126 tcg_gen_ld_i32(tmp, cpu_env, offset);
127 return tmp;
130 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
132 static inline void store_cpu_offset(TCGv var, int offset)
134 tcg_gen_st_i32(var, cpu_env, offset);
135 dead_tmp(var);
138 #define store_cpu_field(var, name) \
139 store_cpu_offset(var, offsetof(CPUState, name))
141 /* Set a variable to the value of a CPU register. */
142 static void load_reg_var(DisasContext *s, TCGv var, int reg)
144 if (reg == 15) {
145 uint32_t addr;
146 /* normaly, since we updated PC, we need only to add one insn */
147 if (s->thumb)
148 addr = (long)s->pc + 2;
149 else
150 addr = (long)s->pc + 4;
151 tcg_gen_movi_i32(var, addr);
152 } else {
153 tcg_gen_mov_i32(var, cpu_R[reg]);
157 /* Create a new temporary and set it to the value of a CPU register. */
158 static inline TCGv load_reg(DisasContext *s, int reg)
160 TCGv tmp = new_tmp();
161 load_reg_var(s, tmp, reg);
162 return tmp;
165 /* Set a CPU register. The source must be a temporary and will be
166 marked as dead. */
167 static void store_reg(DisasContext *s, int reg, TCGv var)
169 if (reg == 15) {
170 tcg_gen_andi_i32(var, var, ~1);
171 s->is_jmp = DISAS_JUMP;
173 tcg_gen_mov_i32(cpu_R[reg], var);
174 dead_tmp(var);
177 /* Value extensions. */
178 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
179 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
180 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
181 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
183 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
184 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
187 static inline void gen_set_cpsr(TCGv var, uint32_t mask)
189 TCGv tmp_mask = tcg_const_i32(mask);
190 gen_helper_cpsr_write(var, tmp_mask);
191 tcg_temp_free_i32(tmp_mask);
193 /* Set NZCV flags from the high 4 bits of var. */
194 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
196 static void gen_exception(int excp)
198 TCGv tmp = new_tmp();
199 tcg_gen_movi_i32(tmp, excp);
200 gen_helper_exception(tmp);
201 dead_tmp(tmp);
204 static void gen_smul_dual(TCGv a, TCGv b)
206 TCGv tmp1 = new_tmp();
207 TCGv tmp2 = new_tmp();
208 tcg_gen_ext16s_i32(tmp1, a);
209 tcg_gen_ext16s_i32(tmp2, b);
210 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
211 dead_tmp(tmp2);
212 tcg_gen_sari_i32(a, a, 16);
213 tcg_gen_sari_i32(b, b, 16);
214 tcg_gen_mul_i32(b, b, a);
215 tcg_gen_mov_i32(a, tmp1);
216 dead_tmp(tmp1);
219 /* Byteswap each halfword. */
220 static void gen_rev16(TCGv var)
222 TCGv tmp = new_tmp();
223 tcg_gen_shri_i32(tmp, var, 8);
224 tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
225 tcg_gen_shli_i32(var, var, 8);
226 tcg_gen_andi_i32(var, var, 0xff00ff00);
227 tcg_gen_or_i32(var, var, tmp);
228 dead_tmp(tmp);
231 /* Byteswap low halfword and sign extend. */
232 static void gen_revsh(TCGv var)
234 TCGv tmp = new_tmp();
235 tcg_gen_shri_i32(tmp, var, 8);
236 tcg_gen_andi_i32(tmp, tmp, 0x00ff);
237 tcg_gen_shli_i32(var, var, 8);
238 tcg_gen_ext8s_i32(var, var);
239 tcg_gen_or_i32(var, var, tmp);
240 dead_tmp(tmp);
243 /* Unsigned bitfield extract. */
244 static void gen_ubfx(TCGv var, int shift, uint32_t mask)
246 if (shift)
247 tcg_gen_shri_i32(var, var, shift);
248 tcg_gen_andi_i32(var, var, mask);
251 /* Signed bitfield extract. */
252 static void gen_sbfx(TCGv var, int shift, int width)
254 uint32_t signbit;
256 if (shift)
257 tcg_gen_sari_i32(var, var, shift);
258 if (shift + width < 32) {
259 signbit = 1u << (width - 1);
260 tcg_gen_andi_i32(var, var, (1u << width) - 1);
261 tcg_gen_xori_i32(var, var, signbit);
262 tcg_gen_subi_i32(var, var, signbit);
266 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
267 static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
269 tcg_gen_andi_i32(val, val, mask);
270 tcg_gen_shli_i32(val, val, shift);
271 tcg_gen_andi_i32(base, base, ~(mask << shift));
272 tcg_gen_or_i32(dest, base, val);
275 /* Round the top 32 bits of a 64-bit value. */
276 static void gen_roundqd(TCGv a, TCGv b)
278 tcg_gen_shri_i32(a, a, 31);
279 tcg_gen_add_i32(a, a, b);
282 /* FIXME: Most targets have native widening multiplication.
283 It would be good to use that instead of a full wide multiply. */
284 /* 32x32->64 multiply. Marks inputs as dead. */
285 static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b)
287 TCGv_i64 tmp1 = tcg_temp_new_i64();
288 TCGv_i64 tmp2 = tcg_temp_new_i64();
290 tcg_gen_extu_i32_i64(tmp1, a);
291 dead_tmp(a);
292 tcg_gen_extu_i32_i64(tmp2, b);
293 dead_tmp(b);
294 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
295 tcg_temp_free_i64(tmp2);
296 return tmp1;
299 static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
301 TCGv_i64 tmp1 = tcg_temp_new_i64();
302 TCGv_i64 tmp2 = tcg_temp_new_i64();
304 tcg_gen_ext_i32_i64(tmp1, a);
305 dead_tmp(a);
306 tcg_gen_ext_i32_i64(tmp2, b);
307 dead_tmp(b);
308 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
309 tcg_temp_free_i64(tmp2);
310 return tmp1;
313 /* Unsigned 32x32->64 multiply. */
314 static void gen_mull(TCGv a, TCGv b)
316 TCGv_i64 tmp1 = tcg_temp_new_i64();
317 TCGv_i64 tmp2 = tcg_temp_new_i64();
319 tcg_gen_extu_i32_i64(tmp1, a);
320 tcg_gen_extu_i32_i64(tmp2, b);
321 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
322 tcg_temp_free_i64(tmp2);
323 tcg_gen_trunc_i64_i32(a, tmp1);
324 tcg_gen_shri_i64(tmp1, tmp1, 32);
325 tcg_gen_trunc_i64_i32(b, tmp1);
326 tcg_temp_free_i64(tmp1);
329 /* Signed 32x32->64 multiply. */
330 static void gen_imull(TCGv a, TCGv b)
332 TCGv_i64 tmp1 = tcg_temp_new_i64();
333 TCGv_i64 tmp2 = tcg_temp_new_i64();
335 tcg_gen_ext_i32_i64(tmp1, a);
336 tcg_gen_ext_i32_i64(tmp2, b);
337 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
338 tcg_temp_free_i64(tmp2);
339 tcg_gen_trunc_i64_i32(a, tmp1);
340 tcg_gen_shri_i64(tmp1, tmp1, 32);
341 tcg_gen_trunc_i64_i32(b, tmp1);
342 tcg_temp_free_i64(tmp1);
345 /* Swap low and high halfwords. */
346 static void gen_swap_half(TCGv var)
348 TCGv tmp = new_tmp();
349 tcg_gen_shri_i32(tmp, var, 16);
350 tcg_gen_shli_i32(var, var, 16);
351 tcg_gen_or_i32(var, var, tmp);
352 dead_tmp(tmp);
355 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
356 tmp = (t0 ^ t1) & 0x8000;
357 t0 &= ~0x8000;
358 t1 &= ~0x8000;
359 t0 = (t0 + t1) ^ tmp;
362 static void gen_add16(TCGv t0, TCGv t1)
364 TCGv tmp = new_tmp();
365 tcg_gen_xor_i32(tmp, t0, t1);
366 tcg_gen_andi_i32(tmp, tmp, 0x8000);
367 tcg_gen_andi_i32(t0, t0, ~0x8000);
368 tcg_gen_andi_i32(t1, t1, ~0x8000);
369 tcg_gen_add_i32(t0, t0, t1);
370 tcg_gen_xor_i32(t0, t0, tmp);
371 dead_tmp(tmp);
372 dead_tmp(t1);
375 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
377 /* Set CF to the top bit of var. */
378 static void gen_set_CF_bit31(TCGv var)
380 TCGv tmp = new_tmp();
381 tcg_gen_shri_i32(tmp, var, 31);
382 gen_set_CF(tmp);
383 dead_tmp(tmp);
386 /* Set N and Z flags from var. */
387 static inline void gen_logic_CC(TCGv var)
389 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF));
390 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF));
393 /* T0 += T1 + CF. */
394 static void gen_adc(TCGv t0, TCGv t1)
396 TCGv tmp;
397 tcg_gen_add_i32(t0, t0, t1);
398 tmp = load_cpu_field(CF);
399 tcg_gen_add_i32(t0, t0, tmp);
400 dead_tmp(tmp);
403 /* dest = T0 + T1 + CF. */
404 static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
406 TCGv tmp;
407 tcg_gen_add_i32(dest, t0, t1);
408 tmp = load_cpu_field(CF);
409 tcg_gen_add_i32(dest, dest, tmp);
410 dead_tmp(tmp);
413 /* dest = T0 - T1 + CF - 1. */
414 static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
416 TCGv tmp;
417 tcg_gen_sub_i32(dest, t0, t1);
418 tmp = load_cpu_field(CF);
419 tcg_gen_add_i32(dest, dest, tmp);
420 tcg_gen_subi_i32(dest, dest, 1);
421 dead_tmp(tmp);
424 /* T0 &= ~T1. Clobbers T1. */
425 /* FIXME: Implement bic natively. */
426 static inline void tcg_gen_bic_i32(TCGv dest, TCGv t0, TCGv t1)
428 TCGv tmp = new_tmp();
429 tcg_gen_not_i32(tmp, t1);
430 tcg_gen_and_i32(dest, t0, tmp);
431 dead_tmp(tmp);
434 /* FIXME: Implement this natively. */
435 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
437 /* FIXME: Implement this natively. */
438 static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i)
440 TCGv tmp;
442 if (i == 0)
443 return;
445 tmp = new_tmp();
446 tcg_gen_shri_i32(tmp, t1, i);
447 tcg_gen_shli_i32(t1, t1, 32 - i);
448 tcg_gen_or_i32(t0, t1, tmp);
449 dead_tmp(tmp);
452 static void shifter_out_im(TCGv var, int shift)
454 TCGv tmp = new_tmp();
455 if (shift == 0) {
456 tcg_gen_andi_i32(tmp, var, 1);
457 } else {
458 tcg_gen_shri_i32(tmp, var, shift);
459 if (shift != 31)
460 tcg_gen_andi_i32(tmp, tmp, 1);
462 gen_set_CF(tmp);
463 dead_tmp(tmp);
466 /* Shift by immediate. Includes special handling for shift == 0. */
467 static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
469 switch (shiftop) {
470 case 0: /* LSL */
471 if (shift != 0) {
472 if (flags)
473 shifter_out_im(var, 32 - shift);
474 tcg_gen_shli_i32(var, var, shift);
476 break;
477 case 1: /* LSR */
478 if (shift == 0) {
479 if (flags) {
480 tcg_gen_shri_i32(var, var, 31);
481 gen_set_CF(var);
483 tcg_gen_movi_i32(var, 0);
484 } else {
485 if (flags)
486 shifter_out_im(var, shift - 1);
487 tcg_gen_shri_i32(var, var, shift);
489 break;
490 case 2: /* ASR */
491 if (shift == 0)
492 shift = 32;
493 if (flags)
494 shifter_out_im(var, shift - 1);
495 if (shift == 32)
496 shift = 31;
497 tcg_gen_sari_i32(var, var, shift);
498 break;
499 case 3: /* ROR/RRX */
500 if (shift != 0) {
501 if (flags)
502 shifter_out_im(var, shift - 1);
503 tcg_gen_rori_i32(var, var, shift); break;
504 } else {
505 TCGv tmp = load_cpu_field(CF);
506 if (flags)
507 shifter_out_im(var, 0);
508 tcg_gen_shri_i32(var, var, 1);
509 tcg_gen_shli_i32(tmp, tmp, 31);
510 tcg_gen_or_i32(var, var, tmp);
511 dead_tmp(tmp);
516 static inline void gen_arm_shift_reg(TCGv var, int shiftop,
517 TCGv shift, int flags)
519 if (flags) {
520 switch (shiftop) {
521 case 0: gen_helper_shl_cc(var, var, shift); break;
522 case 1: gen_helper_shr_cc(var, var, shift); break;
523 case 2: gen_helper_sar_cc(var, var, shift); break;
524 case 3: gen_helper_ror_cc(var, var, shift); break;
526 } else {
527 switch (shiftop) {
528 case 0: gen_helper_shl(var, var, shift); break;
529 case 1: gen_helper_shr(var, var, shift); break;
530 case 2: gen_helper_sar(var, var, shift); break;
531 case 3: gen_helper_ror(var, var, shift); break;
534 dead_tmp(shift);
537 #define PAS_OP(pfx) \
538 switch (op2) { \
539 case 0: gen_pas_helper(glue(pfx,add16)); break; \
540 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
541 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
542 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
543 case 4: gen_pas_helper(glue(pfx,add8)); break; \
544 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
546 static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
548 TCGv_ptr tmp;
550 switch (op1) {
551 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
552 case 1:
553 tmp = tcg_temp_new_ptr();
554 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
555 PAS_OP(s)
556 tcg_temp_free_ptr(tmp);
557 break;
558 case 5:
559 tmp = tcg_temp_new_ptr();
560 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
561 PAS_OP(u)
562 tcg_temp_free_ptr(tmp);
563 break;
564 #undef gen_pas_helper
565 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
566 case 2:
567 PAS_OP(q);
568 break;
569 case 3:
570 PAS_OP(sh);
571 break;
572 case 6:
573 PAS_OP(uq);
574 break;
575 case 7:
576 PAS_OP(uh);
577 break;
578 #undef gen_pas_helper
581 #undef PAS_OP
583 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
584 #define PAS_OP(pfx) \
585 switch (op2) { \
586 case 0: gen_pas_helper(glue(pfx,add8)); break; \
587 case 1: gen_pas_helper(glue(pfx,add16)); break; \
588 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
589 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
590 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
591 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
593 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
595 TCGv_ptr tmp;
597 switch (op1) {
598 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
599 case 0:
600 tmp = tcg_temp_new_ptr();
601 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
602 PAS_OP(s)
603 tcg_temp_free_ptr(tmp);
604 break;
605 case 4:
606 tmp = tcg_temp_new_ptr();
607 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
608 PAS_OP(u)
609 tcg_temp_free_ptr(tmp);
610 break;
611 #undef gen_pas_helper
612 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
613 case 1:
614 PAS_OP(q);
615 break;
616 case 2:
617 PAS_OP(sh);
618 break;
619 case 5:
620 PAS_OP(uq);
621 break;
622 case 6:
623 PAS_OP(uh);
624 break;
625 #undef gen_pas_helper
628 #undef PAS_OP
630 static void gen_test_cc(int cc, int label)
632 TCGv tmp;
633 TCGv tmp2;
634 int inv;
636 switch (cc) {
637 case 0: /* eq: Z */
638 tmp = load_cpu_field(ZF);
639 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
640 break;
641 case 1: /* ne: !Z */
642 tmp = load_cpu_field(ZF);
643 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
644 break;
645 case 2: /* cs: C */
646 tmp = load_cpu_field(CF);
647 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
648 break;
649 case 3: /* cc: !C */
650 tmp = load_cpu_field(CF);
651 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
652 break;
653 case 4: /* mi: N */
654 tmp = load_cpu_field(NF);
655 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
656 break;
657 case 5: /* pl: !N */
658 tmp = load_cpu_field(NF);
659 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
660 break;
661 case 6: /* vs: V */
662 tmp = load_cpu_field(VF);
663 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
664 break;
665 case 7: /* vc: !V */
666 tmp = load_cpu_field(VF);
667 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
668 break;
669 case 8: /* hi: C && !Z */
670 inv = gen_new_label();
671 tmp = load_cpu_field(CF);
672 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
673 dead_tmp(tmp);
674 tmp = load_cpu_field(ZF);
675 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
676 gen_set_label(inv);
677 break;
678 case 9: /* ls: !C || Z */
679 tmp = load_cpu_field(CF);
680 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
681 dead_tmp(tmp);
682 tmp = load_cpu_field(ZF);
683 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
684 break;
685 case 10: /* ge: N == V -> N ^ V == 0 */
686 tmp = load_cpu_field(VF);
687 tmp2 = load_cpu_field(NF);
688 tcg_gen_xor_i32(tmp, tmp, tmp2);
689 dead_tmp(tmp2);
690 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
691 break;
692 case 11: /* lt: N != V -> N ^ V != 0 */
693 tmp = load_cpu_field(VF);
694 tmp2 = load_cpu_field(NF);
695 tcg_gen_xor_i32(tmp, tmp, tmp2);
696 dead_tmp(tmp2);
697 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
698 break;
699 case 12: /* gt: !Z && N == V */
700 inv = gen_new_label();
701 tmp = load_cpu_field(ZF);
702 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
703 dead_tmp(tmp);
704 tmp = load_cpu_field(VF);
705 tmp2 = load_cpu_field(NF);
706 tcg_gen_xor_i32(tmp, tmp, tmp2);
707 dead_tmp(tmp2);
708 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
709 gen_set_label(inv);
710 break;
711 case 13: /* le: Z || N != V */
712 tmp = load_cpu_field(ZF);
713 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
714 dead_tmp(tmp);
715 tmp = load_cpu_field(VF);
716 tmp2 = load_cpu_field(NF);
717 tcg_gen_xor_i32(tmp, tmp, tmp2);
718 dead_tmp(tmp2);
719 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
720 break;
721 default:
722 fprintf(stderr, "Bad condition code 0x%x\n", cc);
723 abort();
725 dead_tmp(tmp);
728 static const uint8_t table_logic_cc[16] = {
729 1, /* and */
730 1, /* xor */
731 0, /* sub */
732 0, /* rsb */
733 0, /* add */
734 0, /* adc */
735 0, /* sbc */
736 0, /* rsc */
737 1, /* andl */
738 1, /* xorl */
739 0, /* cmp */
740 0, /* cmn */
741 1, /* orr */
742 1, /* mov */
743 1, /* bic */
744 1, /* mvn */
747 /* Set PC and Thumb state from an immediate address. */
748 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
750 TCGv tmp;
752 s->is_jmp = DISAS_UPDATE;
753 if (s->thumb != (addr & 1)) {
754 tmp = new_tmp();
755 tcg_gen_movi_i32(tmp, addr & 1);
756 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
757 dead_tmp(tmp);
759 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
762 /* Set PC and Thumb state from var. var is marked as dead. */
763 static inline void gen_bx(DisasContext *s, TCGv var)
765 s->is_jmp = DISAS_UPDATE;
766 tcg_gen_andi_i32(cpu_R[15], var, ~1);
767 tcg_gen_andi_i32(var, var, 1);
768 store_cpu_field(var, thumb);
771 /* Variant of store_reg which uses branch&exchange logic when storing
772 to r15 in ARM architecture v7 and above. The source must be a temporary
773 and will be marked as dead. */
774 static inline void store_reg_bx(CPUState *env, DisasContext *s,
775 int reg, TCGv var)
777 if (reg == 15 && ENABLE_ARCH_7) {
778 gen_bx(s, var);
779 } else {
780 store_reg(s, reg, var);
784 static inline TCGv gen_ld8s(TCGv addr, int index)
786 TCGv tmp = new_tmp();
787 tcg_gen_qemu_ld8s(tmp, addr, index);
788 return tmp;
790 static inline TCGv gen_ld8u(TCGv addr, int index)
792 TCGv tmp = new_tmp();
793 tcg_gen_qemu_ld8u(tmp, addr, index);
794 return tmp;
796 static inline TCGv gen_ld16s(TCGv addr, int index)
798 TCGv tmp = new_tmp();
799 tcg_gen_qemu_ld16s(tmp, addr, index);
800 return tmp;
802 static inline TCGv gen_ld16u(TCGv addr, int index)
804 TCGv tmp = new_tmp();
805 tcg_gen_qemu_ld16u(tmp, addr, index);
806 return tmp;
808 static inline TCGv gen_ld32(TCGv addr, int index)
810 TCGv tmp = new_tmp();
811 tcg_gen_qemu_ld32u(tmp, addr, index);
812 return tmp;
814 static inline void gen_st8(TCGv val, TCGv addr, int index)
816 tcg_gen_qemu_st8(val, addr, index);
817 dead_tmp(val);
819 static inline void gen_st16(TCGv val, TCGv addr, int index)
821 tcg_gen_qemu_st16(val, addr, index);
822 dead_tmp(val);
824 static inline void gen_st32(TCGv val, TCGv addr, int index)
826 tcg_gen_qemu_st32(val, addr, index);
827 dead_tmp(val);
830 static inline void gen_set_pc_im(uint32_t val)
832 tcg_gen_movi_i32(cpu_R[15], val);
835 /* Force a TB lookup after an instruction that changes the CPU state. */
836 static inline void gen_lookup_tb(DisasContext *s)
838 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
839 s->is_jmp = DISAS_UPDATE;
842 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
843 TCGv var)
845 int val, rm, shift, shiftop;
846 TCGv offset;
848 if (!(insn & (1 << 25))) {
849 /* immediate */
850 val = insn & 0xfff;
851 if (!(insn & (1 << 23)))
852 val = -val;
853 if (val != 0)
854 tcg_gen_addi_i32(var, var, val);
855 } else {
856 /* shift/register */
857 rm = (insn) & 0xf;
858 shift = (insn >> 7) & 0x1f;
859 shiftop = (insn >> 5) & 3;
860 offset = load_reg(s, rm);
861 gen_arm_shift_im(offset, shiftop, shift, 0);
862 if (!(insn & (1 << 23)))
863 tcg_gen_sub_i32(var, var, offset);
864 else
865 tcg_gen_add_i32(var, var, offset);
866 dead_tmp(offset);
870 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
871 int extra, TCGv var)
873 int val, rm;
874 TCGv offset;
876 if (insn & (1 << 22)) {
877 /* immediate */
878 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
879 if (!(insn & (1 << 23)))
880 val = -val;
881 val += extra;
882 if (val != 0)
883 tcg_gen_addi_i32(var, var, val);
884 } else {
885 /* register */
886 if (extra)
887 tcg_gen_addi_i32(var, var, extra);
888 rm = (insn) & 0xf;
889 offset = load_reg(s, rm);
890 if (!(insn & (1 << 23)))
891 tcg_gen_sub_i32(var, var, offset);
892 else
893 tcg_gen_add_i32(var, var, offset);
894 dead_tmp(offset);
898 #define VFP_OP2(name) \
899 static inline void gen_vfp_##name(int dp) \
901 if (dp) \
902 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
903 else \
904 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
907 VFP_OP2(add)
908 VFP_OP2(sub)
909 VFP_OP2(mul)
910 VFP_OP2(div)
912 #undef VFP_OP2
914 static inline void gen_vfp_abs(int dp)
916 if (dp)
917 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
918 else
919 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
922 static inline void gen_vfp_neg(int dp)
924 if (dp)
925 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
926 else
927 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
930 static inline void gen_vfp_sqrt(int dp)
932 if (dp)
933 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
934 else
935 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
938 static inline void gen_vfp_cmp(int dp)
940 if (dp)
941 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
942 else
943 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
946 static inline void gen_vfp_cmpe(int dp)
948 if (dp)
949 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
950 else
951 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
954 static inline void gen_vfp_F1_ld0(int dp)
956 if (dp)
957 tcg_gen_movi_i64(cpu_F1d, 0);
958 else
959 tcg_gen_movi_i32(cpu_F1s, 0);
962 static inline void gen_vfp_uito(int dp)
964 if (dp)
965 gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
966 else
967 gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
970 static inline void gen_vfp_sito(int dp)
972 if (dp)
973 gen_helper_vfp_sitod(cpu_F0d, cpu_F0s, cpu_env);
974 else
975 gen_helper_vfp_sitos(cpu_F0s, cpu_F0s, cpu_env);
978 static inline void gen_vfp_toui(int dp)
980 if (dp)
981 gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env);
982 else
983 gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env);
986 static inline void gen_vfp_touiz(int dp)
988 if (dp)
989 gen_helper_vfp_touizd(cpu_F0s, cpu_F0d, cpu_env);
990 else
991 gen_helper_vfp_touizs(cpu_F0s, cpu_F0s, cpu_env);
994 static inline void gen_vfp_tosi(int dp)
996 if (dp)
997 gen_helper_vfp_tosid(cpu_F0s, cpu_F0d, cpu_env);
998 else
999 gen_helper_vfp_tosis(cpu_F0s, cpu_F0s, cpu_env);
1002 static inline void gen_vfp_tosiz(int dp)
1004 if (dp)
1005 gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env);
1006 else
1007 gen_helper_vfp_tosizs(cpu_F0s, cpu_F0s, cpu_env);
1010 #define VFP_GEN_FIX(name) \
1011 static inline void gen_vfp_##name(int dp, int shift) \
1013 TCGv tmp_shift = tcg_const_i32(shift); \
1014 if (dp) \
1015 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, cpu_env);\
1016 else \
1017 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, cpu_env);\
1018 tcg_temp_free_i32(tmp_shift); \
1020 VFP_GEN_FIX(tosh)
1021 VFP_GEN_FIX(tosl)
1022 VFP_GEN_FIX(touh)
1023 VFP_GEN_FIX(toul)
1024 VFP_GEN_FIX(shto)
1025 VFP_GEN_FIX(slto)
1026 VFP_GEN_FIX(uhto)
1027 VFP_GEN_FIX(ulto)
1028 #undef VFP_GEN_FIX
1030 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv addr)
1032 if (dp)
1033 tcg_gen_qemu_ld64(cpu_F0d, addr, IS_USER(s));
1034 else
1035 tcg_gen_qemu_ld32u(cpu_F0s, addr, IS_USER(s));
1038 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv addr)
1040 if (dp)
1041 tcg_gen_qemu_st64(cpu_F0d, addr, IS_USER(s));
1042 else
1043 tcg_gen_qemu_st32(cpu_F0s, addr, IS_USER(s));
1046 static inline long
1047 vfp_reg_offset (int dp, int reg)
1049 if (dp)
1050 return offsetof(CPUARMState, vfp.regs[reg]);
1051 else if (reg & 1) {
1052 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1053 + offsetof(CPU_DoubleU, l.upper);
1054 } else {
1055 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1056 + offsetof(CPU_DoubleU, l.lower);
1060 /* Return the offset of a 32-bit piece of a NEON register.
1061 zero is the least significant end of the register. */
1062 static inline long
1063 neon_reg_offset (int reg, int n)
1065 int sreg;
1066 sreg = reg * 2 + n;
1067 return vfp_reg_offset(0, sreg);
1070 static TCGv neon_load_reg(int reg, int pass)
1072 TCGv tmp = new_tmp();
1073 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1074 return tmp;
1077 static void neon_store_reg(int reg, int pass, TCGv var)
1079 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1080 dead_tmp(var);
1083 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1085 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1088 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1090 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1093 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1094 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1095 #define tcg_gen_st_f32 tcg_gen_st_i32
1096 #define tcg_gen_st_f64 tcg_gen_st_i64
1098 static inline void gen_mov_F0_vreg(int dp, int reg)
1100 if (dp)
1101 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1102 else
1103 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1106 static inline void gen_mov_F1_vreg(int dp, int reg)
1108 if (dp)
1109 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1110 else
1111 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1114 static inline void gen_mov_vreg_F0(int dp, int reg)
1116 if (dp)
1117 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1118 else
1119 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1122 #define ARM_CP_RW_BIT (1 << 20)
1124 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1126 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1129 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1131 tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1134 static inline TCGv iwmmxt_load_creg(int reg)
1136 TCGv var = new_tmp();
1137 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1138 return var;
1141 static inline void iwmmxt_store_creg(int reg, TCGv var)
1143 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1146 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1148 iwmmxt_store_reg(cpu_M0, rn);
1151 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1153 iwmmxt_load_reg(cpu_M0, rn);
1156 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1158 iwmmxt_load_reg(cpu_V1, rn);
1159 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1162 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1164 iwmmxt_load_reg(cpu_V1, rn);
1165 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1168 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1170 iwmmxt_load_reg(cpu_V1, rn);
1171 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1174 #define IWMMXT_OP(name) \
1175 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1177 iwmmxt_load_reg(cpu_V1, rn); \
1178 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1181 #define IWMMXT_OP_ENV(name) \
1182 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1184 iwmmxt_load_reg(cpu_V1, rn); \
1185 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1188 #define IWMMXT_OP_ENV_SIZE(name) \
1189 IWMMXT_OP_ENV(name##b) \
1190 IWMMXT_OP_ENV(name##w) \
1191 IWMMXT_OP_ENV(name##l)
1193 #define IWMMXT_OP_ENV1(name) \
1194 static inline void gen_op_iwmmxt_##name##_M0(void) \
1196 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1199 IWMMXT_OP(maddsq)
1200 IWMMXT_OP(madduq)
1201 IWMMXT_OP(sadb)
1202 IWMMXT_OP(sadw)
1203 IWMMXT_OP(mulslw)
1204 IWMMXT_OP(mulshw)
1205 IWMMXT_OP(mululw)
1206 IWMMXT_OP(muluhw)
1207 IWMMXT_OP(macsw)
1208 IWMMXT_OP(macuw)
1210 IWMMXT_OP_ENV_SIZE(unpackl)
1211 IWMMXT_OP_ENV_SIZE(unpackh)
1213 IWMMXT_OP_ENV1(unpacklub)
1214 IWMMXT_OP_ENV1(unpackluw)
1215 IWMMXT_OP_ENV1(unpacklul)
1216 IWMMXT_OP_ENV1(unpackhub)
1217 IWMMXT_OP_ENV1(unpackhuw)
1218 IWMMXT_OP_ENV1(unpackhul)
1219 IWMMXT_OP_ENV1(unpacklsb)
1220 IWMMXT_OP_ENV1(unpacklsw)
1221 IWMMXT_OP_ENV1(unpacklsl)
1222 IWMMXT_OP_ENV1(unpackhsb)
1223 IWMMXT_OP_ENV1(unpackhsw)
1224 IWMMXT_OP_ENV1(unpackhsl)
1226 IWMMXT_OP_ENV_SIZE(cmpeq)
1227 IWMMXT_OP_ENV_SIZE(cmpgtu)
1228 IWMMXT_OP_ENV_SIZE(cmpgts)
1230 IWMMXT_OP_ENV_SIZE(mins)
1231 IWMMXT_OP_ENV_SIZE(minu)
1232 IWMMXT_OP_ENV_SIZE(maxs)
1233 IWMMXT_OP_ENV_SIZE(maxu)
1235 IWMMXT_OP_ENV_SIZE(subn)
1236 IWMMXT_OP_ENV_SIZE(addn)
1237 IWMMXT_OP_ENV_SIZE(subu)
1238 IWMMXT_OP_ENV_SIZE(addu)
1239 IWMMXT_OP_ENV_SIZE(subs)
1240 IWMMXT_OP_ENV_SIZE(adds)
1242 IWMMXT_OP_ENV(avgb0)
1243 IWMMXT_OP_ENV(avgb1)
1244 IWMMXT_OP_ENV(avgw0)
1245 IWMMXT_OP_ENV(avgw1)
1247 IWMMXT_OP(msadb)
1249 IWMMXT_OP_ENV(packuw)
1250 IWMMXT_OP_ENV(packul)
1251 IWMMXT_OP_ENV(packuq)
1252 IWMMXT_OP_ENV(packsw)
1253 IWMMXT_OP_ENV(packsl)
1254 IWMMXT_OP_ENV(packsq)
1256 static void gen_op_iwmmxt_set_mup(void)
1258 TCGv tmp;
1259 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1260 tcg_gen_ori_i32(tmp, tmp, 2);
1261 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1264 static void gen_op_iwmmxt_set_cup(void)
1266 TCGv tmp;
1267 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1268 tcg_gen_ori_i32(tmp, tmp, 1);
1269 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1272 static void gen_op_iwmmxt_setpsr_nz(void)
1274 TCGv tmp = new_tmp();
1275 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1276 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1279 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1281 iwmmxt_load_reg(cpu_V1, rn);
1282 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1283 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1286 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn, TCGv dest)
1288 int rd;
1289 uint32_t offset;
1290 TCGv tmp;
1292 rd = (insn >> 16) & 0xf;
1293 tmp = load_reg(s, rd);
1295 offset = (insn & 0xff) << ((insn >> 7) & 2);
1296 if (insn & (1 << 24)) {
1297 /* Pre indexed */
1298 if (insn & (1 << 23))
1299 tcg_gen_addi_i32(tmp, tmp, offset);
1300 else
1301 tcg_gen_addi_i32(tmp, tmp, -offset);
1302 tcg_gen_mov_i32(dest, tmp);
1303 if (insn & (1 << 21))
1304 store_reg(s, rd, tmp);
1305 else
1306 dead_tmp(tmp);
1307 } else if (insn & (1 << 21)) {
1308 /* Post indexed */
1309 tcg_gen_mov_i32(dest, tmp);
1310 if (insn & (1 << 23))
1311 tcg_gen_addi_i32(tmp, tmp, offset);
1312 else
1313 tcg_gen_addi_i32(tmp, tmp, -offset);
1314 store_reg(s, rd, tmp);
1315 } else if (!(insn & (1 << 23)))
1316 return 1;
1317 return 0;
1320 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv dest)
1322 int rd = (insn >> 0) & 0xf;
1323 TCGv tmp;
1325 if (insn & (1 << 8)) {
1326 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1327 return 1;
1328 } else {
1329 tmp = iwmmxt_load_creg(rd);
1331 } else {
1332 tmp = new_tmp();
1333 iwmmxt_load_reg(cpu_V0, rd);
1334 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
1336 tcg_gen_andi_i32(tmp, tmp, mask);
1337 tcg_gen_mov_i32(dest, tmp);
1338 dead_tmp(tmp);
1339 return 0;
1342 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1343 (ie. an undefined instruction). */
1344 static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1346 int rd, wrd;
1347 int rdhi, rdlo, rd0, rd1, i;
1348 TCGv addr;
1349 TCGv tmp, tmp2, tmp3;
1351 if ((insn & 0x0e000e00) == 0x0c000000) {
1352 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1353 wrd = insn & 0xf;
1354 rdlo = (insn >> 12) & 0xf;
1355 rdhi = (insn >> 16) & 0xf;
1356 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1357 iwmmxt_load_reg(cpu_V0, wrd);
1358 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
1359 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1360 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
1361 } else { /* TMCRR */
1362 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1363 iwmmxt_store_reg(cpu_V0, wrd);
1364 gen_op_iwmmxt_set_mup();
1366 return 0;
1369 wrd = (insn >> 12) & 0xf;
1370 addr = new_tmp();
1371 if (gen_iwmmxt_address(s, insn, addr)) {
1372 dead_tmp(addr);
1373 return 1;
1375 if (insn & ARM_CP_RW_BIT) {
1376 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1377 tmp = new_tmp();
1378 tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s));
1379 iwmmxt_store_creg(wrd, tmp);
1380 } else {
1381 i = 1;
1382 if (insn & (1 << 8)) {
1383 if (insn & (1 << 22)) { /* WLDRD */
1384 tcg_gen_qemu_ld64(cpu_M0, addr, IS_USER(s));
1385 i = 0;
1386 } else { /* WLDRW wRd */
1387 tmp = gen_ld32(addr, IS_USER(s));
1389 } else {
1390 if (insn & (1 << 22)) { /* WLDRH */
1391 tmp = gen_ld16u(addr, IS_USER(s));
1392 } else { /* WLDRB */
1393 tmp = gen_ld8u(addr, IS_USER(s));
1396 if (i) {
1397 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1398 dead_tmp(tmp);
1400 gen_op_iwmmxt_movq_wRn_M0(wrd);
1402 } else {
1403 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1404 tmp = iwmmxt_load_creg(wrd);
1405 gen_st32(tmp, addr, IS_USER(s));
1406 } else {
1407 gen_op_iwmmxt_movq_M0_wRn(wrd);
1408 tmp = new_tmp();
1409 if (insn & (1 << 8)) {
1410 if (insn & (1 << 22)) { /* WSTRD */
1411 dead_tmp(tmp);
1412 tcg_gen_qemu_st64(cpu_M0, addr, IS_USER(s));
1413 } else { /* WSTRW wRd */
1414 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1415 gen_st32(tmp, addr, IS_USER(s));
1417 } else {
1418 if (insn & (1 << 22)) { /* WSTRH */
1419 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1420 gen_st16(tmp, addr, IS_USER(s));
1421 } else { /* WSTRB */
1422 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1423 gen_st8(tmp, addr, IS_USER(s));
1428 return 0;
1431 if ((insn & 0x0f000000) != 0x0e000000)
1432 return 1;
1434 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1435 case 0x000: /* WOR */
1436 wrd = (insn >> 12) & 0xf;
1437 rd0 = (insn >> 0) & 0xf;
1438 rd1 = (insn >> 16) & 0xf;
1439 gen_op_iwmmxt_movq_M0_wRn(rd0);
1440 gen_op_iwmmxt_orq_M0_wRn(rd1);
1441 gen_op_iwmmxt_setpsr_nz();
1442 gen_op_iwmmxt_movq_wRn_M0(wrd);
1443 gen_op_iwmmxt_set_mup();
1444 gen_op_iwmmxt_set_cup();
1445 break;
1446 case 0x011: /* TMCR */
1447 if (insn & 0xf)
1448 return 1;
1449 rd = (insn >> 12) & 0xf;
1450 wrd = (insn >> 16) & 0xf;
1451 switch (wrd) {
1452 case ARM_IWMMXT_wCID:
1453 case ARM_IWMMXT_wCASF:
1454 break;
1455 case ARM_IWMMXT_wCon:
1456 gen_op_iwmmxt_set_cup();
1457 /* Fall through. */
1458 case ARM_IWMMXT_wCSSF:
1459 tmp = iwmmxt_load_creg(wrd);
1460 tmp2 = load_reg(s, rd);
1461 tcg_gen_bic_i32(tmp, tmp, tmp2);
1462 dead_tmp(tmp2);
1463 iwmmxt_store_creg(wrd, tmp);
1464 break;
1465 case ARM_IWMMXT_wCGR0:
1466 case ARM_IWMMXT_wCGR1:
1467 case ARM_IWMMXT_wCGR2:
1468 case ARM_IWMMXT_wCGR3:
1469 gen_op_iwmmxt_set_cup();
1470 tmp = load_reg(s, rd);
1471 iwmmxt_store_creg(wrd, tmp);
1472 break;
1473 default:
1474 return 1;
1476 break;
1477 case 0x100: /* WXOR */
1478 wrd = (insn >> 12) & 0xf;
1479 rd0 = (insn >> 0) & 0xf;
1480 rd1 = (insn >> 16) & 0xf;
1481 gen_op_iwmmxt_movq_M0_wRn(rd0);
1482 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1483 gen_op_iwmmxt_setpsr_nz();
1484 gen_op_iwmmxt_movq_wRn_M0(wrd);
1485 gen_op_iwmmxt_set_mup();
1486 gen_op_iwmmxt_set_cup();
1487 break;
1488 case 0x111: /* TMRC */
1489 if (insn & 0xf)
1490 return 1;
1491 rd = (insn >> 12) & 0xf;
1492 wrd = (insn >> 16) & 0xf;
1493 tmp = iwmmxt_load_creg(wrd);
1494 store_reg(s, rd, tmp);
1495 break;
1496 case 0x300: /* WANDN */
1497 wrd = (insn >> 12) & 0xf;
1498 rd0 = (insn >> 0) & 0xf;
1499 rd1 = (insn >> 16) & 0xf;
1500 gen_op_iwmmxt_movq_M0_wRn(rd0);
1501 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1502 gen_op_iwmmxt_andq_M0_wRn(rd1);
1503 gen_op_iwmmxt_setpsr_nz();
1504 gen_op_iwmmxt_movq_wRn_M0(wrd);
1505 gen_op_iwmmxt_set_mup();
1506 gen_op_iwmmxt_set_cup();
1507 break;
1508 case 0x200: /* WAND */
1509 wrd = (insn >> 12) & 0xf;
1510 rd0 = (insn >> 0) & 0xf;
1511 rd1 = (insn >> 16) & 0xf;
1512 gen_op_iwmmxt_movq_M0_wRn(rd0);
1513 gen_op_iwmmxt_andq_M0_wRn(rd1);
1514 gen_op_iwmmxt_setpsr_nz();
1515 gen_op_iwmmxt_movq_wRn_M0(wrd);
1516 gen_op_iwmmxt_set_mup();
1517 gen_op_iwmmxt_set_cup();
1518 break;
1519 case 0x810: case 0xa10: /* WMADD */
1520 wrd = (insn >> 12) & 0xf;
1521 rd0 = (insn >> 0) & 0xf;
1522 rd1 = (insn >> 16) & 0xf;
1523 gen_op_iwmmxt_movq_M0_wRn(rd0);
1524 if (insn & (1 << 21))
1525 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1526 else
1527 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1528 gen_op_iwmmxt_movq_wRn_M0(wrd);
1529 gen_op_iwmmxt_set_mup();
1530 break;
1531 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1532 wrd = (insn >> 12) & 0xf;
1533 rd0 = (insn >> 16) & 0xf;
1534 rd1 = (insn >> 0) & 0xf;
1535 gen_op_iwmmxt_movq_M0_wRn(rd0);
1536 switch ((insn >> 22) & 3) {
1537 case 0:
1538 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1539 break;
1540 case 1:
1541 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1542 break;
1543 case 2:
1544 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1545 break;
1546 case 3:
1547 return 1;
1549 gen_op_iwmmxt_movq_wRn_M0(wrd);
1550 gen_op_iwmmxt_set_mup();
1551 gen_op_iwmmxt_set_cup();
1552 break;
1553 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1554 wrd = (insn >> 12) & 0xf;
1555 rd0 = (insn >> 16) & 0xf;
1556 rd1 = (insn >> 0) & 0xf;
1557 gen_op_iwmmxt_movq_M0_wRn(rd0);
1558 switch ((insn >> 22) & 3) {
1559 case 0:
1560 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1561 break;
1562 case 1:
1563 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1564 break;
1565 case 2:
1566 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1567 break;
1568 case 3:
1569 return 1;
1571 gen_op_iwmmxt_movq_wRn_M0(wrd);
1572 gen_op_iwmmxt_set_mup();
1573 gen_op_iwmmxt_set_cup();
1574 break;
1575 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1576 wrd = (insn >> 12) & 0xf;
1577 rd0 = (insn >> 16) & 0xf;
1578 rd1 = (insn >> 0) & 0xf;
1579 gen_op_iwmmxt_movq_M0_wRn(rd0);
1580 if (insn & (1 << 22))
1581 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1582 else
1583 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1584 if (!(insn & (1 << 20)))
1585 gen_op_iwmmxt_addl_M0_wRn(wrd);
1586 gen_op_iwmmxt_movq_wRn_M0(wrd);
1587 gen_op_iwmmxt_set_mup();
1588 break;
1589 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1590 wrd = (insn >> 12) & 0xf;
1591 rd0 = (insn >> 16) & 0xf;
1592 rd1 = (insn >> 0) & 0xf;
1593 gen_op_iwmmxt_movq_M0_wRn(rd0);
1594 if (insn & (1 << 21)) {
1595 if (insn & (1 << 20))
1596 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1597 else
1598 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1599 } else {
1600 if (insn & (1 << 20))
1601 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1602 else
1603 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1605 gen_op_iwmmxt_movq_wRn_M0(wrd);
1606 gen_op_iwmmxt_set_mup();
1607 break;
1608 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1609 wrd = (insn >> 12) & 0xf;
1610 rd0 = (insn >> 16) & 0xf;
1611 rd1 = (insn >> 0) & 0xf;
1612 gen_op_iwmmxt_movq_M0_wRn(rd0);
1613 if (insn & (1 << 21))
1614 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1615 else
1616 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1617 if (!(insn & (1 << 20))) {
1618 iwmmxt_load_reg(cpu_V1, wrd);
1619 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1621 gen_op_iwmmxt_movq_wRn_M0(wrd);
1622 gen_op_iwmmxt_set_mup();
1623 break;
1624 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1625 wrd = (insn >> 12) & 0xf;
1626 rd0 = (insn >> 16) & 0xf;
1627 rd1 = (insn >> 0) & 0xf;
1628 gen_op_iwmmxt_movq_M0_wRn(rd0);
1629 switch ((insn >> 22) & 3) {
1630 case 0:
1631 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1632 break;
1633 case 1:
1634 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1635 break;
1636 case 2:
1637 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1638 break;
1639 case 3:
1640 return 1;
1642 gen_op_iwmmxt_movq_wRn_M0(wrd);
1643 gen_op_iwmmxt_set_mup();
1644 gen_op_iwmmxt_set_cup();
1645 break;
1646 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1647 wrd = (insn >> 12) & 0xf;
1648 rd0 = (insn >> 16) & 0xf;
1649 rd1 = (insn >> 0) & 0xf;
1650 gen_op_iwmmxt_movq_M0_wRn(rd0);
1651 if (insn & (1 << 22)) {
1652 if (insn & (1 << 20))
1653 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1654 else
1655 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1656 } else {
1657 if (insn & (1 << 20))
1658 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1659 else
1660 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1662 gen_op_iwmmxt_movq_wRn_M0(wrd);
1663 gen_op_iwmmxt_set_mup();
1664 gen_op_iwmmxt_set_cup();
1665 break;
1666 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1667 wrd = (insn >> 12) & 0xf;
1668 rd0 = (insn >> 16) & 0xf;
1669 rd1 = (insn >> 0) & 0xf;
1670 gen_op_iwmmxt_movq_M0_wRn(rd0);
1671 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1672 tcg_gen_andi_i32(tmp, tmp, 7);
1673 iwmmxt_load_reg(cpu_V1, rd1);
1674 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
1675 dead_tmp(tmp);
1676 gen_op_iwmmxt_movq_wRn_M0(wrd);
1677 gen_op_iwmmxt_set_mup();
1678 break;
1679 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1680 if (((insn >> 6) & 3) == 3)
1681 return 1;
1682 rd = (insn >> 12) & 0xf;
1683 wrd = (insn >> 16) & 0xf;
1684 tmp = load_reg(s, rd);
1685 gen_op_iwmmxt_movq_M0_wRn(wrd);
1686 switch ((insn >> 6) & 3) {
1687 case 0:
1688 tmp2 = tcg_const_i32(0xff);
1689 tmp3 = tcg_const_i32((insn & 7) << 3);
1690 break;
1691 case 1:
1692 tmp2 = tcg_const_i32(0xffff);
1693 tmp3 = tcg_const_i32((insn & 3) << 4);
1694 break;
1695 case 2:
1696 tmp2 = tcg_const_i32(0xffffffff);
1697 tmp3 = tcg_const_i32((insn & 1) << 5);
1698 break;
1699 default:
1700 TCGV_UNUSED(tmp2);
1701 TCGV_UNUSED(tmp3);
1703 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
1704 tcg_temp_free(tmp3);
1705 tcg_temp_free(tmp2);
1706 dead_tmp(tmp);
1707 gen_op_iwmmxt_movq_wRn_M0(wrd);
1708 gen_op_iwmmxt_set_mup();
1709 break;
1710 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1711 rd = (insn >> 12) & 0xf;
1712 wrd = (insn >> 16) & 0xf;
1713 if (rd == 15 || ((insn >> 22) & 3) == 3)
1714 return 1;
1715 gen_op_iwmmxt_movq_M0_wRn(wrd);
1716 tmp = new_tmp();
1717 switch ((insn >> 22) & 3) {
1718 case 0:
1719 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
1720 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1721 if (insn & 8) {
1722 tcg_gen_ext8s_i32(tmp, tmp);
1723 } else {
1724 tcg_gen_andi_i32(tmp, tmp, 0xff);
1726 break;
1727 case 1:
1728 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
1729 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1730 if (insn & 8) {
1731 tcg_gen_ext16s_i32(tmp, tmp);
1732 } else {
1733 tcg_gen_andi_i32(tmp, tmp, 0xffff);
1735 break;
1736 case 2:
1737 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
1738 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1739 break;
1741 store_reg(s, rd, tmp);
1742 break;
1743 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1744 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1745 return 1;
1746 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1747 switch ((insn >> 22) & 3) {
1748 case 0:
1749 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
1750 break;
1751 case 1:
1752 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
1753 break;
1754 case 2:
1755 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
1756 break;
1758 tcg_gen_shli_i32(tmp, tmp, 28);
1759 gen_set_nzcv(tmp);
1760 dead_tmp(tmp);
1761 break;
1762 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1763 if (((insn >> 6) & 3) == 3)
1764 return 1;
1765 rd = (insn >> 12) & 0xf;
1766 wrd = (insn >> 16) & 0xf;
1767 tmp = load_reg(s, rd);
1768 switch ((insn >> 6) & 3) {
1769 case 0:
1770 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
1771 break;
1772 case 1:
1773 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
1774 break;
1775 case 2:
1776 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
1777 break;
1779 dead_tmp(tmp);
1780 gen_op_iwmmxt_movq_wRn_M0(wrd);
1781 gen_op_iwmmxt_set_mup();
1782 break;
1783 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1784 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1785 return 1;
1786 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1787 tmp2 = new_tmp();
1788 tcg_gen_mov_i32(tmp2, tmp);
1789 switch ((insn >> 22) & 3) {
1790 case 0:
1791 for (i = 0; i < 7; i ++) {
1792 tcg_gen_shli_i32(tmp2, tmp2, 4);
1793 tcg_gen_and_i32(tmp, tmp, tmp2);
1795 break;
1796 case 1:
1797 for (i = 0; i < 3; i ++) {
1798 tcg_gen_shli_i32(tmp2, tmp2, 8);
1799 tcg_gen_and_i32(tmp, tmp, tmp2);
1801 break;
1802 case 2:
1803 tcg_gen_shli_i32(tmp2, tmp2, 16);
1804 tcg_gen_and_i32(tmp, tmp, tmp2);
1805 break;
1807 gen_set_nzcv(tmp);
1808 dead_tmp(tmp2);
1809 dead_tmp(tmp);
1810 break;
1811 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1812 wrd = (insn >> 12) & 0xf;
1813 rd0 = (insn >> 16) & 0xf;
1814 gen_op_iwmmxt_movq_M0_wRn(rd0);
1815 switch ((insn >> 22) & 3) {
1816 case 0:
1817 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1818 break;
1819 case 1:
1820 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1821 break;
1822 case 2:
1823 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1824 break;
1825 case 3:
1826 return 1;
1828 gen_op_iwmmxt_movq_wRn_M0(wrd);
1829 gen_op_iwmmxt_set_mup();
1830 break;
1831 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1832 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1833 return 1;
1834 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1835 tmp2 = new_tmp();
1836 tcg_gen_mov_i32(tmp2, tmp);
1837 switch ((insn >> 22) & 3) {
1838 case 0:
1839 for (i = 0; i < 7; i ++) {
1840 tcg_gen_shli_i32(tmp2, tmp2, 4);
1841 tcg_gen_or_i32(tmp, tmp, tmp2);
1843 break;
1844 case 1:
1845 for (i = 0; i < 3; i ++) {
1846 tcg_gen_shli_i32(tmp2, tmp2, 8);
1847 tcg_gen_or_i32(tmp, tmp, tmp2);
1849 break;
1850 case 2:
1851 tcg_gen_shli_i32(tmp2, tmp2, 16);
1852 tcg_gen_or_i32(tmp, tmp, tmp2);
1853 break;
1855 gen_set_nzcv(tmp);
1856 dead_tmp(tmp2);
1857 dead_tmp(tmp);
1858 break;
1859 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1860 rd = (insn >> 12) & 0xf;
1861 rd0 = (insn >> 16) & 0xf;
1862 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
1863 return 1;
1864 gen_op_iwmmxt_movq_M0_wRn(rd0);
1865 tmp = new_tmp();
1866 switch ((insn >> 22) & 3) {
1867 case 0:
1868 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
1869 break;
1870 case 1:
1871 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
1872 break;
1873 case 2:
1874 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
1875 break;
1877 store_reg(s, rd, tmp);
1878 break;
1879 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1880 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1881 wrd = (insn >> 12) & 0xf;
1882 rd0 = (insn >> 16) & 0xf;
1883 rd1 = (insn >> 0) & 0xf;
1884 gen_op_iwmmxt_movq_M0_wRn(rd0);
1885 switch ((insn >> 22) & 3) {
1886 case 0:
1887 if (insn & (1 << 21))
1888 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1889 else
1890 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1891 break;
1892 case 1:
1893 if (insn & (1 << 21))
1894 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1895 else
1896 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
1897 break;
1898 case 2:
1899 if (insn & (1 << 21))
1900 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
1901 else
1902 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
1903 break;
1904 case 3:
1905 return 1;
1907 gen_op_iwmmxt_movq_wRn_M0(wrd);
1908 gen_op_iwmmxt_set_mup();
1909 gen_op_iwmmxt_set_cup();
1910 break;
1911 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1912 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1913 wrd = (insn >> 12) & 0xf;
1914 rd0 = (insn >> 16) & 0xf;
1915 gen_op_iwmmxt_movq_M0_wRn(rd0);
1916 switch ((insn >> 22) & 3) {
1917 case 0:
1918 if (insn & (1 << 21))
1919 gen_op_iwmmxt_unpacklsb_M0();
1920 else
1921 gen_op_iwmmxt_unpacklub_M0();
1922 break;
1923 case 1:
1924 if (insn & (1 << 21))
1925 gen_op_iwmmxt_unpacklsw_M0();
1926 else
1927 gen_op_iwmmxt_unpackluw_M0();
1928 break;
1929 case 2:
1930 if (insn & (1 << 21))
1931 gen_op_iwmmxt_unpacklsl_M0();
1932 else
1933 gen_op_iwmmxt_unpacklul_M0();
1934 break;
1935 case 3:
1936 return 1;
1938 gen_op_iwmmxt_movq_wRn_M0(wrd);
1939 gen_op_iwmmxt_set_mup();
1940 gen_op_iwmmxt_set_cup();
1941 break;
1942 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
1943 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1944 wrd = (insn >> 12) & 0xf;
1945 rd0 = (insn >> 16) & 0xf;
1946 gen_op_iwmmxt_movq_M0_wRn(rd0);
1947 switch ((insn >> 22) & 3) {
1948 case 0:
1949 if (insn & (1 << 21))
1950 gen_op_iwmmxt_unpackhsb_M0();
1951 else
1952 gen_op_iwmmxt_unpackhub_M0();
1953 break;
1954 case 1:
1955 if (insn & (1 << 21))
1956 gen_op_iwmmxt_unpackhsw_M0();
1957 else
1958 gen_op_iwmmxt_unpackhuw_M0();
1959 break;
1960 case 2:
1961 if (insn & (1 << 21))
1962 gen_op_iwmmxt_unpackhsl_M0();
1963 else
1964 gen_op_iwmmxt_unpackhul_M0();
1965 break;
1966 case 3:
1967 return 1;
1969 gen_op_iwmmxt_movq_wRn_M0(wrd);
1970 gen_op_iwmmxt_set_mup();
1971 gen_op_iwmmxt_set_cup();
1972 break;
1973 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
1974 case 0x214: case 0x614: case 0xa14: case 0xe14:
1975 if (((insn >> 22) & 3) == 0)
1976 return 1;
1977 wrd = (insn >> 12) & 0xf;
1978 rd0 = (insn >> 16) & 0xf;
1979 gen_op_iwmmxt_movq_M0_wRn(rd0);
1980 tmp = new_tmp();
1981 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
1982 dead_tmp(tmp);
1983 return 1;
1985 switch ((insn >> 22) & 3) {
1986 case 1:
1987 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
1988 break;
1989 case 2:
1990 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
1991 break;
1992 case 3:
1993 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
1994 break;
1996 dead_tmp(tmp);
1997 gen_op_iwmmxt_movq_wRn_M0(wrd);
1998 gen_op_iwmmxt_set_mup();
1999 gen_op_iwmmxt_set_cup();
2000 break;
2001 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2002 case 0x014: case 0x414: case 0x814: case 0xc14:
2003 if (((insn >> 22) & 3) == 0)
2004 return 1;
2005 wrd = (insn >> 12) & 0xf;
2006 rd0 = (insn >> 16) & 0xf;
2007 gen_op_iwmmxt_movq_M0_wRn(rd0);
2008 tmp = new_tmp();
2009 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2010 dead_tmp(tmp);
2011 return 1;
2013 switch ((insn >> 22) & 3) {
2014 case 1:
2015 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2016 break;
2017 case 2:
2018 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2019 break;
2020 case 3:
2021 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2022 break;
2024 dead_tmp(tmp);
2025 gen_op_iwmmxt_movq_wRn_M0(wrd);
2026 gen_op_iwmmxt_set_mup();
2027 gen_op_iwmmxt_set_cup();
2028 break;
2029 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2030 case 0x114: case 0x514: case 0x914: case 0xd14:
2031 if (((insn >> 22) & 3) == 0)
2032 return 1;
2033 wrd = (insn >> 12) & 0xf;
2034 rd0 = (insn >> 16) & 0xf;
2035 gen_op_iwmmxt_movq_M0_wRn(rd0);
2036 tmp = new_tmp();
2037 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2038 dead_tmp(tmp);
2039 return 1;
2041 switch ((insn >> 22) & 3) {
2042 case 1:
2043 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2044 break;
2045 case 2:
2046 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2047 break;
2048 case 3:
2049 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2050 break;
2052 dead_tmp(tmp);
2053 gen_op_iwmmxt_movq_wRn_M0(wrd);
2054 gen_op_iwmmxt_set_mup();
2055 gen_op_iwmmxt_set_cup();
2056 break;
2057 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2058 case 0x314: case 0x714: case 0xb14: case 0xf14:
2059 if (((insn >> 22) & 3) == 0)
2060 return 1;
2061 wrd = (insn >> 12) & 0xf;
2062 rd0 = (insn >> 16) & 0xf;
2063 gen_op_iwmmxt_movq_M0_wRn(rd0);
2064 tmp = new_tmp();
2065 switch ((insn >> 22) & 3) {
2066 case 1:
2067 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2068 dead_tmp(tmp);
2069 return 1;
2071 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2072 break;
2073 case 2:
2074 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2075 dead_tmp(tmp);
2076 return 1;
2078 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2079 break;
2080 case 3:
2081 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2082 dead_tmp(tmp);
2083 return 1;
2085 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2086 break;
2088 dead_tmp(tmp);
2089 gen_op_iwmmxt_movq_wRn_M0(wrd);
2090 gen_op_iwmmxt_set_mup();
2091 gen_op_iwmmxt_set_cup();
2092 break;
2093 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2094 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2095 wrd = (insn >> 12) & 0xf;
2096 rd0 = (insn >> 16) & 0xf;
2097 rd1 = (insn >> 0) & 0xf;
2098 gen_op_iwmmxt_movq_M0_wRn(rd0);
2099 switch ((insn >> 22) & 3) {
2100 case 0:
2101 if (insn & (1 << 21))
2102 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2103 else
2104 gen_op_iwmmxt_minub_M0_wRn(rd1);
2105 break;
2106 case 1:
2107 if (insn & (1 << 21))
2108 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2109 else
2110 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2111 break;
2112 case 2:
2113 if (insn & (1 << 21))
2114 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2115 else
2116 gen_op_iwmmxt_minul_M0_wRn(rd1);
2117 break;
2118 case 3:
2119 return 1;
2121 gen_op_iwmmxt_movq_wRn_M0(wrd);
2122 gen_op_iwmmxt_set_mup();
2123 break;
2124 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2125 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2126 wrd = (insn >> 12) & 0xf;
2127 rd0 = (insn >> 16) & 0xf;
2128 rd1 = (insn >> 0) & 0xf;
2129 gen_op_iwmmxt_movq_M0_wRn(rd0);
2130 switch ((insn >> 22) & 3) {
2131 case 0:
2132 if (insn & (1 << 21))
2133 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2134 else
2135 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2136 break;
2137 case 1:
2138 if (insn & (1 << 21))
2139 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2140 else
2141 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2142 break;
2143 case 2:
2144 if (insn & (1 << 21))
2145 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2146 else
2147 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2148 break;
2149 case 3:
2150 return 1;
2152 gen_op_iwmmxt_movq_wRn_M0(wrd);
2153 gen_op_iwmmxt_set_mup();
2154 break;
2155 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2156 case 0x402: case 0x502: case 0x602: case 0x702:
2157 wrd = (insn >> 12) & 0xf;
2158 rd0 = (insn >> 16) & 0xf;
2159 rd1 = (insn >> 0) & 0xf;
2160 gen_op_iwmmxt_movq_M0_wRn(rd0);
2161 tmp = tcg_const_i32((insn >> 20) & 3);
2162 iwmmxt_load_reg(cpu_V1, rd1);
2163 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2164 tcg_temp_free(tmp);
2165 gen_op_iwmmxt_movq_wRn_M0(wrd);
2166 gen_op_iwmmxt_set_mup();
2167 break;
2168 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2169 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2170 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2171 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2172 wrd = (insn >> 12) & 0xf;
2173 rd0 = (insn >> 16) & 0xf;
2174 rd1 = (insn >> 0) & 0xf;
2175 gen_op_iwmmxt_movq_M0_wRn(rd0);
2176 switch ((insn >> 20) & 0xf) {
2177 case 0x0:
2178 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2179 break;
2180 case 0x1:
2181 gen_op_iwmmxt_subub_M0_wRn(rd1);
2182 break;
2183 case 0x3:
2184 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2185 break;
2186 case 0x4:
2187 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2188 break;
2189 case 0x5:
2190 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2191 break;
2192 case 0x7:
2193 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2194 break;
2195 case 0x8:
2196 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2197 break;
2198 case 0x9:
2199 gen_op_iwmmxt_subul_M0_wRn(rd1);
2200 break;
2201 case 0xb:
2202 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2203 break;
2204 default:
2205 return 1;
2207 gen_op_iwmmxt_movq_wRn_M0(wrd);
2208 gen_op_iwmmxt_set_mup();
2209 gen_op_iwmmxt_set_cup();
2210 break;
2211 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2212 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2213 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2214 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2215 wrd = (insn >> 12) & 0xf;
2216 rd0 = (insn >> 16) & 0xf;
2217 gen_op_iwmmxt_movq_M0_wRn(rd0);
2218 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2219 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2220 tcg_temp_free(tmp);
2221 gen_op_iwmmxt_movq_wRn_M0(wrd);
2222 gen_op_iwmmxt_set_mup();
2223 gen_op_iwmmxt_set_cup();
2224 break;
2225 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2226 case 0x418: case 0x518: case 0x618: case 0x718:
2227 case 0x818: case 0x918: case 0xa18: case 0xb18:
2228 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2229 wrd = (insn >> 12) & 0xf;
2230 rd0 = (insn >> 16) & 0xf;
2231 rd1 = (insn >> 0) & 0xf;
2232 gen_op_iwmmxt_movq_M0_wRn(rd0);
2233 switch ((insn >> 20) & 0xf) {
2234 case 0x0:
2235 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2236 break;
2237 case 0x1:
2238 gen_op_iwmmxt_addub_M0_wRn(rd1);
2239 break;
2240 case 0x3:
2241 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2242 break;
2243 case 0x4:
2244 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2245 break;
2246 case 0x5:
2247 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2248 break;
2249 case 0x7:
2250 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2251 break;
2252 case 0x8:
2253 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2254 break;
2255 case 0x9:
2256 gen_op_iwmmxt_addul_M0_wRn(rd1);
2257 break;
2258 case 0xb:
2259 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2260 break;
2261 default:
2262 return 1;
2264 gen_op_iwmmxt_movq_wRn_M0(wrd);
2265 gen_op_iwmmxt_set_mup();
2266 gen_op_iwmmxt_set_cup();
2267 break;
2268 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2269 case 0x408: case 0x508: case 0x608: case 0x708:
2270 case 0x808: case 0x908: case 0xa08: case 0xb08:
2271 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2272 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2273 return 1;
2274 wrd = (insn >> 12) & 0xf;
2275 rd0 = (insn >> 16) & 0xf;
2276 rd1 = (insn >> 0) & 0xf;
2277 gen_op_iwmmxt_movq_M0_wRn(rd0);
2278 switch ((insn >> 22) & 3) {
2279 case 1:
2280 if (insn & (1 << 21))
2281 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2282 else
2283 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2284 break;
2285 case 2:
2286 if (insn & (1 << 21))
2287 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2288 else
2289 gen_op_iwmmxt_packul_M0_wRn(rd1);
2290 break;
2291 case 3:
2292 if (insn & (1 << 21))
2293 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2294 else
2295 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2296 break;
2298 gen_op_iwmmxt_movq_wRn_M0(wrd);
2299 gen_op_iwmmxt_set_mup();
2300 gen_op_iwmmxt_set_cup();
2301 break;
2302 case 0x201: case 0x203: case 0x205: case 0x207:
2303 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2304 case 0x211: case 0x213: case 0x215: case 0x217:
2305 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2306 wrd = (insn >> 5) & 0xf;
2307 rd0 = (insn >> 12) & 0xf;
2308 rd1 = (insn >> 0) & 0xf;
2309 if (rd0 == 0xf || rd1 == 0xf)
2310 return 1;
2311 gen_op_iwmmxt_movq_M0_wRn(wrd);
2312 tmp = load_reg(s, rd0);
2313 tmp2 = load_reg(s, rd1);
2314 switch ((insn >> 16) & 0xf) {
2315 case 0x0: /* TMIA */
2316 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2317 break;
2318 case 0x8: /* TMIAPH */
2319 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2320 break;
2321 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2322 if (insn & (1 << 16))
2323 tcg_gen_shri_i32(tmp, tmp, 16);
2324 if (insn & (1 << 17))
2325 tcg_gen_shri_i32(tmp2, tmp2, 16);
2326 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2327 break;
2328 default:
2329 dead_tmp(tmp2);
2330 dead_tmp(tmp);
2331 return 1;
2333 dead_tmp(tmp2);
2334 dead_tmp(tmp);
2335 gen_op_iwmmxt_movq_wRn_M0(wrd);
2336 gen_op_iwmmxt_set_mup();
2337 break;
2338 default:
2339 return 1;
2342 return 0;
2345 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2346 (ie. an undefined instruction). */
2347 static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2349 int acc, rd0, rd1, rdhi, rdlo;
2350 TCGv tmp, tmp2;
2352 if ((insn & 0x0ff00f10) == 0x0e200010) {
2353 /* Multiply with Internal Accumulate Format */
2354 rd0 = (insn >> 12) & 0xf;
2355 rd1 = insn & 0xf;
2356 acc = (insn >> 5) & 7;
2358 if (acc != 0)
2359 return 1;
2361 tmp = load_reg(s, rd0);
2362 tmp2 = load_reg(s, rd1);
2363 switch ((insn >> 16) & 0xf) {
2364 case 0x0: /* MIA */
2365 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2366 break;
2367 case 0x8: /* MIAPH */
2368 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2369 break;
2370 case 0xc: /* MIABB */
2371 case 0xd: /* MIABT */
2372 case 0xe: /* MIATB */
2373 case 0xf: /* MIATT */
2374 if (insn & (1 << 16))
2375 tcg_gen_shri_i32(tmp, tmp, 16);
2376 if (insn & (1 << 17))
2377 tcg_gen_shri_i32(tmp2, tmp2, 16);
2378 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2379 break;
2380 default:
2381 return 1;
2383 dead_tmp(tmp2);
2384 dead_tmp(tmp);
2386 gen_op_iwmmxt_movq_wRn_M0(acc);
2387 return 0;
2390 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2391 /* Internal Accumulator Access Format */
2392 rdhi = (insn >> 16) & 0xf;
2393 rdlo = (insn >> 12) & 0xf;
2394 acc = insn & 7;
2396 if (acc != 0)
2397 return 1;
2399 if (insn & ARM_CP_RW_BIT) { /* MRA */
2400 iwmmxt_load_reg(cpu_V0, acc);
2401 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
2402 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
2403 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
2404 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2405 } else { /* MAR */
2406 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2407 iwmmxt_store_reg(cpu_V0, acc);
2409 return 0;
2412 return 1;
2415 /* Disassemble system coprocessor instruction. Return nonzero if
2416 instruction is not defined. */
2417 static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2419 TCGv tmp, tmp2;
2420 uint32_t rd = (insn >> 12) & 0xf;
2421 uint32_t cp = (insn >> 8) & 0xf;
2422 if (IS_USER(s)) {
2423 return 1;
2426 if (insn & ARM_CP_RW_BIT) {
2427 if (!env->cp[cp].cp_read)
2428 return 1;
2429 gen_set_pc_im(s->pc);
2430 tmp = new_tmp();
2431 tmp2 = tcg_const_i32(insn);
2432 gen_helper_get_cp(tmp, cpu_env, tmp2);
2433 tcg_temp_free(tmp2);
2434 store_reg(s, rd, tmp);
2435 } else {
2436 if (!env->cp[cp].cp_write)
2437 return 1;
2438 gen_set_pc_im(s->pc);
2439 tmp = load_reg(s, rd);
2440 tmp2 = tcg_const_i32(insn);
2441 gen_helper_set_cp(cpu_env, tmp2, tmp);
2442 tcg_temp_free(tmp2);
2443 dead_tmp(tmp);
2445 return 0;
2448 static int cp15_user_ok(uint32_t insn)
2450 int cpn = (insn >> 16) & 0xf;
2451 int cpm = insn & 0xf;
2452 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2454 if (cpn == 13 && cpm == 0) {
2455 /* TLS register. */
2456 if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2457 return 1;
2459 if (cpn == 7) {
2460 /* ISB, DSB, DMB. */
2461 if ((cpm == 5 && op == 4)
2462 || (cpm == 10 && (op == 4 || op == 5)))
2463 return 1;
2465 return 0;
2468 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2469 instruction is not defined. */
2470 static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2472 uint32_t rd;
2473 TCGv tmp, tmp2;
2475 /* M profile cores use memory mapped registers instead of cp15. */
2476 if (arm_feature(env, ARM_FEATURE_M))
2477 return 1;
2479 if ((insn & (1 << 25)) == 0) {
2480 if (insn & (1 << 20)) {
2481 /* mrrc */
2482 return 1;
2484 /* mcrr. Used for block cache operations, so implement as no-op. */
2485 return 0;
2487 if ((insn & (1 << 4)) == 0) {
2488 /* cdp */
2489 return 1;
2491 if (IS_USER(s) && !cp15_user_ok(insn)) {
2492 return 1;
2494 if ((insn & 0x0fff0fff) == 0x0e070f90
2495 || (insn & 0x0fff0fff) == 0x0e070f58) {
2496 /* Wait for interrupt. */
2497 gen_set_pc_im(s->pc);
2498 s->is_jmp = DISAS_WFI;
2499 return 0;
2501 rd = (insn >> 12) & 0xf;
2502 tmp2 = tcg_const_i32(insn);
2503 if (insn & ARM_CP_RW_BIT) {
2504 tmp = new_tmp();
2505 gen_helper_get_cp15(tmp, cpu_env, tmp2);
2506 /* If the destination register is r15 then sets condition codes. */
2507 if (rd != 15)
2508 store_reg(s, rd, tmp);
2509 else
2510 dead_tmp(tmp);
2511 } else {
2512 tmp = load_reg(s, rd);
2513 gen_helper_set_cp15(cpu_env, tmp2, tmp);
2514 dead_tmp(tmp);
2515 /* Normally we would always end the TB here, but Linux
2516 * arch/arm/mach-pxa/sleep.S expects two instructions following
2517 * an MMU enable to execute from cache. Imitate this behaviour. */
2518 if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2519 (insn & 0x0fff0fff) != 0x0e010f10)
2520 gen_lookup_tb(s);
2522 tcg_temp_free_i32(tmp2);
2523 return 0;
2526 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2527 #define VFP_SREG(insn, bigbit, smallbit) \
2528 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2529 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2530 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2531 reg = (((insn) >> (bigbit)) & 0x0f) \
2532 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2533 } else { \
2534 if (insn & (1 << (smallbit))) \
2535 return 1; \
2536 reg = ((insn) >> (bigbit)) & 0x0f; \
2537 }} while (0)
2539 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2540 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2541 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2542 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2543 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2544 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2546 /* Move between integer and VFP cores. */
2547 static TCGv gen_vfp_mrs(void)
2549 TCGv tmp = new_tmp();
2550 tcg_gen_mov_i32(tmp, cpu_F0s);
2551 return tmp;
2554 static void gen_vfp_msr(TCGv tmp)
2556 tcg_gen_mov_i32(cpu_F0s, tmp);
2557 dead_tmp(tmp);
2560 static inline int
2561 vfp_enabled(CPUState * env)
2563 return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
2566 static void gen_neon_dup_u8(TCGv var, int shift)
2568 TCGv tmp = new_tmp();
2569 if (shift)
2570 tcg_gen_shri_i32(var, var, shift);
2571 tcg_gen_ext8u_i32(var, var);
2572 tcg_gen_shli_i32(tmp, var, 8);
2573 tcg_gen_or_i32(var, var, tmp);
2574 tcg_gen_shli_i32(tmp, var, 16);
2575 tcg_gen_or_i32(var, var, tmp);
2576 dead_tmp(tmp);
2579 static void gen_neon_dup_low16(TCGv var)
2581 TCGv tmp = new_tmp();
2582 tcg_gen_ext16u_i32(var, var);
2583 tcg_gen_shli_i32(tmp, var, 16);
2584 tcg_gen_or_i32(var, var, tmp);
2585 dead_tmp(tmp);
2588 static void gen_neon_dup_high16(TCGv var)
2590 TCGv tmp = new_tmp();
2591 tcg_gen_andi_i32(var, var, 0xffff0000);
2592 tcg_gen_shri_i32(tmp, var, 16);
2593 tcg_gen_or_i32(var, var, tmp);
2594 dead_tmp(tmp);
2597 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2598 (ie. an undefined instruction). */
2599 static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2601 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2602 int dp, veclen;
2603 TCGv addr;
2604 TCGv tmp;
2605 TCGv tmp2;
2607 if (!arm_feature(env, ARM_FEATURE_VFP))
2608 return 1;
2610 if (!vfp_enabled(env)) {
2611 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2612 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2613 return 1;
2614 rn = (insn >> 16) & 0xf;
2615 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2616 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2617 return 1;
2619 dp = ((insn & 0xf00) == 0xb00);
2620 switch ((insn >> 24) & 0xf) {
2621 case 0xe:
2622 if (insn & (1 << 4)) {
2623 /* single register transfer */
2624 rd = (insn >> 12) & 0xf;
2625 if (dp) {
2626 int size;
2627 int pass;
2629 VFP_DREG_N(rn, insn);
2630 if (insn & 0xf)
2631 return 1;
2632 if (insn & 0x00c00060
2633 && !arm_feature(env, ARM_FEATURE_NEON))
2634 return 1;
2636 pass = (insn >> 21) & 1;
2637 if (insn & (1 << 22)) {
2638 size = 0;
2639 offset = ((insn >> 5) & 3) * 8;
2640 } else if (insn & (1 << 5)) {
2641 size = 1;
2642 offset = (insn & (1 << 6)) ? 16 : 0;
2643 } else {
2644 size = 2;
2645 offset = 0;
2647 if (insn & ARM_CP_RW_BIT) {
2648 /* vfp->arm */
2649 tmp = neon_load_reg(rn, pass);
2650 switch (size) {
2651 case 0:
2652 if (offset)
2653 tcg_gen_shri_i32(tmp, tmp, offset);
2654 if (insn & (1 << 23))
2655 gen_uxtb(tmp);
2656 else
2657 gen_sxtb(tmp);
2658 break;
2659 case 1:
2660 if (insn & (1 << 23)) {
2661 if (offset) {
2662 tcg_gen_shri_i32(tmp, tmp, 16);
2663 } else {
2664 gen_uxth(tmp);
2666 } else {
2667 if (offset) {
2668 tcg_gen_sari_i32(tmp, tmp, 16);
2669 } else {
2670 gen_sxth(tmp);
2673 break;
2674 case 2:
2675 break;
2677 store_reg(s, rd, tmp);
2678 } else {
2679 /* arm->vfp */
2680 tmp = load_reg(s, rd);
2681 if (insn & (1 << 23)) {
2682 /* VDUP */
2683 if (size == 0) {
2684 gen_neon_dup_u8(tmp, 0);
2685 } else if (size == 1) {
2686 gen_neon_dup_low16(tmp);
2688 for (n = 0; n <= pass * 2; n++) {
2689 tmp2 = new_tmp();
2690 tcg_gen_mov_i32(tmp2, tmp);
2691 neon_store_reg(rn, n, tmp2);
2693 neon_store_reg(rn, n, tmp);
2694 } else {
2695 /* VMOV */
2696 switch (size) {
2697 case 0:
2698 tmp2 = neon_load_reg(rn, pass);
2699 gen_bfi(tmp, tmp2, tmp, offset, 0xff);
2700 dead_tmp(tmp2);
2701 break;
2702 case 1:
2703 tmp2 = neon_load_reg(rn, pass);
2704 gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
2705 dead_tmp(tmp2);
2706 break;
2707 case 2:
2708 break;
2710 neon_store_reg(rn, pass, tmp);
2713 } else { /* !dp */
2714 if ((insn & 0x6f) != 0x00)
2715 return 1;
2716 rn = VFP_SREG_N(insn);
2717 if (insn & ARM_CP_RW_BIT) {
2718 /* vfp->arm */
2719 if (insn & (1 << 21)) {
2720 /* system register */
2721 rn >>= 1;
2723 switch (rn) {
2724 case ARM_VFP_FPSID:
2725 /* VFP2 allows access to FSID from userspace.
2726 VFP3 restricts all id registers to privileged
2727 accesses. */
2728 if (IS_USER(s)
2729 && arm_feature(env, ARM_FEATURE_VFP3))
2730 return 1;
2731 tmp = load_cpu_field(vfp.xregs[rn]);
2732 break;
2733 case ARM_VFP_FPEXC:
2734 if (IS_USER(s))
2735 return 1;
2736 tmp = load_cpu_field(vfp.xregs[rn]);
2737 break;
2738 case ARM_VFP_FPINST:
2739 case ARM_VFP_FPINST2:
2740 /* Not present in VFP3. */
2741 if (IS_USER(s)
2742 || arm_feature(env, ARM_FEATURE_VFP3))
2743 return 1;
2744 tmp = load_cpu_field(vfp.xregs[rn]);
2745 break;
2746 case ARM_VFP_FPSCR:
2747 if (rd == 15) {
2748 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2749 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2750 } else {
2751 tmp = new_tmp();
2752 gen_helper_vfp_get_fpscr(tmp, cpu_env);
2754 break;
2755 case ARM_VFP_MVFR0:
2756 case ARM_VFP_MVFR1:
2757 if (IS_USER(s)
2758 || !arm_feature(env, ARM_FEATURE_VFP3))
2759 return 1;
2760 tmp = load_cpu_field(vfp.xregs[rn]);
2761 break;
2762 default:
2763 return 1;
2765 } else {
2766 gen_mov_F0_vreg(0, rn);
2767 tmp = gen_vfp_mrs();
2769 if (rd == 15) {
2770 /* Set the 4 flag bits in the CPSR. */
2771 gen_set_nzcv(tmp);
2772 dead_tmp(tmp);
2773 } else {
2774 store_reg(s, rd, tmp);
2776 } else {
2777 /* arm->vfp */
2778 tmp = load_reg(s, rd);
2779 if (insn & (1 << 21)) {
2780 rn >>= 1;
2781 /* system register */
2782 switch (rn) {
2783 case ARM_VFP_FPSID:
2784 case ARM_VFP_MVFR0:
2785 case ARM_VFP_MVFR1:
2786 /* Writes are ignored. */
2787 break;
2788 case ARM_VFP_FPSCR:
2789 gen_helper_vfp_set_fpscr(cpu_env, tmp);
2790 dead_tmp(tmp);
2791 gen_lookup_tb(s);
2792 break;
2793 case ARM_VFP_FPEXC:
2794 if (IS_USER(s))
2795 return 1;
2796 store_cpu_field(tmp, vfp.xregs[rn]);
2797 gen_lookup_tb(s);
2798 break;
2799 case ARM_VFP_FPINST:
2800 case ARM_VFP_FPINST2:
2801 store_cpu_field(tmp, vfp.xregs[rn]);
2802 break;
2803 default:
2804 return 1;
2806 } else {
2807 gen_vfp_msr(tmp);
2808 gen_mov_vreg_F0(0, rn);
2812 } else {
2813 /* data processing */
2814 /* The opcode is in bits 23, 21, 20 and 6. */
2815 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2816 if (dp) {
2817 if (op == 15) {
2818 /* rn is opcode */
2819 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2820 } else {
2821 /* rn is register number */
2822 VFP_DREG_N(rn, insn);
2825 if (op == 15 && (rn == 15 || rn > 17)) {
2826 /* Integer or single precision destination. */
2827 rd = VFP_SREG_D(insn);
2828 } else {
2829 VFP_DREG_D(rd, insn);
2832 if (op == 15 && (rn == 16 || rn == 17)) {
2833 /* Integer source. */
2834 rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2835 } else {
2836 VFP_DREG_M(rm, insn);
2838 } else {
2839 rn = VFP_SREG_N(insn);
2840 if (op == 15 && rn == 15) {
2841 /* Double precision destination. */
2842 VFP_DREG_D(rd, insn);
2843 } else {
2844 rd = VFP_SREG_D(insn);
2846 rm = VFP_SREG_M(insn);
2849 veclen = env->vfp.vec_len;
2850 if (op == 15 && rn > 3)
2851 veclen = 0;
2853 /* Shut up compiler warnings. */
2854 delta_m = 0;
2855 delta_d = 0;
2856 bank_mask = 0;
2858 if (veclen > 0) {
2859 if (dp)
2860 bank_mask = 0xc;
2861 else
2862 bank_mask = 0x18;
2864 /* Figure out what type of vector operation this is. */
2865 if ((rd & bank_mask) == 0) {
2866 /* scalar */
2867 veclen = 0;
2868 } else {
2869 if (dp)
2870 delta_d = (env->vfp.vec_stride >> 1) + 1;
2871 else
2872 delta_d = env->vfp.vec_stride + 1;
2874 if ((rm & bank_mask) == 0) {
2875 /* mixed scalar/vector */
2876 delta_m = 0;
2877 } else {
2878 /* vector */
2879 delta_m = delta_d;
2884 /* Load the initial operands. */
2885 if (op == 15) {
2886 switch (rn) {
2887 case 16:
2888 case 17:
2889 /* Integer source */
2890 gen_mov_F0_vreg(0, rm);
2891 break;
2892 case 8:
2893 case 9:
2894 /* Compare */
2895 gen_mov_F0_vreg(dp, rd);
2896 gen_mov_F1_vreg(dp, rm);
2897 break;
2898 case 10:
2899 case 11:
2900 /* Compare with zero */
2901 gen_mov_F0_vreg(dp, rd);
2902 gen_vfp_F1_ld0(dp);
2903 break;
2904 case 20:
2905 case 21:
2906 case 22:
2907 case 23:
2908 case 28:
2909 case 29:
2910 case 30:
2911 case 31:
2912 /* Source and destination the same. */
2913 gen_mov_F0_vreg(dp, rd);
2914 break;
2915 default:
2916 /* One source operand. */
2917 gen_mov_F0_vreg(dp, rm);
2918 break;
2920 } else {
2921 /* Two source operands. */
2922 gen_mov_F0_vreg(dp, rn);
2923 gen_mov_F1_vreg(dp, rm);
2926 for (;;) {
2927 /* Perform the calculation. */
2928 switch (op) {
2929 case 0: /* mac: fd + (fn * fm) */
2930 gen_vfp_mul(dp);
2931 gen_mov_F1_vreg(dp, rd);
2932 gen_vfp_add(dp);
2933 break;
2934 case 1: /* nmac: fd - (fn * fm) */
2935 gen_vfp_mul(dp);
2936 gen_vfp_neg(dp);
2937 gen_mov_F1_vreg(dp, rd);
2938 gen_vfp_add(dp);
2939 break;
2940 case 2: /* msc: -fd + (fn * fm) */
2941 gen_vfp_mul(dp);
2942 gen_mov_F1_vreg(dp, rd);
2943 gen_vfp_sub(dp);
2944 break;
2945 case 3: /* nmsc: -fd - (fn * fm) */
2946 gen_vfp_mul(dp);
2947 gen_vfp_neg(dp);
2948 gen_mov_F1_vreg(dp, rd);
2949 gen_vfp_sub(dp);
2950 break;
2951 case 4: /* mul: fn * fm */
2952 gen_vfp_mul(dp);
2953 break;
2954 case 5: /* nmul: -(fn * fm) */
2955 gen_vfp_mul(dp);
2956 gen_vfp_neg(dp);
2957 break;
2958 case 6: /* add: fn + fm */
2959 gen_vfp_add(dp);
2960 break;
2961 case 7: /* sub: fn - fm */
2962 gen_vfp_sub(dp);
2963 break;
2964 case 8: /* div: fn / fm */
2965 gen_vfp_div(dp);
2966 break;
2967 case 14: /* fconst */
2968 if (!arm_feature(env, ARM_FEATURE_VFP3))
2969 return 1;
2971 n = (insn << 12) & 0x80000000;
2972 i = ((insn >> 12) & 0x70) | (insn & 0xf);
2973 if (dp) {
2974 if (i & 0x40)
2975 i |= 0x3f80;
2976 else
2977 i |= 0x4000;
2978 n |= i << 16;
2979 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
2980 } else {
2981 if (i & 0x40)
2982 i |= 0x780;
2983 else
2984 i |= 0x800;
2985 n |= i << 19;
2986 tcg_gen_movi_i32(cpu_F0s, n);
2988 break;
2989 case 15: /* extension space */
2990 switch (rn) {
2991 case 0: /* cpy */
2992 /* no-op */
2993 break;
2994 case 1: /* abs */
2995 gen_vfp_abs(dp);
2996 break;
2997 case 2: /* neg */
2998 gen_vfp_neg(dp);
2999 break;
3000 case 3: /* sqrt */
3001 gen_vfp_sqrt(dp);
3002 break;
3003 case 8: /* cmp */
3004 gen_vfp_cmp(dp);
3005 break;
3006 case 9: /* cmpe */
3007 gen_vfp_cmpe(dp);
3008 break;
3009 case 10: /* cmpz */
3010 gen_vfp_cmp(dp);
3011 break;
3012 case 11: /* cmpez */
3013 gen_vfp_F1_ld0(dp);
3014 gen_vfp_cmpe(dp);
3015 break;
3016 case 15: /* single<->double conversion */
3017 if (dp)
3018 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3019 else
3020 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3021 break;
3022 case 16: /* fuito */
3023 gen_vfp_uito(dp);
3024 break;
3025 case 17: /* fsito */
3026 gen_vfp_sito(dp);
3027 break;
3028 case 20: /* fshto */
3029 if (!arm_feature(env, ARM_FEATURE_VFP3))
3030 return 1;
3031 gen_vfp_shto(dp, 16 - rm);
3032 break;
3033 case 21: /* fslto */
3034 if (!arm_feature(env, ARM_FEATURE_VFP3))
3035 return 1;
3036 gen_vfp_slto(dp, 32 - rm);
3037 break;
3038 case 22: /* fuhto */
3039 if (!arm_feature(env, ARM_FEATURE_VFP3))
3040 return 1;
3041 gen_vfp_uhto(dp, 16 - rm);
3042 break;
3043 case 23: /* fulto */
3044 if (!arm_feature(env, ARM_FEATURE_VFP3))
3045 return 1;
3046 gen_vfp_ulto(dp, 32 - rm);
3047 break;
3048 case 24: /* ftoui */
3049 gen_vfp_toui(dp);
3050 break;
3051 case 25: /* ftouiz */
3052 gen_vfp_touiz(dp);
3053 break;
3054 case 26: /* ftosi */
3055 gen_vfp_tosi(dp);
3056 break;
3057 case 27: /* ftosiz */
3058 gen_vfp_tosiz(dp);
3059 break;
3060 case 28: /* ftosh */
3061 if (!arm_feature(env, ARM_FEATURE_VFP3))
3062 return 1;
3063 gen_vfp_tosh(dp, 16 - rm);
3064 break;
3065 case 29: /* ftosl */
3066 if (!arm_feature(env, ARM_FEATURE_VFP3))
3067 return 1;
3068 gen_vfp_tosl(dp, 32 - rm);
3069 break;
3070 case 30: /* ftouh */
3071 if (!arm_feature(env, ARM_FEATURE_VFP3))
3072 return 1;
3073 gen_vfp_touh(dp, 16 - rm);
3074 break;
3075 case 31: /* ftoul */
3076 if (!arm_feature(env, ARM_FEATURE_VFP3))
3077 return 1;
3078 gen_vfp_toul(dp, 32 - rm);
3079 break;
3080 default: /* undefined */
3081 printf ("rn:%d\n", rn);
3082 return 1;
3084 break;
3085 default: /* undefined */
3086 printf ("op:%d\n", op);
3087 return 1;
3090 /* Write back the result. */
3091 if (op == 15 && (rn >= 8 && rn <= 11))
3092 ; /* Comparison, do nothing. */
3093 else if (op == 15 && rn > 17)
3094 /* Integer result. */
3095 gen_mov_vreg_F0(0, rd);
3096 else if (op == 15 && rn == 15)
3097 /* conversion */
3098 gen_mov_vreg_F0(!dp, rd);
3099 else
3100 gen_mov_vreg_F0(dp, rd);
3102 /* break out of the loop if we have finished */
3103 if (veclen == 0)
3104 break;
3106 if (op == 15 && delta_m == 0) {
3107 /* single source one-many */
3108 while (veclen--) {
3109 rd = ((rd + delta_d) & (bank_mask - 1))
3110 | (rd & bank_mask);
3111 gen_mov_vreg_F0(dp, rd);
3113 break;
3115 /* Setup the next operands. */
3116 veclen--;
3117 rd = ((rd + delta_d) & (bank_mask - 1))
3118 | (rd & bank_mask);
3120 if (op == 15) {
3121 /* One source operand. */
3122 rm = ((rm + delta_m) & (bank_mask - 1))
3123 | (rm & bank_mask);
3124 gen_mov_F0_vreg(dp, rm);
3125 } else {
3126 /* Two source operands. */
3127 rn = ((rn + delta_d) & (bank_mask - 1))
3128 | (rn & bank_mask);
3129 gen_mov_F0_vreg(dp, rn);
3130 if (delta_m) {
3131 rm = ((rm + delta_m) & (bank_mask - 1))
3132 | (rm & bank_mask);
3133 gen_mov_F1_vreg(dp, rm);
3138 break;
3139 case 0xc:
3140 case 0xd:
3141 if (dp && (insn & 0x03e00000) == 0x00400000) {
3142 /* two-register transfer */
3143 rn = (insn >> 16) & 0xf;
3144 rd = (insn >> 12) & 0xf;
3145 if (dp) {
3146 VFP_DREG_M(rm, insn);
3147 } else {
3148 rm = VFP_SREG_M(insn);
3151 if (insn & ARM_CP_RW_BIT) {
3152 /* vfp->arm */
3153 if (dp) {
3154 gen_mov_F0_vreg(0, rm * 2);
3155 tmp = gen_vfp_mrs();
3156 store_reg(s, rd, tmp);
3157 gen_mov_F0_vreg(0, rm * 2 + 1);
3158 tmp = gen_vfp_mrs();
3159 store_reg(s, rn, tmp);
3160 } else {
3161 gen_mov_F0_vreg(0, rm);
3162 tmp = gen_vfp_mrs();
3163 store_reg(s, rn, tmp);
3164 gen_mov_F0_vreg(0, rm + 1);
3165 tmp = gen_vfp_mrs();
3166 store_reg(s, rd, tmp);
3168 } else {
3169 /* arm->vfp */
3170 if (dp) {
3171 tmp = load_reg(s, rd);
3172 gen_vfp_msr(tmp);
3173 gen_mov_vreg_F0(0, rm * 2);
3174 tmp = load_reg(s, rn);
3175 gen_vfp_msr(tmp);
3176 gen_mov_vreg_F0(0, rm * 2 + 1);
3177 } else {
3178 tmp = load_reg(s, rn);
3179 gen_vfp_msr(tmp);
3180 gen_mov_vreg_F0(0, rm);
3181 tmp = load_reg(s, rd);
3182 gen_vfp_msr(tmp);
3183 gen_mov_vreg_F0(0, rm + 1);
3186 } else {
3187 /* Load/store */
3188 rn = (insn >> 16) & 0xf;
3189 if (dp)
3190 VFP_DREG_D(rd, insn);
3191 else
3192 rd = VFP_SREG_D(insn);
3193 if (s->thumb && rn == 15) {
3194 addr = new_tmp();
3195 tcg_gen_movi_i32(addr, s->pc & ~2);
3196 } else {
3197 addr = load_reg(s, rn);
3199 if ((insn & 0x01200000) == 0x01000000) {
3200 /* Single load/store */
3201 offset = (insn & 0xff) << 2;
3202 if ((insn & (1 << 23)) == 0)
3203 offset = -offset;
3204 tcg_gen_addi_i32(addr, addr, offset);
3205 if (insn & (1 << 20)) {
3206 gen_vfp_ld(s, dp, addr);
3207 gen_mov_vreg_F0(dp, rd);
3208 } else {
3209 gen_mov_F0_vreg(dp, rd);
3210 gen_vfp_st(s, dp, addr);
3212 dead_tmp(addr);
3213 } else {
3214 /* load/store multiple */
3215 if (dp)
3216 n = (insn >> 1) & 0x7f;
3217 else
3218 n = insn & 0xff;
3220 if (insn & (1 << 24)) /* pre-decrement */
3221 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
3223 if (dp)
3224 offset = 8;
3225 else
3226 offset = 4;
3227 for (i = 0; i < n; i++) {
3228 if (insn & ARM_CP_RW_BIT) {
3229 /* load */
3230 gen_vfp_ld(s, dp, addr);
3231 gen_mov_vreg_F0(dp, rd + i);
3232 } else {
3233 /* store */
3234 gen_mov_F0_vreg(dp, rd + i);
3235 gen_vfp_st(s, dp, addr);
3237 tcg_gen_addi_i32(addr, addr, offset);
3239 if (insn & (1 << 21)) {
3240 /* writeback */
3241 if (insn & (1 << 24))
3242 offset = -offset * n;
3243 else if (dp && (insn & 1))
3244 offset = 4;
3245 else
3246 offset = 0;
3248 if (offset != 0)
3249 tcg_gen_addi_i32(addr, addr, offset);
3250 store_reg(s, rn, addr);
3251 } else {
3252 dead_tmp(addr);
3256 break;
3257 default:
3258 /* Should never happen. */
3259 return 1;
3261 return 0;
3264 static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3266 TranslationBlock *tb;
3268 tb = s->tb;
3269 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3270 tcg_gen_goto_tb(n);
3271 gen_set_pc_im(dest);
3272 tcg_gen_exit_tb((long)tb + n);
3273 } else {
3274 gen_set_pc_im(dest);
3275 tcg_gen_exit_tb(0);
3279 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3281 if (unlikely(s->singlestep_enabled)) {
3282 /* An indirect jump so that we still trigger the debug exception. */
3283 if (s->thumb)
3284 dest |= 1;
3285 gen_bx_im(s, dest);
3286 } else {
3287 gen_goto_tb(s, 0, dest);
3288 s->is_jmp = DISAS_TB_JUMP;
3292 static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3294 if (x)
3295 tcg_gen_sari_i32(t0, t0, 16);
3296 else
3297 gen_sxth(t0);
3298 if (y)
3299 tcg_gen_sari_i32(t1, t1, 16);
3300 else
3301 gen_sxth(t1);
3302 tcg_gen_mul_i32(t0, t0, t1);
3305 /* Return the mask of PSR bits set by a MSR instruction. */
3306 static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3307 uint32_t mask;
3309 mask = 0;
3310 if (flags & (1 << 0))
3311 mask |= 0xff;
3312 if (flags & (1 << 1))
3313 mask |= 0xff00;
3314 if (flags & (1 << 2))
3315 mask |= 0xff0000;
3316 if (flags & (1 << 3))
3317 mask |= 0xff000000;
3319 /* Mask out undefined bits. */
3320 mask &= ~CPSR_RESERVED;
3321 if (!arm_feature(env, ARM_FEATURE_V6))
3322 mask &= ~(CPSR_E | CPSR_GE);
3323 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3324 mask &= ~CPSR_IT;
3325 /* Mask out execution state bits. */
3326 if (!spsr)
3327 mask &= ~CPSR_EXEC;
3328 /* Mask out privileged bits. */
3329 if (IS_USER(s))
3330 mask &= CPSR_USER;
3331 return mask;
3334 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3335 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0)
3337 TCGv tmp;
3338 if (spsr) {
3339 /* ??? This is also undefined in system mode. */
3340 if (IS_USER(s))
3341 return 1;
3343 tmp = load_cpu_field(spsr);
3344 tcg_gen_andi_i32(tmp, tmp, ~mask);
3345 tcg_gen_andi_i32(t0, t0, mask);
3346 tcg_gen_or_i32(tmp, tmp, t0);
3347 store_cpu_field(tmp, spsr);
3348 } else {
3349 gen_set_cpsr(t0, mask);
3351 dead_tmp(t0);
3352 gen_lookup_tb(s);
3353 return 0;
3356 /* Returns nonzero if access to the PSR is not permitted. */
3357 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3359 TCGv tmp;
3360 tmp = new_tmp();
3361 tcg_gen_movi_i32(tmp, val);
3362 return gen_set_psr(s, mask, spsr, tmp);
3365 /* Generate an old-style exception return. Marks pc as dead. */
3366 static void gen_exception_return(DisasContext *s, TCGv pc)
3368 TCGv tmp;
3369 store_reg(s, 15, pc);
3370 tmp = load_cpu_field(spsr);
3371 gen_set_cpsr(tmp, 0xffffffff);
3372 dead_tmp(tmp);
3373 s->is_jmp = DISAS_UPDATE;
3376 /* Generate a v6 exception return. Marks both values as dead. */
3377 static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3379 gen_set_cpsr(cpsr, 0xffffffff);
3380 dead_tmp(cpsr);
3381 store_reg(s, 15, pc);
3382 s->is_jmp = DISAS_UPDATE;
3385 static inline void
3386 gen_set_condexec (DisasContext *s)
3388 if (s->condexec_mask) {
3389 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3390 TCGv tmp = new_tmp();
3391 tcg_gen_movi_i32(tmp, val);
3392 store_cpu_field(tmp, condexec_bits);
3396 static void gen_nop_hint(DisasContext *s, int val)
3398 switch (val) {
3399 case 3: /* wfi */
3400 gen_set_pc_im(s->pc);
3401 s->is_jmp = DISAS_WFI;
3402 break;
3403 case 2: /* wfe */
3404 case 4: /* sev */
3405 /* TODO: Implement SEV and WFE. May help SMP performance. */
3406 default: /* nop */
3407 break;
3411 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3413 static inline int gen_neon_add(int size, TCGv t0, TCGv t1)
3415 switch (size) {
3416 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
3417 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
3418 case 2: tcg_gen_add_i32(t0, t0, t1); break;
3419 default: return 1;
3421 return 0;
3424 static inline void gen_neon_rsb(int size, TCGv t0, TCGv t1)
3426 switch (size) {
3427 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
3428 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
3429 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
3430 default: return;
3434 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3435 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3436 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3437 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3438 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3440 /* FIXME: This is wrong. They set the wrong overflow bit. */
3441 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3442 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3443 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3444 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3446 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3447 switch ((size << 1) | u) { \
3448 case 0: \
3449 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3450 break; \
3451 case 1: \
3452 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3453 break; \
3454 case 2: \
3455 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3456 break; \
3457 case 3: \
3458 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3459 break; \
3460 case 4: \
3461 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3462 break; \
3463 case 5: \
3464 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3465 break; \
3466 default: return 1; \
3467 }} while (0)
3469 #define GEN_NEON_INTEGER_OP(name) do { \
3470 switch ((size << 1) | u) { \
3471 case 0: \
3472 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3473 break; \
3474 case 1: \
3475 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3476 break; \
3477 case 2: \
3478 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3479 break; \
3480 case 3: \
3481 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3482 break; \
3483 case 4: \
3484 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3485 break; \
3486 case 5: \
3487 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3488 break; \
3489 default: return 1; \
3490 }} while (0)
3492 static TCGv neon_load_scratch(int scratch)
3494 TCGv tmp = new_tmp();
3495 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3496 return tmp;
3499 static void neon_store_scratch(int scratch, TCGv var)
3501 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3502 dead_tmp(var);
3505 static inline TCGv neon_get_scalar(int size, int reg)
3507 TCGv tmp;
3508 if (size == 1) {
3509 tmp = neon_load_reg(reg >> 1, reg & 1);
3510 } else {
3511 tmp = neon_load_reg(reg >> 2, (reg >> 1) & 1);
3512 if (reg & 1) {
3513 gen_neon_dup_low16(tmp);
3514 } else {
3515 gen_neon_dup_high16(tmp);
3518 return tmp;
3521 static void gen_neon_unzip_u8(TCGv t0, TCGv t1)
3523 TCGv rd, rm, tmp;
3525 rd = new_tmp();
3526 rm = new_tmp();
3527 tmp = new_tmp();
3529 tcg_gen_andi_i32(rd, t0, 0xff);
3530 tcg_gen_shri_i32(tmp, t0, 8);
3531 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3532 tcg_gen_or_i32(rd, rd, tmp);
3533 tcg_gen_shli_i32(tmp, t1, 16);
3534 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3535 tcg_gen_or_i32(rd, rd, tmp);
3536 tcg_gen_shli_i32(tmp, t1, 8);
3537 tcg_gen_andi_i32(tmp, tmp, 0xff000000);
3538 tcg_gen_or_i32(rd, rd, tmp);
3540 tcg_gen_shri_i32(rm, t0, 8);
3541 tcg_gen_andi_i32(rm, rm, 0xff);
3542 tcg_gen_shri_i32(tmp, t0, 16);
3543 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3544 tcg_gen_or_i32(rm, rm, tmp);
3545 tcg_gen_shli_i32(tmp, t1, 8);
3546 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3547 tcg_gen_or_i32(rm, rm, tmp);
3548 tcg_gen_andi_i32(tmp, t1, 0xff000000);
3549 tcg_gen_or_i32(t1, rm, tmp);
3550 tcg_gen_mov_i32(t0, rd);
3552 dead_tmp(tmp);
3553 dead_tmp(rm);
3554 dead_tmp(rd);
3557 static void gen_neon_zip_u8(TCGv t0, TCGv t1)
3559 TCGv rd, rm, tmp;
3561 rd = new_tmp();
3562 rm = new_tmp();
3563 tmp = new_tmp();
3565 tcg_gen_andi_i32(rd, t0, 0xff);
3566 tcg_gen_shli_i32(tmp, t1, 8);
3567 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3568 tcg_gen_or_i32(rd, rd, tmp);
3569 tcg_gen_shli_i32(tmp, t0, 16);
3570 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3571 tcg_gen_or_i32(rd, rd, tmp);
3572 tcg_gen_shli_i32(tmp, t1, 24);
3573 tcg_gen_andi_i32(tmp, tmp, 0xff000000);
3574 tcg_gen_or_i32(rd, rd, tmp);
3576 tcg_gen_andi_i32(rm, t1, 0xff000000);
3577 tcg_gen_shri_i32(tmp, t0, 8);
3578 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3579 tcg_gen_or_i32(rm, rm, tmp);
3580 tcg_gen_shri_i32(tmp, t1, 8);
3581 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3582 tcg_gen_or_i32(rm, rm, tmp);
3583 tcg_gen_shri_i32(tmp, t0, 16);
3584 tcg_gen_andi_i32(tmp, tmp, 0xff);
3585 tcg_gen_or_i32(t1, rm, tmp);
3586 tcg_gen_mov_i32(t0, rd);
3588 dead_tmp(tmp);
3589 dead_tmp(rm);
3590 dead_tmp(rd);
3593 static void gen_neon_zip_u16(TCGv t0, TCGv t1)
3595 TCGv tmp, tmp2;
3597 tmp = new_tmp();
3598 tmp2 = new_tmp();
3600 tcg_gen_andi_i32(tmp, t0, 0xffff);
3601 tcg_gen_shli_i32(tmp2, t1, 16);
3602 tcg_gen_or_i32(tmp, tmp, tmp2);
3603 tcg_gen_andi_i32(t1, t1, 0xffff0000);
3604 tcg_gen_shri_i32(tmp2, t0, 16);
3605 tcg_gen_or_i32(t1, t1, tmp2);
3606 tcg_gen_mov_i32(t0, tmp);
3608 dead_tmp(tmp2);
3609 dead_tmp(tmp);
3612 static void gen_neon_unzip(int reg, int q, int tmp, int size)
3614 int n;
3615 TCGv t0, t1;
3617 for (n = 0; n < q + 1; n += 2) {
3618 t0 = neon_load_reg(reg, n);
3619 t1 = neon_load_reg(reg, n + 1);
3620 switch (size) {
3621 case 0: gen_neon_unzip_u8(t0, t1); break;
3622 case 1: gen_neon_zip_u16(t0, t1); break; /* zip and unzip are the same. */
3623 case 2: /* no-op */; break;
3624 default: abort();
3626 neon_store_scratch(tmp + n, t0);
3627 neon_store_scratch(tmp + n + 1, t1);
3631 static void gen_neon_trn_u8(TCGv t0, TCGv t1)
3633 TCGv rd, tmp;
3635 rd = new_tmp();
3636 tmp = new_tmp();
3638 tcg_gen_shli_i32(rd, t0, 8);
3639 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3640 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3641 tcg_gen_or_i32(rd, rd, tmp);
3643 tcg_gen_shri_i32(t1, t1, 8);
3644 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3645 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3646 tcg_gen_or_i32(t1, t1, tmp);
3647 tcg_gen_mov_i32(t0, rd);
3649 dead_tmp(tmp);
3650 dead_tmp(rd);
3653 static void gen_neon_trn_u16(TCGv t0, TCGv t1)
3655 TCGv rd, tmp;
3657 rd = new_tmp();
3658 tmp = new_tmp();
3660 tcg_gen_shli_i32(rd, t0, 16);
3661 tcg_gen_andi_i32(tmp, t1, 0xffff);
3662 tcg_gen_or_i32(rd, rd, tmp);
3663 tcg_gen_shri_i32(t1, t1, 16);
3664 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3665 tcg_gen_or_i32(t1, t1, tmp);
3666 tcg_gen_mov_i32(t0, rd);
3668 dead_tmp(tmp);
3669 dead_tmp(rd);
3673 static struct {
3674 int nregs;
3675 int interleave;
3676 int spacing;
3677 } neon_ls_element_type[11] = {
3678 {4, 4, 1},
3679 {4, 4, 2},
3680 {4, 1, 1},
3681 {4, 2, 1},
3682 {3, 3, 1},
3683 {3, 3, 2},
3684 {3, 1, 1},
3685 {1, 1, 1},
3686 {2, 2, 1},
3687 {2, 2, 2},
3688 {2, 1, 1}
3691 /* Translate a NEON load/store element instruction. Return nonzero if the
3692 instruction is invalid. */
3693 static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3695 int rd, rn, rm;
3696 int op;
3697 int nregs;
3698 int interleave;
3699 int stride;
3700 int size;
3701 int reg;
3702 int pass;
3703 int load;
3704 int shift;
3705 int n;
3706 TCGv addr;
3707 TCGv tmp;
3708 TCGv tmp2;
3710 if (!vfp_enabled(env))
3711 return 1;
3712 VFP_DREG_D(rd, insn);
3713 rn = (insn >> 16) & 0xf;
3714 rm = insn & 0xf;
3715 load = (insn & (1 << 21)) != 0;
3716 addr = new_tmp();
3717 if ((insn & (1 << 23)) == 0) {
3718 /* Load store all elements. */
3719 op = (insn >> 8) & 0xf;
3720 size = (insn >> 6) & 3;
3721 if (op > 10 || size == 3)
3722 return 1;
3723 nregs = neon_ls_element_type[op].nregs;
3724 interleave = neon_ls_element_type[op].interleave;
3725 load_reg_var(s, addr, rn);
3726 stride = (1 << size) * interleave;
3727 for (reg = 0; reg < nregs; reg++) {
3728 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3729 load_reg_var(s, addr, rn);
3730 tcg_gen_addi_i32(addr, addr, (1 << size) * reg);
3731 } else if (interleave == 2 && nregs == 4 && reg == 2) {
3732 load_reg_var(s, addr, rn);
3733 tcg_gen_addi_i32(addr, addr, 1 << size);
3735 for (pass = 0; pass < 2; pass++) {
3736 if (size == 2) {
3737 if (load) {
3738 tmp = gen_ld32(addr, IS_USER(s));
3739 neon_store_reg(rd, pass, tmp);
3740 } else {
3741 tmp = neon_load_reg(rd, pass);
3742 gen_st32(tmp, addr, IS_USER(s));
3744 tcg_gen_addi_i32(addr, addr, stride);
3745 } else if (size == 1) {
3746 if (load) {
3747 tmp = gen_ld16u(addr, IS_USER(s));
3748 tcg_gen_addi_i32(addr, addr, stride);
3749 tmp2 = gen_ld16u(addr, IS_USER(s));
3750 tcg_gen_addi_i32(addr, addr, stride);
3751 gen_bfi(tmp, tmp, tmp2, 16, 0xffff);
3752 dead_tmp(tmp2);
3753 neon_store_reg(rd, pass, tmp);
3754 } else {
3755 tmp = neon_load_reg(rd, pass);
3756 tmp2 = new_tmp();
3757 tcg_gen_shri_i32(tmp2, tmp, 16);
3758 gen_st16(tmp, addr, IS_USER(s));
3759 tcg_gen_addi_i32(addr, addr, stride);
3760 gen_st16(tmp2, addr, IS_USER(s));
3761 tcg_gen_addi_i32(addr, addr, stride);
3763 } else /* size == 0 */ {
3764 if (load) {
3765 TCGV_UNUSED(tmp2);
3766 for (n = 0; n < 4; n++) {
3767 tmp = gen_ld8u(addr, IS_USER(s));
3768 tcg_gen_addi_i32(addr, addr, stride);
3769 if (n == 0) {
3770 tmp2 = tmp;
3771 } else {
3772 gen_bfi(tmp2, tmp2, tmp, n * 8, 0xff);
3773 dead_tmp(tmp);
3776 neon_store_reg(rd, pass, tmp2);
3777 } else {
3778 tmp2 = neon_load_reg(rd, pass);
3779 for (n = 0; n < 4; n++) {
3780 tmp = new_tmp();
3781 if (n == 0) {
3782 tcg_gen_mov_i32(tmp, tmp2);
3783 } else {
3784 tcg_gen_shri_i32(tmp, tmp2, n * 8);
3786 gen_st8(tmp, addr, IS_USER(s));
3787 tcg_gen_addi_i32(addr, addr, stride);
3789 dead_tmp(tmp2);
3793 rd += neon_ls_element_type[op].spacing;
3795 stride = nregs * 8;
3796 } else {
3797 size = (insn >> 10) & 3;
3798 if (size == 3) {
3799 /* Load single element to all lanes. */
3800 if (!load)
3801 return 1;
3802 size = (insn >> 6) & 3;
3803 nregs = ((insn >> 8) & 3) + 1;
3804 stride = (insn & (1 << 5)) ? 2 : 1;
3805 load_reg_var(s, addr, rn);
3806 for (reg = 0; reg < nregs; reg++) {
3807 switch (size) {
3808 case 0:
3809 tmp = gen_ld8u(addr, IS_USER(s));
3810 gen_neon_dup_u8(tmp, 0);
3811 break;
3812 case 1:
3813 tmp = gen_ld16u(addr, IS_USER(s));
3814 gen_neon_dup_low16(tmp);
3815 break;
3816 case 2:
3817 tmp = gen_ld32(addr, IS_USER(s));
3818 break;
3819 case 3:
3820 return 1;
3821 default: /* Avoid compiler warnings. */
3822 abort();
3824 tcg_gen_addi_i32(addr, addr, 1 << size);
3825 tmp2 = new_tmp();
3826 tcg_gen_mov_i32(tmp2, tmp);
3827 neon_store_reg(rd, 0, tmp2);
3828 neon_store_reg(rd, 1, tmp);
3829 rd += stride;
3831 stride = (1 << size) * nregs;
3832 } else {
3833 /* Single element. */
3834 pass = (insn >> 7) & 1;
3835 switch (size) {
3836 case 0:
3837 shift = ((insn >> 5) & 3) * 8;
3838 stride = 1;
3839 break;
3840 case 1:
3841 shift = ((insn >> 6) & 1) * 16;
3842 stride = (insn & (1 << 5)) ? 2 : 1;
3843 break;
3844 case 2:
3845 shift = 0;
3846 stride = (insn & (1 << 6)) ? 2 : 1;
3847 break;
3848 default:
3849 abort();
3851 nregs = ((insn >> 8) & 3) + 1;
3852 load_reg_var(s, addr, rn);
3853 for (reg = 0; reg < nregs; reg++) {
3854 if (load) {
3855 switch (size) {
3856 case 0:
3857 tmp = gen_ld8u(addr, IS_USER(s));
3858 break;
3859 case 1:
3860 tmp = gen_ld16u(addr, IS_USER(s));
3861 break;
3862 case 2:
3863 tmp = gen_ld32(addr, IS_USER(s));
3864 break;
3865 default: /* Avoid compiler warnings. */
3866 abort();
3868 if (size != 2) {
3869 tmp2 = neon_load_reg(rd, pass);
3870 gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
3871 dead_tmp(tmp2);
3873 neon_store_reg(rd, pass, tmp);
3874 } else { /* Store */
3875 tmp = neon_load_reg(rd, pass);
3876 if (shift)
3877 tcg_gen_shri_i32(tmp, tmp, shift);
3878 switch (size) {
3879 case 0:
3880 gen_st8(tmp, addr, IS_USER(s));
3881 break;
3882 case 1:
3883 gen_st16(tmp, addr, IS_USER(s));
3884 break;
3885 case 2:
3886 gen_st32(tmp, addr, IS_USER(s));
3887 break;
3890 rd += stride;
3891 tcg_gen_addi_i32(addr, addr, 1 << size);
3893 stride = nregs * (1 << size);
3896 dead_tmp(addr);
3897 if (rm != 15) {
3898 TCGv base;
3900 base = load_reg(s, rn);
3901 if (rm == 13) {
3902 tcg_gen_addi_i32(base, base, stride);
3903 } else {
3904 TCGv index;
3905 index = load_reg(s, rm);
3906 tcg_gen_add_i32(base, base, index);
3907 dead_tmp(index);
3909 store_reg(s, rn, base);
3911 return 0;
3914 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
3915 static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
3917 tcg_gen_and_i32(t, t, c);
3918 tcg_gen_bic_i32(f, f, c);
3919 tcg_gen_or_i32(dest, t, f);
3922 static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
3924 switch (size) {
3925 case 0: gen_helper_neon_narrow_u8(dest, src); break;
3926 case 1: gen_helper_neon_narrow_u16(dest, src); break;
3927 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
3928 default: abort();
3932 static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
3934 switch (size) {
3935 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
3936 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
3937 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
3938 default: abort();
3942 static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
3944 switch (size) {
3945 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
3946 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
3947 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
3948 default: abort();
3952 static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
3953 int q, int u)
3955 if (q) {
3956 if (u) {
3957 switch (size) {
3958 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3959 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3960 default: abort();
3962 } else {
3963 switch (size) {
3964 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
3965 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
3966 default: abort();
3969 } else {
3970 if (u) {
3971 switch (size) {
3972 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3973 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3974 default: abort();
3976 } else {
3977 switch (size) {
3978 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
3979 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
3980 default: abort();
3986 static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
3988 if (u) {
3989 switch (size) {
3990 case 0: gen_helper_neon_widen_u8(dest, src); break;
3991 case 1: gen_helper_neon_widen_u16(dest, src); break;
3992 case 2: tcg_gen_extu_i32_i64(dest, src); break;
3993 default: abort();
3995 } else {
3996 switch (size) {
3997 case 0: gen_helper_neon_widen_s8(dest, src); break;
3998 case 1: gen_helper_neon_widen_s16(dest, src); break;
3999 case 2: tcg_gen_ext_i32_i64(dest, src); break;
4000 default: abort();
4003 dead_tmp(src);
4006 static inline void gen_neon_addl(int size)
4008 switch (size) {
4009 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4010 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4011 case 2: tcg_gen_add_i64(CPU_V001); break;
4012 default: abort();
4016 static inline void gen_neon_subl(int size)
4018 switch (size) {
4019 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4020 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4021 case 2: tcg_gen_sub_i64(CPU_V001); break;
4022 default: abort();
4026 static inline void gen_neon_negl(TCGv_i64 var, int size)
4028 switch (size) {
4029 case 0: gen_helper_neon_negl_u16(var, var); break;
4030 case 1: gen_helper_neon_negl_u32(var, var); break;
4031 case 2: gen_helper_neon_negl_u64(var, var); break;
4032 default: abort();
4036 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4038 switch (size) {
4039 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4040 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4041 default: abort();
4045 static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
4047 TCGv_i64 tmp;
4049 switch ((size << 1) | u) {
4050 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4051 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4052 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4053 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4054 case 4:
4055 tmp = gen_muls_i64_i32(a, b);
4056 tcg_gen_mov_i64(dest, tmp);
4057 break;
4058 case 5:
4059 tmp = gen_mulu_i64_i32(a, b);
4060 tcg_gen_mov_i64(dest, tmp);
4061 break;
4062 default: abort();
4066 /* Translate a NEON data processing instruction. Return nonzero if the
4067 instruction is invalid.
4068 We process data in a mixture of 32-bit and 64-bit chunks.
4069 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4071 static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4073 int op;
4074 int q;
4075 int rd, rn, rm;
4076 int size;
4077 int shift;
4078 int pass;
4079 int count;
4080 int pairwise;
4081 int u;
4082 int n;
4083 uint32_t imm;
4084 TCGv tmp, tmp2, tmp3, tmp4, tmp5;
4085 TCGv_i64 tmp64;
4087 if (!vfp_enabled(env))
4088 return 1;
4089 q = (insn & (1 << 6)) != 0;
4090 u = (insn >> 24) & 1;
4091 VFP_DREG_D(rd, insn);
4092 VFP_DREG_N(rn, insn);
4093 VFP_DREG_M(rm, insn);
4094 size = (insn >> 20) & 3;
4095 if ((insn & (1 << 23)) == 0) {
4096 /* Three register same length. */
4097 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4098 if (size == 3 && (op == 1 || op == 5 || op == 8 || op == 9
4099 || op == 10 || op == 11 || op == 16)) {
4100 /* 64-bit element instructions. */
4101 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4102 neon_load_reg64(cpu_V0, rn + pass);
4103 neon_load_reg64(cpu_V1, rm + pass);
4104 switch (op) {
4105 case 1: /* VQADD */
4106 if (u) {
4107 gen_helper_neon_add_saturate_u64(CPU_V001);
4108 } else {
4109 gen_helper_neon_add_saturate_s64(CPU_V001);
4111 break;
4112 case 5: /* VQSUB */
4113 if (u) {
4114 gen_helper_neon_sub_saturate_u64(CPU_V001);
4115 } else {
4116 gen_helper_neon_sub_saturate_s64(CPU_V001);
4118 break;
4119 case 8: /* VSHL */
4120 if (u) {
4121 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4122 } else {
4123 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4125 break;
4126 case 9: /* VQSHL */
4127 if (u) {
4128 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4129 cpu_V0, cpu_V0);
4130 } else {
4131 gen_helper_neon_qshl_s64(cpu_V1, cpu_env,
4132 cpu_V1, cpu_V0);
4134 break;
4135 case 10: /* VRSHL */
4136 if (u) {
4137 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4138 } else {
4139 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4141 break;
4142 case 11: /* VQRSHL */
4143 if (u) {
4144 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4145 cpu_V1, cpu_V0);
4146 } else {
4147 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4148 cpu_V1, cpu_V0);
4150 break;
4151 case 16:
4152 if (u) {
4153 tcg_gen_sub_i64(CPU_V001);
4154 } else {
4155 tcg_gen_add_i64(CPU_V001);
4157 break;
4158 default:
4159 abort();
4161 neon_store_reg64(cpu_V0, rd + pass);
4163 return 0;
4165 switch (op) {
4166 case 8: /* VSHL */
4167 case 9: /* VQSHL */
4168 case 10: /* VRSHL */
4169 case 11: /* VQRSHL */
4171 int rtmp;
4172 /* Shift instruction operands are reversed. */
4173 rtmp = rn;
4174 rn = rm;
4175 rm = rtmp;
4176 pairwise = 0;
4178 break;
4179 case 20: /* VPMAX */
4180 case 21: /* VPMIN */
4181 case 23: /* VPADD */
4182 pairwise = 1;
4183 break;
4184 case 26: /* VPADD (float) */
4185 pairwise = (u && size < 2);
4186 break;
4187 case 30: /* VPMIN/VPMAX (float) */
4188 pairwise = u;
4189 break;
4190 default:
4191 pairwise = 0;
4192 break;
4195 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4197 if (pairwise) {
4198 /* Pairwise. */
4199 if (q)
4200 n = (pass & 1) * 2;
4201 else
4202 n = 0;
4203 if (pass < q + 1) {
4204 tmp = neon_load_reg(rn, n);
4205 tmp2 = neon_load_reg(rn, n + 1);
4206 } else {
4207 tmp = neon_load_reg(rm, n);
4208 tmp2 = neon_load_reg(rm, n + 1);
4210 } else {
4211 /* Elementwise. */
4212 tmp = neon_load_reg(rn, pass);
4213 tmp2 = neon_load_reg(rm, pass);
4215 switch (op) {
4216 case 0: /* VHADD */
4217 GEN_NEON_INTEGER_OP(hadd);
4218 break;
4219 case 1: /* VQADD */
4220 GEN_NEON_INTEGER_OP_ENV(qadd);
4221 break;
4222 case 2: /* VRHADD */
4223 GEN_NEON_INTEGER_OP(rhadd);
4224 break;
4225 case 3: /* Logic ops. */
4226 switch ((u << 2) | size) {
4227 case 0: /* VAND */
4228 tcg_gen_and_i32(tmp, tmp, tmp2);
4229 break;
4230 case 1: /* BIC */
4231 tcg_gen_bic_i32(tmp, tmp, tmp2);
4232 break;
4233 case 2: /* VORR */
4234 tcg_gen_or_i32(tmp, tmp, tmp2);
4235 break;
4236 case 3: /* VORN */
4237 tcg_gen_not_i32(tmp2, tmp2);
4238 tcg_gen_or_i32(tmp, tmp, tmp2);
4239 break;
4240 case 4: /* VEOR */
4241 tcg_gen_xor_i32(tmp, tmp, tmp2);
4242 break;
4243 case 5: /* VBSL */
4244 tmp3 = neon_load_reg(rd, pass);
4245 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
4246 dead_tmp(tmp3);
4247 break;
4248 case 6: /* VBIT */
4249 tmp3 = neon_load_reg(rd, pass);
4250 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
4251 dead_tmp(tmp3);
4252 break;
4253 case 7: /* VBIF */
4254 tmp3 = neon_load_reg(rd, pass);
4255 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
4256 dead_tmp(tmp3);
4257 break;
4259 break;
4260 case 4: /* VHSUB */
4261 GEN_NEON_INTEGER_OP(hsub);
4262 break;
4263 case 5: /* VQSUB */
4264 GEN_NEON_INTEGER_OP_ENV(qsub);
4265 break;
4266 case 6: /* VCGT */
4267 GEN_NEON_INTEGER_OP(cgt);
4268 break;
4269 case 7: /* VCGE */
4270 GEN_NEON_INTEGER_OP(cge);
4271 break;
4272 case 8: /* VSHL */
4273 GEN_NEON_INTEGER_OP(shl);
4274 break;
4275 case 9: /* VQSHL */
4276 GEN_NEON_INTEGER_OP_ENV(qshl);
4277 break;
4278 case 10: /* VRSHL */
4279 GEN_NEON_INTEGER_OP(rshl);
4280 break;
4281 case 11: /* VQRSHL */
4282 GEN_NEON_INTEGER_OP_ENV(qrshl);
4283 break;
4284 case 12: /* VMAX */
4285 GEN_NEON_INTEGER_OP(max);
4286 break;
4287 case 13: /* VMIN */
4288 GEN_NEON_INTEGER_OP(min);
4289 break;
4290 case 14: /* VABD */
4291 GEN_NEON_INTEGER_OP(abd);
4292 break;
4293 case 15: /* VABA */
4294 GEN_NEON_INTEGER_OP(abd);
4295 dead_tmp(tmp2);
4296 tmp2 = neon_load_reg(rd, pass);
4297 gen_neon_add(size, tmp, tmp2);
4298 break;
4299 case 16:
4300 if (!u) { /* VADD */
4301 if (gen_neon_add(size, tmp, tmp2))
4302 return 1;
4303 } else { /* VSUB */
4304 switch (size) {
4305 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
4306 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
4307 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
4308 default: return 1;
4311 break;
4312 case 17:
4313 if (!u) { /* VTST */
4314 switch (size) {
4315 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
4316 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
4317 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
4318 default: return 1;
4320 } else { /* VCEQ */
4321 switch (size) {
4322 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
4323 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
4324 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
4325 default: return 1;
4328 break;
4329 case 18: /* Multiply. */
4330 switch (size) {
4331 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4332 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4333 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4334 default: return 1;
4336 dead_tmp(tmp2);
4337 tmp2 = neon_load_reg(rd, pass);
4338 if (u) { /* VMLS */
4339 gen_neon_rsb(size, tmp, tmp2);
4340 } else { /* VMLA */
4341 gen_neon_add(size, tmp, tmp2);
4343 break;
4344 case 19: /* VMUL */
4345 if (u) { /* polynomial */
4346 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
4347 } else { /* Integer */
4348 switch (size) {
4349 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4350 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4351 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4352 default: return 1;
4355 break;
4356 case 20: /* VPMAX */
4357 GEN_NEON_INTEGER_OP(pmax);
4358 break;
4359 case 21: /* VPMIN */
4360 GEN_NEON_INTEGER_OP(pmin);
4361 break;
4362 case 22: /* Hultiply high. */
4363 if (!u) { /* VQDMULH */
4364 switch (size) {
4365 case 1: gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4366 case 2: gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4367 default: return 1;
4369 } else { /* VQRDHMUL */
4370 switch (size) {
4371 case 1: gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4372 case 2: gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4373 default: return 1;
4376 break;
4377 case 23: /* VPADD */
4378 if (u)
4379 return 1;
4380 switch (size) {
4381 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
4382 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
4383 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
4384 default: return 1;
4386 break;
4387 case 26: /* Floating point arithnetic. */
4388 switch ((u << 2) | size) {
4389 case 0: /* VADD */
4390 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4391 break;
4392 case 2: /* VSUB */
4393 gen_helper_neon_sub_f32(tmp, tmp, tmp2);
4394 break;
4395 case 4: /* VPADD */
4396 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4397 break;
4398 case 6: /* VABD */
4399 gen_helper_neon_abd_f32(tmp, tmp, tmp2);
4400 break;
4401 default:
4402 return 1;
4404 break;
4405 case 27: /* Float multiply. */
4406 gen_helper_neon_mul_f32(tmp, tmp, tmp2);
4407 if (!u) {
4408 dead_tmp(tmp2);
4409 tmp2 = neon_load_reg(rd, pass);
4410 if (size == 0) {
4411 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4412 } else {
4413 gen_helper_neon_sub_f32(tmp, tmp2, tmp);
4416 break;
4417 case 28: /* Float compare. */
4418 if (!u) {
4419 gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
4420 } else {
4421 if (size == 0)
4422 gen_helper_neon_cge_f32(tmp, tmp, tmp2);
4423 else
4424 gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
4426 break;
4427 case 29: /* Float compare absolute. */
4428 if (!u)
4429 return 1;
4430 if (size == 0)
4431 gen_helper_neon_acge_f32(tmp, tmp, tmp2);
4432 else
4433 gen_helper_neon_acgt_f32(tmp, tmp, tmp2);
4434 break;
4435 case 30: /* Float min/max. */
4436 if (size == 0)
4437 gen_helper_neon_max_f32(tmp, tmp, tmp2);
4438 else
4439 gen_helper_neon_min_f32(tmp, tmp, tmp2);
4440 break;
4441 case 31:
4442 if (size == 0)
4443 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
4444 else
4445 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
4446 break;
4447 default:
4448 abort();
4450 dead_tmp(tmp2);
4452 /* Save the result. For elementwise operations we can put it
4453 straight into the destination register. For pairwise operations
4454 we have to be careful to avoid clobbering the source operands. */
4455 if (pairwise && rd == rm) {
4456 neon_store_scratch(pass, tmp);
4457 } else {
4458 neon_store_reg(rd, pass, tmp);
4461 } /* for pass */
4462 if (pairwise && rd == rm) {
4463 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4464 tmp = neon_load_scratch(pass);
4465 neon_store_reg(rd, pass, tmp);
4468 /* End of 3 register same size operations. */
4469 } else if (insn & (1 << 4)) {
4470 if ((insn & 0x00380080) != 0) {
4471 /* Two registers and shift. */
4472 op = (insn >> 8) & 0xf;
4473 if (insn & (1 << 7)) {
4474 /* 64-bit shift. */
4475 size = 3;
4476 } else {
4477 size = 2;
4478 while ((insn & (1 << (size + 19))) == 0)
4479 size--;
4481 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4482 /* To avoid excessive dumplication of ops we implement shift
4483 by immediate using the variable shift operations. */
4484 if (op < 8) {
4485 /* Shift by immediate:
4486 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4487 /* Right shifts are encoded as N - shift, where N is the
4488 element size in bits. */
4489 if (op <= 4)
4490 shift = shift - (1 << (size + 3));
4491 if (size == 3) {
4492 count = q + 1;
4493 } else {
4494 count = q ? 4: 2;
4496 switch (size) {
4497 case 0:
4498 imm = (uint8_t) shift;
4499 imm |= imm << 8;
4500 imm |= imm << 16;
4501 break;
4502 case 1:
4503 imm = (uint16_t) shift;
4504 imm |= imm << 16;
4505 break;
4506 case 2:
4507 case 3:
4508 imm = shift;
4509 break;
4510 default:
4511 abort();
4514 for (pass = 0; pass < count; pass++) {
4515 if (size == 3) {
4516 neon_load_reg64(cpu_V0, rm + pass);
4517 tcg_gen_movi_i64(cpu_V1, imm);
4518 switch (op) {
4519 case 0: /* VSHR */
4520 case 1: /* VSRA */
4521 if (u)
4522 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4523 else
4524 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
4525 break;
4526 case 2: /* VRSHR */
4527 case 3: /* VRSRA */
4528 if (u)
4529 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
4530 else
4531 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
4532 break;
4533 case 4: /* VSRI */
4534 if (!u)
4535 return 1;
4536 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4537 break;
4538 case 5: /* VSHL, VSLI */
4539 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4540 break;
4541 case 6: /* VQSHL */
4542 if (u)
4543 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4544 else
4545 gen_helper_neon_qshl_s64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4546 break;
4547 case 7: /* VQSHLU */
4548 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4549 break;
4551 if (op == 1 || op == 3) {
4552 /* Accumulate. */
4553 neon_load_reg64(cpu_V0, rd + pass);
4554 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
4555 } else if (op == 4 || (op == 5 && u)) {
4556 /* Insert */
4557 cpu_abort(env, "VS[LR]I.64 not implemented");
4559 neon_store_reg64(cpu_V0, rd + pass);
4560 } else { /* size < 3 */
4561 /* Operands in T0 and T1. */
4562 tmp = neon_load_reg(rm, pass);
4563 tmp2 = new_tmp();
4564 tcg_gen_movi_i32(tmp2, imm);
4565 switch (op) {
4566 case 0: /* VSHR */
4567 case 1: /* VSRA */
4568 GEN_NEON_INTEGER_OP(shl);
4569 break;
4570 case 2: /* VRSHR */
4571 case 3: /* VRSRA */
4572 GEN_NEON_INTEGER_OP(rshl);
4573 break;
4574 case 4: /* VSRI */
4575 if (!u)
4576 return 1;
4577 GEN_NEON_INTEGER_OP(shl);
4578 break;
4579 case 5: /* VSHL, VSLI */
4580 switch (size) {
4581 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
4582 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
4583 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
4584 default: return 1;
4586 break;
4587 case 6: /* VQSHL */
4588 GEN_NEON_INTEGER_OP_ENV(qshl);
4589 break;
4590 case 7: /* VQSHLU */
4591 switch (size) {
4592 case 0: gen_helper_neon_qshl_u8(tmp, cpu_env, tmp, tmp2); break;
4593 case 1: gen_helper_neon_qshl_u16(tmp, cpu_env, tmp, tmp2); break;
4594 case 2: gen_helper_neon_qshl_u32(tmp, cpu_env, tmp, tmp2); break;
4595 default: return 1;
4597 break;
4599 dead_tmp(tmp2);
4601 if (op == 1 || op == 3) {
4602 /* Accumulate. */
4603 tmp2 = neon_load_reg(rd, pass);
4604 gen_neon_add(size, tmp2, tmp);
4605 dead_tmp(tmp2);
4606 } else if (op == 4 || (op == 5 && u)) {
4607 /* Insert */
4608 switch (size) {
4609 case 0:
4610 if (op == 4)
4611 imm = 0xff >> -shift;
4612 else
4613 imm = (uint8_t)(0xff << shift);
4614 imm |= imm << 8;
4615 imm |= imm << 16;
4616 break;
4617 case 1:
4618 if (op == 4)
4619 imm = 0xffff >> -shift;
4620 else
4621 imm = (uint16_t)(0xffff << shift);
4622 imm |= imm << 16;
4623 break;
4624 case 2:
4625 if (op == 4)
4626 imm = 0xffffffffu >> -shift;
4627 else
4628 imm = 0xffffffffu << shift;
4629 break;
4630 default:
4631 abort();
4633 tmp2 = neon_load_reg(rd, pass);
4634 tcg_gen_andi_i32(tmp, tmp, imm);
4635 tcg_gen_andi_i32(tmp2, tmp2, ~imm);
4636 tcg_gen_or_i32(tmp, tmp, tmp2);
4637 dead_tmp(tmp2);
4639 neon_store_reg(rd, pass, tmp);
4641 } /* for pass */
4642 } else if (op < 10) {
4643 /* Shift by immediate and narrow:
4644 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4645 shift = shift - (1 << (size + 3));
4646 size++;
4647 switch (size) {
4648 case 1:
4649 imm = (uint16_t)shift;
4650 imm |= imm << 16;
4651 tmp2 = tcg_const_i32(imm);
4652 TCGV_UNUSED_I64(tmp64);
4653 break;
4654 case 2:
4655 imm = (uint32_t)shift;
4656 tmp2 = tcg_const_i32(imm);
4657 TCGV_UNUSED_I64(tmp64);
4658 break;
4659 case 3:
4660 tmp64 = tcg_const_i64(shift);
4661 TCGV_UNUSED(tmp2);
4662 break;
4663 default:
4664 abort();
4667 for (pass = 0; pass < 2; pass++) {
4668 if (size == 3) {
4669 neon_load_reg64(cpu_V0, rm + pass);
4670 if (q) {
4671 if (u)
4672 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, tmp64);
4673 else
4674 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, tmp64);
4675 } else {
4676 if (u)
4677 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, tmp64);
4678 else
4679 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, tmp64);
4681 } else {
4682 tmp = neon_load_reg(rm + pass, 0);
4683 gen_neon_shift_narrow(size, tmp, tmp2, q, u);
4684 tmp3 = neon_load_reg(rm + pass, 1);
4685 gen_neon_shift_narrow(size, tmp3, tmp2, q, u);
4686 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
4687 dead_tmp(tmp);
4688 dead_tmp(tmp3);
4690 tmp = new_tmp();
4691 if (op == 8 && !u) {
4692 gen_neon_narrow(size - 1, tmp, cpu_V0);
4693 } else {
4694 if (op == 8)
4695 gen_neon_narrow_sats(size - 1, tmp, cpu_V0);
4696 else
4697 gen_neon_narrow_satu(size - 1, tmp, cpu_V0);
4699 if (pass == 0) {
4700 if (size != 3) {
4701 dead_tmp(tmp2);
4703 tmp2 = tmp;
4704 } else {
4705 neon_store_reg(rd, 0, tmp2);
4706 neon_store_reg(rd, 1, tmp);
4708 } /* for pass */
4709 if (size == 3) {
4710 tcg_temp_free_i64(tmp64);
4712 } else if (op == 10) {
4713 /* VSHLL */
4714 if (q || size == 3)
4715 return 1;
4716 tmp = neon_load_reg(rm, 0);
4717 tmp2 = neon_load_reg(rm, 1);
4718 for (pass = 0; pass < 2; pass++) {
4719 if (pass == 1)
4720 tmp = tmp2;
4722 gen_neon_widen(cpu_V0, tmp, size, u);
4724 if (shift != 0) {
4725 /* The shift is less than the width of the source
4726 type, so we can just shift the whole register. */
4727 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
4728 if (size < 2 || !u) {
4729 uint64_t imm64;
4730 if (size == 0) {
4731 imm = (0xffu >> (8 - shift));
4732 imm |= imm << 16;
4733 } else {
4734 imm = 0xffff >> (16 - shift);
4736 imm64 = imm | (((uint64_t)imm) << 32);
4737 tcg_gen_andi_i64(cpu_V0, cpu_V0, imm64);
4740 neon_store_reg64(cpu_V0, rd + pass);
4742 } else if (op == 15 || op == 16) {
4743 /* VCVT fixed-point. */
4744 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4745 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
4746 if (op & 1) {
4747 if (u)
4748 gen_vfp_ulto(0, shift);
4749 else
4750 gen_vfp_slto(0, shift);
4751 } else {
4752 if (u)
4753 gen_vfp_toul(0, shift);
4754 else
4755 gen_vfp_tosl(0, shift);
4757 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
4759 } else {
4760 return 1;
4762 } else { /* (insn & 0x00380080) == 0 */
4763 int invert;
4765 op = (insn >> 8) & 0xf;
4766 /* One register and immediate. */
4767 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4768 invert = (insn & (1 << 5)) != 0;
4769 switch (op) {
4770 case 0: case 1:
4771 /* no-op */
4772 break;
4773 case 2: case 3:
4774 imm <<= 8;
4775 break;
4776 case 4: case 5:
4777 imm <<= 16;
4778 break;
4779 case 6: case 7:
4780 imm <<= 24;
4781 break;
4782 case 8: case 9:
4783 imm |= imm << 16;
4784 break;
4785 case 10: case 11:
4786 imm = (imm << 8) | (imm << 24);
4787 break;
4788 case 12:
4789 imm = (imm < 8) | 0xff;
4790 break;
4791 case 13:
4792 imm = (imm << 16) | 0xffff;
4793 break;
4794 case 14:
4795 imm |= (imm << 8) | (imm << 16) | (imm << 24);
4796 if (invert)
4797 imm = ~imm;
4798 break;
4799 case 15:
4800 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
4801 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
4802 break;
4804 if (invert)
4805 imm = ~imm;
4807 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4808 if (op & 1 && op < 12) {
4809 tmp = neon_load_reg(rd, pass);
4810 if (invert) {
4811 /* The immediate value has already been inverted, so
4812 BIC becomes AND. */
4813 tcg_gen_andi_i32(tmp, tmp, imm);
4814 } else {
4815 tcg_gen_ori_i32(tmp, tmp, imm);
4817 } else {
4818 /* VMOV, VMVN. */
4819 tmp = new_tmp();
4820 if (op == 14 && invert) {
4821 uint32_t val;
4822 val = 0;
4823 for (n = 0; n < 4; n++) {
4824 if (imm & (1 << (n + (pass & 1) * 4)))
4825 val |= 0xff << (n * 8);
4827 tcg_gen_movi_i32(tmp, val);
4828 } else {
4829 tcg_gen_movi_i32(tmp, imm);
4832 neon_store_reg(rd, pass, tmp);
4835 } else { /* (insn & 0x00800010 == 0x00800000) */
4836 if (size != 3) {
4837 op = (insn >> 8) & 0xf;
4838 if ((insn & (1 << 6)) == 0) {
4839 /* Three registers of different lengths. */
4840 int src1_wide;
4841 int src2_wide;
4842 int prewiden;
4843 /* prewiden, src1_wide, src2_wide */
4844 static const int neon_3reg_wide[16][3] = {
4845 {1, 0, 0}, /* VADDL */
4846 {1, 1, 0}, /* VADDW */
4847 {1, 0, 0}, /* VSUBL */
4848 {1, 1, 0}, /* VSUBW */
4849 {0, 1, 1}, /* VADDHN */
4850 {0, 0, 0}, /* VABAL */
4851 {0, 1, 1}, /* VSUBHN */
4852 {0, 0, 0}, /* VABDL */
4853 {0, 0, 0}, /* VMLAL */
4854 {0, 0, 0}, /* VQDMLAL */
4855 {0, 0, 0}, /* VMLSL */
4856 {0, 0, 0}, /* VQDMLSL */
4857 {0, 0, 0}, /* Integer VMULL */
4858 {0, 0, 0}, /* VQDMULL */
4859 {0, 0, 0} /* Polynomial VMULL */
4862 prewiden = neon_3reg_wide[op][0];
4863 src1_wide = neon_3reg_wide[op][1];
4864 src2_wide = neon_3reg_wide[op][2];
4866 if (size == 0 && (op == 9 || op == 11 || op == 13))
4867 return 1;
4869 /* Avoid overlapping operands. Wide source operands are
4870 always aligned so will never overlap with wide
4871 destinations in problematic ways. */
4872 if (rd == rm && !src2_wide) {
4873 tmp = neon_load_reg(rm, 1);
4874 neon_store_scratch(2, tmp);
4875 } else if (rd == rn && !src1_wide) {
4876 tmp = neon_load_reg(rn, 1);
4877 neon_store_scratch(2, tmp);
4879 TCGV_UNUSED(tmp3);
4880 for (pass = 0; pass < 2; pass++) {
4881 if (src1_wide) {
4882 neon_load_reg64(cpu_V0, rn + pass);
4883 TCGV_UNUSED(tmp);
4884 } else {
4885 if (pass == 1 && rd == rn) {
4886 tmp = neon_load_scratch(2);
4887 } else {
4888 tmp = neon_load_reg(rn, pass);
4890 if (prewiden) {
4891 gen_neon_widen(cpu_V0, tmp, size, u);
4894 if (src2_wide) {
4895 neon_load_reg64(cpu_V1, rm + pass);
4896 TCGV_UNUSED(tmp2);
4897 } else {
4898 if (pass == 1 && rd == rm) {
4899 tmp2 = neon_load_scratch(2);
4900 } else {
4901 tmp2 = neon_load_reg(rm, pass);
4903 if (prewiden) {
4904 gen_neon_widen(cpu_V1, tmp2, size, u);
4907 switch (op) {
4908 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4909 gen_neon_addl(size);
4910 break;
4911 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4912 gen_neon_subl(size);
4913 break;
4914 case 5: case 7: /* VABAL, VABDL */
4915 switch ((size << 1) | u) {
4916 case 0:
4917 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
4918 break;
4919 case 1:
4920 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
4921 break;
4922 case 2:
4923 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
4924 break;
4925 case 3:
4926 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
4927 break;
4928 case 4:
4929 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
4930 break;
4931 case 5:
4932 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
4933 break;
4934 default: abort();
4936 dead_tmp(tmp2);
4937 dead_tmp(tmp);
4938 break;
4939 case 8: case 9: case 10: case 11: case 12: case 13:
4940 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4941 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
4942 dead_tmp(tmp2);
4943 dead_tmp(tmp);
4944 break;
4945 case 14: /* Polynomial VMULL */
4946 cpu_abort(env, "Polynomial VMULL not implemented");
4948 default: /* 15 is RESERVED. */
4949 return 1;
4951 if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
4952 /* Accumulate. */
4953 if (op == 10 || op == 11) {
4954 gen_neon_negl(cpu_V0, size);
4957 if (op != 13) {
4958 neon_load_reg64(cpu_V1, rd + pass);
4961 switch (op) {
4962 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4963 gen_neon_addl(size);
4964 break;
4965 case 9: case 11: /* VQDMLAL, VQDMLSL */
4966 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4967 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
4968 break;
4969 /* Fall through. */
4970 case 13: /* VQDMULL */
4971 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4972 break;
4973 default:
4974 abort();
4976 neon_store_reg64(cpu_V0, rd + pass);
4977 } else if (op == 4 || op == 6) {
4978 /* Narrowing operation. */
4979 tmp = new_tmp();
4980 if (u) {
4981 switch (size) {
4982 case 0:
4983 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
4984 break;
4985 case 1:
4986 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
4987 break;
4988 case 2:
4989 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
4990 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
4991 break;
4992 default: abort();
4994 } else {
4995 switch (size) {
4996 case 0:
4997 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
4998 break;
4999 case 1:
5000 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
5001 break;
5002 case 2:
5003 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
5004 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5005 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5006 break;
5007 default: abort();
5010 if (pass == 0) {
5011 tmp3 = tmp;
5012 } else {
5013 neon_store_reg(rd, 0, tmp3);
5014 neon_store_reg(rd, 1, tmp);
5016 } else {
5017 /* Write back the result. */
5018 neon_store_reg64(cpu_V0, rd + pass);
5021 } else {
5022 /* Two registers and a scalar. */
5023 switch (op) {
5024 case 0: /* Integer VMLA scalar */
5025 case 1: /* Float VMLA scalar */
5026 case 4: /* Integer VMLS scalar */
5027 case 5: /* Floating point VMLS scalar */
5028 case 8: /* Integer VMUL scalar */
5029 case 9: /* Floating point VMUL scalar */
5030 case 12: /* VQDMULH scalar */
5031 case 13: /* VQRDMULH scalar */
5032 tmp = neon_get_scalar(size, rm);
5033 neon_store_scratch(0, tmp);
5034 for (pass = 0; pass < (u ? 4 : 2); pass++) {
5035 tmp = neon_load_scratch(0);
5036 tmp2 = neon_load_reg(rn, pass);
5037 if (op == 12) {
5038 if (size == 1) {
5039 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5040 } else {
5041 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5043 } else if (op == 13) {
5044 if (size == 1) {
5045 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5046 } else {
5047 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5049 } else if (op & 1) {
5050 gen_helper_neon_mul_f32(tmp, tmp, tmp2);
5051 } else {
5052 switch (size) {
5053 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5054 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5055 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5056 default: return 1;
5059 dead_tmp(tmp2);
5060 if (op < 8) {
5061 /* Accumulate. */
5062 tmp2 = neon_load_reg(rd, pass);
5063 switch (op) {
5064 case 0:
5065 gen_neon_add(size, tmp, tmp2);
5066 break;
5067 case 1:
5068 gen_helper_neon_add_f32(tmp, tmp, tmp2);
5069 break;
5070 case 4:
5071 gen_neon_rsb(size, tmp, tmp2);
5072 break;
5073 case 5:
5074 gen_helper_neon_sub_f32(tmp, tmp2, tmp);
5075 break;
5076 default:
5077 abort();
5079 dead_tmp(tmp2);
5081 neon_store_reg(rd, pass, tmp);
5083 break;
5084 case 2: /* VMLAL sclar */
5085 case 3: /* VQDMLAL scalar */
5086 case 6: /* VMLSL scalar */
5087 case 7: /* VQDMLSL scalar */
5088 case 10: /* VMULL scalar */
5089 case 11: /* VQDMULL scalar */
5090 if (size == 0 && (op == 3 || op == 7 || op == 11))
5091 return 1;
5093 tmp2 = neon_get_scalar(size, rm);
5094 tmp3 = neon_load_reg(rn, 1);
5096 for (pass = 0; pass < 2; pass++) {
5097 if (pass == 0) {
5098 tmp = neon_load_reg(rn, 0);
5099 } else {
5100 tmp = tmp3;
5102 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5103 dead_tmp(tmp);
5104 if (op == 6 || op == 7) {
5105 gen_neon_negl(cpu_V0, size);
5107 if (op != 11) {
5108 neon_load_reg64(cpu_V1, rd + pass);
5110 switch (op) {
5111 case 2: case 6:
5112 gen_neon_addl(size);
5113 break;
5114 case 3: case 7:
5115 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5116 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5117 break;
5118 case 10:
5119 /* no-op */
5120 break;
5121 case 11:
5122 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5123 break;
5124 default:
5125 abort();
5127 neon_store_reg64(cpu_V0, rd + pass);
5130 dead_tmp(tmp2);
5132 break;
5133 default: /* 14 and 15 are RESERVED */
5134 return 1;
5137 } else { /* size == 3 */
5138 if (!u) {
5139 /* Extract. */
5140 imm = (insn >> 8) & 0xf;
5141 count = q + 1;
5143 if (imm > 7 && !q)
5144 return 1;
5146 if (imm == 0) {
5147 neon_load_reg64(cpu_V0, rn);
5148 if (q) {
5149 neon_load_reg64(cpu_V1, rn + 1);
5151 } else if (imm == 8) {
5152 neon_load_reg64(cpu_V0, rn + 1);
5153 if (q) {
5154 neon_load_reg64(cpu_V1, rm);
5156 } else if (q) {
5157 tmp64 = tcg_temp_new_i64();
5158 if (imm < 8) {
5159 neon_load_reg64(cpu_V0, rn);
5160 neon_load_reg64(tmp64, rn + 1);
5161 } else {
5162 neon_load_reg64(cpu_V0, rn + 1);
5163 neon_load_reg64(tmp64, rm);
5165 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5166 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
5167 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5168 if (imm < 8) {
5169 neon_load_reg64(cpu_V1, rm);
5170 } else {
5171 neon_load_reg64(cpu_V1, rm + 1);
5172 imm -= 8;
5174 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5175 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
5176 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
5177 tcg_temp_free_i64(tmp64);
5178 } else {
5179 /* BUGFIX */
5180 neon_load_reg64(cpu_V0, rn);
5181 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
5182 neon_load_reg64(cpu_V1, rm);
5183 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5184 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5186 neon_store_reg64(cpu_V0, rd);
5187 if (q) {
5188 neon_store_reg64(cpu_V1, rd + 1);
5190 } else if ((insn & (1 << 11)) == 0) {
5191 /* Two register misc. */
5192 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5193 size = (insn >> 18) & 3;
5194 switch (op) {
5195 case 0: /* VREV64 */
5196 if (size == 3)
5197 return 1;
5198 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5199 tmp = neon_load_reg(rm, pass * 2);
5200 tmp2 = neon_load_reg(rm, pass * 2 + 1);
5201 switch (size) {
5202 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5203 case 1: gen_swap_half(tmp); break;
5204 case 2: /* no-op */ break;
5205 default: abort();
5207 neon_store_reg(rd, pass * 2 + 1, tmp);
5208 if (size == 2) {
5209 neon_store_reg(rd, pass * 2, tmp2);
5210 } else {
5211 switch (size) {
5212 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
5213 case 1: gen_swap_half(tmp2); break;
5214 default: abort();
5216 neon_store_reg(rd, pass * 2, tmp2);
5219 break;
5220 case 4: case 5: /* VPADDL */
5221 case 12: case 13: /* VPADAL */
5222 if (size == 3)
5223 return 1;
5224 for (pass = 0; pass < q + 1; pass++) {
5225 tmp = neon_load_reg(rm, pass * 2);
5226 gen_neon_widen(cpu_V0, tmp, size, op & 1);
5227 tmp = neon_load_reg(rm, pass * 2 + 1);
5228 gen_neon_widen(cpu_V1, tmp, size, op & 1);
5229 switch (size) {
5230 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5231 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5232 case 2: tcg_gen_add_i64(CPU_V001); break;
5233 default: abort();
5235 if (op >= 12) {
5236 /* Accumulate. */
5237 neon_load_reg64(cpu_V1, rd + pass);
5238 gen_neon_addl(size);
5240 neon_store_reg64(cpu_V0, rd + pass);
5242 break;
5243 case 33: /* VTRN */
5244 if (size == 2) {
5245 for (n = 0; n < (q ? 4 : 2); n += 2) {
5246 tmp = neon_load_reg(rm, n);
5247 tmp2 = neon_load_reg(rd, n + 1);
5248 neon_store_reg(rm, n, tmp2);
5249 neon_store_reg(rd, n + 1, tmp);
5251 } else {
5252 goto elementwise;
5254 break;
5255 case 34: /* VUZP */
5256 /* Reg Before After
5257 Rd A3 A2 A1 A0 B2 B0 A2 A0
5258 Rm B3 B2 B1 B0 B3 B1 A3 A1
5260 if (size == 3)
5261 return 1;
5262 gen_neon_unzip(rd, q, 0, size);
5263 gen_neon_unzip(rm, q, 4, size);
5264 if (q) {
5265 static int unzip_order_q[8] =
5266 {0, 2, 4, 6, 1, 3, 5, 7};
5267 for (n = 0; n < 8; n++) {
5268 int reg = (n < 4) ? rd : rm;
5269 tmp = neon_load_scratch(unzip_order_q[n]);
5270 neon_store_reg(reg, n % 4, tmp);
5272 } else {
5273 static int unzip_order[4] =
5274 {0, 4, 1, 5};
5275 for (n = 0; n < 4; n++) {
5276 int reg = (n < 2) ? rd : rm;
5277 tmp = neon_load_scratch(unzip_order[n]);
5278 neon_store_reg(reg, n % 2, tmp);
5281 break;
5282 case 35: /* VZIP */
5283 /* Reg Before After
5284 Rd A3 A2 A1 A0 B1 A1 B0 A0
5285 Rm B3 B2 B1 B0 B3 A3 B2 A2
5287 if (size == 3)
5288 return 1;
5289 count = (q ? 4 : 2);
5290 for (n = 0; n < count; n++) {
5291 tmp = neon_load_reg(rd, n);
5292 tmp2 = neon_load_reg(rd, n);
5293 switch (size) {
5294 case 0: gen_neon_zip_u8(tmp, tmp2); break;
5295 case 1: gen_neon_zip_u16(tmp, tmp2); break;
5296 case 2: /* no-op */; break;
5297 default: abort();
5299 neon_store_scratch(n * 2, tmp);
5300 neon_store_scratch(n * 2 + 1, tmp2);
5302 for (n = 0; n < count * 2; n++) {
5303 int reg = (n < count) ? rd : rm;
5304 tmp = neon_load_scratch(n);
5305 neon_store_reg(reg, n % count, tmp);
5307 break;
5308 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5309 if (size == 3)
5310 return 1;
5311 TCGV_UNUSED(tmp2);
5312 for (pass = 0; pass < 2; pass++) {
5313 neon_load_reg64(cpu_V0, rm + pass);
5314 tmp = new_tmp();
5315 if (op == 36 && q == 0) {
5316 gen_neon_narrow(size, tmp, cpu_V0);
5317 } else if (q) {
5318 gen_neon_narrow_satu(size, tmp, cpu_V0);
5319 } else {
5320 gen_neon_narrow_sats(size, tmp, cpu_V0);
5322 if (pass == 0) {
5323 tmp2 = tmp;
5324 } else {
5325 neon_store_reg(rd, 0, tmp2);
5326 neon_store_reg(rd, 1, tmp);
5329 break;
5330 case 38: /* VSHLL */
5331 if (q || size == 3)
5332 return 1;
5333 tmp = neon_load_reg(rm, 0);
5334 tmp2 = neon_load_reg(rm, 1);
5335 for (pass = 0; pass < 2; pass++) {
5336 if (pass == 1)
5337 tmp = tmp2;
5338 gen_neon_widen(cpu_V0, tmp, size, 1);
5339 neon_store_reg64(cpu_V0, rd + pass);
5341 break;
5342 default:
5343 elementwise:
5344 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5345 if (op == 30 || op == 31 || op >= 58) {
5346 tcg_gen_ld_f32(cpu_F0s, cpu_env,
5347 neon_reg_offset(rm, pass));
5348 TCGV_UNUSED(tmp);
5349 } else {
5350 tmp = neon_load_reg(rm, pass);
5352 switch (op) {
5353 case 1: /* VREV32 */
5354 switch (size) {
5355 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5356 case 1: gen_swap_half(tmp); break;
5357 default: return 1;
5359 break;
5360 case 2: /* VREV16 */
5361 if (size != 0)
5362 return 1;
5363 gen_rev16(tmp);
5364 break;
5365 case 8: /* CLS */
5366 switch (size) {
5367 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
5368 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
5369 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
5370 default: return 1;
5372 break;
5373 case 9: /* CLZ */
5374 switch (size) {
5375 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
5376 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
5377 case 2: gen_helper_clz(tmp, tmp); break;
5378 default: return 1;
5380 break;
5381 case 10: /* CNT */
5382 if (size != 0)
5383 return 1;
5384 gen_helper_neon_cnt_u8(tmp, tmp);
5385 break;
5386 case 11: /* VNOT */
5387 if (size != 0)
5388 return 1;
5389 tcg_gen_not_i32(tmp, tmp);
5390 break;
5391 case 14: /* VQABS */
5392 switch (size) {
5393 case 0: gen_helper_neon_qabs_s8(tmp, cpu_env, tmp); break;
5394 case 1: gen_helper_neon_qabs_s16(tmp, cpu_env, tmp); break;
5395 case 2: gen_helper_neon_qabs_s32(tmp, cpu_env, tmp); break;
5396 default: return 1;
5398 break;
5399 case 15: /* VQNEG */
5400 switch (size) {
5401 case 0: gen_helper_neon_qneg_s8(tmp, cpu_env, tmp); break;
5402 case 1: gen_helper_neon_qneg_s16(tmp, cpu_env, tmp); break;
5403 case 2: gen_helper_neon_qneg_s32(tmp, cpu_env, tmp); break;
5404 default: return 1;
5406 break;
5407 case 16: case 19: /* VCGT #0, VCLE #0 */
5408 tmp2 = tcg_const_i32(0);
5409 switch(size) {
5410 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
5411 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
5412 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
5413 default: return 1;
5415 tcg_temp_free(tmp2);
5416 if (op == 19)
5417 tcg_gen_not_i32(tmp, tmp);
5418 break;
5419 case 17: case 20: /* VCGE #0, VCLT #0 */
5420 tmp2 = tcg_const_i32(0);
5421 switch(size) {
5422 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
5423 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
5424 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
5425 default: return 1;
5427 tcg_temp_free(tmp2);
5428 if (op == 20)
5429 tcg_gen_not_i32(tmp, tmp);
5430 break;
5431 case 18: /* VCEQ #0 */
5432 tmp2 = tcg_const_i32(0);
5433 switch(size) {
5434 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
5435 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
5436 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
5437 default: return 1;
5439 tcg_temp_free(tmp2);
5440 break;
5441 case 22: /* VABS */
5442 switch(size) {
5443 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
5444 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
5445 case 2: tcg_gen_abs_i32(tmp, tmp); break;
5446 default: return 1;
5448 break;
5449 case 23: /* VNEG */
5450 if (size == 3)
5451 return 1;
5452 tmp2 = tcg_const_i32(0);
5453 gen_neon_rsb(size, tmp, tmp2);
5454 tcg_temp_free(tmp2);
5455 break;
5456 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5457 tmp2 = tcg_const_i32(0);
5458 gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
5459 tcg_temp_free(tmp2);
5460 if (op == 27)
5461 tcg_gen_not_i32(tmp, tmp);
5462 break;
5463 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5464 tmp2 = tcg_const_i32(0);
5465 gen_helper_neon_cge_f32(tmp, tmp, tmp2);
5466 tcg_temp_free(tmp2);
5467 if (op == 28)
5468 tcg_gen_not_i32(tmp, tmp);
5469 break;
5470 case 26: /* Float VCEQ #0 */
5471 tmp2 = tcg_const_i32(0);
5472 gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
5473 tcg_temp_free(tmp2);
5474 break;
5475 case 30: /* Float VABS */
5476 gen_vfp_abs(0);
5477 break;
5478 case 31: /* Float VNEG */
5479 gen_vfp_neg(0);
5480 break;
5481 case 32: /* VSWP */
5482 tmp2 = neon_load_reg(rd, pass);
5483 neon_store_reg(rm, pass, tmp2);
5484 break;
5485 case 33: /* VTRN */
5486 tmp2 = neon_load_reg(rd, pass);
5487 switch (size) {
5488 case 0: gen_neon_trn_u8(tmp, tmp2); break;
5489 case 1: gen_neon_trn_u16(tmp, tmp2); break;
5490 case 2: abort();
5491 default: return 1;
5493 neon_store_reg(rm, pass, tmp2);
5494 break;
5495 case 56: /* Integer VRECPE */
5496 gen_helper_recpe_u32(tmp, tmp, cpu_env);
5497 break;
5498 case 57: /* Integer VRSQRTE */
5499 gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
5500 break;
5501 case 58: /* Float VRECPE */
5502 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
5503 break;
5504 case 59: /* Float VRSQRTE */
5505 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
5506 break;
5507 case 60: /* VCVT.F32.S32 */
5508 gen_vfp_tosiz(0);
5509 break;
5510 case 61: /* VCVT.F32.U32 */
5511 gen_vfp_touiz(0);
5512 break;
5513 case 62: /* VCVT.S32.F32 */
5514 gen_vfp_sito(0);
5515 break;
5516 case 63: /* VCVT.U32.F32 */
5517 gen_vfp_uito(0);
5518 break;
5519 default:
5520 /* Reserved: 21, 29, 39-56 */
5521 return 1;
5523 if (op == 30 || op == 31 || op >= 58) {
5524 tcg_gen_st_f32(cpu_F0s, cpu_env,
5525 neon_reg_offset(rd, pass));
5526 } else {
5527 neon_store_reg(rd, pass, tmp);
5530 break;
5532 } else if ((insn & (1 << 10)) == 0) {
5533 /* VTBL, VTBX. */
5534 n = ((insn >> 5) & 0x18) + 8;
5535 if (insn & (1 << 6)) {
5536 tmp = neon_load_reg(rd, 0);
5537 } else {
5538 tmp = new_tmp();
5539 tcg_gen_movi_i32(tmp, 0);
5541 tmp2 = neon_load_reg(rm, 0);
5542 tmp4 = tcg_const_i32(rn);
5543 tmp5 = tcg_const_i32(n);
5544 gen_helper_neon_tbl(tmp2, tmp2, tmp, tmp4, tmp5);
5545 dead_tmp(tmp);
5546 if (insn & (1 << 6)) {
5547 tmp = neon_load_reg(rd, 1);
5548 } else {
5549 tmp = new_tmp();
5550 tcg_gen_movi_i32(tmp, 0);
5552 tmp3 = neon_load_reg(rm, 1);
5553 gen_helper_neon_tbl(tmp3, tmp3, tmp, tmp4, tmp5);
5554 dead_tmp(tmp5);
5555 dead_tmp(tmp4);
5556 neon_store_reg(rd, 0, tmp2);
5557 neon_store_reg(rd, 1, tmp3);
5558 dead_tmp(tmp);
5559 } else if ((insn & 0x380) == 0) {
5560 /* VDUP */
5561 if (insn & (1 << 19)) {
5562 tmp = neon_load_reg(rm, 1);
5563 } else {
5564 tmp = neon_load_reg(rm, 0);
5566 if (insn & (1 << 16)) {
5567 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
5568 } else if (insn & (1 << 17)) {
5569 if ((insn >> 18) & 1)
5570 gen_neon_dup_high16(tmp);
5571 else
5572 gen_neon_dup_low16(tmp);
5574 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5575 tmp2 = new_tmp();
5576 tcg_gen_mov_i32(tmp2, tmp);
5577 neon_store_reg(rd, pass, tmp2);
5579 dead_tmp(tmp);
5580 } else {
5581 return 1;
5585 return 0;
5588 static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
5590 int crn = (insn >> 16) & 0xf;
5591 int crm = insn & 0xf;
5592 int op1 = (insn >> 21) & 7;
5593 int op2 = (insn >> 5) & 7;
5594 int rt = (insn >> 12) & 0xf;
5595 TCGv tmp;
5597 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5598 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5599 /* TEECR */
5600 if (IS_USER(s))
5601 return 1;
5602 tmp = load_cpu_field(teecr);
5603 store_reg(s, rt, tmp);
5604 return 0;
5606 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5607 /* TEEHBR */
5608 if (IS_USER(s) && (env->teecr & 1))
5609 return 1;
5610 tmp = load_cpu_field(teehbr);
5611 store_reg(s, rt, tmp);
5612 return 0;
5615 fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5616 op1, crn, crm, op2);
5617 return 1;
5620 static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
5622 int crn = (insn >> 16) & 0xf;
5623 int crm = insn & 0xf;
5624 int op1 = (insn >> 21) & 7;
5625 int op2 = (insn >> 5) & 7;
5626 int rt = (insn >> 12) & 0xf;
5627 TCGv tmp;
5629 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5630 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5631 /* TEECR */
5632 if (IS_USER(s))
5633 return 1;
5634 tmp = load_reg(s, rt);
5635 gen_helper_set_teecr(cpu_env, tmp);
5636 dead_tmp(tmp);
5637 return 0;
5639 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5640 /* TEEHBR */
5641 if (IS_USER(s) && (env->teecr & 1))
5642 return 1;
5643 tmp = load_reg(s, rt);
5644 store_cpu_field(tmp, teehbr);
5645 return 0;
5648 fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5649 op1, crn, crm, op2);
5650 return 1;
5653 static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
5655 int cpnum;
5657 cpnum = (insn >> 8) & 0xf;
5658 if (arm_feature(env, ARM_FEATURE_XSCALE)
5659 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
5660 return 1;
5662 switch (cpnum) {
5663 case 0:
5664 case 1:
5665 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5666 return disas_iwmmxt_insn(env, s, insn);
5667 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
5668 return disas_dsp_insn(env, s, insn);
5670 return 1;
5671 case 10:
5672 case 11:
5673 return disas_vfp_insn (env, s, insn);
5674 case 14:
5675 /* Coprocessors 7-15 are architecturally reserved by ARM.
5676 Unfortunately Intel decided to ignore this. */
5677 if (arm_feature(env, ARM_FEATURE_XSCALE))
5678 goto board;
5679 if (insn & (1 << 20))
5680 return disas_cp14_read(env, s, insn);
5681 else
5682 return disas_cp14_write(env, s, insn);
5683 case 15:
5684 return disas_cp15_insn (env, s, insn);
5685 default:
5686 board:
5687 /* Unknown coprocessor. See if the board has hooked it. */
5688 return disas_cp_insn (env, s, insn);
5693 /* Store a 64-bit value to a register pair. Clobbers val. */
5694 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5696 TCGv tmp;
5697 tmp = new_tmp();
5698 tcg_gen_trunc_i64_i32(tmp, val);
5699 store_reg(s, rlow, tmp);
5700 tmp = new_tmp();
5701 tcg_gen_shri_i64(val, val, 32);
5702 tcg_gen_trunc_i64_i32(tmp, val);
5703 store_reg(s, rhigh, tmp);
5706 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5707 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5709 TCGv_i64 tmp;
5710 TCGv tmp2;
5712 /* Load value and extend to 64 bits. */
5713 tmp = tcg_temp_new_i64();
5714 tmp2 = load_reg(s, rlow);
5715 tcg_gen_extu_i32_i64(tmp, tmp2);
5716 dead_tmp(tmp2);
5717 tcg_gen_add_i64(val, val, tmp);
5718 tcg_temp_free_i64(tmp);
5721 /* load and add a 64-bit value from a register pair. */
5722 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5724 TCGv_i64 tmp;
5725 TCGv tmpl;
5726 TCGv tmph;
5728 /* Load 64-bit value rd:rn. */
5729 tmpl = load_reg(s, rlow);
5730 tmph = load_reg(s, rhigh);
5731 tmp = tcg_temp_new_i64();
5732 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
5733 dead_tmp(tmpl);
5734 dead_tmp(tmph);
5735 tcg_gen_add_i64(val, val, tmp);
5736 tcg_temp_free_i64(tmp);
5739 /* Set N and Z flags from a 64-bit value. */
5740 static void gen_logicq_cc(TCGv_i64 val)
5742 TCGv tmp = new_tmp();
5743 gen_helper_logicq_cc(tmp, val);
5744 gen_logic_CC(tmp);
5745 dead_tmp(tmp);
5748 static void disas_arm_insn(CPUState * env, DisasContext *s)
5750 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
5751 TCGv tmp;
5752 TCGv tmp2;
5753 TCGv tmp3;
5754 TCGv addr;
5755 TCGv_i64 tmp64;
5757 insn = ldl_code(s->pc);
5758 s->pc += 4;
5760 /* M variants do not implement ARM mode. */
5761 if (IS_M(env))
5762 goto illegal_op;
5763 cond = insn >> 28;
5764 if (cond == 0xf){
5765 /* Unconditional instructions. */
5766 if (((insn >> 25) & 7) == 1) {
5767 /* NEON Data processing. */
5768 if (!arm_feature(env, ARM_FEATURE_NEON))
5769 goto illegal_op;
5771 if (disas_neon_data_insn(env, s, insn))
5772 goto illegal_op;
5773 return;
5775 if ((insn & 0x0f100000) == 0x04000000) {
5776 /* NEON load/store. */
5777 if (!arm_feature(env, ARM_FEATURE_NEON))
5778 goto illegal_op;
5780 if (disas_neon_ls_insn(env, s, insn))
5781 goto illegal_op;
5782 return;
5784 if ((insn & 0x0d70f000) == 0x0550f000)
5785 return; /* PLD */
5786 else if ((insn & 0x0ffffdff) == 0x01010000) {
5787 ARCH(6);
5788 /* setend */
5789 if (insn & (1 << 9)) {
5790 /* BE8 mode not implemented. */
5791 goto illegal_op;
5793 return;
5794 } else if ((insn & 0x0fffff00) == 0x057ff000) {
5795 switch ((insn >> 4) & 0xf) {
5796 case 1: /* clrex */
5797 ARCH(6K);
5798 gen_helper_clrex(cpu_env);
5799 return;
5800 case 4: /* dsb */
5801 case 5: /* dmb */
5802 case 6: /* isb */
5803 ARCH(7);
5804 /* We don't emulate caches so these are a no-op. */
5805 return;
5806 default:
5807 goto illegal_op;
5809 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
5810 /* srs */
5811 int32_t offset;
5812 if (IS_USER(s))
5813 goto illegal_op;
5814 ARCH(6);
5815 op1 = (insn & 0x1f);
5816 if (op1 == (env->uncached_cpsr & CPSR_M)) {
5817 addr = load_reg(s, 13);
5818 } else {
5819 addr = new_tmp();
5820 tmp = tcg_const_i32(op1);
5821 gen_helper_get_r13_banked(addr, cpu_env, tmp);
5822 tcg_temp_free_i32(tmp);
5824 i = (insn >> 23) & 3;
5825 switch (i) {
5826 case 0: offset = -4; break; /* DA */
5827 case 1: offset = 0; break; /* IA */
5828 case 2: offset = -8; break; /* DB */
5829 case 3: offset = 4; break; /* IB */
5830 default: abort();
5832 if (offset)
5833 tcg_gen_addi_i32(addr, addr, offset);
5834 tmp = load_reg(s, 14);
5835 gen_st32(tmp, addr, 0);
5836 tmp = load_cpu_field(spsr);
5837 tcg_gen_addi_i32(addr, addr, 4);
5838 gen_st32(tmp, addr, 0);
5839 if (insn & (1 << 21)) {
5840 /* Base writeback. */
5841 switch (i) {
5842 case 0: offset = -8; break;
5843 case 1: offset = 4; break;
5844 case 2: offset = -4; break;
5845 case 3: offset = 0; break;
5846 default: abort();
5848 if (offset)
5849 tcg_gen_addi_i32(addr, addr, offset);
5850 if (op1 == (env->uncached_cpsr & CPSR_M)) {
5851 store_reg(s, 13, addr);
5852 } else {
5853 tmp = tcg_const_i32(op1);
5854 gen_helper_set_r13_banked(cpu_env, tmp, addr);
5855 tcg_temp_free_i32(tmp);
5856 dead_tmp(addr);
5858 } else {
5859 dead_tmp(addr);
5861 } else if ((insn & 0x0e5fffe0) == 0x081d0a00) {
5862 /* rfe */
5863 int32_t offset;
5864 if (IS_USER(s))
5865 goto illegal_op;
5866 ARCH(6);
5867 rn = (insn >> 16) & 0xf;
5868 addr = load_reg(s, rn);
5869 i = (insn >> 23) & 3;
5870 switch (i) {
5871 case 0: offset = -4; break; /* DA */
5872 case 1: offset = 0; break; /* IA */
5873 case 2: offset = -8; break; /* DB */
5874 case 3: offset = 4; break; /* IB */
5875 default: abort();
5877 if (offset)
5878 tcg_gen_addi_i32(addr, addr, offset);
5879 /* Load PC into tmp and CPSR into tmp2. */
5880 tmp = gen_ld32(addr, 0);
5881 tcg_gen_addi_i32(addr, addr, 4);
5882 tmp2 = gen_ld32(addr, 0);
5883 if (insn & (1 << 21)) {
5884 /* Base writeback. */
5885 switch (i) {
5886 case 0: offset = -8; break;
5887 case 1: offset = 4; break;
5888 case 2: offset = -4; break;
5889 case 3: offset = 0; break;
5890 default: abort();
5892 if (offset)
5893 tcg_gen_addi_i32(addr, addr, offset);
5894 store_reg(s, rn, addr);
5895 } else {
5896 dead_tmp(addr);
5898 gen_rfe(s, tmp, tmp2);
5899 return;
5900 } else if ((insn & 0x0e000000) == 0x0a000000) {
5901 /* branch link and change to thumb (blx <offset>) */
5902 int32_t offset;
5904 val = (uint32_t)s->pc;
5905 tmp = new_tmp();
5906 tcg_gen_movi_i32(tmp, val);
5907 store_reg(s, 14, tmp);
5908 /* Sign-extend the 24-bit offset */
5909 offset = (((int32_t)insn) << 8) >> 8;
5910 /* offset * 4 + bit24 * 2 + (thumb bit) */
5911 val += (offset << 2) | ((insn >> 23) & 2) | 1;
5912 /* pipeline offset */
5913 val += 4;
5914 gen_bx_im(s, val);
5915 return;
5916 } else if ((insn & 0x0e000f00) == 0x0c000100) {
5917 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5918 /* iWMMXt register transfer. */
5919 if (env->cp15.c15_cpar & (1 << 1))
5920 if (!disas_iwmmxt_insn(env, s, insn))
5921 return;
5923 } else if ((insn & 0x0fe00000) == 0x0c400000) {
5924 /* Coprocessor double register transfer. */
5925 } else if ((insn & 0x0f000010) == 0x0e000010) {
5926 /* Additional coprocessor register transfer. */
5927 } else if ((insn & 0x0ff10020) == 0x01000000) {
5928 uint32_t mask;
5929 uint32_t val;
5930 /* cps (privileged) */
5931 if (IS_USER(s))
5932 return;
5933 mask = val = 0;
5934 if (insn & (1 << 19)) {
5935 if (insn & (1 << 8))
5936 mask |= CPSR_A;
5937 if (insn & (1 << 7))
5938 mask |= CPSR_I;
5939 if (insn & (1 << 6))
5940 mask |= CPSR_F;
5941 if (insn & (1 << 18))
5942 val |= mask;
5944 if (insn & (1 << 17)) {
5945 mask |= CPSR_M;
5946 val |= (insn & 0x1f);
5948 if (mask) {
5949 gen_set_psr_im(s, mask, 0, val);
5951 return;
5953 goto illegal_op;
5955 if (cond != 0xe) {
5956 /* if not always execute, we generate a conditional jump to
5957 next instruction */
5958 s->condlabel = gen_new_label();
5959 gen_test_cc(cond ^ 1, s->condlabel);
5960 s->condjmp = 1;
5962 if ((insn & 0x0f900000) == 0x03000000) {
5963 if ((insn & (1 << 21)) == 0) {
5964 ARCH(6T2);
5965 rd = (insn >> 12) & 0xf;
5966 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
5967 if ((insn & (1 << 22)) == 0) {
5968 /* MOVW */
5969 tmp = new_tmp();
5970 tcg_gen_movi_i32(tmp, val);
5971 } else {
5972 /* MOVT */
5973 tmp = load_reg(s, rd);
5974 tcg_gen_ext16u_i32(tmp, tmp);
5975 tcg_gen_ori_i32(tmp, tmp, val << 16);
5977 store_reg(s, rd, tmp);
5978 } else {
5979 if (((insn >> 12) & 0xf) != 0xf)
5980 goto illegal_op;
5981 if (((insn >> 16) & 0xf) == 0) {
5982 gen_nop_hint(s, insn & 0xff);
5983 } else {
5984 /* CPSR = immediate */
5985 val = insn & 0xff;
5986 shift = ((insn >> 8) & 0xf) * 2;
5987 if (shift)
5988 val = (val >> shift) | (val << (32 - shift));
5989 i = ((insn & (1 << 22)) != 0);
5990 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
5991 goto illegal_op;
5994 } else if ((insn & 0x0f900000) == 0x01000000
5995 && (insn & 0x00000090) != 0x00000090) {
5996 /* miscellaneous instructions */
5997 op1 = (insn >> 21) & 3;
5998 sh = (insn >> 4) & 0xf;
5999 rm = insn & 0xf;
6000 switch (sh) {
6001 case 0x0: /* move program status register */
6002 if (op1 & 1) {
6003 /* PSR = reg */
6004 tmp = load_reg(s, rm);
6005 i = ((op1 & 2) != 0);
6006 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
6007 goto illegal_op;
6008 } else {
6009 /* reg = PSR */
6010 rd = (insn >> 12) & 0xf;
6011 if (op1 & 2) {
6012 if (IS_USER(s))
6013 goto illegal_op;
6014 tmp = load_cpu_field(spsr);
6015 } else {
6016 tmp = new_tmp();
6017 gen_helper_cpsr_read(tmp);
6019 store_reg(s, rd, tmp);
6021 break;
6022 case 0x1:
6023 if (op1 == 1) {
6024 /* branch/exchange thumb (bx). */
6025 tmp = load_reg(s, rm);
6026 gen_bx(s, tmp);
6027 } else if (op1 == 3) {
6028 /* clz */
6029 rd = (insn >> 12) & 0xf;
6030 tmp = load_reg(s, rm);
6031 gen_helper_clz(tmp, tmp);
6032 store_reg(s, rd, tmp);
6033 } else {
6034 goto illegal_op;
6036 break;
6037 case 0x2:
6038 if (op1 == 1) {
6039 ARCH(5J); /* bxj */
6040 /* Trivial implementation equivalent to bx. */
6041 tmp = load_reg(s, rm);
6042 gen_bx(s, tmp);
6043 } else {
6044 goto illegal_op;
6046 break;
6047 case 0x3:
6048 if (op1 != 1)
6049 goto illegal_op;
6051 /* branch link/exchange thumb (blx) */
6052 tmp = load_reg(s, rm);
6053 tmp2 = new_tmp();
6054 tcg_gen_movi_i32(tmp2, s->pc);
6055 store_reg(s, 14, tmp2);
6056 gen_bx(s, tmp);
6057 break;
6058 case 0x5: /* saturating add/subtract */
6059 rd = (insn >> 12) & 0xf;
6060 rn = (insn >> 16) & 0xf;
6061 tmp = load_reg(s, rm);
6062 tmp2 = load_reg(s, rn);
6063 if (op1 & 2)
6064 gen_helper_double_saturate(tmp2, tmp2);
6065 if (op1 & 1)
6066 gen_helper_sub_saturate(tmp, tmp, tmp2);
6067 else
6068 gen_helper_add_saturate(tmp, tmp, tmp2);
6069 dead_tmp(tmp2);
6070 store_reg(s, rd, tmp);
6071 break;
6072 case 7: /* bkpt */
6073 gen_set_condexec(s);
6074 gen_set_pc_im(s->pc - 4);
6075 gen_exception(EXCP_BKPT);
6076 s->is_jmp = DISAS_JUMP;
6077 break;
6078 case 0x8: /* signed multiply */
6079 case 0xa:
6080 case 0xc:
6081 case 0xe:
6082 rs = (insn >> 8) & 0xf;
6083 rn = (insn >> 12) & 0xf;
6084 rd = (insn >> 16) & 0xf;
6085 if (op1 == 1) {
6086 /* (32 * 16) >> 16 */
6087 tmp = load_reg(s, rm);
6088 tmp2 = load_reg(s, rs);
6089 if (sh & 4)
6090 tcg_gen_sari_i32(tmp2, tmp2, 16);
6091 else
6092 gen_sxth(tmp2);
6093 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6094 tcg_gen_shri_i64(tmp64, tmp64, 16);
6095 tmp = new_tmp();
6096 tcg_gen_trunc_i64_i32(tmp, tmp64);
6097 tcg_temp_free_i64(tmp64);
6098 if ((sh & 2) == 0) {
6099 tmp2 = load_reg(s, rn);
6100 gen_helper_add_setq(tmp, tmp, tmp2);
6101 dead_tmp(tmp2);
6103 store_reg(s, rd, tmp);
6104 } else {
6105 /* 16 * 16 */
6106 tmp = load_reg(s, rm);
6107 tmp2 = load_reg(s, rs);
6108 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
6109 dead_tmp(tmp2);
6110 if (op1 == 2) {
6111 tmp64 = tcg_temp_new_i64();
6112 tcg_gen_ext_i32_i64(tmp64, tmp);
6113 dead_tmp(tmp);
6114 gen_addq(s, tmp64, rn, rd);
6115 gen_storeq_reg(s, rn, rd, tmp64);
6116 tcg_temp_free_i64(tmp64);
6117 } else {
6118 if (op1 == 0) {
6119 tmp2 = load_reg(s, rn);
6120 gen_helper_add_setq(tmp, tmp, tmp2);
6121 dead_tmp(tmp2);
6123 store_reg(s, rd, tmp);
6126 break;
6127 default:
6128 goto illegal_op;
6130 } else if (((insn & 0x0e000000) == 0 &&
6131 (insn & 0x00000090) != 0x90) ||
6132 ((insn & 0x0e000000) == (1 << 25))) {
6133 int set_cc, logic_cc, shiftop;
6135 op1 = (insn >> 21) & 0xf;
6136 set_cc = (insn >> 20) & 1;
6137 logic_cc = table_logic_cc[op1] & set_cc;
6139 /* data processing instruction */
6140 if (insn & (1 << 25)) {
6141 /* immediate operand */
6142 val = insn & 0xff;
6143 shift = ((insn >> 8) & 0xf) * 2;
6144 if (shift) {
6145 val = (val >> shift) | (val << (32 - shift));
6147 tmp2 = new_tmp();
6148 tcg_gen_movi_i32(tmp2, val);
6149 if (logic_cc && shift) {
6150 gen_set_CF_bit31(tmp2);
6152 } else {
6153 /* register */
6154 rm = (insn) & 0xf;
6155 tmp2 = load_reg(s, rm);
6156 shiftop = (insn >> 5) & 3;
6157 if (!(insn & (1 << 4))) {
6158 shift = (insn >> 7) & 0x1f;
6159 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
6160 } else {
6161 rs = (insn >> 8) & 0xf;
6162 tmp = load_reg(s, rs);
6163 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
6166 if (op1 != 0x0f && op1 != 0x0d) {
6167 rn = (insn >> 16) & 0xf;
6168 tmp = load_reg(s, rn);
6169 } else {
6170 TCGV_UNUSED(tmp);
6172 rd = (insn >> 12) & 0xf;
6173 switch(op1) {
6174 case 0x00:
6175 tcg_gen_and_i32(tmp, tmp, tmp2);
6176 if (logic_cc) {
6177 gen_logic_CC(tmp);
6179 store_reg_bx(env, s, rd, tmp);
6180 break;
6181 case 0x01:
6182 tcg_gen_xor_i32(tmp, tmp, tmp2);
6183 if (logic_cc) {
6184 gen_logic_CC(tmp);
6186 store_reg_bx(env, s, rd, tmp);
6187 break;
6188 case 0x02:
6189 if (set_cc && rd == 15) {
6190 /* SUBS r15, ... is used for exception return. */
6191 if (IS_USER(s)) {
6192 goto illegal_op;
6194 gen_helper_sub_cc(tmp, tmp, tmp2);
6195 gen_exception_return(s, tmp);
6196 } else {
6197 if (set_cc) {
6198 gen_helper_sub_cc(tmp, tmp, tmp2);
6199 } else {
6200 tcg_gen_sub_i32(tmp, tmp, tmp2);
6202 store_reg_bx(env, s, rd, tmp);
6204 break;
6205 case 0x03:
6206 if (set_cc) {
6207 gen_helper_sub_cc(tmp, tmp2, tmp);
6208 } else {
6209 tcg_gen_sub_i32(tmp, tmp2, tmp);
6211 store_reg_bx(env, s, rd, tmp);
6212 break;
6213 case 0x04:
6214 if (set_cc) {
6215 gen_helper_add_cc(tmp, tmp, tmp2);
6216 } else {
6217 tcg_gen_add_i32(tmp, tmp, tmp2);
6219 store_reg_bx(env, s, rd, tmp);
6220 break;
6221 case 0x05:
6222 if (set_cc) {
6223 gen_helper_adc_cc(tmp, tmp, tmp2);
6224 } else {
6225 gen_add_carry(tmp, tmp, tmp2);
6227 store_reg_bx(env, s, rd, tmp);
6228 break;
6229 case 0x06:
6230 if (set_cc) {
6231 gen_helper_sbc_cc(tmp, tmp, tmp2);
6232 } else {
6233 gen_sub_carry(tmp, tmp, tmp2);
6235 store_reg_bx(env, s, rd, tmp);
6236 break;
6237 case 0x07:
6238 if (set_cc) {
6239 gen_helper_sbc_cc(tmp, tmp2, tmp);
6240 } else {
6241 gen_sub_carry(tmp, tmp2, tmp);
6243 store_reg_bx(env, s, rd, tmp);
6244 break;
6245 case 0x08:
6246 if (set_cc) {
6247 tcg_gen_and_i32(tmp, tmp, tmp2);
6248 gen_logic_CC(tmp);
6250 dead_tmp(tmp);
6251 break;
6252 case 0x09:
6253 if (set_cc) {
6254 tcg_gen_xor_i32(tmp, tmp, tmp2);
6255 gen_logic_CC(tmp);
6257 dead_tmp(tmp);
6258 break;
6259 case 0x0a:
6260 if (set_cc) {
6261 gen_helper_sub_cc(tmp, tmp, tmp2);
6263 dead_tmp(tmp);
6264 break;
6265 case 0x0b:
6266 if (set_cc) {
6267 gen_helper_add_cc(tmp, tmp, tmp2);
6269 dead_tmp(tmp);
6270 break;
6271 case 0x0c:
6272 tcg_gen_or_i32(tmp, tmp, tmp2);
6273 if (logic_cc) {
6274 gen_logic_CC(tmp);
6276 store_reg_bx(env, s, rd, tmp);
6277 break;
6278 case 0x0d:
6279 if (logic_cc && rd == 15) {
6280 /* MOVS r15, ... is used for exception return. */
6281 if (IS_USER(s)) {
6282 goto illegal_op;
6284 gen_exception_return(s, tmp2);
6285 } else {
6286 if (logic_cc) {
6287 gen_logic_CC(tmp2);
6289 store_reg_bx(env, s, rd, tmp2);
6291 break;
6292 case 0x0e:
6293 tcg_gen_bic_i32(tmp, tmp, tmp2);
6294 if (logic_cc) {
6295 gen_logic_CC(tmp);
6297 store_reg_bx(env, s, rd, tmp);
6298 break;
6299 default:
6300 case 0x0f:
6301 tcg_gen_not_i32(tmp2, tmp2);
6302 if (logic_cc) {
6303 gen_logic_CC(tmp2);
6305 store_reg_bx(env, s, rd, tmp2);
6306 break;
6308 if (op1 != 0x0f && op1 != 0x0d) {
6309 dead_tmp(tmp2);
6311 } else {
6312 /* other instructions */
6313 op1 = (insn >> 24) & 0xf;
6314 switch(op1) {
6315 case 0x0:
6316 case 0x1:
6317 /* multiplies, extra load/stores */
6318 sh = (insn >> 5) & 3;
6319 if (sh == 0) {
6320 if (op1 == 0x0) {
6321 rd = (insn >> 16) & 0xf;
6322 rn = (insn >> 12) & 0xf;
6323 rs = (insn >> 8) & 0xf;
6324 rm = (insn) & 0xf;
6325 op1 = (insn >> 20) & 0xf;
6326 switch (op1) {
6327 case 0: case 1: case 2: case 3: case 6:
6328 /* 32 bit mul */
6329 tmp = load_reg(s, rs);
6330 tmp2 = load_reg(s, rm);
6331 tcg_gen_mul_i32(tmp, tmp, tmp2);
6332 dead_tmp(tmp2);
6333 if (insn & (1 << 22)) {
6334 /* Subtract (mls) */
6335 ARCH(6T2);
6336 tmp2 = load_reg(s, rn);
6337 tcg_gen_sub_i32(tmp, tmp2, tmp);
6338 dead_tmp(tmp2);
6339 } else if (insn & (1 << 21)) {
6340 /* Add */
6341 tmp2 = load_reg(s, rn);
6342 tcg_gen_add_i32(tmp, tmp, tmp2);
6343 dead_tmp(tmp2);
6345 if (insn & (1 << 20))
6346 gen_logic_CC(tmp);
6347 store_reg(s, rd, tmp);
6348 break;
6349 default:
6350 /* 64 bit mul */
6351 tmp = load_reg(s, rs);
6352 tmp2 = load_reg(s, rm);
6353 if (insn & (1 << 22))
6354 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6355 else
6356 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
6357 if (insn & (1 << 21)) /* mult accumulate */
6358 gen_addq(s, tmp64, rn, rd);
6359 if (!(insn & (1 << 23))) { /* double accumulate */
6360 ARCH(6);
6361 gen_addq_lo(s, tmp64, rn);
6362 gen_addq_lo(s, tmp64, rd);
6364 if (insn & (1 << 20))
6365 gen_logicq_cc(tmp64);
6366 gen_storeq_reg(s, rn, rd, tmp64);
6367 tcg_temp_free_i64(tmp64);
6368 break;
6370 } else {
6371 rn = (insn >> 16) & 0xf;
6372 rd = (insn >> 12) & 0xf;
6373 if (insn & (1 << 23)) {
6374 /* load/store exclusive */
6375 op1 = (insn >> 21) & 0x3;
6376 if (op1)
6377 ARCH(6K);
6378 else
6379 ARCH(6);
6380 addr = tcg_temp_local_new_i32();
6381 load_reg_var(s, addr, rn);
6382 if (insn & (1 << 20)) {
6383 gen_helper_mark_exclusive(cpu_env, addr);
6384 switch (op1) {
6385 case 0: /* ldrex */
6386 tmp = gen_ld32(addr, IS_USER(s));
6387 break;
6388 case 1: /* ldrexd */
6389 tmp = gen_ld32(addr, IS_USER(s));
6390 store_reg(s, rd, tmp);
6391 tcg_gen_addi_i32(addr, addr, 4);
6392 tmp = gen_ld32(addr, IS_USER(s));
6393 rd++;
6394 break;
6395 case 2: /* ldrexb */
6396 tmp = gen_ld8u(addr, IS_USER(s));
6397 break;
6398 case 3: /* ldrexh */
6399 tmp = gen_ld16u(addr, IS_USER(s));
6400 break;
6401 default:
6402 abort();
6404 store_reg(s, rd, tmp);
6405 } else {
6406 int label = gen_new_label();
6407 rm = insn & 0xf;
6408 tmp2 = tcg_temp_local_new_i32();
6409 gen_helper_test_exclusive(tmp2, cpu_env, addr);
6410 tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label);
6411 tmp = load_reg(s,rm);
6412 switch (op1) {
6413 case 0: /* strex */
6414 gen_st32(tmp, addr, IS_USER(s));
6415 break;
6416 case 1: /* strexd */
6417 gen_st32(tmp, addr, IS_USER(s));
6418 tcg_gen_addi_i32(addr, addr, 4);
6419 tmp = load_reg(s, rm + 1);
6420 gen_st32(tmp, addr, IS_USER(s));
6421 break;
6422 case 2: /* strexb */
6423 gen_st8(tmp, addr, IS_USER(s));
6424 break;
6425 case 3: /* strexh */
6426 gen_st16(tmp, addr, IS_USER(s));
6427 break;
6428 default:
6429 abort();
6431 gen_set_label(label);
6432 tcg_gen_mov_i32(cpu_R[rd], tmp2);
6433 tcg_temp_free(tmp2);
6435 tcg_temp_free(addr);
6436 } else {
6437 /* SWP instruction */
6438 rm = (insn) & 0xf;
6440 /* ??? This is not really atomic. However we know
6441 we never have multiple CPUs running in parallel,
6442 so it is good enough. */
6443 addr = load_reg(s, rn);
6444 tmp = load_reg(s, rm);
6445 if (insn & (1 << 22)) {
6446 tmp2 = gen_ld8u(addr, IS_USER(s));
6447 gen_st8(tmp, addr, IS_USER(s));
6448 } else {
6449 tmp2 = gen_ld32(addr, IS_USER(s));
6450 gen_st32(tmp, addr, IS_USER(s));
6452 dead_tmp(addr);
6453 store_reg(s, rd, tmp2);
6456 } else {
6457 int address_offset;
6458 int load;
6459 /* Misc load/store */
6460 rn = (insn >> 16) & 0xf;
6461 rd = (insn >> 12) & 0xf;
6462 addr = load_reg(s, rn);
6463 if (insn & (1 << 24))
6464 gen_add_datah_offset(s, insn, 0, addr);
6465 address_offset = 0;
6466 if (insn & (1 << 20)) {
6467 /* load */
6468 switch(sh) {
6469 case 1:
6470 tmp = gen_ld16u(addr, IS_USER(s));
6471 break;
6472 case 2:
6473 tmp = gen_ld8s(addr, IS_USER(s));
6474 break;
6475 default:
6476 case 3:
6477 tmp = gen_ld16s(addr, IS_USER(s));
6478 break;
6480 load = 1;
6481 } else if (sh & 2) {
6482 /* doubleword */
6483 if (sh & 1) {
6484 /* store */
6485 tmp = load_reg(s, rd);
6486 gen_st32(tmp, addr, IS_USER(s));
6487 tcg_gen_addi_i32(addr, addr, 4);
6488 tmp = load_reg(s, rd + 1);
6489 gen_st32(tmp, addr, IS_USER(s));
6490 load = 0;
6491 } else {
6492 /* load */
6493 tmp = gen_ld32(addr, IS_USER(s));
6494 store_reg(s, rd, tmp);
6495 tcg_gen_addi_i32(addr, addr, 4);
6496 tmp = gen_ld32(addr, IS_USER(s));
6497 rd++;
6498 load = 1;
6500 address_offset = -4;
6501 } else {
6502 /* store */
6503 tmp = load_reg(s, rd);
6504 gen_st16(tmp, addr, IS_USER(s));
6505 load = 0;
6507 /* Perform base writeback before the loaded value to
6508 ensure correct behavior with overlapping index registers.
6509 ldrd with base writeback is is undefined if the
6510 destination and index registers overlap. */
6511 if (!(insn & (1 << 24))) {
6512 gen_add_datah_offset(s, insn, address_offset, addr);
6513 store_reg(s, rn, addr);
6514 } else if (insn & (1 << 21)) {
6515 if (address_offset)
6516 tcg_gen_addi_i32(addr, addr, address_offset);
6517 store_reg(s, rn, addr);
6518 } else {
6519 dead_tmp(addr);
6521 if (load) {
6522 /* Complete the load. */
6523 store_reg(s, rd, tmp);
6526 break;
6527 case 0x4:
6528 case 0x5:
6529 goto do_ldst;
6530 case 0x6:
6531 case 0x7:
6532 if (insn & (1 << 4)) {
6533 ARCH(6);
6534 /* Armv6 Media instructions. */
6535 rm = insn & 0xf;
6536 rn = (insn >> 16) & 0xf;
6537 rd = (insn >> 12) & 0xf;
6538 rs = (insn >> 8) & 0xf;
6539 switch ((insn >> 23) & 3) {
6540 case 0: /* Parallel add/subtract. */
6541 op1 = (insn >> 20) & 7;
6542 tmp = load_reg(s, rn);
6543 tmp2 = load_reg(s, rm);
6544 sh = (insn >> 5) & 7;
6545 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
6546 goto illegal_op;
6547 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
6548 dead_tmp(tmp2);
6549 store_reg(s, rd, tmp);
6550 break;
6551 case 1:
6552 if ((insn & 0x00700020) == 0) {
6553 /* Halfword pack. */
6554 tmp = load_reg(s, rn);
6555 tmp2 = load_reg(s, rm);
6556 shift = (insn >> 7) & 0x1f;
6557 if (insn & (1 << 6)) {
6558 /* pkhtb */
6559 if (shift == 0)
6560 shift = 31;
6561 tcg_gen_sari_i32(tmp2, tmp2, shift);
6562 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
6563 tcg_gen_ext16u_i32(tmp2, tmp2);
6564 } else {
6565 /* pkhbt */
6566 if (shift)
6567 tcg_gen_shli_i32(tmp2, tmp2, shift);
6568 tcg_gen_ext16u_i32(tmp, tmp);
6569 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
6571 tcg_gen_or_i32(tmp, tmp, tmp2);
6572 dead_tmp(tmp2);
6573 store_reg(s, rd, tmp);
6574 } else if ((insn & 0x00200020) == 0x00200000) {
6575 /* [us]sat */
6576 tmp = load_reg(s, rm);
6577 shift = (insn >> 7) & 0x1f;
6578 if (insn & (1 << 6)) {
6579 if (shift == 0)
6580 shift = 31;
6581 tcg_gen_sari_i32(tmp, tmp, shift);
6582 } else {
6583 tcg_gen_shli_i32(tmp, tmp, shift);
6585 sh = (insn >> 16) & 0x1f;
6586 if (sh != 0) {
6587 tmp2 = tcg_const_i32(sh);
6588 if (insn & (1 << 22))
6589 gen_helper_usat(tmp, tmp, tmp2);
6590 else
6591 gen_helper_ssat(tmp, tmp, tmp2);
6592 tcg_temp_free_i32(tmp2);
6594 store_reg(s, rd, tmp);
6595 } else if ((insn & 0x00300fe0) == 0x00200f20) {
6596 /* [us]sat16 */
6597 tmp = load_reg(s, rm);
6598 sh = (insn >> 16) & 0x1f;
6599 if (sh != 0) {
6600 tmp2 = tcg_const_i32(sh);
6601 if (insn & (1 << 22))
6602 gen_helper_usat16(tmp, tmp, tmp2);
6603 else
6604 gen_helper_ssat16(tmp, tmp, tmp2);
6605 tcg_temp_free_i32(tmp2);
6607 store_reg(s, rd, tmp);
6608 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
6609 /* Select bytes. */
6610 tmp = load_reg(s, rn);
6611 tmp2 = load_reg(s, rm);
6612 tmp3 = new_tmp();
6613 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
6614 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
6615 dead_tmp(tmp3);
6616 dead_tmp(tmp2);
6617 store_reg(s, rd, tmp);
6618 } else if ((insn & 0x000003e0) == 0x00000060) {
6619 tmp = load_reg(s, rm);
6620 shift = (insn >> 10) & 3;
6621 /* ??? In many cases it's not neccessary to do a
6622 rotate, a shift is sufficient. */
6623 if (shift != 0)
6624 tcg_gen_rori_i32(tmp, tmp, shift * 8);
6625 op1 = (insn >> 20) & 7;
6626 switch (op1) {
6627 case 0: gen_sxtb16(tmp); break;
6628 case 2: gen_sxtb(tmp); break;
6629 case 3: gen_sxth(tmp); break;
6630 case 4: gen_uxtb16(tmp); break;
6631 case 6: gen_uxtb(tmp); break;
6632 case 7: gen_uxth(tmp); break;
6633 default: goto illegal_op;
6635 if (rn != 15) {
6636 tmp2 = load_reg(s, rn);
6637 if ((op1 & 3) == 0) {
6638 gen_add16(tmp, tmp2);
6639 } else {
6640 tcg_gen_add_i32(tmp, tmp, tmp2);
6641 dead_tmp(tmp2);
6644 store_reg(s, rd, tmp);
6645 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
6646 /* rev */
6647 tmp = load_reg(s, rm);
6648 if (insn & (1 << 22)) {
6649 if (insn & (1 << 7)) {
6650 gen_revsh(tmp);
6651 } else {
6652 ARCH(6T2);
6653 gen_helper_rbit(tmp, tmp);
6655 } else {
6656 if (insn & (1 << 7))
6657 gen_rev16(tmp);
6658 else
6659 tcg_gen_bswap32_i32(tmp, tmp);
6661 store_reg(s, rd, tmp);
6662 } else {
6663 goto illegal_op;
6665 break;
6666 case 2: /* Multiplies (Type 3). */
6667 tmp = load_reg(s, rm);
6668 tmp2 = load_reg(s, rs);
6669 if (insn & (1 << 20)) {
6670 /* Signed multiply most significant [accumulate]. */
6671 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6672 if (insn & (1 << 5))
6673 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
6674 tcg_gen_shri_i64(tmp64, tmp64, 32);
6675 tmp = new_tmp();
6676 tcg_gen_trunc_i64_i32(tmp, tmp64);
6677 tcg_temp_free_i64(tmp64);
6678 if (rd != 15) {
6679 tmp2 = load_reg(s, rd);
6680 if (insn & (1 << 6)) {
6681 tcg_gen_sub_i32(tmp, tmp, tmp2);
6682 } else {
6683 tcg_gen_add_i32(tmp, tmp, tmp2);
6685 dead_tmp(tmp2);
6687 store_reg(s, rn, tmp);
6688 } else {
6689 if (insn & (1 << 5))
6690 gen_swap_half(tmp2);
6691 gen_smul_dual(tmp, tmp2);
6692 /* This addition cannot overflow. */
6693 if (insn & (1 << 6)) {
6694 tcg_gen_sub_i32(tmp, tmp, tmp2);
6695 } else {
6696 tcg_gen_add_i32(tmp, tmp, tmp2);
6698 dead_tmp(tmp2);
6699 if (insn & (1 << 22)) {
6700 /* smlald, smlsld */
6701 tmp64 = tcg_temp_new_i64();
6702 tcg_gen_ext_i32_i64(tmp64, tmp);
6703 dead_tmp(tmp);
6704 gen_addq(s, tmp64, rd, rn);
6705 gen_storeq_reg(s, rd, rn, tmp64);
6706 tcg_temp_free_i64(tmp64);
6707 } else {
6708 /* smuad, smusd, smlad, smlsd */
6709 if (rd != 15)
6711 tmp2 = load_reg(s, rd);
6712 gen_helper_add_setq(tmp, tmp, tmp2);
6713 dead_tmp(tmp2);
6715 store_reg(s, rn, tmp);
6718 break;
6719 case 3:
6720 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
6721 switch (op1) {
6722 case 0: /* Unsigned sum of absolute differences. */
6723 ARCH(6);
6724 tmp = load_reg(s, rm);
6725 tmp2 = load_reg(s, rs);
6726 gen_helper_usad8(tmp, tmp, tmp2);
6727 dead_tmp(tmp2);
6728 if (rd != 15) {
6729 tmp2 = load_reg(s, rd);
6730 tcg_gen_add_i32(tmp, tmp, tmp2);
6731 dead_tmp(tmp2);
6733 store_reg(s, rn, tmp);
6734 break;
6735 case 0x20: case 0x24: case 0x28: case 0x2c:
6736 /* Bitfield insert/clear. */
6737 ARCH(6T2);
6738 shift = (insn >> 7) & 0x1f;
6739 i = (insn >> 16) & 0x1f;
6740 i = i + 1 - shift;
6741 if (rm == 15) {
6742 tmp = new_tmp();
6743 tcg_gen_movi_i32(tmp, 0);
6744 } else {
6745 tmp = load_reg(s, rm);
6747 if (i != 32) {
6748 tmp2 = load_reg(s, rd);
6749 gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
6750 dead_tmp(tmp2);
6752 store_reg(s, rd, tmp);
6753 break;
6754 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6755 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6756 ARCH(6T2);
6757 tmp = load_reg(s, rm);
6758 shift = (insn >> 7) & 0x1f;
6759 i = ((insn >> 16) & 0x1f) + 1;
6760 if (shift + i > 32)
6761 goto illegal_op;
6762 if (i < 32) {
6763 if (op1 & 0x20) {
6764 gen_ubfx(tmp, shift, (1u << i) - 1);
6765 } else {
6766 gen_sbfx(tmp, shift, i);
6769 store_reg(s, rd, tmp);
6770 break;
6771 default:
6772 goto illegal_op;
6774 break;
6776 break;
6778 do_ldst:
6779 /* Check for undefined extension instructions
6780 * per the ARM Bible IE:
6781 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6783 sh = (0xf << 20) | (0xf << 4);
6784 if (op1 == 0x7 && ((insn & sh) == sh))
6786 goto illegal_op;
6788 /* load/store byte/word */
6789 rn = (insn >> 16) & 0xf;
6790 rd = (insn >> 12) & 0xf;
6791 tmp2 = load_reg(s, rn);
6792 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
6793 if (insn & (1 << 24))
6794 gen_add_data_offset(s, insn, tmp2);
6795 if (insn & (1 << 20)) {
6796 /* load */
6797 if (insn & (1 << 22)) {
6798 tmp = gen_ld8u(tmp2, i);
6799 } else {
6800 tmp = gen_ld32(tmp2, i);
6802 } else {
6803 /* store */
6804 tmp = load_reg(s, rd);
6805 if (insn & (1 << 22))
6806 gen_st8(tmp, tmp2, i);
6807 else
6808 gen_st32(tmp, tmp2, i);
6810 if (!(insn & (1 << 24))) {
6811 gen_add_data_offset(s, insn, tmp2);
6812 store_reg(s, rn, tmp2);
6813 } else if (insn & (1 << 21)) {
6814 store_reg(s, rn, tmp2);
6815 } else {
6816 dead_tmp(tmp2);
6818 if (insn & (1 << 20)) {
6819 /* Complete the load. */
6820 if (rd == 15)
6821 gen_bx(s, tmp);
6822 else
6823 store_reg(s, rd, tmp);
6825 break;
6826 case 0x08:
6827 case 0x09:
6829 int j, n, user, loaded_base;
6830 TCGv loaded_var;
6831 /* load/store multiple words */
6832 /* XXX: store correct base if write back */
6833 user = 0;
6834 if (insn & (1 << 22)) {
6835 if (IS_USER(s))
6836 goto illegal_op; /* only usable in supervisor mode */
6838 if ((insn & (1 << 15)) == 0)
6839 user = 1;
6841 rn = (insn >> 16) & 0xf;
6842 addr = load_reg(s, rn);
6844 /* compute total size */
6845 loaded_base = 0;
6846 TCGV_UNUSED(loaded_var);
6847 n = 0;
6848 for(i=0;i<16;i++) {
6849 if (insn & (1 << i))
6850 n++;
6852 /* XXX: test invalid n == 0 case ? */
6853 if (insn & (1 << 23)) {
6854 if (insn & (1 << 24)) {
6855 /* pre increment */
6856 tcg_gen_addi_i32(addr, addr, 4);
6857 } else {
6858 /* post increment */
6860 } else {
6861 if (insn & (1 << 24)) {
6862 /* pre decrement */
6863 tcg_gen_addi_i32(addr, addr, -(n * 4));
6864 } else {
6865 /* post decrement */
6866 if (n != 1)
6867 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6870 j = 0;
6871 for(i=0;i<16;i++) {
6872 if (insn & (1 << i)) {
6873 if (insn & (1 << 20)) {
6874 /* load */
6875 tmp = gen_ld32(addr, IS_USER(s));
6876 if (i == 15) {
6877 gen_bx(s, tmp);
6878 } else if (user) {
6879 tmp2 = tcg_const_i32(i);
6880 gen_helper_set_user_reg(tmp2, tmp);
6881 tcg_temp_free_i32(tmp2);
6882 dead_tmp(tmp);
6883 } else if (i == rn) {
6884 loaded_var = tmp;
6885 loaded_base = 1;
6886 } else {
6887 store_reg(s, i, tmp);
6889 } else {
6890 /* store */
6891 if (i == 15) {
6892 /* special case: r15 = PC + 8 */
6893 val = (long)s->pc + 4;
6894 tmp = new_tmp();
6895 tcg_gen_movi_i32(tmp, val);
6896 } else if (user) {
6897 tmp = new_tmp();
6898 tmp2 = tcg_const_i32(i);
6899 gen_helper_get_user_reg(tmp, tmp2);
6900 tcg_temp_free_i32(tmp2);
6901 } else {
6902 tmp = load_reg(s, i);
6904 gen_st32(tmp, addr, IS_USER(s));
6906 j++;
6907 /* no need to add after the last transfer */
6908 if (j != n)
6909 tcg_gen_addi_i32(addr, addr, 4);
6912 if (insn & (1 << 21)) {
6913 /* write back */
6914 if (insn & (1 << 23)) {
6915 if (insn & (1 << 24)) {
6916 /* pre increment */
6917 } else {
6918 /* post increment */
6919 tcg_gen_addi_i32(addr, addr, 4);
6921 } else {
6922 if (insn & (1 << 24)) {
6923 /* pre decrement */
6924 if (n != 1)
6925 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6926 } else {
6927 /* post decrement */
6928 tcg_gen_addi_i32(addr, addr, -(n * 4));
6931 store_reg(s, rn, addr);
6932 } else {
6933 dead_tmp(addr);
6935 if (loaded_base) {
6936 store_reg(s, rn, loaded_var);
6938 if ((insn & (1 << 22)) && !user) {
6939 /* Restore CPSR from SPSR. */
6940 tmp = load_cpu_field(spsr);
6941 gen_set_cpsr(tmp, 0xffffffff);
6942 dead_tmp(tmp);
6943 s->is_jmp = DISAS_UPDATE;
6946 break;
6947 case 0xa:
6948 case 0xb:
6950 int32_t offset;
6952 /* branch (and link) */
6953 val = (int32_t)s->pc;
6954 if (insn & (1 << 24)) {
6955 tmp = new_tmp();
6956 tcg_gen_movi_i32(tmp, val);
6957 store_reg(s, 14, tmp);
6959 offset = (((int32_t)insn << 8) >> 8);
6960 val += (offset << 2) + 4;
6961 gen_jmp(s, val);
6963 break;
6964 case 0xc:
6965 case 0xd:
6966 case 0xe:
6967 /* Coprocessor. */
6968 if (disas_coproc_insn(env, s, insn))
6969 goto illegal_op;
6970 break;
6971 case 0xf:
6972 /* swi */
6973 gen_set_pc_im(s->pc);
6974 s->is_jmp = DISAS_SWI;
6975 break;
6976 default:
6977 illegal_op:
6978 gen_set_condexec(s);
6979 gen_set_pc_im(s->pc - 4);
6980 gen_exception(EXCP_UDEF);
6981 s->is_jmp = DISAS_JUMP;
6982 break;
6987 /* Return true if this is a Thumb-2 logical op. */
6988 static int
6989 thumb2_logic_op(int op)
6991 return (op < 8);
6994 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
6995 then set condition code flags based on the result of the operation.
6996 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
6997 to the high bit of T1.
6998 Returns zero if the opcode is valid. */
7000 static int
7001 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCGv t0, TCGv t1)
7003 int logic_cc;
7005 logic_cc = 0;
7006 switch (op) {
7007 case 0: /* and */
7008 tcg_gen_and_i32(t0, t0, t1);
7009 logic_cc = conds;
7010 break;
7011 case 1: /* bic */
7012 tcg_gen_bic_i32(t0, t0, t1);
7013 logic_cc = conds;
7014 break;
7015 case 2: /* orr */
7016 tcg_gen_or_i32(t0, t0, t1);
7017 logic_cc = conds;
7018 break;
7019 case 3: /* orn */
7020 tcg_gen_not_i32(t1, t1);
7021 tcg_gen_or_i32(t0, t0, t1);
7022 logic_cc = conds;
7023 break;
7024 case 4: /* eor */
7025 tcg_gen_xor_i32(t0, t0, t1);
7026 logic_cc = conds;
7027 break;
7028 case 8: /* add */
7029 if (conds)
7030 gen_helper_add_cc(t0, t0, t1);
7031 else
7032 tcg_gen_add_i32(t0, t0, t1);
7033 break;
7034 case 10: /* adc */
7035 if (conds)
7036 gen_helper_adc_cc(t0, t0, t1);
7037 else
7038 gen_adc(t0, t1);
7039 break;
7040 case 11: /* sbc */
7041 if (conds)
7042 gen_helper_sbc_cc(t0, t0, t1);
7043 else
7044 gen_sub_carry(t0, t0, t1);
7045 break;
7046 case 13: /* sub */
7047 if (conds)
7048 gen_helper_sub_cc(t0, t0, t1);
7049 else
7050 tcg_gen_sub_i32(t0, t0, t1);
7051 break;
7052 case 14: /* rsb */
7053 if (conds)
7054 gen_helper_sub_cc(t0, t1, t0);
7055 else
7056 tcg_gen_sub_i32(t0, t1, t0);
7057 break;
7058 default: /* 5, 6, 7, 9, 12, 15. */
7059 return 1;
7061 if (logic_cc) {
7062 gen_logic_CC(t0);
7063 if (shifter_out)
7064 gen_set_CF_bit31(t1);
7066 return 0;
7069 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7070 is not legal. */
7071 static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7073 uint32_t insn, imm, shift, offset;
7074 uint32_t rd, rn, rm, rs;
7075 TCGv tmp;
7076 TCGv tmp2;
7077 TCGv tmp3;
7078 TCGv addr;
7079 TCGv_i64 tmp64;
7080 int op;
7081 int shiftop;
7082 int conds;
7083 int logic_cc;
7085 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
7086 || arm_feature (env, ARM_FEATURE_M))) {
7087 /* Thumb-1 cores may need to treat bl and blx as a pair of
7088 16-bit instructions to get correct prefetch abort behavior. */
7089 insn = insn_hw1;
7090 if ((insn & (1 << 12)) == 0) {
7091 /* Second half of blx. */
7092 offset = ((insn & 0x7ff) << 1);
7093 tmp = load_reg(s, 14);
7094 tcg_gen_addi_i32(tmp, tmp, offset);
7095 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
7097 tmp2 = new_tmp();
7098 tcg_gen_movi_i32(tmp2, s->pc | 1);
7099 store_reg(s, 14, tmp2);
7100 gen_bx(s, tmp);
7101 return 0;
7103 if (insn & (1 << 11)) {
7104 /* Second half of bl. */
7105 offset = ((insn & 0x7ff) << 1) | 1;
7106 tmp = load_reg(s, 14);
7107 tcg_gen_addi_i32(tmp, tmp, offset);
7109 tmp2 = new_tmp();
7110 tcg_gen_movi_i32(tmp2, s->pc | 1);
7111 store_reg(s, 14, tmp2);
7112 gen_bx(s, tmp);
7113 return 0;
7115 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
7116 /* Instruction spans a page boundary. Implement it as two
7117 16-bit instructions in case the second half causes an
7118 prefetch abort. */
7119 offset = ((int32_t)insn << 21) >> 9;
7120 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
7121 return 0;
7123 /* Fall through to 32-bit decode. */
7126 insn = lduw_code(s->pc);
7127 s->pc += 2;
7128 insn |= (uint32_t)insn_hw1 << 16;
7130 if ((insn & 0xf800e800) != 0xf000e800) {
7131 ARCH(6T2);
7134 rn = (insn >> 16) & 0xf;
7135 rs = (insn >> 12) & 0xf;
7136 rd = (insn >> 8) & 0xf;
7137 rm = insn & 0xf;
7138 switch ((insn >> 25) & 0xf) {
7139 case 0: case 1: case 2: case 3:
7140 /* 16-bit instructions. Should never happen. */
7141 abort();
7142 case 4:
7143 if (insn & (1 << 22)) {
7144 /* Other load/store, table branch. */
7145 if (insn & 0x01200000) {
7146 /* Load/store doubleword. */
7147 if (rn == 15) {
7148 addr = new_tmp();
7149 tcg_gen_movi_i32(addr, s->pc & ~3);
7150 } else {
7151 addr = load_reg(s, rn);
7153 offset = (insn & 0xff) * 4;
7154 if ((insn & (1 << 23)) == 0)
7155 offset = -offset;
7156 if (insn & (1 << 24)) {
7157 tcg_gen_addi_i32(addr, addr, offset);
7158 offset = 0;
7160 if (insn & (1 << 20)) {
7161 /* ldrd */
7162 tmp = gen_ld32(addr, IS_USER(s));
7163 store_reg(s, rs, tmp);
7164 tcg_gen_addi_i32(addr, addr, 4);
7165 tmp = gen_ld32(addr, IS_USER(s));
7166 store_reg(s, rd, tmp);
7167 } else {
7168 /* strd */
7169 tmp = load_reg(s, rs);
7170 gen_st32(tmp, addr, IS_USER(s));
7171 tcg_gen_addi_i32(addr, addr, 4);
7172 tmp = load_reg(s, rd);
7173 gen_st32(tmp, addr, IS_USER(s));
7175 if (insn & (1 << 21)) {
7176 /* Base writeback. */
7177 if (rn == 15)
7178 goto illegal_op;
7179 tcg_gen_addi_i32(addr, addr, offset - 4);
7180 store_reg(s, rn, addr);
7181 } else {
7182 dead_tmp(addr);
7184 } else if ((insn & (1 << 23)) == 0) {
7185 /* Load/store exclusive word. */
7186 addr = tcg_temp_local_new();
7187 load_reg_var(s, addr, rn);
7188 if (insn & (1 << 20)) {
7189 gen_helper_mark_exclusive(cpu_env, addr);
7190 tmp = gen_ld32(addr, IS_USER(s));
7191 store_reg(s, rd, tmp);
7192 } else {
7193 int label = gen_new_label();
7194 tmp2 = tcg_temp_local_new();
7195 gen_helper_test_exclusive(tmp2, cpu_env, addr);
7196 tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label);
7197 tmp = load_reg(s, rs);
7198 gen_st32(tmp, addr, IS_USER(s));
7199 gen_set_label(label);
7200 tcg_gen_mov_i32(cpu_R[rd], tmp2);
7201 tcg_temp_free(tmp2);
7203 tcg_temp_free(addr);
7204 } else if ((insn & (1 << 6)) == 0) {
7205 /* Table Branch. */
7206 if (rn == 15) {
7207 addr = new_tmp();
7208 tcg_gen_movi_i32(addr, s->pc);
7209 } else {
7210 addr = load_reg(s, rn);
7212 tmp = load_reg(s, rm);
7213 tcg_gen_add_i32(addr, addr, tmp);
7214 if (insn & (1 << 4)) {
7215 /* tbh */
7216 tcg_gen_add_i32(addr, addr, tmp);
7217 dead_tmp(tmp);
7218 tmp = gen_ld16u(addr, IS_USER(s));
7219 } else { /* tbb */
7220 dead_tmp(tmp);
7221 tmp = gen_ld8u(addr, IS_USER(s));
7223 dead_tmp(addr);
7224 tcg_gen_shli_i32(tmp, tmp, 1);
7225 tcg_gen_addi_i32(tmp, tmp, s->pc);
7226 store_reg(s, 15, tmp);
7227 } else {
7228 /* Load/store exclusive byte/halfword/doubleword. */
7229 /* ??? These are not really atomic. However we know
7230 we never have multiple CPUs running in parallel,
7231 so it is good enough. */
7232 op = (insn >> 4) & 0x3;
7233 addr = tcg_temp_local_new();
7234 load_reg_var(s, addr, rn);
7235 if (insn & (1 << 20)) {
7236 gen_helper_mark_exclusive(cpu_env, addr);
7237 switch (op) {
7238 case 0:
7239 tmp = gen_ld8u(addr, IS_USER(s));
7240 break;
7241 case 1:
7242 tmp = gen_ld16u(addr, IS_USER(s));
7243 break;
7244 case 3:
7245 tmp = gen_ld32(addr, IS_USER(s));
7246 tcg_gen_addi_i32(addr, addr, 4);
7247 tmp2 = gen_ld32(addr, IS_USER(s));
7248 store_reg(s, rd, tmp2);
7249 break;
7250 default:
7251 goto illegal_op;
7253 store_reg(s, rs, tmp);
7254 } else {
7255 int label = gen_new_label();
7256 tmp2 = tcg_temp_local_new();
7257 gen_helper_test_exclusive(tmp2, cpu_env, addr);
7258 tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label);
7259 tmp = load_reg(s, rs);
7260 switch (op) {
7261 case 0:
7262 gen_st8(tmp, addr, IS_USER(s));
7263 break;
7264 case 1:
7265 gen_st16(tmp, addr, IS_USER(s));
7266 break;
7267 case 3:
7268 gen_st32(tmp, addr, IS_USER(s));
7269 tcg_gen_addi_i32(addr, addr, 4);
7270 tmp = load_reg(s, rd);
7271 gen_st32(tmp, addr, IS_USER(s));
7272 break;
7273 default:
7274 goto illegal_op;
7276 gen_set_label(label);
7277 tcg_gen_mov_i32(cpu_R[rm], tmp2);
7278 tcg_temp_free(tmp2);
7280 tcg_temp_free(addr);
7282 } else {
7283 /* Load/store multiple, RFE, SRS. */
7284 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
7285 /* Not available in user mode. */
7286 if (IS_USER(s))
7287 goto illegal_op;
7288 if (insn & (1 << 20)) {
7289 /* rfe */
7290 addr = load_reg(s, rn);
7291 if ((insn & (1 << 24)) == 0)
7292 tcg_gen_addi_i32(addr, addr, -8);
7293 /* Load PC into tmp and CPSR into tmp2. */
7294 tmp = gen_ld32(addr, 0);
7295 tcg_gen_addi_i32(addr, addr, 4);
7296 tmp2 = gen_ld32(addr, 0);
7297 if (insn & (1 << 21)) {
7298 /* Base writeback. */
7299 if (insn & (1 << 24)) {
7300 tcg_gen_addi_i32(addr, addr, 4);
7301 } else {
7302 tcg_gen_addi_i32(addr, addr, -4);
7304 store_reg(s, rn, addr);
7305 } else {
7306 dead_tmp(addr);
7308 gen_rfe(s, tmp, tmp2);
7309 } else {
7310 /* srs */
7311 op = (insn & 0x1f);
7312 if (op == (env->uncached_cpsr & CPSR_M)) {
7313 addr = load_reg(s, 13);
7314 } else {
7315 addr = new_tmp();
7316 tmp = tcg_const_i32(op);
7317 gen_helper_get_r13_banked(addr, cpu_env, tmp);
7318 tcg_temp_free_i32(tmp);
7320 if ((insn & (1 << 24)) == 0) {
7321 tcg_gen_addi_i32(addr, addr, -8);
7323 tmp = load_reg(s, 14);
7324 gen_st32(tmp, addr, 0);
7325 tcg_gen_addi_i32(addr, addr, 4);
7326 tmp = new_tmp();
7327 gen_helper_cpsr_read(tmp);
7328 gen_st32(tmp, addr, 0);
7329 if (insn & (1 << 21)) {
7330 if ((insn & (1 << 24)) == 0) {
7331 tcg_gen_addi_i32(addr, addr, -4);
7332 } else {
7333 tcg_gen_addi_i32(addr, addr, 4);
7335 if (op == (env->uncached_cpsr & CPSR_M)) {
7336 store_reg(s, 13, addr);
7337 } else {
7338 tmp = tcg_const_i32(op);
7339 gen_helper_set_r13_banked(cpu_env, tmp, addr);
7340 tcg_temp_free_i32(tmp);
7342 } else {
7343 dead_tmp(addr);
7346 } else {
7347 int i;
7348 /* Load/store multiple. */
7349 addr = load_reg(s, rn);
7350 offset = 0;
7351 for (i = 0; i < 16; i++) {
7352 if (insn & (1 << i))
7353 offset += 4;
7355 if (insn & (1 << 24)) {
7356 tcg_gen_addi_i32(addr, addr, -offset);
7359 for (i = 0; i < 16; i++) {
7360 if ((insn & (1 << i)) == 0)
7361 continue;
7362 if (insn & (1 << 20)) {
7363 /* Load. */
7364 tmp = gen_ld32(addr, IS_USER(s));
7365 if (i == 15) {
7366 gen_bx(s, tmp);
7367 } else {
7368 store_reg(s, i, tmp);
7370 } else {
7371 /* Store. */
7372 tmp = load_reg(s, i);
7373 gen_st32(tmp, addr, IS_USER(s));
7375 tcg_gen_addi_i32(addr, addr, 4);
7377 if (insn & (1 << 21)) {
7378 /* Base register writeback. */
7379 if (insn & (1 << 24)) {
7380 tcg_gen_addi_i32(addr, addr, -offset);
7382 /* Fault if writeback register is in register list. */
7383 if (insn & (1 << rn))
7384 goto illegal_op;
7385 store_reg(s, rn, addr);
7386 } else {
7387 dead_tmp(addr);
7391 break;
7392 case 5: /* Data processing register constant shift. */
7393 if (rn == 15) {
7394 tmp = new_tmp();
7395 tcg_gen_movi_i32(tmp, 0);
7396 } else {
7397 tmp = load_reg(s, rn);
7399 tmp2 = load_reg(s, rm);
7400 op = (insn >> 21) & 0xf;
7401 shiftop = (insn >> 4) & 3;
7402 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7403 conds = (insn & (1 << 20)) != 0;
7404 logic_cc = (conds && thumb2_logic_op(op));
7405 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
7406 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
7407 goto illegal_op;
7408 dead_tmp(tmp2);
7409 if (rd != 15) {
7410 store_reg(s, rd, tmp);
7411 } else {
7412 dead_tmp(tmp);
7414 break;
7415 case 13: /* Misc data processing. */
7416 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
7417 if (op < 4 && (insn & 0xf000) != 0xf000)
7418 goto illegal_op;
7419 switch (op) {
7420 case 0: /* Register controlled shift. */
7421 tmp = load_reg(s, rn);
7422 tmp2 = load_reg(s, rm);
7423 if ((insn & 0x70) != 0)
7424 goto illegal_op;
7425 op = (insn >> 21) & 3;
7426 logic_cc = (insn & (1 << 20)) != 0;
7427 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
7428 if (logic_cc)
7429 gen_logic_CC(tmp);
7430 store_reg_bx(env, s, rd, tmp);
7431 break;
7432 case 1: /* Sign/zero extend. */
7433 tmp = load_reg(s, rm);
7434 shift = (insn >> 4) & 3;
7435 /* ??? In many cases it's not neccessary to do a
7436 rotate, a shift is sufficient. */
7437 if (shift != 0)
7438 tcg_gen_rori_i32(tmp, tmp, shift * 8);
7439 op = (insn >> 20) & 7;
7440 switch (op) {
7441 case 0: gen_sxth(tmp); break;
7442 case 1: gen_uxth(tmp); break;
7443 case 2: gen_sxtb16(tmp); break;
7444 case 3: gen_uxtb16(tmp); break;
7445 case 4: gen_sxtb(tmp); break;
7446 case 5: gen_uxtb(tmp); break;
7447 default: goto illegal_op;
7449 if (rn != 15) {
7450 tmp2 = load_reg(s, rn);
7451 if ((op >> 1) == 1) {
7452 gen_add16(tmp, tmp2);
7453 } else {
7454 tcg_gen_add_i32(tmp, tmp, tmp2);
7455 dead_tmp(tmp2);
7458 store_reg(s, rd, tmp);
7459 break;
7460 case 2: /* SIMD add/subtract. */
7461 op = (insn >> 20) & 7;
7462 shift = (insn >> 4) & 7;
7463 if ((op & 3) == 3 || (shift & 3) == 3)
7464 goto illegal_op;
7465 tmp = load_reg(s, rn);
7466 tmp2 = load_reg(s, rm);
7467 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7468 dead_tmp(tmp2);
7469 store_reg(s, rd, tmp);
7470 break;
7471 case 3: /* Other data processing. */
7472 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
7473 if (op < 4) {
7474 /* Saturating add/subtract. */
7475 tmp = load_reg(s, rn);
7476 tmp2 = load_reg(s, rm);
7477 if (op & 2)
7478 gen_helper_double_saturate(tmp, tmp);
7479 if (op & 1)
7480 gen_helper_sub_saturate(tmp, tmp2, tmp);
7481 else
7482 gen_helper_add_saturate(tmp, tmp, tmp2);
7483 dead_tmp(tmp2);
7484 } else {
7485 tmp = load_reg(s, rn);
7486 switch (op) {
7487 case 0x0a: /* rbit */
7488 gen_helper_rbit(tmp, tmp);
7489 break;
7490 case 0x08: /* rev */
7491 tcg_gen_bswap32_i32(tmp, tmp);
7492 break;
7493 case 0x09: /* rev16 */
7494 gen_rev16(tmp);
7495 break;
7496 case 0x0b: /* revsh */
7497 gen_revsh(tmp);
7498 break;
7499 case 0x10: /* sel */
7500 tmp2 = load_reg(s, rm);
7501 tmp3 = new_tmp();
7502 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
7503 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7504 dead_tmp(tmp3);
7505 dead_tmp(tmp2);
7506 break;
7507 case 0x18: /* clz */
7508 gen_helper_clz(tmp, tmp);
7509 break;
7510 default:
7511 goto illegal_op;
7514 store_reg(s, rd, tmp);
7515 break;
7516 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7517 op = (insn >> 4) & 0xf;
7518 tmp = load_reg(s, rn);
7519 tmp2 = load_reg(s, rm);
7520 switch ((insn >> 20) & 7) {
7521 case 0: /* 32 x 32 -> 32 */
7522 tcg_gen_mul_i32(tmp, tmp, tmp2);
7523 dead_tmp(tmp2);
7524 if (rs != 15) {
7525 tmp2 = load_reg(s, rs);
7526 if (op)
7527 tcg_gen_sub_i32(tmp, tmp2, tmp);
7528 else
7529 tcg_gen_add_i32(tmp, tmp, tmp2);
7530 dead_tmp(tmp2);
7532 break;
7533 case 1: /* 16 x 16 -> 32 */
7534 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7535 dead_tmp(tmp2);
7536 if (rs != 15) {
7537 tmp2 = load_reg(s, rs);
7538 gen_helper_add_setq(tmp, tmp, tmp2);
7539 dead_tmp(tmp2);
7541 break;
7542 case 2: /* Dual multiply add. */
7543 case 4: /* Dual multiply subtract. */
7544 if (op)
7545 gen_swap_half(tmp2);
7546 gen_smul_dual(tmp, tmp2);
7547 /* This addition cannot overflow. */
7548 if (insn & (1 << 22)) {
7549 tcg_gen_sub_i32(tmp, tmp, tmp2);
7550 } else {
7551 tcg_gen_add_i32(tmp, tmp, tmp2);
7553 dead_tmp(tmp2);
7554 if (rs != 15)
7556 tmp2 = load_reg(s, rs);
7557 gen_helper_add_setq(tmp, tmp, tmp2);
7558 dead_tmp(tmp2);
7560 break;
7561 case 3: /* 32 * 16 -> 32msb */
7562 if (op)
7563 tcg_gen_sari_i32(tmp2, tmp2, 16);
7564 else
7565 gen_sxth(tmp2);
7566 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7567 tcg_gen_shri_i64(tmp64, tmp64, 16);
7568 tmp = new_tmp();
7569 tcg_gen_trunc_i64_i32(tmp, tmp64);
7570 tcg_temp_free_i64(tmp64);
7571 if (rs != 15)
7573 tmp2 = load_reg(s, rs);
7574 gen_helper_add_setq(tmp, tmp, tmp2);
7575 dead_tmp(tmp2);
7577 break;
7578 case 5: case 6: /* 32 * 32 -> 32msb */
7579 gen_imull(tmp, tmp2);
7580 if (insn & (1 << 5)) {
7581 gen_roundqd(tmp, tmp2);
7582 dead_tmp(tmp2);
7583 } else {
7584 dead_tmp(tmp);
7585 tmp = tmp2;
7587 if (rs != 15) {
7588 tmp2 = load_reg(s, rs);
7589 if (insn & (1 << 21)) {
7590 tcg_gen_add_i32(tmp, tmp, tmp2);
7591 } else {
7592 tcg_gen_sub_i32(tmp, tmp2, tmp);
7594 dead_tmp(tmp2);
7596 break;
7597 case 7: /* Unsigned sum of absolute differences. */
7598 gen_helper_usad8(tmp, tmp, tmp2);
7599 dead_tmp(tmp2);
7600 if (rs != 15) {
7601 tmp2 = load_reg(s, rs);
7602 tcg_gen_add_i32(tmp, tmp, tmp2);
7603 dead_tmp(tmp2);
7605 break;
7607 store_reg(s, rd, tmp);
7608 break;
7609 case 6: case 7: /* 64-bit multiply, Divide. */
7610 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
7611 tmp = load_reg(s, rn);
7612 tmp2 = load_reg(s, rm);
7613 if ((op & 0x50) == 0x10) {
7614 /* sdiv, udiv */
7615 if (!arm_feature(env, ARM_FEATURE_DIV))
7616 goto illegal_op;
7617 if (op & 0x20)
7618 gen_helper_udiv(tmp, tmp, tmp2);
7619 else
7620 gen_helper_sdiv(tmp, tmp, tmp2);
7621 dead_tmp(tmp2);
7622 store_reg(s, rd, tmp);
7623 } else if ((op & 0xe) == 0xc) {
7624 /* Dual multiply accumulate long. */
7625 if (op & 1)
7626 gen_swap_half(tmp2);
7627 gen_smul_dual(tmp, tmp2);
7628 if (op & 0x10) {
7629 tcg_gen_sub_i32(tmp, tmp, tmp2);
7630 } else {
7631 tcg_gen_add_i32(tmp, tmp, tmp2);
7633 dead_tmp(tmp2);
7634 /* BUGFIX */
7635 tmp64 = tcg_temp_new_i64();
7636 tcg_gen_ext_i32_i64(tmp64, tmp);
7637 dead_tmp(tmp);
7638 gen_addq(s, tmp64, rs, rd);
7639 gen_storeq_reg(s, rs, rd, tmp64);
7640 tcg_temp_free_i64(tmp64);
7641 } else {
7642 if (op & 0x20) {
7643 /* Unsigned 64-bit multiply */
7644 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7645 } else {
7646 if (op & 8) {
7647 /* smlalxy */
7648 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7649 dead_tmp(tmp2);
7650 tmp64 = tcg_temp_new_i64();
7651 tcg_gen_ext_i32_i64(tmp64, tmp);
7652 dead_tmp(tmp);
7653 } else {
7654 /* Signed 64-bit multiply */
7655 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7658 if (op & 4) {
7659 /* umaal */
7660 gen_addq_lo(s, tmp64, rs);
7661 gen_addq_lo(s, tmp64, rd);
7662 } else if (op & 0x40) {
7663 /* 64-bit accumulate. */
7664 gen_addq(s, tmp64, rs, rd);
7666 gen_storeq_reg(s, rs, rd, tmp64);
7667 tcg_temp_free_i64(tmp64);
7669 break;
7671 break;
7672 case 6: case 7: case 14: case 15:
7673 /* Coprocessor. */
7674 if (((insn >> 24) & 3) == 3) {
7675 /* Translate into the equivalent ARM encoding. */
7676 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);
7677 if (disas_neon_data_insn(env, s, insn))
7678 goto illegal_op;
7679 } else {
7680 if (insn & (1 << 28))
7681 goto illegal_op;
7682 if (disas_coproc_insn (env, s, insn))
7683 goto illegal_op;
7685 break;
7686 case 8: case 9: case 10: case 11:
7687 if (insn & (1 << 15)) {
7688 /* Branches, misc control. */
7689 if (insn & 0x5000) {
7690 /* Unconditional branch. */
7691 /* signextend(hw1[10:0]) -> offset[:12]. */
7692 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
7693 /* hw1[10:0] -> offset[11:1]. */
7694 offset |= (insn & 0x7ff) << 1;
7695 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7696 offset[24:22] already have the same value because of the
7697 sign extension above. */
7698 offset ^= ((~insn) & (1 << 13)) << 10;
7699 offset ^= ((~insn) & (1 << 11)) << 11;
7701 if (insn & (1 << 14)) {
7702 /* Branch and link. */
7703 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
7706 offset += s->pc;
7707 if (insn & (1 << 12)) {
7708 /* b/bl */
7709 gen_jmp(s, offset);
7710 } else {
7711 /* blx */
7712 offset &= ~(uint32_t)2;
7713 gen_bx_im(s, offset);
7715 } else if (((insn >> 23) & 7) == 7) {
7716 /* Misc control */
7717 if (insn & (1 << 13))
7718 goto illegal_op;
7720 if (insn & (1 << 26)) {
7721 /* Secure monitor call (v6Z) */
7722 goto illegal_op; /* not implemented. */
7723 } else {
7724 op = (insn >> 20) & 7;
7725 switch (op) {
7726 case 0: /* msr cpsr. */
7727 if (IS_M(env)) {
7728 tmp = load_reg(s, rn);
7729 addr = tcg_const_i32(insn & 0xff);
7730 gen_helper_v7m_msr(cpu_env, addr, tmp);
7731 tcg_temp_free_i32(addr);
7732 dead_tmp(tmp);
7733 gen_lookup_tb(s);
7734 break;
7736 /* fall through */
7737 case 1: /* msr spsr. */
7738 if (IS_M(env))
7739 goto illegal_op;
7740 tmp = load_reg(s, rn);
7741 if (gen_set_psr(s,
7742 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
7743 op == 1, tmp))
7744 goto illegal_op;
7745 break;
7746 case 2: /* cps, nop-hint. */
7747 if (((insn >> 8) & 7) == 0) {
7748 gen_nop_hint(s, insn & 0xff);
7750 /* Implemented as NOP in user mode. */
7751 if (IS_USER(s))
7752 break;
7753 offset = 0;
7754 imm = 0;
7755 if (insn & (1 << 10)) {
7756 if (insn & (1 << 7))
7757 offset |= CPSR_A;
7758 if (insn & (1 << 6))
7759 offset |= CPSR_I;
7760 if (insn & (1 << 5))
7761 offset |= CPSR_F;
7762 if (insn & (1 << 9))
7763 imm = CPSR_A | CPSR_I | CPSR_F;
7765 if (insn & (1 << 8)) {
7766 offset |= 0x1f;
7767 imm |= (insn & 0x1f);
7769 if (offset) {
7770 gen_set_psr_im(s, offset, 0, imm);
7772 break;
7773 case 3: /* Special control operations. */
7774 op = (insn >> 4) & 0xf;
7775 switch (op) {
7776 case 2: /* clrex */
7777 gen_helper_clrex(cpu_env);
7778 break;
7779 case 4: /* dsb */
7780 case 5: /* dmb */
7781 case 6: /* isb */
7782 /* These execute as NOPs. */
7783 ARCH(7);
7784 break;
7785 default:
7786 goto illegal_op;
7788 break;
7789 case 4: /* bxj */
7790 /* Trivial implementation equivalent to bx. */
7791 tmp = load_reg(s, rn);
7792 gen_bx(s, tmp);
7793 break;
7794 case 5: /* Exception return. */
7795 /* Unpredictable in user mode. */
7796 goto illegal_op;
7797 case 6: /* mrs cpsr. */
7798 tmp = new_tmp();
7799 if (IS_M(env)) {
7800 addr = tcg_const_i32(insn & 0xff);
7801 gen_helper_v7m_mrs(tmp, cpu_env, addr);
7802 tcg_temp_free_i32(addr);
7803 } else {
7804 gen_helper_cpsr_read(tmp);
7806 store_reg(s, rd, tmp);
7807 break;
7808 case 7: /* mrs spsr. */
7809 /* Not accessible in user mode. */
7810 if (IS_USER(s) || IS_M(env))
7811 goto illegal_op;
7812 tmp = load_cpu_field(spsr);
7813 store_reg(s, rd, tmp);
7814 break;
7817 } else {
7818 /* Conditional branch. */
7819 op = (insn >> 22) & 0xf;
7820 /* Generate a conditional jump to next instruction. */
7821 s->condlabel = gen_new_label();
7822 gen_test_cc(op ^ 1, s->condlabel);
7823 s->condjmp = 1;
7825 /* offset[11:1] = insn[10:0] */
7826 offset = (insn & 0x7ff) << 1;
7827 /* offset[17:12] = insn[21:16]. */
7828 offset |= (insn & 0x003f0000) >> 4;
7829 /* offset[31:20] = insn[26]. */
7830 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
7831 /* offset[18] = insn[13]. */
7832 offset |= (insn & (1 << 13)) << 5;
7833 /* offset[19] = insn[11]. */
7834 offset |= (insn & (1 << 11)) << 8;
7836 /* jump to the offset */
7837 gen_jmp(s, s->pc + offset);
7839 } else {
7840 /* Data processing immediate. */
7841 if (insn & (1 << 25)) {
7842 if (insn & (1 << 24)) {
7843 if (insn & (1 << 20))
7844 goto illegal_op;
7845 /* Bitfield/Saturate. */
7846 op = (insn >> 21) & 7;
7847 imm = insn & 0x1f;
7848 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7849 if (rn == 15) {
7850 tmp = new_tmp();
7851 tcg_gen_movi_i32(tmp, 0);
7852 } else {
7853 tmp = load_reg(s, rn);
7855 switch (op) {
7856 case 2: /* Signed bitfield extract. */
7857 imm++;
7858 if (shift + imm > 32)
7859 goto illegal_op;
7860 if (imm < 32)
7861 gen_sbfx(tmp, shift, imm);
7862 break;
7863 case 6: /* Unsigned bitfield extract. */
7864 imm++;
7865 if (shift + imm > 32)
7866 goto illegal_op;
7867 if (imm < 32)
7868 gen_ubfx(tmp, shift, (1u << imm) - 1);
7869 break;
7870 case 3: /* Bitfield insert/clear. */
7871 if (imm < shift)
7872 goto illegal_op;
7873 imm = imm + 1 - shift;
7874 if (imm != 32) {
7875 tmp2 = load_reg(s, rd);
7876 gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
7877 dead_tmp(tmp2);
7879 break;
7880 case 7:
7881 goto illegal_op;
7882 default: /* Saturate. */
7883 if (shift) {
7884 if (op & 1)
7885 tcg_gen_sari_i32(tmp, tmp, shift);
7886 else
7887 tcg_gen_shli_i32(tmp, tmp, shift);
7889 tmp2 = tcg_const_i32(imm);
7890 if (op & 4) {
7891 /* Unsigned. */
7892 if ((op & 1) && shift == 0)
7893 gen_helper_usat16(tmp, tmp, tmp2);
7894 else
7895 gen_helper_usat(tmp, tmp, tmp2);
7896 } else {
7897 /* Signed. */
7898 if ((op & 1) && shift == 0)
7899 gen_helper_ssat16(tmp, tmp, tmp2);
7900 else
7901 gen_helper_ssat(tmp, tmp, tmp2);
7903 tcg_temp_free_i32(tmp2);
7904 break;
7906 store_reg(s, rd, tmp);
7907 } else {
7908 imm = ((insn & 0x04000000) >> 15)
7909 | ((insn & 0x7000) >> 4) | (insn & 0xff);
7910 if (insn & (1 << 22)) {
7911 /* 16-bit immediate. */
7912 imm |= (insn >> 4) & 0xf000;
7913 if (insn & (1 << 23)) {
7914 /* movt */
7915 tmp = load_reg(s, rd);
7916 tcg_gen_ext16u_i32(tmp, tmp);
7917 tcg_gen_ori_i32(tmp, tmp, imm << 16);
7918 } else {
7919 /* movw */
7920 tmp = new_tmp();
7921 tcg_gen_movi_i32(tmp, imm);
7923 } else {
7924 /* Add/sub 12-bit immediate. */
7925 if (rn == 15) {
7926 offset = s->pc & ~(uint32_t)3;
7927 if (insn & (1 << 23))
7928 offset -= imm;
7929 else
7930 offset += imm;
7931 tmp = new_tmp();
7932 tcg_gen_movi_i32(tmp, offset);
7933 } else {
7934 tmp = load_reg(s, rn);
7935 if (insn & (1 << 23))
7936 tcg_gen_subi_i32(tmp, tmp, imm);
7937 else
7938 tcg_gen_addi_i32(tmp, tmp, imm);
7941 store_reg(s, rd, tmp);
7943 } else {
7944 int shifter_out = 0;
7945 /* modified 12-bit immediate. */
7946 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
7947 imm = (insn & 0xff);
7948 switch (shift) {
7949 case 0: /* XY */
7950 /* Nothing to do. */
7951 break;
7952 case 1: /* 00XY00XY */
7953 imm |= imm << 16;
7954 break;
7955 case 2: /* XY00XY00 */
7956 imm |= imm << 16;
7957 imm <<= 8;
7958 break;
7959 case 3: /* XYXYXYXY */
7960 imm |= imm << 16;
7961 imm |= imm << 8;
7962 break;
7963 default: /* Rotated constant. */
7964 shift = (shift << 1) | (imm >> 7);
7965 imm |= 0x80;
7966 imm = imm << (32 - shift);
7967 shifter_out = 1;
7968 break;
7970 tmp2 = new_tmp();
7971 tcg_gen_movi_i32(tmp2, imm);
7972 rn = (insn >> 16) & 0xf;
7973 if (rn == 15) {
7974 tmp = new_tmp();
7975 tcg_gen_movi_i32(tmp, 0);
7976 } else {
7977 tmp = load_reg(s, rn);
7979 op = (insn >> 21) & 0xf;
7980 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
7981 shifter_out, tmp, tmp2))
7982 goto illegal_op;
7983 dead_tmp(tmp2);
7984 rd = (insn >> 8) & 0xf;
7985 if (rd != 15) {
7986 store_reg(s, rd, tmp);
7987 } else {
7988 dead_tmp(tmp);
7992 break;
7993 case 12: /* Load/store single data item. */
7995 int postinc = 0;
7996 int writeback = 0;
7997 int user;
7998 if ((insn & 0x01100000) == 0x01000000) {
7999 if (disas_neon_ls_insn(env, s, insn))
8000 goto illegal_op;
8001 break;
8003 user = IS_USER(s);
8004 if (rn == 15) {
8005 addr = new_tmp();
8006 /* PC relative. */
8007 /* s->pc has already been incremented by 4. */
8008 imm = s->pc & 0xfffffffc;
8009 if (insn & (1 << 23))
8010 imm += insn & 0xfff;
8011 else
8012 imm -= insn & 0xfff;
8013 tcg_gen_movi_i32(addr, imm);
8014 } else {
8015 addr = load_reg(s, rn);
8016 if (insn & (1 << 23)) {
8017 /* Positive offset. */
8018 imm = insn & 0xfff;
8019 tcg_gen_addi_i32(addr, addr, imm);
8020 } else {
8021 op = (insn >> 8) & 7;
8022 imm = insn & 0xff;
8023 switch (op) {
8024 case 0: case 8: /* Shifted Register. */
8025 shift = (insn >> 4) & 0xf;
8026 if (shift > 3)
8027 goto illegal_op;
8028 tmp = load_reg(s, rm);
8029 if (shift)
8030 tcg_gen_shli_i32(tmp, tmp, shift);
8031 tcg_gen_add_i32(addr, addr, tmp);
8032 dead_tmp(tmp);
8033 break;
8034 case 4: /* Negative offset. */
8035 tcg_gen_addi_i32(addr, addr, -imm);
8036 break;
8037 case 6: /* User privilege. */
8038 tcg_gen_addi_i32(addr, addr, imm);
8039 user = 1;
8040 break;
8041 case 1: /* Post-decrement. */
8042 imm = -imm;
8043 /* Fall through. */
8044 case 3: /* Post-increment. */
8045 postinc = 1;
8046 writeback = 1;
8047 break;
8048 case 5: /* Pre-decrement. */
8049 imm = -imm;
8050 /* Fall through. */
8051 case 7: /* Pre-increment. */
8052 tcg_gen_addi_i32(addr, addr, imm);
8053 writeback = 1;
8054 break;
8055 default:
8056 goto illegal_op;
8060 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
8061 if (insn & (1 << 20)) {
8062 /* Load. */
8063 if (rs == 15 && op != 2) {
8064 if (op & 2)
8065 goto illegal_op;
8066 /* Memory hint. Implemented as NOP. */
8067 } else {
8068 switch (op) {
8069 case 0: tmp = gen_ld8u(addr, user); break;
8070 case 4: tmp = gen_ld8s(addr, user); break;
8071 case 1: tmp = gen_ld16u(addr, user); break;
8072 case 5: tmp = gen_ld16s(addr, user); break;
8073 case 2: tmp = gen_ld32(addr, user); break;
8074 default: goto illegal_op;
8076 if (rs == 15) {
8077 gen_bx(s, tmp);
8078 } else {
8079 store_reg(s, rs, tmp);
8082 } else {
8083 /* Store. */
8084 if (rs == 15)
8085 goto illegal_op;
8086 tmp = load_reg(s, rs);
8087 switch (op) {
8088 case 0: gen_st8(tmp, addr, user); break;
8089 case 1: gen_st16(tmp, addr, user); break;
8090 case 2: gen_st32(tmp, addr, user); break;
8091 default: goto illegal_op;
8094 if (postinc)
8095 tcg_gen_addi_i32(addr, addr, imm);
8096 if (writeback) {
8097 store_reg(s, rn, addr);
8098 } else {
8099 dead_tmp(addr);
8102 break;
8103 default:
8104 goto illegal_op;
8106 return 0;
8107 illegal_op:
8108 return 1;
8111 static void disas_thumb_insn(CPUState *env, DisasContext *s)
8113 uint32_t val, insn, op, rm, rn, rd, shift, cond;
8114 int32_t offset;
8115 int i;
8116 TCGv tmp;
8117 TCGv tmp2;
8118 TCGv addr;
8120 if (s->condexec_mask) {
8121 cond = s->condexec_cond;
8122 s->condlabel = gen_new_label();
8123 gen_test_cc(cond ^ 1, s->condlabel);
8124 s->condjmp = 1;
8127 insn = lduw_code(s->pc);
8128 s->pc += 2;
8130 switch (insn >> 12) {
8131 case 0: case 1:
8133 rd = insn & 7;
8134 op = (insn >> 11) & 3;
8135 if (op == 3) {
8136 /* add/subtract */
8137 rn = (insn >> 3) & 7;
8138 tmp = load_reg(s, rn);
8139 if (insn & (1 << 10)) {
8140 /* immediate */
8141 tmp2 = new_tmp();
8142 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
8143 } else {
8144 /* reg */
8145 rm = (insn >> 6) & 7;
8146 tmp2 = load_reg(s, rm);
8148 if (insn & (1 << 9)) {
8149 if (s->condexec_mask)
8150 tcg_gen_sub_i32(tmp, tmp, tmp2);
8151 else
8152 gen_helper_sub_cc(tmp, tmp, tmp2);
8153 } else {
8154 if (s->condexec_mask)
8155 tcg_gen_add_i32(tmp, tmp, tmp2);
8156 else
8157 gen_helper_add_cc(tmp, tmp, tmp2);
8159 dead_tmp(tmp2);
8160 store_reg(s, rd, tmp);
8161 } else {
8162 /* shift immediate */
8163 rm = (insn >> 3) & 7;
8164 shift = (insn >> 6) & 0x1f;
8165 tmp = load_reg(s, rm);
8166 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
8167 if (!s->condexec_mask)
8168 gen_logic_CC(tmp);
8169 store_reg(s, rd, tmp);
8171 break;
8172 case 2: case 3:
8173 /* arithmetic large immediate */
8174 op = (insn >> 11) & 3;
8175 rd = (insn >> 8) & 0x7;
8176 if (op == 0) { /* mov */
8177 tmp = new_tmp();
8178 tcg_gen_movi_i32(tmp, insn & 0xff);
8179 if (!s->condexec_mask)
8180 gen_logic_CC(tmp);
8181 store_reg(s, rd, tmp);
8182 } else {
8183 tmp = load_reg(s, rd);
8184 tmp2 = new_tmp();
8185 tcg_gen_movi_i32(tmp2, insn & 0xff);
8186 switch (op) {
8187 case 1: /* cmp */
8188 gen_helper_sub_cc(tmp, tmp, tmp2);
8189 dead_tmp(tmp);
8190 dead_tmp(tmp2);
8191 break;
8192 case 2: /* add */
8193 if (s->condexec_mask)
8194 tcg_gen_add_i32(tmp, tmp, tmp2);
8195 else
8196 gen_helper_add_cc(tmp, tmp, tmp2);
8197 dead_tmp(tmp2);
8198 store_reg(s, rd, tmp);
8199 break;
8200 case 3: /* sub */
8201 if (s->condexec_mask)
8202 tcg_gen_sub_i32(tmp, tmp, tmp2);
8203 else
8204 gen_helper_sub_cc(tmp, tmp, tmp2);
8205 dead_tmp(tmp2);
8206 store_reg(s, rd, tmp);
8207 break;
8210 break;
8211 case 4:
8212 if (insn & (1 << 11)) {
8213 rd = (insn >> 8) & 7;
8214 /* load pc-relative. Bit 1 of PC is ignored. */
8215 val = s->pc + 2 + ((insn & 0xff) * 4);
8216 val &= ~(uint32_t)2;
8217 addr = new_tmp();
8218 tcg_gen_movi_i32(addr, val);
8219 tmp = gen_ld32(addr, IS_USER(s));
8220 dead_tmp(addr);
8221 store_reg(s, rd, tmp);
8222 break;
8224 if (insn & (1 << 10)) {
8225 /* data processing extended or blx */
8226 rd = (insn & 7) | ((insn >> 4) & 8);
8227 rm = (insn >> 3) & 0xf;
8228 op = (insn >> 8) & 3;
8229 switch (op) {
8230 case 0: /* add */
8231 tmp = load_reg(s, rd);
8232 tmp2 = load_reg(s, rm);
8233 tcg_gen_add_i32(tmp, tmp, tmp2);
8234 dead_tmp(tmp2);
8235 store_reg(s, rd, tmp);
8236 break;
8237 case 1: /* cmp */
8238 tmp = load_reg(s, rd);
8239 tmp2 = load_reg(s, rm);
8240 gen_helper_sub_cc(tmp, tmp, tmp2);
8241 dead_tmp(tmp2);
8242 dead_tmp(tmp);
8243 break;
8244 case 2: /* mov/cpy */
8245 tmp = load_reg(s, rm);
8246 store_reg(s, rd, tmp);
8247 break;
8248 case 3:/* branch [and link] exchange thumb register */
8249 tmp = load_reg(s, rm);
8250 if (insn & (1 << 7)) {
8251 val = (uint32_t)s->pc | 1;
8252 tmp2 = new_tmp();
8253 tcg_gen_movi_i32(tmp2, val);
8254 store_reg(s, 14, tmp2);
8256 gen_bx(s, tmp);
8257 break;
8259 break;
8262 /* data processing register */
8263 rd = insn & 7;
8264 rm = (insn >> 3) & 7;
8265 op = (insn >> 6) & 0xf;
8266 if (op == 2 || op == 3 || op == 4 || op == 7) {
8267 /* the shift/rotate ops want the operands backwards */
8268 val = rm;
8269 rm = rd;
8270 rd = val;
8271 val = 1;
8272 } else {
8273 val = 0;
8276 if (op == 9) { /* neg */
8277 tmp = new_tmp();
8278 tcg_gen_movi_i32(tmp, 0);
8279 } else if (op != 0xf) { /* mvn doesn't read its first operand */
8280 tmp = load_reg(s, rd);
8281 } else {
8282 TCGV_UNUSED(tmp);
8285 tmp2 = load_reg(s, rm);
8286 switch (op) {
8287 case 0x0: /* and */
8288 tcg_gen_and_i32(tmp, tmp, tmp2);
8289 if (!s->condexec_mask)
8290 gen_logic_CC(tmp);
8291 break;
8292 case 0x1: /* eor */
8293 tcg_gen_xor_i32(tmp, tmp, tmp2);
8294 if (!s->condexec_mask)
8295 gen_logic_CC(tmp);
8296 break;
8297 case 0x2: /* lsl */
8298 if (s->condexec_mask) {
8299 gen_helper_shl(tmp2, tmp2, tmp);
8300 } else {
8301 gen_helper_shl_cc(tmp2, tmp2, tmp);
8302 gen_logic_CC(tmp2);
8304 break;
8305 case 0x3: /* lsr */
8306 if (s->condexec_mask) {
8307 gen_helper_shr(tmp2, tmp2, tmp);
8308 } else {
8309 gen_helper_shr_cc(tmp2, tmp2, tmp);
8310 gen_logic_CC(tmp2);
8312 break;
8313 case 0x4: /* asr */
8314 if (s->condexec_mask) {
8315 gen_helper_sar(tmp2, tmp2, tmp);
8316 } else {
8317 gen_helper_sar_cc(tmp2, tmp2, tmp);
8318 gen_logic_CC(tmp2);
8320 break;
8321 case 0x5: /* adc */
8322 if (s->condexec_mask)
8323 gen_adc(tmp, tmp2);
8324 else
8325 gen_helper_adc_cc(tmp, tmp, tmp2);
8326 break;
8327 case 0x6: /* sbc */
8328 if (s->condexec_mask)
8329 gen_sub_carry(tmp, tmp, tmp2);
8330 else
8331 gen_helper_sbc_cc(tmp, tmp, tmp2);
8332 break;
8333 case 0x7: /* ror */
8334 if (s->condexec_mask) {
8335 gen_helper_ror(tmp2, tmp2, tmp);
8336 } else {
8337 gen_helper_ror_cc(tmp2, tmp2, tmp);
8338 gen_logic_CC(tmp2);
8340 break;
8341 case 0x8: /* tst */
8342 tcg_gen_and_i32(tmp, tmp, tmp2);
8343 gen_logic_CC(tmp);
8344 rd = 16;
8345 break;
8346 case 0x9: /* neg */
8347 if (s->condexec_mask)
8348 tcg_gen_neg_i32(tmp, tmp2);
8349 else
8350 gen_helper_sub_cc(tmp, tmp, tmp2);
8351 break;
8352 case 0xa: /* cmp */
8353 gen_helper_sub_cc(tmp, tmp, tmp2);
8354 rd = 16;
8355 break;
8356 case 0xb: /* cmn */
8357 gen_helper_add_cc(tmp, tmp, tmp2);
8358 rd = 16;
8359 break;
8360 case 0xc: /* orr */
8361 tcg_gen_or_i32(tmp, tmp, tmp2);
8362 if (!s->condexec_mask)
8363 gen_logic_CC(tmp);
8364 break;
8365 case 0xd: /* mul */
8366 gen_mull(tmp, tmp2);
8367 if (!s->condexec_mask)
8368 gen_logic_CC(tmp);
8369 break;
8370 case 0xe: /* bic */
8371 tcg_gen_bic_i32(tmp, tmp, tmp2);
8372 if (!s->condexec_mask)
8373 gen_logic_CC(tmp);
8374 break;
8375 case 0xf: /* mvn */
8376 tcg_gen_not_i32(tmp2, tmp2);
8377 if (!s->condexec_mask)
8378 gen_logic_CC(tmp2);
8379 val = 1;
8380 rm = rd;
8381 break;
8383 if (rd != 16) {
8384 if (val) {
8385 store_reg(s, rm, tmp2);
8386 if (op != 0xf)
8387 dead_tmp(tmp);
8388 } else {
8389 store_reg(s, rd, tmp);
8390 dead_tmp(tmp2);
8392 } else {
8393 dead_tmp(tmp);
8394 dead_tmp(tmp2);
8396 break;
8398 case 5:
8399 /* load/store register offset. */
8400 rd = insn & 7;
8401 rn = (insn >> 3) & 7;
8402 rm = (insn >> 6) & 7;
8403 op = (insn >> 9) & 7;
8404 addr = load_reg(s, rn);
8405 tmp = load_reg(s, rm);
8406 tcg_gen_add_i32(addr, addr, tmp);
8407 dead_tmp(tmp);
8409 if (op < 3) /* store */
8410 tmp = load_reg(s, rd);
8412 switch (op) {
8413 case 0: /* str */
8414 gen_st32(tmp, addr, IS_USER(s));
8415 break;
8416 case 1: /* strh */
8417 gen_st16(tmp, addr, IS_USER(s));
8418 break;
8419 case 2: /* strb */
8420 gen_st8(tmp, addr, IS_USER(s));
8421 break;
8422 case 3: /* ldrsb */
8423 tmp = gen_ld8s(addr, IS_USER(s));
8424 break;
8425 case 4: /* ldr */
8426 tmp = gen_ld32(addr, IS_USER(s));
8427 break;
8428 case 5: /* ldrh */
8429 tmp = gen_ld16u(addr, IS_USER(s));
8430 break;
8431 case 6: /* ldrb */
8432 tmp = gen_ld8u(addr, IS_USER(s));
8433 break;
8434 case 7: /* ldrsh */
8435 tmp = gen_ld16s(addr, IS_USER(s));
8436 break;
8438 if (op >= 3) /* load */
8439 store_reg(s, rd, tmp);
8440 dead_tmp(addr);
8441 break;
8443 case 6:
8444 /* load/store word immediate offset */
8445 rd = insn & 7;
8446 rn = (insn >> 3) & 7;
8447 addr = load_reg(s, rn);
8448 val = (insn >> 4) & 0x7c;
8449 tcg_gen_addi_i32(addr, addr, val);
8451 if (insn & (1 << 11)) {
8452 /* load */
8453 tmp = gen_ld32(addr, IS_USER(s));
8454 store_reg(s, rd, tmp);
8455 } else {
8456 /* store */
8457 tmp = load_reg(s, rd);
8458 gen_st32(tmp, addr, IS_USER(s));
8460 dead_tmp(addr);
8461 break;
8463 case 7:
8464 /* load/store byte immediate offset */
8465 rd = insn & 7;
8466 rn = (insn >> 3) & 7;
8467 addr = load_reg(s, rn);
8468 val = (insn >> 6) & 0x1f;
8469 tcg_gen_addi_i32(addr, addr, val);
8471 if (insn & (1 << 11)) {
8472 /* load */
8473 tmp = gen_ld8u(addr, IS_USER(s));
8474 store_reg(s, rd, tmp);
8475 } else {
8476 /* store */
8477 tmp = load_reg(s, rd);
8478 gen_st8(tmp, addr, IS_USER(s));
8480 dead_tmp(addr);
8481 break;
8483 case 8:
8484 /* load/store halfword immediate offset */
8485 rd = insn & 7;
8486 rn = (insn >> 3) & 7;
8487 addr = load_reg(s, rn);
8488 val = (insn >> 5) & 0x3e;
8489 tcg_gen_addi_i32(addr, addr, val);
8491 if (insn & (1 << 11)) {
8492 /* load */
8493 tmp = gen_ld16u(addr, IS_USER(s));
8494 store_reg(s, rd, tmp);
8495 } else {
8496 /* store */
8497 tmp = load_reg(s, rd);
8498 gen_st16(tmp, addr, IS_USER(s));
8500 dead_tmp(addr);
8501 break;
8503 case 9:
8504 /* load/store from stack */
8505 rd = (insn >> 8) & 7;
8506 addr = load_reg(s, 13);
8507 val = (insn & 0xff) * 4;
8508 tcg_gen_addi_i32(addr, addr, val);
8510 if (insn & (1 << 11)) {
8511 /* load */
8512 tmp = gen_ld32(addr, IS_USER(s));
8513 store_reg(s, rd, tmp);
8514 } else {
8515 /* store */
8516 tmp = load_reg(s, rd);
8517 gen_st32(tmp, addr, IS_USER(s));
8519 dead_tmp(addr);
8520 break;
8522 case 10:
8523 /* add to high reg */
8524 rd = (insn >> 8) & 7;
8525 if (insn & (1 << 11)) {
8526 /* SP */
8527 tmp = load_reg(s, 13);
8528 } else {
8529 /* PC. bit 1 is ignored. */
8530 tmp = new_tmp();
8531 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
8533 val = (insn & 0xff) * 4;
8534 tcg_gen_addi_i32(tmp, tmp, val);
8535 store_reg(s, rd, tmp);
8536 break;
8538 case 11:
8539 /* misc */
8540 op = (insn >> 8) & 0xf;
8541 switch (op) {
8542 case 0:
8543 /* adjust stack pointer */
8544 tmp = load_reg(s, 13);
8545 val = (insn & 0x7f) * 4;
8546 if (insn & (1 << 7))
8547 val = -(int32_t)val;
8548 tcg_gen_addi_i32(tmp, tmp, val);
8549 store_reg(s, 13, tmp);
8550 break;
8552 case 2: /* sign/zero extend. */
8553 ARCH(6);
8554 rd = insn & 7;
8555 rm = (insn >> 3) & 7;
8556 tmp = load_reg(s, rm);
8557 switch ((insn >> 6) & 3) {
8558 case 0: gen_sxth(tmp); break;
8559 case 1: gen_sxtb(tmp); break;
8560 case 2: gen_uxth(tmp); break;
8561 case 3: gen_uxtb(tmp); break;
8563 store_reg(s, rd, tmp);
8564 break;
8565 case 4: case 5: case 0xc: case 0xd:
8566 /* push/pop */
8567 addr = load_reg(s, 13);
8568 if (insn & (1 << 8))
8569 offset = 4;
8570 else
8571 offset = 0;
8572 for (i = 0; i < 8; i++) {
8573 if (insn & (1 << i))
8574 offset += 4;
8576 if ((insn & (1 << 11)) == 0) {
8577 tcg_gen_addi_i32(addr, addr, -offset);
8579 for (i = 0; i < 8; i++) {
8580 if (insn & (1 << i)) {
8581 if (insn & (1 << 11)) {
8582 /* pop */
8583 tmp = gen_ld32(addr, IS_USER(s));
8584 store_reg(s, i, tmp);
8585 } else {
8586 /* push */
8587 tmp = load_reg(s, i);
8588 gen_st32(tmp, addr, IS_USER(s));
8590 /* advance to the next address. */
8591 tcg_gen_addi_i32(addr, addr, 4);
8594 TCGV_UNUSED(tmp);
8595 if (insn & (1 << 8)) {
8596 if (insn & (1 << 11)) {
8597 /* pop pc */
8598 tmp = gen_ld32(addr, IS_USER(s));
8599 /* don't set the pc until the rest of the instruction
8600 has completed */
8601 } else {
8602 /* push lr */
8603 tmp = load_reg(s, 14);
8604 gen_st32(tmp, addr, IS_USER(s));
8606 tcg_gen_addi_i32(addr, addr, 4);
8608 if ((insn & (1 << 11)) == 0) {
8609 tcg_gen_addi_i32(addr, addr, -offset);
8611 /* write back the new stack pointer */
8612 store_reg(s, 13, addr);
8613 /* set the new PC value */
8614 if ((insn & 0x0900) == 0x0900)
8615 gen_bx(s, tmp);
8616 break;
8618 case 1: case 3: case 9: case 11: /* czb */
8619 rm = insn & 7;
8620 tmp = load_reg(s, rm);
8621 s->condlabel = gen_new_label();
8622 s->condjmp = 1;
8623 if (insn & (1 << 11))
8624 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
8625 else
8626 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
8627 dead_tmp(tmp);
8628 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
8629 val = (uint32_t)s->pc + 2;
8630 val += offset;
8631 gen_jmp(s, val);
8632 break;
8634 case 15: /* IT, nop-hint. */
8635 if ((insn & 0xf) == 0) {
8636 gen_nop_hint(s, (insn >> 4) & 0xf);
8637 break;
8639 /* If Then. */
8640 s->condexec_cond = (insn >> 4) & 0xe;
8641 s->condexec_mask = insn & 0x1f;
8642 /* No actual code generated for this insn, just setup state. */
8643 break;
8645 case 0xe: /* bkpt */
8646 gen_set_condexec(s);
8647 gen_set_pc_im(s->pc - 2);
8648 gen_exception(EXCP_BKPT);
8649 s->is_jmp = DISAS_JUMP;
8650 break;
8652 case 0xa: /* rev */
8653 ARCH(6);
8654 rn = (insn >> 3) & 0x7;
8655 rd = insn & 0x7;
8656 tmp = load_reg(s, rn);
8657 switch ((insn >> 6) & 3) {
8658 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
8659 case 1: gen_rev16(tmp); break;
8660 case 3: gen_revsh(tmp); break;
8661 default: goto illegal_op;
8663 store_reg(s, rd, tmp);
8664 break;
8666 case 6: /* cps */
8667 ARCH(6);
8668 if (IS_USER(s))
8669 break;
8670 if (IS_M(env)) {
8671 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
8672 /* PRIMASK */
8673 if (insn & 1) {
8674 addr = tcg_const_i32(16);
8675 gen_helper_v7m_msr(cpu_env, addr, tmp);
8676 tcg_temp_free_i32(addr);
8678 /* FAULTMASK */
8679 if (insn & 2) {
8680 addr = tcg_const_i32(17);
8681 gen_helper_v7m_msr(cpu_env, addr, tmp);
8682 tcg_temp_free_i32(addr);
8684 tcg_temp_free_i32(tmp);
8685 gen_lookup_tb(s);
8686 } else {
8687 if (insn & (1 << 4))
8688 shift = CPSR_A | CPSR_I | CPSR_F;
8689 else
8690 shift = 0;
8691 gen_set_psr_im(s, shift, 0, ((insn & 7) << 6) & shift);
8693 break;
8695 default:
8696 goto undef;
8698 break;
8700 case 12:
8701 /* load/store multiple */
8702 rn = (insn >> 8) & 0x7;
8703 addr = load_reg(s, rn);
8704 for (i = 0; i < 8; i++) {
8705 if (insn & (1 << i)) {
8706 if (insn & (1 << 11)) {
8707 /* load */
8708 tmp = gen_ld32(addr, IS_USER(s));
8709 store_reg(s, i, tmp);
8710 } else {
8711 /* store */
8712 tmp = load_reg(s, i);
8713 gen_st32(tmp, addr, IS_USER(s));
8715 /* advance to the next address */
8716 tcg_gen_addi_i32(addr, addr, 4);
8719 /* Base register writeback. */
8720 if ((insn & (1 << rn)) == 0) {
8721 store_reg(s, rn, addr);
8722 } else {
8723 dead_tmp(addr);
8725 break;
8727 case 13:
8728 /* conditional branch or swi */
8729 cond = (insn >> 8) & 0xf;
8730 if (cond == 0xe)
8731 goto undef;
8733 if (cond == 0xf) {
8734 /* swi */
8735 gen_set_condexec(s);
8736 gen_set_pc_im(s->pc);
8737 s->is_jmp = DISAS_SWI;
8738 break;
8740 /* generate a conditional jump to next instruction */
8741 s->condlabel = gen_new_label();
8742 gen_test_cc(cond ^ 1, s->condlabel);
8743 s->condjmp = 1;
8745 /* jump to the offset */
8746 val = (uint32_t)s->pc + 2;
8747 offset = ((int32_t)insn << 24) >> 24;
8748 val += offset << 1;
8749 gen_jmp(s, val);
8750 break;
8752 case 14:
8753 if (insn & (1 << 11)) {
8754 if (disas_thumb2_insn(env, s, insn))
8755 goto undef32;
8756 break;
8758 /* unconditional branch */
8759 val = (uint32_t)s->pc;
8760 offset = ((int32_t)insn << 21) >> 21;
8761 val += (offset << 1) + 2;
8762 gen_jmp(s, val);
8763 break;
8765 case 15:
8766 if (disas_thumb2_insn(env, s, insn))
8767 goto undef32;
8768 break;
8770 return;
8771 undef32:
8772 gen_set_condexec(s);
8773 gen_set_pc_im(s->pc - 4);
8774 gen_exception(EXCP_UDEF);
8775 s->is_jmp = DISAS_JUMP;
8776 return;
8777 illegal_op:
8778 undef:
8779 gen_set_condexec(s);
8780 gen_set_pc_im(s->pc - 2);
8781 gen_exception(EXCP_UDEF);
8782 s->is_jmp = DISAS_JUMP;
8785 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8786 basic block 'tb'. If search_pc is TRUE, also generate PC
8787 information for each intermediate instruction. */
8788 static inline void gen_intermediate_code_internal(CPUState *env,
8789 TranslationBlock *tb,
8790 int search_pc)
8792 DisasContext dc1, *dc = &dc1;
8793 CPUBreakpoint *bp;
8794 uint16_t *gen_opc_end;
8795 int j, lj;
8796 target_ulong pc_start;
8797 uint32_t next_page_start;
8798 int num_insns;
8799 int max_insns;
8801 /* generate intermediate code */
8802 num_temps = 0;
8804 pc_start = tb->pc;
8806 dc->tb = tb;
8808 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8810 dc->is_jmp = DISAS_NEXT;
8811 dc->pc = pc_start;
8812 dc->singlestep_enabled = env->singlestep_enabled;
8813 dc->condjmp = 0;
8814 dc->thumb = env->thumb;
8815 dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
8816 dc->condexec_cond = env->condexec_bits >> 4;
8817 #if !defined(CONFIG_USER_ONLY)
8818 if (IS_M(env)) {
8819 dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
8820 } else {
8821 dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
8823 #endif
8824 cpu_F0s = tcg_temp_new_i32();
8825 cpu_F1s = tcg_temp_new_i32();
8826 cpu_F0d = tcg_temp_new_i64();
8827 cpu_F1d = tcg_temp_new_i64();
8828 cpu_V0 = cpu_F0d;
8829 cpu_V1 = cpu_F1d;
8830 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8831 cpu_M0 = tcg_temp_new_i64();
8832 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
8833 lj = -1;
8834 num_insns = 0;
8835 max_insns = tb->cflags & CF_COUNT_MASK;
8836 if (max_insns == 0)
8837 max_insns = CF_COUNT_MASK;
8839 gen_icount_start();
8840 /* Reset the conditional execution bits immediately. This avoids
8841 complications trying to do it at the end of the block. */
8842 if (env->condexec_bits)
8844 TCGv tmp = new_tmp();
8845 tcg_gen_movi_i32(tmp, 0);
8846 store_cpu_field(tmp, condexec_bits);
8848 do {
8849 #ifdef CONFIG_USER_ONLY
8850 /* Intercept jump to the magic kernel page. */
8851 if (dc->pc >= 0xffff0000) {
8852 /* We always get here via a jump, so know we are not in a
8853 conditional execution block. */
8854 gen_exception(EXCP_KERNEL_TRAP);
8855 dc->is_jmp = DISAS_UPDATE;
8856 break;
8858 #else
8859 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
8860 /* We always get here via a jump, so know we are not in a
8861 conditional execution block. */
8862 gen_exception(EXCP_EXCEPTION_EXIT);
8863 dc->is_jmp = DISAS_UPDATE;
8864 break;
8866 #endif
8868 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
8869 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
8870 if (bp->pc == dc->pc) {
8871 gen_set_condexec(dc);
8872 gen_set_pc_im(dc->pc);
8873 gen_exception(EXCP_DEBUG);
8874 dc->is_jmp = DISAS_JUMP;
8875 /* Advance PC so that clearing the breakpoint will
8876 invalidate this TB. */
8877 dc->pc += 2;
8878 goto done_generating;
8879 break;
8883 if (search_pc) {
8884 j = gen_opc_ptr - gen_opc_buf;
8885 if (lj < j) {
8886 lj++;
8887 while (lj < j)
8888 gen_opc_instr_start[lj++] = 0;
8890 gen_opc_pc[lj] = dc->pc;
8891 gen_opc_instr_start[lj] = 1;
8892 gen_opc_icount[lj] = num_insns;
8895 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8896 gen_io_start();
8898 if (env->thumb) {
8899 disas_thumb_insn(env, dc);
8900 if (dc->condexec_mask) {
8901 dc->condexec_cond = (dc->condexec_cond & 0xe)
8902 | ((dc->condexec_mask >> 4) & 1);
8903 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
8904 if (dc->condexec_mask == 0) {
8905 dc->condexec_cond = 0;
8908 } else {
8909 disas_arm_insn(env, dc);
8911 if (num_temps) {
8912 fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
8913 num_temps = 0;
8916 if (dc->condjmp && !dc->is_jmp) {
8917 gen_set_label(dc->condlabel);
8918 dc->condjmp = 0;
8920 /* Translation stops when a conditional branch is encountered.
8921 * Otherwise the subsequent code could get translated several times.
8922 * Also stop translation when a page boundary is reached. This
8923 * ensures prefetch aborts occur at the right place. */
8924 num_insns ++;
8925 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
8926 !env->singlestep_enabled &&
8927 !singlestep &&
8928 dc->pc < next_page_start &&
8929 num_insns < max_insns);
8931 if (tb->cflags & CF_LAST_IO) {
8932 if (dc->condjmp) {
8933 /* FIXME: This can theoretically happen with self-modifying
8934 code. */
8935 cpu_abort(env, "IO on conditional branch instruction");
8937 gen_io_end();
8940 /* At this stage dc->condjmp will only be set when the skipped
8941 instruction was a conditional branch or trap, and the PC has
8942 already been written. */
8943 if (unlikely(env->singlestep_enabled)) {
8944 /* Make sure the pc is updated, and raise a debug exception. */
8945 if (dc->condjmp) {
8946 gen_set_condexec(dc);
8947 if (dc->is_jmp == DISAS_SWI) {
8948 gen_exception(EXCP_SWI);
8949 } else {
8950 gen_exception(EXCP_DEBUG);
8952 gen_set_label(dc->condlabel);
8954 if (dc->condjmp || !dc->is_jmp) {
8955 gen_set_pc_im(dc->pc);
8956 dc->condjmp = 0;
8958 gen_set_condexec(dc);
8959 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
8960 gen_exception(EXCP_SWI);
8961 } else {
8962 /* FIXME: Single stepping a WFI insn will not halt
8963 the CPU. */
8964 gen_exception(EXCP_DEBUG);
8966 } else {
8967 /* While branches must always occur at the end of an IT block,
8968 there are a few other things that can cause us to terminate
8969 the TB in the middel of an IT block:
8970 - Exception generating instructions (bkpt, swi, undefined).
8971 - Page boundaries.
8972 - Hardware watchpoints.
8973 Hardware breakpoints have already been handled and skip this code.
8975 gen_set_condexec(dc);
8976 switch(dc->is_jmp) {
8977 case DISAS_NEXT:
8978 gen_goto_tb(dc, 1, dc->pc);
8979 break;
8980 default:
8981 case DISAS_JUMP:
8982 case DISAS_UPDATE:
8983 /* indicate that the hash table must be used to find the next TB */
8984 tcg_gen_exit_tb(0);
8985 break;
8986 case DISAS_TB_JUMP:
8987 /* nothing more to generate */
8988 break;
8989 case DISAS_WFI:
8990 gen_helper_wfi();
8991 break;
8992 case DISAS_SWI:
8993 gen_exception(EXCP_SWI);
8994 break;
8996 if (dc->condjmp) {
8997 gen_set_label(dc->condlabel);
8998 gen_set_condexec(dc);
8999 gen_goto_tb(dc, 1, dc->pc);
9000 dc->condjmp = 0;
9004 done_generating:
9005 gen_icount_end(tb, num_insns);
9006 *gen_opc_ptr = INDEX_op_end;
9008 #ifdef DEBUG_DISAS
9009 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9010 qemu_log("----------------\n");
9011 qemu_log("IN: %s\n", lookup_symbol(pc_start));
9012 log_target_disas(pc_start, dc->pc - pc_start, env->thumb);
9013 qemu_log("\n");
9015 #endif
9016 if (search_pc) {
9017 j = gen_opc_ptr - gen_opc_buf;
9018 lj++;
9019 while (lj <= j)
9020 gen_opc_instr_start[lj++] = 0;
9021 } else {
9022 tb->size = dc->pc - pc_start;
9023 tb->icount = num_insns;
9027 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
9029 gen_intermediate_code_internal(env, tb, 0);
9032 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
9034 gen_intermediate_code_internal(env, tb, 1);
9037 static const char *cpu_mode_names[16] = {
9038 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9039 "???", "???", "???", "und", "???", "???", "???", "sys"
9042 void cpu_dump_state(CPUState *env, FILE *f,
9043 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
9044 int flags)
9046 int i;
9047 #if 0
9048 union {
9049 uint32_t i;
9050 float s;
9051 } s0, s1;
9052 CPU_DoubleU d;
9053 /* ??? This assumes float64 and double have the same layout.
9054 Oh well, it's only debug dumps. */
9055 union {
9056 float64 f64;
9057 double d;
9058 } d0;
9059 #endif
9060 uint32_t psr;
9062 for(i=0;i<16;i++) {
9063 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
9064 if ((i % 4) == 3)
9065 cpu_fprintf(f, "\n");
9066 else
9067 cpu_fprintf(f, " ");
9069 psr = cpsr_read(env);
9070 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
9071 psr,
9072 psr & (1 << 31) ? 'N' : '-',
9073 psr & (1 << 30) ? 'Z' : '-',
9074 psr & (1 << 29) ? 'C' : '-',
9075 psr & (1 << 28) ? 'V' : '-',
9076 psr & CPSR_T ? 'T' : 'A',
9077 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
9079 #if 0
9080 for (i = 0; i < 16; i++) {
9081 d.d = env->vfp.regs[i];
9082 s0.i = d.l.lower;
9083 s1.i = d.l.upper;
9084 d0.f64 = d.d;
9085 cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9086 i * 2, (int)s0.i, s0.s,
9087 i * 2 + 1, (int)s1.i, s1.s,
9088 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
9089 d0.d);
9091 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
9092 #endif
9095 void gen_pc_load(CPUState *env, TranslationBlock *tb,
9096 unsigned long searched_pc, int pc_pos, void *puc)
9098 env->regs[15] = gen_opc_pc[pc_pos];