target-arm: fix incorrect temporary variable freeing
[qemu/stefanha.git] / target-arm / translate.c
blob1988cc693e6c0933d670773709573d29cc654dcb
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 /* Signed 32x32->64 multiply. */
314 static void gen_imull(TCGv a, TCGv b)
316 TCGv_i64 tmp1 = tcg_temp_new_i64();
317 TCGv_i64 tmp2 = tcg_temp_new_i64();
319 tcg_gen_ext_i32_i64(tmp1, a);
320 tcg_gen_ext_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 /* Swap low and high halfwords. */
330 static void gen_swap_half(TCGv var)
332 TCGv tmp = new_tmp();
333 tcg_gen_shri_i32(tmp, var, 16);
334 tcg_gen_shli_i32(var, var, 16);
335 tcg_gen_or_i32(var, var, tmp);
336 dead_tmp(tmp);
339 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
340 tmp = (t0 ^ t1) & 0x8000;
341 t0 &= ~0x8000;
342 t1 &= ~0x8000;
343 t0 = (t0 + t1) ^ tmp;
346 static void gen_add16(TCGv t0, TCGv t1)
348 TCGv tmp = new_tmp();
349 tcg_gen_xor_i32(tmp, t0, t1);
350 tcg_gen_andi_i32(tmp, tmp, 0x8000);
351 tcg_gen_andi_i32(t0, t0, ~0x8000);
352 tcg_gen_andi_i32(t1, t1, ~0x8000);
353 tcg_gen_add_i32(t0, t0, t1);
354 tcg_gen_xor_i32(t0, t0, tmp);
355 dead_tmp(tmp);
356 dead_tmp(t1);
359 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
361 /* Set CF to the top bit of var. */
362 static void gen_set_CF_bit31(TCGv var)
364 TCGv tmp = new_tmp();
365 tcg_gen_shri_i32(tmp, var, 31);
366 gen_set_CF(tmp);
367 dead_tmp(tmp);
370 /* Set N and Z flags from var. */
371 static inline void gen_logic_CC(TCGv var)
373 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF));
374 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF));
377 /* T0 += T1 + CF. */
378 static void gen_adc(TCGv t0, TCGv t1)
380 TCGv tmp;
381 tcg_gen_add_i32(t0, t0, t1);
382 tmp = load_cpu_field(CF);
383 tcg_gen_add_i32(t0, t0, tmp);
384 dead_tmp(tmp);
387 /* dest = T0 + T1 + CF. */
388 static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
390 TCGv tmp;
391 tcg_gen_add_i32(dest, t0, t1);
392 tmp = load_cpu_field(CF);
393 tcg_gen_add_i32(dest, dest, tmp);
394 dead_tmp(tmp);
397 /* dest = T0 - T1 + CF - 1. */
398 static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
400 TCGv tmp;
401 tcg_gen_sub_i32(dest, t0, t1);
402 tmp = load_cpu_field(CF);
403 tcg_gen_add_i32(dest, dest, tmp);
404 tcg_gen_subi_i32(dest, dest, 1);
405 dead_tmp(tmp);
408 /* T0 &= ~T1. Clobbers T1. */
409 /* FIXME: Implement bic natively. */
410 static inline void tcg_gen_bic_i32(TCGv dest, TCGv t0, TCGv t1)
412 TCGv tmp = new_tmp();
413 tcg_gen_not_i32(tmp, t1);
414 tcg_gen_and_i32(dest, t0, tmp);
415 dead_tmp(tmp);
418 /* FIXME: Implement this natively. */
419 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
421 /* FIXME: Implement this natively. */
422 static void tcg_gen_rori_i32(TCGv t0, TCGv t1, int i)
424 TCGv tmp;
426 if (i == 0)
427 return;
429 tmp = new_tmp();
430 tcg_gen_shri_i32(tmp, t1, i);
431 tcg_gen_shli_i32(t1, t1, 32 - i);
432 tcg_gen_or_i32(t0, t1, tmp);
433 dead_tmp(tmp);
436 static void shifter_out_im(TCGv var, int shift)
438 TCGv tmp = new_tmp();
439 if (shift == 0) {
440 tcg_gen_andi_i32(tmp, var, 1);
441 } else {
442 tcg_gen_shri_i32(tmp, var, shift);
443 if (shift != 31)
444 tcg_gen_andi_i32(tmp, tmp, 1);
446 gen_set_CF(tmp);
447 dead_tmp(tmp);
450 /* Shift by immediate. Includes special handling for shift == 0. */
451 static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
453 switch (shiftop) {
454 case 0: /* LSL */
455 if (shift != 0) {
456 if (flags)
457 shifter_out_im(var, 32 - shift);
458 tcg_gen_shli_i32(var, var, shift);
460 break;
461 case 1: /* LSR */
462 if (shift == 0) {
463 if (flags) {
464 tcg_gen_shri_i32(var, var, 31);
465 gen_set_CF(var);
467 tcg_gen_movi_i32(var, 0);
468 } else {
469 if (flags)
470 shifter_out_im(var, shift - 1);
471 tcg_gen_shri_i32(var, var, shift);
473 break;
474 case 2: /* ASR */
475 if (shift == 0)
476 shift = 32;
477 if (flags)
478 shifter_out_im(var, shift - 1);
479 if (shift == 32)
480 shift = 31;
481 tcg_gen_sari_i32(var, var, shift);
482 break;
483 case 3: /* ROR/RRX */
484 if (shift != 0) {
485 if (flags)
486 shifter_out_im(var, shift - 1);
487 tcg_gen_rori_i32(var, var, shift); break;
488 } else {
489 TCGv tmp = load_cpu_field(CF);
490 if (flags)
491 shifter_out_im(var, 0);
492 tcg_gen_shri_i32(var, var, 1);
493 tcg_gen_shli_i32(tmp, tmp, 31);
494 tcg_gen_or_i32(var, var, tmp);
495 dead_tmp(tmp);
500 static inline void gen_arm_shift_reg(TCGv var, int shiftop,
501 TCGv shift, int flags)
503 if (flags) {
504 switch (shiftop) {
505 case 0: gen_helper_shl_cc(var, var, shift); break;
506 case 1: gen_helper_shr_cc(var, var, shift); break;
507 case 2: gen_helper_sar_cc(var, var, shift); break;
508 case 3: gen_helper_ror_cc(var, var, shift); break;
510 } else {
511 switch (shiftop) {
512 case 0: gen_helper_shl(var, var, shift); break;
513 case 1: gen_helper_shr(var, var, shift); break;
514 case 2: gen_helper_sar(var, var, shift); break;
515 case 3: gen_helper_ror(var, var, shift); break;
518 dead_tmp(shift);
521 #define PAS_OP(pfx) \
522 switch (op2) { \
523 case 0: gen_pas_helper(glue(pfx,add16)); break; \
524 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
525 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
526 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
527 case 4: gen_pas_helper(glue(pfx,add8)); break; \
528 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
530 static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
532 TCGv_ptr tmp;
534 switch (op1) {
535 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
536 case 1:
537 tmp = tcg_temp_new_ptr();
538 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
539 PAS_OP(s)
540 tcg_temp_free_ptr(tmp);
541 break;
542 case 5:
543 tmp = tcg_temp_new_ptr();
544 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
545 PAS_OP(u)
546 tcg_temp_free_ptr(tmp);
547 break;
548 #undef gen_pas_helper
549 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
550 case 2:
551 PAS_OP(q);
552 break;
553 case 3:
554 PAS_OP(sh);
555 break;
556 case 6:
557 PAS_OP(uq);
558 break;
559 case 7:
560 PAS_OP(uh);
561 break;
562 #undef gen_pas_helper
565 #undef PAS_OP
567 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
568 #define PAS_OP(pfx) \
569 switch (op2) { \
570 case 0: gen_pas_helper(glue(pfx,add8)); break; \
571 case 1: gen_pas_helper(glue(pfx,add16)); break; \
572 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
573 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
574 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
575 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
577 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
579 TCGv_ptr tmp;
581 switch (op1) {
582 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
583 case 0:
584 tmp = tcg_temp_new_ptr();
585 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
586 PAS_OP(s)
587 tcg_temp_free_ptr(tmp);
588 break;
589 case 4:
590 tmp = tcg_temp_new_ptr();
591 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
592 PAS_OP(u)
593 tcg_temp_free_ptr(tmp);
594 break;
595 #undef gen_pas_helper
596 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
597 case 1:
598 PAS_OP(q);
599 break;
600 case 2:
601 PAS_OP(sh);
602 break;
603 case 5:
604 PAS_OP(uq);
605 break;
606 case 6:
607 PAS_OP(uh);
608 break;
609 #undef gen_pas_helper
612 #undef PAS_OP
614 static void gen_test_cc(int cc, int label)
616 TCGv tmp;
617 TCGv tmp2;
618 int inv;
620 switch (cc) {
621 case 0: /* eq: Z */
622 tmp = load_cpu_field(ZF);
623 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
624 break;
625 case 1: /* ne: !Z */
626 tmp = load_cpu_field(ZF);
627 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
628 break;
629 case 2: /* cs: C */
630 tmp = load_cpu_field(CF);
631 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
632 break;
633 case 3: /* cc: !C */
634 tmp = load_cpu_field(CF);
635 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
636 break;
637 case 4: /* mi: N */
638 tmp = load_cpu_field(NF);
639 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
640 break;
641 case 5: /* pl: !N */
642 tmp = load_cpu_field(NF);
643 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
644 break;
645 case 6: /* vs: V */
646 tmp = load_cpu_field(VF);
647 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
648 break;
649 case 7: /* vc: !V */
650 tmp = load_cpu_field(VF);
651 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
652 break;
653 case 8: /* hi: C && !Z */
654 inv = gen_new_label();
655 tmp = load_cpu_field(CF);
656 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
657 dead_tmp(tmp);
658 tmp = load_cpu_field(ZF);
659 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
660 gen_set_label(inv);
661 break;
662 case 9: /* ls: !C || Z */
663 tmp = load_cpu_field(CF);
664 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
665 dead_tmp(tmp);
666 tmp = load_cpu_field(ZF);
667 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
668 break;
669 case 10: /* ge: N == V -> N ^ V == 0 */
670 tmp = load_cpu_field(VF);
671 tmp2 = load_cpu_field(NF);
672 tcg_gen_xor_i32(tmp, tmp, tmp2);
673 dead_tmp(tmp2);
674 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
675 break;
676 case 11: /* lt: N != V -> N ^ V != 0 */
677 tmp = load_cpu_field(VF);
678 tmp2 = load_cpu_field(NF);
679 tcg_gen_xor_i32(tmp, tmp, tmp2);
680 dead_tmp(tmp2);
681 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
682 break;
683 case 12: /* gt: !Z && N == V */
684 inv = gen_new_label();
685 tmp = load_cpu_field(ZF);
686 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
687 dead_tmp(tmp);
688 tmp = load_cpu_field(VF);
689 tmp2 = load_cpu_field(NF);
690 tcg_gen_xor_i32(tmp, tmp, tmp2);
691 dead_tmp(tmp2);
692 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
693 gen_set_label(inv);
694 break;
695 case 13: /* le: Z || N != V */
696 tmp = load_cpu_field(ZF);
697 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
698 dead_tmp(tmp);
699 tmp = load_cpu_field(VF);
700 tmp2 = load_cpu_field(NF);
701 tcg_gen_xor_i32(tmp, tmp, tmp2);
702 dead_tmp(tmp2);
703 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
704 break;
705 default:
706 fprintf(stderr, "Bad condition code 0x%x\n", cc);
707 abort();
709 dead_tmp(tmp);
712 static const uint8_t table_logic_cc[16] = {
713 1, /* and */
714 1, /* xor */
715 0, /* sub */
716 0, /* rsb */
717 0, /* add */
718 0, /* adc */
719 0, /* sbc */
720 0, /* rsc */
721 1, /* andl */
722 1, /* xorl */
723 0, /* cmp */
724 0, /* cmn */
725 1, /* orr */
726 1, /* mov */
727 1, /* bic */
728 1, /* mvn */
731 /* Set PC and Thumb state from an immediate address. */
732 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
734 TCGv tmp;
736 s->is_jmp = DISAS_UPDATE;
737 if (s->thumb != (addr & 1)) {
738 tmp = new_tmp();
739 tcg_gen_movi_i32(tmp, addr & 1);
740 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
741 dead_tmp(tmp);
743 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
746 /* Set PC and Thumb state from var. var is marked as dead. */
747 static inline void gen_bx(DisasContext *s, TCGv var)
749 s->is_jmp = DISAS_UPDATE;
750 tcg_gen_andi_i32(cpu_R[15], var, ~1);
751 tcg_gen_andi_i32(var, var, 1);
752 store_cpu_field(var, thumb);
755 /* Variant of store_reg which uses branch&exchange logic when storing
756 to r15 in ARM architecture v7 and above. The source must be a temporary
757 and will be marked as dead. */
758 static inline void store_reg_bx(CPUState *env, DisasContext *s,
759 int reg, TCGv var)
761 if (reg == 15 && ENABLE_ARCH_7) {
762 gen_bx(s, var);
763 } else {
764 store_reg(s, reg, var);
768 static inline TCGv gen_ld8s(TCGv addr, int index)
770 TCGv tmp = new_tmp();
771 tcg_gen_qemu_ld8s(tmp, addr, index);
772 return tmp;
774 static inline TCGv gen_ld8u(TCGv addr, int index)
776 TCGv tmp = new_tmp();
777 tcg_gen_qemu_ld8u(tmp, addr, index);
778 return tmp;
780 static inline TCGv gen_ld16s(TCGv addr, int index)
782 TCGv tmp = new_tmp();
783 tcg_gen_qemu_ld16s(tmp, addr, index);
784 return tmp;
786 static inline TCGv gen_ld16u(TCGv addr, int index)
788 TCGv tmp = new_tmp();
789 tcg_gen_qemu_ld16u(tmp, addr, index);
790 return tmp;
792 static inline TCGv gen_ld32(TCGv addr, int index)
794 TCGv tmp = new_tmp();
795 tcg_gen_qemu_ld32u(tmp, addr, index);
796 return tmp;
798 static inline void gen_st8(TCGv val, TCGv addr, int index)
800 tcg_gen_qemu_st8(val, addr, index);
801 dead_tmp(val);
803 static inline void gen_st16(TCGv val, TCGv addr, int index)
805 tcg_gen_qemu_st16(val, addr, index);
806 dead_tmp(val);
808 static inline void gen_st32(TCGv val, TCGv addr, int index)
810 tcg_gen_qemu_st32(val, addr, index);
811 dead_tmp(val);
814 static inline void gen_set_pc_im(uint32_t val)
816 tcg_gen_movi_i32(cpu_R[15], val);
819 /* Force a TB lookup after an instruction that changes the CPU state. */
820 static inline void gen_lookup_tb(DisasContext *s)
822 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
823 s->is_jmp = DISAS_UPDATE;
826 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
827 TCGv var)
829 int val, rm, shift, shiftop;
830 TCGv offset;
832 if (!(insn & (1 << 25))) {
833 /* immediate */
834 val = insn & 0xfff;
835 if (!(insn & (1 << 23)))
836 val = -val;
837 if (val != 0)
838 tcg_gen_addi_i32(var, var, val);
839 } else {
840 /* shift/register */
841 rm = (insn) & 0xf;
842 shift = (insn >> 7) & 0x1f;
843 shiftop = (insn >> 5) & 3;
844 offset = load_reg(s, rm);
845 gen_arm_shift_im(offset, shiftop, shift, 0);
846 if (!(insn & (1 << 23)))
847 tcg_gen_sub_i32(var, var, offset);
848 else
849 tcg_gen_add_i32(var, var, offset);
850 dead_tmp(offset);
854 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
855 int extra, TCGv var)
857 int val, rm;
858 TCGv offset;
860 if (insn & (1 << 22)) {
861 /* immediate */
862 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
863 if (!(insn & (1 << 23)))
864 val = -val;
865 val += extra;
866 if (val != 0)
867 tcg_gen_addi_i32(var, var, val);
868 } else {
869 /* register */
870 if (extra)
871 tcg_gen_addi_i32(var, var, extra);
872 rm = (insn) & 0xf;
873 offset = load_reg(s, rm);
874 if (!(insn & (1 << 23)))
875 tcg_gen_sub_i32(var, var, offset);
876 else
877 tcg_gen_add_i32(var, var, offset);
878 dead_tmp(offset);
882 #define VFP_OP2(name) \
883 static inline void gen_vfp_##name(int dp) \
885 if (dp) \
886 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
887 else \
888 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
891 VFP_OP2(add)
892 VFP_OP2(sub)
893 VFP_OP2(mul)
894 VFP_OP2(div)
896 #undef VFP_OP2
898 static inline void gen_vfp_abs(int dp)
900 if (dp)
901 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
902 else
903 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
906 static inline void gen_vfp_neg(int dp)
908 if (dp)
909 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
910 else
911 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
914 static inline void gen_vfp_sqrt(int dp)
916 if (dp)
917 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
918 else
919 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
922 static inline void gen_vfp_cmp(int dp)
924 if (dp)
925 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
926 else
927 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
930 static inline void gen_vfp_cmpe(int dp)
932 if (dp)
933 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
934 else
935 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
938 static inline void gen_vfp_F1_ld0(int dp)
940 if (dp)
941 tcg_gen_movi_i64(cpu_F1d, 0);
942 else
943 tcg_gen_movi_i32(cpu_F1s, 0);
946 static inline void gen_vfp_uito(int dp)
948 if (dp)
949 gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
950 else
951 gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
954 static inline void gen_vfp_sito(int dp)
956 if (dp)
957 gen_helper_vfp_sitod(cpu_F0d, cpu_F0s, cpu_env);
958 else
959 gen_helper_vfp_sitos(cpu_F0s, cpu_F0s, cpu_env);
962 static inline void gen_vfp_toui(int dp)
964 if (dp)
965 gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env);
966 else
967 gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env);
970 static inline void gen_vfp_touiz(int dp)
972 if (dp)
973 gen_helper_vfp_touizd(cpu_F0s, cpu_F0d, cpu_env);
974 else
975 gen_helper_vfp_touizs(cpu_F0s, cpu_F0s, cpu_env);
978 static inline void gen_vfp_tosi(int dp)
980 if (dp)
981 gen_helper_vfp_tosid(cpu_F0s, cpu_F0d, cpu_env);
982 else
983 gen_helper_vfp_tosis(cpu_F0s, cpu_F0s, cpu_env);
986 static inline void gen_vfp_tosiz(int dp)
988 if (dp)
989 gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env);
990 else
991 gen_helper_vfp_tosizs(cpu_F0s, cpu_F0s, cpu_env);
994 #define VFP_GEN_FIX(name) \
995 static inline void gen_vfp_##name(int dp, int shift) \
997 TCGv tmp_shift = tcg_const_i32(shift); \
998 if (dp) \
999 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, cpu_env);\
1000 else \
1001 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, cpu_env);\
1002 tcg_temp_free_i32(tmp_shift); \
1004 VFP_GEN_FIX(tosh)
1005 VFP_GEN_FIX(tosl)
1006 VFP_GEN_FIX(touh)
1007 VFP_GEN_FIX(toul)
1008 VFP_GEN_FIX(shto)
1009 VFP_GEN_FIX(slto)
1010 VFP_GEN_FIX(uhto)
1011 VFP_GEN_FIX(ulto)
1012 #undef VFP_GEN_FIX
1014 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv addr)
1016 if (dp)
1017 tcg_gen_qemu_ld64(cpu_F0d, addr, IS_USER(s));
1018 else
1019 tcg_gen_qemu_ld32u(cpu_F0s, addr, IS_USER(s));
1022 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv addr)
1024 if (dp)
1025 tcg_gen_qemu_st64(cpu_F0d, addr, IS_USER(s));
1026 else
1027 tcg_gen_qemu_st32(cpu_F0s, addr, IS_USER(s));
1030 static inline long
1031 vfp_reg_offset (int dp, int reg)
1033 if (dp)
1034 return offsetof(CPUARMState, vfp.regs[reg]);
1035 else if (reg & 1) {
1036 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1037 + offsetof(CPU_DoubleU, l.upper);
1038 } else {
1039 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1040 + offsetof(CPU_DoubleU, l.lower);
1044 /* Return the offset of a 32-bit piece of a NEON register.
1045 zero is the least significant end of the register. */
1046 static inline long
1047 neon_reg_offset (int reg, int n)
1049 int sreg;
1050 sreg = reg * 2 + n;
1051 return vfp_reg_offset(0, sreg);
1054 static TCGv neon_load_reg(int reg, int pass)
1056 TCGv tmp = new_tmp();
1057 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1058 return tmp;
1061 static void neon_store_reg(int reg, int pass, TCGv var)
1063 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1064 dead_tmp(var);
1067 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1069 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1072 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1074 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1077 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1078 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1079 #define tcg_gen_st_f32 tcg_gen_st_i32
1080 #define tcg_gen_st_f64 tcg_gen_st_i64
1082 static inline void gen_mov_F0_vreg(int dp, int reg)
1084 if (dp)
1085 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1086 else
1087 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1090 static inline void gen_mov_F1_vreg(int dp, int reg)
1092 if (dp)
1093 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1094 else
1095 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1098 static inline void gen_mov_vreg_F0(int dp, int reg)
1100 if (dp)
1101 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1102 else
1103 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1106 #define ARM_CP_RW_BIT (1 << 20)
1108 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1110 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1113 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1115 tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1118 static inline TCGv iwmmxt_load_creg(int reg)
1120 TCGv var = new_tmp();
1121 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1122 return var;
1125 static inline void iwmmxt_store_creg(int reg, TCGv var)
1127 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1130 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1132 iwmmxt_store_reg(cpu_M0, rn);
1135 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1137 iwmmxt_load_reg(cpu_M0, rn);
1140 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1142 iwmmxt_load_reg(cpu_V1, rn);
1143 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1146 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1148 iwmmxt_load_reg(cpu_V1, rn);
1149 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1152 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1154 iwmmxt_load_reg(cpu_V1, rn);
1155 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1158 #define IWMMXT_OP(name) \
1159 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1161 iwmmxt_load_reg(cpu_V1, rn); \
1162 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1165 #define IWMMXT_OP_ENV(name) \
1166 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1168 iwmmxt_load_reg(cpu_V1, rn); \
1169 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1172 #define IWMMXT_OP_ENV_SIZE(name) \
1173 IWMMXT_OP_ENV(name##b) \
1174 IWMMXT_OP_ENV(name##w) \
1175 IWMMXT_OP_ENV(name##l)
1177 #define IWMMXT_OP_ENV1(name) \
1178 static inline void gen_op_iwmmxt_##name##_M0(void) \
1180 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1183 IWMMXT_OP(maddsq)
1184 IWMMXT_OP(madduq)
1185 IWMMXT_OP(sadb)
1186 IWMMXT_OP(sadw)
1187 IWMMXT_OP(mulslw)
1188 IWMMXT_OP(mulshw)
1189 IWMMXT_OP(mululw)
1190 IWMMXT_OP(muluhw)
1191 IWMMXT_OP(macsw)
1192 IWMMXT_OP(macuw)
1194 IWMMXT_OP_ENV_SIZE(unpackl)
1195 IWMMXT_OP_ENV_SIZE(unpackh)
1197 IWMMXT_OP_ENV1(unpacklub)
1198 IWMMXT_OP_ENV1(unpackluw)
1199 IWMMXT_OP_ENV1(unpacklul)
1200 IWMMXT_OP_ENV1(unpackhub)
1201 IWMMXT_OP_ENV1(unpackhuw)
1202 IWMMXT_OP_ENV1(unpackhul)
1203 IWMMXT_OP_ENV1(unpacklsb)
1204 IWMMXT_OP_ENV1(unpacklsw)
1205 IWMMXT_OP_ENV1(unpacklsl)
1206 IWMMXT_OP_ENV1(unpackhsb)
1207 IWMMXT_OP_ENV1(unpackhsw)
1208 IWMMXT_OP_ENV1(unpackhsl)
1210 IWMMXT_OP_ENV_SIZE(cmpeq)
1211 IWMMXT_OP_ENV_SIZE(cmpgtu)
1212 IWMMXT_OP_ENV_SIZE(cmpgts)
1214 IWMMXT_OP_ENV_SIZE(mins)
1215 IWMMXT_OP_ENV_SIZE(minu)
1216 IWMMXT_OP_ENV_SIZE(maxs)
1217 IWMMXT_OP_ENV_SIZE(maxu)
1219 IWMMXT_OP_ENV_SIZE(subn)
1220 IWMMXT_OP_ENV_SIZE(addn)
1221 IWMMXT_OP_ENV_SIZE(subu)
1222 IWMMXT_OP_ENV_SIZE(addu)
1223 IWMMXT_OP_ENV_SIZE(subs)
1224 IWMMXT_OP_ENV_SIZE(adds)
1226 IWMMXT_OP_ENV(avgb0)
1227 IWMMXT_OP_ENV(avgb1)
1228 IWMMXT_OP_ENV(avgw0)
1229 IWMMXT_OP_ENV(avgw1)
1231 IWMMXT_OP(msadb)
1233 IWMMXT_OP_ENV(packuw)
1234 IWMMXT_OP_ENV(packul)
1235 IWMMXT_OP_ENV(packuq)
1236 IWMMXT_OP_ENV(packsw)
1237 IWMMXT_OP_ENV(packsl)
1238 IWMMXT_OP_ENV(packsq)
1240 static void gen_op_iwmmxt_set_mup(void)
1242 TCGv tmp;
1243 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1244 tcg_gen_ori_i32(tmp, tmp, 2);
1245 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1248 static void gen_op_iwmmxt_set_cup(void)
1250 TCGv tmp;
1251 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1252 tcg_gen_ori_i32(tmp, tmp, 1);
1253 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1256 static void gen_op_iwmmxt_setpsr_nz(void)
1258 TCGv tmp = new_tmp();
1259 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1260 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1263 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1265 iwmmxt_load_reg(cpu_V1, rn);
1266 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1267 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1270 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn, TCGv dest)
1272 int rd;
1273 uint32_t offset;
1274 TCGv tmp;
1276 rd = (insn >> 16) & 0xf;
1277 tmp = load_reg(s, rd);
1279 offset = (insn & 0xff) << ((insn >> 7) & 2);
1280 if (insn & (1 << 24)) {
1281 /* Pre indexed */
1282 if (insn & (1 << 23))
1283 tcg_gen_addi_i32(tmp, tmp, offset);
1284 else
1285 tcg_gen_addi_i32(tmp, tmp, -offset);
1286 tcg_gen_mov_i32(dest, tmp);
1287 if (insn & (1 << 21))
1288 store_reg(s, rd, tmp);
1289 else
1290 dead_tmp(tmp);
1291 } else if (insn & (1 << 21)) {
1292 /* Post indexed */
1293 tcg_gen_mov_i32(dest, tmp);
1294 if (insn & (1 << 23))
1295 tcg_gen_addi_i32(tmp, tmp, offset);
1296 else
1297 tcg_gen_addi_i32(tmp, tmp, -offset);
1298 store_reg(s, rd, tmp);
1299 } else if (!(insn & (1 << 23)))
1300 return 1;
1301 return 0;
1304 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv dest)
1306 int rd = (insn >> 0) & 0xf;
1307 TCGv tmp;
1309 if (insn & (1 << 8)) {
1310 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1311 return 1;
1312 } else {
1313 tmp = iwmmxt_load_creg(rd);
1315 } else {
1316 tmp = new_tmp();
1317 iwmmxt_load_reg(cpu_V0, rd);
1318 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
1320 tcg_gen_andi_i32(tmp, tmp, mask);
1321 tcg_gen_mov_i32(dest, tmp);
1322 dead_tmp(tmp);
1323 return 0;
1326 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1327 (ie. an undefined instruction). */
1328 static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1330 int rd, wrd;
1331 int rdhi, rdlo, rd0, rd1, i;
1332 TCGv addr;
1333 TCGv tmp, tmp2, tmp3;
1335 if ((insn & 0x0e000e00) == 0x0c000000) {
1336 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1337 wrd = insn & 0xf;
1338 rdlo = (insn >> 12) & 0xf;
1339 rdhi = (insn >> 16) & 0xf;
1340 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1341 iwmmxt_load_reg(cpu_V0, wrd);
1342 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
1343 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1344 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
1345 } else { /* TMCRR */
1346 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1347 iwmmxt_store_reg(cpu_V0, wrd);
1348 gen_op_iwmmxt_set_mup();
1350 return 0;
1353 wrd = (insn >> 12) & 0xf;
1354 addr = new_tmp();
1355 if (gen_iwmmxt_address(s, insn, addr)) {
1356 dead_tmp(addr);
1357 return 1;
1359 if (insn & ARM_CP_RW_BIT) {
1360 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1361 tmp = new_tmp();
1362 tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s));
1363 iwmmxt_store_creg(wrd, tmp);
1364 } else {
1365 i = 1;
1366 if (insn & (1 << 8)) {
1367 if (insn & (1 << 22)) { /* WLDRD */
1368 tcg_gen_qemu_ld64(cpu_M0, addr, IS_USER(s));
1369 i = 0;
1370 } else { /* WLDRW wRd */
1371 tmp = gen_ld32(addr, IS_USER(s));
1373 } else {
1374 if (insn & (1 << 22)) { /* WLDRH */
1375 tmp = gen_ld16u(addr, IS_USER(s));
1376 } else { /* WLDRB */
1377 tmp = gen_ld8u(addr, IS_USER(s));
1380 if (i) {
1381 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1382 dead_tmp(tmp);
1384 gen_op_iwmmxt_movq_wRn_M0(wrd);
1386 } else {
1387 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1388 tmp = iwmmxt_load_creg(wrd);
1389 gen_st32(tmp, addr, IS_USER(s));
1390 } else {
1391 gen_op_iwmmxt_movq_M0_wRn(wrd);
1392 tmp = new_tmp();
1393 if (insn & (1 << 8)) {
1394 if (insn & (1 << 22)) { /* WSTRD */
1395 dead_tmp(tmp);
1396 tcg_gen_qemu_st64(cpu_M0, addr, IS_USER(s));
1397 } else { /* WSTRW wRd */
1398 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1399 gen_st32(tmp, addr, IS_USER(s));
1401 } else {
1402 if (insn & (1 << 22)) { /* WSTRH */
1403 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1404 gen_st16(tmp, addr, IS_USER(s));
1405 } else { /* WSTRB */
1406 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1407 gen_st8(tmp, addr, IS_USER(s));
1412 return 0;
1415 if ((insn & 0x0f000000) != 0x0e000000)
1416 return 1;
1418 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1419 case 0x000: /* WOR */
1420 wrd = (insn >> 12) & 0xf;
1421 rd0 = (insn >> 0) & 0xf;
1422 rd1 = (insn >> 16) & 0xf;
1423 gen_op_iwmmxt_movq_M0_wRn(rd0);
1424 gen_op_iwmmxt_orq_M0_wRn(rd1);
1425 gen_op_iwmmxt_setpsr_nz();
1426 gen_op_iwmmxt_movq_wRn_M0(wrd);
1427 gen_op_iwmmxt_set_mup();
1428 gen_op_iwmmxt_set_cup();
1429 break;
1430 case 0x011: /* TMCR */
1431 if (insn & 0xf)
1432 return 1;
1433 rd = (insn >> 12) & 0xf;
1434 wrd = (insn >> 16) & 0xf;
1435 switch (wrd) {
1436 case ARM_IWMMXT_wCID:
1437 case ARM_IWMMXT_wCASF:
1438 break;
1439 case ARM_IWMMXT_wCon:
1440 gen_op_iwmmxt_set_cup();
1441 /* Fall through. */
1442 case ARM_IWMMXT_wCSSF:
1443 tmp = iwmmxt_load_creg(wrd);
1444 tmp2 = load_reg(s, rd);
1445 tcg_gen_bic_i32(tmp, tmp, tmp2);
1446 dead_tmp(tmp2);
1447 iwmmxt_store_creg(wrd, tmp);
1448 break;
1449 case ARM_IWMMXT_wCGR0:
1450 case ARM_IWMMXT_wCGR1:
1451 case ARM_IWMMXT_wCGR2:
1452 case ARM_IWMMXT_wCGR3:
1453 gen_op_iwmmxt_set_cup();
1454 tmp = load_reg(s, rd);
1455 iwmmxt_store_creg(wrd, tmp);
1456 break;
1457 default:
1458 return 1;
1460 break;
1461 case 0x100: /* WXOR */
1462 wrd = (insn >> 12) & 0xf;
1463 rd0 = (insn >> 0) & 0xf;
1464 rd1 = (insn >> 16) & 0xf;
1465 gen_op_iwmmxt_movq_M0_wRn(rd0);
1466 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1467 gen_op_iwmmxt_setpsr_nz();
1468 gen_op_iwmmxt_movq_wRn_M0(wrd);
1469 gen_op_iwmmxt_set_mup();
1470 gen_op_iwmmxt_set_cup();
1471 break;
1472 case 0x111: /* TMRC */
1473 if (insn & 0xf)
1474 return 1;
1475 rd = (insn >> 12) & 0xf;
1476 wrd = (insn >> 16) & 0xf;
1477 tmp = iwmmxt_load_creg(wrd);
1478 store_reg(s, rd, tmp);
1479 break;
1480 case 0x300: /* WANDN */
1481 wrd = (insn >> 12) & 0xf;
1482 rd0 = (insn >> 0) & 0xf;
1483 rd1 = (insn >> 16) & 0xf;
1484 gen_op_iwmmxt_movq_M0_wRn(rd0);
1485 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1486 gen_op_iwmmxt_andq_M0_wRn(rd1);
1487 gen_op_iwmmxt_setpsr_nz();
1488 gen_op_iwmmxt_movq_wRn_M0(wrd);
1489 gen_op_iwmmxt_set_mup();
1490 gen_op_iwmmxt_set_cup();
1491 break;
1492 case 0x200: /* WAND */
1493 wrd = (insn >> 12) & 0xf;
1494 rd0 = (insn >> 0) & 0xf;
1495 rd1 = (insn >> 16) & 0xf;
1496 gen_op_iwmmxt_movq_M0_wRn(rd0);
1497 gen_op_iwmmxt_andq_M0_wRn(rd1);
1498 gen_op_iwmmxt_setpsr_nz();
1499 gen_op_iwmmxt_movq_wRn_M0(wrd);
1500 gen_op_iwmmxt_set_mup();
1501 gen_op_iwmmxt_set_cup();
1502 break;
1503 case 0x810: case 0xa10: /* WMADD */
1504 wrd = (insn >> 12) & 0xf;
1505 rd0 = (insn >> 0) & 0xf;
1506 rd1 = (insn >> 16) & 0xf;
1507 gen_op_iwmmxt_movq_M0_wRn(rd0);
1508 if (insn & (1 << 21))
1509 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1510 else
1511 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1512 gen_op_iwmmxt_movq_wRn_M0(wrd);
1513 gen_op_iwmmxt_set_mup();
1514 break;
1515 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1516 wrd = (insn >> 12) & 0xf;
1517 rd0 = (insn >> 16) & 0xf;
1518 rd1 = (insn >> 0) & 0xf;
1519 gen_op_iwmmxt_movq_M0_wRn(rd0);
1520 switch ((insn >> 22) & 3) {
1521 case 0:
1522 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1523 break;
1524 case 1:
1525 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1526 break;
1527 case 2:
1528 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1529 break;
1530 case 3:
1531 return 1;
1533 gen_op_iwmmxt_movq_wRn_M0(wrd);
1534 gen_op_iwmmxt_set_mup();
1535 gen_op_iwmmxt_set_cup();
1536 break;
1537 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1538 wrd = (insn >> 12) & 0xf;
1539 rd0 = (insn >> 16) & 0xf;
1540 rd1 = (insn >> 0) & 0xf;
1541 gen_op_iwmmxt_movq_M0_wRn(rd0);
1542 switch ((insn >> 22) & 3) {
1543 case 0:
1544 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1545 break;
1546 case 1:
1547 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1548 break;
1549 case 2:
1550 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1551 break;
1552 case 3:
1553 return 1;
1555 gen_op_iwmmxt_movq_wRn_M0(wrd);
1556 gen_op_iwmmxt_set_mup();
1557 gen_op_iwmmxt_set_cup();
1558 break;
1559 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1560 wrd = (insn >> 12) & 0xf;
1561 rd0 = (insn >> 16) & 0xf;
1562 rd1 = (insn >> 0) & 0xf;
1563 gen_op_iwmmxt_movq_M0_wRn(rd0);
1564 if (insn & (1 << 22))
1565 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1566 else
1567 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1568 if (!(insn & (1 << 20)))
1569 gen_op_iwmmxt_addl_M0_wRn(wrd);
1570 gen_op_iwmmxt_movq_wRn_M0(wrd);
1571 gen_op_iwmmxt_set_mup();
1572 break;
1573 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1574 wrd = (insn >> 12) & 0xf;
1575 rd0 = (insn >> 16) & 0xf;
1576 rd1 = (insn >> 0) & 0xf;
1577 gen_op_iwmmxt_movq_M0_wRn(rd0);
1578 if (insn & (1 << 21)) {
1579 if (insn & (1 << 20))
1580 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1581 else
1582 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1583 } else {
1584 if (insn & (1 << 20))
1585 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1586 else
1587 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1589 gen_op_iwmmxt_movq_wRn_M0(wrd);
1590 gen_op_iwmmxt_set_mup();
1591 break;
1592 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1593 wrd = (insn >> 12) & 0xf;
1594 rd0 = (insn >> 16) & 0xf;
1595 rd1 = (insn >> 0) & 0xf;
1596 gen_op_iwmmxt_movq_M0_wRn(rd0);
1597 if (insn & (1 << 21))
1598 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1599 else
1600 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1601 if (!(insn & (1 << 20))) {
1602 iwmmxt_load_reg(cpu_V1, wrd);
1603 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1605 gen_op_iwmmxt_movq_wRn_M0(wrd);
1606 gen_op_iwmmxt_set_mup();
1607 break;
1608 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1609 wrd = (insn >> 12) & 0xf;
1610 rd0 = (insn >> 16) & 0xf;
1611 rd1 = (insn >> 0) & 0xf;
1612 gen_op_iwmmxt_movq_M0_wRn(rd0);
1613 switch ((insn >> 22) & 3) {
1614 case 0:
1615 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1616 break;
1617 case 1:
1618 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1619 break;
1620 case 2:
1621 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1622 break;
1623 case 3:
1624 return 1;
1626 gen_op_iwmmxt_movq_wRn_M0(wrd);
1627 gen_op_iwmmxt_set_mup();
1628 gen_op_iwmmxt_set_cup();
1629 break;
1630 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1631 wrd = (insn >> 12) & 0xf;
1632 rd0 = (insn >> 16) & 0xf;
1633 rd1 = (insn >> 0) & 0xf;
1634 gen_op_iwmmxt_movq_M0_wRn(rd0);
1635 if (insn & (1 << 22)) {
1636 if (insn & (1 << 20))
1637 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1638 else
1639 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1640 } else {
1641 if (insn & (1 << 20))
1642 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1643 else
1644 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1646 gen_op_iwmmxt_movq_wRn_M0(wrd);
1647 gen_op_iwmmxt_set_mup();
1648 gen_op_iwmmxt_set_cup();
1649 break;
1650 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1651 wrd = (insn >> 12) & 0xf;
1652 rd0 = (insn >> 16) & 0xf;
1653 rd1 = (insn >> 0) & 0xf;
1654 gen_op_iwmmxt_movq_M0_wRn(rd0);
1655 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1656 tcg_gen_andi_i32(tmp, tmp, 7);
1657 iwmmxt_load_reg(cpu_V1, rd1);
1658 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
1659 dead_tmp(tmp);
1660 gen_op_iwmmxt_movq_wRn_M0(wrd);
1661 gen_op_iwmmxt_set_mup();
1662 break;
1663 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1664 if (((insn >> 6) & 3) == 3)
1665 return 1;
1666 rd = (insn >> 12) & 0xf;
1667 wrd = (insn >> 16) & 0xf;
1668 tmp = load_reg(s, rd);
1669 gen_op_iwmmxt_movq_M0_wRn(wrd);
1670 switch ((insn >> 6) & 3) {
1671 case 0:
1672 tmp2 = tcg_const_i32(0xff);
1673 tmp3 = tcg_const_i32((insn & 7) << 3);
1674 break;
1675 case 1:
1676 tmp2 = tcg_const_i32(0xffff);
1677 tmp3 = tcg_const_i32((insn & 3) << 4);
1678 break;
1679 case 2:
1680 tmp2 = tcg_const_i32(0xffffffff);
1681 tmp3 = tcg_const_i32((insn & 1) << 5);
1682 break;
1683 default:
1684 TCGV_UNUSED(tmp2);
1685 TCGV_UNUSED(tmp3);
1687 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
1688 tcg_temp_free(tmp3);
1689 tcg_temp_free(tmp2);
1690 dead_tmp(tmp);
1691 gen_op_iwmmxt_movq_wRn_M0(wrd);
1692 gen_op_iwmmxt_set_mup();
1693 break;
1694 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1695 rd = (insn >> 12) & 0xf;
1696 wrd = (insn >> 16) & 0xf;
1697 if (rd == 15 || ((insn >> 22) & 3) == 3)
1698 return 1;
1699 gen_op_iwmmxt_movq_M0_wRn(wrd);
1700 tmp = new_tmp();
1701 switch ((insn >> 22) & 3) {
1702 case 0:
1703 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
1704 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1705 if (insn & 8) {
1706 tcg_gen_ext8s_i32(tmp, tmp);
1707 } else {
1708 tcg_gen_andi_i32(tmp, tmp, 0xff);
1710 break;
1711 case 1:
1712 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
1713 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1714 if (insn & 8) {
1715 tcg_gen_ext16s_i32(tmp, tmp);
1716 } else {
1717 tcg_gen_andi_i32(tmp, tmp, 0xffff);
1719 break;
1720 case 2:
1721 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
1722 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1723 break;
1725 store_reg(s, rd, tmp);
1726 break;
1727 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1728 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1729 return 1;
1730 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1731 switch ((insn >> 22) & 3) {
1732 case 0:
1733 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
1734 break;
1735 case 1:
1736 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
1737 break;
1738 case 2:
1739 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
1740 break;
1742 tcg_gen_shli_i32(tmp, tmp, 28);
1743 gen_set_nzcv(tmp);
1744 dead_tmp(tmp);
1745 break;
1746 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1747 if (((insn >> 6) & 3) == 3)
1748 return 1;
1749 rd = (insn >> 12) & 0xf;
1750 wrd = (insn >> 16) & 0xf;
1751 tmp = load_reg(s, rd);
1752 switch ((insn >> 6) & 3) {
1753 case 0:
1754 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
1755 break;
1756 case 1:
1757 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
1758 break;
1759 case 2:
1760 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
1761 break;
1763 dead_tmp(tmp);
1764 gen_op_iwmmxt_movq_wRn_M0(wrd);
1765 gen_op_iwmmxt_set_mup();
1766 break;
1767 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1768 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1769 return 1;
1770 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1771 tmp2 = new_tmp();
1772 tcg_gen_mov_i32(tmp2, tmp);
1773 switch ((insn >> 22) & 3) {
1774 case 0:
1775 for (i = 0; i < 7; i ++) {
1776 tcg_gen_shli_i32(tmp2, tmp2, 4);
1777 tcg_gen_and_i32(tmp, tmp, tmp2);
1779 break;
1780 case 1:
1781 for (i = 0; i < 3; i ++) {
1782 tcg_gen_shli_i32(tmp2, tmp2, 8);
1783 tcg_gen_and_i32(tmp, tmp, tmp2);
1785 break;
1786 case 2:
1787 tcg_gen_shli_i32(tmp2, tmp2, 16);
1788 tcg_gen_and_i32(tmp, tmp, tmp2);
1789 break;
1791 gen_set_nzcv(tmp);
1792 dead_tmp(tmp2);
1793 dead_tmp(tmp);
1794 break;
1795 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1796 wrd = (insn >> 12) & 0xf;
1797 rd0 = (insn >> 16) & 0xf;
1798 gen_op_iwmmxt_movq_M0_wRn(rd0);
1799 switch ((insn >> 22) & 3) {
1800 case 0:
1801 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1802 break;
1803 case 1:
1804 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1805 break;
1806 case 2:
1807 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1808 break;
1809 case 3:
1810 return 1;
1812 gen_op_iwmmxt_movq_wRn_M0(wrd);
1813 gen_op_iwmmxt_set_mup();
1814 break;
1815 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1816 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1817 return 1;
1818 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1819 tmp2 = new_tmp();
1820 tcg_gen_mov_i32(tmp2, tmp);
1821 switch ((insn >> 22) & 3) {
1822 case 0:
1823 for (i = 0; i < 7; i ++) {
1824 tcg_gen_shli_i32(tmp2, tmp2, 4);
1825 tcg_gen_or_i32(tmp, tmp, tmp2);
1827 break;
1828 case 1:
1829 for (i = 0; i < 3; i ++) {
1830 tcg_gen_shli_i32(tmp2, tmp2, 8);
1831 tcg_gen_or_i32(tmp, tmp, tmp2);
1833 break;
1834 case 2:
1835 tcg_gen_shli_i32(tmp2, tmp2, 16);
1836 tcg_gen_or_i32(tmp, tmp, tmp2);
1837 break;
1839 gen_set_nzcv(tmp);
1840 dead_tmp(tmp2);
1841 dead_tmp(tmp);
1842 break;
1843 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1844 rd = (insn >> 12) & 0xf;
1845 rd0 = (insn >> 16) & 0xf;
1846 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
1847 return 1;
1848 gen_op_iwmmxt_movq_M0_wRn(rd0);
1849 tmp = new_tmp();
1850 switch ((insn >> 22) & 3) {
1851 case 0:
1852 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
1853 break;
1854 case 1:
1855 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
1856 break;
1857 case 2:
1858 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
1859 break;
1861 store_reg(s, rd, tmp);
1862 break;
1863 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1864 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1865 wrd = (insn >> 12) & 0xf;
1866 rd0 = (insn >> 16) & 0xf;
1867 rd1 = (insn >> 0) & 0xf;
1868 gen_op_iwmmxt_movq_M0_wRn(rd0);
1869 switch ((insn >> 22) & 3) {
1870 case 0:
1871 if (insn & (1 << 21))
1872 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1873 else
1874 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1875 break;
1876 case 1:
1877 if (insn & (1 << 21))
1878 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1879 else
1880 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
1881 break;
1882 case 2:
1883 if (insn & (1 << 21))
1884 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
1885 else
1886 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
1887 break;
1888 case 3:
1889 return 1;
1891 gen_op_iwmmxt_movq_wRn_M0(wrd);
1892 gen_op_iwmmxt_set_mup();
1893 gen_op_iwmmxt_set_cup();
1894 break;
1895 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1896 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1897 wrd = (insn >> 12) & 0xf;
1898 rd0 = (insn >> 16) & 0xf;
1899 gen_op_iwmmxt_movq_M0_wRn(rd0);
1900 switch ((insn >> 22) & 3) {
1901 case 0:
1902 if (insn & (1 << 21))
1903 gen_op_iwmmxt_unpacklsb_M0();
1904 else
1905 gen_op_iwmmxt_unpacklub_M0();
1906 break;
1907 case 1:
1908 if (insn & (1 << 21))
1909 gen_op_iwmmxt_unpacklsw_M0();
1910 else
1911 gen_op_iwmmxt_unpackluw_M0();
1912 break;
1913 case 2:
1914 if (insn & (1 << 21))
1915 gen_op_iwmmxt_unpacklsl_M0();
1916 else
1917 gen_op_iwmmxt_unpacklul_M0();
1918 break;
1919 case 3:
1920 return 1;
1922 gen_op_iwmmxt_movq_wRn_M0(wrd);
1923 gen_op_iwmmxt_set_mup();
1924 gen_op_iwmmxt_set_cup();
1925 break;
1926 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
1927 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1928 wrd = (insn >> 12) & 0xf;
1929 rd0 = (insn >> 16) & 0xf;
1930 gen_op_iwmmxt_movq_M0_wRn(rd0);
1931 switch ((insn >> 22) & 3) {
1932 case 0:
1933 if (insn & (1 << 21))
1934 gen_op_iwmmxt_unpackhsb_M0();
1935 else
1936 gen_op_iwmmxt_unpackhub_M0();
1937 break;
1938 case 1:
1939 if (insn & (1 << 21))
1940 gen_op_iwmmxt_unpackhsw_M0();
1941 else
1942 gen_op_iwmmxt_unpackhuw_M0();
1943 break;
1944 case 2:
1945 if (insn & (1 << 21))
1946 gen_op_iwmmxt_unpackhsl_M0();
1947 else
1948 gen_op_iwmmxt_unpackhul_M0();
1949 break;
1950 case 3:
1951 return 1;
1953 gen_op_iwmmxt_movq_wRn_M0(wrd);
1954 gen_op_iwmmxt_set_mup();
1955 gen_op_iwmmxt_set_cup();
1956 break;
1957 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
1958 case 0x214: case 0x614: case 0xa14: case 0xe14:
1959 if (((insn >> 22) & 3) == 0)
1960 return 1;
1961 wrd = (insn >> 12) & 0xf;
1962 rd0 = (insn >> 16) & 0xf;
1963 gen_op_iwmmxt_movq_M0_wRn(rd0);
1964 tmp = new_tmp();
1965 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
1966 dead_tmp(tmp);
1967 return 1;
1969 switch ((insn >> 22) & 3) {
1970 case 1:
1971 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
1972 break;
1973 case 2:
1974 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
1975 break;
1976 case 3:
1977 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
1978 break;
1980 dead_tmp(tmp);
1981 gen_op_iwmmxt_movq_wRn_M0(wrd);
1982 gen_op_iwmmxt_set_mup();
1983 gen_op_iwmmxt_set_cup();
1984 break;
1985 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
1986 case 0x014: case 0x414: case 0x814: case 0xc14:
1987 if (((insn >> 22) & 3) == 0)
1988 return 1;
1989 wrd = (insn >> 12) & 0xf;
1990 rd0 = (insn >> 16) & 0xf;
1991 gen_op_iwmmxt_movq_M0_wRn(rd0);
1992 tmp = new_tmp();
1993 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
1994 dead_tmp(tmp);
1995 return 1;
1997 switch ((insn >> 22) & 3) {
1998 case 1:
1999 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2000 break;
2001 case 2:
2002 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2003 break;
2004 case 3:
2005 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2006 break;
2008 dead_tmp(tmp);
2009 gen_op_iwmmxt_movq_wRn_M0(wrd);
2010 gen_op_iwmmxt_set_mup();
2011 gen_op_iwmmxt_set_cup();
2012 break;
2013 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2014 case 0x114: case 0x514: case 0x914: case 0xd14:
2015 if (((insn >> 22) & 3) == 0)
2016 return 1;
2017 wrd = (insn >> 12) & 0xf;
2018 rd0 = (insn >> 16) & 0xf;
2019 gen_op_iwmmxt_movq_M0_wRn(rd0);
2020 tmp = new_tmp();
2021 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2022 dead_tmp(tmp);
2023 return 1;
2025 switch ((insn >> 22) & 3) {
2026 case 1:
2027 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2028 break;
2029 case 2:
2030 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2031 break;
2032 case 3:
2033 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2034 break;
2036 dead_tmp(tmp);
2037 gen_op_iwmmxt_movq_wRn_M0(wrd);
2038 gen_op_iwmmxt_set_mup();
2039 gen_op_iwmmxt_set_cup();
2040 break;
2041 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2042 case 0x314: case 0x714: case 0xb14: case 0xf14:
2043 if (((insn >> 22) & 3) == 0)
2044 return 1;
2045 wrd = (insn >> 12) & 0xf;
2046 rd0 = (insn >> 16) & 0xf;
2047 gen_op_iwmmxt_movq_M0_wRn(rd0);
2048 tmp = new_tmp();
2049 switch ((insn >> 22) & 3) {
2050 case 1:
2051 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2052 dead_tmp(tmp);
2053 return 1;
2055 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2056 break;
2057 case 2:
2058 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2059 dead_tmp(tmp);
2060 return 1;
2062 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2063 break;
2064 case 3:
2065 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2066 dead_tmp(tmp);
2067 return 1;
2069 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2070 break;
2072 dead_tmp(tmp);
2073 gen_op_iwmmxt_movq_wRn_M0(wrd);
2074 gen_op_iwmmxt_set_mup();
2075 gen_op_iwmmxt_set_cup();
2076 break;
2077 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2078 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2079 wrd = (insn >> 12) & 0xf;
2080 rd0 = (insn >> 16) & 0xf;
2081 rd1 = (insn >> 0) & 0xf;
2082 gen_op_iwmmxt_movq_M0_wRn(rd0);
2083 switch ((insn >> 22) & 3) {
2084 case 0:
2085 if (insn & (1 << 21))
2086 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2087 else
2088 gen_op_iwmmxt_minub_M0_wRn(rd1);
2089 break;
2090 case 1:
2091 if (insn & (1 << 21))
2092 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2093 else
2094 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2095 break;
2096 case 2:
2097 if (insn & (1 << 21))
2098 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2099 else
2100 gen_op_iwmmxt_minul_M0_wRn(rd1);
2101 break;
2102 case 3:
2103 return 1;
2105 gen_op_iwmmxt_movq_wRn_M0(wrd);
2106 gen_op_iwmmxt_set_mup();
2107 break;
2108 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2109 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2110 wrd = (insn >> 12) & 0xf;
2111 rd0 = (insn >> 16) & 0xf;
2112 rd1 = (insn >> 0) & 0xf;
2113 gen_op_iwmmxt_movq_M0_wRn(rd0);
2114 switch ((insn >> 22) & 3) {
2115 case 0:
2116 if (insn & (1 << 21))
2117 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2118 else
2119 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2120 break;
2121 case 1:
2122 if (insn & (1 << 21))
2123 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2124 else
2125 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2126 break;
2127 case 2:
2128 if (insn & (1 << 21))
2129 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2130 else
2131 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2132 break;
2133 case 3:
2134 return 1;
2136 gen_op_iwmmxt_movq_wRn_M0(wrd);
2137 gen_op_iwmmxt_set_mup();
2138 break;
2139 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2140 case 0x402: case 0x502: case 0x602: case 0x702:
2141 wrd = (insn >> 12) & 0xf;
2142 rd0 = (insn >> 16) & 0xf;
2143 rd1 = (insn >> 0) & 0xf;
2144 gen_op_iwmmxt_movq_M0_wRn(rd0);
2145 tmp = tcg_const_i32((insn >> 20) & 3);
2146 iwmmxt_load_reg(cpu_V1, rd1);
2147 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2148 tcg_temp_free(tmp);
2149 gen_op_iwmmxt_movq_wRn_M0(wrd);
2150 gen_op_iwmmxt_set_mup();
2151 break;
2152 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2153 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2154 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2155 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2156 wrd = (insn >> 12) & 0xf;
2157 rd0 = (insn >> 16) & 0xf;
2158 rd1 = (insn >> 0) & 0xf;
2159 gen_op_iwmmxt_movq_M0_wRn(rd0);
2160 switch ((insn >> 20) & 0xf) {
2161 case 0x0:
2162 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2163 break;
2164 case 0x1:
2165 gen_op_iwmmxt_subub_M0_wRn(rd1);
2166 break;
2167 case 0x3:
2168 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2169 break;
2170 case 0x4:
2171 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2172 break;
2173 case 0x5:
2174 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2175 break;
2176 case 0x7:
2177 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2178 break;
2179 case 0x8:
2180 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2181 break;
2182 case 0x9:
2183 gen_op_iwmmxt_subul_M0_wRn(rd1);
2184 break;
2185 case 0xb:
2186 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2187 break;
2188 default:
2189 return 1;
2191 gen_op_iwmmxt_movq_wRn_M0(wrd);
2192 gen_op_iwmmxt_set_mup();
2193 gen_op_iwmmxt_set_cup();
2194 break;
2195 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2196 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2197 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2198 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2199 wrd = (insn >> 12) & 0xf;
2200 rd0 = (insn >> 16) & 0xf;
2201 gen_op_iwmmxt_movq_M0_wRn(rd0);
2202 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2203 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2204 tcg_temp_free(tmp);
2205 gen_op_iwmmxt_movq_wRn_M0(wrd);
2206 gen_op_iwmmxt_set_mup();
2207 gen_op_iwmmxt_set_cup();
2208 break;
2209 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2210 case 0x418: case 0x518: case 0x618: case 0x718:
2211 case 0x818: case 0x918: case 0xa18: case 0xb18:
2212 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2213 wrd = (insn >> 12) & 0xf;
2214 rd0 = (insn >> 16) & 0xf;
2215 rd1 = (insn >> 0) & 0xf;
2216 gen_op_iwmmxt_movq_M0_wRn(rd0);
2217 switch ((insn >> 20) & 0xf) {
2218 case 0x0:
2219 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2220 break;
2221 case 0x1:
2222 gen_op_iwmmxt_addub_M0_wRn(rd1);
2223 break;
2224 case 0x3:
2225 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2226 break;
2227 case 0x4:
2228 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2229 break;
2230 case 0x5:
2231 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2232 break;
2233 case 0x7:
2234 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2235 break;
2236 case 0x8:
2237 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2238 break;
2239 case 0x9:
2240 gen_op_iwmmxt_addul_M0_wRn(rd1);
2241 break;
2242 case 0xb:
2243 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2244 break;
2245 default:
2246 return 1;
2248 gen_op_iwmmxt_movq_wRn_M0(wrd);
2249 gen_op_iwmmxt_set_mup();
2250 gen_op_iwmmxt_set_cup();
2251 break;
2252 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2253 case 0x408: case 0x508: case 0x608: case 0x708:
2254 case 0x808: case 0x908: case 0xa08: case 0xb08:
2255 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2256 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2257 return 1;
2258 wrd = (insn >> 12) & 0xf;
2259 rd0 = (insn >> 16) & 0xf;
2260 rd1 = (insn >> 0) & 0xf;
2261 gen_op_iwmmxt_movq_M0_wRn(rd0);
2262 switch ((insn >> 22) & 3) {
2263 case 1:
2264 if (insn & (1 << 21))
2265 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2266 else
2267 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2268 break;
2269 case 2:
2270 if (insn & (1 << 21))
2271 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2272 else
2273 gen_op_iwmmxt_packul_M0_wRn(rd1);
2274 break;
2275 case 3:
2276 if (insn & (1 << 21))
2277 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2278 else
2279 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2280 break;
2282 gen_op_iwmmxt_movq_wRn_M0(wrd);
2283 gen_op_iwmmxt_set_mup();
2284 gen_op_iwmmxt_set_cup();
2285 break;
2286 case 0x201: case 0x203: case 0x205: case 0x207:
2287 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2288 case 0x211: case 0x213: case 0x215: case 0x217:
2289 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2290 wrd = (insn >> 5) & 0xf;
2291 rd0 = (insn >> 12) & 0xf;
2292 rd1 = (insn >> 0) & 0xf;
2293 if (rd0 == 0xf || rd1 == 0xf)
2294 return 1;
2295 gen_op_iwmmxt_movq_M0_wRn(wrd);
2296 tmp = load_reg(s, rd0);
2297 tmp2 = load_reg(s, rd1);
2298 switch ((insn >> 16) & 0xf) {
2299 case 0x0: /* TMIA */
2300 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2301 break;
2302 case 0x8: /* TMIAPH */
2303 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2304 break;
2305 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2306 if (insn & (1 << 16))
2307 tcg_gen_shri_i32(tmp, tmp, 16);
2308 if (insn & (1 << 17))
2309 tcg_gen_shri_i32(tmp2, tmp2, 16);
2310 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2311 break;
2312 default:
2313 dead_tmp(tmp2);
2314 dead_tmp(tmp);
2315 return 1;
2317 dead_tmp(tmp2);
2318 dead_tmp(tmp);
2319 gen_op_iwmmxt_movq_wRn_M0(wrd);
2320 gen_op_iwmmxt_set_mup();
2321 break;
2322 default:
2323 return 1;
2326 return 0;
2329 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2330 (ie. an undefined instruction). */
2331 static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2333 int acc, rd0, rd1, rdhi, rdlo;
2334 TCGv tmp, tmp2;
2336 if ((insn & 0x0ff00f10) == 0x0e200010) {
2337 /* Multiply with Internal Accumulate Format */
2338 rd0 = (insn >> 12) & 0xf;
2339 rd1 = insn & 0xf;
2340 acc = (insn >> 5) & 7;
2342 if (acc != 0)
2343 return 1;
2345 tmp = load_reg(s, rd0);
2346 tmp2 = load_reg(s, rd1);
2347 switch ((insn >> 16) & 0xf) {
2348 case 0x0: /* MIA */
2349 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2350 break;
2351 case 0x8: /* MIAPH */
2352 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2353 break;
2354 case 0xc: /* MIABB */
2355 case 0xd: /* MIABT */
2356 case 0xe: /* MIATB */
2357 case 0xf: /* MIATT */
2358 if (insn & (1 << 16))
2359 tcg_gen_shri_i32(tmp, tmp, 16);
2360 if (insn & (1 << 17))
2361 tcg_gen_shri_i32(tmp2, tmp2, 16);
2362 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2363 break;
2364 default:
2365 return 1;
2367 dead_tmp(tmp2);
2368 dead_tmp(tmp);
2370 gen_op_iwmmxt_movq_wRn_M0(acc);
2371 return 0;
2374 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2375 /* Internal Accumulator Access Format */
2376 rdhi = (insn >> 16) & 0xf;
2377 rdlo = (insn >> 12) & 0xf;
2378 acc = insn & 7;
2380 if (acc != 0)
2381 return 1;
2383 if (insn & ARM_CP_RW_BIT) { /* MRA */
2384 iwmmxt_load_reg(cpu_V0, acc);
2385 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
2386 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
2387 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
2388 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2389 } else { /* MAR */
2390 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2391 iwmmxt_store_reg(cpu_V0, acc);
2393 return 0;
2396 return 1;
2399 /* Disassemble system coprocessor instruction. Return nonzero if
2400 instruction is not defined. */
2401 static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2403 TCGv tmp, tmp2;
2404 uint32_t rd = (insn >> 12) & 0xf;
2405 uint32_t cp = (insn >> 8) & 0xf;
2406 if (IS_USER(s)) {
2407 return 1;
2410 if (insn & ARM_CP_RW_BIT) {
2411 if (!env->cp[cp].cp_read)
2412 return 1;
2413 gen_set_pc_im(s->pc);
2414 tmp = new_tmp();
2415 tmp2 = tcg_const_i32(insn);
2416 gen_helper_get_cp(tmp, cpu_env, tmp2);
2417 tcg_temp_free(tmp2);
2418 store_reg(s, rd, tmp);
2419 } else {
2420 if (!env->cp[cp].cp_write)
2421 return 1;
2422 gen_set_pc_im(s->pc);
2423 tmp = load_reg(s, rd);
2424 tmp2 = tcg_const_i32(insn);
2425 gen_helper_set_cp(cpu_env, tmp2, tmp);
2426 tcg_temp_free(tmp2);
2427 dead_tmp(tmp);
2429 return 0;
2432 static int cp15_user_ok(uint32_t insn)
2434 int cpn = (insn >> 16) & 0xf;
2435 int cpm = insn & 0xf;
2436 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2438 if (cpn == 13 && cpm == 0) {
2439 /* TLS register. */
2440 if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2441 return 1;
2443 if (cpn == 7) {
2444 /* ISB, DSB, DMB. */
2445 if ((cpm == 5 && op == 4)
2446 || (cpm == 10 && (op == 4 || op == 5)))
2447 return 1;
2449 return 0;
2452 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2453 instruction is not defined. */
2454 static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2456 uint32_t rd;
2457 TCGv tmp, tmp2;
2459 /* M profile cores use memory mapped registers instead of cp15. */
2460 if (arm_feature(env, ARM_FEATURE_M))
2461 return 1;
2463 if ((insn & (1 << 25)) == 0) {
2464 if (insn & (1 << 20)) {
2465 /* mrrc */
2466 return 1;
2468 /* mcrr. Used for block cache operations, so implement as no-op. */
2469 return 0;
2471 if ((insn & (1 << 4)) == 0) {
2472 /* cdp */
2473 return 1;
2475 if (IS_USER(s) && !cp15_user_ok(insn)) {
2476 return 1;
2478 if ((insn & 0x0fff0fff) == 0x0e070f90
2479 || (insn & 0x0fff0fff) == 0x0e070f58) {
2480 /* Wait for interrupt. */
2481 gen_set_pc_im(s->pc);
2482 s->is_jmp = DISAS_WFI;
2483 return 0;
2485 rd = (insn >> 12) & 0xf;
2486 tmp2 = tcg_const_i32(insn);
2487 if (insn & ARM_CP_RW_BIT) {
2488 tmp = new_tmp();
2489 gen_helper_get_cp15(tmp, cpu_env, tmp2);
2490 /* If the destination register is r15 then sets condition codes. */
2491 if (rd != 15)
2492 store_reg(s, rd, tmp);
2493 else
2494 dead_tmp(tmp);
2495 } else {
2496 tmp = load_reg(s, rd);
2497 gen_helper_set_cp15(cpu_env, tmp2, tmp);
2498 dead_tmp(tmp);
2499 /* Normally we would always end the TB here, but Linux
2500 * arch/arm/mach-pxa/sleep.S expects two instructions following
2501 * an MMU enable to execute from cache. Imitate this behaviour. */
2502 if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2503 (insn & 0x0fff0fff) != 0x0e010f10)
2504 gen_lookup_tb(s);
2506 tcg_temp_free_i32(tmp2);
2507 return 0;
2510 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2511 #define VFP_SREG(insn, bigbit, smallbit) \
2512 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2513 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2514 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2515 reg = (((insn) >> (bigbit)) & 0x0f) \
2516 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2517 } else { \
2518 if (insn & (1 << (smallbit))) \
2519 return 1; \
2520 reg = ((insn) >> (bigbit)) & 0x0f; \
2521 }} while (0)
2523 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2524 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2525 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2526 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2527 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2528 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2530 /* Move between integer and VFP cores. */
2531 static TCGv gen_vfp_mrs(void)
2533 TCGv tmp = new_tmp();
2534 tcg_gen_mov_i32(tmp, cpu_F0s);
2535 return tmp;
2538 static void gen_vfp_msr(TCGv tmp)
2540 tcg_gen_mov_i32(cpu_F0s, tmp);
2541 dead_tmp(tmp);
2544 static inline int
2545 vfp_enabled(CPUState * env)
2547 return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
2550 static void gen_neon_dup_u8(TCGv var, int shift)
2552 TCGv tmp = new_tmp();
2553 if (shift)
2554 tcg_gen_shri_i32(var, var, shift);
2555 tcg_gen_ext8u_i32(var, var);
2556 tcg_gen_shli_i32(tmp, var, 8);
2557 tcg_gen_or_i32(var, var, tmp);
2558 tcg_gen_shli_i32(tmp, var, 16);
2559 tcg_gen_or_i32(var, var, tmp);
2560 dead_tmp(tmp);
2563 static void gen_neon_dup_low16(TCGv var)
2565 TCGv tmp = new_tmp();
2566 tcg_gen_ext16u_i32(var, var);
2567 tcg_gen_shli_i32(tmp, var, 16);
2568 tcg_gen_or_i32(var, var, tmp);
2569 dead_tmp(tmp);
2572 static void gen_neon_dup_high16(TCGv var)
2574 TCGv tmp = new_tmp();
2575 tcg_gen_andi_i32(var, var, 0xffff0000);
2576 tcg_gen_shri_i32(tmp, var, 16);
2577 tcg_gen_or_i32(var, var, tmp);
2578 dead_tmp(tmp);
2581 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2582 (ie. an undefined instruction). */
2583 static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2585 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2586 int dp, veclen;
2587 TCGv addr;
2588 TCGv tmp;
2589 TCGv tmp2;
2591 if (!arm_feature(env, ARM_FEATURE_VFP))
2592 return 1;
2594 if (!vfp_enabled(env)) {
2595 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2596 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2597 return 1;
2598 rn = (insn >> 16) & 0xf;
2599 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2600 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2601 return 1;
2603 dp = ((insn & 0xf00) == 0xb00);
2604 switch ((insn >> 24) & 0xf) {
2605 case 0xe:
2606 if (insn & (1 << 4)) {
2607 /* single register transfer */
2608 rd = (insn >> 12) & 0xf;
2609 if (dp) {
2610 int size;
2611 int pass;
2613 VFP_DREG_N(rn, insn);
2614 if (insn & 0xf)
2615 return 1;
2616 if (insn & 0x00c00060
2617 && !arm_feature(env, ARM_FEATURE_NEON))
2618 return 1;
2620 pass = (insn >> 21) & 1;
2621 if (insn & (1 << 22)) {
2622 size = 0;
2623 offset = ((insn >> 5) & 3) * 8;
2624 } else if (insn & (1 << 5)) {
2625 size = 1;
2626 offset = (insn & (1 << 6)) ? 16 : 0;
2627 } else {
2628 size = 2;
2629 offset = 0;
2631 if (insn & ARM_CP_RW_BIT) {
2632 /* vfp->arm */
2633 tmp = neon_load_reg(rn, pass);
2634 switch (size) {
2635 case 0:
2636 if (offset)
2637 tcg_gen_shri_i32(tmp, tmp, offset);
2638 if (insn & (1 << 23))
2639 gen_uxtb(tmp);
2640 else
2641 gen_sxtb(tmp);
2642 break;
2643 case 1:
2644 if (insn & (1 << 23)) {
2645 if (offset) {
2646 tcg_gen_shri_i32(tmp, tmp, 16);
2647 } else {
2648 gen_uxth(tmp);
2650 } else {
2651 if (offset) {
2652 tcg_gen_sari_i32(tmp, tmp, 16);
2653 } else {
2654 gen_sxth(tmp);
2657 break;
2658 case 2:
2659 break;
2661 store_reg(s, rd, tmp);
2662 } else {
2663 /* arm->vfp */
2664 tmp = load_reg(s, rd);
2665 if (insn & (1 << 23)) {
2666 /* VDUP */
2667 if (size == 0) {
2668 gen_neon_dup_u8(tmp, 0);
2669 } else if (size == 1) {
2670 gen_neon_dup_low16(tmp);
2672 for (n = 0; n <= pass * 2; n++) {
2673 tmp2 = new_tmp();
2674 tcg_gen_mov_i32(tmp2, tmp);
2675 neon_store_reg(rn, n, tmp2);
2677 neon_store_reg(rn, n, tmp);
2678 } else {
2679 /* VMOV */
2680 switch (size) {
2681 case 0:
2682 tmp2 = neon_load_reg(rn, pass);
2683 gen_bfi(tmp, tmp2, tmp, offset, 0xff);
2684 dead_tmp(tmp2);
2685 break;
2686 case 1:
2687 tmp2 = neon_load_reg(rn, pass);
2688 gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
2689 dead_tmp(tmp2);
2690 break;
2691 case 2:
2692 break;
2694 neon_store_reg(rn, pass, tmp);
2697 } else { /* !dp */
2698 if ((insn & 0x6f) != 0x00)
2699 return 1;
2700 rn = VFP_SREG_N(insn);
2701 if (insn & ARM_CP_RW_BIT) {
2702 /* vfp->arm */
2703 if (insn & (1 << 21)) {
2704 /* system register */
2705 rn >>= 1;
2707 switch (rn) {
2708 case ARM_VFP_FPSID:
2709 /* VFP2 allows access to FSID from userspace.
2710 VFP3 restricts all id registers to privileged
2711 accesses. */
2712 if (IS_USER(s)
2713 && arm_feature(env, ARM_FEATURE_VFP3))
2714 return 1;
2715 tmp = load_cpu_field(vfp.xregs[rn]);
2716 break;
2717 case ARM_VFP_FPEXC:
2718 if (IS_USER(s))
2719 return 1;
2720 tmp = load_cpu_field(vfp.xregs[rn]);
2721 break;
2722 case ARM_VFP_FPINST:
2723 case ARM_VFP_FPINST2:
2724 /* Not present in VFP3. */
2725 if (IS_USER(s)
2726 || arm_feature(env, ARM_FEATURE_VFP3))
2727 return 1;
2728 tmp = load_cpu_field(vfp.xregs[rn]);
2729 break;
2730 case ARM_VFP_FPSCR:
2731 if (rd == 15) {
2732 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2733 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2734 } else {
2735 tmp = new_tmp();
2736 gen_helper_vfp_get_fpscr(tmp, cpu_env);
2738 break;
2739 case ARM_VFP_MVFR0:
2740 case ARM_VFP_MVFR1:
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 default:
2747 return 1;
2749 } else {
2750 gen_mov_F0_vreg(0, rn);
2751 tmp = gen_vfp_mrs();
2753 if (rd == 15) {
2754 /* Set the 4 flag bits in the CPSR. */
2755 gen_set_nzcv(tmp);
2756 dead_tmp(tmp);
2757 } else {
2758 store_reg(s, rd, tmp);
2760 } else {
2761 /* arm->vfp */
2762 tmp = load_reg(s, rd);
2763 if (insn & (1 << 21)) {
2764 rn >>= 1;
2765 /* system register */
2766 switch (rn) {
2767 case ARM_VFP_FPSID:
2768 case ARM_VFP_MVFR0:
2769 case ARM_VFP_MVFR1:
2770 /* Writes are ignored. */
2771 break;
2772 case ARM_VFP_FPSCR:
2773 gen_helper_vfp_set_fpscr(cpu_env, tmp);
2774 dead_tmp(tmp);
2775 gen_lookup_tb(s);
2776 break;
2777 case ARM_VFP_FPEXC:
2778 if (IS_USER(s))
2779 return 1;
2780 store_cpu_field(tmp, vfp.xregs[rn]);
2781 gen_lookup_tb(s);
2782 break;
2783 case ARM_VFP_FPINST:
2784 case ARM_VFP_FPINST2:
2785 store_cpu_field(tmp, vfp.xregs[rn]);
2786 break;
2787 default:
2788 return 1;
2790 } else {
2791 gen_vfp_msr(tmp);
2792 gen_mov_vreg_F0(0, rn);
2796 } else {
2797 /* data processing */
2798 /* The opcode is in bits 23, 21, 20 and 6. */
2799 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2800 if (dp) {
2801 if (op == 15) {
2802 /* rn is opcode */
2803 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2804 } else {
2805 /* rn is register number */
2806 VFP_DREG_N(rn, insn);
2809 if (op == 15 && (rn == 15 || rn > 17)) {
2810 /* Integer or single precision destination. */
2811 rd = VFP_SREG_D(insn);
2812 } else {
2813 VFP_DREG_D(rd, insn);
2816 if (op == 15 && (rn == 16 || rn == 17)) {
2817 /* Integer source. */
2818 rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2819 } else {
2820 VFP_DREG_M(rm, insn);
2822 } else {
2823 rn = VFP_SREG_N(insn);
2824 if (op == 15 && rn == 15) {
2825 /* Double precision destination. */
2826 VFP_DREG_D(rd, insn);
2827 } else {
2828 rd = VFP_SREG_D(insn);
2830 rm = VFP_SREG_M(insn);
2833 veclen = env->vfp.vec_len;
2834 if (op == 15 && rn > 3)
2835 veclen = 0;
2837 /* Shut up compiler warnings. */
2838 delta_m = 0;
2839 delta_d = 0;
2840 bank_mask = 0;
2842 if (veclen > 0) {
2843 if (dp)
2844 bank_mask = 0xc;
2845 else
2846 bank_mask = 0x18;
2848 /* Figure out what type of vector operation this is. */
2849 if ((rd & bank_mask) == 0) {
2850 /* scalar */
2851 veclen = 0;
2852 } else {
2853 if (dp)
2854 delta_d = (env->vfp.vec_stride >> 1) + 1;
2855 else
2856 delta_d = env->vfp.vec_stride + 1;
2858 if ((rm & bank_mask) == 0) {
2859 /* mixed scalar/vector */
2860 delta_m = 0;
2861 } else {
2862 /* vector */
2863 delta_m = delta_d;
2868 /* Load the initial operands. */
2869 if (op == 15) {
2870 switch (rn) {
2871 case 16:
2872 case 17:
2873 /* Integer source */
2874 gen_mov_F0_vreg(0, rm);
2875 break;
2876 case 8:
2877 case 9:
2878 /* Compare */
2879 gen_mov_F0_vreg(dp, rd);
2880 gen_mov_F1_vreg(dp, rm);
2881 break;
2882 case 10:
2883 case 11:
2884 /* Compare with zero */
2885 gen_mov_F0_vreg(dp, rd);
2886 gen_vfp_F1_ld0(dp);
2887 break;
2888 case 20:
2889 case 21:
2890 case 22:
2891 case 23:
2892 case 28:
2893 case 29:
2894 case 30:
2895 case 31:
2896 /* Source and destination the same. */
2897 gen_mov_F0_vreg(dp, rd);
2898 break;
2899 default:
2900 /* One source operand. */
2901 gen_mov_F0_vreg(dp, rm);
2902 break;
2904 } else {
2905 /* Two source operands. */
2906 gen_mov_F0_vreg(dp, rn);
2907 gen_mov_F1_vreg(dp, rm);
2910 for (;;) {
2911 /* Perform the calculation. */
2912 switch (op) {
2913 case 0: /* mac: fd + (fn * fm) */
2914 gen_vfp_mul(dp);
2915 gen_mov_F1_vreg(dp, rd);
2916 gen_vfp_add(dp);
2917 break;
2918 case 1: /* nmac: fd - (fn * fm) */
2919 gen_vfp_mul(dp);
2920 gen_vfp_neg(dp);
2921 gen_mov_F1_vreg(dp, rd);
2922 gen_vfp_add(dp);
2923 break;
2924 case 2: /* msc: -fd + (fn * fm) */
2925 gen_vfp_mul(dp);
2926 gen_mov_F1_vreg(dp, rd);
2927 gen_vfp_sub(dp);
2928 break;
2929 case 3: /* nmsc: -fd - (fn * fm) */
2930 gen_vfp_mul(dp);
2931 gen_vfp_neg(dp);
2932 gen_mov_F1_vreg(dp, rd);
2933 gen_vfp_sub(dp);
2934 break;
2935 case 4: /* mul: fn * fm */
2936 gen_vfp_mul(dp);
2937 break;
2938 case 5: /* nmul: -(fn * fm) */
2939 gen_vfp_mul(dp);
2940 gen_vfp_neg(dp);
2941 break;
2942 case 6: /* add: fn + fm */
2943 gen_vfp_add(dp);
2944 break;
2945 case 7: /* sub: fn - fm */
2946 gen_vfp_sub(dp);
2947 break;
2948 case 8: /* div: fn / fm */
2949 gen_vfp_div(dp);
2950 break;
2951 case 14: /* fconst */
2952 if (!arm_feature(env, ARM_FEATURE_VFP3))
2953 return 1;
2955 n = (insn << 12) & 0x80000000;
2956 i = ((insn >> 12) & 0x70) | (insn & 0xf);
2957 if (dp) {
2958 if (i & 0x40)
2959 i |= 0x3f80;
2960 else
2961 i |= 0x4000;
2962 n |= i << 16;
2963 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
2964 } else {
2965 if (i & 0x40)
2966 i |= 0x780;
2967 else
2968 i |= 0x800;
2969 n |= i << 19;
2970 tcg_gen_movi_i32(cpu_F0s, n);
2972 break;
2973 case 15: /* extension space */
2974 switch (rn) {
2975 case 0: /* cpy */
2976 /* no-op */
2977 break;
2978 case 1: /* abs */
2979 gen_vfp_abs(dp);
2980 break;
2981 case 2: /* neg */
2982 gen_vfp_neg(dp);
2983 break;
2984 case 3: /* sqrt */
2985 gen_vfp_sqrt(dp);
2986 break;
2987 case 8: /* cmp */
2988 gen_vfp_cmp(dp);
2989 break;
2990 case 9: /* cmpe */
2991 gen_vfp_cmpe(dp);
2992 break;
2993 case 10: /* cmpz */
2994 gen_vfp_cmp(dp);
2995 break;
2996 case 11: /* cmpez */
2997 gen_vfp_F1_ld0(dp);
2998 gen_vfp_cmpe(dp);
2999 break;
3000 case 15: /* single<->double conversion */
3001 if (dp)
3002 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3003 else
3004 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3005 break;
3006 case 16: /* fuito */
3007 gen_vfp_uito(dp);
3008 break;
3009 case 17: /* fsito */
3010 gen_vfp_sito(dp);
3011 break;
3012 case 20: /* fshto */
3013 if (!arm_feature(env, ARM_FEATURE_VFP3))
3014 return 1;
3015 gen_vfp_shto(dp, 16 - rm);
3016 break;
3017 case 21: /* fslto */
3018 if (!arm_feature(env, ARM_FEATURE_VFP3))
3019 return 1;
3020 gen_vfp_slto(dp, 32 - rm);
3021 break;
3022 case 22: /* fuhto */
3023 if (!arm_feature(env, ARM_FEATURE_VFP3))
3024 return 1;
3025 gen_vfp_uhto(dp, 16 - rm);
3026 break;
3027 case 23: /* fulto */
3028 if (!arm_feature(env, ARM_FEATURE_VFP3))
3029 return 1;
3030 gen_vfp_ulto(dp, 32 - rm);
3031 break;
3032 case 24: /* ftoui */
3033 gen_vfp_toui(dp);
3034 break;
3035 case 25: /* ftouiz */
3036 gen_vfp_touiz(dp);
3037 break;
3038 case 26: /* ftosi */
3039 gen_vfp_tosi(dp);
3040 break;
3041 case 27: /* ftosiz */
3042 gen_vfp_tosiz(dp);
3043 break;
3044 case 28: /* ftosh */
3045 if (!arm_feature(env, ARM_FEATURE_VFP3))
3046 return 1;
3047 gen_vfp_tosh(dp, 16 - rm);
3048 break;
3049 case 29: /* ftosl */
3050 if (!arm_feature(env, ARM_FEATURE_VFP3))
3051 return 1;
3052 gen_vfp_tosl(dp, 32 - rm);
3053 break;
3054 case 30: /* ftouh */
3055 if (!arm_feature(env, ARM_FEATURE_VFP3))
3056 return 1;
3057 gen_vfp_touh(dp, 16 - rm);
3058 break;
3059 case 31: /* ftoul */
3060 if (!arm_feature(env, ARM_FEATURE_VFP3))
3061 return 1;
3062 gen_vfp_toul(dp, 32 - rm);
3063 break;
3064 default: /* undefined */
3065 printf ("rn:%d\n", rn);
3066 return 1;
3068 break;
3069 default: /* undefined */
3070 printf ("op:%d\n", op);
3071 return 1;
3074 /* Write back the result. */
3075 if (op == 15 && (rn >= 8 && rn <= 11))
3076 ; /* Comparison, do nothing. */
3077 else if (op == 15 && rn > 17)
3078 /* Integer result. */
3079 gen_mov_vreg_F0(0, rd);
3080 else if (op == 15 && rn == 15)
3081 /* conversion */
3082 gen_mov_vreg_F0(!dp, rd);
3083 else
3084 gen_mov_vreg_F0(dp, rd);
3086 /* break out of the loop if we have finished */
3087 if (veclen == 0)
3088 break;
3090 if (op == 15 && delta_m == 0) {
3091 /* single source one-many */
3092 while (veclen--) {
3093 rd = ((rd + delta_d) & (bank_mask - 1))
3094 | (rd & bank_mask);
3095 gen_mov_vreg_F0(dp, rd);
3097 break;
3099 /* Setup the next operands. */
3100 veclen--;
3101 rd = ((rd + delta_d) & (bank_mask - 1))
3102 | (rd & bank_mask);
3104 if (op == 15) {
3105 /* One source operand. */
3106 rm = ((rm + delta_m) & (bank_mask - 1))
3107 | (rm & bank_mask);
3108 gen_mov_F0_vreg(dp, rm);
3109 } else {
3110 /* Two source operands. */
3111 rn = ((rn + delta_d) & (bank_mask - 1))
3112 | (rn & bank_mask);
3113 gen_mov_F0_vreg(dp, rn);
3114 if (delta_m) {
3115 rm = ((rm + delta_m) & (bank_mask - 1))
3116 | (rm & bank_mask);
3117 gen_mov_F1_vreg(dp, rm);
3122 break;
3123 case 0xc:
3124 case 0xd:
3125 if (dp && (insn & 0x03e00000) == 0x00400000) {
3126 /* two-register transfer */
3127 rn = (insn >> 16) & 0xf;
3128 rd = (insn >> 12) & 0xf;
3129 if (dp) {
3130 VFP_DREG_M(rm, insn);
3131 } else {
3132 rm = VFP_SREG_M(insn);
3135 if (insn & ARM_CP_RW_BIT) {
3136 /* vfp->arm */
3137 if (dp) {
3138 gen_mov_F0_vreg(0, rm * 2);
3139 tmp = gen_vfp_mrs();
3140 store_reg(s, rd, tmp);
3141 gen_mov_F0_vreg(0, rm * 2 + 1);
3142 tmp = gen_vfp_mrs();
3143 store_reg(s, rn, tmp);
3144 } else {
3145 gen_mov_F0_vreg(0, rm);
3146 tmp = gen_vfp_mrs();
3147 store_reg(s, rn, tmp);
3148 gen_mov_F0_vreg(0, rm + 1);
3149 tmp = gen_vfp_mrs();
3150 store_reg(s, rd, tmp);
3152 } else {
3153 /* arm->vfp */
3154 if (dp) {
3155 tmp = load_reg(s, rd);
3156 gen_vfp_msr(tmp);
3157 gen_mov_vreg_F0(0, rm * 2);
3158 tmp = load_reg(s, rn);
3159 gen_vfp_msr(tmp);
3160 gen_mov_vreg_F0(0, rm * 2 + 1);
3161 } else {
3162 tmp = load_reg(s, rn);
3163 gen_vfp_msr(tmp);
3164 gen_mov_vreg_F0(0, rm);
3165 tmp = load_reg(s, rd);
3166 gen_vfp_msr(tmp);
3167 gen_mov_vreg_F0(0, rm + 1);
3170 } else {
3171 /* Load/store */
3172 rn = (insn >> 16) & 0xf;
3173 if (dp)
3174 VFP_DREG_D(rd, insn);
3175 else
3176 rd = VFP_SREG_D(insn);
3177 if (s->thumb && rn == 15) {
3178 addr = new_tmp();
3179 tcg_gen_movi_i32(addr, s->pc & ~2);
3180 } else {
3181 addr = load_reg(s, rn);
3183 if ((insn & 0x01200000) == 0x01000000) {
3184 /* Single load/store */
3185 offset = (insn & 0xff) << 2;
3186 if ((insn & (1 << 23)) == 0)
3187 offset = -offset;
3188 tcg_gen_addi_i32(addr, addr, offset);
3189 if (insn & (1 << 20)) {
3190 gen_vfp_ld(s, dp, addr);
3191 gen_mov_vreg_F0(dp, rd);
3192 } else {
3193 gen_mov_F0_vreg(dp, rd);
3194 gen_vfp_st(s, dp, addr);
3196 dead_tmp(addr);
3197 } else {
3198 /* load/store multiple */
3199 if (dp)
3200 n = (insn >> 1) & 0x7f;
3201 else
3202 n = insn & 0xff;
3204 if (insn & (1 << 24)) /* pre-decrement */
3205 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
3207 if (dp)
3208 offset = 8;
3209 else
3210 offset = 4;
3211 for (i = 0; i < n; i++) {
3212 if (insn & ARM_CP_RW_BIT) {
3213 /* load */
3214 gen_vfp_ld(s, dp, addr);
3215 gen_mov_vreg_F0(dp, rd + i);
3216 } else {
3217 /* store */
3218 gen_mov_F0_vreg(dp, rd + i);
3219 gen_vfp_st(s, dp, addr);
3221 tcg_gen_addi_i32(addr, addr, offset);
3223 if (insn & (1 << 21)) {
3224 /* writeback */
3225 if (insn & (1 << 24))
3226 offset = -offset * n;
3227 else if (dp && (insn & 1))
3228 offset = 4;
3229 else
3230 offset = 0;
3232 if (offset != 0)
3233 tcg_gen_addi_i32(addr, addr, offset);
3234 store_reg(s, rn, addr);
3235 } else {
3236 dead_tmp(addr);
3240 break;
3241 default:
3242 /* Should never happen. */
3243 return 1;
3245 return 0;
3248 static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3250 TranslationBlock *tb;
3252 tb = s->tb;
3253 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3254 tcg_gen_goto_tb(n);
3255 gen_set_pc_im(dest);
3256 tcg_gen_exit_tb((long)tb + n);
3257 } else {
3258 gen_set_pc_im(dest);
3259 tcg_gen_exit_tb(0);
3263 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3265 if (unlikely(s->singlestep_enabled)) {
3266 /* An indirect jump so that we still trigger the debug exception. */
3267 if (s->thumb)
3268 dest |= 1;
3269 gen_bx_im(s, dest);
3270 } else {
3271 gen_goto_tb(s, 0, dest);
3272 s->is_jmp = DISAS_TB_JUMP;
3276 static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3278 if (x)
3279 tcg_gen_sari_i32(t0, t0, 16);
3280 else
3281 gen_sxth(t0);
3282 if (y)
3283 tcg_gen_sari_i32(t1, t1, 16);
3284 else
3285 gen_sxth(t1);
3286 tcg_gen_mul_i32(t0, t0, t1);
3289 /* Return the mask of PSR bits set by a MSR instruction. */
3290 static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3291 uint32_t mask;
3293 mask = 0;
3294 if (flags & (1 << 0))
3295 mask |= 0xff;
3296 if (flags & (1 << 1))
3297 mask |= 0xff00;
3298 if (flags & (1 << 2))
3299 mask |= 0xff0000;
3300 if (flags & (1 << 3))
3301 mask |= 0xff000000;
3303 /* Mask out undefined bits. */
3304 mask &= ~CPSR_RESERVED;
3305 if (!arm_feature(env, ARM_FEATURE_V6))
3306 mask &= ~(CPSR_E | CPSR_GE);
3307 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3308 mask &= ~CPSR_IT;
3309 /* Mask out execution state bits. */
3310 if (!spsr)
3311 mask &= ~CPSR_EXEC;
3312 /* Mask out privileged bits. */
3313 if (IS_USER(s))
3314 mask &= CPSR_USER;
3315 return mask;
3318 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3319 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0)
3321 TCGv tmp;
3322 if (spsr) {
3323 /* ??? This is also undefined in system mode. */
3324 if (IS_USER(s))
3325 return 1;
3327 tmp = load_cpu_field(spsr);
3328 tcg_gen_andi_i32(tmp, tmp, ~mask);
3329 tcg_gen_andi_i32(t0, t0, mask);
3330 tcg_gen_or_i32(tmp, tmp, t0);
3331 store_cpu_field(tmp, spsr);
3332 } else {
3333 gen_set_cpsr(t0, mask);
3335 dead_tmp(t0);
3336 gen_lookup_tb(s);
3337 return 0;
3340 /* Returns nonzero if access to the PSR is not permitted. */
3341 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3343 TCGv tmp;
3344 tmp = new_tmp();
3345 tcg_gen_movi_i32(tmp, val);
3346 return gen_set_psr(s, mask, spsr, tmp);
3349 /* Generate an old-style exception return. Marks pc as dead. */
3350 static void gen_exception_return(DisasContext *s, TCGv pc)
3352 TCGv tmp;
3353 store_reg(s, 15, pc);
3354 tmp = load_cpu_field(spsr);
3355 gen_set_cpsr(tmp, 0xffffffff);
3356 dead_tmp(tmp);
3357 s->is_jmp = DISAS_UPDATE;
3360 /* Generate a v6 exception return. Marks both values as dead. */
3361 static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3363 gen_set_cpsr(cpsr, 0xffffffff);
3364 dead_tmp(cpsr);
3365 store_reg(s, 15, pc);
3366 s->is_jmp = DISAS_UPDATE;
3369 static inline void
3370 gen_set_condexec (DisasContext *s)
3372 if (s->condexec_mask) {
3373 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3374 TCGv tmp = new_tmp();
3375 tcg_gen_movi_i32(tmp, val);
3376 store_cpu_field(tmp, condexec_bits);
3380 static void gen_nop_hint(DisasContext *s, int val)
3382 switch (val) {
3383 case 3: /* wfi */
3384 gen_set_pc_im(s->pc);
3385 s->is_jmp = DISAS_WFI;
3386 break;
3387 case 2: /* wfe */
3388 case 4: /* sev */
3389 /* TODO: Implement SEV and WFE. May help SMP performance. */
3390 default: /* nop */
3391 break;
3395 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3397 static inline int gen_neon_add(int size, TCGv t0, TCGv t1)
3399 switch (size) {
3400 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
3401 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
3402 case 2: tcg_gen_add_i32(t0, t0, t1); break;
3403 default: return 1;
3405 return 0;
3408 static inline void gen_neon_rsb(int size, TCGv t0, TCGv t1)
3410 switch (size) {
3411 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
3412 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
3413 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
3414 default: return;
3418 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3419 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3420 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3421 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3422 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3424 /* FIXME: This is wrong. They set the wrong overflow bit. */
3425 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3426 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3427 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3428 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3430 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3431 switch ((size << 1) | u) { \
3432 case 0: \
3433 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3434 break; \
3435 case 1: \
3436 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3437 break; \
3438 case 2: \
3439 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3440 break; \
3441 case 3: \
3442 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3443 break; \
3444 case 4: \
3445 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3446 break; \
3447 case 5: \
3448 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3449 break; \
3450 default: return 1; \
3451 }} while (0)
3453 #define GEN_NEON_INTEGER_OP(name) do { \
3454 switch ((size << 1) | u) { \
3455 case 0: \
3456 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3457 break; \
3458 case 1: \
3459 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3460 break; \
3461 case 2: \
3462 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3463 break; \
3464 case 3: \
3465 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3466 break; \
3467 case 4: \
3468 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3469 break; \
3470 case 5: \
3471 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3472 break; \
3473 default: return 1; \
3474 }} while (0)
3476 static TCGv neon_load_scratch(int scratch)
3478 TCGv tmp = new_tmp();
3479 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3480 return tmp;
3483 static void neon_store_scratch(int scratch, TCGv var)
3485 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3486 dead_tmp(var);
3489 static inline TCGv neon_get_scalar(int size, int reg)
3491 TCGv tmp;
3492 if (size == 1) {
3493 tmp = neon_load_reg(reg >> 1, reg & 1);
3494 } else {
3495 tmp = neon_load_reg(reg >> 2, (reg >> 1) & 1);
3496 if (reg & 1) {
3497 gen_neon_dup_low16(tmp);
3498 } else {
3499 gen_neon_dup_high16(tmp);
3502 return tmp;
3505 static void gen_neon_unzip_u8(TCGv t0, TCGv t1)
3507 TCGv rd, rm, tmp;
3509 rd = new_tmp();
3510 rm = new_tmp();
3511 tmp = new_tmp();
3513 tcg_gen_andi_i32(rd, t0, 0xff);
3514 tcg_gen_shri_i32(tmp, t0, 8);
3515 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3516 tcg_gen_or_i32(rd, rd, tmp);
3517 tcg_gen_shli_i32(tmp, t1, 16);
3518 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3519 tcg_gen_or_i32(rd, rd, tmp);
3520 tcg_gen_shli_i32(tmp, t1, 8);
3521 tcg_gen_andi_i32(tmp, tmp, 0xff000000);
3522 tcg_gen_or_i32(rd, rd, tmp);
3524 tcg_gen_shri_i32(rm, t0, 8);
3525 tcg_gen_andi_i32(rm, rm, 0xff);
3526 tcg_gen_shri_i32(tmp, t0, 16);
3527 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3528 tcg_gen_or_i32(rm, rm, tmp);
3529 tcg_gen_shli_i32(tmp, t1, 8);
3530 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3531 tcg_gen_or_i32(rm, rm, tmp);
3532 tcg_gen_andi_i32(tmp, t1, 0xff000000);
3533 tcg_gen_or_i32(t1, rm, tmp);
3534 tcg_gen_mov_i32(t0, rd);
3536 dead_tmp(tmp);
3537 dead_tmp(rm);
3538 dead_tmp(rd);
3541 static void gen_neon_zip_u8(TCGv t0, TCGv t1)
3543 TCGv rd, rm, tmp;
3545 rd = new_tmp();
3546 rm = new_tmp();
3547 tmp = new_tmp();
3549 tcg_gen_andi_i32(rd, t0, 0xff);
3550 tcg_gen_shli_i32(tmp, t1, 8);
3551 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3552 tcg_gen_or_i32(rd, rd, tmp);
3553 tcg_gen_shli_i32(tmp, t0, 16);
3554 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3555 tcg_gen_or_i32(rd, rd, tmp);
3556 tcg_gen_shli_i32(tmp, t1, 24);
3557 tcg_gen_andi_i32(tmp, tmp, 0xff000000);
3558 tcg_gen_or_i32(rd, rd, tmp);
3560 tcg_gen_andi_i32(rm, t1, 0xff000000);
3561 tcg_gen_shri_i32(tmp, t0, 8);
3562 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3563 tcg_gen_or_i32(rm, rm, tmp);
3564 tcg_gen_shri_i32(tmp, t1, 8);
3565 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3566 tcg_gen_or_i32(rm, rm, tmp);
3567 tcg_gen_shri_i32(tmp, t0, 16);
3568 tcg_gen_andi_i32(tmp, tmp, 0xff);
3569 tcg_gen_or_i32(t1, rm, tmp);
3570 tcg_gen_mov_i32(t0, rd);
3572 dead_tmp(tmp);
3573 dead_tmp(rm);
3574 dead_tmp(rd);
3577 static void gen_neon_zip_u16(TCGv t0, TCGv t1)
3579 TCGv tmp, tmp2;
3581 tmp = new_tmp();
3582 tmp2 = new_tmp();
3584 tcg_gen_andi_i32(tmp, t0, 0xffff);
3585 tcg_gen_shli_i32(tmp2, t1, 16);
3586 tcg_gen_or_i32(tmp, tmp, tmp2);
3587 tcg_gen_andi_i32(t1, t1, 0xffff0000);
3588 tcg_gen_shri_i32(tmp2, t0, 16);
3589 tcg_gen_or_i32(t1, t1, tmp2);
3590 tcg_gen_mov_i32(t0, tmp);
3592 dead_tmp(tmp2);
3593 dead_tmp(tmp);
3596 static void gen_neon_unzip(int reg, int q, int tmp, int size)
3598 int n;
3599 TCGv t0, t1;
3601 for (n = 0; n < q + 1; n += 2) {
3602 t0 = neon_load_reg(reg, n);
3603 t1 = neon_load_reg(reg, n + 1);
3604 switch (size) {
3605 case 0: gen_neon_unzip_u8(t0, t1); break;
3606 case 1: gen_neon_zip_u16(t0, t1); break; /* zip and unzip are the same. */
3607 case 2: /* no-op */; break;
3608 default: abort();
3610 neon_store_scratch(tmp + n, t0);
3611 neon_store_scratch(tmp + n + 1, t1);
3615 static void gen_neon_trn_u8(TCGv t0, TCGv t1)
3617 TCGv rd, tmp;
3619 rd = new_tmp();
3620 tmp = new_tmp();
3622 tcg_gen_shli_i32(rd, t0, 8);
3623 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3624 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3625 tcg_gen_or_i32(rd, rd, tmp);
3627 tcg_gen_shri_i32(t1, t1, 8);
3628 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3629 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3630 tcg_gen_or_i32(t1, t1, tmp);
3631 tcg_gen_mov_i32(t0, rd);
3633 dead_tmp(tmp);
3634 dead_tmp(rd);
3637 static void gen_neon_trn_u16(TCGv t0, TCGv t1)
3639 TCGv rd, tmp;
3641 rd = new_tmp();
3642 tmp = new_tmp();
3644 tcg_gen_shli_i32(rd, t0, 16);
3645 tcg_gen_andi_i32(tmp, t1, 0xffff);
3646 tcg_gen_or_i32(rd, rd, tmp);
3647 tcg_gen_shri_i32(t1, t1, 16);
3648 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3649 tcg_gen_or_i32(t1, t1, tmp);
3650 tcg_gen_mov_i32(t0, rd);
3652 dead_tmp(tmp);
3653 dead_tmp(rd);
3657 static struct {
3658 int nregs;
3659 int interleave;
3660 int spacing;
3661 } neon_ls_element_type[11] = {
3662 {4, 4, 1},
3663 {4, 4, 2},
3664 {4, 1, 1},
3665 {4, 2, 1},
3666 {3, 3, 1},
3667 {3, 3, 2},
3668 {3, 1, 1},
3669 {1, 1, 1},
3670 {2, 2, 1},
3671 {2, 2, 2},
3672 {2, 1, 1}
3675 /* Translate a NEON load/store element instruction. Return nonzero if the
3676 instruction is invalid. */
3677 static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3679 int rd, rn, rm;
3680 int op;
3681 int nregs;
3682 int interleave;
3683 int stride;
3684 int size;
3685 int reg;
3686 int pass;
3687 int load;
3688 int shift;
3689 int n;
3690 TCGv addr;
3691 TCGv tmp;
3692 TCGv tmp2;
3694 if (!vfp_enabled(env))
3695 return 1;
3696 VFP_DREG_D(rd, insn);
3697 rn = (insn >> 16) & 0xf;
3698 rm = insn & 0xf;
3699 load = (insn & (1 << 21)) != 0;
3700 addr = new_tmp();
3701 if ((insn & (1 << 23)) == 0) {
3702 /* Load store all elements. */
3703 op = (insn >> 8) & 0xf;
3704 size = (insn >> 6) & 3;
3705 if (op > 10 || size == 3)
3706 return 1;
3707 nregs = neon_ls_element_type[op].nregs;
3708 interleave = neon_ls_element_type[op].interleave;
3709 load_reg_var(s, addr, rn);
3710 stride = (1 << size) * interleave;
3711 for (reg = 0; reg < nregs; reg++) {
3712 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3713 load_reg_var(s, addr, rn);
3714 tcg_gen_addi_i32(addr, addr, (1 << size) * reg);
3715 } else if (interleave == 2 && nregs == 4 && reg == 2) {
3716 load_reg_var(s, addr, rn);
3717 tcg_gen_addi_i32(addr, addr, 1 << size);
3719 for (pass = 0; pass < 2; pass++) {
3720 if (size == 2) {
3721 if (load) {
3722 tmp = gen_ld32(addr, IS_USER(s));
3723 neon_store_reg(rd, pass, tmp);
3724 } else {
3725 tmp = neon_load_reg(rd, pass);
3726 gen_st32(tmp, addr, IS_USER(s));
3728 tcg_gen_addi_i32(addr, addr, stride);
3729 } else if (size == 1) {
3730 if (load) {
3731 tmp = gen_ld16u(addr, IS_USER(s));
3732 tcg_gen_addi_i32(addr, addr, stride);
3733 tmp2 = gen_ld16u(addr, IS_USER(s));
3734 tcg_gen_addi_i32(addr, addr, stride);
3735 gen_bfi(tmp, tmp, tmp2, 16, 0xffff);
3736 dead_tmp(tmp2);
3737 neon_store_reg(rd, pass, tmp);
3738 } else {
3739 tmp = neon_load_reg(rd, pass);
3740 tmp2 = new_tmp();
3741 tcg_gen_shri_i32(tmp2, tmp, 16);
3742 gen_st16(tmp, addr, IS_USER(s));
3743 tcg_gen_addi_i32(addr, addr, stride);
3744 gen_st16(tmp2, addr, IS_USER(s));
3745 tcg_gen_addi_i32(addr, addr, stride);
3747 } else /* size == 0 */ {
3748 if (load) {
3749 TCGV_UNUSED(tmp2);
3750 for (n = 0; n < 4; n++) {
3751 tmp = gen_ld8u(addr, IS_USER(s));
3752 tcg_gen_addi_i32(addr, addr, stride);
3753 if (n == 0) {
3754 tmp2 = tmp;
3755 } else {
3756 gen_bfi(tmp2, tmp2, tmp, n * 8, 0xff);
3757 dead_tmp(tmp);
3760 neon_store_reg(rd, pass, tmp2);
3761 } else {
3762 tmp2 = neon_load_reg(rd, pass);
3763 for (n = 0; n < 4; n++) {
3764 tmp = new_tmp();
3765 if (n == 0) {
3766 tcg_gen_mov_i32(tmp, tmp2);
3767 } else {
3768 tcg_gen_shri_i32(tmp, tmp2, n * 8);
3770 gen_st8(tmp, addr, IS_USER(s));
3771 tcg_gen_addi_i32(addr, addr, stride);
3773 dead_tmp(tmp2);
3777 rd += neon_ls_element_type[op].spacing;
3779 stride = nregs * 8;
3780 } else {
3781 size = (insn >> 10) & 3;
3782 if (size == 3) {
3783 /* Load single element to all lanes. */
3784 if (!load)
3785 return 1;
3786 size = (insn >> 6) & 3;
3787 nregs = ((insn >> 8) & 3) + 1;
3788 stride = (insn & (1 << 5)) ? 2 : 1;
3789 load_reg_var(s, addr, rn);
3790 for (reg = 0; reg < nregs; reg++) {
3791 switch (size) {
3792 case 0:
3793 tmp = gen_ld8u(addr, IS_USER(s));
3794 gen_neon_dup_u8(tmp, 0);
3795 break;
3796 case 1:
3797 tmp = gen_ld16u(addr, IS_USER(s));
3798 gen_neon_dup_low16(tmp);
3799 break;
3800 case 2:
3801 tmp = gen_ld32(addr, IS_USER(s));
3802 break;
3803 case 3:
3804 return 1;
3805 default: /* Avoid compiler warnings. */
3806 abort();
3808 tcg_gen_addi_i32(addr, addr, 1 << size);
3809 tmp2 = new_tmp();
3810 tcg_gen_mov_i32(tmp2, tmp);
3811 neon_store_reg(rd, 0, tmp2);
3812 neon_store_reg(rd, 1, tmp);
3813 rd += stride;
3815 stride = (1 << size) * nregs;
3816 } else {
3817 /* Single element. */
3818 pass = (insn >> 7) & 1;
3819 switch (size) {
3820 case 0:
3821 shift = ((insn >> 5) & 3) * 8;
3822 stride = 1;
3823 break;
3824 case 1:
3825 shift = ((insn >> 6) & 1) * 16;
3826 stride = (insn & (1 << 5)) ? 2 : 1;
3827 break;
3828 case 2:
3829 shift = 0;
3830 stride = (insn & (1 << 6)) ? 2 : 1;
3831 break;
3832 default:
3833 abort();
3835 nregs = ((insn >> 8) & 3) + 1;
3836 load_reg_var(s, addr, rn);
3837 for (reg = 0; reg < nregs; reg++) {
3838 if (load) {
3839 switch (size) {
3840 case 0:
3841 tmp = gen_ld8u(addr, IS_USER(s));
3842 break;
3843 case 1:
3844 tmp = gen_ld16u(addr, IS_USER(s));
3845 break;
3846 case 2:
3847 tmp = gen_ld32(addr, IS_USER(s));
3848 break;
3849 default: /* Avoid compiler warnings. */
3850 abort();
3852 if (size != 2) {
3853 tmp2 = neon_load_reg(rd, pass);
3854 gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
3855 dead_tmp(tmp2);
3857 neon_store_reg(rd, pass, tmp);
3858 } else { /* Store */
3859 tmp = neon_load_reg(rd, pass);
3860 if (shift)
3861 tcg_gen_shri_i32(tmp, tmp, shift);
3862 switch (size) {
3863 case 0:
3864 gen_st8(tmp, addr, IS_USER(s));
3865 break;
3866 case 1:
3867 gen_st16(tmp, addr, IS_USER(s));
3868 break;
3869 case 2:
3870 gen_st32(tmp, addr, IS_USER(s));
3871 break;
3874 rd += stride;
3875 tcg_gen_addi_i32(addr, addr, 1 << size);
3877 stride = nregs * (1 << size);
3880 dead_tmp(addr);
3881 if (rm != 15) {
3882 TCGv base;
3884 base = load_reg(s, rn);
3885 if (rm == 13) {
3886 tcg_gen_addi_i32(base, base, stride);
3887 } else {
3888 TCGv index;
3889 index = load_reg(s, rm);
3890 tcg_gen_add_i32(base, base, index);
3891 dead_tmp(index);
3893 store_reg(s, rn, base);
3895 return 0;
3898 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
3899 static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
3901 tcg_gen_and_i32(t, t, c);
3902 tcg_gen_bic_i32(f, f, c);
3903 tcg_gen_or_i32(dest, t, f);
3906 static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
3908 switch (size) {
3909 case 0: gen_helper_neon_narrow_u8(dest, src); break;
3910 case 1: gen_helper_neon_narrow_u16(dest, src); break;
3911 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
3912 default: abort();
3916 static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
3918 switch (size) {
3919 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
3920 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
3921 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
3922 default: abort();
3926 static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
3928 switch (size) {
3929 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
3930 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
3931 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
3932 default: abort();
3936 static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
3937 int q, int u)
3939 if (q) {
3940 if (u) {
3941 switch (size) {
3942 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3943 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3944 default: abort();
3946 } else {
3947 switch (size) {
3948 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
3949 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
3950 default: abort();
3953 } else {
3954 if (u) {
3955 switch (size) {
3956 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3957 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3958 default: abort();
3960 } else {
3961 switch (size) {
3962 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
3963 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
3964 default: abort();
3970 static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
3972 if (u) {
3973 switch (size) {
3974 case 0: gen_helper_neon_widen_u8(dest, src); break;
3975 case 1: gen_helper_neon_widen_u16(dest, src); break;
3976 case 2: tcg_gen_extu_i32_i64(dest, src); break;
3977 default: abort();
3979 } else {
3980 switch (size) {
3981 case 0: gen_helper_neon_widen_s8(dest, src); break;
3982 case 1: gen_helper_neon_widen_s16(dest, src); break;
3983 case 2: tcg_gen_ext_i32_i64(dest, src); break;
3984 default: abort();
3987 dead_tmp(src);
3990 static inline void gen_neon_addl(int size)
3992 switch (size) {
3993 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
3994 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
3995 case 2: tcg_gen_add_i64(CPU_V001); break;
3996 default: abort();
4000 static inline void gen_neon_subl(int size)
4002 switch (size) {
4003 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4004 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4005 case 2: tcg_gen_sub_i64(CPU_V001); break;
4006 default: abort();
4010 static inline void gen_neon_negl(TCGv_i64 var, int size)
4012 switch (size) {
4013 case 0: gen_helper_neon_negl_u16(var, var); break;
4014 case 1: gen_helper_neon_negl_u32(var, var); break;
4015 case 2: gen_helper_neon_negl_u64(var, var); break;
4016 default: abort();
4020 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4022 switch (size) {
4023 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4024 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4025 default: abort();
4029 static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
4031 TCGv_i64 tmp;
4033 switch ((size << 1) | u) {
4034 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4035 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4036 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4037 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4038 case 4:
4039 tmp = gen_muls_i64_i32(a, b);
4040 tcg_gen_mov_i64(dest, tmp);
4041 break;
4042 case 5:
4043 tmp = gen_mulu_i64_i32(a, b);
4044 tcg_gen_mov_i64(dest, tmp);
4045 break;
4046 default: abort();
4050 /* Translate a NEON data processing instruction. Return nonzero if the
4051 instruction is invalid.
4052 We process data in a mixture of 32-bit and 64-bit chunks.
4053 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4055 static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4057 int op;
4058 int q;
4059 int rd, rn, rm;
4060 int size;
4061 int shift;
4062 int pass;
4063 int count;
4064 int pairwise;
4065 int u;
4066 int n;
4067 uint32_t imm;
4068 TCGv tmp, tmp2, tmp3, tmp4, tmp5;
4069 TCGv_i64 tmp64;
4071 if (!vfp_enabled(env))
4072 return 1;
4073 q = (insn & (1 << 6)) != 0;
4074 u = (insn >> 24) & 1;
4075 VFP_DREG_D(rd, insn);
4076 VFP_DREG_N(rn, insn);
4077 VFP_DREG_M(rm, insn);
4078 size = (insn >> 20) & 3;
4079 if ((insn & (1 << 23)) == 0) {
4080 /* Three register same length. */
4081 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4082 if (size == 3 && (op == 1 || op == 5 || op == 8 || op == 9
4083 || op == 10 || op == 11 || op == 16)) {
4084 /* 64-bit element instructions. */
4085 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4086 neon_load_reg64(cpu_V0, rn + pass);
4087 neon_load_reg64(cpu_V1, rm + pass);
4088 switch (op) {
4089 case 1: /* VQADD */
4090 if (u) {
4091 gen_helper_neon_add_saturate_u64(CPU_V001);
4092 } else {
4093 gen_helper_neon_add_saturate_s64(CPU_V001);
4095 break;
4096 case 5: /* VQSUB */
4097 if (u) {
4098 gen_helper_neon_sub_saturate_u64(CPU_V001);
4099 } else {
4100 gen_helper_neon_sub_saturate_s64(CPU_V001);
4102 break;
4103 case 8: /* VSHL */
4104 if (u) {
4105 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4106 } else {
4107 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4109 break;
4110 case 9: /* VQSHL */
4111 if (u) {
4112 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4113 cpu_V0, cpu_V0);
4114 } else {
4115 gen_helper_neon_qshl_s64(cpu_V1, cpu_env,
4116 cpu_V1, cpu_V0);
4118 break;
4119 case 10: /* VRSHL */
4120 if (u) {
4121 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4122 } else {
4123 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4125 break;
4126 case 11: /* VQRSHL */
4127 if (u) {
4128 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4129 cpu_V1, cpu_V0);
4130 } else {
4131 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4132 cpu_V1, cpu_V0);
4134 break;
4135 case 16:
4136 if (u) {
4137 tcg_gen_sub_i64(CPU_V001);
4138 } else {
4139 tcg_gen_add_i64(CPU_V001);
4141 break;
4142 default:
4143 abort();
4145 neon_store_reg64(cpu_V0, rd + pass);
4147 return 0;
4149 switch (op) {
4150 case 8: /* VSHL */
4151 case 9: /* VQSHL */
4152 case 10: /* VRSHL */
4153 case 11: /* VQRSHL */
4155 int rtmp;
4156 /* Shift instruction operands are reversed. */
4157 rtmp = rn;
4158 rn = rm;
4159 rm = rtmp;
4160 pairwise = 0;
4162 break;
4163 case 20: /* VPMAX */
4164 case 21: /* VPMIN */
4165 case 23: /* VPADD */
4166 pairwise = 1;
4167 break;
4168 case 26: /* VPADD (float) */
4169 pairwise = (u && size < 2);
4170 break;
4171 case 30: /* VPMIN/VPMAX (float) */
4172 pairwise = u;
4173 break;
4174 default:
4175 pairwise = 0;
4176 break;
4179 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4181 if (pairwise) {
4182 /* Pairwise. */
4183 if (q)
4184 n = (pass & 1) * 2;
4185 else
4186 n = 0;
4187 if (pass < q + 1) {
4188 tmp = neon_load_reg(rn, n);
4189 tmp2 = neon_load_reg(rn, n + 1);
4190 } else {
4191 tmp = neon_load_reg(rm, n);
4192 tmp2 = neon_load_reg(rm, n + 1);
4194 } else {
4195 /* Elementwise. */
4196 tmp = neon_load_reg(rn, pass);
4197 tmp2 = neon_load_reg(rm, pass);
4199 switch (op) {
4200 case 0: /* VHADD */
4201 GEN_NEON_INTEGER_OP(hadd);
4202 break;
4203 case 1: /* VQADD */
4204 GEN_NEON_INTEGER_OP_ENV(qadd);
4205 break;
4206 case 2: /* VRHADD */
4207 GEN_NEON_INTEGER_OP(rhadd);
4208 break;
4209 case 3: /* Logic ops. */
4210 switch ((u << 2) | size) {
4211 case 0: /* VAND */
4212 tcg_gen_and_i32(tmp, tmp, tmp2);
4213 break;
4214 case 1: /* BIC */
4215 tcg_gen_bic_i32(tmp, tmp, tmp2);
4216 break;
4217 case 2: /* VORR */
4218 tcg_gen_or_i32(tmp, tmp, tmp2);
4219 break;
4220 case 3: /* VORN */
4221 tcg_gen_not_i32(tmp2, tmp2);
4222 tcg_gen_or_i32(tmp, tmp, tmp2);
4223 break;
4224 case 4: /* VEOR */
4225 tcg_gen_xor_i32(tmp, tmp, tmp2);
4226 break;
4227 case 5: /* VBSL */
4228 tmp3 = neon_load_reg(rd, pass);
4229 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
4230 dead_tmp(tmp3);
4231 break;
4232 case 6: /* VBIT */
4233 tmp3 = neon_load_reg(rd, pass);
4234 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
4235 dead_tmp(tmp3);
4236 break;
4237 case 7: /* VBIF */
4238 tmp3 = neon_load_reg(rd, pass);
4239 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
4240 dead_tmp(tmp3);
4241 break;
4243 break;
4244 case 4: /* VHSUB */
4245 GEN_NEON_INTEGER_OP(hsub);
4246 break;
4247 case 5: /* VQSUB */
4248 GEN_NEON_INTEGER_OP_ENV(qsub);
4249 break;
4250 case 6: /* VCGT */
4251 GEN_NEON_INTEGER_OP(cgt);
4252 break;
4253 case 7: /* VCGE */
4254 GEN_NEON_INTEGER_OP(cge);
4255 break;
4256 case 8: /* VSHL */
4257 GEN_NEON_INTEGER_OP(shl);
4258 break;
4259 case 9: /* VQSHL */
4260 GEN_NEON_INTEGER_OP_ENV(qshl);
4261 break;
4262 case 10: /* VRSHL */
4263 GEN_NEON_INTEGER_OP(rshl);
4264 break;
4265 case 11: /* VQRSHL */
4266 GEN_NEON_INTEGER_OP_ENV(qrshl);
4267 break;
4268 case 12: /* VMAX */
4269 GEN_NEON_INTEGER_OP(max);
4270 break;
4271 case 13: /* VMIN */
4272 GEN_NEON_INTEGER_OP(min);
4273 break;
4274 case 14: /* VABD */
4275 GEN_NEON_INTEGER_OP(abd);
4276 break;
4277 case 15: /* VABA */
4278 GEN_NEON_INTEGER_OP(abd);
4279 dead_tmp(tmp2);
4280 tmp2 = neon_load_reg(rd, pass);
4281 gen_neon_add(size, tmp, tmp2);
4282 break;
4283 case 16:
4284 if (!u) { /* VADD */
4285 if (gen_neon_add(size, tmp, tmp2))
4286 return 1;
4287 } else { /* VSUB */
4288 switch (size) {
4289 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
4290 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
4291 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
4292 default: return 1;
4295 break;
4296 case 17:
4297 if (!u) { /* VTST */
4298 switch (size) {
4299 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
4300 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
4301 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
4302 default: return 1;
4304 } else { /* VCEQ */
4305 switch (size) {
4306 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
4307 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
4308 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
4309 default: return 1;
4312 break;
4313 case 18: /* Multiply. */
4314 switch (size) {
4315 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4316 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4317 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4318 default: return 1;
4320 dead_tmp(tmp2);
4321 tmp2 = neon_load_reg(rd, pass);
4322 if (u) { /* VMLS */
4323 gen_neon_rsb(size, tmp, tmp2);
4324 } else { /* VMLA */
4325 gen_neon_add(size, tmp, tmp2);
4327 break;
4328 case 19: /* VMUL */
4329 if (u) { /* polynomial */
4330 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
4331 } else { /* Integer */
4332 switch (size) {
4333 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4334 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4335 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4336 default: return 1;
4339 break;
4340 case 20: /* VPMAX */
4341 GEN_NEON_INTEGER_OP(pmax);
4342 break;
4343 case 21: /* VPMIN */
4344 GEN_NEON_INTEGER_OP(pmin);
4345 break;
4346 case 22: /* Hultiply high. */
4347 if (!u) { /* VQDMULH */
4348 switch (size) {
4349 case 1: gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4350 case 2: gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4351 default: return 1;
4353 } else { /* VQRDHMUL */
4354 switch (size) {
4355 case 1: gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4356 case 2: gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4357 default: return 1;
4360 break;
4361 case 23: /* VPADD */
4362 if (u)
4363 return 1;
4364 switch (size) {
4365 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
4366 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
4367 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
4368 default: return 1;
4370 break;
4371 case 26: /* Floating point arithnetic. */
4372 switch ((u << 2) | size) {
4373 case 0: /* VADD */
4374 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4375 break;
4376 case 2: /* VSUB */
4377 gen_helper_neon_sub_f32(tmp, tmp, tmp2);
4378 break;
4379 case 4: /* VPADD */
4380 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4381 break;
4382 case 6: /* VABD */
4383 gen_helper_neon_abd_f32(tmp, tmp, tmp2);
4384 break;
4385 default:
4386 return 1;
4388 break;
4389 case 27: /* Float multiply. */
4390 gen_helper_neon_mul_f32(tmp, tmp, tmp2);
4391 if (!u) {
4392 dead_tmp(tmp2);
4393 tmp2 = neon_load_reg(rd, pass);
4394 if (size == 0) {
4395 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4396 } else {
4397 gen_helper_neon_sub_f32(tmp, tmp2, tmp);
4400 break;
4401 case 28: /* Float compare. */
4402 if (!u) {
4403 gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
4404 } else {
4405 if (size == 0)
4406 gen_helper_neon_cge_f32(tmp, tmp, tmp2);
4407 else
4408 gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
4410 break;
4411 case 29: /* Float compare absolute. */
4412 if (!u)
4413 return 1;
4414 if (size == 0)
4415 gen_helper_neon_acge_f32(tmp, tmp, tmp2);
4416 else
4417 gen_helper_neon_acgt_f32(tmp, tmp, tmp2);
4418 break;
4419 case 30: /* Float min/max. */
4420 if (size == 0)
4421 gen_helper_neon_max_f32(tmp, tmp, tmp2);
4422 else
4423 gen_helper_neon_min_f32(tmp, tmp, tmp2);
4424 break;
4425 case 31:
4426 if (size == 0)
4427 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
4428 else
4429 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
4430 break;
4431 default:
4432 abort();
4434 dead_tmp(tmp2);
4436 /* Save the result. For elementwise operations we can put it
4437 straight into the destination register. For pairwise operations
4438 we have to be careful to avoid clobbering the source operands. */
4439 if (pairwise && rd == rm) {
4440 neon_store_scratch(pass, tmp);
4441 } else {
4442 neon_store_reg(rd, pass, tmp);
4445 } /* for pass */
4446 if (pairwise && rd == rm) {
4447 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4448 tmp = neon_load_scratch(pass);
4449 neon_store_reg(rd, pass, tmp);
4452 /* End of 3 register same size operations. */
4453 } else if (insn & (1 << 4)) {
4454 if ((insn & 0x00380080) != 0) {
4455 /* Two registers and shift. */
4456 op = (insn >> 8) & 0xf;
4457 if (insn & (1 << 7)) {
4458 /* 64-bit shift. */
4459 size = 3;
4460 } else {
4461 size = 2;
4462 while ((insn & (1 << (size + 19))) == 0)
4463 size--;
4465 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4466 /* To avoid excessive dumplication of ops we implement shift
4467 by immediate using the variable shift operations. */
4468 if (op < 8) {
4469 /* Shift by immediate:
4470 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4471 /* Right shifts are encoded as N - shift, where N is the
4472 element size in bits. */
4473 if (op <= 4)
4474 shift = shift - (1 << (size + 3));
4475 if (size == 3) {
4476 count = q + 1;
4477 } else {
4478 count = q ? 4: 2;
4480 switch (size) {
4481 case 0:
4482 imm = (uint8_t) shift;
4483 imm |= imm << 8;
4484 imm |= imm << 16;
4485 break;
4486 case 1:
4487 imm = (uint16_t) shift;
4488 imm |= imm << 16;
4489 break;
4490 case 2:
4491 case 3:
4492 imm = shift;
4493 break;
4494 default:
4495 abort();
4498 for (pass = 0; pass < count; pass++) {
4499 if (size == 3) {
4500 neon_load_reg64(cpu_V0, rm + pass);
4501 tcg_gen_movi_i64(cpu_V1, imm);
4502 switch (op) {
4503 case 0: /* VSHR */
4504 case 1: /* VSRA */
4505 if (u)
4506 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4507 else
4508 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
4509 break;
4510 case 2: /* VRSHR */
4511 case 3: /* VRSRA */
4512 if (u)
4513 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
4514 else
4515 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
4516 break;
4517 case 4: /* VSRI */
4518 if (!u)
4519 return 1;
4520 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4521 break;
4522 case 5: /* VSHL, VSLI */
4523 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4524 break;
4525 case 6: /* VQSHL */
4526 if (u)
4527 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4528 else
4529 gen_helper_neon_qshl_s64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4530 break;
4531 case 7: /* VQSHLU */
4532 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4533 break;
4535 if (op == 1 || op == 3) {
4536 /* Accumulate. */
4537 neon_load_reg64(cpu_V0, rd + pass);
4538 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
4539 } else if (op == 4 || (op == 5 && u)) {
4540 /* Insert */
4541 cpu_abort(env, "VS[LR]I.64 not implemented");
4543 neon_store_reg64(cpu_V0, rd + pass);
4544 } else { /* size < 3 */
4545 /* Operands in T0 and T1. */
4546 tmp = neon_load_reg(rm, pass);
4547 tmp2 = new_tmp();
4548 tcg_gen_movi_i32(tmp2, imm);
4549 switch (op) {
4550 case 0: /* VSHR */
4551 case 1: /* VSRA */
4552 GEN_NEON_INTEGER_OP(shl);
4553 break;
4554 case 2: /* VRSHR */
4555 case 3: /* VRSRA */
4556 GEN_NEON_INTEGER_OP(rshl);
4557 break;
4558 case 4: /* VSRI */
4559 if (!u)
4560 return 1;
4561 GEN_NEON_INTEGER_OP(shl);
4562 break;
4563 case 5: /* VSHL, VSLI */
4564 switch (size) {
4565 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
4566 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
4567 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
4568 default: return 1;
4570 break;
4571 case 6: /* VQSHL */
4572 GEN_NEON_INTEGER_OP_ENV(qshl);
4573 break;
4574 case 7: /* VQSHLU */
4575 switch (size) {
4576 case 0: gen_helper_neon_qshl_u8(tmp, cpu_env, tmp, tmp2); break;
4577 case 1: gen_helper_neon_qshl_u16(tmp, cpu_env, tmp, tmp2); break;
4578 case 2: gen_helper_neon_qshl_u32(tmp, cpu_env, tmp, tmp2); break;
4579 default: return 1;
4581 break;
4583 dead_tmp(tmp2);
4585 if (op == 1 || op == 3) {
4586 /* Accumulate. */
4587 tmp2 = neon_load_reg(rd, pass);
4588 gen_neon_add(size, tmp2, tmp);
4589 dead_tmp(tmp2);
4590 } else if (op == 4 || (op == 5 && u)) {
4591 /* Insert */
4592 switch (size) {
4593 case 0:
4594 if (op == 4)
4595 imm = 0xff >> -shift;
4596 else
4597 imm = (uint8_t)(0xff << shift);
4598 imm |= imm << 8;
4599 imm |= imm << 16;
4600 break;
4601 case 1:
4602 if (op == 4)
4603 imm = 0xffff >> -shift;
4604 else
4605 imm = (uint16_t)(0xffff << shift);
4606 imm |= imm << 16;
4607 break;
4608 case 2:
4609 if (op == 4)
4610 imm = 0xffffffffu >> -shift;
4611 else
4612 imm = 0xffffffffu << shift;
4613 break;
4614 default:
4615 abort();
4617 tmp2 = neon_load_reg(rd, pass);
4618 tcg_gen_andi_i32(tmp, tmp, imm);
4619 tcg_gen_andi_i32(tmp2, tmp2, ~imm);
4620 tcg_gen_or_i32(tmp, tmp, tmp2);
4621 dead_tmp(tmp2);
4623 neon_store_reg(rd, pass, tmp);
4625 } /* for pass */
4626 } else if (op < 10) {
4627 /* Shift by immediate and narrow:
4628 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4629 shift = shift - (1 << (size + 3));
4630 size++;
4631 switch (size) {
4632 case 1:
4633 imm = (uint16_t)shift;
4634 imm |= imm << 16;
4635 tmp2 = tcg_const_i32(imm);
4636 TCGV_UNUSED_I64(tmp64);
4637 break;
4638 case 2:
4639 imm = (uint32_t)shift;
4640 tmp2 = tcg_const_i32(imm);
4641 TCGV_UNUSED_I64(tmp64);
4642 break;
4643 case 3:
4644 tmp64 = tcg_const_i64(shift);
4645 TCGV_UNUSED(tmp2);
4646 break;
4647 default:
4648 abort();
4651 for (pass = 0; pass < 2; pass++) {
4652 if (size == 3) {
4653 neon_load_reg64(cpu_V0, rm + pass);
4654 if (q) {
4655 if (u)
4656 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, tmp64);
4657 else
4658 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, tmp64);
4659 } else {
4660 if (u)
4661 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, tmp64);
4662 else
4663 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, tmp64);
4665 } else {
4666 tmp = neon_load_reg(rm + pass, 0);
4667 gen_neon_shift_narrow(size, tmp, tmp2, q, u);
4668 tmp3 = neon_load_reg(rm + pass, 1);
4669 gen_neon_shift_narrow(size, tmp3, tmp2, q, u);
4670 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
4671 dead_tmp(tmp);
4672 dead_tmp(tmp3);
4674 tmp = new_tmp();
4675 if (op == 8 && !u) {
4676 gen_neon_narrow(size - 1, tmp, cpu_V0);
4677 } else {
4678 if (op == 8)
4679 gen_neon_narrow_sats(size - 1, tmp, cpu_V0);
4680 else
4681 gen_neon_narrow_satu(size - 1, tmp, cpu_V0);
4683 if (pass == 0) {
4684 if (size != 3) {
4685 dead_tmp(tmp2);
4687 tmp2 = tmp;
4688 } else {
4689 neon_store_reg(rd, 0, tmp2);
4690 neon_store_reg(rd, 1, tmp);
4692 } /* for pass */
4693 if (size == 3) {
4694 tcg_temp_free_i64(tmp64);
4696 } else if (op == 10) {
4697 /* VSHLL */
4698 if (q || size == 3)
4699 return 1;
4700 tmp = neon_load_reg(rm, 0);
4701 tmp2 = neon_load_reg(rm, 1);
4702 for (pass = 0; pass < 2; pass++) {
4703 if (pass == 1)
4704 tmp = tmp2;
4706 gen_neon_widen(cpu_V0, tmp, size, u);
4708 if (shift != 0) {
4709 /* The shift is less than the width of the source
4710 type, so we can just shift the whole register. */
4711 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
4712 if (size < 2 || !u) {
4713 uint64_t imm64;
4714 if (size == 0) {
4715 imm = (0xffu >> (8 - shift));
4716 imm |= imm << 16;
4717 } else {
4718 imm = 0xffff >> (16 - shift);
4720 imm64 = imm | (((uint64_t)imm) << 32);
4721 tcg_gen_andi_i64(cpu_V0, cpu_V0, imm64);
4724 neon_store_reg64(cpu_V0, rd + pass);
4726 } else if (op == 15 || op == 16) {
4727 /* VCVT fixed-point. */
4728 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4729 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
4730 if (op & 1) {
4731 if (u)
4732 gen_vfp_ulto(0, shift);
4733 else
4734 gen_vfp_slto(0, shift);
4735 } else {
4736 if (u)
4737 gen_vfp_toul(0, shift);
4738 else
4739 gen_vfp_tosl(0, shift);
4741 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
4743 } else {
4744 return 1;
4746 } else { /* (insn & 0x00380080) == 0 */
4747 int invert;
4749 op = (insn >> 8) & 0xf;
4750 /* One register and immediate. */
4751 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4752 invert = (insn & (1 << 5)) != 0;
4753 switch (op) {
4754 case 0: case 1:
4755 /* no-op */
4756 break;
4757 case 2: case 3:
4758 imm <<= 8;
4759 break;
4760 case 4: case 5:
4761 imm <<= 16;
4762 break;
4763 case 6: case 7:
4764 imm <<= 24;
4765 break;
4766 case 8: case 9:
4767 imm |= imm << 16;
4768 break;
4769 case 10: case 11:
4770 imm = (imm << 8) | (imm << 24);
4771 break;
4772 case 12:
4773 imm = (imm < 8) | 0xff;
4774 break;
4775 case 13:
4776 imm = (imm << 16) | 0xffff;
4777 break;
4778 case 14:
4779 imm |= (imm << 8) | (imm << 16) | (imm << 24);
4780 if (invert)
4781 imm = ~imm;
4782 break;
4783 case 15:
4784 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
4785 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
4786 break;
4788 if (invert)
4789 imm = ~imm;
4791 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4792 if (op & 1 && op < 12) {
4793 tmp = neon_load_reg(rd, pass);
4794 if (invert) {
4795 /* The immediate value has already been inverted, so
4796 BIC becomes AND. */
4797 tcg_gen_andi_i32(tmp, tmp, imm);
4798 } else {
4799 tcg_gen_ori_i32(tmp, tmp, imm);
4801 } else {
4802 /* VMOV, VMVN. */
4803 tmp = new_tmp();
4804 if (op == 14 && invert) {
4805 uint32_t val;
4806 val = 0;
4807 for (n = 0; n < 4; n++) {
4808 if (imm & (1 << (n + (pass & 1) * 4)))
4809 val |= 0xff << (n * 8);
4811 tcg_gen_movi_i32(tmp, val);
4812 } else {
4813 tcg_gen_movi_i32(tmp, imm);
4816 neon_store_reg(rd, pass, tmp);
4819 } else { /* (insn & 0x00800010 == 0x00800000) */
4820 if (size != 3) {
4821 op = (insn >> 8) & 0xf;
4822 if ((insn & (1 << 6)) == 0) {
4823 /* Three registers of different lengths. */
4824 int src1_wide;
4825 int src2_wide;
4826 int prewiden;
4827 /* prewiden, src1_wide, src2_wide */
4828 static const int neon_3reg_wide[16][3] = {
4829 {1, 0, 0}, /* VADDL */
4830 {1, 1, 0}, /* VADDW */
4831 {1, 0, 0}, /* VSUBL */
4832 {1, 1, 0}, /* VSUBW */
4833 {0, 1, 1}, /* VADDHN */
4834 {0, 0, 0}, /* VABAL */
4835 {0, 1, 1}, /* VSUBHN */
4836 {0, 0, 0}, /* VABDL */
4837 {0, 0, 0}, /* VMLAL */
4838 {0, 0, 0}, /* VQDMLAL */
4839 {0, 0, 0}, /* VMLSL */
4840 {0, 0, 0}, /* VQDMLSL */
4841 {0, 0, 0}, /* Integer VMULL */
4842 {0, 0, 0}, /* VQDMULL */
4843 {0, 0, 0} /* Polynomial VMULL */
4846 prewiden = neon_3reg_wide[op][0];
4847 src1_wide = neon_3reg_wide[op][1];
4848 src2_wide = neon_3reg_wide[op][2];
4850 if (size == 0 && (op == 9 || op == 11 || op == 13))
4851 return 1;
4853 /* Avoid overlapping operands. Wide source operands are
4854 always aligned so will never overlap with wide
4855 destinations in problematic ways. */
4856 if (rd == rm && !src2_wide) {
4857 tmp = neon_load_reg(rm, 1);
4858 neon_store_scratch(2, tmp);
4859 } else if (rd == rn && !src1_wide) {
4860 tmp = neon_load_reg(rn, 1);
4861 neon_store_scratch(2, tmp);
4863 TCGV_UNUSED(tmp3);
4864 for (pass = 0; pass < 2; pass++) {
4865 if (src1_wide) {
4866 neon_load_reg64(cpu_V0, rn + pass);
4867 TCGV_UNUSED(tmp);
4868 } else {
4869 if (pass == 1 && rd == rn) {
4870 tmp = neon_load_scratch(2);
4871 } else {
4872 tmp = neon_load_reg(rn, pass);
4874 if (prewiden) {
4875 gen_neon_widen(cpu_V0, tmp, size, u);
4878 if (src2_wide) {
4879 neon_load_reg64(cpu_V1, rm + pass);
4880 TCGV_UNUSED(tmp2);
4881 } else {
4882 if (pass == 1 && rd == rm) {
4883 tmp2 = neon_load_scratch(2);
4884 } else {
4885 tmp2 = neon_load_reg(rm, pass);
4887 if (prewiden) {
4888 gen_neon_widen(cpu_V1, tmp2, size, u);
4891 switch (op) {
4892 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4893 gen_neon_addl(size);
4894 break;
4895 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4896 gen_neon_subl(size);
4897 break;
4898 case 5: case 7: /* VABAL, VABDL */
4899 switch ((size << 1) | u) {
4900 case 0:
4901 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
4902 break;
4903 case 1:
4904 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
4905 break;
4906 case 2:
4907 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
4908 break;
4909 case 3:
4910 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
4911 break;
4912 case 4:
4913 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
4914 break;
4915 case 5:
4916 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
4917 break;
4918 default: abort();
4920 dead_tmp(tmp2);
4921 dead_tmp(tmp);
4922 break;
4923 case 8: case 9: case 10: case 11: case 12: case 13:
4924 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4925 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
4926 dead_tmp(tmp2);
4927 dead_tmp(tmp);
4928 break;
4929 case 14: /* Polynomial VMULL */
4930 cpu_abort(env, "Polynomial VMULL not implemented");
4932 default: /* 15 is RESERVED. */
4933 return 1;
4935 if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
4936 /* Accumulate. */
4937 if (op == 10 || op == 11) {
4938 gen_neon_negl(cpu_V0, size);
4941 if (op != 13) {
4942 neon_load_reg64(cpu_V1, rd + pass);
4945 switch (op) {
4946 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4947 gen_neon_addl(size);
4948 break;
4949 case 9: case 11: /* VQDMLAL, VQDMLSL */
4950 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4951 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
4952 break;
4953 /* Fall through. */
4954 case 13: /* VQDMULL */
4955 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4956 break;
4957 default:
4958 abort();
4960 neon_store_reg64(cpu_V0, rd + pass);
4961 } else if (op == 4 || op == 6) {
4962 /* Narrowing operation. */
4963 tmp = new_tmp();
4964 if (u) {
4965 switch (size) {
4966 case 0:
4967 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
4968 break;
4969 case 1:
4970 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
4971 break;
4972 case 2:
4973 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
4974 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
4975 break;
4976 default: abort();
4978 } else {
4979 switch (size) {
4980 case 0:
4981 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
4982 break;
4983 case 1:
4984 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
4985 break;
4986 case 2:
4987 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
4988 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
4989 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
4990 break;
4991 default: abort();
4994 if (pass == 0) {
4995 tmp3 = tmp;
4996 } else {
4997 neon_store_reg(rd, 0, tmp3);
4998 neon_store_reg(rd, 1, tmp);
5000 } else {
5001 /* Write back the result. */
5002 neon_store_reg64(cpu_V0, rd + pass);
5005 } else {
5006 /* Two registers and a scalar. */
5007 switch (op) {
5008 case 0: /* Integer VMLA scalar */
5009 case 1: /* Float VMLA scalar */
5010 case 4: /* Integer VMLS scalar */
5011 case 5: /* Floating point VMLS scalar */
5012 case 8: /* Integer VMUL scalar */
5013 case 9: /* Floating point VMUL scalar */
5014 case 12: /* VQDMULH scalar */
5015 case 13: /* VQRDMULH scalar */
5016 tmp = neon_get_scalar(size, rm);
5017 neon_store_scratch(0, tmp);
5018 for (pass = 0; pass < (u ? 4 : 2); pass++) {
5019 tmp = neon_load_scratch(0);
5020 tmp2 = neon_load_reg(rn, pass);
5021 if (op == 12) {
5022 if (size == 1) {
5023 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5024 } else {
5025 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5027 } else if (op == 13) {
5028 if (size == 1) {
5029 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5030 } else {
5031 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5033 } else if (op & 1) {
5034 gen_helper_neon_mul_f32(tmp, tmp, tmp2);
5035 } else {
5036 switch (size) {
5037 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5038 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5039 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5040 default: return 1;
5043 dead_tmp(tmp2);
5044 if (op < 8) {
5045 /* Accumulate. */
5046 tmp2 = neon_load_reg(rd, pass);
5047 switch (op) {
5048 case 0:
5049 gen_neon_add(size, tmp, tmp2);
5050 break;
5051 case 1:
5052 gen_helper_neon_add_f32(tmp, tmp, tmp2);
5053 break;
5054 case 4:
5055 gen_neon_rsb(size, tmp, tmp2);
5056 break;
5057 case 5:
5058 gen_helper_neon_sub_f32(tmp, tmp2, tmp);
5059 break;
5060 default:
5061 abort();
5063 dead_tmp(tmp2);
5065 neon_store_reg(rd, pass, tmp);
5067 break;
5068 case 2: /* VMLAL sclar */
5069 case 3: /* VQDMLAL scalar */
5070 case 6: /* VMLSL scalar */
5071 case 7: /* VQDMLSL scalar */
5072 case 10: /* VMULL scalar */
5073 case 11: /* VQDMULL scalar */
5074 if (size == 0 && (op == 3 || op == 7 || op == 11))
5075 return 1;
5077 tmp2 = neon_get_scalar(size, rm);
5078 tmp3 = neon_load_reg(rn, 1);
5080 for (pass = 0; pass < 2; pass++) {
5081 if (pass == 0) {
5082 tmp = neon_load_reg(rn, 0);
5083 } else {
5084 tmp = tmp3;
5086 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5087 dead_tmp(tmp);
5088 if (op == 6 || op == 7) {
5089 gen_neon_negl(cpu_V0, size);
5091 if (op != 11) {
5092 neon_load_reg64(cpu_V1, rd + pass);
5094 switch (op) {
5095 case 2: case 6:
5096 gen_neon_addl(size);
5097 break;
5098 case 3: case 7:
5099 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5100 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5101 break;
5102 case 10:
5103 /* no-op */
5104 break;
5105 case 11:
5106 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5107 break;
5108 default:
5109 abort();
5111 neon_store_reg64(cpu_V0, rd + pass);
5114 dead_tmp(tmp2);
5116 break;
5117 default: /* 14 and 15 are RESERVED */
5118 return 1;
5121 } else { /* size == 3 */
5122 if (!u) {
5123 /* Extract. */
5124 imm = (insn >> 8) & 0xf;
5125 count = q + 1;
5127 if (imm > 7 && !q)
5128 return 1;
5130 if (imm == 0) {
5131 neon_load_reg64(cpu_V0, rn);
5132 if (q) {
5133 neon_load_reg64(cpu_V1, rn + 1);
5135 } else if (imm == 8) {
5136 neon_load_reg64(cpu_V0, rn + 1);
5137 if (q) {
5138 neon_load_reg64(cpu_V1, rm);
5140 } else if (q) {
5141 tmp64 = tcg_temp_new_i64();
5142 if (imm < 8) {
5143 neon_load_reg64(cpu_V0, rn);
5144 neon_load_reg64(tmp64, rn + 1);
5145 } else {
5146 neon_load_reg64(cpu_V0, rn + 1);
5147 neon_load_reg64(tmp64, rm);
5149 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5150 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
5151 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5152 if (imm < 8) {
5153 neon_load_reg64(cpu_V1, rm);
5154 } else {
5155 neon_load_reg64(cpu_V1, rm + 1);
5156 imm -= 8;
5158 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5159 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
5160 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
5161 tcg_temp_free_i64(tmp64);
5162 } else {
5163 /* BUGFIX */
5164 neon_load_reg64(cpu_V0, rn);
5165 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
5166 neon_load_reg64(cpu_V1, rm);
5167 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5168 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5170 neon_store_reg64(cpu_V0, rd);
5171 if (q) {
5172 neon_store_reg64(cpu_V1, rd + 1);
5174 } else if ((insn & (1 << 11)) == 0) {
5175 /* Two register misc. */
5176 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5177 size = (insn >> 18) & 3;
5178 switch (op) {
5179 case 0: /* VREV64 */
5180 if (size == 3)
5181 return 1;
5182 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5183 tmp = neon_load_reg(rm, pass * 2);
5184 tmp2 = neon_load_reg(rm, pass * 2 + 1);
5185 switch (size) {
5186 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5187 case 1: gen_swap_half(tmp); break;
5188 case 2: /* no-op */ break;
5189 default: abort();
5191 neon_store_reg(rd, pass * 2 + 1, tmp);
5192 if (size == 2) {
5193 neon_store_reg(rd, pass * 2, tmp2);
5194 } else {
5195 switch (size) {
5196 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
5197 case 1: gen_swap_half(tmp2); break;
5198 default: abort();
5200 neon_store_reg(rd, pass * 2, tmp2);
5203 break;
5204 case 4: case 5: /* VPADDL */
5205 case 12: case 13: /* VPADAL */
5206 if (size == 3)
5207 return 1;
5208 for (pass = 0; pass < q + 1; pass++) {
5209 tmp = neon_load_reg(rm, pass * 2);
5210 gen_neon_widen(cpu_V0, tmp, size, op & 1);
5211 tmp = neon_load_reg(rm, pass * 2 + 1);
5212 gen_neon_widen(cpu_V1, tmp, size, op & 1);
5213 switch (size) {
5214 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5215 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5216 case 2: tcg_gen_add_i64(CPU_V001); break;
5217 default: abort();
5219 if (op >= 12) {
5220 /* Accumulate. */
5221 neon_load_reg64(cpu_V1, rd + pass);
5222 gen_neon_addl(size);
5224 neon_store_reg64(cpu_V0, rd + pass);
5226 break;
5227 case 33: /* VTRN */
5228 if (size == 2) {
5229 for (n = 0; n < (q ? 4 : 2); n += 2) {
5230 tmp = neon_load_reg(rm, n);
5231 tmp2 = neon_load_reg(rd, n + 1);
5232 neon_store_reg(rm, n, tmp2);
5233 neon_store_reg(rd, n + 1, tmp);
5235 } else {
5236 goto elementwise;
5238 break;
5239 case 34: /* VUZP */
5240 /* Reg Before After
5241 Rd A3 A2 A1 A0 B2 B0 A2 A0
5242 Rm B3 B2 B1 B0 B3 B1 A3 A1
5244 if (size == 3)
5245 return 1;
5246 gen_neon_unzip(rd, q, 0, size);
5247 gen_neon_unzip(rm, q, 4, size);
5248 if (q) {
5249 static int unzip_order_q[8] =
5250 {0, 2, 4, 6, 1, 3, 5, 7};
5251 for (n = 0; n < 8; n++) {
5252 int reg = (n < 4) ? rd : rm;
5253 tmp = neon_load_scratch(unzip_order_q[n]);
5254 neon_store_reg(reg, n % 4, tmp);
5256 } else {
5257 static int unzip_order[4] =
5258 {0, 4, 1, 5};
5259 for (n = 0; n < 4; n++) {
5260 int reg = (n < 2) ? rd : rm;
5261 tmp = neon_load_scratch(unzip_order[n]);
5262 neon_store_reg(reg, n % 2, tmp);
5265 break;
5266 case 35: /* VZIP */
5267 /* Reg Before After
5268 Rd A3 A2 A1 A0 B1 A1 B0 A0
5269 Rm B3 B2 B1 B0 B3 A3 B2 A2
5271 if (size == 3)
5272 return 1;
5273 count = (q ? 4 : 2);
5274 for (n = 0; n < count; n++) {
5275 tmp = neon_load_reg(rd, n);
5276 tmp2 = neon_load_reg(rd, n);
5277 switch (size) {
5278 case 0: gen_neon_zip_u8(tmp, tmp2); break;
5279 case 1: gen_neon_zip_u16(tmp, tmp2); break;
5280 case 2: /* no-op */; break;
5281 default: abort();
5283 neon_store_scratch(n * 2, tmp);
5284 neon_store_scratch(n * 2 + 1, tmp2);
5286 for (n = 0; n < count * 2; n++) {
5287 int reg = (n < count) ? rd : rm;
5288 tmp = neon_load_scratch(n);
5289 neon_store_reg(reg, n % count, tmp);
5291 break;
5292 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5293 if (size == 3)
5294 return 1;
5295 TCGV_UNUSED(tmp2);
5296 for (pass = 0; pass < 2; pass++) {
5297 neon_load_reg64(cpu_V0, rm + pass);
5298 tmp = new_tmp();
5299 if (op == 36 && q == 0) {
5300 gen_neon_narrow(size, tmp, cpu_V0);
5301 } else if (q) {
5302 gen_neon_narrow_satu(size, tmp, cpu_V0);
5303 } else {
5304 gen_neon_narrow_sats(size, tmp, cpu_V0);
5306 if (pass == 0) {
5307 tmp2 = tmp;
5308 } else {
5309 neon_store_reg(rd, 0, tmp2);
5310 neon_store_reg(rd, 1, tmp);
5313 break;
5314 case 38: /* VSHLL */
5315 if (q || size == 3)
5316 return 1;
5317 tmp = neon_load_reg(rm, 0);
5318 tmp2 = neon_load_reg(rm, 1);
5319 for (pass = 0; pass < 2; pass++) {
5320 if (pass == 1)
5321 tmp = tmp2;
5322 gen_neon_widen(cpu_V0, tmp, size, 1);
5323 neon_store_reg64(cpu_V0, rd + pass);
5325 break;
5326 default:
5327 elementwise:
5328 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5329 if (op == 30 || op == 31 || op >= 58) {
5330 tcg_gen_ld_f32(cpu_F0s, cpu_env,
5331 neon_reg_offset(rm, pass));
5332 TCGV_UNUSED(tmp);
5333 } else {
5334 tmp = neon_load_reg(rm, pass);
5336 switch (op) {
5337 case 1: /* VREV32 */
5338 switch (size) {
5339 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5340 case 1: gen_swap_half(tmp); break;
5341 default: return 1;
5343 break;
5344 case 2: /* VREV16 */
5345 if (size != 0)
5346 return 1;
5347 gen_rev16(tmp);
5348 break;
5349 case 8: /* CLS */
5350 switch (size) {
5351 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
5352 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
5353 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
5354 default: return 1;
5356 break;
5357 case 9: /* CLZ */
5358 switch (size) {
5359 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
5360 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
5361 case 2: gen_helper_clz(tmp, tmp); break;
5362 default: return 1;
5364 break;
5365 case 10: /* CNT */
5366 if (size != 0)
5367 return 1;
5368 gen_helper_neon_cnt_u8(tmp, tmp);
5369 break;
5370 case 11: /* VNOT */
5371 if (size != 0)
5372 return 1;
5373 tcg_gen_not_i32(tmp, tmp);
5374 break;
5375 case 14: /* VQABS */
5376 switch (size) {
5377 case 0: gen_helper_neon_qabs_s8(tmp, cpu_env, tmp); break;
5378 case 1: gen_helper_neon_qabs_s16(tmp, cpu_env, tmp); break;
5379 case 2: gen_helper_neon_qabs_s32(tmp, cpu_env, tmp); break;
5380 default: return 1;
5382 break;
5383 case 15: /* VQNEG */
5384 switch (size) {
5385 case 0: gen_helper_neon_qneg_s8(tmp, cpu_env, tmp); break;
5386 case 1: gen_helper_neon_qneg_s16(tmp, cpu_env, tmp); break;
5387 case 2: gen_helper_neon_qneg_s32(tmp, cpu_env, tmp); break;
5388 default: return 1;
5390 break;
5391 case 16: case 19: /* VCGT #0, VCLE #0 */
5392 tmp2 = tcg_const_i32(0);
5393 switch(size) {
5394 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
5395 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
5396 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
5397 default: return 1;
5399 tcg_temp_free(tmp2);
5400 if (op == 19)
5401 tcg_gen_not_i32(tmp, tmp);
5402 break;
5403 case 17: case 20: /* VCGE #0, VCLT #0 */
5404 tmp2 = tcg_const_i32(0);
5405 switch(size) {
5406 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
5407 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
5408 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
5409 default: return 1;
5411 tcg_temp_free(tmp2);
5412 if (op == 20)
5413 tcg_gen_not_i32(tmp, tmp);
5414 break;
5415 case 18: /* VCEQ #0 */
5416 tmp2 = tcg_const_i32(0);
5417 switch(size) {
5418 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
5419 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
5420 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
5421 default: return 1;
5423 tcg_temp_free(tmp2);
5424 break;
5425 case 22: /* VABS */
5426 switch(size) {
5427 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
5428 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
5429 case 2: tcg_gen_abs_i32(tmp, tmp); break;
5430 default: return 1;
5432 break;
5433 case 23: /* VNEG */
5434 if (size == 3)
5435 return 1;
5436 tmp2 = tcg_const_i32(0);
5437 gen_neon_rsb(size, tmp, tmp2);
5438 tcg_temp_free(tmp2);
5439 break;
5440 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5441 tmp2 = tcg_const_i32(0);
5442 gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
5443 tcg_temp_free(tmp2);
5444 if (op == 27)
5445 tcg_gen_not_i32(tmp, tmp);
5446 break;
5447 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5448 tmp2 = tcg_const_i32(0);
5449 gen_helper_neon_cge_f32(tmp, tmp, tmp2);
5450 tcg_temp_free(tmp2);
5451 if (op == 28)
5452 tcg_gen_not_i32(tmp, tmp);
5453 break;
5454 case 26: /* Float VCEQ #0 */
5455 tmp2 = tcg_const_i32(0);
5456 gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
5457 tcg_temp_free(tmp2);
5458 break;
5459 case 30: /* Float VABS */
5460 gen_vfp_abs(0);
5461 break;
5462 case 31: /* Float VNEG */
5463 gen_vfp_neg(0);
5464 break;
5465 case 32: /* VSWP */
5466 tmp2 = neon_load_reg(rd, pass);
5467 neon_store_reg(rm, pass, tmp2);
5468 break;
5469 case 33: /* VTRN */
5470 tmp2 = neon_load_reg(rd, pass);
5471 switch (size) {
5472 case 0: gen_neon_trn_u8(tmp, tmp2); break;
5473 case 1: gen_neon_trn_u16(tmp, tmp2); break;
5474 case 2: abort();
5475 default: return 1;
5477 neon_store_reg(rm, pass, tmp2);
5478 break;
5479 case 56: /* Integer VRECPE */
5480 gen_helper_recpe_u32(tmp, tmp, cpu_env);
5481 break;
5482 case 57: /* Integer VRSQRTE */
5483 gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
5484 break;
5485 case 58: /* Float VRECPE */
5486 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
5487 break;
5488 case 59: /* Float VRSQRTE */
5489 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
5490 break;
5491 case 60: /* VCVT.F32.S32 */
5492 gen_vfp_tosiz(0);
5493 break;
5494 case 61: /* VCVT.F32.U32 */
5495 gen_vfp_touiz(0);
5496 break;
5497 case 62: /* VCVT.S32.F32 */
5498 gen_vfp_sito(0);
5499 break;
5500 case 63: /* VCVT.U32.F32 */
5501 gen_vfp_uito(0);
5502 break;
5503 default:
5504 /* Reserved: 21, 29, 39-56 */
5505 return 1;
5507 if (op == 30 || op == 31 || op >= 58) {
5508 tcg_gen_st_f32(cpu_F0s, cpu_env,
5509 neon_reg_offset(rd, pass));
5510 } else {
5511 neon_store_reg(rd, pass, tmp);
5514 break;
5516 } else if ((insn & (1 << 10)) == 0) {
5517 /* VTBL, VTBX. */
5518 n = ((insn >> 5) & 0x18) + 8;
5519 if (insn & (1 << 6)) {
5520 tmp = neon_load_reg(rd, 0);
5521 } else {
5522 tmp = new_tmp();
5523 tcg_gen_movi_i32(tmp, 0);
5525 tmp2 = neon_load_reg(rm, 0);
5526 tmp4 = tcg_const_i32(rn);
5527 tmp5 = tcg_const_i32(n);
5528 gen_helper_neon_tbl(tmp2, tmp2, tmp, tmp4, tmp5);
5529 dead_tmp(tmp);
5530 if (insn & (1 << 6)) {
5531 tmp = neon_load_reg(rd, 1);
5532 } else {
5533 tmp = new_tmp();
5534 tcg_gen_movi_i32(tmp, 0);
5536 tmp3 = neon_load_reg(rm, 1);
5537 gen_helper_neon_tbl(tmp3, tmp3, tmp, tmp4, tmp5);
5538 tcg_temp_free_i32(tmp5);
5539 tcg_temp_free_i32(tmp4);
5540 neon_store_reg(rd, 0, tmp2);
5541 neon_store_reg(rd, 1, tmp3);
5542 dead_tmp(tmp);
5543 } else if ((insn & 0x380) == 0) {
5544 /* VDUP */
5545 if (insn & (1 << 19)) {
5546 tmp = neon_load_reg(rm, 1);
5547 } else {
5548 tmp = neon_load_reg(rm, 0);
5550 if (insn & (1 << 16)) {
5551 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
5552 } else if (insn & (1 << 17)) {
5553 if ((insn >> 18) & 1)
5554 gen_neon_dup_high16(tmp);
5555 else
5556 gen_neon_dup_low16(tmp);
5558 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5559 tmp2 = new_tmp();
5560 tcg_gen_mov_i32(tmp2, tmp);
5561 neon_store_reg(rd, pass, tmp2);
5563 dead_tmp(tmp);
5564 } else {
5565 return 1;
5569 return 0;
5572 static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
5574 int crn = (insn >> 16) & 0xf;
5575 int crm = insn & 0xf;
5576 int op1 = (insn >> 21) & 7;
5577 int op2 = (insn >> 5) & 7;
5578 int rt = (insn >> 12) & 0xf;
5579 TCGv tmp;
5581 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5582 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5583 /* TEECR */
5584 if (IS_USER(s))
5585 return 1;
5586 tmp = load_cpu_field(teecr);
5587 store_reg(s, rt, tmp);
5588 return 0;
5590 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5591 /* TEEHBR */
5592 if (IS_USER(s) && (env->teecr & 1))
5593 return 1;
5594 tmp = load_cpu_field(teehbr);
5595 store_reg(s, rt, tmp);
5596 return 0;
5599 fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5600 op1, crn, crm, op2);
5601 return 1;
5604 static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
5606 int crn = (insn >> 16) & 0xf;
5607 int crm = insn & 0xf;
5608 int op1 = (insn >> 21) & 7;
5609 int op2 = (insn >> 5) & 7;
5610 int rt = (insn >> 12) & 0xf;
5611 TCGv tmp;
5613 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5614 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5615 /* TEECR */
5616 if (IS_USER(s))
5617 return 1;
5618 tmp = load_reg(s, rt);
5619 gen_helper_set_teecr(cpu_env, tmp);
5620 dead_tmp(tmp);
5621 return 0;
5623 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5624 /* TEEHBR */
5625 if (IS_USER(s) && (env->teecr & 1))
5626 return 1;
5627 tmp = load_reg(s, rt);
5628 store_cpu_field(tmp, teehbr);
5629 return 0;
5632 fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5633 op1, crn, crm, op2);
5634 return 1;
5637 static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
5639 int cpnum;
5641 cpnum = (insn >> 8) & 0xf;
5642 if (arm_feature(env, ARM_FEATURE_XSCALE)
5643 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
5644 return 1;
5646 switch (cpnum) {
5647 case 0:
5648 case 1:
5649 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5650 return disas_iwmmxt_insn(env, s, insn);
5651 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
5652 return disas_dsp_insn(env, s, insn);
5654 return 1;
5655 case 10:
5656 case 11:
5657 return disas_vfp_insn (env, s, insn);
5658 case 14:
5659 /* Coprocessors 7-15 are architecturally reserved by ARM.
5660 Unfortunately Intel decided to ignore this. */
5661 if (arm_feature(env, ARM_FEATURE_XSCALE))
5662 goto board;
5663 if (insn & (1 << 20))
5664 return disas_cp14_read(env, s, insn);
5665 else
5666 return disas_cp14_write(env, s, insn);
5667 case 15:
5668 return disas_cp15_insn (env, s, insn);
5669 default:
5670 board:
5671 /* Unknown coprocessor. See if the board has hooked it. */
5672 return disas_cp_insn (env, s, insn);
5677 /* Store a 64-bit value to a register pair. Clobbers val. */
5678 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5680 TCGv tmp;
5681 tmp = new_tmp();
5682 tcg_gen_trunc_i64_i32(tmp, val);
5683 store_reg(s, rlow, tmp);
5684 tmp = new_tmp();
5685 tcg_gen_shri_i64(val, val, 32);
5686 tcg_gen_trunc_i64_i32(tmp, val);
5687 store_reg(s, rhigh, tmp);
5690 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5691 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5693 TCGv_i64 tmp;
5694 TCGv tmp2;
5696 /* Load value and extend to 64 bits. */
5697 tmp = tcg_temp_new_i64();
5698 tmp2 = load_reg(s, rlow);
5699 tcg_gen_extu_i32_i64(tmp, tmp2);
5700 dead_tmp(tmp2);
5701 tcg_gen_add_i64(val, val, tmp);
5702 tcg_temp_free_i64(tmp);
5705 /* load and add a 64-bit value from a register pair. */
5706 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5708 TCGv_i64 tmp;
5709 TCGv tmpl;
5710 TCGv tmph;
5712 /* Load 64-bit value rd:rn. */
5713 tmpl = load_reg(s, rlow);
5714 tmph = load_reg(s, rhigh);
5715 tmp = tcg_temp_new_i64();
5716 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
5717 dead_tmp(tmpl);
5718 dead_tmp(tmph);
5719 tcg_gen_add_i64(val, val, tmp);
5720 tcg_temp_free_i64(tmp);
5723 /* Set N and Z flags from a 64-bit value. */
5724 static void gen_logicq_cc(TCGv_i64 val)
5726 TCGv tmp = new_tmp();
5727 gen_helper_logicq_cc(tmp, val);
5728 gen_logic_CC(tmp);
5729 dead_tmp(tmp);
5732 static void disas_arm_insn(CPUState * env, DisasContext *s)
5734 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
5735 TCGv tmp;
5736 TCGv tmp2;
5737 TCGv tmp3;
5738 TCGv addr;
5739 TCGv_i64 tmp64;
5741 insn = ldl_code(s->pc);
5742 s->pc += 4;
5744 /* M variants do not implement ARM mode. */
5745 if (IS_M(env))
5746 goto illegal_op;
5747 cond = insn >> 28;
5748 if (cond == 0xf){
5749 /* Unconditional instructions. */
5750 if (((insn >> 25) & 7) == 1) {
5751 /* NEON Data processing. */
5752 if (!arm_feature(env, ARM_FEATURE_NEON))
5753 goto illegal_op;
5755 if (disas_neon_data_insn(env, s, insn))
5756 goto illegal_op;
5757 return;
5759 if ((insn & 0x0f100000) == 0x04000000) {
5760 /* NEON load/store. */
5761 if (!arm_feature(env, ARM_FEATURE_NEON))
5762 goto illegal_op;
5764 if (disas_neon_ls_insn(env, s, insn))
5765 goto illegal_op;
5766 return;
5768 if ((insn & 0x0d70f000) == 0x0550f000)
5769 return; /* PLD */
5770 else if ((insn & 0x0ffffdff) == 0x01010000) {
5771 ARCH(6);
5772 /* setend */
5773 if (insn & (1 << 9)) {
5774 /* BE8 mode not implemented. */
5775 goto illegal_op;
5777 return;
5778 } else if ((insn & 0x0fffff00) == 0x057ff000) {
5779 switch ((insn >> 4) & 0xf) {
5780 case 1: /* clrex */
5781 ARCH(6K);
5782 gen_helper_clrex(cpu_env);
5783 return;
5784 case 4: /* dsb */
5785 case 5: /* dmb */
5786 case 6: /* isb */
5787 ARCH(7);
5788 /* We don't emulate caches so these are a no-op. */
5789 return;
5790 default:
5791 goto illegal_op;
5793 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
5794 /* srs */
5795 int32_t offset;
5796 if (IS_USER(s))
5797 goto illegal_op;
5798 ARCH(6);
5799 op1 = (insn & 0x1f);
5800 if (op1 == (env->uncached_cpsr & CPSR_M)) {
5801 addr = load_reg(s, 13);
5802 } else {
5803 addr = new_tmp();
5804 tmp = tcg_const_i32(op1);
5805 gen_helper_get_r13_banked(addr, cpu_env, tmp);
5806 tcg_temp_free_i32(tmp);
5808 i = (insn >> 23) & 3;
5809 switch (i) {
5810 case 0: offset = -4; break; /* DA */
5811 case 1: offset = 0; break; /* IA */
5812 case 2: offset = -8; break; /* DB */
5813 case 3: offset = 4; break; /* IB */
5814 default: abort();
5816 if (offset)
5817 tcg_gen_addi_i32(addr, addr, offset);
5818 tmp = load_reg(s, 14);
5819 gen_st32(tmp, addr, 0);
5820 tmp = load_cpu_field(spsr);
5821 tcg_gen_addi_i32(addr, addr, 4);
5822 gen_st32(tmp, addr, 0);
5823 if (insn & (1 << 21)) {
5824 /* Base writeback. */
5825 switch (i) {
5826 case 0: offset = -8; break;
5827 case 1: offset = 4; break;
5828 case 2: offset = -4; break;
5829 case 3: offset = 0; break;
5830 default: abort();
5832 if (offset)
5833 tcg_gen_addi_i32(addr, addr, offset);
5834 if (op1 == (env->uncached_cpsr & CPSR_M)) {
5835 store_reg(s, 13, addr);
5836 } else {
5837 tmp = tcg_const_i32(op1);
5838 gen_helper_set_r13_banked(cpu_env, tmp, addr);
5839 tcg_temp_free_i32(tmp);
5840 dead_tmp(addr);
5842 } else {
5843 dead_tmp(addr);
5845 } else if ((insn & 0x0e5fffe0) == 0x081d0a00) {
5846 /* rfe */
5847 int32_t offset;
5848 if (IS_USER(s))
5849 goto illegal_op;
5850 ARCH(6);
5851 rn = (insn >> 16) & 0xf;
5852 addr = load_reg(s, rn);
5853 i = (insn >> 23) & 3;
5854 switch (i) {
5855 case 0: offset = -4; break; /* DA */
5856 case 1: offset = 0; break; /* IA */
5857 case 2: offset = -8; break; /* DB */
5858 case 3: offset = 4; break; /* IB */
5859 default: abort();
5861 if (offset)
5862 tcg_gen_addi_i32(addr, addr, offset);
5863 /* Load PC into tmp and CPSR into tmp2. */
5864 tmp = gen_ld32(addr, 0);
5865 tcg_gen_addi_i32(addr, addr, 4);
5866 tmp2 = gen_ld32(addr, 0);
5867 if (insn & (1 << 21)) {
5868 /* Base writeback. */
5869 switch (i) {
5870 case 0: offset = -8; break;
5871 case 1: offset = 4; break;
5872 case 2: offset = -4; break;
5873 case 3: offset = 0; break;
5874 default: abort();
5876 if (offset)
5877 tcg_gen_addi_i32(addr, addr, offset);
5878 store_reg(s, rn, addr);
5879 } else {
5880 dead_tmp(addr);
5882 gen_rfe(s, tmp, tmp2);
5883 return;
5884 } else if ((insn & 0x0e000000) == 0x0a000000) {
5885 /* branch link and change to thumb (blx <offset>) */
5886 int32_t offset;
5888 val = (uint32_t)s->pc;
5889 tmp = new_tmp();
5890 tcg_gen_movi_i32(tmp, val);
5891 store_reg(s, 14, tmp);
5892 /* Sign-extend the 24-bit offset */
5893 offset = (((int32_t)insn) << 8) >> 8;
5894 /* offset * 4 + bit24 * 2 + (thumb bit) */
5895 val += (offset << 2) | ((insn >> 23) & 2) | 1;
5896 /* pipeline offset */
5897 val += 4;
5898 gen_bx_im(s, val);
5899 return;
5900 } else if ((insn & 0x0e000f00) == 0x0c000100) {
5901 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5902 /* iWMMXt register transfer. */
5903 if (env->cp15.c15_cpar & (1 << 1))
5904 if (!disas_iwmmxt_insn(env, s, insn))
5905 return;
5907 } else if ((insn & 0x0fe00000) == 0x0c400000) {
5908 /* Coprocessor double register transfer. */
5909 } else if ((insn & 0x0f000010) == 0x0e000010) {
5910 /* Additional coprocessor register transfer. */
5911 } else if ((insn & 0x0ff10020) == 0x01000000) {
5912 uint32_t mask;
5913 uint32_t val;
5914 /* cps (privileged) */
5915 if (IS_USER(s))
5916 return;
5917 mask = val = 0;
5918 if (insn & (1 << 19)) {
5919 if (insn & (1 << 8))
5920 mask |= CPSR_A;
5921 if (insn & (1 << 7))
5922 mask |= CPSR_I;
5923 if (insn & (1 << 6))
5924 mask |= CPSR_F;
5925 if (insn & (1 << 18))
5926 val |= mask;
5928 if (insn & (1 << 17)) {
5929 mask |= CPSR_M;
5930 val |= (insn & 0x1f);
5932 if (mask) {
5933 gen_set_psr_im(s, mask, 0, val);
5935 return;
5937 goto illegal_op;
5939 if (cond != 0xe) {
5940 /* if not always execute, we generate a conditional jump to
5941 next instruction */
5942 s->condlabel = gen_new_label();
5943 gen_test_cc(cond ^ 1, s->condlabel);
5944 s->condjmp = 1;
5946 if ((insn & 0x0f900000) == 0x03000000) {
5947 if ((insn & (1 << 21)) == 0) {
5948 ARCH(6T2);
5949 rd = (insn >> 12) & 0xf;
5950 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
5951 if ((insn & (1 << 22)) == 0) {
5952 /* MOVW */
5953 tmp = new_tmp();
5954 tcg_gen_movi_i32(tmp, val);
5955 } else {
5956 /* MOVT */
5957 tmp = load_reg(s, rd);
5958 tcg_gen_ext16u_i32(tmp, tmp);
5959 tcg_gen_ori_i32(tmp, tmp, val << 16);
5961 store_reg(s, rd, tmp);
5962 } else {
5963 if (((insn >> 12) & 0xf) != 0xf)
5964 goto illegal_op;
5965 if (((insn >> 16) & 0xf) == 0) {
5966 gen_nop_hint(s, insn & 0xff);
5967 } else {
5968 /* CPSR = immediate */
5969 val = insn & 0xff;
5970 shift = ((insn >> 8) & 0xf) * 2;
5971 if (shift)
5972 val = (val >> shift) | (val << (32 - shift));
5973 i = ((insn & (1 << 22)) != 0);
5974 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
5975 goto illegal_op;
5978 } else if ((insn & 0x0f900000) == 0x01000000
5979 && (insn & 0x00000090) != 0x00000090) {
5980 /* miscellaneous instructions */
5981 op1 = (insn >> 21) & 3;
5982 sh = (insn >> 4) & 0xf;
5983 rm = insn & 0xf;
5984 switch (sh) {
5985 case 0x0: /* move program status register */
5986 if (op1 & 1) {
5987 /* PSR = reg */
5988 tmp = load_reg(s, rm);
5989 i = ((op1 & 2) != 0);
5990 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
5991 goto illegal_op;
5992 } else {
5993 /* reg = PSR */
5994 rd = (insn >> 12) & 0xf;
5995 if (op1 & 2) {
5996 if (IS_USER(s))
5997 goto illegal_op;
5998 tmp = load_cpu_field(spsr);
5999 } else {
6000 tmp = new_tmp();
6001 gen_helper_cpsr_read(tmp);
6003 store_reg(s, rd, tmp);
6005 break;
6006 case 0x1:
6007 if (op1 == 1) {
6008 /* branch/exchange thumb (bx). */
6009 tmp = load_reg(s, rm);
6010 gen_bx(s, tmp);
6011 } else if (op1 == 3) {
6012 /* clz */
6013 rd = (insn >> 12) & 0xf;
6014 tmp = load_reg(s, rm);
6015 gen_helper_clz(tmp, tmp);
6016 store_reg(s, rd, tmp);
6017 } else {
6018 goto illegal_op;
6020 break;
6021 case 0x2:
6022 if (op1 == 1) {
6023 ARCH(5J); /* bxj */
6024 /* Trivial implementation equivalent to bx. */
6025 tmp = load_reg(s, rm);
6026 gen_bx(s, tmp);
6027 } else {
6028 goto illegal_op;
6030 break;
6031 case 0x3:
6032 if (op1 != 1)
6033 goto illegal_op;
6035 /* branch link/exchange thumb (blx) */
6036 tmp = load_reg(s, rm);
6037 tmp2 = new_tmp();
6038 tcg_gen_movi_i32(tmp2, s->pc);
6039 store_reg(s, 14, tmp2);
6040 gen_bx(s, tmp);
6041 break;
6042 case 0x5: /* saturating add/subtract */
6043 rd = (insn >> 12) & 0xf;
6044 rn = (insn >> 16) & 0xf;
6045 tmp = load_reg(s, rm);
6046 tmp2 = load_reg(s, rn);
6047 if (op1 & 2)
6048 gen_helper_double_saturate(tmp2, tmp2);
6049 if (op1 & 1)
6050 gen_helper_sub_saturate(tmp, tmp, tmp2);
6051 else
6052 gen_helper_add_saturate(tmp, tmp, tmp2);
6053 dead_tmp(tmp2);
6054 store_reg(s, rd, tmp);
6055 break;
6056 case 7: /* bkpt */
6057 gen_set_condexec(s);
6058 gen_set_pc_im(s->pc - 4);
6059 gen_exception(EXCP_BKPT);
6060 s->is_jmp = DISAS_JUMP;
6061 break;
6062 case 0x8: /* signed multiply */
6063 case 0xa:
6064 case 0xc:
6065 case 0xe:
6066 rs = (insn >> 8) & 0xf;
6067 rn = (insn >> 12) & 0xf;
6068 rd = (insn >> 16) & 0xf;
6069 if (op1 == 1) {
6070 /* (32 * 16) >> 16 */
6071 tmp = load_reg(s, rm);
6072 tmp2 = load_reg(s, rs);
6073 if (sh & 4)
6074 tcg_gen_sari_i32(tmp2, tmp2, 16);
6075 else
6076 gen_sxth(tmp2);
6077 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6078 tcg_gen_shri_i64(tmp64, tmp64, 16);
6079 tmp = new_tmp();
6080 tcg_gen_trunc_i64_i32(tmp, tmp64);
6081 tcg_temp_free_i64(tmp64);
6082 if ((sh & 2) == 0) {
6083 tmp2 = load_reg(s, rn);
6084 gen_helper_add_setq(tmp, tmp, tmp2);
6085 dead_tmp(tmp2);
6087 store_reg(s, rd, tmp);
6088 } else {
6089 /* 16 * 16 */
6090 tmp = load_reg(s, rm);
6091 tmp2 = load_reg(s, rs);
6092 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
6093 dead_tmp(tmp2);
6094 if (op1 == 2) {
6095 tmp64 = tcg_temp_new_i64();
6096 tcg_gen_ext_i32_i64(tmp64, tmp);
6097 dead_tmp(tmp);
6098 gen_addq(s, tmp64, rn, rd);
6099 gen_storeq_reg(s, rn, rd, tmp64);
6100 tcg_temp_free_i64(tmp64);
6101 } else {
6102 if (op1 == 0) {
6103 tmp2 = load_reg(s, rn);
6104 gen_helper_add_setq(tmp, tmp, tmp2);
6105 dead_tmp(tmp2);
6107 store_reg(s, rd, tmp);
6110 break;
6111 default:
6112 goto illegal_op;
6114 } else if (((insn & 0x0e000000) == 0 &&
6115 (insn & 0x00000090) != 0x90) ||
6116 ((insn & 0x0e000000) == (1 << 25))) {
6117 int set_cc, logic_cc, shiftop;
6119 op1 = (insn >> 21) & 0xf;
6120 set_cc = (insn >> 20) & 1;
6121 logic_cc = table_logic_cc[op1] & set_cc;
6123 /* data processing instruction */
6124 if (insn & (1 << 25)) {
6125 /* immediate operand */
6126 val = insn & 0xff;
6127 shift = ((insn >> 8) & 0xf) * 2;
6128 if (shift) {
6129 val = (val >> shift) | (val << (32 - shift));
6131 tmp2 = new_tmp();
6132 tcg_gen_movi_i32(tmp2, val);
6133 if (logic_cc && shift) {
6134 gen_set_CF_bit31(tmp2);
6136 } else {
6137 /* register */
6138 rm = (insn) & 0xf;
6139 tmp2 = load_reg(s, rm);
6140 shiftop = (insn >> 5) & 3;
6141 if (!(insn & (1 << 4))) {
6142 shift = (insn >> 7) & 0x1f;
6143 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
6144 } else {
6145 rs = (insn >> 8) & 0xf;
6146 tmp = load_reg(s, rs);
6147 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
6150 if (op1 != 0x0f && op1 != 0x0d) {
6151 rn = (insn >> 16) & 0xf;
6152 tmp = load_reg(s, rn);
6153 } else {
6154 TCGV_UNUSED(tmp);
6156 rd = (insn >> 12) & 0xf;
6157 switch(op1) {
6158 case 0x00:
6159 tcg_gen_and_i32(tmp, tmp, tmp2);
6160 if (logic_cc) {
6161 gen_logic_CC(tmp);
6163 store_reg_bx(env, s, rd, tmp);
6164 break;
6165 case 0x01:
6166 tcg_gen_xor_i32(tmp, tmp, tmp2);
6167 if (logic_cc) {
6168 gen_logic_CC(tmp);
6170 store_reg_bx(env, s, rd, tmp);
6171 break;
6172 case 0x02:
6173 if (set_cc && rd == 15) {
6174 /* SUBS r15, ... is used for exception return. */
6175 if (IS_USER(s)) {
6176 goto illegal_op;
6178 gen_helper_sub_cc(tmp, tmp, tmp2);
6179 gen_exception_return(s, tmp);
6180 } else {
6181 if (set_cc) {
6182 gen_helper_sub_cc(tmp, tmp, tmp2);
6183 } else {
6184 tcg_gen_sub_i32(tmp, tmp, tmp2);
6186 store_reg_bx(env, s, rd, tmp);
6188 break;
6189 case 0x03:
6190 if (set_cc) {
6191 gen_helper_sub_cc(tmp, tmp2, tmp);
6192 } else {
6193 tcg_gen_sub_i32(tmp, tmp2, tmp);
6195 store_reg_bx(env, s, rd, tmp);
6196 break;
6197 case 0x04:
6198 if (set_cc) {
6199 gen_helper_add_cc(tmp, tmp, tmp2);
6200 } else {
6201 tcg_gen_add_i32(tmp, tmp, tmp2);
6203 store_reg_bx(env, s, rd, tmp);
6204 break;
6205 case 0x05:
6206 if (set_cc) {
6207 gen_helper_adc_cc(tmp, tmp, tmp2);
6208 } else {
6209 gen_add_carry(tmp, tmp, tmp2);
6211 store_reg_bx(env, s, rd, tmp);
6212 break;
6213 case 0x06:
6214 if (set_cc) {
6215 gen_helper_sbc_cc(tmp, tmp, tmp2);
6216 } else {
6217 gen_sub_carry(tmp, tmp, tmp2);
6219 store_reg_bx(env, s, rd, tmp);
6220 break;
6221 case 0x07:
6222 if (set_cc) {
6223 gen_helper_sbc_cc(tmp, tmp2, tmp);
6224 } else {
6225 gen_sub_carry(tmp, tmp2, tmp);
6227 store_reg_bx(env, s, rd, tmp);
6228 break;
6229 case 0x08:
6230 if (set_cc) {
6231 tcg_gen_and_i32(tmp, tmp, tmp2);
6232 gen_logic_CC(tmp);
6234 dead_tmp(tmp);
6235 break;
6236 case 0x09:
6237 if (set_cc) {
6238 tcg_gen_xor_i32(tmp, tmp, tmp2);
6239 gen_logic_CC(tmp);
6241 dead_tmp(tmp);
6242 break;
6243 case 0x0a:
6244 if (set_cc) {
6245 gen_helper_sub_cc(tmp, tmp, tmp2);
6247 dead_tmp(tmp);
6248 break;
6249 case 0x0b:
6250 if (set_cc) {
6251 gen_helper_add_cc(tmp, tmp, tmp2);
6253 dead_tmp(tmp);
6254 break;
6255 case 0x0c:
6256 tcg_gen_or_i32(tmp, tmp, tmp2);
6257 if (logic_cc) {
6258 gen_logic_CC(tmp);
6260 store_reg_bx(env, s, rd, tmp);
6261 break;
6262 case 0x0d:
6263 if (logic_cc && rd == 15) {
6264 /* MOVS r15, ... is used for exception return. */
6265 if (IS_USER(s)) {
6266 goto illegal_op;
6268 gen_exception_return(s, tmp2);
6269 } else {
6270 if (logic_cc) {
6271 gen_logic_CC(tmp2);
6273 store_reg_bx(env, s, rd, tmp2);
6275 break;
6276 case 0x0e:
6277 tcg_gen_bic_i32(tmp, tmp, tmp2);
6278 if (logic_cc) {
6279 gen_logic_CC(tmp);
6281 store_reg_bx(env, s, rd, tmp);
6282 break;
6283 default:
6284 case 0x0f:
6285 tcg_gen_not_i32(tmp2, tmp2);
6286 if (logic_cc) {
6287 gen_logic_CC(tmp2);
6289 store_reg_bx(env, s, rd, tmp2);
6290 break;
6292 if (op1 != 0x0f && op1 != 0x0d) {
6293 dead_tmp(tmp2);
6295 } else {
6296 /* other instructions */
6297 op1 = (insn >> 24) & 0xf;
6298 switch(op1) {
6299 case 0x0:
6300 case 0x1:
6301 /* multiplies, extra load/stores */
6302 sh = (insn >> 5) & 3;
6303 if (sh == 0) {
6304 if (op1 == 0x0) {
6305 rd = (insn >> 16) & 0xf;
6306 rn = (insn >> 12) & 0xf;
6307 rs = (insn >> 8) & 0xf;
6308 rm = (insn) & 0xf;
6309 op1 = (insn >> 20) & 0xf;
6310 switch (op1) {
6311 case 0: case 1: case 2: case 3: case 6:
6312 /* 32 bit mul */
6313 tmp = load_reg(s, rs);
6314 tmp2 = load_reg(s, rm);
6315 tcg_gen_mul_i32(tmp, tmp, tmp2);
6316 dead_tmp(tmp2);
6317 if (insn & (1 << 22)) {
6318 /* Subtract (mls) */
6319 ARCH(6T2);
6320 tmp2 = load_reg(s, rn);
6321 tcg_gen_sub_i32(tmp, tmp2, tmp);
6322 dead_tmp(tmp2);
6323 } else if (insn & (1 << 21)) {
6324 /* Add */
6325 tmp2 = load_reg(s, rn);
6326 tcg_gen_add_i32(tmp, tmp, tmp2);
6327 dead_tmp(tmp2);
6329 if (insn & (1 << 20))
6330 gen_logic_CC(tmp);
6331 store_reg(s, rd, tmp);
6332 break;
6333 default:
6334 /* 64 bit mul */
6335 tmp = load_reg(s, rs);
6336 tmp2 = load_reg(s, rm);
6337 if (insn & (1 << 22))
6338 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6339 else
6340 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
6341 if (insn & (1 << 21)) /* mult accumulate */
6342 gen_addq(s, tmp64, rn, rd);
6343 if (!(insn & (1 << 23))) { /* double accumulate */
6344 ARCH(6);
6345 gen_addq_lo(s, tmp64, rn);
6346 gen_addq_lo(s, tmp64, rd);
6348 if (insn & (1 << 20))
6349 gen_logicq_cc(tmp64);
6350 gen_storeq_reg(s, rn, rd, tmp64);
6351 tcg_temp_free_i64(tmp64);
6352 break;
6354 } else {
6355 rn = (insn >> 16) & 0xf;
6356 rd = (insn >> 12) & 0xf;
6357 if (insn & (1 << 23)) {
6358 /* load/store exclusive */
6359 op1 = (insn >> 21) & 0x3;
6360 if (op1)
6361 ARCH(6K);
6362 else
6363 ARCH(6);
6364 addr = tcg_temp_local_new_i32();
6365 load_reg_var(s, addr, rn);
6366 if (insn & (1 << 20)) {
6367 gen_helper_mark_exclusive(cpu_env, addr);
6368 switch (op1) {
6369 case 0: /* ldrex */
6370 tmp = gen_ld32(addr, IS_USER(s));
6371 break;
6372 case 1: /* ldrexd */
6373 tmp = gen_ld32(addr, IS_USER(s));
6374 store_reg(s, rd, tmp);
6375 tcg_gen_addi_i32(addr, addr, 4);
6376 tmp = gen_ld32(addr, IS_USER(s));
6377 rd++;
6378 break;
6379 case 2: /* ldrexb */
6380 tmp = gen_ld8u(addr, IS_USER(s));
6381 break;
6382 case 3: /* ldrexh */
6383 tmp = gen_ld16u(addr, IS_USER(s));
6384 break;
6385 default:
6386 abort();
6388 store_reg(s, rd, tmp);
6389 } else {
6390 int label = gen_new_label();
6391 rm = insn & 0xf;
6392 tmp2 = tcg_temp_local_new_i32();
6393 gen_helper_test_exclusive(tmp2, cpu_env, addr);
6394 tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label);
6395 tmp = load_reg(s,rm);
6396 switch (op1) {
6397 case 0: /* strex */
6398 gen_st32(tmp, addr, IS_USER(s));
6399 break;
6400 case 1: /* strexd */
6401 gen_st32(tmp, addr, IS_USER(s));
6402 tcg_gen_addi_i32(addr, addr, 4);
6403 tmp = load_reg(s, rm + 1);
6404 gen_st32(tmp, addr, IS_USER(s));
6405 break;
6406 case 2: /* strexb */
6407 gen_st8(tmp, addr, IS_USER(s));
6408 break;
6409 case 3: /* strexh */
6410 gen_st16(tmp, addr, IS_USER(s));
6411 break;
6412 default:
6413 abort();
6415 gen_set_label(label);
6416 tcg_gen_mov_i32(cpu_R[rd], tmp2);
6417 tcg_temp_free(tmp2);
6419 tcg_temp_free(addr);
6420 } else {
6421 /* SWP instruction */
6422 rm = (insn) & 0xf;
6424 /* ??? This is not really atomic. However we know
6425 we never have multiple CPUs running in parallel,
6426 so it is good enough. */
6427 addr = load_reg(s, rn);
6428 tmp = load_reg(s, rm);
6429 if (insn & (1 << 22)) {
6430 tmp2 = gen_ld8u(addr, IS_USER(s));
6431 gen_st8(tmp, addr, IS_USER(s));
6432 } else {
6433 tmp2 = gen_ld32(addr, IS_USER(s));
6434 gen_st32(tmp, addr, IS_USER(s));
6436 dead_tmp(addr);
6437 store_reg(s, rd, tmp2);
6440 } else {
6441 int address_offset;
6442 int load;
6443 /* Misc load/store */
6444 rn = (insn >> 16) & 0xf;
6445 rd = (insn >> 12) & 0xf;
6446 addr = load_reg(s, rn);
6447 if (insn & (1 << 24))
6448 gen_add_datah_offset(s, insn, 0, addr);
6449 address_offset = 0;
6450 if (insn & (1 << 20)) {
6451 /* load */
6452 switch(sh) {
6453 case 1:
6454 tmp = gen_ld16u(addr, IS_USER(s));
6455 break;
6456 case 2:
6457 tmp = gen_ld8s(addr, IS_USER(s));
6458 break;
6459 default:
6460 case 3:
6461 tmp = gen_ld16s(addr, IS_USER(s));
6462 break;
6464 load = 1;
6465 } else if (sh & 2) {
6466 /* doubleword */
6467 if (sh & 1) {
6468 /* store */
6469 tmp = load_reg(s, rd);
6470 gen_st32(tmp, addr, IS_USER(s));
6471 tcg_gen_addi_i32(addr, addr, 4);
6472 tmp = load_reg(s, rd + 1);
6473 gen_st32(tmp, addr, IS_USER(s));
6474 load = 0;
6475 } else {
6476 /* load */
6477 tmp = gen_ld32(addr, IS_USER(s));
6478 store_reg(s, rd, tmp);
6479 tcg_gen_addi_i32(addr, addr, 4);
6480 tmp = gen_ld32(addr, IS_USER(s));
6481 rd++;
6482 load = 1;
6484 address_offset = -4;
6485 } else {
6486 /* store */
6487 tmp = load_reg(s, rd);
6488 gen_st16(tmp, addr, IS_USER(s));
6489 load = 0;
6491 /* Perform base writeback before the loaded value to
6492 ensure correct behavior with overlapping index registers.
6493 ldrd with base writeback is is undefined if the
6494 destination and index registers overlap. */
6495 if (!(insn & (1 << 24))) {
6496 gen_add_datah_offset(s, insn, address_offset, addr);
6497 store_reg(s, rn, addr);
6498 } else if (insn & (1 << 21)) {
6499 if (address_offset)
6500 tcg_gen_addi_i32(addr, addr, address_offset);
6501 store_reg(s, rn, addr);
6502 } else {
6503 dead_tmp(addr);
6505 if (load) {
6506 /* Complete the load. */
6507 store_reg(s, rd, tmp);
6510 break;
6511 case 0x4:
6512 case 0x5:
6513 goto do_ldst;
6514 case 0x6:
6515 case 0x7:
6516 if (insn & (1 << 4)) {
6517 ARCH(6);
6518 /* Armv6 Media instructions. */
6519 rm = insn & 0xf;
6520 rn = (insn >> 16) & 0xf;
6521 rd = (insn >> 12) & 0xf;
6522 rs = (insn >> 8) & 0xf;
6523 switch ((insn >> 23) & 3) {
6524 case 0: /* Parallel add/subtract. */
6525 op1 = (insn >> 20) & 7;
6526 tmp = load_reg(s, rn);
6527 tmp2 = load_reg(s, rm);
6528 sh = (insn >> 5) & 7;
6529 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
6530 goto illegal_op;
6531 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
6532 dead_tmp(tmp2);
6533 store_reg(s, rd, tmp);
6534 break;
6535 case 1:
6536 if ((insn & 0x00700020) == 0) {
6537 /* Halfword pack. */
6538 tmp = load_reg(s, rn);
6539 tmp2 = load_reg(s, rm);
6540 shift = (insn >> 7) & 0x1f;
6541 if (insn & (1 << 6)) {
6542 /* pkhtb */
6543 if (shift == 0)
6544 shift = 31;
6545 tcg_gen_sari_i32(tmp2, tmp2, shift);
6546 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
6547 tcg_gen_ext16u_i32(tmp2, tmp2);
6548 } else {
6549 /* pkhbt */
6550 if (shift)
6551 tcg_gen_shli_i32(tmp2, tmp2, shift);
6552 tcg_gen_ext16u_i32(tmp, tmp);
6553 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
6555 tcg_gen_or_i32(tmp, tmp, tmp2);
6556 dead_tmp(tmp2);
6557 store_reg(s, rd, tmp);
6558 } else if ((insn & 0x00200020) == 0x00200000) {
6559 /* [us]sat */
6560 tmp = load_reg(s, rm);
6561 shift = (insn >> 7) & 0x1f;
6562 if (insn & (1 << 6)) {
6563 if (shift == 0)
6564 shift = 31;
6565 tcg_gen_sari_i32(tmp, tmp, shift);
6566 } else {
6567 tcg_gen_shli_i32(tmp, tmp, shift);
6569 sh = (insn >> 16) & 0x1f;
6570 if (sh != 0) {
6571 tmp2 = tcg_const_i32(sh);
6572 if (insn & (1 << 22))
6573 gen_helper_usat(tmp, tmp, tmp2);
6574 else
6575 gen_helper_ssat(tmp, tmp, tmp2);
6576 tcg_temp_free_i32(tmp2);
6578 store_reg(s, rd, tmp);
6579 } else if ((insn & 0x00300fe0) == 0x00200f20) {
6580 /* [us]sat16 */
6581 tmp = load_reg(s, rm);
6582 sh = (insn >> 16) & 0x1f;
6583 if (sh != 0) {
6584 tmp2 = tcg_const_i32(sh);
6585 if (insn & (1 << 22))
6586 gen_helper_usat16(tmp, tmp, tmp2);
6587 else
6588 gen_helper_ssat16(tmp, tmp, tmp2);
6589 tcg_temp_free_i32(tmp2);
6591 store_reg(s, rd, tmp);
6592 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
6593 /* Select bytes. */
6594 tmp = load_reg(s, rn);
6595 tmp2 = load_reg(s, rm);
6596 tmp3 = new_tmp();
6597 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
6598 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
6599 dead_tmp(tmp3);
6600 dead_tmp(tmp2);
6601 store_reg(s, rd, tmp);
6602 } else if ((insn & 0x000003e0) == 0x00000060) {
6603 tmp = load_reg(s, rm);
6604 shift = (insn >> 10) & 3;
6605 /* ??? In many cases it's not neccessary to do a
6606 rotate, a shift is sufficient. */
6607 if (shift != 0)
6608 tcg_gen_rori_i32(tmp, tmp, shift * 8);
6609 op1 = (insn >> 20) & 7;
6610 switch (op1) {
6611 case 0: gen_sxtb16(tmp); break;
6612 case 2: gen_sxtb(tmp); break;
6613 case 3: gen_sxth(tmp); break;
6614 case 4: gen_uxtb16(tmp); break;
6615 case 6: gen_uxtb(tmp); break;
6616 case 7: gen_uxth(tmp); break;
6617 default: goto illegal_op;
6619 if (rn != 15) {
6620 tmp2 = load_reg(s, rn);
6621 if ((op1 & 3) == 0) {
6622 gen_add16(tmp, tmp2);
6623 } else {
6624 tcg_gen_add_i32(tmp, tmp, tmp2);
6625 dead_tmp(tmp2);
6628 store_reg(s, rd, tmp);
6629 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
6630 /* rev */
6631 tmp = load_reg(s, rm);
6632 if (insn & (1 << 22)) {
6633 if (insn & (1 << 7)) {
6634 gen_revsh(tmp);
6635 } else {
6636 ARCH(6T2);
6637 gen_helper_rbit(tmp, tmp);
6639 } else {
6640 if (insn & (1 << 7))
6641 gen_rev16(tmp);
6642 else
6643 tcg_gen_bswap32_i32(tmp, tmp);
6645 store_reg(s, rd, tmp);
6646 } else {
6647 goto illegal_op;
6649 break;
6650 case 2: /* Multiplies (Type 3). */
6651 tmp = load_reg(s, rm);
6652 tmp2 = load_reg(s, rs);
6653 if (insn & (1 << 20)) {
6654 /* Signed multiply most significant [accumulate]. */
6655 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6656 if (insn & (1 << 5))
6657 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
6658 tcg_gen_shri_i64(tmp64, tmp64, 32);
6659 tmp = new_tmp();
6660 tcg_gen_trunc_i64_i32(tmp, tmp64);
6661 tcg_temp_free_i64(tmp64);
6662 if (rd != 15) {
6663 tmp2 = load_reg(s, rd);
6664 if (insn & (1 << 6)) {
6665 tcg_gen_sub_i32(tmp, tmp, tmp2);
6666 } else {
6667 tcg_gen_add_i32(tmp, tmp, tmp2);
6669 dead_tmp(tmp2);
6671 store_reg(s, rn, tmp);
6672 } else {
6673 if (insn & (1 << 5))
6674 gen_swap_half(tmp2);
6675 gen_smul_dual(tmp, tmp2);
6676 /* This addition cannot overflow. */
6677 if (insn & (1 << 6)) {
6678 tcg_gen_sub_i32(tmp, tmp, tmp2);
6679 } else {
6680 tcg_gen_add_i32(tmp, tmp, tmp2);
6682 dead_tmp(tmp2);
6683 if (insn & (1 << 22)) {
6684 /* smlald, smlsld */
6685 tmp64 = tcg_temp_new_i64();
6686 tcg_gen_ext_i32_i64(tmp64, tmp);
6687 dead_tmp(tmp);
6688 gen_addq(s, tmp64, rd, rn);
6689 gen_storeq_reg(s, rd, rn, tmp64);
6690 tcg_temp_free_i64(tmp64);
6691 } else {
6692 /* smuad, smusd, smlad, smlsd */
6693 if (rd != 15)
6695 tmp2 = load_reg(s, rd);
6696 gen_helper_add_setq(tmp, tmp, tmp2);
6697 dead_tmp(tmp2);
6699 store_reg(s, rn, tmp);
6702 break;
6703 case 3:
6704 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
6705 switch (op1) {
6706 case 0: /* Unsigned sum of absolute differences. */
6707 ARCH(6);
6708 tmp = load_reg(s, rm);
6709 tmp2 = load_reg(s, rs);
6710 gen_helper_usad8(tmp, tmp, tmp2);
6711 dead_tmp(tmp2);
6712 if (rd != 15) {
6713 tmp2 = load_reg(s, rd);
6714 tcg_gen_add_i32(tmp, tmp, tmp2);
6715 dead_tmp(tmp2);
6717 store_reg(s, rn, tmp);
6718 break;
6719 case 0x20: case 0x24: case 0x28: case 0x2c:
6720 /* Bitfield insert/clear. */
6721 ARCH(6T2);
6722 shift = (insn >> 7) & 0x1f;
6723 i = (insn >> 16) & 0x1f;
6724 i = i + 1 - shift;
6725 if (rm == 15) {
6726 tmp = new_tmp();
6727 tcg_gen_movi_i32(tmp, 0);
6728 } else {
6729 tmp = load_reg(s, rm);
6731 if (i != 32) {
6732 tmp2 = load_reg(s, rd);
6733 gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
6734 dead_tmp(tmp2);
6736 store_reg(s, rd, tmp);
6737 break;
6738 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6739 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6740 ARCH(6T2);
6741 tmp = load_reg(s, rm);
6742 shift = (insn >> 7) & 0x1f;
6743 i = ((insn >> 16) & 0x1f) + 1;
6744 if (shift + i > 32)
6745 goto illegal_op;
6746 if (i < 32) {
6747 if (op1 & 0x20) {
6748 gen_ubfx(tmp, shift, (1u << i) - 1);
6749 } else {
6750 gen_sbfx(tmp, shift, i);
6753 store_reg(s, rd, tmp);
6754 break;
6755 default:
6756 goto illegal_op;
6758 break;
6760 break;
6762 do_ldst:
6763 /* Check for undefined extension instructions
6764 * per the ARM Bible IE:
6765 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6767 sh = (0xf << 20) | (0xf << 4);
6768 if (op1 == 0x7 && ((insn & sh) == sh))
6770 goto illegal_op;
6772 /* load/store byte/word */
6773 rn = (insn >> 16) & 0xf;
6774 rd = (insn >> 12) & 0xf;
6775 tmp2 = load_reg(s, rn);
6776 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
6777 if (insn & (1 << 24))
6778 gen_add_data_offset(s, insn, tmp2);
6779 if (insn & (1 << 20)) {
6780 /* load */
6781 if (insn & (1 << 22)) {
6782 tmp = gen_ld8u(tmp2, i);
6783 } else {
6784 tmp = gen_ld32(tmp2, i);
6786 } else {
6787 /* store */
6788 tmp = load_reg(s, rd);
6789 if (insn & (1 << 22))
6790 gen_st8(tmp, tmp2, i);
6791 else
6792 gen_st32(tmp, tmp2, i);
6794 if (!(insn & (1 << 24))) {
6795 gen_add_data_offset(s, insn, tmp2);
6796 store_reg(s, rn, tmp2);
6797 } else if (insn & (1 << 21)) {
6798 store_reg(s, rn, tmp2);
6799 } else {
6800 dead_tmp(tmp2);
6802 if (insn & (1 << 20)) {
6803 /* Complete the load. */
6804 if (rd == 15)
6805 gen_bx(s, tmp);
6806 else
6807 store_reg(s, rd, tmp);
6809 break;
6810 case 0x08:
6811 case 0x09:
6813 int j, n, user, loaded_base;
6814 TCGv loaded_var;
6815 /* load/store multiple words */
6816 /* XXX: store correct base if write back */
6817 user = 0;
6818 if (insn & (1 << 22)) {
6819 if (IS_USER(s))
6820 goto illegal_op; /* only usable in supervisor mode */
6822 if ((insn & (1 << 15)) == 0)
6823 user = 1;
6825 rn = (insn >> 16) & 0xf;
6826 addr = load_reg(s, rn);
6828 /* compute total size */
6829 loaded_base = 0;
6830 TCGV_UNUSED(loaded_var);
6831 n = 0;
6832 for(i=0;i<16;i++) {
6833 if (insn & (1 << i))
6834 n++;
6836 /* XXX: test invalid n == 0 case ? */
6837 if (insn & (1 << 23)) {
6838 if (insn & (1 << 24)) {
6839 /* pre increment */
6840 tcg_gen_addi_i32(addr, addr, 4);
6841 } else {
6842 /* post increment */
6844 } else {
6845 if (insn & (1 << 24)) {
6846 /* pre decrement */
6847 tcg_gen_addi_i32(addr, addr, -(n * 4));
6848 } else {
6849 /* post decrement */
6850 if (n != 1)
6851 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6854 j = 0;
6855 for(i=0;i<16;i++) {
6856 if (insn & (1 << i)) {
6857 if (insn & (1 << 20)) {
6858 /* load */
6859 tmp = gen_ld32(addr, IS_USER(s));
6860 if (i == 15) {
6861 gen_bx(s, tmp);
6862 } else if (user) {
6863 tmp2 = tcg_const_i32(i);
6864 gen_helper_set_user_reg(tmp2, tmp);
6865 tcg_temp_free_i32(tmp2);
6866 dead_tmp(tmp);
6867 } else if (i == rn) {
6868 loaded_var = tmp;
6869 loaded_base = 1;
6870 } else {
6871 store_reg(s, i, tmp);
6873 } else {
6874 /* store */
6875 if (i == 15) {
6876 /* special case: r15 = PC + 8 */
6877 val = (long)s->pc + 4;
6878 tmp = new_tmp();
6879 tcg_gen_movi_i32(tmp, val);
6880 } else if (user) {
6881 tmp = new_tmp();
6882 tmp2 = tcg_const_i32(i);
6883 gen_helper_get_user_reg(tmp, tmp2);
6884 tcg_temp_free_i32(tmp2);
6885 } else {
6886 tmp = load_reg(s, i);
6888 gen_st32(tmp, addr, IS_USER(s));
6890 j++;
6891 /* no need to add after the last transfer */
6892 if (j != n)
6893 tcg_gen_addi_i32(addr, addr, 4);
6896 if (insn & (1 << 21)) {
6897 /* write back */
6898 if (insn & (1 << 23)) {
6899 if (insn & (1 << 24)) {
6900 /* pre increment */
6901 } else {
6902 /* post increment */
6903 tcg_gen_addi_i32(addr, addr, 4);
6905 } else {
6906 if (insn & (1 << 24)) {
6907 /* pre decrement */
6908 if (n != 1)
6909 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6910 } else {
6911 /* post decrement */
6912 tcg_gen_addi_i32(addr, addr, -(n * 4));
6915 store_reg(s, rn, addr);
6916 } else {
6917 dead_tmp(addr);
6919 if (loaded_base) {
6920 store_reg(s, rn, loaded_var);
6922 if ((insn & (1 << 22)) && !user) {
6923 /* Restore CPSR from SPSR. */
6924 tmp = load_cpu_field(spsr);
6925 gen_set_cpsr(tmp, 0xffffffff);
6926 dead_tmp(tmp);
6927 s->is_jmp = DISAS_UPDATE;
6930 break;
6931 case 0xa:
6932 case 0xb:
6934 int32_t offset;
6936 /* branch (and link) */
6937 val = (int32_t)s->pc;
6938 if (insn & (1 << 24)) {
6939 tmp = new_tmp();
6940 tcg_gen_movi_i32(tmp, val);
6941 store_reg(s, 14, tmp);
6943 offset = (((int32_t)insn << 8) >> 8);
6944 val += (offset << 2) + 4;
6945 gen_jmp(s, val);
6947 break;
6948 case 0xc:
6949 case 0xd:
6950 case 0xe:
6951 /* Coprocessor. */
6952 if (disas_coproc_insn(env, s, insn))
6953 goto illegal_op;
6954 break;
6955 case 0xf:
6956 /* swi */
6957 gen_set_pc_im(s->pc);
6958 s->is_jmp = DISAS_SWI;
6959 break;
6960 default:
6961 illegal_op:
6962 gen_set_condexec(s);
6963 gen_set_pc_im(s->pc - 4);
6964 gen_exception(EXCP_UDEF);
6965 s->is_jmp = DISAS_JUMP;
6966 break;
6971 /* Return true if this is a Thumb-2 logical op. */
6972 static int
6973 thumb2_logic_op(int op)
6975 return (op < 8);
6978 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
6979 then set condition code flags based on the result of the operation.
6980 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
6981 to the high bit of T1.
6982 Returns zero if the opcode is valid. */
6984 static int
6985 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCGv t0, TCGv t1)
6987 int logic_cc;
6989 logic_cc = 0;
6990 switch (op) {
6991 case 0: /* and */
6992 tcg_gen_and_i32(t0, t0, t1);
6993 logic_cc = conds;
6994 break;
6995 case 1: /* bic */
6996 tcg_gen_bic_i32(t0, t0, t1);
6997 logic_cc = conds;
6998 break;
6999 case 2: /* orr */
7000 tcg_gen_or_i32(t0, t0, t1);
7001 logic_cc = conds;
7002 break;
7003 case 3: /* orn */
7004 tcg_gen_not_i32(t1, t1);
7005 tcg_gen_or_i32(t0, t0, t1);
7006 logic_cc = conds;
7007 break;
7008 case 4: /* eor */
7009 tcg_gen_xor_i32(t0, t0, t1);
7010 logic_cc = conds;
7011 break;
7012 case 8: /* add */
7013 if (conds)
7014 gen_helper_add_cc(t0, t0, t1);
7015 else
7016 tcg_gen_add_i32(t0, t0, t1);
7017 break;
7018 case 10: /* adc */
7019 if (conds)
7020 gen_helper_adc_cc(t0, t0, t1);
7021 else
7022 gen_adc(t0, t1);
7023 break;
7024 case 11: /* sbc */
7025 if (conds)
7026 gen_helper_sbc_cc(t0, t0, t1);
7027 else
7028 gen_sub_carry(t0, t0, t1);
7029 break;
7030 case 13: /* sub */
7031 if (conds)
7032 gen_helper_sub_cc(t0, t0, t1);
7033 else
7034 tcg_gen_sub_i32(t0, t0, t1);
7035 break;
7036 case 14: /* rsb */
7037 if (conds)
7038 gen_helper_sub_cc(t0, t1, t0);
7039 else
7040 tcg_gen_sub_i32(t0, t1, t0);
7041 break;
7042 default: /* 5, 6, 7, 9, 12, 15. */
7043 return 1;
7045 if (logic_cc) {
7046 gen_logic_CC(t0);
7047 if (shifter_out)
7048 gen_set_CF_bit31(t1);
7050 return 0;
7053 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7054 is not legal. */
7055 static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7057 uint32_t insn, imm, shift, offset;
7058 uint32_t rd, rn, rm, rs;
7059 TCGv tmp;
7060 TCGv tmp2;
7061 TCGv tmp3;
7062 TCGv addr;
7063 TCGv_i64 tmp64;
7064 int op;
7065 int shiftop;
7066 int conds;
7067 int logic_cc;
7069 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
7070 || arm_feature (env, ARM_FEATURE_M))) {
7071 /* Thumb-1 cores may need to treat bl and blx as a pair of
7072 16-bit instructions to get correct prefetch abort behavior. */
7073 insn = insn_hw1;
7074 if ((insn & (1 << 12)) == 0) {
7075 /* Second half of blx. */
7076 offset = ((insn & 0x7ff) << 1);
7077 tmp = load_reg(s, 14);
7078 tcg_gen_addi_i32(tmp, tmp, offset);
7079 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
7081 tmp2 = new_tmp();
7082 tcg_gen_movi_i32(tmp2, s->pc | 1);
7083 store_reg(s, 14, tmp2);
7084 gen_bx(s, tmp);
7085 return 0;
7087 if (insn & (1 << 11)) {
7088 /* Second half of bl. */
7089 offset = ((insn & 0x7ff) << 1) | 1;
7090 tmp = load_reg(s, 14);
7091 tcg_gen_addi_i32(tmp, tmp, offset);
7093 tmp2 = new_tmp();
7094 tcg_gen_movi_i32(tmp2, s->pc | 1);
7095 store_reg(s, 14, tmp2);
7096 gen_bx(s, tmp);
7097 return 0;
7099 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
7100 /* Instruction spans a page boundary. Implement it as two
7101 16-bit instructions in case the second half causes an
7102 prefetch abort. */
7103 offset = ((int32_t)insn << 21) >> 9;
7104 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
7105 return 0;
7107 /* Fall through to 32-bit decode. */
7110 insn = lduw_code(s->pc);
7111 s->pc += 2;
7112 insn |= (uint32_t)insn_hw1 << 16;
7114 if ((insn & 0xf800e800) != 0xf000e800) {
7115 ARCH(6T2);
7118 rn = (insn >> 16) & 0xf;
7119 rs = (insn >> 12) & 0xf;
7120 rd = (insn >> 8) & 0xf;
7121 rm = insn & 0xf;
7122 switch ((insn >> 25) & 0xf) {
7123 case 0: case 1: case 2: case 3:
7124 /* 16-bit instructions. Should never happen. */
7125 abort();
7126 case 4:
7127 if (insn & (1 << 22)) {
7128 /* Other load/store, table branch. */
7129 if (insn & 0x01200000) {
7130 /* Load/store doubleword. */
7131 if (rn == 15) {
7132 addr = new_tmp();
7133 tcg_gen_movi_i32(addr, s->pc & ~3);
7134 } else {
7135 addr = load_reg(s, rn);
7137 offset = (insn & 0xff) * 4;
7138 if ((insn & (1 << 23)) == 0)
7139 offset = -offset;
7140 if (insn & (1 << 24)) {
7141 tcg_gen_addi_i32(addr, addr, offset);
7142 offset = 0;
7144 if (insn & (1 << 20)) {
7145 /* ldrd */
7146 tmp = gen_ld32(addr, IS_USER(s));
7147 store_reg(s, rs, tmp);
7148 tcg_gen_addi_i32(addr, addr, 4);
7149 tmp = gen_ld32(addr, IS_USER(s));
7150 store_reg(s, rd, tmp);
7151 } else {
7152 /* strd */
7153 tmp = load_reg(s, rs);
7154 gen_st32(tmp, addr, IS_USER(s));
7155 tcg_gen_addi_i32(addr, addr, 4);
7156 tmp = load_reg(s, rd);
7157 gen_st32(tmp, addr, IS_USER(s));
7159 if (insn & (1 << 21)) {
7160 /* Base writeback. */
7161 if (rn == 15)
7162 goto illegal_op;
7163 tcg_gen_addi_i32(addr, addr, offset - 4);
7164 store_reg(s, rn, addr);
7165 } else {
7166 dead_tmp(addr);
7168 } else if ((insn & (1 << 23)) == 0) {
7169 /* Load/store exclusive word. */
7170 addr = tcg_temp_local_new();
7171 load_reg_var(s, addr, rn);
7172 if (insn & (1 << 20)) {
7173 gen_helper_mark_exclusive(cpu_env, addr);
7174 tmp = gen_ld32(addr, IS_USER(s));
7175 store_reg(s, rd, tmp);
7176 } else {
7177 int label = gen_new_label();
7178 tmp2 = tcg_temp_local_new();
7179 gen_helper_test_exclusive(tmp2, cpu_env, addr);
7180 tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label);
7181 tmp = load_reg(s, rs);
7182 gen_st32(tmp, addr, IS_USER(s));
7183 gen_set_label(label);
7184 tcg_gen_mov_i32(cpu_R[rd], tmp2);
7185 tcg_temp_free(tmp2);
7187 tcg_temp_free(addr);
7188 } else if ((insn & (1 << 6)) == 0) {
7189 /* Table Branch. */
7190 if (rn == 15) {
7191 addr = new_tmp();
7192 tcg_gen_movi_i32(addr, s->pc);
7193 } else {
7194 addr = load_reg(s, rn);
7196 tmp = load_reg(s, rm);
7197 tcg_gen_add_i32(addr, addr, tmp);
7198 if (insn & (1 << 4)) {
7199 /* tbh */
7200 tcg_gen_add_i32(addr, addr, tmp);
7201 dead_tmp(tmp);
7202 tmp = gen_ld16u(addr, IS_USER(s));
7203 } else { /* tbb */
7204 dead_tmp(tmp);
7205 tmp = gen_ld8u(addr, IS_USER(s));
7207 dead_tmp(addr);
7208 tcg_gen_shli_i32(tmp, tmp, 1);
7209 tcg_gen_addi_i32(tmp, tmp, s->pc);
7210 store_reg(s, 15, tmp);
7211 } else {
7212 /* Load/store exclusive byte/halfword/doubleword. */
7213 /* ??? These are not really atomic. However we know
7214 we never have multiple CPUs running in parallel,
7215 so it is good enough. */
7216 op = (insn >> 4) & 0x3;
7217 addr = tcg_temp_local_new();
7218 load_reg_var(s, addr, rn);
7219 if (insn & (1 << 20)) {
7220 gen_helper_mark_exclusive(cpu_env, addr);
7221 switch (op) {
7222 case 0:
7223 tmp = gen_ld8u(addr, IS_USER(s));
7224 break;
7225 case 1:
7226 tmp = gen_ld16u(addr, IS_USER(s));
7227 break;
7228 case 3:
7229 tmp = gen_ld32(addr, IS_USER(s));
7230 tcg_gen_addi_i32(addr, addr, 4);
7231 tmp2 = gen_ld32(addr, IS_USER(s));
7232 store_reg(s, rd, tmp2);
7233 break;
7234 default:
7235 goto illegal_op;
7237 store_reg(s, rs, tmp);
7238 } else {
7239 int label = gen_new_label();
7240 tmp2 = tcg_temp_local_new();
7241 gen_helper_test_exclusive(tmp2, cpu_env, addr);
7242 tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label);
7243 tmp = load_reg(s, rs);
7244 switch (op) {
7245 case 0:
7246 gen_st8(tmp, addr, IS_USER(s));
7247 break;
7248 case 1:
7249 gen_st16(tmp, addr, IS_USER(s));
7250 break;
7251 case 3:
7252 gen_st32(tmp, addr, IS_USER(s));
7253 tcg_gen_addi_i32(addr, addr, 4);
7254 tmp = load_reg(s, rd);
7255 gen_st32(tmp, addr, IS_USER(s));
7256 break;
7257 default:
7258 goto illegal_op;
7260 gen_set_label(label);
7261 tcg_gen_mov_i32(cpu_R[rm], tmp2);
7262 tcg_temp_free(tmp2);
7264 tcg_temp_free(addr);
7266 } else {
7267 /* Load/store multiple, RFE, SRS. */
7268 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
7269 /* Not available in user mode. */
7270 if (IS_USER(s))
7271 goto illegal_op;
7272 if (insn & (1 << 20)) {
7273 /* rfe */
7274 addr = load_reg(s, rn);
7275 if ((insn & (1 << 24)) == 0)
7276 tcg_gen_addi_i32(addr, addr, -8);
7277 /* Load PC into tmp and CPSR into tmp2. */
7278 tmp = gen_ld32(addr, 0);
7279 tcg_gen_addi_i32(addr, addr, 4);
7280 tmp2 = gen_ld32(addr, 0);
7281 if (insn & (1 << 21)) {
7282 /* Base writeback. */
7283 if (insn & (1 << 24)) {
7284 tcg_gen_addi_i32(addr, addr, 4);
7285 } else {
7286 tcg_gen_addi_i32(addr, addr, -4);
7288 store_reg(s, rn, addr);
7289 } else {
7290 dead_tmp(addr);
7292 gen_rfe(s, tmp, tmp2);
7293 } else {
7294 /* srs */
7295 op = (insn & 0x1f);
7296 if (op == (env->uncached_cpsr & CPSR_M)) {
7297 addr = load_reg(s, 13);
7298 } else {
7299 addr = new_tmp();
7300 tmp = tcg_const_i32(op);
7301 gen_helper_get_r13_banked(addr, cpu_env, tmp);
7302 tcg_temp_free_i32(tmp);
7304 if ((insn & (1 << 24)) == 0) {
7305 tcg_gen_addi_i32(addr, addr, -8);
7307 tmp = load_reg(s, 14);
7308 gen_st32(tmp, addr, 0);
7309 tcg_gen_addi_i32(addr, addr, 4);
7310 tmp = new_tmp();
7311 gen_helper_cpsr_read(tmp);
7312 gen_st32(tmp, addr, 0);
7313 if (insn & (1 << 21)) {
7314 if ((insn & (1 << 24)) == 0) {
7315 tcg_gen_addi_i32(addr, addr, -4);
7316 } else {
7317 tcg_gen_addi_i32(addr, addr, 4);
7319 if (op == (env->uncached_cpsr & CPSR_M)) {
7320 store_reg(s, 13, addr);
7321 } else {
7322 tmp = tcg_const_i32(op);
7323 gen_helper_set_r13_banked(cpu_env, tmp, addr);
7324 tcg_temp_free_i32(tmp);
7326 } else {
7327 dead_tmp(addr);
7330 } else {
7331 int i;
7332 /* Load/store multiple. */
7333 addr = load_reg(s, rn);
7334 offset = 0;
7335 for (i = 0; i < 16; i++) {
7336 if (insn & (1 << i))
7337 offset += 4;
7339 if (insn & (1 << 24)) {
7340 tcg_gen_addi_i32(addr, addr, -offset);
7343 for (i = 0; i < 16; i++) {
7344 if ((insn & (1 << i)) == 0)
7345 continue;
7346 if (insn & (1 << 20)) {
7347 /* Load. */
7348 tmp = gen_ld32(addr, IS_USER(s));
7349 if (i == 15) {
7350 gen_bx(s, tmp);
7351 } else {
7352 store_reg(s, i, tmp);
7354 } else {
7355 /* Store. */
7356 tmp = load_reg(s, i);
7357 gen_st32(tmp, addr, IS_USER(s));
7359 tcg_gen_addi_i32(addr, addr, 4);
7361 if (insn & (1 << 21)) {
7362 /* Base register writeback. */
7363 if (insn & (1 << 24)) {
7364 tcg_gen_addi_i32(addr, addr, -offset);
7366 /* Fault if writeback register is in register list. */
7367 if (insn & (1 << rn))
7368 goto illegal_op;
7369 store_reg(s, rn, addr);
7370 } else {
7371 dead_tmp(addr);
7375 break;
7376 case 5: /* Data processing register constant shift. */
7377 if (rn == 15) {
7378 tmp = new_tmp();
7379 tcg_gen_movi_i32(tmp, 0);
7380 } else {
7381 tmp = load_reg(s, rn);
7383 tmp2 = load_reg(s, rm);
7384 op = (insn >> 21) & 0xf;
7385 shiftop = (insn >> 4) & 3;
7386 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7387 conds = (insn & (1 << 20)) != 0;
7388 logic_cc = (conds && thumb2_logic_op(op));
7389 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
7390 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
7391 goto illegal_op;
7392 dead_tmp(tmp2);
7393 if (rd != 15) {
7394 store_reg(s, rd, tmp);
7395 } else {
7396 dead_tmp(tmp);
7398 break;
7399 case 13: /* Misc data processing. */
7400 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
7401 if (op < 4 && (insn & 0xf000) != 0xf000)
7402 goto illegal_op;
7403 switch (op) {
7404 case 0: /* Register controlled shift. */
7405 tmp = load_reg(s, rn);
7406 tmp2 = load_reg(s, rm);
7407 if ((insn & 0x70) != 0)
7408 goto illegal_op;
7409 op = (insn >> 21) & 3;
7410 logic_cc = (insn & (1 << 20)) != 0;
7411 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
7412 if (logic_cc)
7413 gen_logic_CC(tmp);
7414 store_reg_bx(env, s, rd, tmp);
7415 break;
7416 case 1: /* Sign/zero extend. */
7417 tmp = load_reg(s, rm);
7418 shift = (insn >> 4) & 3;
7419 /* ??? In many cases it's not neccessary to do a
7420 rotate, a shift is sufficient. */
7421 if (shift != 0)
7422 tcg_gen_rori_i32(tmp, tmp, shift * 8);
7423 op = (insn >> 20) & 7;
7424 switch (op) {
7425 case 0: gen_sxth(tmp); break;
7426 case 1: gen_uxth(tmp); break;
7427 case 2: gen_sxtb16(tmp); break;
7428 case 3: gen_uxtb16(tmp); break;
7429 case 4: gen_sxtb(tmp); break;
7430 case 5: gen_uxtb(tmp); break;
7431 default: goto illegal_op;
7433 if (rn != 15) {
7434 tmp2 = load_reg(s, rn);
7435 if ((op >> 1) == 1) {
7436 gen_add16(tmp, tmp2);
7437 } else {
7438 tcg_gen_add_i32(tmp, tmp, tmp2);
7439 dead_tmp(tmp2);
7442 store_reg(s, rd, tmp);
7443 break;
7444 case 2: /* SIMD add/subtract. */
7445 op = (insn >> 20) & 7;
7446 shift = (insn >> 4) & 7;
7447 if ((op & 3) == 3 || (shift & 3) == 3)
7448 goto illegal_op;
7449 tmp = load_reg(s, rn);
7450 tmp2 = load_reg(s, rm);
7451 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7452 dead_tmp(tmp2);
7453 store_reg(s, rd, tmp);
7454 break;
7455 case 3: /* Other data processing. */
7456 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
7457 if (op < 4) {
7458 /* Saturating add/subtract. */
7459 tmp = load_reg(s, rn);
7460 tmp2 = load_reg(s, rm);
7461 if (op & 2)
7462 gen_helper_double_saturate(tmp, tmp);
7463 if (op & 1)
7464 gen_helper_sub_saturate(tmp, tmp2, tmp);
7465 else
7466 gen_helper_add_saturate(tmp, tmp, tmp2);
7467 dead_tmp(tmp2);
7468 } else {
7469 tmp = load_reg(s, rn);
7470 switch (op) {
7471 case 0x0a: /* rbit */
7472 gen_helper_rbit(tmp, tmp);
7473 break;
7474 case 0x08: /* rev */
7475 tcg_gen_bswap32_i32(tmp, tmp);
7476 break;
7477 case 0x09: /* rev16 */
7478 gen_rev16(tmp);
7479 break;
7480 case 0x0b: /* revsh */
7481 gen_revsh(tmp);
7482 break;
7483 case 0x10: /* sel */
7484 tmp2 = load_reg(s, rm);
7485 tmp3 = new_tmp();
7486 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
7487 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7488 dead_tmp(tmp3);
7489 dead_tmp(tmp2);
7490 break;
7491 case 0x18: /* clz */
7492 gen_helper_clz(tmp, tmp);
7493 break;
7494 default:
7495 goto illegal_op;
7498 store_reg(s, rd, tmp);
7499 break;
7500 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7501 op = (insn >> 4) & 0xf;
7502 tmp = load_reg(s, rn);
7503 tmp2 = load_reg(s, rm);
7504 switch ((insn >> 20) & 7) {
7505 case 0: /* 32 x 32 -> 32 */
7506 tcg_gen_mul_i32(tmp, tmp, tmp2);
7507 dead_tmp(tmp2);
7508 if (rs != 15) {
7509 tmp2 = load_reg(s, rs);
7510 if (op)
7511 tcg_gen_sub_i32(tmp, tmp2, tmp);
7512 else
7513 tcg_gen_add_i32(tmp, tmp, tmp2);
7514 dead_tmp(tmp2);
7516 break;
7517 case 1: /* 16 x 16 -> 32 */
7518 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7519 dead_tmp(tmp2);
7520 if (rs != 15) {
7521 tmp2 = load_reg(s, rs);
7522 gen_helper_add_setq(tmp, tmp, tmp2);
7523 dead_tmp(tmp2);
7525 break;
7526 case 2: /* Dual multiply add. */
7527 case 4: /* Dual multiply subtract. */
7528 if (op)
7529 gen_swap_half(tmp2);
7530 gen_smul_dual(tmp, tmp2);
7531 /* This addition cannot overflow. */
7532 if (insn & (1 << 22)) {
7533 tcg_gen_sub_i32(tmp, tmp, tmp2);
7534 } else {
7535 tcg_gen_add_i32(tmp, tmp, tmp2);
7537 dead_tmp(tmp2);
7538 if (rs != 15)
7540 tmp2 = load_reg(s, rs);
7541 gen_helper_add_setq(tmp, tmp, tmp2);
7542 dead_tmp(tmp2);
7544 break;
7545 case 3: /* 32 * 16 -> 32msb */
7546 if (op)
7547 tcg_gen_sari_i32(tmp2, tmp2, 16);
7548 else
7549 gen_sxth(tmp2);
7550 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7551 tcg_gen_shri_i64(tmp64, tmp64, 16);
7552 tmp = new_tmp();
7553 tcg_gen_trunc_i64_i32(tmp, tmp64);
7554 tcg_temp_free_i64(tmp64);
7555 if (rs != 15)
7557 tmp2 = load_reg(s, rs);
7558 gen_helper_add_setq(tmp, tmp, tmp2);
7559 dead_tmp(tmp2);
7561 break;
7562 case 5: case 6: /* 32 * 32 -> 32msb */
7563 gen_imull(tmp, tmp2);
7564 if (insn & (1 << 5)) {
7565 gen_roundqd(tmp, tmp2);
7566 dead_tmp(tmp2);
7567 } else {
7568 dead_tmp(tmp);
7569 tmp = tmp2;
7571 if (rs != 15) {
7572 tmp2 = load_reg(s, rs);
7573 if (insn & (1 << 21)) {
7574 tcg_gen_add_i32(tmp, tmp, tmp2);
7575 } else {
7576 tcg_gen_sub_i32(tmp, tmp2, tmp);
7578 dead_tmp(tmp2);
7580 break;
7581 case 7: /* Unsigned sum of absolute differences. */
7582 gen_helper_usad8(tmp, tmp, tmp2);
7583 dead_tmp(tmp2);
7584 if (rs != 15) {
7585 tmp2 = load_reg(s, rs);
7586 tcg_gen_add_i32(tmp, tmp, tmp2);
7587 dead_tmp(tmp2);
7589 break;
7591 store_reg(s, rd, tmp);
7592 break;
7593 case 6: case 7: /* 64-bit multiply, Divide. */
7594 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
7595 tmp = load_reg(s, rn);
7596 tmp2 = load_reg(s, rm);
7597 if ((op & 0x50) == 0x10) {
7598 /* sdiv, udiv */
7599 if (!arm_feature(env, ARM_FEATURE_DIV))
7600 goto illegal_op;
7601 if (op & 0x20)
7602 gen_helper_udiv(tmp, tmp, tmp2);
7603 else
7604 gen_helper_sdiv(tmp, tmp, tmp2);
7605 dead_tmp(tmp2);
7606 store_reg(s, rd, tmp);
7607 } else if ((op & 0xe) == 0xc) {
7608 /* Dual multiply accumulate long. */
7609 if (op & 1)
7610 gen_swap_half(tmp2);
7611 gen_smul_dual(tmp, tmp2);
7612 if (op & 0x10) {
7613 tcg_gen_sub_i32(tmp, tmp, tmp2);
7614 } else {
7615 tcg_gen_add_i32(tmp, tmp, tmp2);
7617 dead_tmp(tmp2);
7618 /* BUGFIX */
7619 tmp64 = tcg_temp_new_i64();
7620 tcg_gen_ext_i32_i64(tmp64, tmp);
7621 dead_tmp(tmp);
7622 gen_addq(s, tmp64, rs, rd);
7623 gen_storeq_reg(s, rs, rd, tmp64);
7624 tcg_temp_free_i64(tmp64);
7625 } else {
7626 if (op & 0x20) {
7627 /* Unsigned 64-bit multiply */
7628 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7629 } else {
7630 if (op & 8) {
7631 /* smlalxy */
7632 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7633 dead_tmp(tmp2);
7634 tmp64 = tcg_temp_new_i64();
7635 tcg_gen_ext_i32_i64(tmp64, tmp);
7636 dead_tmp(tmp);
7637 } else {
7638 /* Signed 64-bit multiply */
7639 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7642 if (op & 4) {
7643 /* umaal */
7644 gen_addq_lo(s, tmp64, rs);
7645 gen_addq_lo(s, tmp64, rd);
7646 } else if (op & 0x40) {
7647 /* 64-bit accumulate. */
7648 gen_addq(s, tmp64, rs, rd);
7650 gen_storeq_reg(s, rs, rd, tmp64);
7651 tcg_temp_free_i64(tmp64);
7653 break;
7655 break;
7656 case 6: case 7: case 14: case 15:
7657 /* Coprocessor. */
7658 if (((insn >> 24) & 3) == 3) {
7659 /* Translate into the equivalent ARM encoding. */
7660 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);
7661 if (disas_neon_data_insn(env, s, insn))
7662 goto illegal_op;
7663 } else {
7664 if (insn & (1 << 28))
7665 goto illegal_op;
7666 if (disas_coproc_insn (env, s, insn))
7667 goto illegal_op;
7669 break;
7670 case 8: case 9: case 10: case 11:
7671 if (insn & (1 << 15)) {
7672 /* Branches, misc control. */
7673 if (insn & 0x5000) {
7674 /* Unconditional branch. */
7675 /* signextend(hw1[10:0]) -> offset[:12]. */
7676 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
7677 /* hw1[10:0] -> offset[11:1]. */
7678 offset |= (insn & 0x7ff) << 1;
7679 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7680 offset[24:22] already have the same value because of the
7681 sign extension above. */
7682 offset ^= ((~insn) & (1 << 13)) << 10;
7683 offset ^= ((~insn) & (1 << 11)) << 11;
7685 if (insn & (1 << 14)) {
7686 /* Branch and link. */
7687 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
7690 offset += s->pc;
7691 if (insn & (1 << 12)) {
7692 /* b/bl */
7693 gen_jmp(s, offset);
7694 } else {
7695 /* blx */
7696 offset &= ~(uint32_t)2;
7697 gen_bx_im(s, offset);
7699 } else if (((insn >> 23) & 7) == 7) {
7700 /* Misc control */
7701 if (insn & (1 << 13))
7702 goto illegal_op;
7704 if (insn & (1 << 26)) {
7705 /* Secure monitor call (v6Z) */
7706 goto illegal_op; /* not implemented. */
7707 } else {
7708 op = (insn >> 20) & 7;
7709 switch (op) {
7710 case 0: /* msr cpsr. */
7711 if (IS_M(env)) {
7712 tmp = load_reg(s, rn);
7713 addr = tcg_const_i32(insn & 0xff);
7714 gen_helper_v7m_msr(cpu_env, addr, tmp);
7715 tcg_temp_free_i32(addr);
7716 dead_tmp(tmp);
7717 gen_lookup_tb(s);
7718 break;
7720 /* fall through */
7721 case 1: /* msr spsr. */
7722 if (IS_M(env))
7723 goto illegal_op;
7724 tmp = load_reg(s, rn);
7725 if (gen_set_psr(s,
7726 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
7727 op == 1, tmp))
7728 goto illegal_op;
7729 break;
7730 case 2: /* cps, nop-hint. */
7731 if (((insn >> 8) & 7) == 0) {
7732 gen_nop_hint(s, insn & 0xff);
7734 /* Implemented as NOP in user mode. */
7735 if (IS_USER(s))
7736 break;
7737 offset = 0;
7738 imm = 0;
7739 if (insn & (1 << 10)) {
7740 if (insn & (1 << 7))
7741 offset |= CPSR_A;
7742 if (insn & (1 << 6))
7743 offset |= CPSR_I;
7744 if (insn & (1 << 5))
7745 offset |= CPSR_F;
7746 if (insn & (1 << 9))
7747 imm = CPSR_A | CPSR_I | CPSR_F;
7749 if (insn & (1 << 8)) {
7750 offset |= 0x1f;
7751 imm |= (insn & 0x1f);
7753 if (offset) {
7754 gen_set_psr_im(s, offset, 0, imm);
7756 break;
7757 case 3: /* Special control operations. */
7758 op = (insn >> 4) & 0xf;
7759 switch (op) {
7760 case 2: /* clrex */
7761 gen_helper_clrex(cpu_env);
7762 break;
7763 case 4: /* dsb */
7764 case 5: /* dmb */
7765 case 6: /* isb */
7766 /* These execute as NOPs. */
7767 ARCH(7);
7768 break;
7769 default:
7770 goto illegal_op;
7772 break;
7773 case 4: /* bxj */
7774 /* Trivial implementation equivalent to bx. */
7775 tmp = load_reg(s, rn);
7776 gen_bx(s, tmp);
7777 break;
7778 case 5: /* Exception return. */
7779 /* Unpredictable in user mode. */
7780 goto illegal_op;
7781 case 6: /* mrs cpsr. */
7782 tmp = new_tmp();
7783 if (IS_M(env)) {
7784 addr = tcg_const_i32(insn & 0xff);
7785 gen_helper_v7m_mrs(tmp, cpu_env, addr);
7786 tcg_temp_free_i32(addr);
7787 } else {
7788 gen_helper_cpsr_read(tmp);
7790 store_reg(s, rd, tmp);
7791 break;
7792 case 7: /* mrs spsr. */
7793 /* Not accessible in user mode. */
7794 if (IS_USER(s) || IS_M(env))
7795 goto illegal_op;
7796 tmp = load_cpu_field(spsr);
7797 store_reg(s, rd, tmp);
7798 break;
7801 } else {
7802 /* Conditional branch. */
7803 op = (insn >> 22) & 0xf;
7804 /* Generate a conditional jump to next instruction. */
7805 s->condlabel = gen_new_label();
7806 gen_test_cc(op ^ 1, s->condlabel);
7807 s->condjmp = 1;
7809 /* offset[11:1] = insn[10:0] */
7810 offset = (insn & 0x7ff) << 1;
7811 /* offset[17:12] = insn[21:16]. */
7812 offset |= (insn & 0x003f0000) >> 4;
7813 /* offset[31:20] = insn[26]. */
7814 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
7815 /* offset[18] = insn[13]. */
7816 offset |= (insn & (1 << 13)) << 5;
7817 /* offset[19] = insn[11]. */
7818 offset |= (insn & (1 << 11)) << 8;
7820 /* jump to the offset */
7821 gen_jmp(s, s->pc + offset);
7823 } else {
7824 /* Data processing immediate. */
7825 if (insn & (1 << 25)) {
7826 if (insn & (1 << 24)) {
7827 if (insn & (1 << 20))
7828 goto illegal_op;
7829 /* Bitfield/Saturate. */
7830 op = (insn >> 21) & 7;
7831 imm = insn & 0x1f;
7832 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7833 if (rn == 15) {
7834 tmp = new_tmp();
7835 tcg_gen_movi_i32(tmp, 0);
7836 } else {
7837 tmp = load_reg(s, rn);
7839 switch (op) {
7840 case 2: /* Signed bitfield extract. */
7841 imm++;
7842 if (shift + imm > 32)
7843 goto illegal_op;
7844 if (imm < 32)
7845 gen_sbfx(tmp, shift, imm);
7846 break;
7847 case 6: /* Unsigned bitfield extract. */
7848 imm++;
7849 if (shift + imm > 32)
7850 goto illegal_op;
7851 if (imm < 32)
7852 gen_ubfx(tmp, shift, (1u << imm) - 1);
7853 break;
7854 case 3: /* Bitfield insert/clear. */
7855 if (imm < shift)
7856 goto illegal_op;
7857 imm = imm + 1 - shift;
7858 if (imm != 32) {
7859 tmp2 = load_reg(s, rd);
7860 gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
7861 dead_tmp(tmp2);
7863 break;
7864 case 7:
7865 goto illegal_op;
7866 default: /* Saturate. */
7867 if (shift) {
7868 if (op & 1)
7869 tcg_gen_sari_i32(tmp, tmp, shift);
7870 else
7871 tcg_gen_shli_i32(tmp, tmp, shift);
7873 tmp2 = tcg_const_i32(imm);
7874 if (op & 4) {
7875 /* Unsigned. */
7876 if ((op & 1) && shift == 0)
7877 gen_helper_usat16(tmp, tmp, tmp2);
7878 else
7879 gen_helper_usat(tmp, tmp, tmp2);
7880 } else {
7881 /* Signed. */
7882 if ((op & 1) && shift == 0)
7883 gen_helper_ssat16(tmp, tmp, tmp2);
7884 else
7885 gen_helper_ssat(tmp, tmp, tmp2);
7887 tcg_temp_free_i32(tmp2);
7888 break;
7890 store_reg(s, rd, tmp);
7891 } else {
7892 imm = ((insn & 0x04000000) >> 15)
7893 | ((insn & 0x7000) >> 4) | (insn & 0xff);
7894 if (insn & (1 << 22)) {
7895 /* 16-bit immediate. */
7896 imm |= (insn >> 4) & 0xf000;
7897 if (insn & (1 << 23)) {
7898 /* movt */
7899 tmp = load_reg(s, rd);
7900 tcg_gen_ext16u_i32(tmp, tmp);
7901 tcg_gen_ori_i32(tmp, tmp, imm << 16);
7902 } else {
7903 /* movw */
7904 tmp = new_tmp();
7905 tcg_gen_movi_i32(tmp, imm);
7907 } else {
7908 /* Add/sub 12-bit immediate. */
7909 if (rn == 15) {
7910 offset = s->pc & ~(uint32_t)3;
7911 if (insn & (1 << 23))
7912 offset -= imm;
7913 else
7914 offset += imm;
7915 tmp = new_tmp();
7916 tcg_gen_movi_i32(tmp, offset);
7917 } else {
7918 tmp = load_reg(s, rn);
7919 if (insn & (1 << 23))
7920 tcg_gen_subi_i32(tmp, tmp, imm);
7921 else
7922 tcg_gen_addi_i32(tmp, tmp, imm);
7925 store_reg(s, rd, tmp);
7927 } else {
7928 int shifter_out = 0;
7929 /* modified 12-bit immediate. */
7930 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
7931 imm = (insn & 0xff);
7932 switch (shift) {
7933 case 0: /* XY */
7934 /* Nothing to do. */
7935 break;
7936 case 1: /* 00XY00XY */
7937 imm |= imm << 16;
7938 break;
7939 case 2: /* XY00XY00 */
7940 imm |= imm << 16;
7941 imm <<= 8;
7942 break;
7943 case 3: /* XYXYXYXY */
7944 imm |= imm << 16;
7945 imm |= imm << 8;
7946 break;
7947 default: /* Rotated constant. */
7948 shift = (shift << 1) | (imm >> 7);
7949 imm |= 0x80;
7950 imm = imm << (32 - shift);
7951 shifter_out = 1;
7952 break;
7954 tmp2 = new_tmp();
7955 tcg_gen_movi_i32(tmp2, imm);
7956 rn = (insn >> 16) & 0xf;
7957 if (rn == 15) {
7958 tmp = new_tmp();
7959 tcg_gen_movi_i32(tmp, 0);
7960 } else {
7961 tmp = load_reg(s, rn);
7963 op = (insn >> 21) & 0xf;
7964 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
7965 shifter_out, tmp, tmp2))
7966 goto illegal_op;
7967 dead_tmp(tmp2);
7968 rd = (insn >> 8) & 0xf;
7969 if (rd != 15) {
7970 store_reg(s, rd, tmp);
7971 } else {
7972 dead_tmp(tmp);
7976 break;
7977 case 12: /* Load/store single data item. */
7979 int postinc = 0;
7980 int writeback = 0;
7981 int user;
7982 if ((insn & 0x01100000) == 0x01000000) {
7983 if (disas_neon_ls_insn(env, s, insn))
7984 goto illegal_op;
7985 break;
7987 user = IS_USER(s);
7988 if (rn == 15) {
7989 addr = new_tmp();
7990 /* PC relative. */
7991 /* s->pc has already been incremented by 4. */
7992 imm = s->pc & 0xfffffffc;
7993 if (insn & (1 << 23))
7994 imm += insn & 0xfff;
7995 else
7996 imm -= insn & 0xfff;
7997 tcg_gen_movi_i32(addr, imm);
7998 } else {
7999 addr = load_reg(s, rn);
8000 if (insn & (1 << 23)) {
8001 /* Positive offset. */
8002 imm = insn & 0xfff;
8003 tcg_gen_addi_i32(addr, addr, imm);
8004 } else {
8005 op = (insn >> 8) & 7;
8006 imm = insn & 0xff;
8007 switch (op) {
8008 case 0: case 8: /* Shifted Register. */
8009 shift = (insn >> 4) & 0xf;
8010 if (shift > 3)
8011 goto illegal_op;
8012 tmp = load_reg(s, rm);
8013 if (shift)
8014 tcg_gen_shli_i32(tmp, tmp, shift);
8015 tcg_gen_add_i32(addr, addr, tmp);
8016 dead_tmp(tmp);
8017 break;
8018 case 4: /* Negative offset. */
8019 tcg_gen_addi_i32(addr, addr, -imm);
8020 break;
8021 case 6: /* User privilege. */
8022 tcg_gen_addi_i32(addr, addr, imm);
8023 user = 1;
8024 break;
8025 case 1: /* Post-decrement. */
8026 imm = -imm;
8027 /* Fall through. */
8028 case 3: /* Post-increment. */
8029 postinc = 1;
8030 writeback = 1;
8031 break;
8032 case 5: /* Pre-decrement. */
8033 imm = -imm;
8034 /* Fall through. */
8035 case 7: /* Pre-increment. */
8036 tcg_gen_addi_i32(addr, addr, imm);
8037 writeback = 1;
8038 break;
8039 default:
8040 goto illegal_op;
8044 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
8045 if (insn & (1 << 20)) {
8046 /* Load. */
8047 if (rs == 15 && op != 2) {
8048 if (op & 2)
8049 goto illegal_op;
8050 /* Memory hint. Implemented as NOP. */
8051 } else {
8052 switch (op) {
8053 case 0: tmp = gen_ld8u(addr, user); break;
8054 case 4: tmp = gen_ld8s(addr, user); break;
8055 case 1: tmp = gen_ld16u(addr, user); break;
8056 case 5: tmp = gen_ld16s(addr, user); break;
8057 case 2: tmp = gen_ld32(addr, user); break;
8058 default: goto illegal_op;
8060 if (rs == 15) {
8061 gen_bx(s, tmp);
8062 } else {
8063 store_reg(s, rs, tmp);
8066 } else {
8067 /* Store. */
8068 if (rs == 15)
8069 goto illegal_op;
8070 tmp = load_reg(s, rs);
8071 switch (op) {
8072 case 0: gen_st8(tmp, addr, user); break;
8073 case 1: gen_st16(tmp, addr, user); break;
8074 case 2: gen_st32(tmp, addr, user); break;
8075 default: goto illegal_op;
8078 if (postinc)
8079 tcg_gen_addi_i32(addr, addr, imm);
8080 if (writeback) {
8081 store_reg(s, rn, addr);
8082 } else {
8083 dead_tmp(addr);
8086 break;
8087 default:
8088 goto illegal_op;
8090 return 0;
8091 illegal_op:
8092 return 1;
8095 static void disas_thumb_insn(CPUState *env, DisasContext *s)
8097 uint32_t val, insn, op, rm, rn, rd, shift, cond;
8098 int32_t offset;
8099 int i;
8100 TCGv tmp;
8101 TCGv tmp2;
8102 TCGv addr;
8104 if (s->condexec_mask) {
8105 cond = s->condexec_cond;
8106 s->condlabel = gen_new_label();
8107 gen_test_cc(cond ^ 1, s->condlabel);
8108 s->condjmp = 1;
8111 insn = lduw_code(s->pc);
8112 s->pc += 2;
8114 switch (insn >> 12) {
8115 case 0: case 1:
8117 rd = insn & 7;
8118 op = (insn >> 11) & 3;
8119 if (op == 3) {
8120 /* add/subtract */
8121 rn = (insn >> 3) & 7;
8122 tmp = load_reg(s, rn);
8123 if (insn & (1 << 10)) {
8124 /* immediate */
8125 tmp2 = new_tmp();
8126 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
8127 } else {
8128 /* reg */
8129 rm = (insn >> 6) & 7;
8130 tmp2 = load_reg(s, rm);
8132 if (insn & (1 << 9)) {
8133 if (s->condexec_mask)
8134 tcg_gen_sub_i32(tmp, tmp, tmp2);
8135 else
8136 gen_helper_sub_cc(tmp, tmp, tmp2);
8137 } else {
8138 if (s->condexec_mask)
8139 tcg_gen_add_i32(tmp, tmp, tmp2);
8140 else
8141 gen_helper_add_cc(tmp, tmp, tmp2);
8143 dead_tmp(tmp2);
8144 store_reg(s, rd, tmp);
8145 } else {
8146 /* shift immediate */
8147 rm = (insn >> 3) & 7;
8148 shift = (insn >> 6) & 0x1f;
8149 tmp = load_reg(s, rm);
8150 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
8151 if (!s->condexec_mask)
8152 gen_logic_CC(tmp);
8153 store_reg(s, rd, tmp);
8155 break;
8156 case 2: case 3:
8157 /* arithmetic large immediate */
8158 op = (insn >> 11) & 3;
8159 rd = (insn >> 8) & 0x7;
8160 if (op == 0) { /* mov */
8161 tmp = new_tmp();
8162 tcg_gen_movi_i32(tmp, insn & 0xff);
8163 if (!s->condexec_mask)
8164 gen_logic_CC(tmp);
8165 store_reg(s, rd, tmp);
8166 } else {
8167 tmp = load_reg(s, rd);
8168 tmp2 = new_tmp();
8169 tcg_gen_movi_i32(tmp2, insn & 0xff);
8170 switch (op) {
8171 case 1: /* cmp */
8172 gen_helper_sub_cc(tmp, tmp, tmp2);
8173 dead_tmp(tmp);
8174 dead_tmp(tmp2);
8175 break;
8176 case 2: /* add */
8177 if (s->condexec_mask)
8178 tcg_gen_add_i32(tmp, tmp, tmp2);
8179 else
8180 gen_helper_add_cc(tmp, tmp, tmp2);
8181 dead_tmp(tmp2);
8182 store_reg(s, rd, tmp);
8183 break;
8184 case 3: /* sub */
8185 if (s->condexec_mask)
8186 tcg_gen_sub_i32(tmp, tmp, tmp2);
8187 else
8188 gen_helper_sub_cc(tmp, tmp, tmp2);
8189 dead_tmp(tmp2);
8190 store_reg(s, rd, tmp);
8191 break;
8194 break;
8195 case 4:
8196 if (insn & (1 << 11)) {
8197 rd = (insn >> 8) & 7;
8198 /* load pc-relative. Bit 1 of PC is ignored. */
8199 val = s->pc + 2 + ((insn & 0xff) * 4);
8200 val &= ~(uint32_t)2;
8201 addr = new_tmp();
8202 tcg_gen_movi_i32(addr, val);
8203 tmp = gen_ld32(addr, IS_USER(s));
8204 dead_tmp(addr);
8205 store_reg(s, rd, tmp);
8206 break;
8208 if (insn & (1 << 10)) {
8209 /* data processing extended or blx */
8210 rd = (insn & 7) | ((insn >> 4) & 8);
8211 rm = (insn >> 3) & 0xf;
8212 op = (insn >> 8) & 3;
8213 switch (op) {
8214 case 0: /* add */
8215 tmp = load_reg(s, rd);
8216 tmp2 = load_reg(s, rm);
8217 tcg_gen_add_i32(tmp, tmp, tmp2);
8218 dead_tmp(tmp2);
8219 store_reg(s, rd, tmp);
8220 break;
8221 case 1: /* cmp */
8222 tmp = load_reg(s, rd);
8223 tmp2 = load_reg(s, rm);
8224 gen_helper_sub_cc(tmp, tmp, tmp2);
8225 dead_tmp(tmp2);
8226 dead_tmp(tmp);
8227 break;
8228 case 2: /* mov/cpy */
8229 tmp = load_reg(s, rm);
8230 store_reg(s, rd, tmp);
8231 break;
8232 case 3:/* branch [and link] exchange thumb register */
8233 tmp = load_reg(s, rm);
8234 if (insn & (1 << 7)) {
8235 val = (uint32_t)s->pc | 1;
8236 tmp2 = new_tmp();
8237 tcg_gen_movi_i32(tmp2, val);
8238 store_reg(s, 14, tmp2);
8240 gen_bx(s, tmp);
8241 break;
8243 break;
8246 /* data processing register */
8247 rd = insn & 7;
8248 rm = (insn >> 3) & 7;
8249 op = (insn >> 6) & 0xf;
8250 if (op == 2 || op == 3 || op == 4 || op == 7) {
8251 /* the shift/rotate ops want the operands backwards */
8252 val = rm;
8253 rm = rd;
8254 rd = val;
8255 val = 1;
8256 } else {
8257 val = 0;
8260 if (op == 9) { /* neg */
8261 tmp = new_tmp();
8262 tcg_gen_movi_i32(tmp, 0);
8263 } else if (op != 0xf) { /* mvn doesn't read its first operand */
8264 tmp = load_reg(s, rd);
8265 } else {
8266 TCGV_UNUSED(tmp);
8269 tmp2 = load_reg(s, rm);
8270 switch (op) {
8271 case 0x0: /* and */
8272 tcg_gen_and_i32(tmp, tmp, tmp2);
8273 if (!s->condexec_mask)
8274 gen_logic_CC(tmp);
8275 break;
8276 case 0x1: /* eor */
8277 tcg_gen_xor_i32(tmp, tmp, tmp2);
8278 if (!s->condexec_mask)
8279 gen_logic_CC(tmp);
8280 break;
8281 case 0x2: /* lsl */
8282 if (s->condexec_mask) {
8283 gen_helper_shl(tmp2, tmp2, tmp);
8284 } else {
8285 gen_helper_shl_cc(tmp2, tmp2, tmp);
8286 gen_logic_CC(tmp2);
8288 break;
8289 case 0x3: /* lsr */
8290 if (s->condexec_mask) {
8291 gen_helper_shr(tmp2, tmp2, tmp);
8292 } else {
8293 gen_helper_shr_cc(tmp2, tmp2, tmp);
8294 gen_logic_CC(tmp2);
8296 break;
8297 case 0x4: /* asr */
8298 if (s->condexec_mask) {
8299 gen_helper_sar(tmp2, tmp2, tmp);
8300 } else {
8301 gen_helper_sar_cc(tmp2, tmp2, tmp);
8302 gen_logic_CC(tmp2);
8304 break;
8305 case 0x5: /* adc */
8306 if (s->condexec_mask)
8307 gen_adc(tmp, tmp2);
8308 else
8309 gen_helper_adc_cc(tmp, tmp, tmp2);
8310 break;
8311 case 0x6: /* sbc */
8312 if (s->condexec_mask)
8313 gen_sub_carry(tmp, tmp, tmp2);
8314 else
8315 gen_helper_sbc_cc(tmp, tmp, tmp2);
8316 break;
8317 case 0x7: /* ror */
8318 if (s->condexec_mask) {
8319 gen_helper_ror(tmp2, tmp2, tmp);
8320 } else {
8321 gen_helper_ror_cc(tmp2, tmp2, tmp);
8322 gen_logic_CC(tmp2);
8324 break;
8325 case 0x8: /* tst */
8326 tcg_gen_and_i32(tmp, tmp, tmp2);
8327 gen_logic_CC(tmp);
8328 rd = 16;
8329 break;
8330 case 0x9: /* neg */
8331 if (s->condexec_mask)
8332 tcg_gen_neg_i32(tmp, tmp2);
8333 else
8334 gen_helper_sub_cc(tmp, tmp, tmp2);
8335 break;
8336 case 0xa: /* cmp */
8337 gen_helper_sub_cc(tmp, tmp, tmp2);
8338 rd = 16;
8339 break;
8340 case 0xb: /* cmn */
8341 gen_helper_add_cc(tmp, tmp, tmp2);
8342 rd = 16;
8343 break;
8344 case 0xc: /* orr */
8345 tcg_gen_or_i32(tmp, tmp, tmp2);
8346 if (!s->condexec_mask)
8347 gen_logic_CC(tmp);
8348 break;
8349 case 0xd: /* mul */
8350 tcg_gen_mul_i32(tmp, tmp, tmp2);
8351 if (!s->condexec_mask)
8352 gen_logic_CC(tmp);
8353 break;
8354 case 0xe: /* bic */
8355 tcg_gen_bic_i32(tmp, tmp, tmp2);
8356 if (!s->condexec_mask)
8357 gen_logic_CC(tmp);
8358 break;
8359 case 0xf: /* mvn */
8360 tcg_gen_not_i32(tmp2, tmp2);
8361 if (!s->condexec_mask)
8362 gen_logic_CC(tmp2);
8363 val = 1;
8364 rm = rd;
8365 break;
8367 if (rd != 16) {
8368 if (val) {
8369 store_reg(s, rm, tmp2);
8370 if (op != 0xf)
8371 dead_tmp(tmp);
8372 } else {
8373 store_reg(s, rd, tmp);
8374 dead_tmp(tmp2);
8376 } else {
8377 dead_tmp(tmp);
8378 dead_tmp(tmp2);
8380 break;
8382 case 5:
8383 /* load/store register offset. */
8384 rd = insn & 7;
8385 rn = (insn >> 3) & 7;
8386 rm = (insn >> 6) & 7;
8387 op = (insn >> 9) & 7;
8388 addr = load_reg(s, rn);
8389 tmp = load_reg(s, rm);
8390 tcg_gen_add_i32(addr, addr, tmp);
8391 dead_tmp(tmp);
8393 if (op < 3) /* store */
8394 tmp = load_reg(s, rd);
8396 switch (op) {
8397 case 0: /* str */
8398 gen_st32(tmp, addr, IS_USER(s));
8399 break;
8400 case 1: /* strh */
8401 gen_st16(tmp, addr, IS_USER(s));
8402 break;
8403 case 2: /* strb */
8404 gen_st8(tmp, addr, IS_USER(s));
8405 break;
8406 case 3: /* ldrsb */
8407 tmp = gen_ld8s(addr, IS_USER(s));
8408 break;
8409 case 4: /* ldr */
8410 tmp = gen_ld32(addr, IS_USER(s));
8411 break;
8412 case 5: /* ldrh */
8413 tmp = gen_ld16u(addr, IS_USER(s));
8414 break;
8415 case 6: /* ldrb */
8416 tmp = gen_ld8u(addr, IS_USER(s));
8417 break;
8418 case 7: /* ldrsh */
8419 tmp = gen_ld16s(addr, IS_USER(s));
8420 break;
8422 if (op >= 3) /* load */
8423 store_reg(s, rd, tmp);
8424 dead_tmp(addr);
8425 break;
8427 case 6:
8428 /* load/store word immediate offset */
8429 rd = insn & 7;
8430 rn = (insn >> 3) & 7;
8431 addr = load_reg(s, rn);
8432 val = (insn >> 4) & 0x7c;
8433 tcg_gen_addi_i32(addr, addr, val);
8435 if (insn & (1 << 11)) {
8436 /* load */
8437 tmp = gen_ld32(addr, IS_USER(s));
8438 store_reg(s, rd, tmp);
8439 } else {
8440 /* store */
8441 tmp = load_reg(s, rd);
8442 gen_st32(tmp, addr, IS_USER(s));
8444 dead_tmp(addr);
8445 break;
8447 case 7:
8448 /* load/store byte immediate offset */
8449 rd = insn & 7;
8450 rn = (insn >> 3) & 7;
8451 addr = load_reg(s, rn);
8452 val = (insn >> 6) & 0x1f;
8453 tcg_gen_addi_i32(addr, addr, val);
8455 if (insn & (1 << 11)) {
8456 /* load */
8457 tmp = gen_ld8u(addr, IS_USER(s));
8458 store_reg(s, rd, tmp);
8459 } else {
8460 /* store */
8461 tmp = load_reg(s, rd);
8462 gen_st8(tmp, addr, IS_USER(s));
8464 dead_tmp(addr);
8465 break;
8467 case 8:
8468 /* load/store halfword immediate offset */
8469 rd = insn & 7;
8470 rn = (insn >> 3) & 7;
8471 addr = load_reg(s, rn);
8472 val = (insn >> 5) & 0x3e;
8473 tcg_gen_addi_i32(addr, addr, val);
8475 if (insn & (1 << 11)) {
8476 /* load */
8477 tmp = gen_ld16u(addr, IS_USER(s));
8478 store_reg(s, rd, tmp);
8479 } else {
8480 /* store */
8481 tmp = load_reg(s, rd);
8482 gen_st16(tmp, addr, IS_USER(s));
8484 dead_tmp(addr);
8485 break;
8487 case 9:
8488 /* load/store from stack */
8489 rd = (insn >> 8) & 7;
8490 addr = load_reg(s, 13);
8491 val = (insn & 0xff) * 4;
8492 tcg_gen_addi_i32(addr, addr, val);
8494 if (insn & (1 << 11)) {
8495 /* load */
8496 tmp = gen_ld32(addr, IS_USER(s));
8497 store_reg(s, rd, tmp);
8498 } else {
8499 /* store */
8500 tmp = load_reg(s, rd);
8501 gen_st32(tmp, addr, IS_USER(s));
8503 dead_tmp(addr);
8504 break;
8506 case 10:
8507 /* add to high reg */
8508 rd = (insn >> 8) & 7;
8509 if (insn & (1 << 11)) {
8510 /* SP */
8511 tmp = load_reg(s, 13);
8512 } else {
8513 /* PC. bit 1 is ignored. */
8514 tmp = new_tmp();
8515 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
8517 val = (insn & 0xff) * 4;
8518 tcg_gen_addi_i32(tmp, tmp, val);
8519 store_reg(s, rd, tmp);
8520 break;
8522 case 11:
8523 /* misc */
8524 op = (insn >> 8) & 0xf;
8525 switch (op) {
8526 case 0:
8527 /* adjust stack pointer */
8528 tmp = load_reg(s, 13);
8529 val = (insn & 0x7f) * 4;
8530 if (insn & (1 << 7))
8531 val = -(int32_t)val;
8532 tcg_gen_addi_i32(tmp, tmp, val);
8533 store_reg(s, 13, tmp);
8534 break;
8536 case 2: /* sign/zero extend. */
8537 ARCH(6);
8538 rd = insn & 7;
8539 rm = (insn >> 3) & 7;
8540 tmp = load_reg(s, rm);
8541 switch ((insn >> 6) & 3) {
8542 case 0: gen_sxth(tmp); break;
8543 case 1: gen_sxtb(tmp); break;
8544 case 2: gen_uxth(tmp); break;
8545 case 3: gen_uxtb(tmp); break;
8547 store_reg(s, rd, tmp);
8548 break;
8549 case 4: case 5: case 0xc: case 0xd:
8550 /* push/pop */
8551 addr = load_reg(s, 13);
8552 if (insn & (1 << 8))
8553 offset = 4;
8554 else
8555 offset = 0;
8556 for (i = 0; i < 8; i++) {
8557 if (insn & (1 << i))
8558 offset += 4;
8560 if ((insn & (1 << 11)) == 0) {
8561 tcg_gen_addi_i32(addr, addr, -offset);
8563 for (i = 0; i < 8; i++) {
8564 if (insn & (1 << i)) {
8565 if (insn & (1 << 11)) {
8566 /* pop */
8567 tmp = gen_ld32(addr, IS_USER(s));
8568 store_reg(s, i, tmp);
8569 } else {
8570 /* push */
8571 tmp = load_reg(s, i);
8572 gen_st32(tmp, addr, IS_USER(s));
8574 /* advance to the next address. */
8575 tcg_gen_addi_i32(addr, addr, 4);
8578 TCGV_UNUSED(tmp);
8579 if (insn & (1 << 8)) {
8580 if (insn & (1 << 11)) {
8581 /* pop pc */
8582 tmp = gen_ld32(addr, IS_USER(s));
8583 /* don't set the pc until the rest of the instruction
8584 has completed */
8585 } else {
8586 /* push lr */
8587 tmp = load_reg(s, 14);
8588 gen_st32(tmp, addr, IS_USER(s));
8590 tcg_gen_addi_i32(addr, addr, 4);
8592 if ((insn & (1 << 11)) == 0) {
8593 tcg_gen_addi_i32(addr, addr, -offset);
8595 /* write back the new stack pointer */
8596 store_reg(s, 13, addr);
8597 /* set the new PC value */
8598 if ((insn & 0x0900) == 0x0900)
8599 gen_bx(s, tmp);
8600 break;
8602 case 1: case 3: case 9: case 11: /* czb */
8603 rm = insn & 7;
8604 tmp = load_reg(s, rm);
8605 s->condlabel = gen_new_label();
8606 s->condjmp = 1;
8607 if (insn & (1 << 11))
8608 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
8609 else
8610 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
8611 dead_tmp(tmp);
8612 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
8613 val = (uint32_t)s->pc + 2;
8614 val += offset;
8615 gen_jmp(s, val);
8616 break;
8618 case 15: /* IT, nop-hint. */
8619 if ((insn & 0xf) == 0) {
8620 gen_nop_hint(s, (insn >> 4) & 0xf);
8621 break;
8623 /* If Then. */
8624 s->condexec_cond = (insn >> 4) & 0xe;
8625 s->condexec_mask = insn & 0x1f;
8626 /* No actual code generated for this insn, just setup state. */
8627 break;
8629 case 0xe: /* bkpt */
8630 gen_set_condexec(s);
8631 gen_set_pc_im(s->pc - 2);
8632 gen_exception(EXCP_BKPT);
8633 s->is_jmp = DISAS_JUMP;
8634 break;
8636 case 0xa: /* rev */
8637 ARCH(6);
8638 rn = (insn >> 3) & 0x7;
8639 rd = insn & 0x7;
8640 tmp = load_reg(s, rn);
8641 switch ((insn >> 6) & 3) {
8642 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
8643 case 1: gen_rev16(tmp); break;
8644 case 3: gen_revsh(tmp); break;
8645 default: goto illegal_op;
8647 store_reg(s, rd, tmp);
8648 break;
8650 case 6: /* cps */
8651 ARCH(6);
8652 if (IS_USER(s))
8653 break;
8654 if (IS_M(env)) {
8655 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
8656 /* PRIMASK */
8657 if (insn & 1) {
8658 addr = tcg_const_i32(16);
8659 gen_helper_v7m_msr(cpu_env, addr, tmp);
8660 tcg_temp_free_i32(addr);
8662 /* FAULTMASK */
8663 if (insn & 2) {
8664 addr = tcg_const_i32(17);
8665 gen_helper_v7m_msr(cpu_env, addr, tmp);
8666 tcg_temp_free_i32(addr);
8668 tcg_temp_free_i32(tmp);
8669 gen_lookup_tb(s);
8670 } else {
8671 if (insn & (1 << 4))
8672 shift = CPSR_A | CPSR_I | CPSR_F;
8673 else
8674 shift = 0;
8675 gen_set_psr_im(s, shift, 0, ((insn & 7) << 6) & shift);
8677 break;
8679 default:
8680 goto undef;
8682 break;
8684 case 12:
8685 /* load/store multiple */
8686 rn = (insn >> 8) & 0x7;
8687 addr = load_reg(s, rn);
8688 for (i = 0; i < 8; i++) {
8689 if (insn & (1 << i)) {
8690 if (insn & (1 << 11)) {
8691 /* load */
8692 tmp = gen_ld32(addr, IS_USER(s));
8693 store_reg(s, i, tmp);
8694 } else {
8695 /* store */
8696 tmp = load_reg(s, i);
8697 gen_st32(tmp, addr, IS_USER(s));
8699 /* advance to the next address */
8700 tcg_gen_addi_i32(addr, addr, 4);
8703 /* Base register writeback. */
8704 if ((insn & (1 << rn)) == 0) {
8705 store_reg(s, rn, addr);
8706 } else {
8707 dead_tmp(addr);
8709 break;
8711 case 13:
8712 /* conditional branch or swi */
8713 cond = (insn >> 8) & 0xf;
8714 if (cond == 0xe)
8715 goto undef;
8717 if (cond == 0xf) {
8718 /* swi */
8719 gen_set_condexec(s);
8720 gen_set_pc_im(s->pc);
8721 s->is_jmp = DISAS_SWI;
8722 break;
8724 /* generate a conditional jump to next instruction */
8725 s->condlabel = gen_new_label();
8726 gen_test_cc(cond ^ 1, s->condlabel);
8727 s->condjmp = 1;
8729 /* jump to the offset */
8730 val = (uint32_t)s->pc + 2;
8731 offset = ((int32_t)insn << 24) >> 24;
8732 val += offset << 1;
8733 gen_jmp(s, val);
8734 break;
8736 case 14:
8737 if (insn & (1 << 11)) {
8738 if (disas_thumb2_insn(env, s, insn))
8739 goto undef32;
8740 break;
8742 /* unconditional branch */
8743 val = (uint32_t)s->pc;
8744 offset = ((int32_t)insn << 21) >> 21;
8745 val += (offset << 1) + 2;
8746 gen_jmp(s, val);
8747 break;
8749 case 15:
8750 if (disas_thumb2_insn(env, s, insn))
8751 goto undef32;
8752 break;
8754 return;
8755 undef32:
8756 gen_set_condexec(s);
8757 gen_set_pc_im(s->pc - 4);
8758 gen_exception(EXCP_UDEF);
8759 s->is_jmp = DISAS_JUMP;
8760 return;
8761 illegal_op:
8762 undef:
8763 gen_set_condexec(s);
8764 gen_set_pc_im(s->pc - 2);
8765 gen_exception(EXCP_UDEF);
8766 s->is_jmp = DISAS_JUMP;
8769 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8770 basic block 'tb'. If search_pc is TRUE, also generate PC
8771 information for each intermediate instruction. */
8772 static inline void gen_intermediate_code_internal(CPUState *env,
8773 TranslationBlock *tb,
8774 int search_pc)
8776 DisasContext dc1, *dc = &dc1;
8777 CPUBreakpoint *bp;
8778 uint16_t *gen_opc_end;
8779 int j, lj;
8780 target_ulong pc_start;
8781 uint32_t next_page_start;
8782 int num_insns;
8783 int max_insns;
8785 /* generate intermediate code */
8786 num_temps = 0;
8788 pc_start = tb->pc;
8790 dc->tb = tb;
8792 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8794 dc->is_jmp = DISAS_NEXT;
8795 dc->pc = pc_start;
8796 dc->singlestep_enabled = env->singlestep_enabled;
8797 dc->condjmp = 0;
8798 dc->thumb = env->thumb;
8799 dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
8800 dc->condexec_cond = env->condexec_bits >> 4;
8801 #if !defined(CONFIG_USER_ONLY)
8802 if (IS_M(env)) {
8803 dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
8804 } else {
8805 dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
8807 #endif
8808 cpu_F0s = tcg_temp_new_i32();
8809 cpu_F1s = tcg_temp_new_i32();
8810 cpu_F0d = tcg_temp_new_i64();
8811 cpu_F1d = tcg_temp_new_i64();
8812 cpu_V0 = cpu_F0d;
8813 cpu_V1 = cpu_F1d;
8814 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8815 cpu_M0 = tcg_temp_new_i64();
8816 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
8817 lj = -1;
8818 num_insns = 0;
8819 max_insns = tb->cflags & CF_COUNT_MASK;
8820 if (max_insns == 0)
8821 max_insns = CF_COUNT_MASK;
8823 gen_icount_start();
8824 /* Reset the conditional execution bits immediately. This avoids
8825 complications trying to do it at the end of the block. */
8826 if (env->condexec_bits)
8828 TCGv tmp = new_tmp();
8829 tcg_gen_movi_i32(tmp, 0);
8830 store_cpu_field(tmp, condexec_bits);
8832 do {
8833 #ifdef CONFIG_USER_ONLY
8834 /* Intercept jump to the magic kernel page. */
8835 if (dc->pc >= 0xffff0000) {
8836 /* We always get here via a jump, so know we are not in a
8837 conditional execution block. */
8838 gen_exception(EXCP_KERNEL_TRAP);
8839 dc->is_jmp = DISAS_UPDATE;
8840 break;
8842 #else
8843 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
8844 /* We always get here via a jump, so know we are not in a
8845 conditional execution block. */
8846 gen_exception(EXCP_EXCEPTION_EXIT);
8847 dc->is_jmp = DISAS_UPDATE;
8848 break;
8850 #endif
8852 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
8853 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
8854 if (bp->pc == dc->pc) {
8855 gen_set_condexec(dc);
8856 gen_set_pc_im(dc->pc);
8857 gen_exception(EXCP_DEBUG);
8858 dc->is_jmp = DISAS_JUMP;
8859 /* Advance PC so that clearing the breakpoint will
8860 invalidate this TB. */
8861 dc->pc += 2;
8862 goto done_generating;
8863 break;
8867 if (search_pc) {
8868 j = gen_opc_ptr - gen_opc_buf;
8869 if (lj < j) {
8870 lj++;
8871 while (lj < j)
8872 gen_opc_instr_start[lj++] = 0;
8874 gen_opc_pc[lj] = dc->pc;
8875 gen_opc_instr_start[lj] = 1;
8876 gen_opc_icount[lj] = num_insns;
8879 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8880 gen_io_start();
8882 if (env->thumb) {
8883 disas_thumb_insn(env, dc);
8884 if (dc->condexec_mask) {
8885 dc->condexec_cond = (dc->condexec_cond & 0xe)
8886 | ((dc->condexec_mask >> 4) & 1);
8887 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
8888 if (dc->condexec_mask == 0) {
8889 dc->condexec_cond = 0;
8892 } else {
8893 disas_arm_insn(env, dc);
8895 if (num_temps) {
8896 fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
8897 num_temps = 0;
8900 if (dc->condjmp && !dc->is_jmp) {
8901 gen_set_label(dc->condlabel);
8902 dc->condjmp = 0;
8904 /* Translation stops when a conditional branch is encountered.
8905 * Otherwise the subsequent code could get translated several times.
8906 * Also stop translation when a page boundary is reached. This
8907 * ensures prefetch aborts occur at the right place. */
8908 num_insns ++;
8909 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
8910 !env->singlestep_enabled &&
8911 !singlestep &&
8912 dc->pc < next_page_start &&
8913 num_insns < max_insns);
8915 if (tb->cflags & CF_LAST_IO) {
8916 if (dc->condjmp) {
8917 /* FIXME: This can theoretically happen with self-modifying
8918 code. */
8919 cpu_abort(env, "IO on conditional branch instruction");
8921 gen_io_end();
8924 /* At this stage dc->condjmp will only be set when the skipped
8925 instruction was a conditional branch or trap, and the PC has
8926 already been written. */
8927 if (unlikely(env->singlestep_enabled)) {
8928 /* Make sure the pc is updated, and raise a debug exception. */
8929 if (dc->condjmp) {
8930 gen_set_condexec(dc);
8931 if (dc->is_jmp == DISAS_SWI) {
8932 gen_exception(EXCP_SWI);
8933 } else {
8934 gen_exception(EXCP_DEBUG);
8936 gen_set_label(dc->condlabel);
8938 if (dc->condjmp || !dc->is_jmp) {
8939 gen_set_pc_im(dc->pc);
8940 dc->condjmp = 0;
8942 gen_set_condexec(dc);
8943 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
8944 gen_exception(EXCP_SWI);
8945 } else {
8946 /* FIXME: Single stepping a WFI insn will not halt
8947 the CPU. */
8948 gen_exception(EXCP_DEBUG);
8950 } else {
8951 /* While branches must always occur at the end of an IT block,
8952 there are a few other things that can cause us to terminate
8953 the TB in the middel of an IT block:
8954 - Exception generating instructions (bkpt, swi, undefined).
8955 - Page boundaries.
8956 - Hardware watchpoints.
8957 Hardware breakpoints have already been handled and skip this code.
8959 gen_set_condexec(dc);
8960 switch(dc->is_jmp) {
8961 case DISAS_NEXT:
8962 gen_goto_tb(dc, 1, dc->pc);
8963 break;
8964 default:
8965 case DISAS_JUMP:
8966 case DISAS_UPDATE:
8967 /* indicate that the hash table must be used to find the next TB */
8968 tcg_gen_exit_tb(0);
8969 break;
8970 case DISAS_TB_JUMP:
8971 /* nothing more to generate */
8972 break;
8973 case DISAS_WFI:
8974 gen_helper_wfi();
8975 break;
8976 case DISAS_SWI:
8977 gen_exception(EXCP_SWI);
8978 break;
8980 if (dc->condjmp) {
8981 gen_set_label(dc->condlabel);
8982 gen_set_condexec(dc);
8983 gen_goto_tb(dc, 1, dc->pc);
8984 dc->condjmp = 0;
8988 done_generating:
8989 gen_icount_end(tb, num_insns);
8990 *gen_opc_ptr = INDEX_op_end;
8992 #ifdef DEBUG_DISAS
8993 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
8994 qemu_log("----------------\n");
8995 qemu_log("IN: %s\n", lookup_symbol(pc_start));
8996 log_target_disas(pc_start, dc->pc - pc_start, env->thumb);
8997 qemu_log("\n");
8999 #endif
9000 if (search_pc) {
9001 j = gen_opc_ptr - gen_opc_buf;
9002 lj++;
9003 while (lj <= j)
9004 gen_opc_instr_start[lj++] = 0;
9005 } else {
9006 tb->size = dc->pc - pc_start;
9007 tb->icount = num_insns;
9011 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
9013 gen_intermediate_code_internal(env, tb, 0);
9016 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
9018 gen_intermediate_code_internal(env, tb, 1);
9021 static const char *cpu_mode_names[16] = {
9022 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9023 "???", "???", "???", "und", "???", "???", "???", "sys"
9026 void cpu_dump_state(CPUState *env, FILE *f,
9027 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
9028 int flags)
9030 int i;
9031 #if 0
9032 union {
9033 uint32_t i;
9034 float s;
9035 } s0, s1;
9036 CPU_DoubleU d;
9037 /* ??? This assumes float64 and double have the same layout.
9038 Oh well, it's only debug dumps. */
9039 union {
9040 float64 f64;
9041 double d;
9042 } d0;
9043 #endif
9044 uint32_t psr;
9046 for(i=0;i<16;i++) {
9047 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
9048 if ((i % 4) == 3)
9049 cpu_fprintf(f, "\n");
9050 else
9051 cpu_fprintf(f, " ");
9053 psr = cpsr_read(env);
9054 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
9055 psr,
9056 psr & (1 << 31) ? 'N' : '-',
9057 psr & (1 << 30) ? 'Z' : '-',
9058 psr & (1 << 29) ? 'C' : '-',
9059 psr & (1 << 28) ? 'V' : '-',
9060 psr & CPSR_T ? 'T' : 'A',
9061 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
9063 #if 0
9064 for (i = 0; i < 16; i++) {
9065 d.d = env->vfp.regs[i];
9066 s0.i = d.l.lower;
9067 s1.i = d.l.upper;
9068 d0.f64 = d.d;
9069 cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9070 i * 2, (int)s0.i, s0.s,
9071 i * 2 + 1, (int)s1.i, s1.s,
9072 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
9073 d0.d);
9075 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
9076 #endif
9079 void gen_pc_load(CPUState *env, TranslationBlock *tb,
9080 unsigned long searched_pc, int pc_pos, void *puc)
9082 env->regs[15] = gen_opc_pc[pc_pos];