Replace gen_adc with gen_add_carry.
[qemu/navara.git] / target-arm / translate.c
blobd1c13883ab452ed4196e3295920c3d5a2d41a14e
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_5 arm_feature(env, ARM_FEATURE_V5)
38 #define ENABLE_ARCH_5J 0
39 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
40 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
41 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
42 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
44 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
46 /* internal defines */
47 typedef struct DisasContext {
48 target_ulong pc;
49 int is_jmp;
50 /* Nonzero if this instruction has been conditionally skipped. */
51 int condjmp;
52 /* The label that will be jumped to when the instruction is skipped. */
53 int condlabel;
54 /* Thumb-2 condtional execution bits. */
55 int condexec_mask;
56 int condexec_cond;
57 struct TranslationBlock *tb;
58 int singlestep_enabled;
59 int thumb;
60 #if !defined(CONFIG_USER_ONLY)
61 int user;
62 #endif
63 } DisasContext;
65 #if defined(CONFIG_USER_ONLY)
66 #define IS_USER(s) 1
67 #else
68 #define IS_USER(s) (s->user)
69 #endif
71 /* These instructions trap after executing, so defer them until after the
72 conditional executions state has been updated. */
73 #define DISAS_WFI 4
74 #define DISAS_SWI 5
76 static TCGv_ptr cpu_env;
77 /* We reuse the same 64-bit temporaries for efficiency. */
78 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
79 static TCGv_i32 cpu_R[16];
81 /* FIXME: These should be removed. */
82 static TCGv cpu_F0s, cpu_F1s;
83 static TCGv_i64 cpu_F0d, cpu_F1d;
85 #include "gen-icount.h"
87 static const char *regnames[] =
88 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
89 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
91 /* initialize TCG globals. */
92 void arm_translate_init(void)
94 int i;
96 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
98 for (i = 0; i < 16; i++) {
99 cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
100 offsetof(CPUState, regs[i]),
101 regnames[i]);
104 #define GEN_HELPER 2
105 #include "helpers.h"
108 static int num_temps;
110 /* Allocate a temporary variable. */
111 static TCGv_i32 new_tmp(void)
113 num_temps++;
114 return tcg_temp_new_i32();
117 /* Release a temporary variable. */
118 static void dead_tmp(TCGv tmp)
120 tcg_temp_free(tmp);
121 num_temps--;
124 static inline TCGv load_cpu_offset(int offset)
126 TCGv tmp = new_tmp();
127 tcg_gen_ld_i32(tmp, cpu_env, offset);
128 return tmp;
131 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
133 static inline void store_cpu_offset(TCGv var, int offset)
135 tcg_gen_st_i32(var, cpu_env, offset);
136 dead_tmp(var);
139 #define store_cpu_field(var, name) \
140 store_cpu_offset(var, offsetof(CPUState, name))
142 /* Set a variable to the value of a CPU register. */
143 static void load_reg_var(DisasContext *s, TCGv var, int reg)
145 if (reg == 15) {
146 uint32_t addr;
147 /* normaly, since we updated PC, we need only to add one insn */
148 if (s->thumb)
149 addr = (long)s->pc + 2;
150 else
151 addr = (long)s->pc + 4;
152 tcg_gen_movi_i32(var, addr);
153 } else {
154 tcg_gen_mov_i32(var, cpu_R[reg]);
158 /* Create a new temporary and set it to the value of a CPU register. */
159 static inline TCGv load_reg(DisasContext *s, int reg)
161 TCGv tmp = new_tmp();
162 load_reg_var(s, tmp, reg);
163 return tmp;
166 /* Set a CPU register. The source must be a temporary and will be
167 marked as dead. */
168 static void store_reg(DisasContext *s, int reg, TCGv var)
170 if (reg == 15) {
171 tcg_gen_andi_i32(var, var, ~1);
172 s->is_jmp = DISAS_JUMP;
174 tcg_gen_mov_i32(cpu_R[reg], var);
175 dead_tmp(var);
178 /* Value extensions. */
179 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
180 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
181 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
182 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
184 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
185 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
188 #define gen_set_cpsr(var, mask) gen_helper_cpsr_write(var, tcg_const_i32(mask))
189 /* Set NZCV flags from the high 4 bits of var. */
190 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
192 static void gen_exception(int excp)
194 TCGv tmp = new_tmp();
195 tcg_gen_movi_i32(tmp, excp);
196 gen_helper_exception(tmp);
197 dead_tmp(tmp);
200 static void gen_smul_dual(TCGv a, TCGv b)
202 TCGv tmp1 = new_tmp();
203 TCGv tmp2 = new_tmp();
204 tcg_gen_ext16s_i32(tmp1, a);
205 tcg_gen_ext16s_i32(tmp2, b);
206 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
207 dead_tmp(tmp2);
208 tcg_gen_sari_i32(a, a, 16);
209 tcg_gen_sari_i32(b, b, 16);
210 tcg_gen_mul_i32(b, b, a);
211 tcg_gen_mov_i32(a, tmp1);
212 dead_tmp(tmp1);
215 /* Byteswap each halfword. */
216 static void gen_rev16(TCGv var)
218 TCGv tmp = new_tmp();
219 tcg_gen_shri_i32(tmp, var, 8);
220 tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
221 tcg_gen_shli_i32(var, var, 8);
222 tcg_gen_andi_i32(var, var, 0xff00ff00);
223 tcg_gen_or_i32(var, var, tmp);
224 dead_tmp(tmp);
227 /* Byteswap low halfword and sign extend. */
228 static void gen_revsh(TCGv var)
230 TCGv tmp = new_tmp();
231 tcg_gen_shri_i32(tmp, var, 8);
232 tcg_gen_andi_i32(tmp, tmp, 0x00ff);
233 tcg_gen_shli_i32(var, var, 8);
234 tcg_gen_ext8s_i32(var, var);
235 tcg_gen_or_i32(var, var, tmp);
236 dead_tmp(tmp);
239 /* Unsigned bitfield extract. */
240 static void gen_ubfx(TCGv var, int shift, uint32_t mask)
242 if (shift)
243 tcg_gen_shri_i32(var, var, shift);
244 tcg_gen_andi_i32(var, var, mask);
247 /* Signed bitfield extract. */
248 static void gen_sbfx(TCGv var, int shift, int width)
250 uint32_t signbit;
252 if (shift)
253 tcg_gen_sari_i32(var, var, shift);
254 if (shift + width < 32) {
255 signbit = 1u << (width - 1);
256 tcg_gen_andi_i32(var, var, (1u << width) - 1);
257 tcg_gen_xori_i32(var, var, signbit);
258 tcg_gen_subi_i32(var, var, signbit);
262 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
263 static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
265 tcg_gen_andi_i32(val, val, mask);
266 tcg_gen_shli_i32(val, val, shift);
267 tcg_gen_andi_i32(base, base, ~(mask << shift));
268 tcg_gen_or_i32(dest, base, val);
271 /* Round the top 32 bits of a 64-bit value. */
272 static void gen_roundqd(TCGv a, TCGv b)
274 tcg_gen_shri_i32(a, a, 31);
275 tcg_gen_add_i32(a, a, b);
278 /* FIXME: Most targets have native widening multiplication.
279 It would be good to use that instead of a full wide multiply. */
280 /* 32x32->64 multiply. Marks inputs as dead. */
281 static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b)
283 TCGv_i64 tmp1 = tcg_temp_new_i64();
284 TCGv_i64 tmp2 = tcg_temp_new_i64();
286 tcg_gen_extu_i32_i64(tmp1, a);
287 dead_tmp(a);
288 tcg_gen_extu_i32_i64(tmp2, b);
289 dead_tmp(b);
290 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
291 return tmp1;
294 static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
296 TCGv_i64 tmp1 = tcg_temp_new_i64();
297 TCGv_i64 tmp2 = tcg_temp_new_i64();
299 tcg_gen_ext_i32_i64(tmp1, a);
300 dead_tmp(a);
301 tcg_gen_ext_i32_i64(tmp2, b);
302 dead_tmp(b);
303 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
304 return tmp1;
307 /* Unsigned 32x32->64 multiply. */
308 static void gen_mull(TCGv a, TCGv b)
310 TCGv_i64 tmp1 = tcg_temp_new_i64();
311 TCGv_i64 tmp2 = tcg_temp_new_i64();
313 tcg_gen_extu_i32_i64(tmp1, a);
314 tcg_gen_extu_i32_i64(tmp2, b);
315 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
316 tcg_gen_trunc_i64_i32(a, tmp1);
317 tcg_gen_shri_i64(tmp1, tmp1, 32);
318 tcg_gen_trunc_i64_i32(b, tmp1);
321 /* Signed 32x32->64 multiply. */
322 static void gen_imull(TCGv a, TCGv b)
324 TCGv_i64 tmp1 = tcg_temp_new_i64();
325 TCGv_i64 tmp2 = tcg_temp_new_i64();
327 tcg_gen_ext_i32_i64(tmp1, a);
328 tcg_gen_ext_i32_i64(tmp2, b);
329 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
330 tcg_gen_trunc_i64_i32(a, tmp1);
331 tcg_gen_shri_i64(tmp1, tmp1, 32);
332 tcg_gen_trunc_i64_i32(b, tmp1);
335 /* Swap low and high halfwords. */
336 static void gen_swap_half(TCGv var)
338 TCGv tmp = new_tmp();
339 tcg_gen_shri_i32(tmp, var, 16);
340 tcg_gen_shli_i32(var, var, 16);
341 tcg_gen_or_i32(var, var, tmp);
342 dead_tmp(tmp);
345 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
346 tmp = (t0 ^ t1) & 0x8000;
347 t0 &= ~0x8000;
348 t1 &= ~0x8000;
349 t0 = (t0 + t1) ^ tmp;
352 static void gen_add16(TCGv t0, TCGv t1)
354 TCGv tmp = new_tmp();
355 tcg_gen_xor_i32(tmp, t0, t1);
356 tcg_gen_andi_i32(tmp, tmp, 0x8000);
357 tcg_gen_andi_i32(t0, t0, ~0x8000);
358 tcg_gen_andi_i32(t1, t1, ~0x8000);
359 tcg_gen_add_i32(t0, t0, t1);
360 tcg_gen_xor_i32(t0, t0, tmp);
361 dead_tmp(tmp);
362 dead_tmp(t1);
365 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
367 /* Set CF to the top bit of var. */
368 static void gen_set_CF_bit31(TCGv var)
370 TCGv tmp = new_tmp();
371 tcg_gen_shri_i32(tmp, var, 31);
372 gen_set_CF(tmp);
373 dead_tmp(tmp);
376 /* Set N and Z flags from var. */
377 static inline void gen_logic_CC(TCGv var)
379 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF));
380 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF));
383 /* dest = T0 + T1 + CF. */
384 static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
386 TCGv tmp;
387 tcg_gen_add_i32(dest, t0, t1);
388 tmp = load_cpu_field(CF);
389 tcg_gen_add_i32(dest, dest, tmp);
390 dead_tmp(tmp);
393 /* dest = T0 - T1 + CF - 1. */
394 static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
396 TCGv tmp;
397 tcg_gen_sub_i32(dest, t0, t1);
398 tmp = load_cpu_field(CF);
399 tcg_gen_add_i32(dest, dest, tmp);
400 tcg_gen_subi_i32(dest, dest, 1);
401 dead_tmp(tmp);
404 /* T0 &= ~T1. Clobbers T1. */
405 /* FIXME: Implement bic natively. */
406 static inline void tcg_gen_bic_i32(TCGv dest, TCGv t0, TCGv t1)
408 TCGv tmp = new_tmp();
409 tcg_gen_not_i32(tmp, t1);
410 tcg_gen_and_i32(dest, t0, tmp);
411 dead_tmp(tmp);
414 /* FIXME: Implement this natively. */
415 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
417 static void shifter_out_im(TCGv var, int shift)
419 TCGv tmp = new_tmp();
420 if (shift == 0) {
421 tcg_gen_andi_i32(tmp, var, 1);
422 } else {
423 tcg_gen_shri_i32(tmp, var, shift);
424 if (shift != 31)
425 tcg_gen_andi_i32(tmp, tmp, 1);
427 gen_set_CF(tmp);
428 dead_tmp(tmp);
431 /* Shift by immediate. Includes special handling for shift == 0. */
432 static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
434 switch (shiftop) {
435 case 0: /* LSL */
436 if (shift != 0) {
437 if (flags)
438 shifter_out_im(var, 32 - shift);
439 tcg_gen_shli_i32(var, var, shift);
441 break;
442 case 1: /* LSR */
443 if (shift == 0) {
444 if (flags) {
445 tcg_gen_shri_i32(var, var, 31);
446 gen_set_CF(var);
448 tcg_gen_movi_i32(var, 0);
449 } else {
450 if (flags)
451 shifter_out_im(var, shift - 1);
452 tcg_gen_shri_i32(var, var, shift);
454 break;
455 case 2: /* ASR */
456 if (shift == 0)
457 shift = 32;
458 if (flags)
459 shifter_out_im(var, shift - 1);
460 if (shift == 32)
461 shift = 31;
462 tcg_gen_sari_i32(var, var, shift);
463 break;
464 case 3: /* ROR/RRX */
465 if (shift != 0) {
466 if (flags)
467 shifter_out_im(var, shift - 1);
468 tcg_gen_rotri_i32(var, var, shift); break;
469 } else {
470 TCGv tmp = load_cpu_field(CF);
471 if (flags)
472 shifter_out_im(var, 0);
473 tcg_gen_shri_i32(var, var, 1);
474 tcg_gen_shli_i32(tmp, tmp, 31);
475 tcg_gen_or_i32(var, var, tmp);
476 dead_tmp(tmp);
481 static inline void gen_arm_shift_reg(TCGv var, int shiftop,
482 TCGv shift, int flags)
484 if (flags) {
485 switch (shiftop) {
486 case 0: gen_helper_shl_cc(var, var, shift); break;
487 case 1: gen_helper_shr_cc(var, var, shift); break;
488 case 2: gen_helper_sar_cc(var, var, shift); break;
489 case 3: gen_helper_ror_cc(var, var, shift); break;
491 } else {
492 switch (shiftop) {
493 case 0: gen_helper_shl(var, var, shift); break;
494 case 1: gen_helper_shr(var, var, shift); break;
495 case 2: gen_helper_sar(var, var, shift); break;
496 case 3: gen_helper_ror(var, var, shift); break;
499 dead_tmp(shift);
502 #define PAS_OP(pfx) \
503 switch (op2) { \
504 case 0: gen_pas_helper(glue(pfx,add16)); break; \
505 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
506 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
507 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
508 case 4: gen_pas_helper(glue(pfx,add8)); break; \
509 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
511 static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
513 TCGv_ptr tmp;
515 switch (op1) {
516 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
517 case 1:
518 tmp = tcg_temp_new_ptr();
519 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
520 PAS_OP(s)
521 break;
522 case 5:
523 tmp = tcg_temp_new_ptr();
524 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
525 PAS_OP(u)
526 break;
527 #undef gen_pas_helper
528 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
529 case 2:
530 PAS_OP(q);
531 break;
532 case 3:
533 PAS_OP(sh);
534 break;
535 case 6:
536 PAS_OP(uq);
537 break;
538 case 7:
539 PAS_OP(uh);
540 break;
541 #undef gen_pas_helper
544 #undef PAS_OP
546 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
547 #define PAS_OP(pfx) \
548 switch (op2) { \
549 case 0: gen_pas_helper(glue(pfx,add8)); break; \
550 case 1: gen_pas_helper(glue(pfx,add16)); break; \
551 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
552 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
553 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
554 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
556 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
558 TCGv_ptr tmp;
560 switch (op1) {
561 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
562 case 0:
563 tmp = tcg_temp_new_ptr();
564 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
565 PAS_OP(s)
566 break;
567 case 4:
568 tmp = tcg_temp_new_ptr();
569 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
570 PAS_OP(u)
571 break;
572 #undef gen_pas_helper
573 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
574 case 1:
575 PAS_OP(q);
576 break;
577 case 2:
578 PAS_OP(sh);
579 break;
580 case 5:
581 PAS_OP(uq);
582 break;
583 case 6:
584 PAS_OP(uh);
585 break;
586 #undef gen_pas_helper
589 #undef PAS_OP
591 static void gen_test_cc(int cc, int label)
593 TCGv tmp;
594 TCGv tmp2;
595 int inv;
597 switch (cc) {
598 case 0: /* eq: Z */
599 tmp = load_cpu_field(ZF);
600 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
601 break;
602 case 1: /* ne: !Z */
603 tmp = load_cpu_field(ZF);
604 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
605 break;
606 case 2: /* cs: C */
607 tmp = load_cpu_field(CF);
608 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
609 break;
610 case 3: /* cc: !C */
611 tmp = load_cpu_field(CF);
612 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
613 break;
614 case 4: /* mi: N */
615 tmp = load_cpu_field(NF);
616 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
617 break;
618 case 5: /* pl: !N */
619 tmp = load_cpu_field(NF);
620 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
621 break;
622 case 6: /* vs: V */
623 tmp = load_cpu_field(VF);
624 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
625 break;
626 case 7: /* vc: !V */
627 tmp = load_cpu_field(VF);
628 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
629 break;
630 case 8: /* hi: C && !Z */
631 inv = gen_new_label();
632 tmp = load_cpu_field(CF);
633 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
634 dead_tmp(tmp);
635 tmp = load_cpu_field(ZF);
636 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
637 gen_set_label(inv);
638 break;
639 case 9: /* ls: !C || Z */
640 tmp = load_cpu_field(CF);
641 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
642 dead_tmp(tmp);
643 tmp = load_cpu_field(ZF);
644 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
645 break;
646 case 10: /* ge: N == V -> N ^ V == 0 */
647 tmp = load_cpu_field(VF);
648 tmp2 = load_cpu_field(NF);
649 tcg_gen_xor_i32(tmp, tmp, tmp2);
650 dead_tmp(tmp2);
651 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
652 break;
653 case 11: /* lt: N != V -> N ^ V != 0 */
654 tmp = load_cpu_field(VF);
655 tmp2 = load_cpu_field(NF);
656 tcg_gen_xor_i32(tmp, tmp, tmp2);
657 dead_tmp(tmp2);
658 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
659 break;
660 case 12: /* gt: !Z && N == V */
661 inv = gen_new_label();
662 tmp = load_cpu_field(ZF);
663 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
664 dead_tmp(tmp);
665 tmp = load_cpu_field(VF);
666 tmp2 = load_cpu_field(NF);
667 tcg_gen_xor_i32(tmp, tmp, tmp2);
668 dead_tmp(tmp2);
669 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
670 gen_set_label(inv);
671 break;
672 case 13: /* le: Z || N != V */
673 tmp = load_cpu_field(ZF);
674 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
675 dead_tmp(tmp);
676 tmp = load_cpu_field(VF);
677 tmp2 = load_cpu_field(NF);
678 tcg_gen_xor_i32(tmp, tmp, tmp2);
679 dead_tmp(tmp2);
680 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
681 break;
682 default:
683 fprintf(stderr, "Bad condition code 0x%x\n", cc);
684 abort();
686 dead_tmp(tmp);
689 static const uint8_t table_logic_cc[16] = {
690 1, /* and */
691 1, /* xor */
692 0, /* sub */
693 0, /* rsb */
694 0, /* add */
695 0, /* adc */
696 0, /* sbc */
697 0, /* rsc */
698 1, /* andl */
699 1, /* xorl */
700 0, /* cmp */
701 0, /* cmn */
702 1, /* orr */
703 1, /* mov */
704 1, /* bic */
705 1, /* mvn */
708 /* Set PC and Thumb state from an immediate address. */
709 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
711 TCGv tmp;
713 s->is_jmp = DISAS_UPDATE;
714 if (s->thumb != (addr & 1)) {
715 tmp = new_tmp();
716 tcg_gen_movi_i32(tmp, addr & 1);
717 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
718 dead_tmp(tmp);
720 tcg_gen_mov_i32(cpu_R[15], addr & ~1);
723 /* Set PC and Thumb state from var. var is marked as dead. */
724 static inline void gen_bx(DisasContext *s, TCGv var)
726 s->is_jmp = DISAS_UPDATE;
727 tcg_gen_andi_i32(cpu_R[15], var, ~1);
728 tcg_gen_andi_i32(var, var, 1);
729 store_cpu_field(var, thumb);
732 /* Variant of store_reg which uses branch&exchange logic when storing
733 to r15 in ARM architecture v7 and above. The source must be a temporary
734 and will be marked as dead. */
735 static inline void store_reg_bx(CPUState *env, DisasContext *s,
736 int reg, TCGv var)
738 if (reg == 15 && ENABLE_ARCH_7) {
739 gen_bx(s, var);
740 } else {
741 store_reg(s, reg, var);
745 static inline TCGv gen_ld8s(TCGv addr, int index)
747 TCGv tmp = new_tmp();
748 tcg_gen_qemu_ld8s(tmp, addr, index);
749 return tmp;
751 static inline TCGv gen_ld8u(TCGv addr, int index)
753 TCGv tmp = new_tmp();
754 tcg_gen_qemu_ld8u(tmp, addr, index);
755 return tmp;
757 static inline TCGv gen_ld16s(TCGv addr, int index)
759 TCGv tmp = new_tmp();
760 tcg_gen_qemu_ld16s(tmp, addr, index);
761 return tmp;
763 static inline TCGv gen_ld16u(TCGv addr, int index)
765 TCGv tmp = new_tmp();
766 tcg_gen_qemu_ld16u(tmp, addr, index);
767 return tmp;
769 static inline TCGv gen_ld32(TCGv addr, int index)
771 TCGv tmp = new_tmp();
772 tcg_gen_qemu_ld32u(tmp, addr, index);
773 return tmp;
775 static inline void gen_st8(TCGv val, TCGv addr, int index)
777 tcg_gen_qemu_st8(val, addr, index);
778 dead_tmp(val);
780 static inline void gen_st16(TCGv val, TCGv addr, int index)
782 tcg_gen_qemu_st16(val, addr, index);
783 dead_tmp(val);
785 static inline void gen_st32(TCGv val, TCGv addr, int index)
787 tcg_gen_qemu_st32(val, addr, index);
788 dead_tmp(val);
791 static inline void gen_set_pc_im(uint32_t val)
793 tcg_gen_movi_i32(cpu_R[15], val);
796 /* Force a TB lookup after an instruction that changes the CPU state. */
797 static inline void gen_lookup_tb(DisasContext *s)
799 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
800 s->is_jmp = DISAS_UPDATE;
803 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
804 TCGv var)
806 int val, rm, shift, shiftop;
807 TCGv offset;
809 if (!(insn & (1 << 25))) {
810 /* immediate */
811 val = insn & 0xfff;
812 if (!(insn & (1 << 23)))
813 val = -val;
814 if (val != 0)
815 tcg_gen_addi_i32(var, var, val);
816 } else {
817 /* shift/register */
818 rm = (insn) & 0xf;
819 shift = (insn >> 7) & 0x1f;
820 shiftop = (insn >> 5) & 3;
821 offset = load_reg(s, rm);
822 gen_arm_shift_im(offset, shiftop, shift, 0);
823 if (!(insn & (1 << 23)))
824 tcg_gen_sub_i32(var, var, offset);
825 else
826 tcg_gen_add_i32(var, var, offset);
827 dead_tmp(offset);
831 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
832 int extra, TCGv var)
834 int val, rm;
835 TCGv offset;
837 if (insn & (1 << 22)) {
838 /* immediate */
839 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
840 if (!(insn & (1 << 23)))
841 val = -val;
842 val += extra;
843 if (val != 0)
844 tcg_gen_addi_i32(var, var, val);
845 } else {
846 /* register */
847 if (extra)
848 tcg_gen_addi_i32(var, var, extra);
849 rm = (insn) & 0xf;
850 offset = load_reg(s, rm);
851 if (!(insn & (1 << 23)))
852 tcg_gen_sub_i32(var, var, offset);
853 else
854 tcg_gen_add_i32(var, var, offset);
855 dead_tmp(offset);
859 #define VFP_OP2(name) \
860 static inline void gen_vfp_##name(int dp) \
862 if (dp) \
863 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
864 else \
865 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
868 VFP_OP2(add)
869 VFP_OP2(sub)
870 VFP_OP2(mul)
871 VFP_OP2(div)
873 #undef VFP_OP2
875 static inline void gen_vfp_abs(int dp)
877 if (dp)
878 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
879 else
880 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
883 static inline void gen_vfp_neg(int dp)
885 if (dp)
886 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
887 else
888 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
891 static inline void gen_vfp_sqrt(int dp)
893 if (dp)
894 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
895 else
896 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
899 static inline void gen_vfp_cmp(int dp)
901 if (dp)
902 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
903 else
904 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
907 static inline void gen_vfp_cmpe(int dp)
909 if (dp)
910 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
911 else
912 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
915 static inline void gen_vfp_F1_ld0(int dp)
917 if (dp)
918 tcg_gen_movi_i64(cpu_F1d, 0);
919 else
920 tcg_gen_movi_i32(cpu_F1s, 0);
923 static inline void gen_vfp_uito(int dp)
925 if (dp)
926 gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
927 else
928 gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
931 static inline void gen_vfp_sito(int dp)
933 if (dp)
934 gen_helper_vfp_sitod(cpu_F0d, cpu_F0s, cpu_env);
935 else
936 gen_helper_vfp_sitos(cpu_F0s, cpu_F0s, cpu_env);
939 static inline void gen_vfp_toui(int dp)
941 if (dp)
942 gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env);
943 else
944 gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env);
947 static inline void gen_vfp_touiz(int dp)
949 if (dp)
950 gen_helper_vfp_touizd(cpu_F0s, cpu_F0d, cpu_env);
951 else
952 gen_helper_vfp_touizs(cpu_F0s, cpu_F0s, cpu_env);
955 static inline void gen_vfp_tosi(int dp)
957 if (dp)
958 gen_helper_vfp_tosid(cpu_F0s, cpu_F0d, cpu_env);
959 else
960 gen_helper_vfp_tosis(cpu_F0s, cpu_F0s, cpu_env);
963 static inline void gen_vfp_tosiz(int dp)
965 if (dp)
966 gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env);
967 else
968 gen_helper_vfp_tosizs(cpu_F0s, cpu_F0s, cpu_env);
971 #define VFP_GEN_FIX(name) \
972 static inline void gen_vfp_##name(int dp, int shift) \
974 if (dp) \
975 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
976 else \
977 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
979 VFP_GEN_FIX(tosh)
980 VFP_GEN_FIX(tosl)
981 VFP_GEN_FIX(touh)
982 VFP_GEN_FIX(toul)
983 VFP_GEN_FIX(shto)
984 VFP_GEN_FIX(slto)
985 VFP_GEN_FIX(uhto)
986 VFP_GEN_FIX(ulto)
987 #undef VFP_GEN_FIX
989 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv addr)
991 if (dp)
992 tcg_gen_qemu_ld64(cpu_F0d, addr, IS_USER(s));
993 else
994 tcg_gen_qemu_ld32u(cpu_F0s, addr, IS_USER(s));
997 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv addr)
999 if (dp)
1000 tcg_gen_qemu_st64(cpu_F0d, addr, IS_USER(s));
1001 else
1002 tcg_gen_qemu_st32(cpu_F0s, addr, IS_USER(s));
1005 static inline long
1006 vfp_reg_offset (int dp, int reg)
1008 if (dp)
1009 return offsetof(CPUARMState, vfp.regs[reg]);
1010 else if (reg & 1) {
1011 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1012 + offsetof(CPU_DoubleU, l.upper);
1013 } else {
1014 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1015 + offsetof(CPU_DoubleU, l.lower);
1019 /* Return the offset of a 32-bit piece of a NEON register.
1020 zero is the least significant end of the register. */
1021 static inline long
1022 neon_reg_offset (int reg, int n)
1024 int sreg;
1025 sreg = reg * 2 + n;
1026 return vfp_reg_offset(0, sreg);
1029 static TCGv neon_load_reg(int reg, int pass)
1031 TCGv tmp = new_tmp();
1032 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1033 return tmp;
1036 static void neon_store_reg(int reg, int pass, TCGv var)
1038 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1039 dead_tmp(var);
1042 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1044 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1047 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1049 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1052 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1053 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1054 #define tcg_gen_st_f32 tcg_gen_st_i32
1055 #define tcg_gen_st_f64 tcg_gen_st_i64
1057 static inline void gen_mov_F0_vreg(int dp, int reg)
1059 if (dp)
1060 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1061 else
1062 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1065 static inline void gen_mov_F1_vreg(int dp, int reg)
1067 if (dp)
1068 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1069 else
1070 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1073 static inline void gen_mov_vreg_F0(int dp, int reg)
1075 if (dp)
1076 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1077 else
1078 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1081 #define ARM_CP_RW_BIT (1 << 20)
1083 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1085 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1088 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1090 tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1093 static inline TCGv iwmmxt_load_creg(int reg)
1095 TCGv var = new_tmp();
1096 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1097 return var;
1100 static inline void iwmmxt_store_creg(int reg, TCGv var)
1102 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1105 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1107 iwmmxt_store_reg(cpu_M0, rn);
1110 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1112 iwmmxt_load_reg(cpu_M0, rn);
1115 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1117 iwmmxt_load_reg(cpu_V1, rn);
1118 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1121 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1123 iwmmxt_load_reg(cpu_V1, rn);
1124 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1127 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1129 iwmmxt_load_reg(cpu_V1, rn);
1130 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1133 #define IWMMXT_OP(name) \
1134 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1136 iwmmxt_load_reg(cpu_V1, rn); \
1137 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1140 #define IWMMXT_OP_ENV(name) \
1141 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1143 iwmmxt_load_reg(cpu_V1, rn); \
1144 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1147 #define IWMMXT_OP_ENV_SIZE(name) \
1148 IWMMXT_OP_ENV(name##b) \
1149 IWMMXT_OP_ENV(name##w) \
1150 IWMMXT_OP_ENV(name##l)
1152 #define IWMMXT_OP_ENV1(name) \
1153 static inline void gen_op_iwmmxt_##name##_M0(void) \
1155 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1158 IWMMXT_OP(maddsq)
1159 IWMMXT_OP(madduq)
1160 IWMMXT_OP(sadb)
1161 IWMMXT_OP(sadw)
1162 IWMMXT_OP(mulslw)
1163 IWMMXT_OP(mulshw)
1164 IWMMXT_OP(mululw)
1165 IWMMXT_OP(muluhw)
1166 IWMMXT_OP(macsw)
1167 IWMMXT_OP(macuw)
1169 IWMMXT_OP_ENV_SIZE(unpackl)
1170 IWMMXT_OP_ENV_SIZE(unpackh)
1172 IWMMXT_OP_ENV1(unpacklub)
1173 IWMMXT_OP_ENV1(unpackluw)
1174 IWMMXT_OP_ENV1(unpacklul)
1175 IWMMXT_OP_ENV1(unpackhub)
1176 IWMMXT_OP_ENV1(unpackhuw)
1177 IWMMXT_OP_ENV1(unpackhul)
1178 IWMMXT_OP_ENV1(unpacklsb)
1179 IWMMXT_OP_ENV1(unpacklsw)
1180 IWMMXT_OP_ENV1(unpacklsl)
1181 IWMMXT_OP_ENV1(unpackhsb)
1182 IWMMXT_OP_ENV1(unpackhsw)
1183 IWMMXT_OP_ENV1(unpackhsl)
1185 IWMMXT_OP_ENV_SIZE(cmpeq)
1186 IWMMXT_OP_ENV_SIZE(cmpgtu)
1187 IWMMXT_OP_ENV_SIZE(cmpgts)
1189 IWMMXT_OP_ENV_SIZE(mins)
1190 IWMMXT_OP_ENV_SIZE(minu)
1191 IWMMXT_OP_ENV_SIZE(maxs)
1192 IWMMXT_OP_ENV_SIZE(maxu)
1194 IWMMXT_OP_ENV_SIZE(subn)
1195 IWMMXT_OP_ENV_SIZE(addn)
1196 IWMMXT_OP_ENV_SIZE(subu)
1197 IWMMXT_OP_ENV_SIZE(addu)
1198 IWMMXT_OP_ENV_SIZE(subs)
1199 IWMMXT_OP_ENV_SIZE(adds)
1201 IWMMXT_OP_ENV(avgb0)
1202 IWMMXT_OP_ENV(avgb1)
1203 IWMMXT_OP_ENV(avgw0)
1204 IWMMXT_OP_ENV(avgw1)
1206 IWMMXT_OP(msadb)
1208 IWMMXT_OP_ENV(packuw)
1209 IWMMXT_OP_ENV(packul)
1210 IWMMXT_OP_ENV(packuq)
1211 IWMMXT_OP_ENV(packsw)
1212 IWMMXT_OP_ENV(packsl)
1213 IWMMXT_OP_ENV(packsq)
1215 static void gen_op_iwmmxt_set_mup(void)
1217 TCGv tmp;
1218 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1219 tcg_gen_ori_i32(tmp, tmp, 2);
1220 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1223 static void gen_op_iwmmxt_set_cup(void)
1225 TCGv tmp;
1226 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1227 tcg_gen_ori_i32(tmp, tmp, 1);
1228 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1231 static void gen_op_iwmmxt_setpsr_nz(void)
1233 TCGv tmp = new_tmp();
1234 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1235 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1238 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1240 iwmmxt_load_reg(cpu_V1, rn);
1241 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1242 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1245 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn, TCGv dest)
1247 int rd;
1248 uint32_t offset;
1249 TCGv tmp;
1251 rd = (insn >> 16) & 0xf;
1252 tmp = load_reg(s, rd);
1254 offset = (insn & 0xff) << ((insn >> 7) & 2);
1255 if (insn & (1 << 24)) {
1256 /* Pre indexed */
1257 if (insn & (1 << 23))
1258 tcg_gen_addi_i32(tmp, tmp, offset);
1259 else
1260 tcg_gen_addi_i32(tmp, tmp, -offset);
1261 tcg_gen_mov_i32(dest, tmp);
1262 if (insn & (1 << 21))
1263 store_reg(s, rd, tmp);
1264 else
1265 dead_tmp(tmp);
1266 } else if (insn & (1 << 21)) {
1267 /* Post indexed */
1268 tcg_gen_mov_i32(dest, tmp);
1269 if (insn & (1 << 23))
1270 tcg_gen_addi_i32(tmp, tmp, offset);
1271 else
1272 tcg_gen_addi_i32(tmp, tmp, -offset);
1273 store_reg(s, rd, tmp);
1274 } else if (!(insn & (1 << 23)))
1275 return 1;
1276 return 0;
1279 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv dest)
1281 int rd = (insn >> 0) & 0xf;
1282 TCGv tmp;
1284 if (insn & (1 << 8)) {
1285 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1286 return 1;
1287 } else {
1288 tmp = iwmmxt_load_creg(rd);
1290 } else {
1291 tmp = new_tmp();
1292 iwmmxt_load_reg(cpu_V0, rd);
1293 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
1295 tcg_gen_andi_i32(tmp, tmp, mask);
1296 tcg_gen_mov_i32(dest, tmp);
1297 dead_tmp(tmp);
1298 return 0;
1301 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1302 (ie. an undefined instruction). */
1303 static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1305 int rd, wrd;
1306 int rdhi, rdlo, rd0, rd1, i;
1307 TCGv addr;
1308 TCGv tmp, tmp2, tmp3;
1310 if ((insn & 0x0e000e00) == 0x0c000000) {
1311 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1312 wrd = insn & 0xf;
1313 rdlo = (insn >> 12) & 0xf;
1314 rdhi = (insn >> 16) & 0xf;
1315 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1316 iwmmxt_load_reg(cpu_V0, wrd);
1317 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
1318 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1319 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
1320 } else { /* TMCRR */
1321 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1322 iwmmxt_store_reg(cpu_V0, wrd);
1323 gen_op_iwmmxt_set_mup();
1325 return 0;
1328 wrd = (insn >> 12) & 0xf;
1329 addr = new_tmp();
1330 if (gen_iwmmxt_address(s, insn, addr)) {
1331 dead_tmp(addr);
1332 return 1;
1334 if (insn & ARM_CP_RW_BIT) {
1335 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1336 tmp = new_tmp();
1337 tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s));
1338 iwmmxt_store_creg(wrd, tmp);
1339 } else {
1340 i = 1;
1341 if (insn & (1 << 8)) {
1342 if (insn & (1 << 22)) { /* WLDRD */
1343 tcg_gen_qemu_ld64(cpu_M0, addr, IS_USER(s));
1344 i = 0;
1345 } else { /* WLDRW wRd */
1346 tmp = gen_ld32(addr, IS_USER(s));
1348 } else {
1349 if (insn & (1 << 22)) { /* WLDRH */
1350 tmp = gen_ld16u(addr, IS_USER(s));
1351 } else { /* WLDRB */
1352 tmp = gen_ld8u(addr, IS_USER(s));
1355 if (i) {
1356 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1357 dead_tmp(tmp);
1359 gen_op_iwmmxt_movq_wRn_M0(wrd);
1361 } else {
1362 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1363 tmp = iwmmxt_load_creg(wrd);
1364 gen_st32(tmp, addr, IS_USER(s));
1365 } else {
1366 gen_op_iwmmxt_movq_M0_wRn(wrd);
1367 tmp = new_tmp();
1368 if (insn & (1 << 8)) {
1369 if (insn & (1 << 22)) { /* WSTRD */
1370 dead_tmp(tmp);
1371 tcg_gen_qemu_st64(cpu_M0, addr, IS_USER(s));
1372 } else { /* WSTRW wRd */
1373 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1374 gen_st32(tmp, addr, IS_USER(s));
1376 } else {
1377 if (insn & (1 << 22)) { /* WSTRH */
1378 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1379 gen_st16(tmp, addr, IS_USER(s));
1380 } else { /* WSTRB */
1381 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1382 gen_st8(tmp, addr, IS_USER(s));
1387 return 0;
1390 if ((insn & 0x0f000000) != 0x0e000000)
1391 return 1;
1393 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1394 case 0x000: /* WOR */
1395 wrd = (insn >> 12) & 0xf;
1396 rd0 = (insn >> 0) & 0xf;
1397 rd1 = (insn >> 16) & 0xf;
1398 gen_op_iwmmxt_movq_M0_wRn(rd0);
1399 gen_op_iwmmxt_orq_M0_wRn(rd1);
1400 gen_op_iwmmxt_setpsr_nz();
1401 gen_op_iwmmxt_movq_wRn_M0(wrd);
1402 gen_op_iwmmxt_set_mup();
1403 gen_op_iwmmxt_set_cup();
1404 break;
1405 case 0x011: /* TMCR */
1406 if (insn & 0xf)
1407 return 1;
1408 rd = (insn >> 12) & 0xf;
1409 wrd = (insn >> 16) & 0xf;
1410 switch (wrd) {
1411 case ARM_IWMMXT_wCID:
1412 case ARM_IWMMXT_wCASF:
1413 break;
1414 case ARM_IWMMXT_wCon:
1415 gen_op_iwmmxt_set_cup();
1416 /* Fall through. */
1417 case ARM_IWMMXT_wCSSF:
1418 tmp = iwmmxt_load_creg(wrd);
1419 tmp2 = load_reg(s, rd);
1420 tcg_gen_bic_i32(tmp, tmp, tmp2);
1421 dead_tmp(tmp2);
1422 iwmmxt_store_creg(wrd, tmp);
1423 break;
1424 case ARM_IWMMXT_wCGR0:
1425 case ARM_IWMMXT_wCGR1:
1426 case ARM_IWMMXT_wCGR2:
1427 case ARM_IWMMXT_wCGR3:
1428 gen_op_iwmmxt_set_cup();
1429 tmp = load_reg(s, rd);
1430 iwmmxt_store_creg(wrd, tmp);
1431 break;
1432 default:
1433 return 1;
1435 break;
1436 case 0x100: /* WXOR */
1437 wrd = (insn >> 12) & 0xf;
1438 rd0 = (insn >> 0) & 0xf;
1439 rd1 = (insn >> 16) & 0xf;
1440 gen_op_iwmmxt_movq_M0_wRn(rd0);
1441 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1442 gen_op_iwmmxt_setpsr_nz();
1443 gen_op_iwmmxt_movq_wRn_M0(wrd);
1444 gen_op_iwmmxt_set_mup();
1445 gen_op_iwmmxt_set_cup();
1446 break;
1447 case 0x111: /* TMRC */
1448 if (insn & 0xf)
1449 return 1;
1450 rd = (insn >> 12) & 0xf;
1451 wrd = (insn >> 16) & 0xf;
1452 tmp = iwmmxt_load_creg(wrd);
1453 store_reg(s, rd, tmp);
1454 break;
1455 case 0x300: /* WANDN */
1456 wrd = (insn >> 12) & 0xf;
1457 rd0 = (insn >> 0) & 0xf;
1458 rd1 = (insn >> 16) & 0xf;
1459 gen_op_iwmmxt_movq_M0_wRn(rd0);
1460 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1461 gen_op_iwmmxt_andq_M0_wRn(rd1);
1462 gen_op_iwmmxt_setpsr_nz();
1463 gen_op_iwmmxt_movq_wRn_M0(wrd);
1464 gen_op_iwmmxt_set_mup();
1465 gen_op_iwmmxt_set_cup();
1466 break;
1467 case 0x200: /* WAND */
1468 wrd = (insn >> 12) & 0xf;
1469 rd0 = (insn >> 0) & 0xf;
1470 rd1 = (insn >> 16) & 0xf;
1471 gen_op_iwmmxt_movq_M0_wRn(rd0);
1472 gen_op_iwmmxt_andq_M0_wRn(rd1);
1473 gen_op_iwmmxt_setpsr_nz();
1474 gen_op_iwmmxt_movq_wRn_M0(wrd);
1475 gen_op_iwmmxt_set_mup();
1476 gen_op_iwmmxt_set_cup();
1477 break;
1478 case 0x810: case 0xa10: /* WMADD */
1479 wrd = (insn >> 12) & 0xf;
1480 rd0 = (insn >> 0) & 0xf;
1481 rd1 = (insn >> 16) & 0xf;
1482 gen_op_iwmmxt_movq_M0_wRn(rd0);
1483 if (insn & (1 << 21))
1484 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1485 else
1486 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1487 gen_op_iwmmxt_movq_wRn_M0(wrd);
1488 gen_op_iwmmxt_set_mup();
1489 break;
1490 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1491 wrd = (insn >> 12) & 0xf;
1492 rd0 = (insn >> 16) & 0xf;
1493 rd1 = (insn >> 0) & 0xf;
1494 gen_op_iwmmxt_movq_M0_wRn(rd0);
1495 switch ((insn >> 22) & 3) {
1496 case 0:
1497 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1498 break;
1499 case 1:
1500 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1501 break;
1502 case 2:
1503 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1504 break;
1505 case 3:
1506 return 1;
1508 gen_op_iwmmxt_movq_wRn_M0(wrd);
1509 gen_op_iwmmxt_set_mup();
1510 gen_op_iwmmxt_set_cup();
1511 break;
1512 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1513 wrd = (insn >> 12) & 0xf;
1514 rd0 = (insn >> 16) & 0xf;
1515 rd1 = (insn >> 0) & 0xf;
1516 gen_op_iwmmxt_movq_M0_wRn(rd0);
1517 switch ((insn >> 22) & 3) {
1518 case 0:
1519 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1520 break;
1521 case 1:
1522 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1523 break;
1524 case 2:
1525 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1526 break;
1527 case 3:
1528 return 1;
1530 gen_op_iwmmxt_movq_wRn_M0(wrd);
1531 gen_op_iwmmxt_set_mup();
1532 gen_op_iwmmxt_set_cup();
1533 break;
1534 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1535 wrd = (insn >> 12) & 0xf;
1536 rd0 = (insn >> 16) & 0xf;
1537 rd1 = (insn >> 0) & 0xf;
1538 gen_op_iwmmxt_movq_M0_wRn(rd0);
1539 if (insn & (1 << 22))
1540 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1541 else
1542 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1543 if (!(insn & (1 << 20)))
1544 gen_op_iwmmxt_addl_M0_wRn(wrd);
1545 gen_op_iwmmxt_movq_wRn_M0(wrd);
1546 gen_op_iwmmxt_set_mup();
1547 break;
1548 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1549 wrd = (insn >> 12) & 0xf;
1550 rd0 = (insn >> 16) & 0xf;
1551 rd1 = (insn >> 0) & 0xf;
1552 gen_op_iwmmxt_movq_M0_wRn(rd0);
1553 if (insn & (1 << 21)) {
1554 if (insn & (1 << 20))
1555 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1556 else
1557 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1558 } else {
1559 if (insn & (1 << 20))
1560 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1561 else
1562 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1564 gen_op_iwmmxt_movq_wRn_M0(wrd);
1565 gen_op_iwmmxt_set_mup();
1566 break;
1567 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1568 wrd = (insn >> 12) & 0xf;
1569 rd0 = (insn >> 16) & 0xf;
1570 rd1 = (insn >> 0) & 0xf;
1571 gen_op_iwmmxt_movq_M0_wRn(rd0);
1572 if (insn & (1 << 21))
1573 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1574 else
1575 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1576 if (!(insn & (1 << 20))) {
1577 iwmmxt_load_reg(cpu_V1, wrd);
1578 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1580 gen_op_iwmmxt_movq_wRn_M0(wrd);
1581 gen_op_iwmmxt_set_mup();
1582 break;
1583 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1584 wrd = (insn >> 12) & 0xf;
1585 rd0 = (insn >> 16) & 0xf;
1586 rd1 = (insn >> 0) & 0xf;
1587 gen_op_iwmmxt_movq_M0_wRn(rd0);
1588 switch ((insn >> 22) & 3) {
1589 case 0:
1590 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1591 break;
1592 case 1:
1593 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1594 break;
1595 case 2:
1596 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1597 break;
1598 case 3:
1599 return 1;
1601 gen_op_iwmmxt_movq_wRn_M0(wrd);
1602 gen_op_iwmmxt_set_mup();
1603 gen_op_iwmmxt_set_cup();
1604 break;
1605 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1606 wrd = (insn >> 12) & 0xf;
1607 rd0 = (insn >> 16) & 0xf;
1608 rd1 = (insn >> 0) & 0xf;
1609 gen_op_iwmmxt_movq_M0_wRn(rd0);
1610 if (insn & (1 << 22)) {
1611 if (insn & (1 << 20))
1612 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1613 else
1614 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1615 } else {
1616 if (insn & (1 << 20))
1617 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1618 else
1619 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1621 gen_op_iwmmxt_movq_wRn_M0(wrd);
1622 gen_op_iwmmxt_set_mup();
1623 gen_op_iwmmxt_set_cup();
1624 break;
1625 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1626 wrd = (insn >> 12) & 0xf;
1627 rd0 = (insn >> 16) & 0xf;
1628 rd1 = (insn >> 0) & 0xf;
1629 gen_op_iwmmxt_movq_M0_wRn(rd0);
1630 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1631 tcg_gen_andi_i32(tmp, tmp, 7);
1632 iwmmxt_load_reg(cpu_V1, rd1);
1633 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
1634 dead_tmp(tmp);
1635 gen_op_iwmmxt_movq_wRn_M0(wrd);
1636 gen_op_iwmmxt_set_mup();
1637 break;
1638 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1639 if (((insn >> 6) & 3) == 3)
1640 return 1;
1641 rd = (insn >> 12) & 0xf;
1642 wrd = (insn >> 16) & 0xf;
1643 tmp = load_reg(s, rd);
1644 gen_op_iwmmxt_movq_M0_wRn(wrd);
1645 switch ((insn >> 6) & 3) {
1646 case 0:
1647 tmp2 = tcg_const_i32(0xff);
1648 tmp3 = tcg_const_i32((insn & 7) << 3);
1649 break;
1650 case 1:
1651 tmp2 = tcg_const_i32(0xffff);
1652 tmp3 = tcg_const_i32((insn & 3) << 4);
1653 break;
1654 case 2:
1655 tmp2 = tcg_const_i32(0xffffffff);
1656 tmp3 = tcg_const_i32((insn & 1) << 5);
1657 break;
1658 default:
1659 TCGV_UNUSED(tmp2);
1660 TCGV_UNUSED(tmp3);
1662 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
1663 tcg_temp_free(tmp3);
1664 tcg_temp_free(tmp2);
1665 dead_tmp(tmp);
1666 gen_op_iwmmxt_movq_wRn_M0(wrd);
1667 gen_op_iwmmxt_set_mup();
1668 break;
1669 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1670 rd = (insn >> 12) & 0xf;
1671 wrd = (insn >> 16) & 0xf;
1672 if (rd == 15 || ((insn >> 22) & 3) == 3)
1673 return 1;
1674 gen_op_iwmmxt_movq_M0_wRn(wrd);
1675 tmp = new_tmp();
1676 switch ((insn >> 22) & 3) {
1677 case 0:
1678 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
1679 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1680 if (insn & 8) {
1681 tcg_gen_ext8s_i32(tmp, tmp);
1682 } else {
1683 tcg_gen_andi_i32(tmp, tmp, 0xff);
1685 break;
1686 case 1:
1687 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
1688 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1689 if (insn & 8) {
1690 tcg_gen_ext16s_i32(tmp, tmp);
1691 } else {
1692 tcg_gen_andi_i32(tmp, tmp, 0xffff);
1694 break;
1695 case 2:
1696 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
1697 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1698 break;
1700 store_reg(s, rd, tmp);
1701 break;
1702 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1703 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1704 return 1;
1705 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1706 switch ((insn >> 22) & 3) {
1707 case 0:
1708 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
1709 break;
1710 case 1:
1711 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
1712 break;
1713 case 2:
1714 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
1715 break;
1717 tcg_gen_shli_i32(tmp, tmp, 28);
1718 gen_set_nzcv(tmp);
1719 dead_tmp(tmp);
1720 break;
1721 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1722 if (((insn >> 6) & 3) == 3)
1723 return 1;
1724 rd = (insn >> 12) & 0xf;
1725 wrd = (insn >> 16) & 0xf;
1726 tmp = load_reg(s, rd);
1727 switch ((insn >> 6) & 3) {
1728 case 0:
1729 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
1730 break;
1731 case 1:
1732 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
1733 break;
1734 case 2:
1735 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
1736 break;
1738 dead_tmp(tmp);
1739 gen_op_iwmmxt_movq_wRn_M0(wrd);
1740 gen_op_iwmmxt_set_mup();
1741 break;
1742 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1743 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1744 return 1;
1745 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1746 tmp2 = new_tmp();
1747 tcg_gen_mov_i32(tmp2, tmp);
1748 switch ((insn >> 22) & 3) {
1749 case 0:
1750 for (i = 0; i < 7; i ++) {
1751 tcg_gen_shli_i32(tmp2, tmp2, 4);
1752 tcg_gen_and_i32(tmp, tmp, tmp2);
1754 break;
1755 case 1:
1756 for (i = 0; i < 3; i ++) {
1757 tcg_gen_shli_i32(tmp2, tmp2, 8);
1758 tcg_gen_and_i32(tmp, tmp, tmp2);
1760 break;
1761 case 2:
1762 tcg_gen_shli_i32(tmp2, tmp2, 16);
1763 tcg_gen_and_i32(tmp, tmp, tmp2);
1764 break;
1766 gen_set_nzcv(tmp);
1767 dead_tmp(tmp2);
1768 dead_tmp(tmp);
1769 break;
1770 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1771 wrd = (insn >> 12) & 0xf;
1772 rd0 = (insn >> 16) & 0xf;
1773 gen_op_iwmmxt_movq_M0_wRn(rd0);
1774 switch ((insn >> 22) & 3) {
1775 case 0:
1776 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1777 break;
1778 case 1:
1779 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1780 break;
1781 case 2:
1782 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1783 break;
1784 case 3:
1785 return 1;
1787 gen_op_iwmmxt_movq_wRn_M0(wrd);
1788 gen_op_iwmmxt_set_mup();
1789 break;
1790 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1791 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1792 return 1;
1793 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1794 tmp2 = new_tmp();
1795 tcg_gen_mov_i32(tmp2, tmp);
1796 switch ((insn >> 22) & 3) {
1797 case 0:
1798 for (i = 0; i < 7; i ++) {
1799 tcg_gen_shli_i32(tmp2, tmp2, 4);
1800 tcg_gen_or_i32(tmp, tmp, tmp2);
1802 break;
1803 case 1:
1804 for (i = 0; i < 3; i ++) {
1805 tcg_gen_shli_i32(tmp2, tmp2, 8);
1806 tcg_gen_or_i32(tmp, tmp, tmp2);
1808 break;
1809 case 2:
1810 tcg_gen_shli_i32(tmp2, tmp2, 16);
1811 tcg_gen_or_i32(tmp, tmp, tmp2);
1812 break;
1814 gen_set_nzcv(tmp);
1815 dead_tmp(tmp2);
1816 dead_tmp(tmp);
1817 break;
1818 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1819 rd = (insn >> 12) & 0xf;
1820 rd0 = (insn >> 16) & 0xf;
1821 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
1822 return 1;
1823 gen_op_iwmmxt_movq_M0_wRn(rd0);
1824 tmp = new_tmp();
1825 switch ((insn >> 22) & 3) {
1826 case 0:
1827 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
1828 break;
1829 case 1:
1830 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
1831 break;
1832 case 2:
1833 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
1834 break;
1836 store_reg(s, rd, tmp);
1837 break;
1838 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1839 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1840 wrd = (insn >> 12) & 0xf;
1841 rd0 = (insn >> 16) & 0xf;
1842 rd1 = (insn >> 0) & 0xf;
1843 gen_op_iwmmxt_movq_M0_wRn(rd0);
1844 switch ((insn >> 22) & 3) {
1845 case 0:
1846 if (insn & (1 << 21))
1847 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1848 else
1849 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1850 break;
1851 case 1:
1852 if (insn & (1 << 21))
1853 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1854 else
1855 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
1856 break;
1857 case 2:
1858 if (insn & (1 << 21))
1859 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
1860 else
1861 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
1862 break;
1863 case 3:
1864 return 1;
1866 gen_op_iwmmxt_movq_wRn_M0(wrd);
1867 gen_op_iwmmxt_set_mup();
1868 gen_op_iwmmxt_set_cup();
1869 break;
1870 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1871 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1872 wrd = (insn >> 12) & 0xf;
1873 rd0 = (insn >> 16) & 0xf;
1874 gen_op_iwmmxt_movq_M0_wRn(rd0);
1875 switch ((insn >> 22) & 3) {
1876 case 0:
1877 if (insn & (1 << 21))
1878 gen_op_iwmmxt_unpacklsb_M0();
1879 else
1880 gen_op_iwmmxt_unpacklub_M0();
1881 break;
1882 case 1:
1883 if (insn & (1 << 21))
1884 gen_op_iwmmxt_unpacklsw_M0();
1885 else
1886 gen_op_iwmmxt_unpackluw_M0();
1887 break;
1888 case 2:
1889 if (insn & (1 << 21))
1890 gen_op_iwmmxt_unpacklsl_M0();
1891 else
1892 gen_op_iwmmxt_unpacklul_M0();
1893 break;
1894 case 3:
1895 return 1;
1897 gen_op_iwmmxt_movq_wRn_M0(wrd);
1898 gen_op_iwmmxt_set_mup();
1899 gen_op_iwmmxt_set_cup();
1900 break;
1901 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
1902 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1903 wrd = (insn >> 12) & 0xf;
1904 rd0 = (insn >> 16) & 0xf;
1905 gen_op_iwmmxt_movq_M0_wRn(rd0);
1906 switch ((insn >> 22) & 3) {
1907 case 0:
1908 if (insn & (1 << 21))
1909 gen_op_iwmmxt_unpackhsb_M0();
1910 else
1911 gen_op_iwmmxt_unpackhub_M0();
1912 break;
1913 case 1:
1914 if (insn & (1 << 21))
1915 gen_op_iwmmxt_unpackhsw_M0();
1916 else
1917 gen_op_iwmmxt_unpackhuw_M0();
1918 break;
1919 case 2:
1920 if (insn & (1 << 21))
1921 gen_op_iwmmxt_unpackhsl_M0();
1922 else
1923 gen_op_iwmmxt_unpackhul_M0();
1924 break;
1925 case 3:
1926 return 1;
1928 gen_op_iwmmxt_movq_wRn_M0(wrd);
1929 gen_op_iwmmxt_set_mup();
1930 gen_op_iwmmxt_set_cup();
1931 break;
1932 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
1933 case 0x214: case 0x614: case 0xa14: case 0xe14:
1934 if (((insn >> 22) & 3) == 0)
1935 return 1;
1936 wrd = (insn >> 12) & 0xf;
1937 rd0 = (insn >> 16) & 0xf;
1938 gen_op_iwmmxt_movq_M0_wRn(rd0);
1939 tmp = new_tmp();
1940 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
1941 dead_tmp(tmp);
1942 return 1;
1944 switch ((insn >> 22) & 3) {
1945 case 1:
1946 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
1947 break;
1948 case 2:
1949 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
1950 break;
1951 case 3:
1952 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
1953 break;
1955 dead_tmp(tmp);
1956 gen_op_iwmmxt_movq_wRn_M0(wrd);
1957 gen_op_iwmmxt_set_mup();
1958 gen_op_iwmmxt_set_cup();
1959 break;
1960 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
1961 case 0x014: case 0x414: case 0x814: case 0xc14:
1962 if (((insn >> 22) & 3) == 0)
1963 return 1;
1964 wrd = (insn >> 12) & 0xf;
1965 rd0 = (insn >> 16) & 0xf;
1966 gen_op_iwmmxt_movq_M0_wRn(rd0);
1967 tmp = new_tmp();
1968 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
1969 dead_tmp(tmp);
1970 return 1;
1972 switch ((insn >> 22) & 3) {
1973 case 1:
1974 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
1975 break;
1976 case 2:
1977 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
1978 break;
1979 case 3:
1980 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
1981 break;
1983 dead_tmp(tmp);
1984 gen_op_iwmmxt_movq_wRn_M0(wrd);
1985 gen_op_iwmmxt_set_mup();
1986 gen_op_iwmmxt_set_cup();
1987 break;
1988 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
1989 case 0x114: case 0x514: case 0x914: case 0xd14:
1990 if (((insn >> 22) & 3) == 0)
1991 return 1;
1992 wrd = (insn >> 12) & 0xf;
1993 rd0 = (insn >> 16) & 0xf;
1994 gen_op_iwmmxt_movq_M0_wRn(rd0);
1995 tmp = new_tmp();
1996 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
1997 dead_tmp(tmp);
1998 return 1;
2000 switch ((insn >> 22) & 3) {
2001 case 1:
2002 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2003 break;
2004 case 2:
2005 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2006 break;
2007 case 3:
2008 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2009 break;
2011 dead_tmp(tmp);
2012 gen_op_iwmmxt_movq_wRn_M0(wrd);
2013 gen_op_iwmmxt_set_mup();
2014 gen_op_iwmmxt_set_cup();
2015 break;
2016 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2017 case 0x314: case 0x714: case 0xb14: case 0xf14:
2018 if (((insn >> 22) & 3) == 0)
2019 return 1;
2020 wrd = (insn >> 12) & 0xf;
2021 rd0 = (insn >> 16) & 0xf;
2022 gen_op_iwmmxt_movq_M0_wRn(rd0);
2023 tmp = new_tmp();
2024 switch ((insn >> 22) & 3) {
2025 case 1:
2026 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2027 dead_tmp(tmp);
2028 return 1;
2030 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2031 break;
2032 case 2:
2033 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2034 dead_tmp(tmp);
2035 return 1;
2037 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2038 break;
2039 case 3:
2040 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2041 dead_tmp(tmp);
2042 return 1;
2044 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2045 break;
2047 dead_tmp(tmp);
2048 gen_op_iwmmxt_movq_wRn_M0(wrd);
2049 gen_op_iwmmxt_set_mup();
2050 gen_op_iwmmxt_set_cup();
2051 break;
2052 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2053 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2054 wrd = (insn >> 12) & 0xf;
2055 rd0 = (insn >> 16) & 0xf;
2056 rd1 = (insn >> 0) & 0xf;
2057 gen_op_iwmmxt_movq_M0_wRn(rd0);
2058 switch ((insn >> 22) & 3) {
2059 case 0:
2060 if (insn & (1 << 21))
2061 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2062 else
2063 gen_op_iwmmxt_minub_M0_wRn(rd1);
2064 break;
2065 case 1:
2066 if (insn & (1 << 21))
2067 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2068 else
2069 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2070 break;
2071 case 2:
2072 if (insn & (1 << 21))
2073 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2074 else
2075 gen_op_iwmmxt_minul_M0_wRn(rd1);
2076 break;
2077 case 3:
2078 return 1;
2080 gen_op_iwmmxt_movq_wRn_M0(wrd);
2081 gen_op_iwmmxt_set_mup();
2082 break;
2083 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2084 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2085 wrd = (insn >> 12) & 0xf;
2086 rd0 = (insn >> 16) & 0xf;
2087 rd1 = (insn >> 0) & 0xf;
2088 gen_op_iwmmxt_movq_M0_wRn(rd0);
2089 switch ((insn >> 22) & 3) {
2090 case 0:
2091 if (insn & (1 << 21))
2092 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2093 else
2094 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2095 break;
2096 case 1:
2097 if (insn & (1 << 21))
2098 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2099 else
2100 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2101 break;
2102 case 2:
2103 if (insn & (1 << 21))
2104 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2105 else
2106 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2107 break;
2108 case 3:
2109 return 1;
2111 gen_op_iwmmxt_movq_wRn_M0(wrd);
2112 gen_op_iwmmxt_set_mup();
2113 break;
2114 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2115 case 0x402: case 0x502: case 0x602: case 0x702:
2116 wrd = (insn >> 12) & 0xf;
2117 rd0 = (insn >> 16) & 0xf;
2118 rd1 = (insn >> 0) & 0xf;
2119 gen_op_iwmmxt_movq_M0_wRn(rd0);
2120 tmp = tcg_const_i32((insn >> 20) & 3);
2121 iwmmxt_load_reg(cpu_V1, rd1);
2122 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2123 tcg_temp_free(tmp);
2124 gen_op_iwmmxt_movq_wRn_M0(wrd);
2125 gen_op_iwmmxt_set_mup();
2126 break;
2127 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2128 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2129 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2130 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2131 wrd = (insn >> 12) & 0xf;
2132 rd0 = (insn >> 16) & 0xf;
2133 rd1 = (insn >> 0) & 0xf;
2134 gen_op_iwmmxt_movq_M0_wRn(rd0);
2135 switch ((insn >> 20) & 0xf) {
2136 case 0x0:
2137 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2138 break;
2139 case 0x1:
2140 gen_op_iwmmxt_subub_M0_wRn(rd1);
2141 break;
2142 case 0x3:
2143 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2144 break;
2145 case 0x4:
2146 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2147 break;
2148 case 0x5:
2149 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2150 break;
2151 case 0x7:
2152 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2153 break;
2154 case 0x8:
2155 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2156 break;
2157 case 0x9:
2158 gen_op_iwmmxt_subul_M0_wRn(rd1);
2159 break;
2160 case 0xb:
2161 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2162 break;
2163 default:
2164 return 1;
2166 gen_op_iwmmxt_movq_wRn_M0(wrd);
2167 gen_op_iwmmxt_set_mup();
2168 gen_op_iwmmxt_set_cup();
2169 break;
2170 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2171 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2172 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2173 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2174 wrd = (insn >> 12) & 0xf;
2175 rd0 = (insn >> 16) & 0xf;
2176 gen_op_iwmmxt_movq_M0_wRn(rd0);
2177 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2178 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2179 tcg_temp_free(tmp);
2180 gen_op_iwmmxt_movq_wRn_M0(wrd);
2181 gen_op_iwmmxt_set_mup();
2182 gen_op_iwmmxt_set_cup();
2183 break;
2184 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2185 case 0x418: case 0x518: case 0x618: case 0x718:
2186 case 0x818: case 0x918: case 0xa18: case 0xb18:
2187 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2188 wrd = (insn >> 12) & 0xf;
2189 rd0 = (insn >> 16) & 0xf;
2190 rd1 = (insn >> 0) & 0xf;
2191 gen_op_iwmmxt_movq_M0_wRn(rd0);
2192 switch ((insn >> 20) & 0xf) {
2193 case 0x0:
2194 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2195 break;
2196 case 0x1:
2197 gen_op_iwmmxt_addub_M0_wRn(rd1);
2198 break;
2199 case 0x3:
2200 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2201 break;
2202 case 0x4:
2203 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2204 break;
2205 case 0x5:
2206 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2207 break;
2208 case 0x7:
2209 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2210 break;
2211 case 0x8:
2212 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2213 break;
2214 case 0x9:
2215 gen_op_iwmmxt_addul_M0_wRn(rd1);
2216 break;
2217 case 0xb:
2218 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2219 break;
2220 default:
2221 return 1;
2223 gen_op_iwmmxt_movq_wRn_M0(wrd);
2224 gen_op_iwmmxt_set_mup();
2225 gen_op_iwmmxt_set_cup();
2226 break;
2227 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2228 case 0x408: case 0x508: case 0x608: case 0x708:
2229 case 0x808: case 0x908: case 0xa08: case 0xb08:
2230 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2231 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2232 return 1;
2233 wrd = (insn >> 12) & 0xf;
2234 rd0 = (insn >> 16) & 0xf;
2235 rd1 = (insn >> 0) & 0xf;
2236 gen_op_iwmmxt_movq_M0_wRn(rd0);
2237 switch ((insn >> 22) & 3) {
2238 case 1:
2239 if (insn & (1 << 21))
2240 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2241 else
2242 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2243 break;
2244 case 2:
2245 if (insn & (1 << 21))
2246 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2247 else
2248 gen_op_iwmmxt_packul_M0_wRn(rd1);
2249 break;
2250 case 3:
2251 if (insn & (1 << 21))
2252 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2253 else
2254 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2255 break;
2257 gen_op_iwmmxt_movq_wRn_M0(wrd);
2258 gen_op_iwmmxt_set_mup();
2259 gen_op_iwmmxt_set_cup();
2260 break;
2261 case 0x201: case 0x203: case 0x205: case 0x207:
2262 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2263 case 0x211: case 0x213: case 0x215: case 0x217:
2264 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2265 wrd = (insn >> 5) & 0xf;
2266 rd0 = (insn >> 12) & 0xf;
2267 rd1 = (insn >> 0) & 0xf;
2268 if (rd0 == 0xf || rd1 == 0xf)
2269 return 1;
2270 gen_op_iwmmxt_movq_M0_wRn(wrd);
2271 tmp = load_reg(s, rd0);
2272 tmp2 = load_reg(s, rd1);
2273 switch ((insn >> 16) & 0xf) {
2274 case 0x0: /* TMIA */
2275 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2276 break;
2277 case 0x8: /* TMIAPH */
2278 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2279 break;
2280 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2281 if (insn & (1 << 16))
2282 tcg_gen_shri_i32(tmp, tmp, 16);
2283 if (insn & (1 << 17))
2284 tcg_gen_shri_i32(tmp2, tmp2, 16);
2285 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2286 break;
2287 default:
2288 dead_tmp(tmp2);
2289 dead_tmp(tmp);
2290 return 1;
2292 dead_tmp(tmp2);
2293 dead_tmp(tmp);
2294 gen_op_iwmmxt_movq_wRn_M0(wrd);
2295 gen_op_iwmmxt_set_mup();
2296 break;
2297 default:
2298 return 1;
2301 return 0;
2304 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2305 (ie. an undefined instruction). */
2306 static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2308 int acc, rd0, rd1, rdhi, rdlo;
2309 TCGv tmp, tmp2;
2311 if ((insn & 0x0ff00f10) == 0x0e200010) {
2312 /* Multiply with Internal Accumulate Format */
2313 rd0 = (insn >> 12) & 0xf;
2314 rd1 = insn & 0xf;
2315 acc = (insn >> 5) & 7;
2317 if (acc != 0)
2318 return 1;
2320 tmp = load_reg(s, rd0);
2321 tmp2 = load_reg(s, rd1);
2322 switch ((insn >> 16) & 0xf) {
2323 case 0x0: /* MIA */
2324 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2325 break;
2326 case 0x8: /* MIAPH */
2327 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2328 break;
2329 case 0xc: /* MIABB */
2330 case 0xd: /* MIABT */
2331 case 0xe: /* MIATB */
2332 case 0xf: /* MIATT */
2333 if (insn & (1 << 16))
2334 tcg_gen_shri_i32(tmp, tmp, 16);
2335 if (insn & (1 << 17))
2336 tcg_gen_shri_i32(tmp2, tmp2, 16);
2337 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2338 break;
2339 default:
2340 return 1;
2342 dead_tmp(tmp2);
2343 dead_tmp(tmp);
2345 gen_op_iwmmxt_movq_wRn_M0(acc);
2346 return 0;
2349 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2350 /* Internal Accumulator Access Format */
2351 rdhi = (insn >> 16) & 0xf;
2352 rdlo = (insn >> 12) & 0xf;
2353 acc = insn & 7;
2355 if (acc != 0)
2356 return 1;
2358 if (insn & ARM_CP_RW_BIT) { /* MRA */
2359 iwmmxt_load_reg(cpu_V0, acc);
2360 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
2361 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
2362 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
2363 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2364 } else { /* MAR */
2365 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2366 iwmmxt_store_reg(cpu_V0, acc);
2368 return 0;
2371 return 1;
2374 /* Disassemble system coprocessor instruction. Return nonzero if
2375 instruction is not defined. */
2376 static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2378 TCGv tmp;
2379 uint32_t rd = (insn >> 12) & 0xf;
2380 uint32_t cp = (insn >> 8) & 0xf;
2381 if (IS_USER(s)) {
2382 return 1;
2385 if (insn & ARM_CP_RW_BIT) {
2386 if (!env->cp[cp].cp_read)
2387 return 1;
2388 gen_set_pc_im(s->pc);
2389 tmp = new_tmp();
2390 gen_helper_get_cp(tmp, cpu_env, tcg_const_i32(insn));
2391 store_reg(s, rd, tmp);
2392 } else {
2393 if (!env->cp[cp].cp_write)
2394 return 1;
2395 gen_set_pc_im(s->pc);
2396 tmp = load_reg(s, rd);
2397 gen_helper_set_cp(cpu_env, tcg_const_i32(insn), tmp);
2398 dead_tmp(tmp);
2400 return 0;
2403 static int cp15_user_ok(uint32_t insn)
2405 int cpn = (insn >> 16) & 0xf;
2406 int cpm = insn & 0xf;
2407 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2409 if (cpn == 13 && cpm == 0) {
2410 /* TLS register. */
2411 if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2412 return 1;
2414 if (cpn == 7) {
2415 /* ISB, DSB, DMB. */
2416 if ((cpm == 5 && op == 4)
2417 || (cpm == 10 && (op == 4 || op == 5)))
2418 return 1;
2420 return 0;
2423 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2424 instruction is not defined. */
2425 static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2427 uint32_t rd;
2428 TCGv tmp;
2430 /* M profile cores use memory mapped registers instead of cp15. */
2431 if (arm_feature(env, ARM_FEATURE_M) ||
2432 !arm_feature(env, ARM_FEATURE_CP15)) {
2433 return 1;
2436 if ((insn & (1 << 25)) == 0) {
2437 if (insn & (1 << 20)) {
2438 /* mrrc */
2439 return 1;
2441 /* mcrr. Used for block cache operations, so implement as no-op. */
2442 return 0;
2444 if ((insn & (1 << 4)) == 0) {
2445 /* cdp */
2446 return 1;
2448 if (IS_USER(s) && !cp15_user_ok(insn)) {
2449 return 1;
2451 if ((insn & 0x0fff0fff) == 0x0e070f90
2452 || (insn & 0x0fff0fff) == 0x0e070f58) {
2453 /* Wait for interrupt. */
2454 gen_set_pc_im(s->pc);
2455 s->is_jmp = DISAS_WFI;
2456 return 0;
2458 rd = (insn >> 12) & 0xf;
2459 if (insn & ARM_CP_RW_BIT) {
2460 tmp = new_tmp();
2461 gen_helper_get_cp15(tmp, cpu_env, tcg_const_i32(insn));
2462 /* If the destination register is r15 then sets condition codes. */
2463 if (rd != 15)
2464 store_reg(s, rd, tmp);
2465 else
2466 dead_tmp(tmp);
2467 } else {
2468 tmp = load_reg(s, rd);
2469 gen_helper_set_cp15(cpu_env, tcg_const_i32(insn), tmp);
2470 dead_tmp(tmp);
2471 /* Normally we would always end the TB here, but Linux
2472 * arch/arm/mach-pxa/sleep.S expects two instructions following
2473 * an MMU enable to execute from cache. Imitate this behaviour. */
2474 if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2475 (insn & 0x0fff0fff) != 0x0e010f10)
2476 gen_lookup_tb(s);
2478 return 0;
2481 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2482 #define VFP_SREG(insn, bigbit, smallbit) \
2483 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2484 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2485 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2486 reg = (((insn) >> (bigbit)) & 0x0f) \
2487 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2488 } else { \
2489 if (insn & (1 << (smallbit))) \
2490 return 1; \
2491 reg = ((insn) >> (bigbit)) & 0x0f; \
2492 }} while (0)
2494 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2495 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2496 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2497 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2498 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2499 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2501 /* Move between integer and VFP cores. */
2502 static TCGv gen_vfp_mrs(void)
2504 TCGv tmp = new_tmp();
2505 tcg_gen_mov_i32(tmp, cpu_F0s);
2506 return tmp;
2509 static void gen_vfp_msr(TCGv tmp)
2511 tcg_gen_mov_i32(cpu_F0s, tmp);
2512 dead_tmp(tmp);
2515 static inline int
2516 vfp_enabled(CPUState * env)
2518 return ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) != 0);
2521 static void gen_neon_dup_u8(TCGv var, int shift)
2523 TCGv tmp = new_tmp();
2524 if (shift)
2525 tcg_gen_shri_i32(var, var, shift);
2526 tcg_gen_ext8u_i32(var, var);
2527 tcg_gen_shli_i32(tmp, var, 8);
2528 tcg_gen_or_i32(var, var, tmp);
2529 tcg_gen_shli_i32(tmp, var, 16);
2530 tcg_gen_or_i32(var, var, tmp);
2531 dead_tmp(tmp);
2534 static void gen_neon_dup_low16(TCGv var)
2536 TCGv tmp = new_tmp();
2537 tcg_gen_ext16u_i32(var, var);
2538 tcg_gen_shli_i32(tmp, var, 16);
2539 tcg_gen_or_i32(var, var, tmp);
2540 dead_tmp(tmp);
2543 static void gen_neon_dup_high16(TCGv var)
2545 TCGv tmp = new_tmp();
2546 tcg_gen_andi_i32(var, var, 0xffff0000);
2547 tcg_gen_shri_i32(tmp, var, 16);
2548 tcg_gen_or_i32(var, var, tmp);
2549 dead_tmp(tmp);
2552 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2553 (ie. an undefined instruction). */
2554 static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2556 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2557 int dp, veclen;
2558 TCGv addr;
2559 TCGv tmp;
2560 TCGv tmp2;
2562 if (!arm_feature(env, ARM_FEATURE_VFP))
2563 return 1;
2565 if (!vfp_enabled(env)) {
2566 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2567 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2568 return 1;
2569 rn = (insn >> 16) & 0xf;
2570 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2571 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2572 return 1;
2574 dp = ((insn & 0xf00) == 0xb00);
2575 switch ((insn >> 24) & 0xf) {
2576 case 0xe:
2577 if (insn & (1 << 4)) {
2578 /* single register transfer */
2579 rd = (insn >> 12) & 0xf;
2580 if (dp) {
2581 int size;
2582 int pass;
2584 VFP_DREG_N(rn, insn);
2585 if (insn & 0xf)
2586 return 1;
2587 if (insn & 0x00c00060
2588 && !arm_feature(env, ARM_FEATURE_NEON))
2589 return 1;
2591 pass = (insn >> 21) & 1;
2592 if (insn & (1 << 22)) {
2593 size = 0;
2594 offset = ((insn >> 5) & 3) * 8;
2595 } else if (insn & (1 << 5)) {
2596 size = 1;
2597 offset = (insn & (1 << 6)) ? 16 : 0;
2598 } else {
2599 size = 2;
2600 offset = 0;
2602 if (insn & ARM_CP_RW_BIT) {
2603 /* vfp->arm */
2604 tmp = neon_load_reg(rn, pass);
2605 switch (size) {
2606 case 0:
2607 if (offset)
2608 tcg_gen_shri_i32(tmp, tmp, offset);
2609 if (insn & (1 << 23))
2610 gen_uxtb(tmp);
2611 else
2612 gen_sxtb(tmp);
2613 break;
2614 case 1:
2615 if (insn & (1 << 23)) {
2616 if (offset) {
2617 tcg_gen_shri_i32(tmp, tmp, 16);
2618 } else {
2619 gen_uxth(tmp);
2621 } else {
2622 if (offset) {
2623 tcg_gen_sari_i32(tmp, tmp, 16);
2624 } else {
2625 gen_sxth(tmp);
2628 break;
2629 case 2:
2630 break;
2632 store_reg(s, rd, tmp);
2633 } else {
2634 /* arm->vfp */
2635 tmp = load_reg(s, rd);
2636 if (insn & (1 << 23)) {
2637 /* VDUP */
2638 if (size == 0) {
2639 gen_neon_dup_u8(tmp, 0);
2640 } else if (size == 1) {
2641 gen_neon_dup_low16(tmp);
2643 for (n = 0; n <= pass * 2; n++) {
2644 tmp2 = new_tmp();
2645 tcg_gen_mov_i32(tmp2, tmp);
2646 neon_store_reg(rn, n, tmp2);
2648 neon_store_reg(rn, n, tmp);
2649 } else {
2650 /* VMOV */
2651 switch (size) {
2652 case 0:
2653 tmp2 = neon_load_reg(rn, pass);
2654 gen_bfi(tmp, tmp2, tmp, offset, 0xff);
2655 dead_tmp(tmp2);
2656 break;
2657 case 1:
2658 tmp2 = neon_load_reg(rn, pass);
2659 gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
2660 dead_tmp(tmp2);
2661 break;
2662 case 2:
2663 break;
2665 neon_store_reg(rn, pass, tmp);
2668 } else { /* !dp */
2669 if ((insn & 0x6f) != 0x00)
2670 return 1;
2671 rn = VFP_SREG_N(insn);
2672 if (insn & ARM_CP_RW_BIT) {
2673 /* vfp->arm */
2674 if (insn & (1 << 21)) {
2675 /* system register */
2676 rn >>= 1;
2678 switch (rn) {
2679 case ARM_VFP_FPSID:
2680 /* VFP2 allows access to FSID from userspace.
2681 VFP3 restricts all id registers to privileged
2682 accesses. */
2683 if (IS_USER(s)
2684 && arm_feature(env, ARM_FEATURE_VFP3))
2685 return 1;
2686 tmp = load_cpu_field(vfp.xregs[rn]);
2687 break;
2688 case ARM_VFP_FPEXC:
2689 if (IS_USER(s))
2690 return 1;
2691 tmp = load_cpu_field(vfp.xregs[rn]);
2692 break;
2693 case ARM_VFP_FPINST:
2694 case ARM_VFP_FPINST2:
2695 /* Not present in VFP3. */
2696 if (IS_USER(s)
2697 || arm_feature(env, ARM_FEATURE_VFP3))
2698 return 1;
2699 tmp = load_cpu_field(vfp.xregs[rn]);
2700 break;
2701 case ARM_VFP_FPSCR:
2702 if (rd == 15) {
2703 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2704 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2705 } else {
2706 tmp = new_tmp();
2707 gen_helper_vfp_get_fpscr(tmp, cpu_env);
2709 break;
2710 case ARM_VFP_MVFR0:
2711 case ARM_VFP_MVFR1:
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 default:
2718 return 1;
2720 } else {
2721 gen_mov_F0_vreg(0, rn);
2722 tmp = gen_vfp_mrs();
2724 if (rd == 15) {
2725 /* Set the 4 flag bits in the CPSR. */
2726 gen_set_nzcv(tmp);
2727 dead_tmp(tmp);
2728 } else {
2729 store_reg(s, rd, tmp);
2731 } else {
2732 /* arm->vfp */
2733 tmp = load_reg(s, rd);
2734 if (insn & (1 << 21)) {
2735 rn >>= 1;
2736 /* system register */
2737 switch (rn) {
2738 case ARM_VFP_FPSID:
2739 case ARM_VFP_MVFR0:
2740 case ARM_VFP_MVFR1:
2741 /* Writes are ignored. */
2742 break;
2743 case ARM_VFP_FPSCR:
2744 gen_helper_vfp_set_fpscr(cpu_env, tmp);
2745 dead_tmp(tmp);
2746 gen_lookup_tb(s);
2747 break;
2748 case ARM_VFP_FPEXC:
2749 if (IS_USER(s))
2750 return 1;
2751 store_cpu_field(tmp, vfp.xregs[rn]);
2752 gen_lookup_tb(s);
2753 break;
2754 case ARM_VFP_FPINST:
2755 case ARM_VFP_FPINST2:
2756 store_cpu_field(tmp, vfp.xregs[rn]);
2757 break;
2758 default:
2759 return 1;
2761 } else {
2762 gen_vfp_msr(tmp);
2763 gen_mov_vreg_F0(0, rn);
2767 } else {
2768 /* data processing */
2769 /* The opcode is in bits 23, 21, 20 and 6. */
2770 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2771 if (dp) {
2772 if (op == 15) {
2773 /* rn is opcode */
2774 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2775 } else {
2776 /* rn is register number */
2777 VFP_DREG_N(rn, insn);
2780 if (op == 15 && (rn == 15 || rn > 17)) {
2781 /* Integer or single precision destination. */
2782 rd = VFP_SREG_D(insn);
2783 } else {
2784 VFP_DREG_D(rd, insn);
2787 if (op == 15 && (rn == 16 || rn == 17)) {
2788 /* Integer source. */
2789 rm = ((insn << 1) & 0x1e) | ((insn >> 5) & 1);
2790 } else {
2791 VFP_DREG_M(rm, insn);
2793 } else {
2794 rn = VFP_SREG_N(insn);
2795 if (op == 15 && rn == 15) {
2796 /* Double precision destination. */
2797 VFP_DREG_D(rd, insn);
2798 } else {
2799 rd = VFP_SREG_D(insn);
2801 rm = VFP_SREG_M(insn);
2804 veclen = env->vfp.vec_len;
2805 if (op == 15 && rn > 3)
2806 veclen = 0;
2808 /* Shut up compiler warnings. */
2809 delta_m = 0;
2810 delta_d = 0;
2811 bank_mask = 0;
2813 if (veclen > 0) {
2814 if (dp)
2815 bank_mask = 0xc;
2816 else
2817 bank_mask = 0x18;
2819 /* Figure out what type of vector operation this is. */
2820 if ((rd & bank_mask) == 0) {
2821 /* scalar */
2822 veclen = 0;
2823 } else {
2824 if (dp)
2825 delta_d = (env->vfp.vec_stride >> 1) + 1;
2826 else
2827 delta_d = env->vfp.vec_stride + 1;
2829 if ((rm & bank_mask) == 0) {
2830 /* mixed scalar/vector */
2831 delta_m = 0;
2832 } else {
2833 /* vector */
2834 delta_m = delta_d;
2839 /* Load the initial operands. */
2840 if (op == 15) {
2841 switch (rn) {
2842 case 16:
2843 case 17:
2844 /* Integer source */
2845 gen_mov_F0_vreg(0, rm);
2846 break;
2847 case 8:
2848 case 9:
2849 /* Compare */
2850 gen_mov_F0_vreg(dp, rd);
2851 gen_mov_F1_vreg(dp, rm);
2852 break;
2853 case 10:
2854 case 11:
2855 /* Compare with zero */
2856 gen_mov_F0_vreg(dp, rd);
2857 gen_vfp_F1_ld0(dp);
2858 break;
2859 case 20:
2860 case 21:
2861 case 22:
2862 case 23:
2863 case 28:
2864 case 29:
2865 case 30:
2866 case 31:
2867 /* Source and destination the same. */
2868 gen_mov_F0_vreg(dp, rd);
2869 break;
2870 default:
2871 /* One source operand. */
2872 gen_mov_F0_vreg(dp, rm);
2873 break;
2875 } else {
2876 /* Two source operands. */
2877 gen_mov_F0_vreg(dp, rn);
2878 gen_mov_F1_vreg(dp, rm);
2881 for (;;) {
2882 /* Perform the calculation. */
2883 switch (op) {
2884 case 0: /* mac: fd + (fn * fm) */
2885 gen_vfp_mul(dp);
2886 gen_mov_F1_vreg(dp, rd);
2887 gen_vfp_add(dp);
2888 break;
2889 case 1: /* nmac: fd - (fn * fm) */
2890 gen_vfp_mul(dp);
2891 gen_vfp_neg(dp);
2892 gen_mov_F1_vreg(dp, rd);
2893 gen_vfp_add(dp);
2894 break;
2895 case 2: /* msc: -fd + (fn * fm) */
2896 gen_vfp_mul(dp);
2897 gen_mov_F1_vreg(dp, rd);
2898 gen_vfp_sub(dp);
2899 break;
2900 case 3: /* nmsc: -fd - (fn * fm) */
2901 gen_vfp_mul(dp);
2902 gen_vfp_neg(dp);
2903 gen_mov_F1_vreg(dp, rd);
2904 gen_vfp_sub(dp);
2905 break;
2906 case 4: /* mul: fn * fm */
2907 gen_vfp_mul(dp);
2908 break;
2909 case 5: /* nmul: -(fn * fm) */
2910 gen_vfp_mul(dp);
2911 gen_vfp_neg(dp);
2912 break;
2913 case 6: /* add: fn + fm */
2914 gen_vfp_add(dp);
2915 break;
2916 case 7: /* sub: fn - fm */
2917 gen_vfp_sub(dp);
2918 break;
2919 case 8: /* div: fn / fm */
2920 gen_vfp_div(dp);
2921 break;
2922 case 14: /* fconst */
2923 if (!arm_feature(env, ARM_FEATURE_VFP3))
2924 return 1;
2926 n = (insn << 12) & 0x80000000;
2927 i = ((insn >> 12) & 0x70) | (insn & 0xf);
2928 if (dp) {
2929 if (i & 0x40)
2930 i |= 0x3f80;
2931 else
2932 i |= 0x4000;
2933 n |= i << 16;
2934 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
2935 } else {
2936 if (i & 0x40)
2937 i |= 0x780;
2938 else
2939 i |= 0x800;
2940 n |= i << 19;
2941 tcg_gen_movi_i32(cpu_F0s, n);
2943 break;
2944 case 15: /* extension space */
2945 switch (rn) {
2946 case 0: /* cpy */
2947 /* no-op */
2948 break;
2949 case 1: /* abs */
2950 gen_vfp_abs(dp);
2951 break;
2952 case 2: /* neg */
2953 gen_vfp_neg(dp);
2954 break;
2955 case 3: /* sqrt */
2956 gen_vfp_sqrt(dp);
2957 break;
2958 case 8: /* cmp */
2959 gen_vfp_cmp(dp);
2960 break;
2961 case 9: /* cmpe */
2962 gen_vfp_cmpe(dp);
2963 break;
2964 case 10: /* cmpz */
2965 gen_vfp_cmp(dp);
2966 break;
2967 case 11: /* cmpez */
2968 gen_vfp_F1_ld0(dp);
2969 gen_vfp_cmpe(dp);
2970 break;
2971 case 15: /* single<->double conversion */
2972 if (dp)
2973 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
2974 else
2975 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
2976 break;
2977 case 16: /* fuito */
2978 gen_vfp_uito(dp);
2979 break;
2980 case 17: /* fsito */
2981 gen_vfp_sito(dp);
2982 break;
2983 case 20: /* fshto */
2984 if (!arm_feature(env, ARM_FEATURE_VFP3))
2985 return 1;
2986 gen_vfp_shto(dp, 16 - rm);
2987 break;
2988 case 21: /* fslto */
2989 if (!arm_feature(env, ARM_FEATURE_VFP3))
2990 return 1;
2991 gen_vfp_slto(dp, 32 - rm);
2992 break;
2993 case 22: /* fuhto */
2994 if (!arm_feature(env, ARM_FEATURE_VFP3))
2995 return 1;
2996 gen_vfp_uhto(dp, 16 - rm);
2997 break;
2998 case 23: /* fulto */
2999 if (!arm_feature(env, ARM_FEATURE_VFP3))
3000 return 1;
3001 gen_vfp_ulto(dp, 32 - rm);
3002 break;
3003 case 24: /* ftoui */
3004 gen_vfp_toui(dp);
3005 break;
3006 case 25: /* ftouiz */
3007 gen_vfp_touiz(dp);
3008 break;
3009 case 26: /* ftosi */
3010 gen_vfp_tosi(dp);
3011 break;
3012 case 27: /* ftosiz */
3013 gen_vfp_tosiz(dp);
3014 break;
3015 case 28: /* ftosh */
3016 if (!arm_feature(env, ARM_FEATURE_VFP3))
3017 return 1;
3018 gen_vfp_tosh(dp, 16 - rm);
3019 break;
3020 case 29: /* ftosl */
3021 if (!arm_feature(env, ARM_FEATURE_VFP3))
3022 return 1;
3023 gen_vfp_tosl(dp, 32 - rm);
3024 break;
3025 case 30: /* ftouh */
3026 if (!arm_feature(env, ARM_FEATURE_VFP3))
3027 return 1;
3028 gen_vfp_touh(dp, 16 - rm);
3029 break;
3030 case 31: /* ftoul */
3031 if (!arm_feature(env, ARM_FEATURE_VFP3))
3032 return 1;
3033 gen_vfp_toul(dp, 32 - rm);
3034 break;
3035 default: /* undefined */
3036 printf ("rn:%d\n", rn);
3037 return 1;
3039 break;
3040 default: /* undefined */
3041 printf ("op:%d\n", op);
3042 return 1;
3045 /* Write back the result. */
3046 if (op == 15 && (rn >= 8 && rn <= 11))
3047 ; /* Comparison, do nothing. */
3048 else if (op == 15 && rn > 17)
3049 /* Integer result. */
3050 gen_mov_vreg_F0(0, rd);
3051 else if (op == 15 && rn == 15)
3052 /* conversion */
3053 gen_mov_vreg_F0(!dp, rd);
3054 else
3055 gen_mov_vreg_F0(dp, rd);
3057 /* break out of the loop if we have finished */
3058 if (veclen == 0)
3059 break;
3061 if (op == 15 && delta_m == 0) {
3062 /* single source one-many */
3063 while (veclen--) {
3064 rd = ((rd + delta_d) & (bank_mask - 1))
3065 | (rd & bank_mask);
3066 gen_mov_vreg_F0(dp, rd);
3068 break;
3070 /* Setup the next operands. */
3071 veclen--;
3072 rd = ((rd + delta_d) & (bank_mask - 1))
3073 | (rd & bank_mask);
3075 if (op == 15) {
3076 /* One source operand. */
3077 rm = ((rm + delta_m) & (bank_mask - 1))
3078 | (rm & bank_mask);
3079 gen_mov_F0_vreg(dp, rm);
3080 } else {
3081 /* Two source operands. */
3082 rn = ((rn + delta_d) & (bank_mask - 1))
3083 | (rn & bank_mask);
3084 gen_mov_F0_vreg(dp, rn);
3085 if (delta_m) {
3086 rm = ((rm + delta_m) & (bank_mask - 1))
3087 | (rm & bank_mask);
3088 gen_mov_F1_vreg(dp, rm);
3093 break;
3094 case 0xc:
3095 case 0xd:
3096 if (dp && (insn & 0x03e00000) == 0x00400000) {
3097 /* two-register transfer */
3098 rn = (insn >> 16) & 0xf;
3099 rd = (insn >> 12) & 0xf;
3100 if (dp) {
3101 VFP_DREG_M(rm, insn);
3102 } else {
3103 rm = VFP_SREG_M(insn);
3106 if (insn & ARM_CP_RW_BIT) {
3107 /* vfp->arm */
3108 if (dp) {
3109 gen_mov_F0_vreg(0, rm * 2);
3110 tmp = gen_vfp_mrs();
3111 store_reg(s, rd, tmp);
3112 gen_mov_F0_vreg(0, rm * 2 + 1);
3113 tmp = gen_vfp_mrs();
3114 store_reg(s, rn, tmp);
3115 } else {
3116 gen_mov_F0_vreg(0, rm);
3117 tmp = gen_vfp_mrs();
3118 store_reg(s, rn, tmp);
3119 gen_mov_F0_vreg(0, rm + 1);
3120 tmp = gen_vfp_mrs();
3121 store_reg(s, rd, tmp);
3123 } else {
3124 /* arm->vfp */
3125 if (dp) {
3126 tmp = load_reg(s, rd);
3127 gen_vfp_msr(tmp);
3128 gen_mov_vreg_F0(0, rm * 2);
3129 tmp = load_reg(s, rn);
3130 gen_vfp_msr(tmp);
3131 gen_mov_vreg_F0(0, rm * 2 + 1);
3132 } else {
3133 tmp = load_reg(s, rn);
3134 gen_vfp_msr(tmp);
3135 gen_mov_vreg_F0(0, rm);
3136 tmp = load_reg(s, rd);
3137 gen_vfp_msr(tmp);
3138 gen_mov_vreg_F0(0, rm + 1);
3141 } else {
3142 /* Load/store */
3143 rn = (insn >> 16) & 0xf;
3144 if (dp)
3145 VFP_DREG_D(rd, insn);
3146 else
3147 rd = VFP_SREG_D(insn);
3148 if (s->thumb && rn == 15) {
3149 addr = new_tmp();
3150 tcg_gen_movi_i32(addr, s->pc & ~2);
3151 } else {
3152 addr = load_reg(s, rn);
3154 if ((insn & 0x01200000) == 0x01000000) {
3155 /* Single load/store */
3156 offset = (insn & 0xff) << 2;
3157 if ((insn & (1 << 23)) == 0)
3158 offset = -offset;
3159 tcg_gen_addi_i32(addr, addr, offset);
3160 if (insn & (1 << 20)) {
3161 gen_vfp_ld(s, dp, addr);
3162 gen_mov_vreg_F0(dp, rd);
3163 } else {
3164 gen_mov_F0_vreg(dp, rd);
3165 gen_vfp_st(s, dp, addr);
3167 } else {
3168 /* load/store multiple */
3169 if (dp)
3170 n = (insn >> 1) & 0x7f;
3171 else
3172 n = insn & 0xff;
3174 if (insn & (1 << 24)) /* pre-decrement */
3175 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
3177 if (dp)
3178 offset = 8;
3179 else
3180 offset = 4;
3181 for (i = 0; i < n; i++) {
3182 if (insn & ARM_CP_RW_BIT) {
3183 /* load */
3184 gen_vfp_ld(s, dp, addr);
3185 gen_mov_vreg_F0(dp, rd + i);
3186 } else {
3187 /* store */
3188 gen_mov_F0_vreg(dp, rd + i);
3189 gen_vfp_st(s, dp, addr);
3191 tcg_gen_addi_i32(addr, addr, offset);
3193 if (insn & (1 << 21)) {
3194 /* writeback */
3195 if (insn & (1 << 24))
3196 offset = -offset * n;
3197 else if (dp && (insn & 1))
3198 offset = 4;
3199 else
3200 offset = 0;
3202 if (offset != 0)
3203 tcg_gen_addi_i32(addr, addr, offset);
3204 store_reg(s, rn, addr);
3205 } else {
3206 dead_tmp(addr);
3210 break;
3211 default:
3212 /* Should never happen. */
3213 return 1;
3215 return 0;
3218 static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3220 TranslationBlock *tb;
3222 tb = s->tb;
3223 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3224 tcg_gen_goto_tb(n);
3225 gen_set_pc_im(dest);
3226 tcg_gen_exit_tb((long)tb + n);
3227 } else {
3228 gen_set_pc_im(dest);
3229 tcg_gen_exit_tb(0);
3233 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3235 if (unlikely(s->singlestep_enabled)) {
3236 /* An indirect jump so that we still trigger the debug exception. */
3237 if (s->thumb)
3238 dest |= 1;
3239 gen_bx_im(s, dest);
3240 } else {
3241 gen_goto_tb(s, 0, dest);
3242 s->is_jmp = DISAS_TB_JUMP;
3246 static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3248 if (x)
3249 tcg_gen_sari_i32(t0, t0, 16);
3250 else
3251 gen_sxth(t0);
3252 if (y)
3253 tcg_gen_sari_i32(t1, t1, 16);
3254 else
3255 gen_sxth(t1);
3256 tcg_gen_mul_i32(t0, t0, t1);
3259 /* Return the mask of PSR bits set by a MSR instruction. */
3260 static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3261 uint32_t mask;
3263 mask = 0;
3264 if (flags & (1 << 0))
3265 mask |= 0xff;
3266 if (flags & (1 << 1))
3267 mask |= 0xff00;
3268 if (flags & (1 << 2))
3269 mask |= 0xff0000;
3270 if (flags & (1 << 3))
3271 mask |= 0xff000000;
3273 /* Mask out undefined bits. */
3274 mask &= ~CPSR_RESERVED;
3275 if (!arm_feature(env, ARM_FEATURE_V6))
3276 mask &= ~(CPSR_E | CPSR_GE);
3277 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3278 mask &= ~CPSR_IT;
3279 /* Mask out execution state bits. */
3280 if (!spsr)
3281 mask &= ~CPSR_EXEC;
3282 /* Mask out privileged bits. */
3283 if (IS_USER(s))
3284 mask &= CPSR_USER;
3285 return mask;
3288 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3289 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0)
3291 TCGv tmp;
3292 if (spsr) {
3293 /* ??? This is also undefined in system mode. */
3294 if (IS_USER(s))
3295 return 1;
3297 tmp = load_cpu_field(spsr);
3298 tcg_gen_andi_i32(tmp, tmp, ~mask);
3299 tcg_gen_andi_i32(t0, t0, mask);
3300 tcg_gen_or_i32(tmp, tmp, t0);
3301 store_cpu_field(tmp, spsr);
3302 } else {
3303 gen_set_cpsr(t0, mask);
3305 dead_tmp(t0);
3306 gen_lookup_tb(s);
3307 return 0;
3310 /* Returns nonzero if access to the PSR is not permitted. */
3311 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3313 TCGv tmp;
3314 tmp = new_tmp();
3315 tcg_gen_movi_i32(tmp, val);
3316 return gen_set_psr(s, mask, spsr, tmp);
3319 /* Generate an old-style exception return. Marks pc as dead. */
3320 static void gen_exception_return(DisasContext *s, TCGv pc)
3322 TCGv tmp;
3323 store_reg(s, 15, pc);
3324 tmp = load_cpu_field(spsr);
3325 gen_set_cpsr(tmp, 0xffffffff);
3326 dead_tmp(tmp);
3327 s->is_jmp = DISAS_UPDATE;
3330 /* Generate a v6 exception return. Marks both values as dead. */
3331 static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3333 gen_set_cpsr(cpsr, 0xffffffff);
3334 dead_tmp(cpsr);
3335 store_reg(s, 15, pc);
3336 s->is_jmp = DISAS_UPDATE;
3339 static inline void
3340 gen_set_condexec (DisasContext *s)
3342 if (s->condexec_mask) {
3343 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3344 TCGv tmp = new_tmp();
3345 tcg_gen_movi_i32(tmp, val);
3346 store_cpu_field(tmp, condexec_bits);
3350 static void gen_nop_hint(DisasContext *s, int val)
3352 switch (val) {
3353 case 3: /* wfi */
3354 gen_set_pc_im(s->pc);
3355 s->is_jmp = DISAS_WFI;
3356 break;
3357 case 2: /* wfe */
3358 case 4: /* sev */
3359 /* TODO: Implement SEV and WFE. May help SMP performance. */
3360 default: /* nop */
3361 break;
3365 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3367 static inline int gen_neon_add(int size, TCGv t0, TCGv t1)
3369 switch (size) {
3370 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
3371 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
3372 case 2: tcg_gen_add_i32(t0, t0, t1); break;
3373 default: return 1;
3375 return 0;
3378 static inline void gen_neon_rsb(int size, TCGv t0, TCGv t1)
3380 switch (size) {
3381 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
3382 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
3383 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
3384 default: return;
3388 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3389 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3390 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3391 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3392 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3394 /* FIXME: This is wrong. They set the wrong overflow bit. */
3395 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3396 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3397 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3398 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3400 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3401 switch ((size << 1) | u) { \
3402 case 0: \
3403 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3404 break; \
3405 case 1: \
3406 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3407 break; \
3408 case 2: \
3409 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3410 break; \
3411 case 3: \
3412 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3413 break; \
3414 case 4: \
3415 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3416 break; \
3417 case 5: \
3418 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3419 break; \
3420 default: return 1; \
3421 }} while (0)
3423 #define GEN_NEON_INTEGER_OP(name) do { \
3424 switch ((size << 1) | u) { \
3425 case 0: \
3426 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3427 break; \
3428 case 1: \
3429 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3430 break; \
3431 case 2: \
3432 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3433 break; \
3434 case 3: \
3435 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3436 break; \
3437 case 4: \
3438 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3439 break; \
3440 case 5: \
3441 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3442 break; \
3443 default: return 1; \
3444 }} while (0)
3446 static TCGv neon_load_scratch(int scratch)
3448 TCGv tmp = new_tmp();
3449 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3450 return tmp;
3453 static void neon_store_scratch(int scratch, TCGv var)
3455 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3456 dead_tmp(var);
3459 static inline TCGv neon_get_scalar(int size, int reg)
3461 TCGv tmp;
3462 if (size == 1) {
3463 tmp = neon_load_reg(reg >> 1, reg & 1);
3464 } else {
3465 tmp = neon_load_reg(reg >> 2, (reg >> 1) & 1);
3466 if (reg & 1) {
3467 gen_neon_dup_low16(tmp);
3468 } else {
3469 gen_neon_dup_high16(tmp);
3472 return tmp;
3475 static void gen_neon_unzip_u8(TCGv t0, TCGv t1)
3477 TCGv rd, rm, tmp;
3479 rd = new_tmp();
3480 rm = new_tmp();
3481 tmp = new_tmp();
3483 tcg_gen_andi_i32(rd, t0, 0xff);
3484 tcg_gen_shri_i32(tmp, t0, 8);
3485 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3486 tcg_gen_or_i32(rd, rd, tmp);
3487 tcg_gen_shli_i32(tmp, t1, 16);
3488 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3489 tcg_gen_or_i32(rd, rd, tmp);
3490 tcg_gen_shli_i32(tmp, t1, 8);
3491 tcg_gen_andi_i32(tmp, tmp, 0xff000000);
3492 tcg_gen_or_i32(rd, rd, tmp);
3494 tcg_gen_shri_i32(rm, t0, 8);
3495 tcg_gen_andi_i32(rm, rm, 0xff);
3496 tcg_gen_shri_i32(tmp, t0, 16);
3497 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3498 tcg_gen_or_i32(rm, rm, tmp);
3499 tcg_gen_shli_i32(tmp, t1, 8);
3500 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3501 tcg_gen_or_i32(rm, rm, tmp);
3502 tcg_gen_andi_i32(tmp, t1, 0xff000000);
3503 tcg_gen_or_i32(t1, rm, tmp);
3504 tcg_gen_mov_i32(t0, rd);
3506 dead_tmp(tmp);
3507 dead_tmp(rm);
3508 dead_tmp(rd);
3511 static void gen_neon_zip_u8(TCGv t0, TCGv t1)
3513 TCGv rd, rm, tmp;
3515 rd = new_tmp();
3516 rm = new_tmp();
3517 tmp = new_tmp();
3519 tcg_gen_andi_i32(rd, t0, 0xff);
3520 tcg_gen_shli_i32(tmp, t1, 8);
3521 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3522 tcg_gen_or_i32(rd, rd, tmp);
3523 tcg_gen_shli_i32(tmp, t0, 16);
3524 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3525 tcg_gen_or_i32(rd, rd, tmp);
3526 tcg_gen_shli_i32(tmp, t1, 24);
3527 tcg_gen_andi_i32(tmp, tmp, 0xff000000);
3528 tcg_gen_or_i32(rd, rd, tmp);
3530 tcg_gen_andi_i32(rm, t1, 0xff000000);
3531 tcg_gen_shri_i32(tmp, t0, 8);
3532 tcg_gen_andi_i32(tmp, tmp, 0xff0000);
3533 tcg_gen_or_i32(rm, rm, tmp);
3534 tcg_gen_shri_i32(tmp, t1, 8);
3535 tcg_gen_andi_i32(tmp, tmp, 0xff00);
3536 tcg_gen_or_i32(rm, rm, tmp);
3537 tcg_gen_shri_i32(tmp, t0, 16);
3538 tcg_gen_andi_i32(tmp, tmp, 0xff);
3539 tcg_gen_or_i32(t1, rm, tmp);
3540 tcg_gen_mov_i32(t0, rd);
3542 dead_tmp(tmp);
3543 dead_tmp(rm);
3544 dead_tmp(rd);
3547 static void gen_neon_zip_u16(TCGv t0, TCGv t1)
3549 TCGv tmp, tmp2;
3551 tmp = new_tmp();
3552 tmp2 = new_tmp();
3554 tcg_gen_andi_i32(tmp, t0, 0xffff);
3555 tcg_gen_shli_i32(tmp2, t1, 16);
3556 tcg_gen_or_i32(tmp, tmp, tmp2);
3557 tcg_gen_andi_i32(t1, t1, 0xffff0000);
3558 tcg_gen_shri_i32(tmp2, t0, 16);
3559 tcg_gen_or_i32(t1, t1, tmp2);
3560 tcg_gen_mov_i32(t0, tmp);
3562 dead_tmp(tmp2);
3563 dead_tmp(tmp);
3566 static void gen_neon_unzip(int reg, int q, int tmp, int size)
3568 int n;
3569 TCGv t0, t1;
3571 for (n = 0; n < q + 1; n += 2) {
3572 t0 = neon_load_reg(reg, n);
3573 t1 = neon_load_reg(reg, n + 1);
3574 switch (size) {
3575 case 0: gen_neon_unzip_u8(t0, t1); break;
3576 case 1: gen_neon_zip_u16(t0, t1); break; /* zip and unzip are the same. */
3577 case 2: /* no-op */; break;
3578 default: abort();
3580 neon_store_scratch(tmp + n, t0);
3581 neon_store_scratch(tmp + n + 1, t1);
3585 static void gen_neon_trn_u8(TCGv t0, TCGv t1)
3587 TCGv rd, tmp;
3589 rd = new_tmp();
3590 tmp = new_tmp();
3592 tcg_gen_shli_i32(rd, t0, 8);
3593 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3594 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3595 tcg_gen_or_i32(rd, rd, tmp);
3597 tcg_gen_shri_i32(t1, t1, 8);
3598 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3599 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3600 tcg_gen_or_i32(t1, t1, tmp);
3601 tcg_gen_mov_i32(t0, rd);
3603 dead_tmp(tmp);
3604 dead_tmp(rd);
3607 static void gen_neon_trn_u16(TCGv t0, TCGv t1)
3609 TCGv rd, tmp;
3611 rd = new_tmp();
3612 tmp = new_tmp();
3614 tcg_gen_shli_i32(rd, t0, 16);
3615 tcg_gen_andi_i32(tmp, t1, 0xffff);
3616 tcg_gen_or_i32(rd, rd, tmp);
3617 tcg_gen_shri_i32(t1, t1, 16);
3618 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3619 tcg_gen_or_i32(t1, t1, tmp);
3620 tcg_gen_mov_i32(t0, rd);
3622 dead_tmp(tmp);
3623 dead_tmp(rd);
3627 static struct {
3628 int nregs;
3629 int interleave;
3630 int spacing;
3631 } neon_ls_element_type[11] = {
3632 {4, 4, 1},
3633 {4, 4, 2},
3634 {4, 1, 1},
3635 {4, 2, 1},
3636 {3, 3, 1},
3637 {3, 3, 2},
3638 {3, 1, 1},
3639 {1, 1, 1},
3640 {2, 2, 1},
3641 {2, 2, 2},
3642 {2, 1, 1}
3645 /* Translate a NEON load/store element instruction. Return nonzero if the
3646 instruction is invalid. */
3647 static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3649 int rd, rn, rm;
3650 int op;
3651 int nregs;
3652 int interleave;
3653 int stride;
3654 int size;
3655 int reg;
3656 int pass;
3657 int load;
3658 int shift;
3659 int n;
3660 TCGv addr;
3661 TCGv tmp;
3662 TCGv tmp2;
3664 if (!vfp_enabled(env))
3665 return 1;
3666 VFP_DREG_D(rd, insn);
3667 rn = (insn >> 16) & 0xf;
3668 rm = insn & 0xf;
3669 load = (insn & (1 << 21)) != 0;
3670 addr = new_tmp();
3671 if ((insn & (1 << 23)) == 0) {
3672 /* Load store all elements. */
3673 op = (insn >> 8) & 0xf;
3674 size = (insn >> 6) & 3;
3675 if (op > 10 || size == 3)
3676 return 1;
3677 nregs = neon_ls_element_type[op].nregs;
3678 interleave = neon_ls_element_type[op].interleave;
3679 tcg_gen_mov_i32(addr, cpu_R[rn]);
3680 stride = (1 << size) * interleave;
3681 for (reg = 0; reg < nregs; reg++) {
3682 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3683 tcg_gen_add_i32(addr, cpu_R[rn], (1 << size) * reg);
3684 } else if (interleave == 2 && nregs == 4 && reg == 2) {
3685 tcg_gen_add_i32(addr, cpu_R[rn], 1 << size);
3687 for (pass = 0; pass < 2; pass++) {
3688 if (size == 2) {
3689 if (load) {
3690 tmp = gen_ld32(addr, IS_USER(s));
3691 neon_store_reg(rd, pass, tmp);
3692 } else {
3693 tmp = neon_load_reg(rd, pass);
3694 gen_st32(tmp, addr, IS_USER(s));
3696 tcg_gen_addi_i32(addr, addr, stride);
3697 } else if (size == 1) {
3698 if (load) {
3699 tmp = gen_ld16u(addr, IS_USER(s));
3700 tcg_gen_addi_i32(addr, addr, stride);
3701 tmp2 = gen_ld16u(addr, IS_USER(s));
3702 tcg_gen_addi_i32(addr, addr, stride);
3703 gen_bfi(tmp, tmp, tmp2, 16, 0xffff);
3704 dead_tmp(tmp2);
3705 neon_store_reg(rd, pass, tmp);
3706 } else {
3707 tmp = neon_load_reg(rd, pass);
3708 tmp2 = new_tmp();
3709 tcg_gen_shri_i32(tmp2, tmp, 16);
3710 gen_st16(tmp, addr, IS_USER(s));
3711 tcg_gen_addi_i32(addr, addr, stride);
3712 gen_st16(tmp2, addr, IS_USER(s));
3713 tcg_gen_addi_i32(addr, addr, stride);
3715 } else /* size == 0 */ {
3716 if (load) {
3717 TCGV_UNUSED(tmp2);
3718 for (n = 0; n < 4; n++) {
3719 tmp = gen_ld8u(addr, IS_USER(s));
3720 tcg_gen_addi_i32(addr, addr, stride);
3721 if (n == 0) {
3722 tmp2 = tmp;
3723 } else {
3724 gen_bfi(tmp2, tmp2, tmp, n * 8, 0xff);
3725 dead_tmp(tmp);
3728 neon_store_reg(rd, pass, tmp2);
3729 } else {
3730 tmp2 = neon_load_reg(rd, pass);
3731 for (n = 0; n < 4; n++) {
3732 tmp = new_tmp();
3733 if (n == 0) {
3734 tcg_gen_mov_i32(tmp, tmp2);
3735 } else {
3736 tcg_gen_shri_i32(tmp, tmp2, n * 8);
3738 gen_st8(tmp, addr, IS_USER(s));
3739 tcg_gen_addi_i32(addr, addr, stride);
3741 dead_tmp(tmp2);
3745 rd += neon_ls_element_type[op].spacing;
3747 stride = nregs * 8;
3748 } else {
3749 size = (insn >> 10) & 3;
3750 if (size == 3) {
3751 /* Load single element to all lanes. */
3752 if (!load)
3753 return 1;
3754 size = (insn >> 6) & 3;
3755 nregs = ((insn >> 8) & 3) + 1;
3756 stride = (insn & (1 << 5)) ? 2 : 1;
3757 tcg_gen_mov_i32(addr, cpu_R[rn]);
3758 for (reg = 0; reg < nregs; reg++) {
3759 switch (size) {
3760 case 0:
3761 tmp = gen_ld8u(addr, IS_USER(s));
3762 gen_neon_dup_u8(tmp, 0);
3763 break;
3764 case 1:
3765 tmp = gen_ld16u(addr, IS_USER(s));
3766 gen_neon_dup_low16(tmp);
3767 break;
3768 case 2:
3769 tmp = gen_ld32(addr, IS_USER(s));
3770 break;
3771 case 3:
3772 return 1;
3773 default: /* Avoid compiler warnings. */
3774 abort();
3776 tcg_gen_addi_i32(addr, addr, 1 << size);
3777 tmp2 = new_tmp();
3778 tcg_gen_mov_i32(tmp2, tmp);
3779 neon_store_reg(rd, 0, tmp2);
3780 neon_store_reg(rd, 1, tmp);
3781 rd += stride;
3783 stride = (1 << size) * nregs;
3784 } else {
3785 /* Single element. */
3786 pass = (insn >> 7) & 1;
3787 switch (size) {
3788 case 0:
3789 shift = ((insn >> 5) & 3) * 8;
3790 stride = 1;
3791 break;
3792 case 1:
3793 shift = ((insn >> 6) & 1) * 16;
3794 stride = (insn & (1 << 5)) ? 2 : 1;
3795 break;
3796 case 2:
3797 shift = 0;
3798 stride = (insn & (1 << 6)) ? 2 : 1;
3799 break;
3800 default:
3801 abort();
3803 nregs = ((insn >> 8) & 3) + 1;
3804 tcg_gen_mov_i32(addr, cpu_R[rn]);
3805 for (reg = 0; reg < nregs; reg++) {
3806 if (load) {
3807 switch (size) {
3808 case 0:
3809 tmp = gen_ld8u(addr, IS_USER(s));
3810 break;
3811 case 1:
3812 tmp = gen_ld16u(addr, IS_USER(s));
3813 break;
3814 case 2:
3815 tmp = gen_ld32(addr, IS_USER(s));
3816 break;
3817 default: /* Avoid compiler warnings. */
3818 abort();
3820 if (size != 2) {
3821 tmp2 = neon_load_reg(rd, pass);
3822 gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
3823 dead_tmp(tmp2);
3825 neon_store_reg(rd, pass, tmp);
3826 } else { /* Store */
3827 tmp = neon_load_reg(rd, pass);
3828 if (shift)
3829 tcg_gen_shri_i32(tmp, tmp, shift);
3830 switch (size) {
3831 case 0:
3832 gen_st8(tmp, addr, IS_USER(s));
3833 break;
3834 case 1:
3835 gen_st16(tmp, addr, IS_USER(s));
3836 break;
3837 case 2:
3838 gen_st32(tmp, addr, IS_USER(s));
3839 break;
3842 rd += stride;
3843 tcg_gen_addi_i32(addr, addr, 1 << size);
3845 stride = nregs * (1 << size);
3848 dead_tmp(addr);
3849 if (rm != 15) {
3850 TCGv base;
3852 base = load_reg(s, rn);
3853 if (rm == 13) {
3854 tcg_gen_addi_i32(base, base, stride);
3855 } else {
3856 TCGv index;
3857 index = load_reg(s, rm);
3858 tcg_gen_add_i32(base, base, index);
3859 dead_tmp(index);
3861 store_reg(s, rn, base);
3863 return 0;
3866 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
3867 static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
3869 tcg_gen_and_i32(t, t, c);
3870 tcg_gen_bic_i32(f, f, c);
3871 tcg_gen_or_i32(dest, t, f);
3874 static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
3876 switch (size) {
3877 case 0: gen_helper_neon_narrow_u8(dest, src); break;
3878 case 1: gen_helper_neon_narrow_u16(dest, src); break;
3879 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
3880 default: abort();
3884 static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
3886 switch (size) {
3887 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
3888 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
3889 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
3890 default: abort();
3894 static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
3896 switch (size) {
3897 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
3898 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
3899 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
3900 default: abort();
3904 static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
3905 int q, int u)
3907 if (q) {
3908 if (u) {
3909 switch (size) {
3910 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3911 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3912 default: abort();
3914 } else {
3915 switch (size) {
3916 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
3917 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
3918 default: abort();
3921 } else {
3922 if (u) {
3923 switch (size) {
3924 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
3925 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
3926 default: abort();
3928 } else {
3929 switch (size) {
3930 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
3931 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
3932 default: abort();
3938 static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
3940 if (u) {
3941 switch (size) {
3942 case 0: gen_helper_neon_widen_u8(dest, src); break;
3943 case 1: gen_helper_neon_widen_u16(dest, src); break;
3944 case 2: tcg_gen_extu_i32_i64(dest, src); break;
3945 default: abort();
3947 } else {
3948 switch (size) {
3949 case 0: gen_helper_neon_widen_s8(dest, src); break;
3950 case 1: gen_helper_neon_widen_s16(dest, src); break;
3951 case 2: tcg_gen_ext_i32_i64(dest, src); break;
3952 default: abort();
3955 dead_tmp(src);
3958 static inline void gen_neon_addl(int size)
3960 switch (size) {
3961 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
3962 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
3963 case 2: tcg_gen_add_i64(CPU_V001); break;
3964 default: abort();
3968 static inline void gen_neon_subl(int size)
3970 switch (size) {
3971 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
3972 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
3973 case 2: tcg_gen_sub_i64(CPU_V001); break;
3974 default: abort();
3978 static inline void gen_neon_negl(TCGv_i64 var, int size)
3980 switch (size) {
3981 case 0: gen_helper_neon_negl_u16(var, var); break;
3982 case 1: gen_helper_neon_negl_u32(var, var); break;
3983 case 2: gen_helper_neon_negl_u64(var, var); break;
3984 default: abort();
3988 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
3990 switch (size) {
3991 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
3992 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
3993 default: abort();
3997 static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
3999 TCGv_i64 tmp;
4001 switch ((size << 1) | u) {
4002 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4003 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4004 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4005 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4006 case 4:
4007 tmp = gen_muls_i64_i32(a, b);
4008 tcg_gen_mov_i64(dest, tmp);
4009 break;
4010 case 5:
4011 tmp = gen_mulu_i64_i32(a, b);
4012 tcg_gen_mov_i64(dest, tmp);
4013 break;
4014 default: abort();
4018 /* Translate a NEON data processing instruction. Return nonzero if the
4019 instruction is invalid.
4020 We process data in a mixture of 32-bit and 64-bit chunks.
4021 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4023 static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4025 int op;
4026 int q;
4027 int rd, rn, rm;
4028 int size;
4029 int shift;
4030 int pass;
4031 int count;
4032 int pairwise;
4033 int u;
4034 int n;
4035 uint32_t imm;
4036 TCGv tmp;
4037 TCGv tmp2;
4038 TCGv tmp3;
4039 TCGv_i64 tmp64;
4041 if (!vfp_enabled(env))
4042 return 1;
4043 q = (insn & (1 << 6)) != 0;
4044 u = (insn >> 24) & 1;
4045 VFP_DREG_D(rd, insn);
4046 VFP_DREG_N(rn, insn);
4047 VFP_DREG_M(rm, insn);
4048 size = (insn >> 20) & 3;
4049 if ((insn & (1 << 23)) == 0) {
4050 /* Three register same length. */
4051 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4052 if (size == 3 && (op == 1 || op == 5 || op == 8 || op == 9
4053 || op == 10 || op == 11 || op == 16)) {
4054 /* 64-bit element instructions. */
4055 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4056 neon_load_reg64(cpu_V0, rn + pass);
4057 neon_load_reg64(cpu_V1, rm + pass);
4058 switch (op) {
4059 case 1: /* VQADD */
4060 if (u) {
4061 gen_helper_neon_add_saturate_u64(CPU_V001);
4062 } else {
4063 gen_helper_neon_add_saturate_s64(CPU_V001);
4065 break;
4066 case 5: /* VQSUB */
4067 if (u) {
4068 gen_helper_neon_sub_saturate_u64(CPU_V001);
4069 } else {
4070 gen_helper_neon_sub_saturate_s64(CPU_V001);
4072 break;
4073 case 8: /* VSHL */
4074 if (u) {
4075 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4076 } else {
4077 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4079 break;
4080 case 9: /* VQSHL */
4081 if (u) {
4082 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4083 cpu_V0, cpu_V0);
4084 } else {
4085 gen_helper_neon_qshl_s64(cpu_V1, cpu_env,
4086 cpu_V1, cpu_V0);
4088 break;
4089 case 10: /* VRSHL */
4090 if (u) {
4091 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4092 } else {
4093 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4095 break;
4096 case 11: /* VQRSHL */
4097 if (u) {
4098 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4099 cpu_V1, cpu_V0);
4100 } else {
4101 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4102 cpu_V1, cpu_V0);
4104 break;
4105 case 16:
4106 if (u) {
4107 tcg_gen_sub_i64(CPU_V001);
4108 } else {
4109 tcg_gen_add_i64(CPU_V001);
4111 break;
4112 default:
4113 abort();
4115 neon_store_reg64(cpu_V0, rd + pass);
4117 return 0;
4119 switch (op) {
4120 case 8: /* VSHL */
4121 case 9: /* VQSHL */
4122 case 10: /* VRSHL */
4123 case 11: /* VQRSHL */
4125 int rtmp;
4126 /* Shift instruction operands are reversed. */
4127 rtmp = rn;
4128 rn = rm;
4129 rm = rtmp;
4130 pairwise = 0;
4132 break;
4133 case 20: /* VPMAX */
4134 case 21: /* VPMIN */
4135 case 23: /* VPADD */
4136 pairwise = 1;
4137 break;
4138 case 26: /* VPADD (float) */
4139 pairwise = (u && size < 2);
4140 break;
4141 case 30: /* VPMIN/VPMAX (float) */
4142 pairwise = u;
4143 break;
4144 default:
4145 pairwise = 0;
4146 break;
4149 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4151 if (pairwise) {
4152 /* Pairwise. */
4153 if (q)
4154 n = (pass & 1) * 2;
4155 else
4156 n = 0;
4157 if (pass < q + 1) {
4158 tmp = neon_load_reg(rn, n);
4159 tmp2 = neon_load_reg(rn, n + 1);
4160 } else {
4161 tmp = neon_load_reg(rm, n);
4162 tmp2 = neon_load_reg(rm, n + 1);
4164 } else {
4165 /* Elementwise. */
4166 tmp = neon_load_reg(rn, pass);
4167 tmp2 = neon_load_reg(rm, pass);
4169 switch (op) {
4170 case 0: /* VHADD */
4171 GEN_NEON_INTEGER_OP(hadd);
4172 break;
4173 case 1: /* VQADD */
4174 GEN_NEON_INTEGER_OP_ENV(qadd);
4175 break;
4176 case 2: /* VRHADD */
4177 GEN_NEON_INTEGER_OP(rhadd);
4178 break;
4179 case 3: /* Logic ops. */
4180 switch ((u << 2) | size) {
4181 case 0: /* VAND */
4182 tcg_gen_and_i32(tmp, tmp, tmp2);
4183 break;
4184 case 1: /* BIC */
4185 tcg_gen_bic_i32(tmp, tmp, tmp2);
4186 break;
4187 case 2: /* VORR */
4188 tcg_gen_or_i32(tmp, tmp, tmp2);
4189 break;
4190 case 3: /* VORN */
4191 tcg_gen_not_i32(tmp2, tmp2);
4192 tcg_gen_or_i32(tmp, tmp, tmp2);
4193 break;
4194 case 4: /* VEOR */
4195 tcg_gen_xor_i32(tmp, tmp, tmp2);
4196 break;
4197 case 5: /* VBSL */
4198 tmp3 = neon_load_reg(rd, pass);
4199 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
4200 dead_tmp(tmp3);
4201 break;
4202 case 6: /* VBIT */
4203 tmp3 = neon_load_reg(rd, pass);
4204 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
4205 dead_tmp(tmp3);
4206 break;
4207 case 7: /* VBIF */
4208 tmp3 = neon_load_reg(rd, pass);
4209 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
4210 dead_tmp(tmp3);
4211 break;
4213 break;
4214 case 4: /* VHSUB */
4215 GEN_NEON_INTEGER_OP(hsub);
4216 break;
4217 case 5: /* VQSUB */
4218 GEN_NEON_INTEGER_OP_ENV(qsub);
4219 break;
4220 case 6: /* VCGT */
4221 GEN_NEON_INTEGER_OP(cgt);
4222 break;
4223 case 7: /* VCGE */
4224 GEN_NEON_INTEGER_OP(cge);
4225 break;
4226 case 8: /* VSHL */
4227 GEN_NEON_INTEGER_OP(shl);
4228 break;
4229 case 9: /* VQSHL */
4230 GEN_NEON_INTEGER_OP_ENV(qshl);
4231 break;
4232 case 10: /* VRSHL */
4233 GEN_NEON_INTEGER_OP(rshl);
4234 break;
4235 case 11: /* VQRSHL */
4236 GEN_NEON_INTEGER_OP_ENV(qrshl);
4237 break;
4238 case 12: /* VMAX */
4239 GEN_NEON_INTEGER_OP(max);
4240 break;
4241 case 13: /* VMIN */
4242 GEN_NEON_INTEGER_OP(min);
4243 break;
4244 case 14: /* VABD */
4245 GEN_NEON_INTEGER_OP(abd);
4246 break;
4247 case 15: /* VABA */
4248 GEN_NEON_INTEGER_OP(abd);
4249 dead_tmp(tmp2);
4250 tmp2 = neon_load_reg(rd, pass);
4251 gen_neon_add(size, tmp, tmp2);
4252 break;
4253 case 16:
4254 if (!u) { /* VADD */
4255 if (gen_neon_add(size, tmp, tmp2))
4256 return 1;
4257 } else { /* VSUB */
4258 switch (size) {
4259 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
4260 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
4261 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
4262 default: return 1;
4265 break;
4266 case 17:
4267 if (!u) { /* VTST */
4268 switch (size) {
4269 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
4270 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
4271 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
4272 default: return 1;
4274 } else { /* VCEQ */
4275 switch (size) {
4276 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
4277 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
4278 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
4279 default: return 1;
4282 break;
4283 case 18: /* Multiply. */
4284 switch (size) {
4285 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4286 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4287 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4288 default: return 1;
4290 dead_tmp(tmp2);
4291 tmp2 = neon_load_reg(rd, pass);
4292 if (u) { /* VMLS */
4293 gen_neon_rsb(size, tmp, tmp2);
4294 } else { /* VMLA */
4295 gen_neon_add(size, tmp, tmp2);
4297 break;
4298 case 19: /* VMUL */
4299 if (u) { /* polynomial */
4300 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
4301 } else { /* Integer */
4302 switch (size) {
4303 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4304 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4305 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4306 default: return 1;
4309 break;
4310 case 20: /* VPMAX */
4311 GEN_NEON_INTEGER_OP(pmax);
4312 break;
4313 case 21: /* VPMIN */
4314 GEN_NEON_INTEGER_OP(pmin);
4315 break;
4316 case 22: /* Hultiply high. */
4317 if (!u) { /* VQDMULH */
4318 switch (size) {
4319 case 1: gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4320 case 2: gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4321 default: return 1;
4323 } else { /* VQRDHMUL */
4324 switch (size) {
4325 case 1: gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4326 case 2: gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4327 default: return 1;
4330 break;
4331 case 23: /* VPADD */
4332 if (u)
4333 return 1;
4334 switch (size) {
4335 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
4336 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
4337 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
4338 default: return 1;
4340 break;
4341 case 26: /* Floating point arithnetic. */
4342 switch ((u << 2) | size) {
4343 case 0: /* VADD */
4344 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4345 break;
4346 case 2: /* VSUB */
4347 gen_helper_neon_sub_f32(tmp, tmp, tmp2);
4348 break;
4349 case 4: /* VPADD */
4350 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4351 break;
4352 case 6: /* VABD */
4353 gen_helper_neon_abd_f32(tmp, tmp, tmp2);
4354 break;
4355 default:
4356 return 1;
4358 break;
4359 case 27: /* Float multiply. */
4360 gen_helper_neon_mul_f32(tmp, tmp, tmp2);
4361 if (!u) {
4362 dead_tmp(tmp2);
4363 tmp2 = neon_load_reg(rd, pass);
4364 if (size == 0) {
4365 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4366 } else {
4367 gen_helper_neon_sub_f32(tmp, tmp2, tmp);
4370 break;
4371 case 28: /* Float compare. */
4372 if (!u) {
4373 gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
4374 } else {
4375 if (size == 0)
4376 gen_helper_neon_cge_f32(tmp, tmp, tmp2);
4377 else
4378 gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
4380 break;
4381 case 29: /* Float compare absolute. */
4382 if (!u)
4383 return 1;
4384 if (size == 0)
4385 gen_helper_neon_acge_f32(tmp, tmp, tmp2);
4386 else
4387 gen_helper_neon_acgt_f32(tmp, tmp, tmp2);
4388 break;
4389 case 30: /* Float min/max. */
4390 if (size == 0)
4391 gen_helper_neon_max_f32(tmp, tmp, tmp2);
4392 else
4393 gen_helper_neon_min_f32(tmp, tmp, tmp2);
4394 break;
4395 case 31:
4396 if (size == 0)
4397 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
4398 else
4399 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
4400 break;
4401 default:
4402 abort();
4404 dead_tmp(tmp2);
4406 /* Save the result. For elementwise operations we can put it
4407 straight into the destination register. For pairwise operations
4408 we have to be careful to avoid clobbering the source operands. */
4409 if (pairwise && rd == rm) {
4410 neon_store_scratch(pass, tmp);
4411 } else {
4412 neon_store_reg(rd, pass, tmp);
4415 } /* for pass */
4416 if (pairwise && rd == rm) {
4417 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4418 tmp = neon_load_scratch(pass);
4419 neon_store_reg(rd, pass, tmp);
4422 /* End of 3 register same size operations. */
4423 } else if (insn & (1 << 4)) {
4424 if ((insn & 0x00380080) != 0) {
4425 /* Two registers and shift. */
4426 op = (insn >> 8) & 0xf;
4427 if (insn & (1 << 7)) {
4428 /* 64-bit shift. */
4429 size = 3;
4430 } else {
4431 size = 2;
4432 while ((insn & (1 << (size + 19))) == 0)
4433 size--;
4435 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4436 /* To avoid excessive dumplication of ops we implement shift
4437 by immediate using the variable shift operations. */
4438 if (op < 8) {
4439 /* Shift by immediate:
4440 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4441 /* Right shifts are encoded as N - shift, where N is the
4442 element size in bits. */
4443 if (op <= 4)
4444 shift = shift - (1 << (size + 3));
4445 if (size == 3) {
4446 count = q + 1;
4447 } else {
4448 count = q ? 4: 2;
4450 switch (size) {
4451 case 0:
4452 imm = (uint8_t) shift;
4453 imm |= imm << 8;
4454 imm |= imm << 16;
4455 break;
4456 case 1:
4457 imm = (uint16_t) shift;
4458 imm |= imm << 16;
4459 break;
4460 case 2:
4461 case 3:
4462 imm = shift;
4463 break;
4464 default:
4465 abort();
4468 for (pass = 0; pass < count; pass++) {
4469 if (size == 3) {
4470 neon_load_reg64(cpu_V0, rm + pass);
4471 tcg_gen_movi_i64(cpu_V1, imm);
4472 switch (op) {
4473 case 0: /* VSHR */
4474 case 1: /* VSRA */
4475 if (u)
4476 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4477 else
4478 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
4479 break;
4480 case 2: /* VRSHR */
4481 case 3: /* VRSRA */
4482 if (u)
4483 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
4484 else
4485 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
4486 break;
4487 case 4: /* VSRI */
4488 if (!u)
4489 return 1;
4490 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4491 break;
4492 case 5: /* VSHL, VSLI */
4493 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4494 break;
4495 case 6: /* VQSHL */
4496 if (u)
4497 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4498 else
4499 gen_helper_neon_qshl_s64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4500 break;
4501 case 7: /* VQSHLU */
4502 gen_helper_neon_qshl_u64(cpu_V0, cpu_env, cpu_V0, cpu_V1);
4503 break;
4505 if (op == 1 || op == 3) {
4506 /* Accumulate. */
4507 neon_load_reg64(cpu_V0, rd + pass);
4508 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
4509 } else if (op == 4 || (op == 5 && u)) {
4510 /* Insert */
4511 cpu_abort(env, "VS[LR]I.64 not implemented");
4513 neon_store_reg64(cpu_V0, rd + pass);
4514 } else { /* size < 3 */
4515 /* Operands in T0 and T1. */
4516 tmp = neon_load_reg(rm, pass);
4517 tmp2 = new_tmp();
4518 tcg_gen_movi_i32(tmp2, imm);
4519 switch (op) {
4520 case 0: /* VSHR */
4521 case 1: /* VSRA */
4522 GEN_NEON_INTEGER_OP(shl);
4523 break;
4524 case 2: /* VRSHR */
4525 case 3: /* VRSRA */
4526 GEN_NEON_INTEGER_OP(rshl);
4527 break;
4528 case 4: /* VSRI */
4529 if (!u)
4530 return 1;
4531 GEN_NEON_INTEGER_OP(shl);
4532 break;
4533 case 5: /* VSHL, VSLI */
4534 switch (size) {
4535 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
4536 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
4537 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
4538 default: return 1;
4540 break;
4541 case 6: /* VQSHL */
4542 GEN_NEON_INTEGER_OP_ENV(qshl);
4543 break;
4544 case 7: /* VQSHLU */
4545 switch (size) {
4546 case 0: gen_helper_neon_qshl_u8(tmp, cpu_env, tmp, tmp2); break;
4547 case 1: gen_helper_neon_qshl_u16(tmp, cpu_env, tmp, tmp2); break;
4548 case 2: gen_helper_neon_qshl_u32(tmp, cpu_env, tmp, tmp2); break;
4549 default: return 1;
4551 break;
4553 dead_tmp(tmp2);
4555 if (op == 1 || op == 3) {
4556 /* Accumulate. */
4557 tmp2 = neon_load_reg(rd, pass);
4558 gen_neon_add(size, tmp2, tmp);
4559 dead_tmp(tmp2);
4560 } else if (op == 4 || (op == 5 && u)) {
4561 /* Insert */
4562 switch (size) {
4563 case 0:
4564 if (op == 4)
4565 imm = 0xff >> -shift;
4566 else
4567 imm = (uint8_t)(0xff << shift);
4568 imm |= imm << 8;
4569 imm |= imm << 16;
4570 break;
4571 case 1:
4572 if (op == 4)
4573 imm = 0xffff >> -shift;
4574 else
4575 imm = (uint16_t)(0xffff << shift);
4576 imm |= imm << 16;
4577 break;
4578 case 2:
4579 if (op == 4)
4580 imm = 0xffffffffu >> -shift;
4581 else
4582 imm = 0xffffffffu << shift;
4583 break;
4584 default:
4585 abort();
4587 tmp2 = neon_load_reg(rd, pass);
4588 tcg_gen_andi_i32(tmp, tmp, imm);
4589 tcg_gen_andi_i32(tmp2, tmp2, ~imm);
4590 tcg_gen_or_i32(tmp, tmp, tmp2);
4591 dead_tmp(tmp2);
4593 neon_store_reg(rd, pass, tmp);
4595 } /* for pass */
4596 } else if (op < 10) {
4597 /* Shift by immediate and narrow:
4598 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4599 shift = shift - (1 << (size + 3));
4600 size++;
4601 switch (size) {
4602 case 1:
4603 imm = (uint16_t)shift;
4604 imm |= imm << 16;
4605 tmp2 = tcg_const_i32(imm);
4606 TCGV_UNUSED_I64(tmp64);
4607 break;
4608 case 2:
4609 imm = (uint32_t)shift;
4610 tmp2 = tcg_const_i32(imm);
4611 TCGV_UNUSED_I64(tmp64);
4612 break;
4613 case 3:
4614 tmp64 = tcg_const_i64(shift);
4615 TCGV_UNUSED(tmp2);
4616 break;
4617 default:
4618 abort();
4621 for (pass = 0; pass < 2; pass++) {
4622 if (size == 3) {
4623 neon_load_reg64(cpu_V0, rm + pass);
4624 if (q) {
4625 if (u)
4626 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, tmp64);
4627 else
4628 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, tmp64);
4629 } else {
4630 if (u)
4631 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, tmp64);
4632 else
4633 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, tmp64);
4635 } else {
4636 tmp = neon_load_reg(rm + pass, 0);
4637 gen_neon_shift_narrow(size, tmp, tmp2, q, u);
4638 tmp3 = neon_load_reg(rm + pass, 1);
4639 gen_neon_shift_narrow(size, tmp3, tmp2, q, u);
4640 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
4641 dead_tmp(tmp);
4642 dead_tmp(tmp3);
4644 tmp = new_tmp();
4645 if (op == 8 && !u) {
4646 gen_neon_narrow(size - 1, tmp, cpu_V0);
4647 } else {
4648 if (op == 8)
4649 gen_neon_narrow_sats(size - 1, tmp, cpu_V0);
4650 else
4651 gen_neon_narrow_satu(size - 1, tmp, cpu_V0);
4653 if (pass == 0) {
4654 tmp2 = tmp;
4655 } else {
4656 neon_store_reg(rd, 0, tmp2);
4657 neon_store_reg(rd, 1, tmp);
4659 } /* for pass */
4660 } else if (op == 10) {
4661 /* VSHLL */
4662 if (q || size == 3)
4663 return 1;
4664 tmp = neon_load_reg(rm, 0);
4665 tmp2 = neon_load_reg(rm, 1);
4666 for (pass = 0; pass < 2; pass++) {
4667 if (pass == 1)
4668 tmp = tmp2;
4670 gen_neon_widen(cpu_V0, tmp, size, u);
4672 if (shift != 0) {
4673 /* The shift is less than the width of the source
4674 type, so we can just shift the whole register. */
4675 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
4676 if (size < 2 || !u) {
4677 uint64_t imm64;
4678 if (size == 0) {
4679 imm = (0xffu >> (8 - shift));
4680 imm |= imm << 16;
4681 } else {
4682 imm = 0xffff >> (16 - shift);
4684 imm64 = imm | (((uint64_t)imm) << 32);
4685 tcg_gen_andi_i64(cpu_V0, cpu_V0, imm64);
4688 neon_store_reg64(cpu_V0, rd + pass);
4690 } else if (op == 15 || op == 16) {
4691 /* VCVT fixed-point. */
4692 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4693 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
4694 if (op & 1) {
4695 if (u)
4696 gen_vfp_ulto(0, shift);
4697 else
4698 gen_vfp_slto(0, shift);
4699 } else {
4700 if (u)
4701 gen_vfp_toul(0, shift);
4702 else
4703 gen_vfp_tosl(0, shift);
4705 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
4707 } else {
4708 return 1;
4710 } else { /* (insn & 0x00380080) == 0 */
4711 int invert;
4713 op = (insn >> 8) & 0xf;
4714 /* One register and immediate. */
4715 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4716 invert = (insn & (1 << 5)) != 0;
4717 switch (op) {
4718 case 0: case 1:
4719 /* no-op */
4720 break;
4721 case 2: case 3:
4722 imm <<= 8;
4723 break;
4724 case 4: case 5:
4725 imm <<= 16;
4726 break;
4727 case 6: case 7:
4728 imm <<= 24;
4729 break;
4730 case 8: case 9:
4731 imm |= imm << 16;
4732 break;
4733 case 10: case 11:
4734 imm = (imm << 8) | (imm << 24);
4735 break;
4736 case 12:
4737 imm = (imm < 8) | 0xff;
4738 break;
4739 case 13:
4740 imm = (imm << 16) | 0xffff;
4741 break;
4742 case 14:
4743 imm |= (imm << 8) | (imm << 16) | (imm << 24);
4744 if (invert)
4745 imm = ~imm;
4746 break;
4747 case 15:
4748 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
4749 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
4750 break;
4752 if (invert)
4753 imm = ~imm;
4755 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4756 if (op & 1 && op < 12) {
4757 tmp = neon_load_reg(rd, pass);
4758 if (invert) {
4759 /* The immediate value has already been inverted, so
4760 BIC becomes AND. */
4761 tcg_gen_andi_i32(tmp, tmp, imm);
4762 } else {
4763 tcg_gen_ori_i32(tmp, tmp, imm);
4765 } else {
4766 /* VMOV, VMVN. */
4767 tmp = new_tmp();
4768 if (op == 14 && invert) {
4769 uint32_t val;
4770 val = 0;
4771 for (n = 0; n < 4; n++) {
4772 if (imm & (1 << (n + (pass & 1) * 4)))
4773 val |= 0xff << (n * 8);
4775 tcg_gen_movi_i32(tmp, val);
4776 } else {
4777 tcg_gen_movi_i32(tmp, imm);
4780 neon_store_reg(rd, pass, tmp);
4783 } else { /* (insn & 0x00800010 == 0x00800000) */
4784 if (size != 3) {
4785 op = (insn >> 8) & 0xf;
4786 if ((insn & (1 << 6)) == 0) {
4787 /* Three registers of different lengths. */
4788 int src1_wide;
4789 int src2_wide;
4790 int prewiden;
4791 /* prewiden, src1_wide, src2_wide */
4792 static const int neon_3reg_wide[16][3] = {
4793 {1, 0, 0}, /* VADDL */
4794 {1, 1, 0}, /* VADDW */
4795 {1, 0, 0}, /* VSUBL */
4796 {1, 1, 0}, /* VSUBW */
4797 {0, 1, 1}, /* VADDHN */
4798 {0, 0, 0}, /* VABAL */
4799 {0, 1, 1}, /* VSUBHN */
4800 {0, 0, 0}, /* VABDL */
4801 {0, 0, 0}, /* VMLAL */
4802 {0, 0, 0}, /* VQDMLAL */
4803 {0, 0, 0}, /* VMLSL */
4804 {0, 0, 0}, /* VQDMLSL */
4805 {0, 0, 0}, /* Integer VMULL */
4806 {0, 0, 0}, /* VQDMULL */
4807 {0, 0, 0} /* Polynomial VMULL */
4810 prewiden = neon_3reg_wide[op][0];
4811 src1_wide = neon_3reg_wide[op][1];
4812 src2_wide = neon_3reg_wide[op][2];
4814 if (size == 0 && (op == 9 || op == 11 || op == 13))
4815 return 1;
4817 /* Avoid overlapping operands. Wide source operands are
4818 always aligned so will never overlap with wide
4819 destinations in problematic ways. */
4820 if (rd == rm && !src2_wide) {
4821 tmp = neon_load_reg(rm, 1);
4822 neon_store_scratch(2, tmp);
4823 } else if (rd == rn && !src1_wide) {
4824 tmp = neon_load_reg(rn, 1);
4825 neon_store_scratch(2, tmp);
4827 TCGV_UNUSED(tmp3);
4828 for (pass = 0; pass < 2; pass++) {
4829 if (src1_wide) {
4830 neon_load_reg64(cpu_V0, rn + pass);
4831 TCGV_UNUSED(tmp);
4832 } else {
4833 if (pass == 1 && rd == rn) {
4834 tmp = neon_load_scratch(2);
4835 } else {
4836 tmp = neon_load_reg(rn, pass);
4838 if (prewiden) {
4839 gen_neon_widen(cpu_V0, tmp, size, u);
4842 if (src2_wide) {
4843 neon_load_reg64(cpu_V1, rm + pass);
4844 TCGV_UNUSED(tmp2);
4845 } else {
4846 if (pass == 1 && rd == rm) {
4847 tmp2 = neon_load_scratch(2);
4848 } else {
4849 tmp2 = neon_load_reg(rm, pass);
4851 if (prewiden) {
4852 gen_neon_widen(cpu_V1, tmp2, size, u);
4855 switch (op) {
4856 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4857 gen_neon_addl(size);
4858 break;
4859 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4860 gen_neon_subl(size);
4861 break;
4862 case 5: case 7: /* VABAL, VABDL */
4863 switch ((size << 1) | u) {
4864 case 0:
4865 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
4866 break;
4867 case 1:
4868 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
4869 break;
4870 case 2:
4871 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
4872 break;
4873 case 3:
4874 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
4875 break;
4876 case 4:
4877 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
4878 break;
4879 case 5:
4880 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
4881 break;
4882 default: abort();
4884 dead_tmp(tmp2);
4885 dead_tmp(tmp);
4886 break;
4887 case 8: case 9: case 10: case 11: case 12: case 13:
4888 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4889 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
4890 dead_tmp(tmp2);
4891 dead_tmp(tmp);
4892 break;
4893 case 14: /* Polynomial VMULL */
4894 cpu_abort(env, "Polynomial VMULL not implemented");
4896 default: /* 15 is RESERVED. */
4897 return 1;
4899 if (op == 5 || op == 13 || (op >= 8 && op <= 11)) {
4900 /* Accumulate. */
4901 if (op == 10 || op == 11) {
4902 gen_neon_negl(cpu_V0, size);
4905 if (op != 13) {
4906 neon_load_reg64(cpu_V1, rd + pass);
4909 switch (op) {
4910 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4911 gen_neon_addl(size);
4912 break;
4913 case 9: case 11: /* VQDMLAL, VQDMLSL */
4914 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4915 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
4916 break;
4917 /* Fall through. */
4918 case 13: /* VQDMULL */
4919 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
4920 break;
4921 default:
4922 abort();
4924 neon_store_reg64(cpu_V0, rd + pass);
4925 } else if (op == 4 || op == 6) {
4926 /* Narrowing operation. */
4927 tmp = new_tmp();
4928 if (u) {
4929 switch (size) {
4930 case 0:
4931 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
4932 break;
4933 case 1:
4934 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
4935 break;
4936 case 2:
4937 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
4938 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
4939 break;
4940 default: abort();
4942 } else {
4943 switch (size) {
4944 case 0:
4945 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
4946 break;
4947 case 1:
4948 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
4949 break;
4950 case 2:
4951 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
4952 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
4953 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
4954 break;
4955 default: abort();
4958 if (pass == 0) {
4959 tmp3 = tmp;
4960 } else {
4961 neon_store_reg(rd, 0, tmp3);
4962 neon_store_reg(rd, 1, tmp);
4964 } else {
4965 /* Write back the result. */
4966 neon_store_reg64(cpu_V0, rd + pass);
4969 } else {
4970 /* Two registers and a scalar. */
4971 switch (op) {
4972 case 0: /* Integer VMLA scalar */
4973 case 1: /* Float VMLA scalar */
4974 case 4: /* Integer VMLS scalar */
4975 case 5: /* Floating point VMLS scalar */
4976 case 8: /* Integer VMUL scalar */
4977 case 9: /* Floating point VMUL scalar */
4978 case 12: /* VQDMULH scalar */
4979 case 13: /* VQRDMULH scalar */
4980 tmp = neon_get_scalar(size, rm);
4981 neon_store_scratch(0, tmp);
4982 for (pass = 0; pass < (u ? 4 : 2); pass++) {
4983 tmp = neon_load_scratch(0);
4984 tmp2 = neon_load_reg(rn, pass);
4985 if (op == 12) {
4986 if (size == 1) {
4987 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
4988 } else {
4989 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
4991 } else if (op == 13) {
4992 if (size == 1) {
4993 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
4994 } else {
4995 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
4997 } else if (op & 1) {
4998 gen_helper_neon_mul_f32(tmp, tmp, tmp2);
4999 } else {
5000 switch (size) {
5001 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5002 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5003 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5004 default: return 1;
5007 dead_tmp(tmp2);
5008 if (op < 8) {
5009 /* Accumulate. */
5010 tmp2 = neon_load_reg(rd, pass);
5011 switch (op) {
5012 case 0:
5013 gen_neon_add(size, tmp, tmp2);
5014 break;
5015 case 1:
5016 gen_helper_neon_add_f32(tmp, tmp, tmp2);
5017 break;
5018 case 4:
5019 gen_neon_rsb(size, tmp, tmp2);
5020 break;
5021 case 5:
5022 gen_helper_neon_sub_f32(tmp, tmp2, tmp);
5023 break;
5024 default:
5025 abort();
5027 dead_tmp(tmp2);
5029 neon_store_reg(rd, pass, tmp);
5031 break;
5032 case 2: /* VMLAL sclar */
5033 case 3: /* VQDMLAL scalar */
5034 case 6: /* VMLSL scalar */
5035 case 7: /* VQDMLSL scalar */
5036 case 10: /* VMULL scalar */
5037 case 11: /* VQDMULL scalar */
5038 if (size == 0 && (op == 3 || op == 7 || op == 11))
5039 return 1;
5041 tmp2 = neon_get_scalar(size, rm);
5042 tmp3 = neon_load_reg(rn, 1);
5044 for (pass = 0; pass < 2; pass++) {
5045 if (pass == 0) {
5046 tmp = neon_load_reg(rn, 0);
5047 } else {
5048 tmp = tmp3;
5050 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5051 dead_tmp(tmp);
5052 if (op == 6 || op == 7) {
5053 gen_neon_negl(cpu_V0, size);
5055 if (op != 11) {
5056 neon_load_reg64(cpu_V1, rd + pass);
5058 switch (op) {
5059 case 2: case 6:
5060 gen_neon_addl(size);
5061 break;
5062 case 3: case 7:
5063 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5064 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5065 break;
5066 case 10:
5067 /* no-op */
5068 break;
5069 case 11:
5070 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5071 break;
5072 default:
5073 abort();
5075 neon_store_reg64(cpu_V0, rd + pass);
5078 dead_tmp(tmp2);
5080 break;
5081 default: /* 14 and 15 are RESERVED */
5082 return 1;
5085 } else { /* size == 3 */
5086 if (!u) {
5087 /* Extract. */
5088 imm = (insn >> 8) & 0xf;
5089 count = q + 1;
5091 if (imm > 7 && !q)
5092 return 1;
5094 if (imm == 0) {
5095 neon_load_reg64(cpu_V0, rn);
5096 if (q) {
5097 neon_load_reg64(cpu_V1, rn + 1);
5099 } else if (imm == 8) {
5100 neon_load_reg64(cpu_V0, rn + 1);
5101 if (q) {
5102 neon_load_reg64(cpu_V1, rm);
5104 } else if (q) {
5105 tmp64 = tcg_temp_new_i64();
5106 if (imm < 8) {
5107 neon_load_reg64(cpu_V0, rn);
5108 neon_load_reg64(tmp64, rn + 1);
5109 } else {
5110 neon_load_reg64(cpu_V0, rn + 1);
5111 neon_load_reg64(tmp64, rm);
5113 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5114 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
5115 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5116 if (imm < 8) {
5117 neon_load_reg64(cpu_V1, rm);
5118 } else {
5119 neon_load_reg64(cpu_V1, rm + 1);
5120 imm -= 8;
5122 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5123 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
5124 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
5125 } else {
5126 /* BUGFIX */
5127 neon_load_reg64(cpu_V0, rn);
5128 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
5129 neon_load_reg64(cpu_V1, rm);
5130 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5131 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5133 neon_store_reg64(cpu_V0, rd);
5134 if (q) {
5135 neon_store_reg64(cpu_V1, rd + 1);
5137 } else if ((insn & (1 << 11)) == 0) {
5138 /* Two register misc. */
5139 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5140 size = (insn >> 18) & 3;
5141 switch (op) {
5142 case 0: /* VREV64 */
5143 if (size == 3)
5144 return 1;
5145 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5146 tmp = neon_load_reg(rm, pass * 2);
5147 tmp2 = neon_load_reg(rm, pass * 2 + 1);
5148 switch (size) {
5149 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5150 case 1: gen_swap_half(tmp); break;
5151 case 2: /* no-op */ break;
5152 default: abort();
5154 neon_store_reg(rd, pass * 2 + 1, tmp);
5155 if (size == 2) {
5156 neon_store_reg(rd, pass * 2, tmp2);
5157 } else {
5158 switch (size) {
5159 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
5160 case 1: gen_swap_half(tmp2); break;
5161 default: abort();
5163 neon_store_reg(rd, pass * 2, tmp2);
5166 break;
5167 case 4: case 5: /* VPADDL */
5168 case 12: case 13: /* VPADAL */
5169 if (size == 3)
5170 return 1;
5171 for (pass = 0; pass < q + 1; pass++) {
5172 tmp = neon_load_reg(rm, pass * 2);
5173 gen_neon_widen(cpu_V0, tmp, size, op & 1);
5174 tmp = neon_load_reg(rm, pass * 2 + 1);
5175 gen_neon_widen(cpu_V1, tmp, size, op & 1);
5176 switch (size) {
5177 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5178 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5179 case 2: tcg_gen_add_i64(CPU_V001); break;
5180 default: abort();
5182 if (op >= 12) {
5183 /* Accumulate. */
5184 neon_load_reg64(cpu_V1, rd + pass);
5185 gen_neon_addl(size);
5187 neon_store_reg64(cpu_V0, rd + pass);
5189 break;
5190 case 33: /* VTRN */
5191 if (size == 2) {
5192 for (n = 0; n < (q ? 4 : 2); n += 2) {
5193 tmp = neon_load_reg(rm, n);
5194 tmp2 = neon_load_reg(rd, n + 1);
5195 neon_store_reg(rm, n, tmp2);
5196 neon_store_reg(rd, n + 1, tmp);
5198 } else {
5199 goto elementwise;
5201 break;
5202 case 34: /* VUZP */
5203 /* Reg Before After
5204 Rd A3 A2 A1 A0 B2 B0 A2 A0
5205 Rm B3 B2 B1 B0 B3 B1 A3 A1
5207 if (size == 3)
5208 return 1;
5209 gen_neon_unzip(rd, q, 0, size);
5210 gen_neon_unzip(rm, q, 4, size);
5211 if (q) {
5212 static int unzip_order_q[8] =
5213 {0, 2, 4, 6, 1, 3, 5, 7};
5214 for (n = 0; n < 8; n++) {
5215 int reg = (n < 4) ? rd : rm;
5216 tmp = neon_load_scratch(unzip_order_q[n]);
5217 neon_store_reg(reg, n % 4, tmp);
5219 } else {
5220 static int unzip_order[4] =
5221 {0, 4, 1, 5};
5222 for (n = 0; n < 4; n++) {
5223 int reg = (n < 2) ? rd : rm;
5224 tmp = neon_load_scratch(unzip_order[n]);
5225 neon_store_reg(reg, n % 2, tmp);
5228 break;
5229 case 35: /* VZIP */
5230 /* Reg Before After
5231 Rd A3 A2 A1 A0 B1 A1 B0 A0
5232 Rm B3 B2 B1 B0 B3 A3 B2 A2
5234 if (size == 3)
5235 return 1;
5236 count = (q ? 4 : 2);
5237 for (n = 0; n < count; n++) {
5238 tmp = neon_load_reg(rd, n);
5239 tmp2 = neon_load_reg(rd, n);
5240 switch (size) {
5241 case 0: gen_neon_zip_u8(tmp, tmp2); break;
5242 case 1: gen_neon_zip_u16(tmp, tmp2); break;
5243 case 2: /* no-op */; break;
5244 default: abort();
5246 neon_store_scratch(n * 2, tmp);
5247 neon_store_scratch(n * 2 + 1, tmp2);
5249 for (n = 0; n < count * 2; n++) {
5250 int reg = (n < count) ? rd : rm;
5251 tmp = neon_load_scratch(n);
5252 neon_store_reg(reg, n % count, tmp);
5254 break;
5255 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5256 if (size == 3)
5257 return 1;
5258 TCGV_UNUSED(tmp2);
5259 for (pass = 0; pass < 2; pass++) {
5260 neon_load_reg64(cpu_V0, rm + pass);
5261 tmp = new_tmp();
5262 if (op == 36 && q == 0) {
5263 gen_neon_narrow(size, tmp, cpu_V0);
5264 } else if (q) {
5265 gen_neon_narrow_satu(size, tmp, cpu_V0);
5266 } else {
5267 gen_neon_narrow_sats(size, tmp, cpu_V0);
5269 if (pass == 0) {
5270 tmp2 = tmp;
5271 } else {
5272 neon_store_reg(rd, 0, tmp2);
5273 neon_store_reg(rd, 1, tmp);
5276 break;
5277 case 38: /* VSHLL */
5278 if (q || size == 3)
5279 return 1;
5280 tmp = neon_load_reg(rm, 0);
5281 tmp2 = neon_load_reg(rm, 1);
5282 for (pass = 0; pass < 2; pass++) {
5283 if (pass == 1)
5284 tmp = tmp2;
5285 gen_neon_widen(cpu_V0, tmp, size, 1);
5286 neon_store_reg64(cpu_V0, rd + pass);
5288 break;
5289 default:
5290 elementwise:
5291 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5292 if (op == 30 || op == 31 || op >= 58) {
5293 tcg_gen_ld_f32(cpu_F0s, cpu_env,
5294 neon_reg_offset(rm, pass));
5295 TCGV_UNUSED(tmp);
5296 } else {
5297 tmp = neon_load_reg(rm, pass);
5299 switch (op) {
5300 case 1: /* VREV32 */
5301 switch (size) {
5302 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5303 case 1: gen_swap_half(tmp); break;
5304 default: return 1;
5306 break;
5307 case 2: /* VREV16 */
5308 if (size != 0)
5309 return 1;
5310 gen_rev16(tmp);
5311 break;
5312 case 8: /* CLS */
5313 switch (size) {
5314 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
5315 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
5316 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
5317 default: return 1;
5319 break;
5320 case 9: /* CLZ */
5321 switch (size) {
5322 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
5323 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
5324 case 2: gen_helper_clz(tmp, tmp); break;
5325 default: return 1;
5327 break;
5328 case 10: /* CNT */
5329 if (size != 0)
5330 return 1;
5331 gen_helper_neon_cnt_u8(tmp, tmp);
5332 break;
5333 case 11: /* VNOT */
5334 if (size != 0)
5335 return 1;
5336 tcg_gen_not_i32(tmp, tmp);
5337 break;
5338 case 14: /* VQABS */
5339 switch (size) {
5340 case 0: gen_helper_neon_qabs_s8(tmp, cpu_env, tmp); break;
5341 case 1: gen_helper_neon_qabs_s16(tmp, cpu_env, tmp); break;
5342 case 2: gen_helper_neon_qabs_s32(tmp, cpu_env, tmp); break;
5343 default: return 1;
5345 break;
5346 case 15: /* VQNEG */
5347 switch (size) {
5348 case 0: gen_helper_neon_qneg_s8(tmp, cpu_env, tmp); break;
5349 case 1: gen_helper_neon_qneg_s16(tmp, cpu_env, tmp); break;
5350 case 2: gen_helper_neon_qneg_s32(tmp, cpu_env, tmp); break;
5351 default: return 1;
5353 break;
5354 case 16: case 19: /* VCGT #0, VCLE #0 */
5355 tmp2 = tcg_const_i32(0);
5356 switch(size) {
5357 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
5358 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
5359 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
5360 default: return 1;
5362 tcg_temp_free(tmp2);
5363 if (op == 19)
5364 tcg_gen_not_i32(tmp, tmp);
5365 break;
5366 case 17: case 20: /* VCGE #0, VCLT #0 */
5367 tmp2 = tcg_const_i32(0);
5368 switch(size) {
5369 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
5370 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
5371 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
5372 default: return 1;
5374 tcg_temp_free(tmp2);
5375 if (op == 20)
5376 tcg_gen_not_i32(tmp, tmp);
5377 break;
5378 case 18: /* VCEQ #0 */
5379 tmp2 = tcg_const_i32(0);
5380 switch(size) {
5381 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
5382 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
5383 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
5384 default: return 1;
5386 tcg_temp_free(tmp2);
5387 break;
5388 case 22: /* VABS */
5389 switch(size) {
5390 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
5391 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
5392 case 2: tcg_gen_abs_i32(tmp, tmp); break;
5393 default: return 1;
5395 break;
5396 case 23: /* VNEG */
5397 if (size == 3)
5398 return 1;
5399 tmp2 = tcg_const_i32(0);
5400 gen_neon_rsb(size, tmp, tmp2);
5401 tcg_temp_free(tmp2);
5402 break;
5403 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5404 tmp2 = tcg_const_i32(0);
5405 gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
5406 tcg_temp_free(tmp2);
5407 if (op == 27)
5408 tcg_gen_not_i32(tmp, tmp);
5409 break;
5410 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5411 tmp2 = tcg_const_i32(0);
5412 gen_helper_neon_cge_f32(tmp, tmp, tmp2);
5413 tcg_temp_free(tmp2);
5414 if (op == 28)
5415 tcg_gen_not_i32(tmp, tmp);
5416 break;
5417 case 26: /* Float VCEQ #0 */
5418 tmp2 = tcg_const_i32(0);
5419 gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
5420 tcg_temp_free(tmp2);
5421 break;
5422 case 30: /* Float VABS */
5423 gen_vfp_abs(0);
5424 break;
5425 case 31: /* Float VNEG */
5426 gen_vfp_neg(0);
5427 break;
5428 case 32: /* VSWP */
5429 tmp2 = neon_load_reg(rd, pass);
5430 neon_store_reg(rm, pass, tmp2);
5431 break;
5432 case 33: /* VTRN */
5433 tmp2 = neon_load_reg(rd, pass);
5434 switch (size) {
5435 case 0: gen_neon_trn_u8(tmp, tmp2); break;
5436 case 1: gen_neon_trn_u16(tmp, tmp2); break;
5437 case 2: abort();
5438 default: return 1;
5440 neon_store_reg(rm, pass, tmp2);
5441 break;
5442 case 56: /* Integer VRECPE */
5443 gen_helper_recpe_u32(tmp, tmp, cpu_env);
5444 break;
5445 case 57: /* Integer VRSQRTE */
5446 gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
5447 break;
5448 case 58: /* Float VRECPE */
5449 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
5450 break;
5451 case 59: /* Float VRSQRTE */
5452 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
5453 break;
5454 case 60: /* VCVT.F32.S32 */
5455 gen_vfp_tosiz(0);
5456 break;
5457 case 61: /* VCVT.F32.U32 */
5458 gen_vfp_touiz(0);
5459 break;
5460 case 62: /* VCVT.S32.F32 */
5461 gen_vfp_sito(0);
5462 break;
5463 case 63: /* VCVT.U32.F32 */
5464 gen_vfp_uito(0);
5465 break;
5466 default:
5467 /* Reserved: 21, 29, 39-56 */
5468 return 1;
5470 if (op == 30 || op == 31 || op >= 58) {
5471 tcg_gen_st_f32(cpu_F0s, cpu_env,
5472 neon_reg_offset(rd, pass));
5473 } else {
5474 neon_store_reg(rd, pass, tmp);
5477 break;
5479 } else if ((insn & (1 << 10)) == 0) {
5480 /* VTBL, VTBX. */
5481 n = ((insn >> 5) & 0x18) + 8;
5482 if (insn & (1 << 6)) {
5483 tmp = neon_load_reg(rd, 0);
5484 } else {
5485 tmp = new_tmp();
5486 tcg_gen_movi_i32(tmp, 0);
5488 tmp2 = neon_load_reg(rm, 0);
5489 gen_helper_neon_tbl(tmp2, tmp2, tmp, tcg_const_i32(rn),
5490 tcg_const_i32(n));
5491 dead_tmp(tmp);
5492 if (insn & (1 << 6)) {
5493 tmp = neon_load_reg(rd, 1);
5494 } else {
5495 tmp = new_tmp();
5496 tcg_gen_movi_i32(tmp, 0);
5498 tmp3 = neon_load_reg(rm, 1);
5499 gen_helper_neon_tbl(tmp3, tmp3, tmp, tcg_const_i32(rn),
5500 tcg_const_i32(n));
5501 neon_store_reg(rd, 0, tmp2);
5502 neon_store_reg(rd, 1, tmp3);
5503 dead_tmp(tmp);
5504 } else if ((insn & 0x380) == 0) {
5505 /* VDUP */
5506 if (insn & (1 << 19)) {
5507 tmp = neon_load_reg(rm, 1);
5508 } else {
5509 tmp = neon_load_reg(rm, 0);
5511 if (insn & (1 << 16)) {
5512 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
5513 } else if (insn & (1 << 17)) {
5514 if ((insn >> 18) & 1)
5515 gen_neon_dup_high16(tmp);
5516 else
5517 gen_neon_dup_low16(tmp);
5519 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5520 tmp2 = new_tmp();
5521 tcg_gen_mov_i32(tmp2, tmp);
5522 neon_store_reg(rd, pass, tmp2);
5524 dead_tmp(tmp);
5525 } else {
5526 return 1;
5530 return 0;
5533 static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
5535 int crn = (insn >> 16) & 0xf;
5536 int crm = insn & 0xf;
5537 int op1 = (insn >> 21) & 7;
5538 int op2 = (insn >> 5) & 7;
5539 int rt = (insn >> 12) & 0xf;
5540 TCGv tmp;
5542 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5543 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5544 /* TEECR */
5545 if (IS_USER(s))
5546 return 1;
5547 tmp = load_cpu_field(teecr);
5548 store_reg(s, rt, tmp);
5549 return 0;
5551 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5552 /* TEEHBR */
5553 if (IS_USER(s) && (env->teecr & 1))
5554 return 1;
5555 tmp = load_cpu_field(teehbr);
5556 store_reg(s, rt, tmp);
5557 return 0;
5560 fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5561 op1, crn, crm, op2);
5562 return 1;
5565 static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
5567 int crn = (insn >> 16) & 0xf;
5568 int crm = insn & 0xf;
5569 int op1 = (insn >> 21) & 7;
5570 int op2 = (insn >> 5) & 7;
5571 int rt = (insn >> 12) & 0xf;
5572 TCGv tmp;
5574 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5575 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5576 /* TEECR */
5577 if (IS_USER(s))
5578 return 1;
5579 tmp = load_reg(s, rt);
5580 gen_helper_set_teecr(cpu_env, tmp);
5581 dead_tmp(tmp);
5582 return 0;
5584 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5585 /* TEEHBR */
5586 if (IS_USER(s) && (env->teecr & 1))
5587 return 1;
5588 tmp = load_reg(s, rt);
5589 store_cpu_field(tmp, teehbr);
5590 return 0;
5593 fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5594 op1, crn, crm, op2);
5595 return 1;
5598 static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
5600 int cpnum;
5602 cpnum = (insn >> 8) & 0xf;
5603 if (arm_feature(env, ARM_FEATURE_XSCALE)
5604 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
5605 return 1;
5607 switch (cpnum) {
5608 case 0:
5609 case 1:
5610 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5611 return disas_iwmmxt_insn(env, s, insn);
5612 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
5613 return disas_dsp_insn(env, s, insn);
5615 return 1;
5616 case 10:
5617 case 11:
5618 return disas_vfp_insn (env, s, insn);
5619 case 14:
5620 /* Coprocessors 7-15 are architecturally reserved by ARM.
5621 Unfortunately Intel decided to ignore this. */
5622 if (arm_feature(env, ARM_FEATURE_XSCALE))
5623 goto board;
5624 if (insn & (1 << 20))
5625 return disas_cp14_read(env, s, insn);
5626 else
5627 return disas_cp14_write(env, s, insn);
5628 case 15:
5629 return disas_cp15_insn (env, s, insn);
5630 default:
5631 board:
5632 /* Unknown coprocessor. See if the board has hooked it. */
5633 return disas_cp_insn (env, s, insn);
5638 /* Store a 64-bit value to a register pair. Clobbers val. */
5639 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5641 TCGv tmp;
5642 tmp = new_tmp();
5643 tcg_gen_trunc_i64_i32(tmp, val);
5644 store_reg(s, rlow, tmp);
5645 tmp = new_tmp();
5646 tcg_gen_shri_i64(val, val, 32);
5647 tcg_gen_trunc_i64_i32(tmp, val);
5648 store_reg(s, rhigh, tmp);
5651 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5652 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5654 TCGv_i64 tmp;
5655 TCGv tmp2;
5657 /* Load value and extend to 64 bits. */
5658 tmp = tcg_temp_new_i64();
5659 tmp2 = load_reg(s, rlow);
5660 tcg_gen_extu_i32_i64(tmp, tmp2);
5661 dead_tmp(tmp2);
5662 tcg_gen_add_i64(val, val, tmp);
5665 /* load and add a 64-bit value from a register pair. */
5666 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5668 TCGv_i64 tmp;
5669 TCGv tmpl;
5670 TCGv tmph;
5672 /* Load 64-bit value rd:rn. */
5673 tmpl = load_reg(s, rlow);
5674 tmph = load_reg(s, rhigh);
5675 tmp = tcg_temp_new_i64();
5676 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
5677 dead_tmp(tmpl);
5678 dead_tmp(tmph);
5679 tcg_gen_add_i64(val, val, tmp);
5682 /* Set N and Z flags from a 64-bit value. */
5683 static void gen_logicq_cc(TCGv_i64 val)
5685 TCGv tmp = new_tmp();
5686 gen_helper_logicq_cc(tmp, val);
5687 gen_logic_CC(tmp);
5688 dead_tmp(tmp);
5691 static void disas_arm_insn(CPUState * env, DisasContext *s)
5693 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
5694 TCGv tmp;
5695 TCGv tmp2;
5696 TCGv tmp3;
5697 TCGv addr;
5698 TCGv_i64 tmp64;
5700 insn = ldl_code(s->pc);
5701 s->pc += 4;
5703 /* M variants do not implement ARM mode. */
5704 if (IS_M(env))
5705 goto illegal_op;
5706 cond = insn >> 28;
5707 if (cond == 0xf){
5708 /* Unconditional instructions. */
5709 if (((insn >> 25) & 7) == 1) {
5710 /* NEON Data processing. */
5711 if (!arm_feature(env, ARM_FEATURE_NEON))
5712 goto illegal_op;
5714 if (disas_neon_data_insn(env, s, insn))
5715 goto illegal_op;
5716 return;
5718 if ((insn & 0x0f100000) == 0x04000000) {
5719 /* NEON load/store. */
5720 if (!arm_feature(env, ARM_FEATURE_NEON))
5721 goto illegal_op;
5723 if (disas_neon_ls_insn(env, s, insn))
5724 goto illegal_op;
5725 return;
5727 if ((insn & 0x0d70f000) == 0x0550f000) {
5728 ARCH(5);
5729 return; /* PLD */
5730 } else if ((insn & 0x0ffffdff) == 0x01010000) {
5731 ARCH(6);
5732 /* setend */
5733 if (insn & (1 << 9)) {
5734 /* BE8 mode not implemented. */
5735 goto illegal_op;
5737 return;
5738 } else if ((insn & 0x0fffff00) == 0x057ff000) {
5739 switch ((insn >> 4) & 0xf) {
5740 case 1: /* clrex */
5741 ARCH(6K);
5742 gen_helper_clrex(cpu_env);
5743 return;
5744 case 4: /* dsb */
5745 case 5: /* dmb */
5746 case 6: /* isb */
5747 ARCH(7);
5748 /* We don't emulate caches so these are a no-op. */
5749 return;
5750 default:
5751 goto illegal_op;
5753 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
5754 /* srs */
5755 int32_t offset;
5756 if (IS_USER(s))
5757 goto illegal_op;
5758 ARCH(6);
5759 op1 = (insn & 0x1f);
5760 if (op1 == (env->uncached_cpsr & CPSR_M)) {
5761 addr = load_reg(s, 13);
5762 } else {
5763 addr = new_tmp();
5764 gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op1));
5766 i = (insn >> 23) & 3;
5767 switch (i) {
5768 case 0: offset = -4; break; /* DA */
5769 case 1: offset = 0; break; /* IA */
5770 case 2: offset = -8; break; /* DB */
5771 case 3: offset = 4; break; /* IB */
5772 default: abort();
5774 if (offset)
5775 tcg_gen_addi_i32(addr, addr, offset);
5776 tmp = load_reg(s, 14);
5777 gen_st32(tmp, addr, 0);
5778 tmp = load_cpu_field(spsr);
5779 tcg_gen_addi_i32(addr, addr, 4);
5780 gen_st32(tmp, addr, 0);
5781 if (insn & (1 << 21)) {
5782 /* Base writeback. */
5783 switch (i) {
5784 case 0: offset = -8; break;
5785 case 1: offset = 4; break;
5786 case 2: offset = -4; break;
5787 case 3: offset = 0; break;
5788 default: abort();
5790 if (offset)
5791 tcg_gen_addi_i32(addr, addr, offset);
5792 if (op1 == (env->uncached_cpsr & CPSR_M)) {
5793 store_reg(s, 13, addr);
5794 } else {
5795 gen_helper_set_r13_banked(cpu_env, tcg_const_i32(op1), addr);
5796 dead_tmp(addr);
5798 } else {
5799 dead_tmp(addr);
5801 } else if ((insn & 0x0e5fffe0) == 0x081d0a00) {
5802 /* rfe */
5803 int32_t offset;
5804 if (IS_USER(s))
5805 goto illegal_op;
5806 ARCH(6);
5807 rn = (insn >> 16) & 0xf;
5808 addr = load_reg(s, rn);
5809 i = (insn >> 23) & 3;
5810 switch (i) {
5811 case 0: offset = -4; break; /* DA */
5812 case 1: offset = 0; break; /* IA */
5813 case 2: offset = -8; break; /* DB */
5814 case 3: offset = 4; break; /* IB */
5815 default: abort();
5817 if (offset)
5818 tcg_gen_addi_i32(addr, addr, offset);
5819 /* Load PC into tmp and CPSR into tmp2. */
5820 tmp = gen_ld32(addr, 0);
5821 tcg_gen_addi_i32(addr, addr, 4);
5822 tmp2 = gen_ld32(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 store_reg(s, rn, addr);
5835 } else {
5836 dead_tmp(addr);
5838 gen_rfe(s, tmp, tmp2);
5839 return;
5840 } else if ((insn & 0x0e000000) == 0x0a000000) {
5841 /* branch link and change to thumb (blx <offset>) */
5842 int32_t offset;
5843 ARCH(5);
5844 val = (uint32_t)s->pc;
5845 tmp = new_tmp();
5846 tcg_gen_movi_i32(tmp, val);
5847 store_reg(s, 14, tmp);
5848 /* Sign-extend the 24-bit offset */
5849 offset = (((int32_t)insn) << 8) >> 8;
5850 /* offset * 4 + bit24 * 2 + (thumb bit) */
5851 val += (offset << 2) | ((insn >> 23) & 2) | 1;
5852 /* pipeline offset */
5853 val += 4;
5854 gen_bx_im(s, val);
5855 return;
5856 } else if ((insn & 0x0e000f00) == 0x0c000100) {
5857 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5858 /* iWMMXt register transfer. */
5859 if (env->cp15.c15_cpar & (1 << 1))
5860 if (!disas_iwmmxt_insn(env, s, insn))
5861 return;
5863 } else if ((insn & 0x0fe00000) == 0x0c400000) {
5864 /* Coprocessor double register transfer. */
5865 ARCH(5);
5866 } else if ((insn & 0x0f000010) == 0x0e000010) {
5867 /* Additional coprocessor register transfer. */
5868 ARCH(5);
5869 } else if ((insn & 0x0ff10020) == 0x01000000) {
5870 uint32_t mask;
5871 uint32_t val;
5872 /* cps (privileged) */
5873 if (IS_USER(s))
5874 return;
5875 mask = val = 0;
5876 if (insn & (1 << 19)) {
5877 if (insn & (1 << 8))
5878 mask |= CPSR_A;
5879 if (insn & (1 << 7))
5880 mask |= CPSR_I;
5881 if (insn & (1 << 6))
5882 mask |= CPSR_F;
5883 if (insn & (1 << 18))
5884 val |= mask;
5886 if (insn & (1 << 17)) {
5887 mask |= CPSR_M;
5888 val |= (insn & 0x1f);
5890 if (mask) {
5891 gen_set_psr_im(s, mask, 0, val);
5893 return;
5895 goto illegal_op;
5897 if (cond != 0xe) {
5898 /* if not always execute, we generate a conditional jump to
5899 next instruction */
5900 s->condlabel = gen_new_label();
5901 gen_test_cc(cond ^ 1, s->condlabel);
5902 s->condjmp = 1;
5904 if ((insn & 0x0f900000) == 0x03000000) {
5905 if ((insn & (1 << 21)) == 0) {
5906 ARCH(6T2);
5907 rd = (insn >> 12) & 0xf;
5908 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
5909 if ((insn & (1 << 22)) == 0) {
5910 /* MOVW */
5911 tmp = new_tmp();
5912 tcg_gen_movi_i32(tmp, val);
5913 } else {
5914 /* MOVT */
5915 tmp = load_reg(s, rd);
5916 tcg_gen_ext16u_i32(tmp, tmp);
5917 tcg_gen_ori_i32(tmp, tmp, val << 16);
5919 store_reg(s, rd, tmp);
5920 } else {
5921 if (((insn >> 12) & 0xf) != 0xf)
5922 goto illegal_op;
5923 if (((insn >> 16) & 0xf) == 0) {
5924 gen_nop_hint(s, insn & 0xff);
5925 } else {
5926 /* CPSR = immediate */
5927 val = insn & 0xff;
5928 shift = ((insn >> 8) & 0xf) * 2;
5929 if (shift)
5930 val = (val >> shift) | (val << (32 - shift));
5931 i = ((insn & (1 << 22)) != 0);
5932 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
5933 goto illegal_op;
5936 } else if ((insn & 0x0f900000) == 0x01000000
5937 && (insn & 0x00000090) != 0x00000090) {
5938 /* miscellaneous instructions */
5939 op1 = (insn >> 21) & 3;
5940 sh = (insn >> 4) & 0xf;
5941 rm = insn & 0xf;
5942 switch (sh) {
5943 case 0x0: /* move program status register */
5944 if (op1 & 1) {
5945 /* PSR = reg */
5946 tmp = load_reg(s, rm);
5947 i = ((op1 & 2) != 0);
5948 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
5949 goto illegal_op;
5950 } else {
5951 /* reg = PSR */
5952 rd = (insn >> 12) & 0xf;
5953 if (op1 & 2) {
5954 if (IS_USER(s))
5955 goto illegal_op;
5956 tmp = load_cpu_field(spsr);
5957 } else {
5958 tmp = new_tmp();
5959 gen_helper_cpsr_read(tmp);
5961 store_reg(s, rd, tmp);
5963 break;
5964 case 0x1:
5965 if (op1 == 1) {
5966 /* branch/exchange thumb (bx). */
5967 tmp = load_reg(s, rm);
5968 gen_bx(s, tmp);
5969 } else if (op1 == 3) {
5970 /* clz */
5971 rd = (insn >> 12) & 0xf;
5972 tmp = load_reg(s, rm);
5973 gen_helper_clz(tmp, tmp);
5974 store_reg(s, rd, tmp);
5975 } else {
5976 goto illegal_op;
5978 break;
5979 case 0x2:
5980 if (op1 == 1) {
5981 ARCH(5J); /* bxj */
5982 /* Trivial implementation equivalent to bx. */
5983 tmp = load_reg(s, rm);
5984 gen_bx(s, tmp);
5985 } else {
5986 goto illegal_op;
5988 break;
5989 case 0x3:
5990 if (op1 != 1)
5991 goto illegal_op;
5992 ARCH(5);
5993 /* branch link/exchange thumb (blx) */
5994 tmp = load_reg(s, rm);
5995 tmp2 = new_tmp();
5996 tcg_gen_movi_i32(tmp2, s->pc);
5997 store_reg(s, 14, tmp2);
5998 gen_bx(s, tmp);
5999 break;
6000 case 0x5: /* saturating add/subtract */
6001 rd = (insn >> 12) & 0xf;
6002 rn = (insn >> 16) & 0xf;
6003 tmp = load_reg(s, rm);
6004 tmp2 = load_reg(s, rn);
6005 if (op1 & 2)
6006 gen_helper_double_saturate(tmp2, tmp2);
6007 if (op1 & 1)
6008 gen_helper_sub_saturate(tmp, tmp, tmp2);
6009 else
6010 gen_helper_add_saturate(tmp, tmp, tmp2);
6011 dead_tmp(tmp2);
6012 store_reg(s, rd, tmp);
6013 break;
6014 case 7: /* bkpt */
6015 ARCH(5);
6016 gen_set_condexec(s);
6017 gen_set_pc_im(s->pc - 4);
6018 gen_exception(EXCP_BKPT);
6019 s->is_jmp = DISAS_JUMP;
6020 break;
6021 case 0x8: /* signed multiply */
6022 case 0xa:
6023 case 0xc:
6024 case 0xe:
6025 rs = (insn >> 8) & 0xf;
6026 rn = (insn >> 12) & 0xf;
6027 rd = (insn >> 16) & 0xf;
6028 if (op1 == 1) {
6029 /* (32 * 16) >> 16 */
6030 tmp = load_reg(s, rm);
6031 tmp2 = load_reg(s, rs);
6032 if (sh & 4)
6033 tcg_gen_sari_i32(tmp2, tmp2, 16);
6034 else
6035 gen_sxth(tmp2);
6036 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6037 tcg_gen_shri_i64(tmp64, tmp64, 16);
6038 tmp = new_tmp();
6039 tcg_gen_trunc_i64_i32(tmp, tmp64);
6040 if ((sh & 2) == 0) {
6041 tmp2 = load_reg(s, rn);
6042 gen_helper_add_setq(tmp, tmp, tmp2);
6043 dead_tmp(tmp2);
6045 store_reg(s, rd, tmp);
6046 } else {
6047 /* 16 * 16 */
6048 tmp = load_reg(s, rm);
6049 tmp2 = load_reg(s, rs);
6050 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
6051 dead_tmp(tmp2);
6052 if (op1 == 2) {
6053 tmp64 = tcg_temp_new_i64();
6054 tcg_gen_ext_i32_i64(tmp64, tmp);
6055 dead_tmp(tmp);
6056 gen_addq(s, tmp64, rn, rd);
6057 gen_storeq_reg(s, rn, rd, tmp64);
6058 } else {
6059 if (op1 == 0) {
6060 tmp2 = load_reg(s, rn);
6061 gen_helper_add_setq(tmp, tmp, tmp2);
6062 dead_tmp(tmp2);
6064 store_reg(s, rd, tmp);
6067 break;
6068 default:
6069 goto illegal_op;
6071 } else if (((insn & 0x0e000000) == 0 &&
6072 (insn & 0x00000090) != 0x90) ||
6073 ((insn & 0x0e000000) == (1 << 25))) {
6074 int set_cc, logic_cc, shiftop;
6076 op1 = (insn >> 21) & 0xf;
6077 set_cc = (insn >> 20) & 1;
6078 logic_cc = table_logic_cc[op1] & set_cc;
6080 /* data processing instruction */
6081 if (insn & (1 << 25)) {
6082 /* immediate operand */
6083 val = insn & 0xff;
6084 shift = ((insn >> 8) & 0xf) * 2;
6085 if (shift) {
6086 val = (val >> shift) | (val << (32 - shift));
6088 tmp2 = new_tmp();
6089 tcg_gen_movi_i32(tmp2, val);
6090 if (logic_cc && shift) {
6091 gen_set_CF_bit31(tmp2);
6093 } else {
6094 /* register */
6095 rm = (insn) & 0xf;
6096 tmp2 = load_reg(s, rm);
6097 shiftop = (insn >> 5) & 3;
6098 if (!(insn & (1 << 4))) {
6099 shift = (insn >> 7) & 0x1f;
6100 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
6101 } else {
6102 rs = (insn >> 8) & 0xf;
6103 tmp = load_reg(s, rs);
6104 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
6107 if (op1 != 0x0f && op1 != 0x0d) {
6108 rn = (insn >> 16) & 0xf;
6109 tmp = load_reg(s, rn);
6110 } else {
6111 TCGV_UNUSED(tmp);
6113 rd = (insn >> 12) & 0xf;
6114 switch(op1) {
6115 case 0x00:
6116 tcg_gen_and_i32(tmp, tmp, tmp2);
6117 if (logic_cc) {
6118 gen_logic_CC(tmp);
6120 store_reg_bx(env, s, rd, tmp);
6121 break;
6122 case 0x01:
6123 tcg_gen_xor_i32(tmp, tmp, tmp2);
6124 if (logic_cc) {
6125 gen_logic_CC(tmp);
6127 store_reg_bx(env, s, rd, tmp);
6128 break;
6129 case 0x02:
6130 if (set_cc && rd == 15) {
6131 /* SUBS r15, ... is used for exception return. */
6132 if (IS_USER(s)) {
6133 goto illegal_op;
6135 gen_helper_sub_cc(tmp, tmp, tmp2);
6136 gen_exception_return(s, tmp);
6137 } else {
6138 if (set_cc) {
6139 gen_helper_sub_cc(tmp, tmp, tmp2);
6140 } else {
6141 tcg_gen_sub_i32(tmp, tmp, tmp2);
6143 store_reg_bx(env, s, rd, tmp);
6145 break;
6146 case 0x03:
6147 if (set_cc) {
6148 gen_helper_sub_cc(tmp, tmp2, tmp);
6149 } else {
6150 tcg_gen_sub_i32(tmp, tmp2, tmp);
6152 store_reg_bx(env, s, rd, tmp);
6153 break;
6154 case 0x04:
6155 if (set_cc) {
6156 gen_helper_add_cc(tmp, tmp, tmp2);
6157 } else {
6158 tcg_gen_add_i32(tmp, tmp, tmp2);
6160 store_reg_bx(env, s, rd, tmp);
6161 break;
6162 case 0x05:
6163 if (set_cc) {
6164 gen_helper_adc_cc(tmp, tmp, tmp2);
6165 } else {
6166 gen_add_carry(tmp, tmp, tmp2);
6168 store_reg_bx(env, s, rd, tmp);
6169 break;
6170 case 0x06:
6171 if (set_cc) {
6172 gen_helper_sbc_cc(tmp, tmp, tmp2);
6173 } else {
6174 gen_sub_carry(tmp, tmp, tmp2);
6176 store_reg_bx(env, s, rd, tmp);
6177 break;
6178 case 0x07:
6179 if (set_cc) {
6180 gen_helper_sbc_cc(tmp, tmp2, tmp);
6181 } else {
6182 gen_sub_carry(tmp, tmp2, tmp);
6184 store_reg_bx(env, s, rd, tmp);
6185 break;
6186 case 0x08:
6187 if (set_cc) {
6188 tcg_gen_and_i32(tmp, tmp, tmp2);
6189 gen_logic_CC(tmp);
6191 dead_tmp(tmp);
6192 break;
6193 case 0x09:
6194 if (set_cc) {
6195 tcg_gen_xor_i32(tmp, tmp, tmp2);
6196 gen_logic_CC(tmp);
6198 dead_tmp(tmp);
6199 break;
6200 case 0x0a:
6201 if (set_cc) {
6202 gen_helper_sub_cc(tmp, tmp, tmp2);
6204 dead_tmp(tmp);
6205 break;
6206 case 0x0b:
6207 if (set_cc) {
6208 gen_helper_add_cc(tmp, tmp, tmp2);
6210 dead_tmp(tmp);
6211 break;
6212 case 0x0c:
6213 tcg_gen_or_i32(tmp, tmp, tmp2);
6214 if (logic_cc) {
6215 gen_logic_CC(tmp);
6217 store_reg_bx(env, s, rd, tmp);
6218 break;
6219 case 0x0d:
6220 if (logic_cc && rd == 15) {
6221 /* MOVS r15, ... is used for exception return. */
6222 if (IS_USER(s)) {
6223 goto illegal_op;
6225 gen_exception_return(s, tmp2);
6226 } else {
6227 if (logic_cc) {
6228 gen_logic_CC(tmp2);
6230 store_reg_bx(env, s, rd, tmp2);
6232 break;
6233 case 0x0e:
6234 tcg_gen_bic_i32(tmp, tmp, tmp2);
6235 if (logic_cc) {
6236 gen_logic_CC(tmp);
6238 store_reg_bx(env, s, rd, tmp);
6239 break;
6240 default:
6241 case 0x0f:
6242 tcg_gen_not_i32(tmp2, tmp2);
6243 if (logic_cc) {
6244 gen_logic_CC(tmp2);
6246 store_reg_bx(env, s, rd, tmp2);
6247 break;
6249 if (op1 != 0x0f && op1 != 0x0d) {
6250 dead_tmp(tmp2);
6252 } else {
6253 /* other instructions */
6254 op1 = (insn >> 24) & 0xf;
6255 switch(op1) {
6256 case 0x0:
6257 case 0x1:
6258 /* multiplies, extra load/stores */
6259 sh = (insn >> 5) & 3;
6260 if (sh == 0) {
6261 if (op1 == 0x0) {
6262 rd = (insn >> 16) & 0xf;
6263 rn = (insn >> 12) & 0xf;
6264 rs = (insn >> 8) & 0xf;
6265 rm = (insn) & 0xf;
6266 op1 = (insn >> 20) & 0xf;
6267 switch (op1) {
6268 case 0: case 1: case 2: case 3: case 6:
6269 /* 32 bit mul */
6270 tmp = load_reg(s, rs);
6271 tmp2 = load_reg(s, rm);
6272 tcg_gen_mul_i32(tmp, tmp, tmp2);
6273 dead_tmp(tmp2);
6274 if (insn & (1 << 22)) {
6275 /* Subtract (mls) */
6276 ARCH(6T2);
6277 tmp2 = load_reg(s, rn);
6278 tcg_gen_sub_i32(tmp, tmp2, tmp);
6279 dead_tmp(tmp2);
6280 } else if (insn & (1 << 21)) {
6281 /* Add */
6282 tmp2 = load_reg(s, rn);
6283 tcg_gen_add_i32(tmp, tmp, tmp2);
6284 dead_tmp(tmp2);
6286 if (insn & (1 << 20))
6287 gen_logic_CC(tmp);
6288 store_reg(s, rd, tmp);
6289 break;
6290 default:
6291 /* 64 bit mul */
6292 tmp = load_reg(s, rs);
6293 tmp2 = load_reg(s, rm);
6294 if (insn & (1 << 22))
6295 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6296 else
6297 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
6298 if (insn & (1 << 21)) /* mult accumulate */
6299 gen_addq(s, tmp64, rn, rd);
6300 if (!(insn & (1 << 23))) { /* double accumulate */
6301 ARCH(6);
6302 gen_addq_lo(s, tmp64, rn);
6303 gen_addq_lo(s, tmp64, rd);
6305 if (insn & (1 << 20))
6306 gen_logicq_cc(tmp64);
6307 gen_storeq_reg(s, rn, rd, tmp64);
6308 break;
6310 } else {
6311 rn = (insn >> 16) & 0xf;
6312 rd = (insn >> 12) & 0xf;
6313 if (insn & (1 << 23)) {
6314 /* load/store exclusive */
6315 op1 = (insn >> 21) & 0x3;
6316 if (op1)
6317 ARCH(6K);
6318 else
6319 ARCH(6);
6320 addr = tcg_temp_local_new_i32();
6321 tcg_gen_mov_i32(addr, cpu_R[rn]);
6322 if (insn & (1 << 20)) {
6323 gen_helper_mark_exclusive(cpu_env, addr);
6324 switch (op1) {
6325 case 0: /* ldrex */
6326 tmp = gen_ld32(addr, IS_USER(s));
6327 break;
6328 case 1: /* ldrexd */
6329 tmp = gen_ld32(addr, IS_USER(s));
6330 store_reg(s, rd, tmp);
6331 tcg_gen_addi_i32(addr, addr, 4);
6332 tmp = gen_ld32(addr, IS_USER(s));
6333 rd++;
6334 break;
6335 case 2: /* ldrexb */
6336 tmp = gen_ld8u(addr, IS_USER(s));
6337 break;
6338 case 3: /* ldrexh */
6339 tmp = gen_ld16u(addr, IS_USER(s));
6340 break;
6341 default:
6342 abort();
6344 store_reg(s, rd, tmp);
6345 } else {
6346 int label = gen_new_label();
6347 rm = insn & 0xf;
6348 tmp2 = tcg_temp_local_new_i32();
6349 gen_helper_test_exclusive(tmp2, cpu_env, addr);
6350 tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label);
6351 tmp = load_reg(s,rm);
6352 switch (op1) {
6353 case 0: /* strex */
6354 gen_st32(tmp, addr, IS_USER(s));
6355 break;
6356 case 1: /* strexd */
6357 gen_st32(tmp, addr, IS_USER(s));
6358 tcg_gen_addi_i32(addr, addr, 4);
6359 tmp = load_reg(s, rm + 1);
6360 gen_st32(tmp, addr, IS_USER(s));
6361 break;
6362 case 2: /* strexb */
6363 gen_st8(tmp, addr, IS_USER(s));
6364 break;
6365 case 3: /* strexh */
6366 gen_st16(tmp, addr, IS_USER(s));
6367 break;
6368 default:
6369 abort();
6371 gen_set_label(label);
6372 tcg_gen_mov_i32(cpu_R[rd], tmp2);
6373 tcg_temp_free(tmp2);
6375 tcg_temp_free(addr);
6376 } else {
6377 /* SWP instruction */
6378 rm = (insn) & 0xf;
6380 /* ??? This is not really atomic. However we know
6381 we never have multiple CPUs running in parallel,
6382 so it is good enough. */
6383 addr = load_reg(s, rn);
6384 tmp = load_reg(s, rm);
6385 if (insn & (1 << 22)) {
6386 tmp2 = gen_ld8u(addr, IS_USER(s));
6387 gen_st8(tmp, addr, IS_USER(s));
6388 } else {
6389 tmp2 = gen_ld32(addr, IS_USER(s));
6390 gen_st32(tmp, addr, IS_USER(s));
6392 dead_tmp(addr);
6393 store_reg(s, rd, tmp2);
6396 } else {
6397 int address_offset;
6398 int load;
6399 /* Misc load/store */
6400 rn = (insn >> 16) & 0xf;
6401 rd = (insn >> 12) & 0xf;
6402 addr = load_reg(s, rn);
6403 if (insn & (1 << 24))
6404 gen_add_datah_offset(s, insn, 0, addr);
6405 address_offset = 0;
6406 if (insn & (1 << 20)) {
6407 /* load */
6408 switch(sh) {
6409 case 1:
6410 tmp = gen_ld16u(addr, IS_USER(s));
6411 break;
6412 case 2:
6413 tmp = gen_ld8s(addr, IS_USER(s));
6414 break;
6415 default:
6416 case 3:
6417 tmp = gen_ld16s(addr, IS_USER(s));
6418 break;
6420 load = 1;
6421 } else if (sh & 2) {
6422 /* doubleword */
6423 if (sh & 1) {
6424 /* store */
6425 tmp = load_reg(s, rd);
6426 gen_st32(tmp, addr, IS_USER(s));
6427 tcg_gen_addi_i32(addr, addr, 4);
6428 tmp = load_reg(s, rd + 1);
6429 gen_st32(tmp, addr, IS_USER(s));
6430 load = 0;
6431 } else {
6432 /* load */
6433 tmp = gen_ld32(addr, IS_USER(s));
6434 store_reg(s, rd, tmp);
6435 tcg_gen_addi_i32(addr, addr, 4);
6436 tmp = gen_ld32(addr, IS_USER(s));
6437 rd++;
6438 load = 1;
6440 address_offset = -4;
6441 } else {
6442 /* store */
6443 tmp = load_reg(s, rd);
6444 gen_st16(tmp, addr, IS_USER(s));
6445 load = 0;
6447 /* Perform base writeback before the loaded value to
6448 ensure correct behavior with overlapping index registers.
6449 ldrd with base writeback is is undefined if the
6450 destination and index registers overlap. */
6451 if (!(insn & (1 << 24))) {
6452 gen_add_datah_offset(s, insn, address_offset, addr);
6453 store_reg(s, rn, addr);
6454 } else if (insn & (1 << 21)) {
6455 if (address_offset)
6456 tcg_gen_addi_i32(addr, addr, address_offset);
6457 store_reg(s, rn, addr);
6458 } else {
6459 dead_tmp(addr);
6461 if (load) {
6462 /* Complete the load. */
6463 store_reg(s, rd, tmp);
6466 break;
6467 case 0x4:
6468 case 0x5:
6469 goto do_ldst;
6470 case 0x6:
6471 case 0x7:
6472 if (insn & (1 << 4)) {
6473 ARCH(6);
6474 /* Armv6 Media instructions. */
6475 rm = insn & 0xf;
6476 rn = (insn >> 16) & 0xf;
6477 rd = (insn >> 12) & 0xf;
6478 rs = (insn >> 8) & 0xf;
6479 switch ((insn >> 23) & 3) {
6480 case 0: /* Parallel add/subtract. */
6481 op1 = (insn >> 20) & 7;
6482 tmp = load_reg(s, rn);
6483 tmp2 = load_reg(s, rm);
6484 sh = (insn >> 5) & 7;
6485 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
6486 goto illegal_op;
6487 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
6488 dead_tmp(tmp2);
6489 store_reg(s, rd, tmp);
6490 break;
6491 case 1:
6492 if ((insn & 0x00700020) == 0) {
6493 /* Halfword pack. */
6494 tmp = load_reg(s, rn);
6495 tmp2 = load_reg(s, rm);
6496 shift = (insn >> 7) & 0x1f;
6497 if (insn & (1 << 6)) {
6498 /* pkhtb */
6499 if (shift == 0)
6500 shift = 31;
6501 tcg_gen_sari_i32(tmp2, tmp2, shift);
6502 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
6503 tcg_gen_ext16u_i32(tmp2, tmp2);
6504 } else {
6505 /* pkhbt */
6506 if (shift)
6507 tcg_gen_shli_i32(tmp2, tmp2, shift);
6508 tcg_gen_ext16u_i32(tmp, tmp);
6509 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
6511 tcg_gen_or_i32(tmp, tmp, tmp2);
6512 dead_tmp(tmp2);
6513 store_reg(s, rd, tmp);
6514 } else if ((insn & 0x00200020) == 0x00200000) {
6515 /* [us]sat */
6516 tmp = load_reg(s, rm);
6517 shift = (insn >> 7) & 0x1f;
6518 if (insn & (1 << 6)) {
6519 if (shift == 0)
6520 shift = 31;
6521 tcg_gen_sari_i32(tmp, tmp, shift);
6522 } else {
6523 tcg_gen_shli_i32(tmp, tmp, shift);
6525 sh = (insn >> 16) & 0x1f;
6526 if (sh != 0) {
6527 if (insn & (1 << 22))
6528 gen_helper_usat(tmp, tmp, tcg_const_i32(sh));
6529 else
6530 gen_helper_ssat(tmp, tmp, tcg_const_i32(sh));
6532 store_reg(s, rd, tmp);
6533 } else if ((insn & 0x00300fe0) == 0x00200f20) {
6534 /* [us]sat16 */
6535 tmp = load_reg(s, rm);
6536 sh = (insn >> 16) & 0x1f;
6537 if (sh != 0) {
6538 if (insn & (1 << 22))
6539 gen_helper_usat16(tmp, tmp, tcg_const_i32(sh));
6540 else
6541 gen_helper_ssat16(tmp, tmp, tcg_const_i32(sh));
6543 store_reg(s, rd, tmp);
6544 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
6545 /* Select bytes. */
6546 tmp = load_reg(s, rn);
6547 tmp2 = load_reg(s, rm);
6548 tmp3 = new_tmp();
6549 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
6550 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
6551 dead_tmp(tmp3);
6552 dead_tmp(tmp2);
6553 store_reg(s, rd, tmp);
6554 } else if ((insn & 0x000003e0) == 0x00000060) {
6555 tmp = load_reg(s, rm);
6556 shift = (insn >> 10) & 3;
6557 /* ??? In many cases it's not neccessary to do a
6558 rotate, a shift is sufficient. */
6559 if (shift != 0)
6560 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
6561 op1 = (insn >> 20) & 7;
6562 switch (op1) {
6563 case 0: gen_sxtb16(tmp); break;
6564 case 2: gen_sxtb(tmp); break;
6565 case 3: gen_sxth(tmp); break;
6566 case 4: gen_uxtb16(tmp); break;
6567 case 6: gen_uxtb(tmp); break;
6568 case 7: gen_uxth(tmp); break;
6569 default: goto illegal_op;
6571 if (rn != 15) {
6572 tmp2 = load_reg(s, rn);
6573 if ((op1 & 3) == 0) {
6574 gen_add16(tmp, tmp2);
6575 } else {
6576 tcg_gen_add_i32(tmp, tmp, tmp2);
6577 dead_tmp(tmp2);
6580 store_reg(s, rd, tmp);
6581 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
6582 /* rev */
6583 tmp = load_reg(s, rm);
6584 if (insn & (1 << 22)) {
6585 if (insn & (1 << 7)) {
6586 gen_revsh(tmp);
6587 } else {
6588 ARCH(6T2);
6589 gen_helper_rbit(tmp, tmp);
6591 } else {
6592 if (insn & (1 << 7))
6593 gen_rev16(tmp);
6594 else
6595 tcg_gen_bswap32_i32(tmp, tmp);
6597 store_reg(s, rd, tmp);
6598 } else {
6599 goto illegal_op;
6601 break;
6602 case 2: /* Multiplies (Type 3). */
6603 tmp = load_reg(s, rm);
6604 tmp2 = load_reg(s, rs);
6605 if (insn & (1 << 20)) {
6606 /* Signed multiply most significant [accumulate]. */
6607 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6608 if (insn & (1 << 5))
6609 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
6610 tcg_gen_shri_i64(tmp64, tmp64, 32);
6611 tmp = new_tmp();
6612 tcg_gen_trunc_i64_i32(tmp, tmp64);
6613 if (rd != 15) {
6614 tmp2 = load_reg(s, rd);
6615 if (insn & (1 << 6)) {
6616 tcg_gen_sub_i32(tmp, tmp, tmp2);
6617 } else {
6618 tcg_gen_add_i32(tmp, tmp, tmp2);
6620 dead_tmp(tmp2);
6622 store_reg(s, rn, tmp);
6623 } else {
6624 if (insn & (1 << 5))
6625 gen_swap_half(tmp2);
6626 gen_smul_dual(tmp, tmp2);
6627 /* This addition cannot overflow. */
6628 if (insn & (1 << 6)) {
6629 tcg_gen_sub_i32(tmp, tmp, tmp2);
6630 } else {
6631 tcg_gen_add_i32(tmp, tmp, tmp2);
6633 dead_tmp(tmp2);
6634 if (insn & (1 << 22)) {
6635 /* smlald, smlsld */
6636 tmp64 = tcg_temp_new_i64();
6637 tcg_gen_ext_i32_i64(tmp64, tmp);
6638 dead_tmp(tmp);
6639 gen_addq(s, tmp64, rd, rn);
6640 gen_storeq_reg(s, rd, rn, tmp64);
6641 } else {
6642 /* smuad, smusd, smlad, smlsd */
6643 if (rd != 15)
6645 tmp2 = load_reg(s, rd);
6646 gen_helper_add_setq(tmp, tmp, tmp2);
6647 dead_tmp(tmp2);
6649 store_reg(s, rn, tmp);
6652 break;
6653 case 3:
6654 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
6655 switch (op1) {
6656 case 0: /* Unsigned sum of absolute differences. */
6657 ARCH(6);
6658 tmp = load_reg(s, rm);
6659 tmp2 = load_reg(s, rs);
6660 gen_helper_usad8(tmp, tmp, tmp2);
6661 dead_tmp(tmp2);
6662 if (rd != 15) {
6663 tmp2 = load_reg(s, rd);
6664 tcg_gen_add_i32(tmp, tmp, tmp2);
6665 dead_tmp(tmp2);
6667 store_reg(s, rn, tmp);
6668 break;
6669 case 0x20: case 0x24: case 0x28: case 0x2c:
6670 /* Bitfield insert/clear. */
6671 ARCH(6T2);
6672 shift = (insn >> 7) & 0x1f;
6673 i = (insn >> 16) & 0x1f;
6674 i = i + 1 - shift;
6675 if (rm == 15) {
6676 tmp = new_tmp();
6677 tcg_gen_movi_i32(tmp, 0);
6678 } else {
6679 tmp = load_reg(s, rm);
6681 if (i != 32) {
6682 tmp2 = load_reg(s, rd);
6683 gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
6684 dead_tmp(tmp2);
6686 store_reg(s, rd, tmp);
6687 break;
6688 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6689 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6690 ARCH(6T2);
6691 tmp = load_reg(s, rm);
6692 shift = (insn >> 7) & 0x1f;
6693 i = ((insn >> 16) & 0x1f) + 1;
6694 if (shift + i > 32)
6695 goto illegal_op;
6696 if (i < 32) {
6697 if (op1 & 0x20) {
6698 gen_ubfx(tmp, shift, (1u << i) - 1);
6699 } else {
6700 gen_sbfx(tmp, shift, i);
6703 store_reg(s, rd, tmp);
6704 break;
6705 default:
6706 goto illegal_op;
6708 break;
6710 break;
6712 do_ldst:
6713 /* Check for undefined extension instructions
6714 * per the ARM Bible IE:
6715 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6717 sh = (0xf << 20) | (0xf << 4);
6718 if (op1 == 0x7 && ((insn & sh) == sh))
6720 goto illegal_op;
6722 /* load/store byte/word */
6723 rn = (insn >> 16) & 0xf;
6724 rd = (insn >> 12) & 0xf;
6725 tmp2 = load_reg(s, rn);
6726 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
6727 if (insn & (1 << 24))
6728 gen_add_data_offset(s, insn, tmp2);
6729 if (insn & (1 << 20)) {
6730 /* load */
6731 if (insn & (1 << 22)) {
6732 tmp = gen_ld8u(tmp2, i);
6733 } else {
6734 tmp = gen_ld32(tmp2, i);
6736 } else {
6737 /* store */
6738 tmp = load_reg(s, rd);
6739 if (insn & (1 << 22))
6740 gen_st8(tmp, tmp2, i);
6741 else
6742 gen_st32(tmp, tmp2, i);
6744 if (!(insn & (1 << 24))) {
6745 gen_add_data_offset(s, insn, tmp2);
6746 store_reg(s, rn, tmp2);
6747 } else if (insn & (1 << 21)) {
6748 store_reg(s, rn, tmp2);
6749 } else {
6750 dead_tmp(tmp2);
6752 if (insn & (1 << 20)) {
6753 /* Complete the load. */
6754 if (rd == 15 && ENABLE_ARCH_5)
6755 gen_bx(s, tmp);
6756 else
6757 store_reg(s, rd, tmp);
6759 break;
6760 case 0x08:
6761 case 0x09:
6763 int j, n, user, loaded_base;
6764 int crement = 0;
6765 TCGv loaded_var;
6766 /* load/store multiple words */
6767 /* XXX: store correct base if write back */
6768 user = 0;
6769 if (insn & (1 << 22)) {
6770 if (IS_USER(s))
6771 goto illegal_op; /* only usable in supervisor mode */
6773 if ((insn & (1 << 15)) == 0)
6774 user = 1;
6776 rn = (insn >> 16) & 0xf;
6777 addr = load_reg(s, rn);
6779 /* compute total size */
6780 loaded_base = 0;
6781 TCGV_UNUSED(loaded_var);
6782 n = 0;
6783 for(i=0;i<16;i++) {
6784 if (insn & (1 << i))
6785 n++;
6787 /* XXX: test invalid n == 0 case ? */
6788 if (insn & (1 << 23)) {
6789 if (insn & (1 << 24)) {
6790 /* pre increment */
6791 tcg_gen_addi_i32(addr, addr, 4);
6792 } else {
6793 /* post increment */
6795 } else {
6796 if (insn & (1 << 24)) {
6797 /* pre decrement */
6798 tcg_gen_addi_i32(addr, addr, -(n * 4));
6799 } else {
6800 /* post decrement */
6801 if (n != 1)
6802 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6806 if (insn & (1 << 21)) {
6807 /* write back */
6808 if (insn & (1 << 23)) {
6809 if (insn & (1 << 24)) {
6810 /* pre increment */
6811 } else {
6812 /* post increment */
6813 crement = 4;
6815 } else {
6816 if (insn & (1 << 24)) {
6817 /* pre decrement */
6818 if (n != 1) {
6819 crement = -((n - 1) * 4);
6821 } else {
6822 /* post decrement */
6823 crement = -(n * 4);
6826 if (arm_feature(env, ARM_FEATURE_ABORT_BU)) {
6827 /* base-updated abort model: update base register
6828 before an abort can happen */
6829 crement += (n - 1) * 4;
6830 tmp = new_tmp();
6831 tcg_gen_addi_i32(tmp, addr, crement);
6832 store_reg(s, rn, tmp);
6837 j = 0;
6838 for(i=0;i<16;i++) {
6839 if (insn & (1 << i)) {
6840 if (insn & (1 << 20)) {
6841 /* load */
6842 tmp = gen_ld32(addr, IS_USER(s));
6843 if (i == 15) {
6844 if (ENABLE_ARCH_5) {
6845 gen_bx(s, tmp);
6846 } else {
6847 store_reg(s, i, tmp);
6849 } else if (user) {
6850 gen_helper_set_user_reg(tcg_const_i32(i), tmp);
6851 dead_tmp(tmp);
6852 } else if (i == rn) {
6853 loaded_var = tmp;
6854 loaded_base = 1;
6855 } else {
6856 store_reg(s, i, tmp);
6858 } else {
6859 /* store */
6860 if (i == 15) {
6861 /* special case: r15 = PC + 8 */
6862 val = (long)s->pc + 4;
6863 tmp = new_tmp();
6864 tcg_gen_movi_i32(tmp, val);
6865 } else if (user) {
6866 tmp = new_tmp();
6867 gen_helper_get_user_reg(tmp, tcg_const_i32(i));
6868 } else {
6869 tmp = load_reg(s, i);
6871 gen_st32(tmp, addr, IS_USER(s));
6873 j++;
6874 /* no need to add after the last transfer */
6875 if (j != n)
6876 tcg_gen_addi_i32(addr, addr, 4);
6879 if (!arm_feature(env, ARM_FEATURE_ABORT_BU) && (insn & (1 << 21))) {
6880 tcg_gen_addi_i32(addr, addr, crement);
6881 store_reg(s, rn, addr);
6882 } else {
6883 dead_tmp(addr);
6885 if (loaded_base) {
6886 store_reg(s, rn, loaded_var);
6888 if ((insn & (1 << 22)) && !user) {
6889 /* Restore CPSR from SPSR. */
6890 tmp = load_cpu_field(spsr);
6891 gen_set_cpsr(tmp, 0xffffffff);
6892 dead_tmp(tmp);
6893 s->is_jmp = DISAS_UPDATE;
6896 break;
6897 case 0xa:
6898 case 0xb:
6900 int32_t offset;
6902 /* branch (and link) */
6903 val = (int32_t)s->pc;
6904 if (insn & (1 << 24)) {
6905 tmp = new_tmp();
6906 tcg_gen_movi_i32(tmp, val);
6907 store_reg(s, 14, tmp);
6909 offset = (((int32_t)insn << 8) >> 8);
6910 val += (offset << 2) + 4;
6911 gen_jmp(s, val);
6913 break;
6914 case 0xc:
6915 case 0xd:
6916 case 0xe:
6917 /* Coprocessor. */
6918 if (disas_coproc_insn(env, s, insn))
6919 goto illegal_op;
6920 break;
6921 case 0xf:
6922 /* swi */
6923 gen_set_pc_im(s->pc);
6924 s->is_jmp = DISAS_SWI;
6925 break;
6926 default:
6927 illegal_op:
6928 gen_set_condexec(s);
6929 gen_set_pc_im(s->pc - 4);
6930 gen_exception(EXCP_UDEF);
6931 s->is_jmp = DISAS_JUMP;
6932 break;
6937 /* Return true if this is a Thumb-2 logical op. */
6938 static int
6939 thumb2_logic_op(int op)
6941 return (op < 8);
6944 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
6945 then set condition code flags based on the result of the operation.
6946 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
6947 to the high bit of T1.
6948 Returns zero if the opcode is valid. */
6950 static int
6951 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCGv t0, TCGv t1)
6953 int logic_cc;
6955 logic_cc = 0;
6956 switch (op) {
6957 case 0: /* and */
6958 tcg_gen_and_i32(t0, t0, t1);
6959 logic_cc = conds;
6960 break;
6961 case 1: /* bic */
6962 tcg_gen_bic_i32(t0, t0, t1);
6963 logic_cc = conds;
6964 break;
6965 case 2: /* orr */
6966 tcg_gen_or_i32(t0, t0, t1);
6967 logic_cc = conds;
6968 break;
6969 case 3: /* orn */
6970 tcg_gen_not_i32(t1, t1);
6971 tcg_gen_or_i32(t0, t0, t1);
6972 logic_cc = conds;
6973 break;
6974 case 4: /* eor */
6975 tcg_gen_xor_i32(t0, t0, t1);
6976 logic_cc = conds;
6977 break;
6978 case 8: /* add */
6979 if (conds)
6980 gen_helper_add_cc(t0, t0, t1);
6981 else
6982 tcg_gen_add_i32(t0, t0, t1);
6983 break;
6984 case 10: /* adc */
6985 if (conds)
6986 gen_helper_adc_cc(t0, t0, t1);
6987 else
6988 gen_add_carry(t0, t0, t1);
6989 break;
6990 case 11: /* sbc */
6991 if (conds)
6992 gen_helper_sbc_cc(t0, t0, t1);
6993 else
6994 gen_sub_carry(t0, t0, t1);
6995 break;
6996 case 13: /* sub */
6997 if (conds)
6998 gen_helper_sub_cc(t0, t0, t1);
6999 else
7000 tcg_gen_sub_i32(t0, t0, t1);
7001 break;
7002 case 14: /* rsb */
7003 if (conds)
7004 gen_helper_sub_cc(t0, t1, t0);
7005 else
7006 tcg_gen_sub_i32(t0, t1, t0);
7007 break;
7008 default: /* 5, 6, 7, 9, 12, 15. */
7009 return 1;
7011 if (logic_cc) {
7012 gen_logic_CC(t0);
7013 if (shifter_out)
7014 gen_set_CF_bit31(t1);
7016 return 0;
7019 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7020 is not legal. */
7021 static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7023 uint32_t insn, imm, shift, offset;
7024 uint32_t rd, rn, rm, rs;
7025 TCGv tmp;
7026 TCGv tmp2;
7027 TCGv tmp3;
7028 TCGv addr;
7029 TCGv_i64 tmp64;
7030 int op;
7031 int shiftop;
7032 int conds;
7033 int logic_cc;
7035 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
7036 || arm_feature (env, ARM_FEATURE_M))) {
7037 /* Thumb-1 cores may need to treat bl and blx as a pair of
7038 16-bit instructions to get correct prefetch abort behavior. */
7039 insn = insn_hw1;
7040 if ((insn & (1 << 12)) == 0) {
7041 ARCH(5);
7042 /* Second half of blx. */
7043 offset = ((insn & 0x7ff) << 1);
7044 tmp = load_reg(s, 14);
7045 tcg_gen_addi_i32(tmp, tmp, offset);
7046 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
7048 tmp2 = new_tmp();
7049 tcg_gen_movi_i32(tmp2, s->pc | 1);
7050 store_reg(s, 14, tmp2);
7051 gen_bx(s, tmp);
7052 return 0;
7054 if (insn & (1 << 11)) {
7055 /* Second half of bl. */
7056 offset = ((insn & 0x7ff) << 1) | 1;
7057 tmp = load_reg(s, 14);
7058 tcg_gen_addi_i32(tmp, tmp, offset);
7060 tmp2 = new_tmp();
7061 tcg_gen_movi_i32(tmp2, s->pc | 1);
7062 store_reg(s, 14, tmp2);
7063 gen_bx(s, tmp);
7064 return 0;
7066 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
7067 /* Instruction spans a page boundary. Implement it as two
7068 16-bit instructions in case the second half causes an
7069 prefetch abort. */
7070 offset = ((int32_t)insn << 21) >> 9;
7071 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
7072 return 0;
7074 /* Fall through to 32-bit decode. */
7077 insn = lduw_code(s->pc);
7078 s->pc += 2;
7079 insn |= (uint32_t)insn_hw1 << 16;
7081 if ((insn & 0xf800e800) != 0xf000e800) {
7082 ARCH(6T2);
7085 rn = (insn >> 16) & 0xf;
7086 rs = (insn >> 12) & 0xf;
7087 rd = (insn >> 8) & 0xf;
7088 rm = insn & 0xf;
7089 switch ((insn >> 25) & 0xf) {
7090 case 0: case 1: case 2: case 3:
7091 /* 16-bit instructions. Should never happen. */
7092 abort();
7093 case 4:
7094 if (insn & (1 << 22)) {
7095 /* Other load/store, table branch. */
7096 if (insn & 0x01200000) {
7097 /* Load/store doubleword. */
7098 ARCH(5);
7099 if (rn == 15) {
7100 addr = new_tmp();
7101 tcg_gen_movi_i32(addr, s->pc & ~3);
7102 } else {
7103 addr = load_reg(s, rn);
7105 offset = (insn & 0xff) * 4;
7106 if ((insn & (1 << 23)) == 0)
7107 offset = -offset;
7108 if (insn & (1 << 24)) {
7109 tcg_gen_addi_i32(addr, addr, offset);
7110 offset = 0;
7112 if (insn & (1 << 20)) {
7113 /* ldrd */
7114 tmp = gen_ld32(addr, IS_USER(s));
7115 store_reg(s, rs, tmp);
7116 tcg_gen_addi_i32(addr, addr, 4);
7117 tmp = gen_ld32(addr, IS_USER(s));
7118 store_reg(s, rd, tmp);
7119 } else {
7120 /* strd */
7121 tmp = load_reg(s, rs);
7122 gen_st32(tmp, addr, IS_USER(s));
7123 tcg_gen_addi_i32(addr, addr, 4);
7124 tmp = load_reg(s, rd);
7125 gen_st32(tmp, addr, IS_USER(s));
7127 if (insn & (1 << 21)) {
7128 /* Base writeback. */
7129 if (rn == 15)
7130 goto illegal_op;
7131 tcg_gen_addi_i32(addr, addr, offset - 4);
7132 store_reg(s, rn, addr);
7133 } else {
7134 dead_tmp(addr);
7136 } else if ((insn & (1 << 23)) == 0) {
7137 /* Load/store exclusive word. */
7138 addr = tcg_temp_local_new();
7139 tcg_gen_mov_i32(addr, cpu_R[rn]);
7140 if (insn & (1 << 20)) {
7141 gen_helper_mark_exclusive(cpu_env, addr);
7142 tmp = gen_ld32(addr, IS_USER(s));
7143 store_reg(s, rd, tmp);
7144 } else {
7145 int label = gen_new_label();
7146 tmp2 = tcg_temp_local_new();
7147 gen_helper_test_exclusive(tmp2, cpu_env, addr);
7148 tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label);
7149 tmp = load_reg(s, rs);
7150 gen_st32(tmp, addr, IS_USER(s));
7151 gen_set_label(label);
7152 tcg_gen_mov_i32(cpu_R[rd], tmp2);
7153 tcg_temp_free(tmp2);
7155 tcg_temp_free(addr);
7156 } else if ((insn & (1 << 6)) == 0) {
7157 /* Table Branch. */
7158 if (rn == 15) {
7159 addr = new_tmp();
7160 tcg_gen_movi_i32(addr, s->pc);
7161 } else {
7162 addr = load_reg(s, rn);
7164 tmp = load_reg(s, rm);
7165 tcg_gen_add_i32(addr, addr, tmp);
7166 if (insn & (1 << 4)) {
7167 /* tbh */
7168 tcg_gen_add_i32(addr, addr, tmp);
7169 dead_tmp(tmp);
7170 tmp = gen_ld16u(addr, IS_USER(s));
7171 } else { /* tbb */
7172 dead_tmp(tmp);
7173 tmp = gen_ld8u(addr, IS_USER(s));
7175 dead_tmp(addr);
7176 tcg_gen_shli_i32(tmp, tmp, 1);
7177 tcg_gen_addi_i32(tmp, tmp, s->pc);
7178 store_reg(s, 15, tmp);
7179 } else {
7180 /* Load/store exclusive byte/halfword/doubleword. */
7181 /* ??? These are not really atomic. However we know
7182 we never have multiple CPUs running in parallel,
7183 so it is good enough. */
7184 op = (insn >> 4) & 0x3;
7185 addr = tcg_temp_local_new();
7186 tcg_gen_mov_i32(addr, cpu_R[rn]);
7187 if (insn & (1 << 20)) {
7188 gen_helper_mark_exclusive(cpu_env, addr);
7189 switch (op) {
7190 case 0:
7191 tmp = gen_ld8u(addr, IS_USER(s));
7192 break;
7193 case 1:
7194 tmp = gen_ld16u(addr, IS_USER(s));
7195 break;
7196 case 3:
7197 tmp = gen_ld32(addr, IS_USER(s));
7198 tcg_gen_addi_i32(addr, addr, 4);
7199 tmp2 = gen_ld32(addr, IS_USER(s));
7200 store_reg(s, rd, tmp2);
7201 break;
7202 default:
7203 goto illegal_op;
7205 store_reg(s, rs, tmp);
7206 } else {
7207 int label = gen_new_label();
7208 tmp2 = tcg_temp_local_new();
7209 gen_helper_test_exclusive(tmp2, cpu_env, addr);
7210 tcg_gen_brcondi_i32(TCG_COND_NE, tmp2, 0, label);
7211 tmp = load_reg(s, rs);
7212 switch (op) {
7213 case 0:
7214 gen_st8(tmp, addr, IS_USER(s));
7215 break;
7216 case 1:
7217 gen_st16(tmp, addr, IS_USER(s));
7218 break;
7219 case 3:
7220 gen_st32(tmp, addr, IS_USER(s));
7221 tcg_gen_addi_i32(addr, addr, 4);
7222 tmp = load_reg(s, rd);
7223 gen_st32(tmp, addr, IS_USER(s));
7224 break;
7225 default:
7226 goto illegal_op;
7228 gen_set_label(label);
7229 tcg_gen_mov_i32(cpu_R[rm], tmp2);
7230 tcg_temp_free(tmp2);
7232 tcg_temp_free(addr);
7234 } else {
7235 /* Load/store multiple, RFE, SRS. */
7236 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
7237 /* Not available in user mode. */
7238 if (IS_USER(s))
7239 goto illegal_op;
7240 if (insn & (1 << 20)) {
7241 /* rfe */
7242 addr = load_reg(s, rn);
7243 if ((insn & (1 << 24)) == 0)
7244 tcg_gen_addi_i32(addr, addr, -8);
7245 /* Load PC into tmp and CPSR into tmp2. */
7246 tmp = gen_ld32(addr, 0);
7247 tcg_gen_addi_i32(addr, addr, 4);
7248 tmp2 = gen_ld32(addr, 0);
7249 if (insn & (1 << 21)) {
7250 /* Base writeback. */
7251 if (insn & (1 << 24)) {
7252 tcg_gen_addi_i32(addr, addr, 4);
7253 } else {
7254 tcg_gen_addi_i32(addr, addr, -4);
7256 store_reg(s, rn, addr);
7257 } else {
7258 dead_tmp(addr);
7260 gen_rfe(s, tmp, tmp2);
7261 } else {
7262 /* srs */
7263 op = (insn & 0x1f);
7264 if (op == (env->uncached_cpsr & CPSR_M)) {
7265 addr = load_reg(s, 13);
7266 } else {
7267 addr = new_tmp();
7268 gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op));
7270 if ((insn & (1 << 24)) == 0) {
7271 tcg_gen_addi_i32(addr, addr, -8);
7273 tmp = load_reg(s, 14);
7274 gen_st32(tmp, addr, 0);
7275 tcg_gen_addi_i32(addr, addr, 4);
7276 tmp = new_tmp();
7277 gen_helper_cpsr_read(tmp);
7278 gen_st32(tmp, addr, 0);
7279 if (insn & (1 << 21)) {
7280 if ((insn & (1 << 24)) == 0) {
7281 tcg_gen_addi_i32(addr, addr, -4);
7282 } else {
7283 tcg_gen_addi_i32(addr, addr, 4);
7285 if (op == (env->uncached_cpsr & CPSR_M)) {
7286 store_reg(s, 13, addr);
7287 } else {
7288 gen_helper_set_r13_banked(cpu_env,
7289 tcg_const_i32(op), addr);
7291 } else {
7292 dead_tmp(addr);
7295 } else {
7296 int i;
7297 /* Load/store multiple. */
7298 addr = load_reg(s, rn);
7299 offset = 0;
7300 for (i = 0; i < 16; i++) {
7301 if (insn & (1 << i))
7302 offset += 4;
7304 if (insn & (1 << 24)) {
7305 tcg_gen_addi_i32(addr, addr, -offset);
7308 for (i = 0; i < 16; i++) {
7309 if ((insn & (1 << i)) == 0)
7310 continue;
7311 if (insn & (1 << 20)) {
7312 /* Load. */
7313 tmp = gen_ld32(addr, IS_USER(s));
7314 if (i == 15 && ENABLE_ARCH_5) {
7315 gen_bx(s, tmp);
7316 } else {
7317 store_reg(s, i, tmp);
7319 } else {
7320 /* Store. */
7321 tmp = load_reg(s, i);
7322 gen_st32(tmp, addr, IS_USER(s));
7324 tcg_gen_addi_i32(addr, addr, 4);
7326 if (insn & (1 << 21)) {
7327 /* Base register writeback. */
7328 if (insn & (1 << 24)) {
7329 tcg_gen_addi_i32(addr, addr, -offset);
7331 /* Fault if writeback register is in register list. */
7332 if (insn & (1 << rn))
7333 goto illegal_op;
7334 store_reg(s, rn, addr);
7335 } else {
7336 dead_tmp(addr);
7340 break;
7341 case 5: /* Data processing register constant shift. */
7342 if (rn == 15) {
7343 tmp = new_tmp();
7344 tcg_gen_movi_i32(tmp, 0);
7345 } else {
7346 tmp = load_reg(s, rn);
7348 tmp2 = load_reg(s, rm);
7349 op = (insn >> 21) & 0xf;
7350 shiftop = (insn >> 4) & 3;
7351 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7352 conds = (insn & (1 << 20)) != 0;
7353 logic_cc = (conds && thumb2_logic_op(op));
7354 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
7355 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
7356 goto illegal_op;
7357 dead_tmp(tmp2);
7358 if (rd != 15) {
7359 store_reg(s, rd, tmp);
7360 } else {
7361 dead_tmp(tmp);
7363 break;
7364 case 13: /* Misc data processing. */
7365 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
7366 if (op < 4 && (insn & 0xf000) != 0xf000)
7367 goto illegal_op;
7368 switch (op) {
7369 case 0: /* Register controlled shift. */
7370 tmp = load_reg(s, rn);
7371 tmp2 = load_reg(s, rm);
7372 if ((insn & 0x70) != 0)
7373 goto illegal_op;
7374 op = (insn >> 21) & 3;
7375 logic_cc = (insn & (1 << 20)) != 0;
7376 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
7377 if (logic_cc)
7378 gen_logic_CC(tmp);
7379 store_reg_bx(env, s, rd, tmp);
7380 break;
7381 case 1: /* Sign/zero extend. */
7382 tmp = load_reg(s, rm);
7383 shift = (insn >> 4) & 3;
7384 /* ??? In many cases it's not neccessary to do a
7385 rotate, a shift is sufficient. */
7386 if (shift != 0)
7387 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
7388 op = (insn >> 20) & 7;
7389 switch (op) {
7390 case 0: gen_sxth(tmp); break;
7391 case 1: gen_uxth(tmp); break;
7392 case 2: gen_sxtb16(tmp); break;
7393 case 3: gen_uxtb16(tmp); break;
7394 case 4: gen_sxtb(tmp); break;
7395 case 5: gen_uxtb(tmp); break;
7396 default: goto illegal_op;
7398 if (rn != 15) {
7399 tmp2 = load_reg(s, rn);
7400 if ((op >> 1) == 1) {
7401 gen_add16(tmp, tmp2);
7402 } else {
7403 tcg_gen_add_i32(tmp, tmp, tmp2);
7404 dead_tmp(tmp2);
7407 store_reg(s, rd, tmp);
7408 break;
7409 case 2: /* SIMD add/subtract. */
7410 op = (insn >> 20) & 7;
7411 shift = (insn >> 4) & 7;
7412 if ((op & 3) == 3 || (shift & 3) == 3)
7413 goto illegal_op;
7414 tmp = load_reg(s, rn);
7415 tmp2 = load_reg(s, rm);
7416 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7417 dead_tmp(tmp2);
7418 store_reg(s, rd, tmp);
7419 break;
7420 case 3: /* Other data processing. */
7421 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
7422 if (op < 4) {
7423 /* Saturating add/subtract. */
7424 tmp = load_reg(s, rn);
7425 tmp2 = load_reg(s, rm);
7426 if (op & 2)
7427 gen_helper_double_saturate(tmp, tmp);
7428 if (op & 1)
7429 gen_helper_sub_saturate(tmp, tmp2, tmp);
7430 else
7431 gen_helper_add_saturate(tmp, tmp, tmp2);
7432 dead_tmp(tmp2);
7433 } else {
7434 tmp = load_reg(s, rn);
7435 switch (op) {
7436 case 0x0a: /* rbit */
7437 gen_helper_rbit(tmp, tmp);
7438 break;
7439 case 0x08: /* rev */
7440 tcg_gen_bswap32_i32(tmp, tmp);
7441 break;
7442 case 0x09: /* rev16 */
7443 gen_rev16(tmp);
7444 break;
7445 case 0x0b: /* revsh */
7446 gen_revsh(tmp);
7447 break;
7448 case 0x10: /* sel */
7449 tmp2 = load_reg(s, rm);
7450 tmp3 = new_tmp();
7451 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
7452 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7453 dead_tmp(tmp3);
7454 dead_tmp(tmp2);
7455 break;
7456 case 0x18: /* clz */
7457 gen_helper_clz(tmp, tmp);
7458 break;
7459 default:
7460 goto illegal_op;
7463 store_reg(s, rd, tmp);
7464 break;
7465 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7466 op = (insn >> 4) & 0xf;
7467 tmp = load_reg(s, rn);
7468 tmp2 = load_reg(s, rm);
7469 switch ((insn >> 20) & 7) {
7470 case 0: /* 32 x 32 -> 32 */
7471 tcg_gen_mul_i32(tmp, tmp, tmp2);
7472 dead_tmp(tmp2);
7473 if (rs != 15) {
7474 tmp2 = load_reg(s, rs);
7475 if (op)
7476 tcg_gen_sub_i32(tmp, tmp2, tmp);
7477 else
7478 tcg_gen_add_i32(tmp, tmp, tmp2);
7479 dead_tmp(tmp2);
7481 break;
7482 case 1: /* 16 x 16 -> 32 */
7483 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7484 dead_tmp(tmp2);
7485 if (rs != 15) {
7486 tmp2 = load_reg(s, rs);
7487 gen_helper_add_setq(tmp, tmp, tmp2);
7488 dead_tmp(tmp2);
7490 break;
7491 case 2: /* Dual multiply add. */
7492 case 4: /* Dual multiply subtract. */
7493 if (op)
7494 gen_swap_half(tmp2);
7495 gen_smul_dual(tmp, tmp2);
7496 /* This addition cannot overflow. */
7497 if (insn & (1 << 22)) {
7498 tcg_gen_sub_i32(tmp, tmp, tmp2);
7499 } else {
7500 tcg_gen_add_i32(tmp, tmp, tmp2);
7502 dead_tmp(tmp2);
7503 if (rs != 15)
7505 tmp2 = load_reg(s, rs);
7506 gen_helper_add_setq(tmp, tmp, tmp2);
7507 dead_tmp(tmp2);
7509 break;
7510 case 3: /* 32 * 16 -> 32msb */
7511 if (op)
7512 tcg_gen_sari_i32(tmp2, tmp2, 16);
7513 else
7514 gen_sxth(tmp2);
7515 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7516 tcg_gen_shri_i64(tmp64, tmp64, 16);
7517 tmp = new_tmp();
7518 tcg_gen_trunc_i64_i32(tmp, tmp64);
7519 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 5: case 6: /* 32 * 32 -> 32msb */
7527 gen_imull(tmp, tmp2);
7528 if (insn & (1 << 5)) {
7529 gen_roundqd(tmp, tmp2);
7530 dead_tmp(tmp2);
7531 } else {
7532 dead_tmp(tmp);
7533 tmp = tmp2;
7535 if (rs != 15) {
7536 tmp2 = load_reg(s, rs);
7537 if (insn & (1 << 21)) {
7538 tcg_gen_add_i32(tmp, tmp, tmp2);
7539 } else {
7540 tcg_gen_sub_i32(tmp, tmp2, tmp);
7542 dead_tmp(tmp2);
7544 break;
7545 case 7: /* Unsigned sum of absolute differences. */
7546 gen_helper_usad8(tmp, tmp, tmp2);
7547 dead_tmp(tmp2);
7548 if (rs != 15) {
7549 tmp2 = load_reg(s, rs);
7550 tcg_gen_add_i32(tmp, tmp, tmp2);
7551 dead_tmp(tmp2);
7553 break;
7555 store_reg(s, rd, tmp);
7556 break;
7557 case 6: case 7: /* 64-bit multiply, Divide. */
7558 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
7559 tmp = load_reg(s, rn);
7560 tmp2 = load_reg(s, rm);
7561 if ((op & 0x50) == 0x10) {
7562 /* sdiv, udiv */
7563 if (!arm_feature(env, ARM_FEATURE_DIV))
7564 goto illegal_op;
7565 if (op & 0x20)
7566 gen_helper_udiv(tmp, tmp, tmp2);
7567 else
7568 gen_helper_sdiv(tmp, tmp, tmp2);
7569 dead_tmp(tmp2);
7570 store_reg(s, rd, tmp);
7571 } else if ((op & 0xe) == 0xc) {
7572 /* Dual multiply accumulate long. */
7573 if (op & 1)
7574 gen_swap_half(tmp2);
7575 gen_smul_dual(tmp, tmp2);
7576 if (op & 0x10) {
7577 tcg_gen_sub_i32(tmp, tmp, tmp2);
7578 } else {
7579 tcg_gen_add_i32(tmp, tmp, tmp2);
7581 dead_tmp(tmp2);
7582 /* BUGFIX */
7583 tmp64 = tcg_temp_new_i64();
7584 tcg_gen_ext_i32_i64(tmp64, tmp);
7585 dead_tmp(tmp);
7586 gen_addq(s, tmp64, rs, rd);
7587 gen_storeq_reg(s, rs, rd, tmp64);
7588 } else {
7589 if (op & 0x20) {
7590 /* Unsigned 64-bit multiply */
7591 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7592 } else {
7593 if (op & 8) {
7594 /* smlalxy */
7595 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7596 dead_tmp(tmp2);
7597 tmp64 = tcg_temp_new_i64();
7598 tcg_gen_ext_i32_i64(tmp64, tmp);
7599 dead_tmp(tmp);
7600 } else {
7601 /* Signed 64-bit multiply */
7602 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7605 if (op & 4) {
7606 /* umaal */
7607 gen_addq_lo(s, tmp64, rs);
7608 gen_addq_lo(s, tmp64, rd);
7609 } else if (op & 0x40) {
7610 /* 64-bit accumulate. */
7611 gen_addq(s, tmp64, rs, rd);
7613 gen_storeq_reg(s, rs, rd, tmp64);
7615 break;
7617 break;
7618 case 6: case 7: case 14: case 15:
7619 /* Coprocessor. */
7620 if (((insn >> 24) & 3) == 3) {
7621 /* Translate into the equivalent ARM encoding. */
7622 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4);
7623 if (disas_neon_data_insn(env, s, insn))
7624 goto illegal_op;
7625 } else {
7626 if (insn & (1 << 28))
7627 goto illegal_op;
7628 if (disas_coproc_insn (env, s, insn))
7629 goto illegal_op;
7631 break;
7632 case 8: case 9: case 10: case 11:
7633 if (insn & (1 << 15)) {
7634 /* Branches, misc control. */
7635 if (insn & 0x5000) {
7636 /* Unconditional branch. */
7637 /* signextend(hw1[10:0]) -> offset[:12]. */
7638 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
7639 /* hw1[10:0] -> offset[11:1]. */
7640 offset |= (insn & 0x7ff) << 1;
7641 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7642 offset[24:22] already have the same value because of the
7643 sign extension above. */
7644 offset ^= ((~insn) & (1 << 13)) << 10;
7645 offset ^= ((~insn) & (1 << 11)) << 11;
7647 if (insn & (1 << 14)) {
7648 /* Branch and link. */
7649 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
7652 offset += s->pc;
7653 if (insn & (1 << 12)) {
7654 /* b/bl */
7655 gen_jmp(s, offset);
7656 } else {
7657 /* blx */
7658 ARCH(5);
7659 offset &= ~(uint32_t)2;
7660 gen_bx_im(s, offset);
7662 } else if (((insn >> 23) & 7) == 7) {
7663 /* Misc control */
7664 if (insn & (1 << 13))
7665 goto illegal_op;
7667 if (insn & (1 << 26)) {
7668 /* Secure monitor call (v6Z) */
7669 goto illegal_op; /* not implemented. */
7670 } else {
7671 op = (insn >> 20) & 7;
7672 switch (op) {
7673 case 0: /* msr cpsr. */
7674 if (IS_M(env)) {
7675 tmp = load_reg(s, rn);
7676 addr = tcg_const_i32(insn & 0xff);
7677 gen_helper_v7m_msr(cpu_env, addr, tmp);
7678 gen_lookup_tb(s);
7679 break;
7681 /* fall through */
7682 case 1: /* msr spsr. */
7683 if (IS_M(env))
7684 goto illegal_op;
7685 tmp = load_reg(s, rn);
7686 if (gen_set_psr(s,
7687 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
7688 op == 1, tmp))
7689 goto illegal_op;
7690 break;
7691 case 2: /* cps, nop-hint. */
7692 if (((insn >> 8) & 7) == 0) {
7693 gen_nop_hint(s, insn & 0xff);
7695 /* Implemented as NOP in user mode. */
7696 if (IS_USER(s))
7697 break;
7698 offset = 0;
7699 imm = 0;
7700 if (insn & (1 << 10)) {
7701 if (insn & (1 << 7))
7702 offset |= CPSR_A;
7703 if (insn & (1 << 6))
7704 offset |= CPSR_I;
7705 if (insn & (1 << 5))
7706 offset |= CPSR_F;
7707 if (insn & (1 << 9))
7708 imm = CPSR_A | CPSR_I | CPSR_F;
7710 if (insn & (1 << 8)) {
7711 offset |= 0x1f;
7712 imm |= (insn & 0x1f);
7714 if (offset) {
7715 gen_set_psr_im(s, offset, 0, imm);
7717 break;
7718 case 3: /* Special control operations. */
7719 op = (insn >> 4) & 0xf;
7720 switch (op) {
7721 case 2: /* clrex */
7722 gen_helper_clrex(cpu_env);
7723 break;
7724 case 4: /* dsb */
7725 case 5: /* dmb */
7726 case 6: /* isb */
7727 /* These execute as NOPs. */
7728 ARCH(7);
7729 break;
7730 default:
7731 goto illegal_op;
7733 break;
7734 case 4: /* bxj */
7735 /* Trivial implementation equivalent to bx. */
7736 tmp = load_reg(s, rn);
7737 gen_bx(s, tmp);
7738 break;
7739 case 5: /* Exception return. */
7740 /* Unpredictable in user mode. */
7741 goto illegal_op;
7742 case 6: /* mrs cpsr. */
7743 tmp = new_tmp();
7744 if (IS_M(env)) {
7745 addr = tcg_const_i32(insn & 0xff);
7746 gen_helper_v7m_mrs(tmp, cpu_env, addr);
7747 } else {
7748 gen_helper_cpsr_read(tmp);
7750 store_reg(s, rd, tmp);
7751 break;
7752 case 7: /* mrs spsr. */
7753 /* Not accessible in user mode. */
7754 if (IS_USER(s) || IS_M(env))
7755 goto illegal_op;
7756 tmp = load_cpu_field(spsr);
7757 store_reg(s, rd, tmp);
7758 break;
7761 } else {
7762 /* Conditional branch. */
7763 op = (insn >> 22) & 0xf;
7764 /* Generate a conditional jump to next instruction. */
7765 s->condlabel = gen_new_label();
7766 gen_test_cc(op ^ 1, s->condlabel);
7767 s->condjmp = 1;
7769 /* offset[11:1] = insn[10:0] */
7770 offset = (insn & 0x7ff) << 1;
7771 /* offset[17:12] = insn[21:16]. */
7772 offset |= (insn & 0x003f0000) >> 4;
7773 /* offset[31:20] = insn[26]. */
7774 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
7775 /* offset[18] = insn[13]. */
7776 offset |= (insn & (1 << 13)) << 5;
7777 /* offset[19] = insn[11]. */
7778 offset |= (insn & (1 << 11)) << 8;
7780 /* jump to the offset */
7781 gen_jmp(s, s->pc + offset);
7783 } else {
7784 /* Data processing immediate. */
7785 if (insn & (1 << 25)) {
7786 if (insn & (1 << 24)) {
7787 if (insn & (1 << 20))
7788 goto illegal_op;
7789 /* Bitfield/Saturate. */
7790 op = (insn >> 21) & 7;
7791 imm = insn & 0x1f;
7792 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7793 if (rn == 15) {
7794 tmp = new_tmp();
7795 tcg_gen_movi_i32(tmp, 0);
7796 } else {
7797 tmp = load_reg(s, rn);
7799 switch (op) {
7800 case 2: /* Signed bitfield extract. */
7801 imm++;
7802 if (shift + imm > 32)
7803 goto illegal_op;
7804 if (imm < 32)
7805 gen_sbfx(tmp, shift, imm);
7806 break;
7807 case 6: /* Unsigned bitfield extract. */
7808 imm++;
7809 if (shift + imm > 32)
7810 goto illegal_op;
7811 if (imm < 32)
7812 gen_ubfx(tmp, shift, (1u << imm) - 1);
7813 break;
7814 case 3: /* Bitfield insert/clear. */
7815 if (imm < shift)
7816 goto illegal_op;
7817 imm = imm + 1 - shift;
7818 if (imm != 32) {
7819 tmp2 = load_reg(s, rd);
7820 gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
7821 dead_tmp(tmp2);
7823 break;
7824 case 7:
7825 goto illegal_op;
7826 default: /* Saturate. */
7827 if (shift) {
7828 if (op & 1)
7829 tcg_gen_sari_i32(tmp, tmp, shift);
7830 else
7831 tcg_gen_shli_i32(tmp, tmp, shift);
7833 tmp2 = tcg_const_i32(imm);
7834 if (op & 4) {
7835 /* Unsigned. */
7836 if ((op & 1) && shift == 0)
7837 gen_helper_usat16(tmp, tmp, tmp2);
7838 else
7839 gen_helper_usat(tmp, tmp, tmp2);
7840 } else {
7841 /* Signed. */
7842 if ((op & 1) && shift == 0)
7843 gen_helper_ssat16(tmp, tmp, tmp2);
7844 else
7845 gen_helper_ssat(tmp, tmp, tmp2);
7847 break;
7849 store_reg(s, rd, tmp);
7850 } else {
7851 imm = ((insn & 0x04000000) >> 15)
7852 | ((insn & 0x7000) >> 4) | (insn & 0xff);
7853 if (insn & (1 << 22)) {
7854 /* 16-bit immediate. */
7855 imm |= (insn >> 4) & 0xf000;
7856 if (insn & (1 << 23)) {
7857 /* movt */
7858 tmp = load_reg(s, rd);
7859 tcg_gen_ext16u_i32(tmp, tmp);
7860 tcg_gen_ori_i32(tmp, tmp, imm << 16);
7861 } else {
7862 /* movw */
7863 tmp = new_tmp();
7864 tcg_gen_movi_i32(tmp, imm);
7866 } else {
7867 /* Add/sub 12-bit immediate. */
7868 if (rn == 15) {
7869 offset = s->pc & ~(uint32_t)3;
7870 if (insn & (1 << 23))
7871 offset -= imm;
7872 else
7873 offset += imm;
7874 tmp = new_tmp();
7875 tcg_gen_movi_i32(tmp, offset);
7876 } else {
7877 tmp = load_reg(s, rn);
7878 if (insn & (1 << 23))
7879 tcg_gen_subi_i32(tmp, tmp, imm);
7880 else
7881 tcg_gen_addi_i32(tmp, tmp, imm);
7884 store_reg(s, rd, tmp);
7886 } else {
7887 int shifter_out = 0;
7888 /* modified 12-bit immediate. */
7889 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
7890 imm = (insn & 0xff);
7891 switch (shift) {
7892 case 0: /* XY */
7893 /* Nothing to do. */
7894 break;
7895 case 1: /* 00XY00XY */
7896 imm |= imm << 16;
7897 break;
7898 case 2: /* XY00XY00 */
7899 imm |= imm << 16;
7900 imm <<= 8;
7901 break;
7902 case 3: /* XYXYXYXY */
7903 imm |= imm << 16;
7904 imm |= imm << 8;
7905 break;
7906 default: /* Rotated constant. */
7907 shift = (shift << 1) | (imm >> 7);
7908 imm |= 0x80;
7909 imm = imm << (32 - shift);
7910 shifter_out = 1;
7911 break;
7913 tmp2 = new_tmp();
7914 tcg_gen_movi_i32(tmp2, imm);
7915 rn = (insn >> 16) & 0xf;
7916 if (rn == 15) {
7917 tmp = new_tmp();
7918 tcg_gen_movi_i32(tmp, 0);
7919 } else {
7920 tmp = load_reg(s, rn);
7922 op = (insn >> 21) & 0xf;
7923 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
7924 shifter_out, tmp, tmp2))
7925 goto illegal_op;
7926 dead_tmp(tmp2);
7927 rd = (insn >> 8) & 0xf;
7928 if (rd != 15) {
7929 store_reg(s, rd, tmp);
7930 } else {
7931 dead_tmp(tmp);
7935 break;
7936 case 12: /* Load/store single data item. */
7938 int postinc = 0;
7939 int writeback = 0;
7940 int user;
7941 if ((insn & 0x01100000) == 0x01000000) {
7942 if (disas_neon_ls_insn(env, s, insn))
7943 goto illegal_op;
7944 break;
7946 user = IS_USER(s);
7947 if (rn == 15) {
7948 addr = new_tmp();
7949 /* PC relative. */
7950 /* s->pc has already been incremented by 4. */
7951 imm = s->pc & 0xfffffffc;
7952 if (insn & (1 << 23))
7953 imm += insn & 0xfff;
7954 else
7955 imm -= insn & 0xfff;
7956 tcg_gen_movi_i32(addr, imm);
7957 } else {
7958 addr = load_reg(s, rn);
7959 if (insn & (1 << 23)) {
7960 /* Positive offset. */
7961 imm = insn & 0xfff;
7962 tcg_gen_addi_i32(addr, addr, imm);
7963 } else {
7964 op = (insn >> 8) & 7;
7965 imm = insn & 0xff;
7966 switch (op) {
7967 case 0: case 8: /* Shifted Register. */
7968 shift = (insn >> 4) & 0xf;
7969 if (shift > 3)
7970 goto illegal_op;
7971 tmp = load_reg(s, rm);
7972 if (shift)
7973 tcg_gen_shli_i32(tmp, tmp, shift);
7974 tcg_gen_add_i32(addr, addr, tmp);
7975 dead_tmp(tmp);
7976 break;
7977 case 4: /* Negative offset. */
7978 tcg_gen_addi_i32(addr, addr, -imm);
7979 break;
7980 case 6: /* User privilege. */
7981 tcg_gen_addi_i32(addr, addr, imm);
7982 user = 1;
7983 break;
7984 case 1: /* Post-decrement. */
7985 imm = -imm;
7986 /* Fall through. */
7987 case 3: /* Post-increment. */
7988 postinc = 1;
7989 writeback = 1;
7990 break;
7991 case 5: /* Pre-decrement. */
7992 imm = -imm;
7993 /* Fall through. */
7994 case 7: /* Pre-increment. */
7995 tcg_gen_addi_i32(addr, addr, imm);
7996 writeback = 1;
7997 break;
7998 default:
7999 goto illegal_op;
8003 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
8004 if (insn & (1 << 20)) {
8005 /* Load. */
8006 if (rs == 15 && op != 2) {
8007 if (op & 2)
8008 goto illegal_op;
8009 /* Memory hint. Implemented as NOP. */
8010 } else {
8011 switch (op) {
8012 case 0: tmp = gen_ld8u(addr, user); break;
8013 case 4: tmp = gen_ld8s(addr, user); break;
8014 case 1: tmp = gen_ld16u(addr, user); break;
8015 case 5: tmp = gen_ld16s(addr, user); break;
8016 case 2: tmp = gen_ld32(addr, user); break;
8017 default: goto illegal_op;
8019 if (rs == 15 && ENABLE_ARCH_5) {
8020 gen_bx(s, tmp);
8021 } else {
8022 store_reg(s, rs, tmp);
8025 } else {
8026 /* Store. */
8027 if (rs == 15)
8028 goto illegal_op;
8029 tmp = load_reg(s, rs);
8030 switch (op) {
8031 case 0: gen_st8(tmp, addr, user); break;
8032 case 1: gen_st16(tmp, addr, user); break;
8033 case 2: gen_st32(tmp, addr, user); break;
8034 default: goto illegal_op;
8037 if (postinc)
8038 tcg_gen_addi_i32(addr, addr, imm);
8039 if (writeback) {
8040 store_reg(s, rn, addr);
8041 } else {
8042 dead_tmp(addr);
8045 break;
8046 default:
8047 goto illegal_op;
8049 return 0;
8050 illegal_op:
8051 return 1;
8054 static void disas_thumb_insn(CPUState *env, DisasContext *s)
8056 uint32_t val, insn, op, rm, rn, rd, shift, cond;
8057 int32_t offset;
8058 int i;
8059 TCGv tmp;
8060 TCGv tmp2;
8061 TCGv addr;
8062 int crement;
8064 if (s->condexec_mask) {
8065 cond = s->condexec_cond;
8066 s->condlabel = gen_new_label();
8067 gen_test_cc(cond ^ 1, s->condlabel);
8068 s->condjmp = 1;
8071 insn = lduw_code(s->pc);
8072 s->pc += 2;
8074 switch (insn >> 12) {
8075 case 0: case 1:
8077 rd = insn & 7;
8078 op = (insn >> 11) & 3;
8079 if (op == 3) {
8080 /* add/subtract */
8081 rn = (insn >> 3) & 7;
8082 tmp = load_reg(s, rn);
8083 if (insn & (1 << 10)) {
8084 /* immediate */
8085 tmp2 = new_tmp();
8086 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
8087 } else {
8088 /* reg */
8089 rm = (insn >> 6) & 7;
8090 tmp2 = load_reg(s, rm);
8092 if (insn & (1 << 9)) {
8093 if (s->condexec_mask)
8094 tcg_gen_sub_i32(tmp, tmp, tmp2);
8095 else
8096 gen_helper_sub_cc(tmp, tmp, tmp2);
8097 } else {
8098 if (s->condexec_mask)
8099 tcg_gen_add_i32(tmp, tmp, tmp2);
8100 else
8101 gen_helper_add_cc(tmp, tmp, tmp2);
8103 dead_tmp(tmp2);
8104 store_reg(s, rd, tmp);
8105 } else {
8106 /* shift immediate */
8107 rm = (insn >> 3) & 7;
8108 shift = (insn >> 6) & 0x1f;
8109 tmp = load_reg(s, rm);
8110 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
8111 if (!s->condexec_mask)
8112 gen_logic_CC(tmp);
8113 store_reg(s, rd, tmp);
8115 break;
8116 case 2: case 3:
8117 /* arithmetic large immediate */
8118 op = (insn >> 11) & 3;
8119 rd = (insn >> 8) & 0x7;
8120 if (op == 0) { /* mov */
8121 tmp = new_tmp();
8122 tcg_gen_movi_i32(tmp, insn & 0xff);
8123 if (!s->condexec_mask)
8124 gen_logic_CC(tmp);
8125 store_reg(s, rd, tmp);
8126 } else {
8127 tmp = load_reg(s, rd);
8128 tmp2 = new_tmp();
8129 tcg_gen_movi_i32(tmp2, insn & 0xff);
8130 switch (op) {
8131 case 1: /* cmp */
8132 gen_helper_sub_cc(tmp, tmp, tmp2);
8133 dead_tmp(tmp);
8134 dead_tmp(tmp2);
8135 break;
8136 case 2: /* add */
8137 if (s->condexec_mask)
8138 tcg_gen_add_i32(tmp, tmp, tmp2);
8139 else
8140 gen_helper_add_cc(tmp, tmp, tmp2);
8141 dead_tmp(tmp2);
8142 store_reg(s, rd, tmp);
8143 break;
8144 case 3: /* sub */
8145 if (s->condexec_mask)
8146 tcg_gen_sub_i32(tmp, tmp, tmp2);
8147 else
8148 gen_helper_sub_cc(tmp, tmp, tmp2);
8149 dead_tmp(tmp2);
8150 store_reg(s, rd, tmp);
8151 break;
8154 break;
8155 case 4:
8156 if (insn & (1 << 11)) {
8157 rd = (insn >> 8) & 7;
8158 /* load pc-relative. Bit 1 of PC is ignored. */
8159 val = s->pc + 2 + ((insn & 0xff) * 4);
8160 val &= ~(uint32_t)2;
8161 addr = new_tmp();
8162 tcg_gen_movi_i32(addr, val);
8163 tmp = gen_ld32(addr, IS_USER(s));
8164 dead_tmp(addr);
8165 store_reg(s, rd, tmp);
8166 break;
8168 if (insn & (1 << 10)) {
8169 /* data processing extended or blx */
8170 rd = (insn & 7) | ((insn >> 4) & 8);
8171 rm = (insn >> 3) & 0xf;
8172 op = (insn >> 8) & 3;
8173 switch (op) {
8174 case 0: /* add */
8175 tmp = load_reg(s, rd);
8176 tmp2 = load_reg(s, rm);
8177 tcg_gen_add_i32(tmp, tmp, tmp2);
8178 dead_tmp(tmp2);
8179 store_reg(s, rd, tmp);
8180 break;
8181 case 1: /* cmp */
8182 tmp = load_reg(s, rd);
8183 tmp2 = load_reg(s, rm);
8184 gen_helper_sub_cc(tmp, tmp, tmp2);
8185 dead_tmp(tmp2);
8186 dead_tmp(tmp);
8187 break;
8188 case 2: /* mov/cpy */
8189 tmp = load_reg(s, rm);
8190 store_reg(s, rd, tmp);
8191 break;
8192 case 3:/* branch [and link] exchange thumb register */
8193 tmp = load_reg(s, rm);
8194 if (insn & (1 << 7)) {
8195 ARCH(5);
8196 val = (uint32_t)s->pc | 1;
8197 tmp2 = new_tmp();
8198 tcg_gen_movi_i32(tmp2, val);
8199 store_reg(s, 14, tmp2);
8201 gen_bx(s, tmp);
8202 break;
8204 break;
8207 /* data processing register */
8208 rd = insn & 7;
8209 rm = (insn >> 3) & 7;
8210 op = (insn >> 6) & 0xf;
8211 if (op == 2 || op == 3 || op == 4 || op == 7) {
8212 /* the shift/rotate ops want the operands backwards */
8213 val = rm;
8214 rm = rd;
8215 rd = val;
8216 val = 1;
8217 } else {
8218 val = 0;
8221 if (op == 9) { /* neg */
8222 tmp = new_tmp();
8223 tcg_gen_movi_i32(tmp, 0);
8224 } else if (op != 0xf) { /* mvn doesn't read its first operand */
8225 tmp = load_reg(s, rd);
8226 } else {
8227 TCGV_UNUSED(tmp);
8230 tmp2 = load_reg(s, rm);
8231 switch (op) {
8232 case 0x0: /* and */
8233 tcg_gen_and_i32(tmp, tmp, tmp2);
8234 if (!s->condexec_mask)
8235 gen_logic_CC(tmp);
8236 break;
8237 case 0x1: /* eor */
8238 tcg_gen_xor_i32(tmp, tmp, tmp2);
8239 if (!s->condexec_mask)
8240 gen_logic_CC(tmp);
8241 break;
8242 case 0x2: /* lsl */
8243 if (s->condexec_mask) {
8244 gen_helper_shl(tmp2, tmp2, tmp);
8245 } else {
8246 gen_helper_shl_cc(tmp2, tmp2, tmp);
8247 gen_logic_CC(tmp2);
8249 break;
8250 case 0x3: /* lsr */
8251 if (s->condexec_mask) {
8252 gen_helper_shr(tmp2, tmp2, tmp);
8253 } else {
8254 gen_helper_shr_cc(tmp2, tmp2, tmp);
8255 gen_logic_CC(tmp2);
8257 break;
8258 case 0x4: /* asr */
8259 if (s->condexec_mask) {
8260 gen_helper_sar(tmp2, tmp2, tmp);
8261 } else {
8262 gen_helper_sar_cc(tmp2, tmp2, tmp);
8263 gen_logic_CC(tmp2);
8265 break;
8266 case 0x5: /* adc */
8267 if (s->condexec_mask)
8268 gen_add_carry(tmp, tmp, tmp2);
8269 else
8270 gen_helper_adc_cc(tmp, tmp, tmp2);
8271 break;
8272 case 0x6: /* sbc */
8273 if (s->condexec_mask)
8274 gen_sub_carry(tmp, tmp, tmp2);
8275 else
8276 gen_helper_sbc_cc(tmp, tmp, tmp2);
8277 break;
8278 case 0x7: /* ror */
8279 if (s->condexec_mask) {
8280 gen_helper_ror(tmp2, tmp2, tmp);
8281 } else {
8282 gen_helper_ror_cc(tmp2, tmp2, tmp);
8283 gen_logic_CC(tmp2);
8285 break;
8286 case 0x8: /* tst */
8287 tcg_gen_and_i32(tmp, tmp, tmp2);
8288 gen_logic_CC(tmp);
8289 rd = 16;
8290 break;
8291 case 0x9: /* neg */
8292 if (s->condexec_mask)
8293 tcg_gen_neg_i32(tmp, tmp2);
8294 else
8295 gen_helper_sub_cc(tmp, tmp, tmp2);
8296 break;
8297 case 0xa: /* cmp */
8298 gen_helper_sub_cc(tmp, tmp, tmp2);
8299 rd = 16;
8300 break;
8301 case 0xb: /* cmn */
8302 gen_helper_add_cc(tmp, tmp, tmp2);
8303 rd = 16;
8304 break;
8305 case 0xc: /* orr */
8306 tcg_gen_or_i32(tmp, tmp, tmp2);
8307 if (!s->condexec_mask)
8308 gen_logic_CC(tmp);
8309 break;
8310 case 0xd: /* mul */
8311 gen_mull(tmp, tmp2);
8312 if (!s->condexec_mask)
8313 gen_logic_CC(tmp);
8314 break;
8315 case 0xe: /* bic */
8316 tcg_gen_bic_i32(tmp, tmp, tmp2);
8317 if (!s->condexec_mask)
8318 gen_logic_CC(tmp);
8319 break;
8320 case 0xf: /* mvn */
8321 tcg_gen_not_i32(tmp2, tmp2);
8322 if (!s->condexec_mask)
8323 gen_logic_CC(tmp2);
8324 val = 1;
8325 rm = rd;
8326 break;
8328 if (rd != 16) {
8329 if (val) {
8330 store_reg(s, rm, tmp2);
8331 dead_tmp(tmp);
8332 } else {
8333 store_reg(s, rd, tmp);
8334 dead_tmp(tmp2);
8336 } else {
8337 dead_tmp(tmp);
8338 dead_tmp(tmp2);
8340 break;
8342 case 5:
8343 /* load/store register offset. */
8344 rd = insn & 7;
8345 rn = (insn >> 3) & 7;
8346 rm = (insn >> 6) & 7;
8347 op = (insn >> 9) & 7;
8348 addr = load_reg(s, rn);
8349 tmp = load_reg(s, rm);
8350 tcg_gen_add_i32(addr, addr, tmp);
8351 dead_tmp(tmp);
8353 if (op < 3) /* store */
8354 tmp = load_reg(s, rd);
8356 switch (op) {
8357 case 0: /* str */
8358 gen_st32(tmp, addr, IS_USER(s));
8359 break;
8360 case 1: /* strh */
8361 gen_st16(tmp, addr, IS_USER(s));
8362 break;
8363 case 2: /* strb */
8364 gen_st8(tmp, addr, IS_USER(s));
8365 break;
8366 case 3: /* ldrsb */
8367 tmp = gen_ld8s(addr, IS_USER(s));
8368 break;
8369 case 4: /* ldr */
8370 tmp = gen_ld32(addr, IS_USER(s));
8371 break;
8372 case 5: /* ldrh */
8373 tmp = gen_ld16u(addr, IS_USER(s));
8374 break;
8375 case 6: /* ldrb */
8376 tmp = gen_ld8u(addr, IS_USER(s));
8377 break;
8378 case 7: /* ldrsh */
8379 tmp = gen_ld16s(addr, IS_USER(s));
8380 break;
8382 if (op >= 3) /* load */
8383 store_reg(s, rd, tmp);
8384 dead_tmp(addr);
8385 break;
8387 case 6:
8388 /* load/store word immediate offset */
8389 rd = insn & 7;
8390 rn = (insn >> 3) & 7;
8391 addr = load_reg(s, rn);
8392 val = (insn >> 4) & 0x7c;
8393 tcg_gen_addi_i32(addr, addr, val);
8395 if (insn & (1 << 11)) {
8396 /* load */
8397 tmp = gen_ld32(addr, IS_USER(s));
8398 store_reg(s, rd, tmp);
8399 } else {
8400 /* store */
8401 tmp = load_reg(s, rd);
8402 gen_st32(tmp, addr, IS_USER(s));
8404 dead_tmp(addr);
8405 break;
8407 case 7:
8408 /* load/store byte immediate offset */
8409 rd = insn & 7;
8410 rn = (insn >> 3) & 7;
8411 addr = load_reg(s, rn);
8412 val = (insn >> 6) & 0x1f;
8413 tcg_gen_addi_i32(addr, addr, val);
8415 if (insn & (1 << 11)) {
8416 /* load */
8417 tmp = gen_ld8u(addr, IS_USER(s));
8418 store_reg(s, rd, tmp);
8419 } else {
8420 /* store */
8421 tmp = load_reg(s, rd);
8422 gen_st8(tmp, addr, IS_USER(s));
8424 dead_tmp(addr);
8425 break;
8427 case 8:
8428 /* load/store halfword immediate offset */
8429 rd = insn & 7;
8430 rn = (insn >> 3) & 7;
8431 addr = load_reg(s, rn);
8432 val = (insn >> 5) & 0x3e;
8433 tcg_gen_addi_i32(addr, addr, val);
8435 if (insn & (1 << 11)) {
8436 /* load */
8437 tmp = gen_ld16u(addr, IS_USER(s));
8438 store_reg(s, rd, tmp);
8439 } else {
8440 /* store */
8441 tmp = load_reg(s, rd);
8442 gen_st16(tmp, addr, IS_USER(s));
8444 dead_tmp(addr);
8445 break;
8447 case 9:
8448 /* load/store from stack */
8449 rd = (insn >> 8) & 7;
8450 addr = load_reg(s, 13);
8451 val = (insn & 0xff) * 4;
8452 tcg_gen_addi_i32(addr, addr, val);
8454 if (insn & (1 << 11)) {
8455 /* load */
8456 tmp = gen_ld32(addr, IS_USER(s));
8457 store_reg(s, rd, tmp);
8458 } else {
8459 /* store */
8460 tmp = load_reg(s, rd);
8461 gen_st32(tmp, addr, IS_USER(s));
8463 dead_tmp(addr);
8464 break;
8466 case 10:
8467 /* add to high reg */
8468 rd = (insn >> 8) & 7;
8469 if (insn & (1 << 11)) {
8470 /* SP */
8471 tmp = load_reg(s, 13);
8472 } else {
8473 /* PC. bit 1 is ignored. */
8474 tmp = new_tmp();
8475 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
8477 val = (insn & 0xff) * 4;
8478 tcg_gen_addi_i32(tmp, tmp, val);
8479 store_reg(s, rd, tmp);
8480 break;
8482 case 11:
8483 /* misc */
8484 op = (insn >> 8) & 0xf;
8485 switch (op) {
8486 case 0:
8487 /* adjust stack pointer */
8488 tmp = load_reg(s, 13);
8489 val = (insn & 0x7f) * 4;
8490 if (insn & (1 << 7))
8491 val = -(int32_t)val;
8492 tcg_gen_addi_i32(tmp, tmp, val);
8493 store_reg(s, 13, tmp);
8494 break;
8496 case 2: /* sign/zero extend. */
8497 ARCH(6);
8498 rd = insn & 7;
8499 rm = (insn >> 3) & 7;
8500 tmp = load_reg(s, rm);
8501 switch ((insn >> 6) & 3) {
8502 case 0: gen_sxth(tmp); break;
8503 case 1: gen_sxtb(tmp); break;
8504 case 2: gen_uxth(tmp); break;
8505 case 3: gen_uxtb(tmp); break;
8507 store_reg(s, rd, tmp);
8508 break;
8509 case 4: case 5: case 0xc: case 0xd:
8510 /* push/pop */
8511 addr = load_reg(s, 13);
8512 if (insn & (1 << 8))
8513 offset = 4;
8514 else
8515 offset = 0;
8516 for (i = 0; i < 8; i++) {
8517 if (insn & (1 << i))
8518 offset += 4;
8520 if ((insn & (1 << 11)) == 0) {
8521 tcg_gen_addi_i32(addr, addr, -offset);
8523 for (i = 0; i < 8; i++) {
8524 if (insn & (1 << i)) {
8525 if (insn & (1 << 11)) {
8526 /* pop */
8527 tmp = gen_ld32(addr, IS_USER(s));
8528 store_reg(s, i, tmp);
8529 } else {
8530 /* push */
8531 tmp = load_reg(s, i);
8532 gen_st32(tmp, addr, IS_USER(s));
8534 /* advance to the next address. */
8535 tcg_gen_addi_i32(addr, addr, 4);
8538 TCGV_UNUSED(tmp);
8539 if (insn & (1 << 8)) {
8540 if (insn & (1 << 11)) {
8541 /* pop pc */
8542 tmp = gen_ld32(addr, IS_USER(s));
8543 /* don't set the pc until the rest of the instruction
8544 has completed */
8545 } else {
8546 /* push lr */
8547 tmp = load_reg(s, 14);
8548 gen_st32(tmp, addr, IS_USER(s));
8550 tcg_gen_addi_i32(addr, addr, 4);
8552 if ((insn & (1 << 11)) == 0) {
8553 tcg_gen_addi_i32(addr, addr, -offset);
8555 /* write back the new stack pointer */
8556 store_reg(s, 13, addr);
8557 /* set the new PC value */
8558 if ((insn & 0x0900) == 0x0900) {
8559 if (ENABLE_ARCH_5) {
8560 gen_bx(s, tmp);
8561 } else {
8562 store_reg(s, 15, tmp);
8565 break;
8567 case 1: case 3: case 9: case 11: /* czb */
8568 rm = insn & 7;
8569 tmp = load_reg(s, rm);
8570 s->condlabel = gen_new_label();
8571 s->condjmp = 1;
8572 if (insn & (1 << 11))
8573 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
8574 else
8575 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
8576 dead_tmp(tmp);
8577 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
8578 val = (uint32_t)s->pc + 2;
8579 val += offset;
8580 gen_jmp(s, val);
8581 break;
8583 case 15: /* IT, nop-hint. */
8584 if ((insn & 0xf) == 0) {
8585 gen_nop_hint(s, (insn >> 4) & 0xf);
8586 break;
8588 /* If Then. */
8589 s->condexec_cond = (insn >> 4) & 0xe;
8590 s->condexec_mask = insn & 0x1f;
8591 /* No actual code generated for this insn, just setup state. */
8592 break;
8594 case 0xe: /* bkpt */
8595 gen_set_condexec(s);
8596 gen_set_pc_im(s->pc - 2);
8597 gen_exception(EXCP_BKPT);
8598 s->is_jmp = DISAS_JUMP;
8599 break;
8601 case 0xa: /* rev */
8602 ARCH(6);
8603 rn = (insn >> 3) & 0x7;
8604 rd = insn & 0x7;
8605 tmp = load_reg(s, rn);
8606 switch ((insn >> 6) & 3) {
8607 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
8608 case 1: gen_rev16(tmp); break;
8609 case 3: gen_revsh(tmp); break;
8610 default: goto illegal_op;
8612 store_reg(s, rd, tmp);
8613 break;
8615 case 6: /* cps */
8616 ARCH(6);
8617 if (IS_USER(s))
8618 break;
8619 if (IS_M(env)) {
8620 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
8621 /* PRIMASK */
8622 if (insn & 1) {
8623 addr = tcg_const_i32(16);
8624 gen_helper_v7m_msr(cpu_env, addr, tmp);
8626 /* FAULTMASK */
8627 if (insn & 2) {
8628 addr = tcg_const_i32(17);
8629 gen_helper_v7m_msr(cpu_env, addr, tmp);
8631 gen_lookup_tb(s);
8632 } else {
8633 if (insn & (1 << 4))
8634 shift = CPSR_A | CPSR_I | CPSR_F;
8635 else
8636 shift = 0;
8637 gen_set_psr_im(s, shift, 0, ((insn & 7) << 6) & shift);
8639 break;
8641 default:
8642 goto undef;
8644 break;
8646 case 12:
8647 /* load/store multiple */
8648 rn = (insn >> 8) & 0x7;
8649 addr = load_reg(s, rn);
8650 if (arm_feature(env, ARM_FEATURE_ABORT_BU) && (insn & (1 << rn)) == 0) {
8651 /* base-updated abort model: update base register
8652 before an abort can happen */
8653 crement = 0;
8654 for (i = 0; i < 8; i++) {
8655 if (insn & (1 << i)) {
8656 crement += 4;
8659 tmp = new_tmp();
8660 tcg_gen_addi_i32(tmp, addr, crement);
8661 store_reg(s, rn, tmp);
8663 for (i = 0; i < 8; i++) {
8664 if (insn & (1 << i)) {
8665 if (insn & (1 << 11)) {
8666 /* load */
8667 tmp = gen_ld32(addr, IS_USER(s));
8668 store_reg(s, i, tmp);
8669 } else {
8670 /* store */
8671 tmp = load_reg(s, i);
8672 gen_st32(tmp, addr, IS_USER(s));
8674 /* advance to the next address */
8675 tcg_gen_addi_i32(addr, addr, 4);
8678 /* Base register writeback. */
8679 if (!arm_feature(env, ARM_FEATURE_ABORT_BU) && (insn & (1 << rn)) == 0) {
8680 store_reg(s, rn, addr);
8681 } else {
8682 dead_tmp(addr);
8684 break;
8686 case 13:
8687 /* conditional branch or swi */
8688 cond = (insn >> 8) & 0xf;
8689 if (cond == 0xe)
8690 goto undef;
8692 if (cond == 0xf) {
8693 /* swi */
8694 gen_set_condexec(s);
8695 gen_set_pc_im(s->pc);
8696 s->is_jmp = DISAS_SWI;
8697 break;
8699 /* generate a conditional jump to next instruction */
8700 s->condlabel = gen_new_label();
8701 gen_test_cc(cond ^ 1, s->condlabel);
8702 s->condjmp = 1;
8704 /* jump to the offset */
8705 val = (uint32_t)s->pc + 2;
8706 offset = ((int32_t)insn << 24) >> 24;
8707 val += offset << 1;
8708 gen_jmp(s, val);
8709 break;
8711 case 14:
8712 if (insn & (1 << 11)) {
8713 if (disas_thumb2_insn(env, s, insn))
8714 goto undef32;
8715 break;
8717 /* unconditional branch */
8718 val = (uint32_t)s->pc;
8719 offset = ((int32_t)insn << 21) >> 21;
8720 val += (offset << 1) + 2;
8721 gen_jmp(s, val);
8722 break;
8724 case 15:
8725 if (disas_thumb2_insn(env, s, insn))
8726 goto undef32;
8727 break;
8729 return;
8730 undef32:
8731 gen_set_condexec(s);
8732 gen_set_pc_im(s->pc - 4);
8733 gen_exception(EXCP_UDEF);
8734 s->is_jmp = DISAS_JUMP;
8735 return;
8736 illegal_op:
8737 undef:
8738 gen_set_condexec(s);
8739 gen_set_pc_im(s->pc - 2);
8740 gen_exception(EXCP_UDEF);
8741 s->is_jmp = DISAS_JUMP;
8744 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8745 basic block 'tb'. If search_pc is TRUE, also generate PC
8746 information for each intermediate instruction. */
8747 static inline void gen_intermediate_code_internal(CPUState *env,
8748 TranslationBlock *tb,
8749 int search_pc)
8751 DisasContext dc1, *dc = &dc1;
8752 CPUBreakpoint *bp;
8753 uint16_t *gen_opc_end;
8754 int j, lj;
8755 target_ulong pc_start;
8756 uint32_t next_page_start;
8757 int num_insns;
8758 int max_insns;
8760 /* generate intermediate code */
8761 num_temps = 0;
8763 pc_start = tb->pc;
8765 dc->tb = tb;
8767 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
8769 dc->is_jmp = DISAS_NEXT;
8770 dc->pc = pc_start;
8771 dc->singlestep_enabled = env->singlestep_enabled;
8772 dc->condjmp = 0;
8773 dc->thumb = env->thumb;
8774 dc->condexec_mask = (env->condexec_bits & 0xf) << 1;
8775 dc->condexec_cond = env->condexec_bits >> 4;
8776 #if !defined(CONFIG_USER_ONLY)
8777 if (IS_M(env)) {
8778 dc->user = ((env->v7m.exception == 0) && (env->v7m.control & 1));
8779 } else {
8780 dc->user = (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_USR;
8782 #endif
8783 cpu_F0s = tcg_temp_new_i32();
8784 cpu_F1s = tcg_temp_new_i32();
8785 cpu_F0d = tcg_temp_new_i64();
8786 cpu_F1d = tcg_temp_new_i64();
8787 cpu_V0 = cpu_F0d;
8788 cpu_V1 = cpu_F1d;
8789 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8790 cpu_M0 = tcg_temp_new_i64();
8791 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
8792 lj = -1;
8793 num_insns = 0;
8794 max_insns = tb->cflags & CF_COUNT_MASK;
8795 if (max_insns == 0)
8796 max_insns = CF_COUNT_MASK;
8798 gen_icount_start();
8799 /* Reset the conditional execution bits immediately. This avoids
8800 complications trying to do it at the end of the block. */
8801 if (env->condexec_bits)
8803 TCGv tmp = new_tmp();
8804 tcg_gen_movi_i32(tmp, 0);
8805 store_cpu_field(tmp, condexec_bits);
8807 do {
8808 #ifdef CONFIG_USER_ONLY
8809 /* Intercept jump to the magic kernel page. */
8810 if (dc->pc >= 0xffff0000) {
8811 /* We always get here via a jump, so know we are not in a
8812 conditional execution block. */
8813 gen_exception(EXCP_KERNEL_TRAP);
8814 dc->is_jmp = DISAS_UPDATE;
8815 break;
8817 #else
8818 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
8819 /* We always get here via a jump, so know we are not in a
8820 conditional execution block. */
8821 gen_exception(EXCP_EXCEPTION_EXIT);
8822 dc->is_jmp = DISAS_UPDATE;
8823 break;
8825 #endif
8827 if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
8828 TAILQ_FOREACH(bp, &env->breakpoints, entry) {
8829 if (bp->pc == dc->pc) {
8830 gen_set_condexec(dc);
8831 gen_set_pc_im(dc->pc);
8832 gen_exception(EXCP_DEBUG);
8833 dc->is_jmp = DISAS_JUMP;
8834 /* Advance PC so that clearing the breakpoint will
8835 invalidate this TB. */
8836 dc->pc += 2;
8837 goto done_generating;
8838 break;
8842 if (search_pc) {
8843 j = gen_opc_ptr - gen_opc_buf;
8844 if (lj < j) {
8845 lj++;
8846 while (lj < j)
8847 gen_opc_instr_start[lj++] = 0;
8849 gen_opc_pc[lj] = dc->pc;
8850 gen_opc_instr_start[lj] = 1;
8851 gen_opc_icount[lj] = num_insns;
8854 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
8855 gen_io_start();
8857 if (env->thumb) {
8858 disas_thumb_insn(env, dc);
8859 if (dc->condexec_mask) {
8860 dc->condexec_cond = (dc->condexec_cond & 0xe)
8861 | ((dc->condexec_mask >> 4) & 1);
8862 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
8863 if (dc->condexec_mask == 0) {
8864 dc->condexec_cond = 0;
8867 } else {
8868 disas_arm_insn(env, dc);
8870 if (num_temps) {
8871 fprintf(stderr, "Internal resource leak before %08x\n", dc->pc);
8872 num_temps = 0;
8875 if (dc->condjmp && !dc->is_jmp) {
8876 gen_set_label(dc->condlabel);
8877 dc->condjmp = 0;
8879 /* Translation stops when a conditional branch is encountered.
8880 * Otherwise the subsequent code could get translated several times.
8881 * Also stop translation when a page boundary is reached. This
8882 * ensures prefetch aborts occur at the right place. */
8883 num_insns ++;
8884 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
8885 !env->singlestep_enabled &&
8886 !singlestep &&
8887 dc->pc < next_page_start &&
8888 num_insns < max_insns);
8890 if (tb->cflags & CF_LAST_IO) {
8891 if (dc->condjmp) {
8892 /* FIXME: This can theoretically happen with self-modifying
8893 code. */
8894 cpu_abort(env, "IO on conditional branch instruction");
8896 gen_io_end();
8899 /* At this stage dc->condjmp will only be set when the skipped
8900 instruction was a conditional branch or trap, and the PC has
8901 already been written. */
8902 if (unlikely(env->singlestep_enabled)) {
8903 /* Make sure the pc is updated, and raise a debug exception. */
8904 if (dc->condjmp) {
8905 gen_set_condexec(dc);
8906 if (dc->is_jmp == DISAS_SWI) {
8907 gen_exception(EXCP_SWI);
8908 } else {
8909 gen_exception(EXCP_DEBUG);
8911 gen_set_label(dc->condlabel);
8913 if (dc->condjmp || !dc->is_jmp) {
8914 gen_set_pc_im(dc->pc);
8915 dc->condjmp = 0;
8917 gen_set_condexec(dc);
8918 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
8919 gen_exception(EXCP_SWI);
8920 } else {
8921 /* FIXME: Single stepping a WFI insn will not halt
8922 the CPU. */
8923 gen_exception(EXCP_DEBUG);
8925 } else {
8926 /* While branches must always occur at the end of an IT block,
8927 there are a few other things that can cause us to terminate
8928 the TB in the middel of an IT block:
8929 - Exception generating instructions (bkpt, swi, undefined).
8930 - Page boundaries.
8931 - Hardware watchpoints.
8932 Hardware breakpoints have already been handled and skip this code.
8934 gen_set_condexec(dc);
8935 switch(dc->is_jmp) {
8936 case DISAS_NEXT:
8937 gen_goto_tb(dc, 1, dc->pc);
8938 break;
8939 default:
8940 case DISAS_JUMP:
8941 case DISAS_UPDATE:
8942 /* indicate that the hash table must be used to find the next TB */
8943 tcg_gen_exit_tb(0);
8944 break;
8945 case DISAS_TB_JUMP:
8946 /* nothing more to generate */
8947 break;
8948 case DISAS_WFI:
8949 gen_helper_wfi();
8950 break;
8951 case DISAS_SWI:
8952 gen_exception(EXCP_SWI);
8953 break;
8955 if (dc->condjmp) {
8956 gen_set_label(dc->condlabel);
8957 gen_set_condexec(dc);
8958 gen_goto_tb(dc, 1, dc->pc);
8959 dc->condjmp = 0;
8963 done_generating:
8964 gen_icount_end(tb, num_insns);
8965 *gen_opc_ptr = INDEX_op_end;
8967 #ifdef DEBUG_DISAS
8968 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
8969 qemu_log("----------------\n");
8970 qemu_log("IN: %s\n", lookup_symbol(pc_start));
8971 log_target_disas(pc_start, dc->pc - pc_start, env->thumb);
8972 qemu_log("\n");
8974 #endif
8975 if (search_pc) {
8976 j = gen_opc_ptr - gen_opc_buf;
8977 lj++;
8978 while (lj <= j)
8979 gen_opc_instr_start[lj++] = 0;
8980 } else {
8981 tb->size = dc->pc - pc_start;
8982 tb->icount = num_insns;
8986 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
8988 gen_intermediate_code_internal(env, tb, 0);
8991 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
8993 gen_intermediate_code_internal(env, tb, 1);
8996 static const char *cpu_mode_names[16] = {
8997 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
8998 "???", "???", "???", "und", "???", "???", "???", "sys"
9001 void cpu_dump_state(CPUState *env, FILE *f,
9002 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
9003 int flags)
9005 int i;
9006 #if 0
9007 union {
9008 uint32_t i;
9009 float s;
9010 } s0, s1;
9011 CPU_DoubleU d;
9012 /* ??? This assumes float64 and double have the same layout.
9013 Oh well, it's only debug dumps. */
9014 union {
9015 float64 f64;
9016 double d;
9017 } d0;
9018 #endif
9019 uint32_t psr;
9021 for(i=0;i<16;i++) {
9022 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
9023 if ((i % 4) == 3)
9024 cpu_fprintf(f, "\n");
9025 else
9026 cpu_fprintf(f, " ");
9028 psr = cpsr_read(env);
9029 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
9030 psr,
9031 psr & (1 << 31) ? 'N' : '-',
9032 psr & (1 << 30) ? 'Z' : '-',
9033 psr & (1 << 29) ? 'C' : '-',
9034 psr & (1 << 28) ? 'V' : '-',
9035 psr & CPSR_T ? 'T' : 'A',
9036 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
9038 #if 0
9039 for (i = 0; i < 16; i++) {
9040 d.d = env->vfp.regs[i];
9041 s0.i = d.l.lower;
9042 s1.i = d.l.upper;
9043 d0.f64 = d.d;
9044 cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9045 i * 2, (int)s0.i, s0.s,
9046 i * 2 + 1, (int)s1.i, s1.s,
9047 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
9048 d0.d);
9050 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
9051 #endif
9054 void gen_pc_load(CPUState *env, TranslationBlock *tb,
9055 unsigned long searched_pc, int pc_pos, void *puc)
9057 env->regs[15] = gen_opc_pc[pc_pos];