cirrus-vga: convert to pci_register_bar_simple()
[qemu/qemu-dev-zwu.git] / target-arm / translate.c
blobf69912f20c9153bf02ec9e3f007d706e88d8a73d
1 /*
2 * ARM translation
4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2005-2007 CodeSourcery
6 * Copyright (c) 2007 OpenedHand, Ltd.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <inttypes.h>
27 #include "cpu.h"
28 #include "exec-all.h"
29 #include "disas.h"
30 #include "tcg-op.h"
31 #include "qemu-log.h"
33 #include "helpers.h"
34 #define GEN_HELPER 1
35 #include "helpers.h"
37 #define ENABLE_ARCH_5J 0
38 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
39 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
40 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
41 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
43 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
45 /* internal defines */
46 typedef struct DisasContext {
47 target_ulong pc;
48 int is_jmp;
49 /* Nonzero if this instruction has been conditionally skipped. */
50 int condjmp;
51 /* The label that will be jumped to when the instruction is skipped. */
52 int condlabel;
53 /* Thumb-2 condtional execution bits. */
54 int condexec_mask;
55 int condexec_cond;
56 struct TranslationBlock *tb;
57 int singlestep_enabled;
58 int thumb;
59 #if !defined(CONFIG_USER_ONLY)
60 int user;
61 #endif
62 int vfp_enabled;
63 int vec_len;
64 int vec_stride;
65 } DisasContext;
67 static uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE];
69 #if defined(CONFIG_USER_ONLY)
70 #define IS_USER(s) 1
71 #else
72 #define IS_USER(s) (s->user)
73 #endif
75 /* These instructions trap after executing, so defer them until after the
76 conditional executions state has been updated. */
77 #define DISAS_WFI 4
78 #define DISAS_SWI 5
80 static TCGv_ptr cpu_env;
81 /* We reuse the same 64-bit temporaries for efficiency. */
82 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
83 static TCGv_i32 cpu_R[16];
84 static TCGv_i32 cpu_exclusive_addr;
85 static TCGv_i32 cpu_exclusive_val;
86 static TCGv_i32 cpu_exclusive_high;
87 #ifdef CONFIG_USER_ONLY
88 static TCGv_i32 cpu_exclusive_test;
89 static TCGv_i32 cpu_exclusive_info;
90 #endif
92 /* FIXME: These should be removed. */
93 static TCGv cpu_F0s, cpu_F1s;
94 static TCGv_i64 cpu_F0d, cpu_F1d;
96 #include "gen-icount.h"
98 static const char *regnames[] =
99 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
100 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
102 /* initialize TCG globals. */
103 void arm_translate_init(void)
105 int i;
107 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
109 for (i = 0; i < 16; i++) {
110 cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
111 offsetof(CPUState, regs[i]),
112 regnames[i]);
114 cpu_exclusive_addr = tcg_global_mem_new_i32(TCG_AREG0,
115 offsetof(CPUState, exclusive_addr), "exclusive_addr");
116 cpu_exclusive_val = tcg_global_mem_new_i32(TCG_AREG0,
117 offsetof(CPUState, exclusive_val), "exclusive_val");
118 cpu_exclusive_high = tcg_global_mem_new_i32(TCG_AREG0,
119 offsetof(CPUState, exclusive_high), "exclusive_high");
120 #ifdef CONFIG_USER_ONLY
121 cpu_exclusive_test = tcg_global_mem_new_i32(TCG_AREG0,
122 offsetof(CPUState, exclusive_test), "exclusive_test");
123 cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0,
124 offsetof(CPUState, exclusive_info), "exclusive_info");
125 #endif
127 #define GEN_HELPER 2
128 #include "helpers.h"
131 static inline TCGv load_cpu_offset(int offset)
133 TCGv tmp = tcg_temp_new_i32();
134 tcg_gen_ld_i32(tmp, cpu_env, offset);
135 return tmp;
138 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
140 static inline void store_cpu_offset(TCGv var, int offset)
142 tcg_gen_st_i32(var, cpu_env, offset);
143 tcg_temp_free_i32(var);
146 #define store_cpu_field(var, name) \
147 store_cpu_offset(var, offsetof(CPUState, name))
149 /* Set a variable to the value of a CPU register. */
150 static void load_reg_var(DisasContext *s, TCGv var, int reg)
152 if (reg == 15) {
153 uint32_t addr;
154 /* normaly, since we updated PC, we need only to add one insn */
155 if (s->thumb)
156 addr = (long)s->pc + 2;
157 else
158 addr = (long)s->pc + 4;
159 tcg_gen_movi_i32(var, addr);
160 } else {
161 tcg_gen_mov_i32(var, cpu_R[reg]);
165 /* Create a new temporary and set it to the value of a CPU register. */
166 static inline TCGv load_reg(DisasContext *s, int reg)
168 TCGv tmp = tcg_temp_new_i32();
169 load_reg_var(s, tmp, reg);
170 return tmp;
173 /* Set a CPU register. The source must be a temporary and will be
174 marked as dead. */
175 static void store_reg(DisasContext *s, int reg, TCGv var)
177 if (reg == 15) {
178 tcg_gen_andi_i32(var, var, ~1);
179 s->is_jmp = DISAS_JUMP;
181 tcg_gen_mov_i32(cpu_R[reg], var);
182 tcg_temp_free_i32(var);
185 /* Value extensions. */
186 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
187 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
188 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
189 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
191 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
192 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
195 static inline void gen_set_cpsr(TCGv var, uint32_t mask)
197 TCGv tmp_mask = tcg_const_i32(mask);
198 gen_helper_cpsr_write(var, tmp_mask);
199 tcg_temp_free_i32(tmp_mask);
201 /* Set NZCV flags from the high 4 bits of var. */
202 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
204 static void gen_exception(int excp)
206 TCGv tmp = tcg_temp_new_i32();
207 tcg_gen_movi_i32(tmp, excp);
208 gen_helper_exception(tmp);
209 tcg_temp_free_i32(tmp);
212 static void gen_smul_dual(TCGv a, TCGv b)
214 TCGv tmp1 = tcg_temp_new_i32();
215 TCGv tmp2 = tcg_temp_new_i32();
216 tcg_gen_ext16s_i32(tmp1, a);
217 tcg_gen_ext16s_i32(tmp2, b);
218 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
219 tcg_temp_free_i32(tmp2);
220 tcg_gen_sari_i32(a, a, 16);
221 tcg_gen_sari_i32(b, b, 16);
222 tcg_gen_mul_i32(b, b, a);
223 tcg_gen_mov_i32(a, tmp1);
224 tcg_temp_free_i32(tmp1);
227 /* Byteswap each halfword. */
228 static void gen_rev16(TCGv var)
230 TCGv tmp = tcg_temp_new_i32();
231 tcg_gen_shri_i32(tmp, var, 8);
232 tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
233 tcg_gen_shli_i32(var, var, 8);
234 tcg_gen_andi_i32(var, var, 0xff00ff00);
235 tcg_gen_or_i32(var, var, tmp);
236 tcg_temp_free_i32(tmp);
239 /* Byteswap low halfword and sign extend. */
240 static void gen_revsh(TCGv var)
242 tcg_gen_ext16u_i32(var, var);
243 tcg_gen_bswap16_i32(var, var);
244 tcg_gen_ext16s_i32(var, var);
247 /* Unsigned bitfield extract. */
248 static void gen_ubfx(TCGv var, int shift, uint32_t mask)
250 if (shift)
251 tcg_gen_shri_i32(var, var, shift);
252 tcg_gen_andi_i32(var, var, mask);
255 /* Signed bitfield extract. */
256 static void gen_sbfx(TCGv var, int shift, int width)
258 uint32_t signbit;
260 if (shift)
261 tcg_gen_sari_i32(var, var, shift);
262 if (shift + width < 32) {
263 signbit = 1u << (width - 1);
264 tcg_gen_andi_i32(var, var, (1u << width) - 1);
265 tcg_gen_xori_i32(var, var, signbit);
266 tcg_gen_subi_i32(var, var, signbit);
270 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
271 static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
273 tcg_gen_andi_i32(val, val, mask);
274 tcg_gen_shli_i32(val, val, shift);
275 tcg_gen_andi_i32(base, base, ~(mask << shift));
276 tcg_gen_or_i32(dest, base, val);
279 /* Return (b << 32) + a. Mark inputs as dead */
280 static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv b)
282 TCGv_i64 tmp64 = tcg_temp_new_i64();
284 tcg_gen_extu_i32_i64(tmp64, b);
285 tcg_temp_free_i32(b);
286 tcg_gen_shli_i64(tmp64, tmp64, 32);
287 tcg_gen_add_i64(a, tmp64, a);
289 tcg_temp_free_i64(tmp64);
290 return a;
293 /* Return (b << 32) - a. Mark inputs as dead. */
294 static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv b)
296 TCGv_i64 tmp64 = tcg_temp_new_i64();
298 tcg_gen_extu_i32_i64(tmp64, b);
299 tcg_temp_free_i32(b);
300 tcg_gen_shli_i64(tmp64, tmp64, 32);
301 tcg_gen_sub_i64(a, tmp64, a);
303 tcg_temp_free_i64(tmp64);
304 return a;
307 /* FIXME: Most targets have native widening multiplication.
308 It would be good to use that instead of a full wide multiply. */
309 /* 32x32->64 multiply. Marks inputs as dead. */
310 static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b)
312 TCGv_i64 tmp1 = tcg_temp_new_i64();
313 TCGv_i64 tmp2 = tcg_temp_new_i64();
315 tcg_gen_extu_i32_i64(tmp1, a);
316 tcg_temp_free_i32(a);
317 tcg_gen_extu_i32_i64(tmp2, b);
318 tcg_temp_free_i32(b);
319 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
320 tcg_temp_free_i64(tmp2);
321 return tmp1;
324 static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
326 TCGv_i64 tmp1 = tcg_temp_new_i64();
327 TCGv_i64 tmp2 = tcg_temp_new_i64();
329 tcg_gen_ext_i32_i64(tmp1, a);
330 tcg_temp_free_i32(a);
331 tcg_gen_ext_i32_i64(tmp2, b);
332 tcg_temp_free_i32(b);
333 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
334 tcg_temp_free_i64(tmp2);
335 return tmp1;
338 /* Swap low and high halfwords. */
339 static void gen_swap_half(TCGv var)
341 TCGv tmp = tcg_temp_new_i32();
342 tcg_gen_shri_i32(tmp, var, 16);
343 tcg_gen_shli_i32(var, var, 16);
344 tcg_gen_or_i32(var, var, tmp);
345 tcg_temp_free_i32(tmp);
348 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
349 tmp = (t0 ^ t1) & 0x8000;
350 t0 &= ~0x8000;
351 t1 &= ~0x8000;
352 t0 = (t0 + t1) ^ tmp;
355 static void gen_add16(TCGv t0, TCGv t1)
357 TCGv tmp = tcg_temp_new_i32();
358 tcg_gen_xor_i32(tmp, t0, t1);
359 tcg_gen_andi_i32(tmp, tmp, 0x8000);
360 tcg_gen_andi_i32(t0, t0, ~0x8000);
361 tcg_gen_andi_i32(t1, t1, ~0x8000);
362 tcg_gen_add_i32(t0, t0, t1);
363 tcg_gen_xor_i32(t0, t0, tmp);
364 tcg_temp_free_i32(tmp);
365 tcg_temp_free_i32(t1);
368 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
370 /* Set CF to the top bit of var. */
371 static void gen_set_CF_bit31(TCGv var)
373 TCGv tmp = tcg_temp_new_i32();
374 tcg_gen_shri_i32(tmp, var, 31);
375 gen_set_CF(tmp);
376 tcg_temp_free_i32(tmp);
379 /* Set N and Z flags from var. */
380 static inline void gen_logic_CC(TCGv var)
382 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF));
383 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF));
386 /* T0 += T1 + CF. */
387 static void gen_adc(TCGv t0, TCGv t1)
389 TCGv tmp;
390 tcg_gen_add_i32(t0, t0, t1);
391 tmp = load_cpu_field(CF);
392 tcg_gen_add_i32(t0, t0, tmp);
393 tcg_temp_free_i32(tmp);
396 /* dest = T0 + T1 + CF. */
397 static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
399 TCGv tmp;
400 tcg_gen_add_i32(dest, t0, t1);
401 tmp = load_cpu_field(CF);
402 tcg_gen_add_i32(dest, dest, tmp);
403 tcg_temp_free_i32(tmp);
406 /* dest = T0 - T1 + CF - 1. */
407 static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
409 TCGv tmp;
410 tcg_gen_sub_i32(dest, t0, t1);
411 tmp = load_cpu_field(CF);
412 tcg_gen_add_i32(dest, dest, tmp);
413 tcg_gen_subi_i32(dest, dest, 1);
414 tcg_temp_free_i32(tmp);
417 /* FIXME: Implement this natively. */
418 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
420 static void shifter_out_im(TCGv var, int shift)
422 TCGv tmp = tcg_temp_new_i32();
423 if (shift == 0) {
424 tcg_gen_andi_i32(tmp, var, 1);
425 } else {
426 tcg_gen_shri_i32(tmp, var, shift);
427 if (shift != 31)
428 tcg_gen_andi_i32(tmp, tmp, 1);
430 gen_set_CF(tmp);
431 tcg_temp_free_i32(tmp);
434 /* Shift by immediate. Includes special handling for shift == 0. */
435 static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
437 switch (shiftop) {
438 case 0: /* LSL */
439 if (shift != 0) {
440 if (flags)
441 shifter_out_im(var, 32 - shift);
442 tcg_gen_shli_i32(var, var, shift);
444 break;
445 case 1: /* LSR */
446 if (shift == 0) {
447 if (flags) {
448 tcg_gen_shri_i32(var, var, 31);
449 gen_set_CF(var);
451 tcg_gen_movi_i32(var, 0);
452 } else {
453 if (flags)
454 shifter_out_im(var, shift - 1);
455 tcg_gen_shri_i32(var, var, shift);
457 break;
458 case 2: /* ASR */
459 if (shift == 0)
460 shift = 32;
461 if (flags)
462 shifter_out_im(var, shift - 1);
463 if (shift == 32)
464 shift = 31;
465 tcg_gen_sari_i32(var, var, shift);
466 break;
467 case 3: /* ROR/RRX */
468 if (shift != 0) {
469 if (flags)
470 shifter_out_im(var, shift - 1);
471 tcg_gen_rotri_i32(var, var, shift); break;
472 } else {
473 TCGv tmp = load_cpu_field(CF);
474 if (flags)
475 shifter_out_im(var, 0);
476 tcg_gen_shri_i32(var, var, 1);
477 tcg_gen_shli_i32(tmp, tmp, 31);
478 tcg_gen_or_i32(var, var, tmp);
479 tcg_temp_free_i32(tmp);
484 static inline void gen_arm_shift_reg(TCGv var, int shiftop,
485 TCGv shift, int flags)
487 if (flags) {
488 switch (shiftop) {
489 case 0: gen_helper_shl_cc(var, var, shift); break;
490 case 1: gen_helper_shr_cc(var, var, shift); break;
491 case 2: gen_helper_sar_cc(var, var, shift); break;
492 case 3: gen_helper_ror_cc(var, var, shift); break;
494 } else {
495 switch (shiftop) {
496 case 0: gen_helper_shl(var, var, shift); break;
497 case 1: gen_helper_shr(var, var, shift); break;
498 case 2: gen_helper_sar(var, var, shift); break;
499 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
500 tcg_gen_rotr_i32(var, var, shift); break;
503 tcg_temp_free_i32(shift);
506 #define PAS_OP(pfx) \
507 switch (op2) { \
508 case 0: gen_pas_helper(glue(pfx,add16)); break; \
509 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
510 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
511 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
512 case 4: gen_pas_helper(glue(pfx,add8)); break; \
513 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
515 static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
517 TCGv_ptr tmp;
519 switch (op1) {
520 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
521 case 1:
522 tmp = tcg_temp_new_ptr();
523 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
524 PAS_OP(s)
525 tcg_temp_free_ptr(tmp);
526 break;
527 case 5:
528 tmp = tcg_temp_new_ptr();
529 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
530 PAS_OP(u)
531 tcg_temp_free_ptr(tmp);
532 break;
533 #undef gen_pas_helper
534 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
535 case 2:
536 PAS_OP(q);
537 break;
538 case 3:
539 PAS_OP(sh);
540 break;
541 case 6:
542 PAS_OP(uq);
543 break;
544 case 7:
545 PAS_OP(uh);
546 break;
547 #undef gen_pas_helper
550 #undef PAS_OP
552 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
553 #define PAS_OP(pfx) \
554 switch (op1) { \
555 case 0: gen_pas_helper(glue(pfx,add8)); break; \
556 case 1: gen_pas_helper(glue(pfx,add16)); break; \
557 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
558 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
559 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
560 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
562 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
564 TCGv_ptr tmp;
566 switch (op2) {
567 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
568 case 0:
569 tmp = tcg_temp_new_ptr();
570 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
571 PAS_OP(s)
572 tcg_temp_free_ptr(tmp);
573 break;
574 case 4:
575 tmp = tcg_temp_new_ptr();
576 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
577 PAS_OP(u)
578 tcg_temp_free_ptr(tmp);
579 break;
580 #undef gen_pas_helper
581 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
582 case 1:
583 PAS_OP(q);
584 break;
585 case 2:
586 PAS_OP(sh);
587 break;
588 case 5:
589 PAS_OP(uq);
590 break;
591 case 6:
592 PAS_OP(uh);
593 break;
594 #undef gen_pas_helper
597 #undef PAS_OP
599 static void gen_test_cc(int cc, int label)
601 TCGv tmp;
602 TCGv tmp2;
603 int inv;
605 switch (cc) {
606 case 0: /* eq: Z */
607 tmp = load_cpu_field(ZF);
608 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
609 break;
610 case 1: /* ne: !Z */
611 tmp = load_cpu_field(ZF);
612 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
613 break;
614 case 2: /* cs: C */
615 tmp = load_cpu_field(CF);
616 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
617 break;
618 case 3: /* cc: !C */
619 tmp = load_cpu_field(CF);
620 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
621 break;
622 case 4: /* mi: N */
623 tmp = load_cpu_field(NF);
624 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
625 break;
626 case 5: /* pl: !N */
627 tmp = load_cpu_field(NF);
628 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
629 break;
630 case 6: /* vs: V */
631 tmp = load_cpu_field(VF);
632 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
633 break;
634 case 7: /* vc: !V */
635 tmp = load_cpu_field(VF);
636 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
637 break;
638 case 8: /* hi: C && !Z */
639 inv = gen_new_label();
640 tmp = load_cpu_field(CF);
641 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
642 tcg_temp_free_i32(tmp);
643 tmp = load_cpu_field(ZF);
644 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
645 gen_set_label(inv);
646 break;
647 case 9: /* ls: !C || Z */
648 tmp = load_cpu_field(CF);
649 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
650 tcg_temp_free_i32(tmp);
651 tmp = load_cpu_field(ZF);
652 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
653 break;
654 case 10: /* ge: N == V -> N ^ V == 0 */
655 tmp = load_cpu_field(VF);
656 tmp2 = load_cpu_field(NF);
657 tcg_gen_xor_i32(tmp, tmp, tmp2);
658 tcg_temp_free_i32(tmp2);
659 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
660 break;
661 case 11: /* lt: N != V -> N ^ V != 0 */
662 tmp = load_cpu_field(VF);
663 tmp2 = load_cpu_field(NF);
664 tcg_gen_xor_i32(tmp, tmp, tmp2);
665 tcg_temp_free_i32(tmp2);
666 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
667 break;
668 case 12: /* gt: !Z && N == V */
669 inv = gen_new_label();
670 tmp = load_cpu_field(ZF);
671 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
672 tcg_temp_free_i32(tmp);
673 tmp = load_cpu_field(VF);
674 tmp2 = load_cpu_field(NF);
675 tcg_gen_xor_i32(tmp, tmp, tmp2);
676 tcg_temp_free_i32(tmp2);
677 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
678 gen_set_label(inv);
679 break;
680 case 13: /* le: Z || N != V */
681 tmp = load_cpu_field(ZF);
682 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
683 tcg_temp_free_i32(tmp);
684 tmp = load_cpu_field(VF);
685 tmp2 = load_cpu_field(NF);
686 tcg_gen_xor_i32(tmp, tmp, tmp2);
687 tcg_temp_free_i32(tmp2);
688 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
689 break;
690 default:
691 fprintf(stderr, "Bad condition code 0x%x\n", cc);
692 abort();
694 tcg_temp_free_i32(tmp);
697 static const uint8_t table_logic_cc[16] = {
698 1, /* and */
699 1, /* xor */
700 0, /* sub */
701 0, /* rsb */
702 0, /* add */
703 0, /* adc */
704 0, /* sbc */
705 0, /* rsc */
706 1, /* andl */
707 1, /* xorl */
708 0, /* cmp */
709 0, /* cmn */
710 1, /* orr */
711 1, /* mov */
712 1, /* bic */
713 1, /* mvn */
716 /* Set PC and Thumb state from an immediate address. */
717 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
719 TCGv tmp;
721 s->is_jmp = DISAS_UPDATE;
722 if (s->thumb != (addr & 1)) {
723 tmp = tcg_temp_new_i32();
724 tcg_gen_movi_i32(tmp, addr & 1);
725 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
726 tcg_temp_free_i32(tmp);
728 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
731 /* Set PC and Thumb state from var. var is marked as dead. */
732 static inline void gen_bx(DisasContext *s, TCGv var)
734 s->is_jmp = DISAS_UPDATE;
735 tcg_gen_andi_i32(cpu_R[15], var, ~1);
736 tcg_gen_andi_i32(var, var, 1);
737 store_cpu_field(var, thumb);
740 /* Variant of store_reg which uses branch&exchange logic when storing
741 to r15 in ARM architecture v7 and above. The source must be a temporary
742 and will be marked as dead. */
743 static inline void store_reg_bx(CPUState *env, DisasContext *s,
744 int reg, TCGv var)
746 if (reg == 15 && ENABLE_ARCH_7) {
747 gen_bx(s, var);
748 } else {
749 store_reg(s, reg, var);
753 static inline TCGv gen_ld8s(TCGv addr, int index)
755 TCGv tmp = tcg_temp_new_i32();
756 tcg_gen_qemu_ld8s(tmp, addr, index);
757 return tmp;
759 static inline TCGv gen_ld8u(TCGv addr, int index)
761 TCGv tmp = tcg_temp_new_i32();
762 tcg_gen_qemu_ld8u(tmp, addr, index);
763 return tmp;
765 static inline TCGv gen_ld16s(TCGv addr, int index)
767 TCGv tmp = tcg_temp_new_i32();
768 tcg_gen_qemu_ld16s(tmp, addr, index);
769 return tmp;
771 static inline TCGv gen_ld16u(TCGv addr, int index)
773 TCGv tmp = tcg_temp_new_i32();
774 tcg_gen_qemu_ld16u(tmp, addr, index);
775 return tmp;
777 static inline TCGv gen_ld32(TCGv addr, int index)
779 TCGv tmp = tcg_temp_new_i32();
780 tcg_gen_qemu_ld32u(tmp, addr, index);
781 return tmp;
783 static inline TCGv_i64 gen_ld64(TCGv addr, int index)
785 TCGv_i64 tmp = tcg_temp_new_i64();
786 tcg_gen_qemu_ld64(tmp, addr, index);
787 return tmp;
789 static inline void gen_st8(TCGv val, TCGv addr, int index)
791 tcg_gen_qemu_st8(val, addr, index);
792 tcg_temp_free_i32(val);
794 static inline void gen_st16(TCGv val, TCGv addr, int index)
796 tcg_gen_qemu_st16(val, addr, index);
797 tcg_temp_free_i32(val);
799 static inline void gen_st32(TCGv val, TCGv addr, int index)
801 tcg_gen_qemu_st32(val, addr, index);
802 tcg_temp_free_i32(val);
804 static inline void gen_st64(TCGv_i64 val, TCGv addr, int index)
806 tcg_gen_qemu_st64(val, addr, index);
807 tcg_temp_free_i64(val);
810 static inline void gen_set_pc_im(uint32_t val)
812 tcg_gen_movi_i32(cpu_R[15], val);
815 /* Force a TB lookup after an instruction that changes the CPU state. */
816 static inline void gen_lookup_tb(DisasContext *s)
818 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
819 s->is_jmp = DISAS_UPDATE;
822 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
823 TCGv var)
825 int val, rm, shift, shiftop;
826 TCGv offset;
828 if (!(insn & (1 << 25))) {
829 /* immediate */
830 val = insn & 0xfff;
831 if (!(insn & (1 << 23)))
832 val = -val;
833 if (val != 0)
834 tcg_gen_addi_i32(var, var, val);
835 } else {
836 /* shift/register */
837 rm = (insn) & 0xf;
838 shift = (insn >> 7) & 0x1f;
839 shiftop = (insn >> 5) & 3;
840 offset = load_reg(s, rm);
841 gen_arm_shift_im(offset, shiftop, shift, 0);
842 if (!(insn & (1 << 23)))
843 tcg_gen_sub_i32(var, var, offset);
844 else
845 tcg_gen_add_i32(var, var, offset);
846 tcg_temp_free_i32(offset);
850 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
851 int extra, TCGv var)
853 int val, rm;
854 TCGv offset;
856 if (insn & (1 << 22)) {
857 /* immediate */
858 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
859 if (!(insn & (1 << 23)))
860 val = -val;
861 val += extra;
862 if (val != 0)
863 tcg_gen_addi_i32(var, var, val);
864 } else {
865 /* register */
866 if (extra)
867 tcg_gen_addi_i32(var, var, extra);
868 rm = (insn) & 0xf;
869 offset = load_reg(s, rm);
870 if (!(insn & (1 << 23)))
871 tcg_gen_sub_i32(var, var, offset);
872 else
873 tcg_gen_add_i32(var, var, offset);
874 tcg_temp_free_i32(offset);
878 #define VFP_OP2(name) \
879 static inline void gen_vfp_##name(int dp) \
881 if (dp) \
882 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
883 else \
884 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
887 VFP_OP2(add)
888 VFP_OP2(sub)
889 VFP_OP2(mul)
890 VFP_OP2(div)
892 #undef VFP_OP2
894 static inline void gen_vfp_abs(int dp)
896 if (dp)
897 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
898 else
899 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
902 static inline void gen_vfp_neg(int dp)
904 if (dp)
905 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
906 else
907 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
910 static inline void gen_vfp_sqrt(int dp)
912 if (dp)
913 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
914 else
915 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
918 static inline void gen_vfp_cmp(int dp)
920 if (dp)
921 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
922 else
923 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
926 static inline void gen_vfp_cmpe(int dp)
928 if (dp)
929 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
930 else
931 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
934 static inline void gen_vfp_F1_ld0(int dp)
936 if (dp)
937 tcg_gen_movi_i64(cpu_F1d, 0);
938 else
939 tcg_gen_movi_i32(cpu_F1s, 0);
942 static inline void gen_vfp_uito(int dp)
944 if (dp)
945 gen_helper_vfp_uitod(cpu_F0d, cpu_F0s, cpu_env);
946 else
947 gen_helper_vfp_uitos(cpu_F0s, cpu_F0s, cpu_env);
950 static inline void gen_vfp_sito(int dp)
952 if (dp)
953 gen_helper_vfp_sitod(cpu_F0d, cpu_F0s, cpu_env);
954 else
955 gen_helper_vfp_sitos(cpu_F0s, cpu_F0s, cpu_env);
958 static inline void gen_vfp_toui(int dp)
960 if (dp)
961 gen_helper_vfp_touid(cpu_F0s, cpu_F0d, cpu_env);
962 else
963 gen_helper_vfp_touis(cpu_F0s, cpu_F0s, cpu_env);
966 static inline void gen_vfp_touiz(int dp)
968 if (dp)
969 gen_helper_vfp_touizd(cpu_F0s, cpu_F0d, cpu_env);
970 else
971 gen_helper_vfp_touizs(cpu_F0s, cpu_F0s, cpu_env);
974 static inline void gen_vfp_tosi(int dp)
976 if (dp)
977 gen_helper_vfp_tosid(cpu_F0s, cpu_F0d, cpu_env);
978 else
979 gen_helper_vfp_tosis(cpu_F0s, cpu_F0s, cpu_env);
982 static inline void gen_vfp_tosiz(int dp)
984 if (dp)
985 gen_helper_vfp_tosizd(cpu_F0s, cpu_F0d, cpu_env);
986 else
987 gen_helper_vfp_tosizs(cpu_F0s, cpu_F0s, cpu_env);
990 #define VFP_GEN_FIX(name) \
991 static inline void gen_vfp_##name(int dp, int shift) \
993 TCGv tmp_shift = tcg_const_i32(shift); \
994 if (dp) \
995 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, cpu_env);\
996 else \
997 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, cpu_env);\
998 tcg_temp_free_i32(tmp_shift); \
1000 VFP_GEN_FIX(tosh)
1001 VFP_GEN_FIX(tosl)
1002 VFP_GEN_FIX(touh)
1003 VFP_GEN_FIX(toul)
1004 VFP_GEN_FIX(shto)
1005 VFP_GEN_FIX(slto)
1006 VFP_GEN_FIX(uhto)
1007 VFP_GEN_FIX(ulto)
1008 #undef VFP_GEN_FIX
1010 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv addr)
1012 if (dp)
1013 tcg_gen_qemu_ld64(cpu_F0d, addr, IS_USER(s));
1014 else
1015 tcg_gen_qemu_ld32u(cpu_F0s, addr, IS_USER(s));
1018 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv addr)
1020 if (dp)
1021 tcg_gen_qemu_st64(cpu_F0d, addr, IS_USER(s));
1022 else
1023 tcg_gen_qemu_st32(cpu_F0s, addr, IS_USER(s));
1026 static inline long
1027 vfp_reg_offset (int dp, int reg)
1029 if (dp)
1030 return offsetof(CPUARMState, vfp.regs[reg]);
1031 else if (reg & 1) {
1032 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1033 + offsetof(CPU_DoubleU, l.upper);
1034 } else {
1035 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1036 + offsetof(CPU_DoubleU, l.lower);
1040 /* Return the offset of a 32-bit piece of a NEON register.
1041 zero is the least significant end of the register. */
1042 static inline long
1043 neon_reg_offset (int reg, int n)
1045 int sreg;
1046 sreg = reg * 2 + n;
1047 return vfp_reg_offset(0, sreg);
1050 static TCGv neon_load_reg(int reg, int pass)
1052 TCGv tmp = tcg_temp_new_i32();
1053 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1054 return tmp;
1057 static void neon_store_reg(int reg, int pass, TCGv var)
1059 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1060 tcg_temp_free_i32(var);
1063 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1065 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1068 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1070 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1073 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1074 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1075 #define tcg_gen_st_f32 tcg_gen_st_i32
1076 #define tcg_gen_st_f64 tcg_gen_st_i64
1078 static inline void gen_mov_F0_vreg(int dp, int reg)
1080 if (dp)
1081 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1082 else
1083 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1086 static inline void gen_mov_F1_vreg(int dp, int reg)
1088 if (dp)
1089 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1090 else
1091 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1094 static inline void gen_mov_vreg_F0(int dp, int reg)
1096 if (dp)
1097 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1098 else
1099 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1102 #define ARM_CP_RW_BIT (1 << 20)
1104 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1106 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1109 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1111 tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1114 static inline TCGv iwmmxt_load_creg(int reg)
1116 TCGv var = tcg_temp_new_i32();
1117 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1118 return var;
1121 static inline void iwmmxt_store_creg(int reg, TCGv var)
1123 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1124 tcg_temp_free_i32(var);
1127 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1129 iwmmxt_store_reg(cpu_M0, rn);
1132 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1134 iwmmxt_load_reg(cpu_M0, rn);
1137 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1139 iwmmxt_load_reg(cpu_V1, rn);
1140 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1143 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1145 iwmmxt_load_reg(cpu_V1, rn);
1146 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1149 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1151 iwmmxt_load_reg(cpu_V1, rn);
1152 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1155 #define IWMMXT_OP(name) \
1156 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1158 iwmmxt_load_reg(cpu_V1, rn); \
1159 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1162 #define IWMMXT_OP_ENV(name) \
1163 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1165 iwmmxt_load_reg(cpu_V1, rn); \
1166 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1169 #define IWMMXT_OP_ENV_SIZE(name) \
1170 IWMMXT_OP_ENV(name##b) \
1171 IWMMXT_OP_ENV(name##w) \
1172 IWMMXT_OP_ENV(name##l)
1174 #define IWMMXT_OP_ENV1(name) \
1175 static inline void gen_op_iwmmxt_##name##_M0(void) \
1177 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1180 IWMMXT_OP(maddsq)
1181 IWMMXT_OP(madduq)
1182 IWMMXT_OP(sadb)
1183 IWMMXT_OP(sadw)
1184 IWMMXT_OP(mulslw)
1185 IWMMXT_OP(mulshw)
1186 IWMMXT_OP(mululw)
1187 IWMMXT_OP(muluhw)
1188 IWMMXT_OP(macsw)
1189 IWMMXT_OP(macuw)
1191 IWMMXT_OP_ENV_SIZE(unpackl)
1192 IWMMXT_OP_ENV_SIZE(unpackh)
1194 IWMMXT_OP_ENV1(unpacklub)
1195 IWMMXT_OP_ENV1(unpackluw)
1196 IWMMXT_OP_ENV1(unpacklul)
1197 IWMMXT_OP_ENV1(unpackhub)
1198 IWMMXT_OP_ENV1(unpackhuw)
1199 IWMMXT_OP_ENV1(unpackhul)
1200 IWMMXT_OP_ENV1(unpacklsb)
1201 IWMMXT_OP_ENV1(unpacklsw)
1202 IWMMXT_OP_ENV1(unpacklsl)
1203 IWMMXT_OP_ENV1(unpackhsb)
1204 IWMMXT_OP_ENV1(unpackhsw)
1205 IWMMXT_OP_ENV1(unpackhsl)
1207 IWMMXT_OP_ENV_SIZE(cmpeq)
1208 IWMMXT_OP_ENV_SIZE(cmpgtu)
1209 IWMMXT_OP_ENV_SIZE(cmpgts)
1211 IWMMXT_OP_ENV_SIZE(mins)
1212 IWMMXT_OP_ENV_SIZE(minu)
1213 IWMMXT_OP_ENV_SIZE(maxs)
1214 IWMMXT_OP_ENV_SIZE(maxu)
1216 IWMMXT_OP_ENV_SIZE(subn)
1217 IWMMXT_OP_ENV_SIZE(addn)
1218 IWMMXT_OP_ENV_SIZE(subu)
1219 IWMMXT_OP_ENV_SIZE(addu)
1220 IWMMXT_OP_ENV_SIZE(subs)
1221 IWMMXT_OP_ENV_SIZE(adds)
1223 IWMMXT_OP_ENV(avgb0)
1224 IWMMXT_OP_ENV(avgb1)
1225 IWMMXT_OP_ENV(avgw0)
1226 IWMMXT_OP_ENV(avgw1)
1228 IWMMXT_OP(msadb)
1230 IWMMXT_OP_ENV(packuw)
1231 IWMMXT_OP_ENV(packul)
1232 IWMMXT_OP_ENV(packuq)
1233 IWMMXT_OP_ENV(packsw)
1234 IWMMXT_OP_ENV(packsl)
1235 IWMMXT_OP_ENV(packsq)
1237 static void gen_op_iwmmxt_set_mup(void)
1239 TCGv tmp;
1240 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1241 tcg_gen_ori_i32(tmp, tmp, 2);
1242 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1245 static void gen_op_iwmmxt_set_cup(void)
1247 TCGv tmp;
1248 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1249 tcg_gen_ori_i32(tmp, tmp, 1);
1250 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1253 static void gen_op_iwmmxt_setpsr_nz(void)
1255 TCGv tmp = tcg_temp_new_i32();
1256 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1257 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1260 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1262 iwmmxt_load_reg(cpu_V1, rn);
1263 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1264 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1267 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn, TCGv dest)
1269 int rd;
1270 uint32_t offset;
1271 TCGv tmp;
1273 rd = (insn >> 16) & 0xf;
1274 tmp = load_reg(s, rd);
1276 offset = (insn & 0xff) << ((insn >> 7) & 2);
1277 if (insn & (1 << 24)) {
1278 /* Pre indexed */
1279 if (insn & (1 << 23))
1280 tcg_gen_addi_i32(tmp, tmp, offset);
1281 else
1282 tcg_gen_addi_i32(tmp, tmp, -offset);
1283 tcg_gen_mov_i32(dest, tmp);
1284 if (insn & (1 << 21))
1285 store_reg(s, rd, tmp);
1286 else
1287 tcg_temp_free_i32(tmp);
1288 } else if (insn & (1 << 21)) {
1289 /* Post indexed */
1290 tcg_gen_mov_i32(dest, tmp);
1291 if (insn & (1 << 23))
1292 tcg_gen_addi_i32(tmp, tmp, offset);
1293 else
1294 tcg_gen_addi_i32(tmp, tmp, -offset);
1295 store_reg(s, rd, tmp);
1296 } else if (!(insn & (1 << 23)))
1297 return 1;
1298 return 0;
1301 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv dest)
1303 int rd = (insn >> 0) & 0xf;
1304 TCGv tmp;
1306 if (insn & (1 << 8)) {
1307 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1308 return 1;
1309 } else {
1310 tmp = iwmmxt_load_creg(rd);
1312 } else {
1313 tmp = tcg_temp_new_i32();
1314 iwmmxt_load_reg(cpu_V0, rd);
1315 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
1317 tcg_gen_andi_i32(tmp, tmp, mask);
1318 tcg_gen_mov_i32(dest, tmp);
1319 tcg_temp_free_i32(tmp);
1320 return 0;
1323 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1324 (ie. an undefined instruction). */
1325 static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1327 int rd, wrd;
1328 int rdhi, rdlo, rd0, rd1, i;
1329 TCGv addr;
1330 TCGv tmp, tmp2, tmp3;
1332 if ((insn & 0x0e000e00) == 0x0c000000) {
1333 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1334 wrd = insn & 0xf;
1335 rdlo = (insn >> 12) & 0xf;
1336 rdhi = (insn >> 16) & 0xf;
1337 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1338 iwmmxt_load_reg(cpu_V0, wrd);
1339 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
1340 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1341 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
1342 } else { /* TMCRR */
1343 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1344 iwmmxt_store_reg(cpu_V0, wrd);
1345 gen_op_iwmmxt_set_mup();
1347 return 0;
1350 wrd = (insn >> 12) & 0xf;
1351 addr = tcg_temp_new_i32();
1352 if (gen_iwmmxt_address(s, insn, addr)) {
1353 tcg_temp_free_i32(addr);
1354 return 1;
1356 if (insn & ARM_CP_RW_BIT) {
1357 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1358 tmp = tcg_temp_new_i32();
1359 tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s));
1360 iwmmxt_store_creg(wrd, tmp);
1361 } else {
1362 i = 1;
1363 if (insn & (1 << 8)) {
1364 if (insn & (1 << 22)) { /* WLDRD */
1365 tcg_gen_qemu_ld64(cpu_M0, addr, IS_USER(s));
1366 i = 0;
1367 } else { /* WLDRW wRd */
1368 tmp = gen_ld32(addr, IS_USER(s));
1370 } else {
1371 if (insn & (1 << 22)) { /* WLDRH */
1372 tmp = gen_ld16u(addr, IS_USER(s));
1373 } else { /* WLDRB */
1374 tmp = gen_ld8u(addr, IS_USER(s));
1377 if (i) {
1378 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1379 tcg_temp_free_i32(tmp);
1381 gen_op_iwmmxt_movq_wRn_M0(wrd);
1383 } else {
1384 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1385 tmp = iwmmxt_load_creg(wrd);
1386 gen_st32(tmp, addr, IS_USER(s));
1387 } else {
1388 gen_op_iwmmxt_movq_M0_wRn(wrd);
1389 tmp = tcg_temp_new_i32();
1390 if (insn & (1 << 8)) {
1391 if (insn & (1 << 22)) { /* WSTRD */
1392 tcg_temp_free_i32(tmp);
1393 tcg_gen_qemu_st64(cpu_M0, addr, IS_USER(s));
1394 } else { /* WSTRW wRd */
1395 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1396 gen_st32(tmp, addr, IS_USER(s));
1398 } else {
1399 if (insn & (1 << 22)) { /* WSTRH */
1400 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1401 gen_st16(tmp, addr, IS_USER(s));
1402 } else { /* WSTRB */
1403 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1404 gen_st8(tmp, addr, IS_USER(s));
1409 tcg_temp_free_i32(addr);
1410 return 0;
1413 if ((insn & 0x0f000000) != 0x0e000000)
1414 return 1;
1416 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1417 case 0x000: /* WOR */
1418 wrd = (insn >> 12) & 0xf;
1419 rd0 = (insn >> 0) & 0xf;
1420 rd1 = (insn >> 16) & 0xf;
1421 gen_op_iwmmxt_movq_M0_wRn(rd0);
1422 gen_op_iwmmxt_orq_M0_wRn(rd1);
1423 gen_op_iwmmxt_setpsr_nz();
1424 gen_op_iwmmxt_movq_wRn_M0(wrd);
1425 gen_op_iwmmxt_set_mup();
1426 gen_op_iwmmxt_set_cup();
1427 break;
1428 case 0x011: /* TMCR */
1429 if (insn & 0xf)
1430 return 1;
1431 rd = (insn >> 12) & 0xf;
1432 wrd = (insn >> 16) & 0xf;
1433 switch (wrd) {
1434 case ARM_IWMMXT_wCID:
1435 case ARM_IWMMXT_wCASF:
1436 break;
1437 case ARM_IWMMXT_wCon:
1438 gen_op_iwmmxt_set_cup();
1439 /* Fall through. */
1440 case ARM_IWMMXT_wCSSF:
1441 tmp = iwmmxt_load_creg(wrd);
1442 tmp2 = load_reg(s, rd);
1443 tcg_gen_andc_i32(tmp, tmp, tmp2);
1444 tcg_temp_free_i32(tmp2);
1445 iwmmxt_store_creg(wrd, tmp);
1446 break;
1447 case ARM_IWMMXT_wCGR0:
1448 case ARM_IWMMXT_wCGR1:
1449 case ARM_IWMMXT_wCGR2:
1450 case ARM_IWMMXT_wCGR3:
1451 gen_op_iwmmxt_set_cup();
1452 tmp = load_reg(s, rd);
1453 iwmmxt_store_creg(wrd, tmp);
1454 break;
1455 default:
1456 return 1;
1458 break;
1459 case 0x100: /* WXOR */
1460 wrd = (insn >> 12) & 0xf;
1461 rd0 = (insn >> 0) & 0xf;
1462 rd1 = (insn >> 16) & 0xf;
1463 gen_op_iwmmxt_movq_M0_wRn(rd0);
1464 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1465 gen_op_iwmmxt_setpsr_nz();
1466 gen_op_iwmmxt_movq_wRn_M0(wrd);
1467 gen_op_iwmmxt_set_mup();
1468 gen_op_iwmmxt_set_cup();
1469 break;
1470 case 0x111: /* TMRC */
1471 if (insn & 0xf)
1472 return 1;
1473 rd = (insn >> 12) & 0xf;
1474 wrd = (insn >> 16) & 0xf;
1475 tmp = iwmmxt_load_creg(wrd);
1476 store_reg(s, rd, tmp);
1477 break;
1478 case 0x300: /* WANDN */
1479 wrd = (insn >> 12) & 0xf;
1480 rd0 = (insn >> 0) & 0xf;
1481 rd1 = (insn >> 16) & 0xf;
1482 gen_op_iwmmxt_movq_M0_wRn(rd0);
1483 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1484 gen_op_iwmmxt_andq_M0_wRn(rd1);
1485 gen_op_iwmmxt_setpsr_nz();
1486 gen_op_iwmmxt_movq_wRn_M0(wrd);
1487 gen_op_iwmmxt_set_mup();
1488 gen_op_iwmmxt_set_cup();
1489 break;
1490 case 0x200: /* WAND */
1491 wrd = (insn >> 12) & 0xf;
1492 rd0 = (insn >> 0) & 0xf;
1493 rd1 = (insn >> 16) & 0xf;
1494 gen_op_iwmmxt_movq_M0_wRn(rd0);
1495 gen_op_iwmmxt_andq_M0_wRn(rd1);
1496 gen_op_iwmmxt_setpsr_nz();
1497 gen_op_iwmmxt_movq_wRn_M0(wrd);
1498 gen_op_iwmmxt_set_mup();
1499 gen_op_iwmmxt_set_cup();
1500 break;
1501 case 0x810: case 0xa10: /* WMADD */
1502 wrd = (insn >> 12) & 0xf;
1503 rd0 = (insn >> 0) & 0xf;
1504 rd1 = (insn >> 16) & 0xf;
1505 gen_op_iwmmxt_movq_M0_wRn(rd0);
1506 if (insn & (1 << 21))
1507 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1508 else
1509 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1510 gen_op_iwmmxt_movq_wRn_M0(wrd);
1511 gen_op_iwmmxt_set_mup();
1512 break;
1513 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1514 wrd = (insn >> 12) & 0xf;
1515 rd0 = (insn >> 16) & 0xf;
1516 rd1 = (insn >> 0) & 0xf;
1517 gen_op_iwmmxt_movq_M0_wRn(rd0);
1518 switch ((insn >> 22) & 3) {
1519 case 0:
1520 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1521 break;
1522 case 1:
1523 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1524 break;
1525 case 2:
1526 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1527 break;
1528 case 3:
1529 return 1;
1531 gen_op_iwmmxt_movq_wRn_M0(wrd);
1532 gen_op_iwmmxt_set_mup();
1533 gen_op_iwmmxt_set_cup();
1534 break;
1535 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1536 wrd = (insn >> 12) & 0xf;
1537 rd0 = (insn >> 16) & 0xf;
1538 rd1 = (insn >> 0) & 0xf;
1539 gen_op_iwmmxt_movq_M0_wRn(rd0);
1540 switch ((insn >> 22) & 3) {
1541 case 0:
1542 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1543 break;
1544 case 1:
1545 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1546 break;
1547 case 2:
1548 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1549 break;
1550 case 3:
1551 return 1;
1553 gen_op_iwmmxt_movq_wRn_M0(wrd);
1554 gen_op_iwmmxt_set_mup();
1555 gen_op_iwmmxt_set_cup();
1556 break;
1557 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1558 wrd = (insn >> 12) & 0xf;
1559 rd0 = (insn >> 16) & 0xf;
1560 rd1 = (insn >> 0) & 0xf;
1561 gen_op_iwmmxt_movq_M0_wRn(rd0);
1562 if (insn & (1 << 22))
1563 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1564 else
1565 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1566 if (!(insn & (1 << 20)))
1567 gen_op_iwmmxt_addl_M0_wRn(wrd);
1568 gen_op_iwmmxt_movq_wRn_M0(wrd);
1569 gen_op_iwmmxt_set_mup();
1570 break;
1571 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1572 wrd = (insn >> 12) & 0xf;
1573 rd0 = (insn >> 16) & 0xf;
1574 rd1 = (insn >> 0) & 0xf;
1575 gen_op_iwmmxt_movq_M0_wRn(rd0);
1576 if (insn & (1 << 21)) {
1577 if (insn & (1 << 20))
1578 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1579 else
1580 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1581 } else {
1582 if (insn & (1 << 20))
1583 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1584 else
1585 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1587 gen_op_iwmmxt_movq_wRn_M0(wrd);
1588 gen_op_iwmmxt_set_mup();
1589 break;
1590 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1591 wrd = (insn >> 12) & 0xf;
1592 rd0 = (insn >> 16) & 0xf;
1593 rd1 = (insn >> 0) & 0xf;
1594 gen_op_iwmmxt_movq_M0_wRn(rd0);
1595 if (insn & (1 << 21))
1596 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1597 else
1598 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1599 if (!(insn & (1 << 20))) {
1600 iwmmxt_load_reg(cpu_V1, wrd);
1601 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1603 gen_op_iwmmxt_movq_wRn_M0(wrd);
1604 gen_op_iwmmxt_set_mup();
1605 break;
1606 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1607 wrd = (insn >> 12) & 0xf;
1608 rd0 = (insn >> 16) & 0xf;
1609 rd1 = (insn >> 0) & 0xf;
1610 gen_op_iwmmxt_movq_M0_wRn(rd0);
1611 switch ((insn >> 22) & 3) {
1612 case 0:
1613 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1614 break;
1615 case 1:
1616 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1617 break;
1618 case 2:
1619 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1620 break;
1621 case 3:
1622 return 1;
1624 gen_op_iwmmxt_movq_wRn_M0(wrd);
1625 gen_op_iwmmxt_set_mup();
1626 gen_op_iwmmxt_set_cup();
1627 break;
1628 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1629 wrd = (insn >> 12) & 0xf;
1630 rd0 = (insn >> 16) & 0xf;
1631 rd1 = (insn >> 0) & 0xf;
1632 gen_op_iwmmxt_movq_M0_wRn(rd0);
1633 if (insn & (1 << 22)) {
1634 if (insn & (1 << 20))
1635 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1636 else
1637 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1638 } else {
1639 if (insn & (1 << 20))
1640 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1641 else
1642 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1644 gen_op_iwmmxt_movq_wRn_M0(wrd);
1645 gen_op_iwmmxt_set_mup();
1646 gen_op_iwmmxt_set_cup();
1647 break;
1648 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1649 wrd = (insn >> 12) & 0xf;
1650 rd0 = (insn >> 16) & 0xf;
1651 rd1 = (insn >> 0) & 0xf;
1652 gen_op_iwmmxt_movq_M0_wRn(rd0);
1653 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1654 tcg_gen_andi_i32(tmp, tmp, 7);
1655 iwmmxt_load_reg(cpu_V1, rd1);
1656 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
1657 tcg_temp_free_i32(tmp);
1658 gen_op_iwmmxt_movq_wRn_M0(wrd);
1659 gen_op_iwmmxt_set_mup();
1660 break;
1661 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1662 if (((insn >> 6) & 3) == 3)
1663 return 1;
1664 rd = (insn >> 12) & 0xf;
1665 wrd = (insn >> 16) & 0xf;
1666 tmp = load_reg(s, rd);
1667 gen_op_iwmmxt_movq_M0_wRn(wrd);
1668 switch ((insn >> 6) & 3) {
1669 case 0:
1670 tmp2 = tcg_const_i32(0xff);
1671 tmp3 = tcg_const_i32((insn & 7) << 3);
1672 break;
1673 case 1:
1674 tmp2 = tcg_const_i32(0xffff);
1675 tmp3 = tcg_const_i32((insn & 3) << 4);
1676 break;
1677 case 2:
1678 tmp2 = tcg_const_i32(0xffffffff);
1679 tmp3 = tcg_const_i32((insn & 1) << 5);
1680 break;
1681 default:
1682 TCGV_UNUSED(tmp2);
1683 TCGV_UNUSED(tmp3);
1685 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
1686 tcg_temp_free(tmp3);
1687 tcg_temp_free(tmp2);
1688 tcg_temp_free_i32(tmp);
1689 gen_op_iwmmxt_movq_wRn_M0(wrd);
1690 gen_op_iwmmxt_set_mup();
1691 break;
1692 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1693 rd = (insn >> 12) & 0xf;
1694 wrd = (insn >> 16) & 0xf;
1695 if (rd == 15 || ((insn >> 22) & 3) == 3)
1696 return 1;
1697 gen_op_iwmmxt_movq_M0_wRn(wrd);
1698 tmp = tcg_temp_new_i32();
1699 switch ((insn >> 22) & 3) {
1700 case 0:
1701 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
1702 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1703 if (insn & 8) {
1704 tcg_gen_ext8s_i32(tmp, tmp);
1705 } else {
1706 tcg_gen_andi_i32(tmp, tmp, 0xff);
1708 break;
1709 case 1:
1710 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
1711 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1712 if (insn & 8) {
1713 tcg_gen_ext16s_i32(tmp, tmp);
1714 } else {
1715 tcg_gen_andi_i32(tmp, tmp, 0xffff);
1717 break;
1718 case 2:
1719 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
1720 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1721 break;
1723 store_reg(s, rd, tmp);
1724 break;
1725 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1726 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1727 return 1;
1728 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1729 switch ((insn >> 22) & 3) {
1730 case 0:
1731 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
1732 break;
1733 case 1:
1734 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
1735 break;
1736 case 2:
1737 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
1738 break;
1740 tcg_gen_shli_i32(tmp, tmp, 28);
1741 gen_set_nzcv(tmp);
1742 tcg_temp_free_i32(tmp);
1743 break;
1744 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1745 if (((insn >> 6) & 3) == 3)
1746 return 1;
1747 rd = (insn >> 12) & 0xf;
1748 wrd = (insn >> 16) & 0xf;
1749 tmp = load_reg(s, rd);
1750 switch ((insn >> 6) & 3) {
1751 case 0:
1752 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
1753 break;
1754 case 1:
1755 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
1756 break;
1757 case 2:
1758 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
1759 break;
1761 tcg_temp_free_i32(tmp);
1762 gen_op_iwmmxt_movq_wRn_M0(wrd);
1763 gen_op_iwmmxt_set_mup();
1764 break;
1765 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1766 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1767 return 1;
1768 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1769 tmp2 = tcg_temp_new_i32();
1770 tcg_gen_mov_i32(tmp2, tmp);
1771 switch ((insn >> 22) & 3) {
1772 case 0:
1773 for (i = 0; i < 7; i ++) {
1774 tcg_gen_shli_i32(tmp2, tmp2, 4);
1775 tcg_gen_and_i32(tmp, tmp, tmp2);
1777 break;
1778 case 1:
1779 for (i = 0; i < 3; i ++) {
1780 tcg_gen_shli_i32(tmp2, tmp2, 8);
1781 tcg_gen_and_i32(tmp, tmp, tmp2);
1783 break;
1784 case 2:
1785 tcg_gen_shli_i32(tmp2, tmp2, 16);
1786 tcg_gen_and_i32(tmp, tmp, tmp2);
1787 break;
1789 gen_set_nzcv(tmp);
1790 tcg_temp_free_i32(tmp2);
1791 tcg_temp_free_i32(tmp);
1792 break;
1793 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1794 wrd = (insn >> 12) & 0xf;
1795 rd0 = (insn >> 16) & 0xf;
1796 gen_op_iwmmxt_movq_M0_wRn(rd0);
1797 switch ((insn >> 22) & 3) {
1798 case 0:
1799 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1800 break;
1801 case 1:
1802 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1803 break;
1804 case 2:
1805 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1806 break;
1807 case 3:
1808 return 1;
1810 gen_op_iwmmxt_movq_wRn_M0(wrd);
1811 gen_op_iwmmxt_set_mup();
1812 break;
1813 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1814 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1815 return 1;
1816 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1817 tmp2 = tcg_temp_new_i32();
1818 tcg_gen_mov_i32(tmp2, tmp);
1819 switch ((insn >> 22) & 3) {
1820 case 0:
1821 for (i = 0; i < 7; i ++) {
1822 tcg_gen_shli_i32(tmp2, tmp2, 4);
1823 tcg_gen_or_i32(tmp, tmp, tmp2);
1825 break;
1826 case 1:
1827 for (i = 0; i < 3; i ++) {
1828 tcg_gen_shli_i32(tmp2, tmp2, 8);
1829 tcg_gen_or_i32(tmp, tmp, tmp2);
1831 break;
1832 case 2:
1833 tcg_gen_shli_i32(tmp2, tmp2, 16);
1834 tcg_gen_or_i32(tmp, tmp, tmp2);
1835 break;
1837 gen_set_nzcv(tmp);
1838 tcg_temp_free_i32(tmp2);
1839 tcg_temp_free_i32(tmp);
1840 break;
1841 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1842 rd = (insn >> 12) & 0xf;
1843 rd0 = (insn >> 16) & 0xf;
1844 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
1845 return 1;
1846 gen_op_iwmmxt_movq_M0_wRn(rd0);
1847 tmp = tcg_temp_new_i32();
1848 switch ((insn >> 22) & 3) {
1849 case 0:
1850 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
1851 break;
1852 case 1:
1853 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
1854 break;
1855 case 2:
1856 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
1857 break;
1859 store_reg(s, rd, tmp);
1860 break;
1861 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1862 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1863 wrd = (insn >> 12) & 0xf;
1864 rd0 = (insn >> 16) & 0xf;
1865 rd1 = (insn >> 0) & 0xf;
1866 gen_op_iwmmxt_movq_M0_wRn(rd0);
1867 switch ((insn >> 22) & 3) {
1868 case 0:
1869 if (insn & (1 << 21))
1870 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1871 else
1872 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1873 break;
1874 case 1:
1875 if (insn & (1 << 21))
1876 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1877 else
1878 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
1879 break;
1880 case 2:
1881 if (insn & (1 << 21))
1882 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
1883 else
1884 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
1885 break;
1886 case 3:
1887 return 1;
1889 gen_op_iwmmxt_movq_wRn_M0(wrd);
1890 gen_op_iwmmxt_set_mup();
1891 gen_op_iwmmxt_set_cup();
1892 break;
1893 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1894 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1895 wrd = (insn >> 12) & 0xf;
1896 rd0 = (insn >> 16) & 0xf;
1897 gen_op_iwmmxt_movq_M0_wRn(rd0);
1898 switch ((insn >> 22) & 3) {
1899 case 0:
1900 if (insn & (1 << 21))
1901 gen_op_iwmmxt_unpacklsb_M0();
1902 else
1903 gen_op_iwmmxt_unpacklub_M0();
1904 break;
1905 case 1:
1906 if (insn & (1 << 21))
1907 gen_op_iwmmxt_unpacklsw_M0();
1908 else
1909 gen_op_iwmmxt_unpackluw_M0();
1910 break;
1911 case 2:
1912 if (insn & (1 << 21))
1913 gen_op_iwmmxt_unpacklsl_M0();
1914 else
1915 gen_op_iwmmxt_unpacklul_M0();
1916 break;
1917 case 3:
1918 return 1;
1920 gen_op_iwmmxt_movq_wRn_M0(wrd);
1921 gen_op_iwmmxt_set_mup();
1922 gen_op_iwmmxt_set_cup();
1923 break;
1924 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
1925 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1926 wrd = (insn >> 12) & 0xf;
1927 rd0 = (insn >> 16) & 0xf;
1928 gen_op_iwmmxt_movq_M0_wRn(rd0);
1929 switch ((insn >> 22) & 3) {
1930 case 0:
1931 if (insn & (1 << 21))
1932 gen_op_iwmmxt_unpackhsb_M0();
1933 else
1934 gen_op_iwmmxt_unpackhub_M0();
1935 break;
1936 case 1:
1937 if (insn & (1 << 21))
1938 gen_op_iwmmxt_unpackhsw_M0();
1939 else
1940 gen_op_iwmmxt_unpackhuw_M0();
1941 break;
1942 case 2:
1943 if (insn & (1 << 21))
1944 gen_op_iwmmxt_unpackhsl_M0();
1945 else
1946 gen_op_iwmmxt_unpackhul_M0();
1947 break;
1948 case 3:
1949 return 1;
1951 gen_op_iwmmxt_movq_wRn_M0(wrd);
1952 gen_op_iwmmxt_set_mup();
1953 gen_op_iwmmxt_set_cup();
1954 break;
1955 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
1956 case 0x214: case 0x614: case 0xa14: case 0xe14:
1957 if (((insn >> 22) & 3) == 0)
1958 return 1;
1959 wrd = (insn >> 12) & 0xf;
1960 rd0 = (insn >> 16) & 0xf;
1961 gen_op_iwmmxt_movq_M0_wRn(rd0);
1962 tmp = tcg_temp_new_i32();
1963 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
1964 tcg_temp_free_i32(tmp);
1965 return 1;
1967 switch ((insn >> 22) & 3) {
1968 case 1:
1969 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
1970 break;
1971 case 2:
1972 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
1973 break;
1974 case 3:
1975 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
1976 break;
1978 tcg_temp_free_i32(tmp);
1979 gen_op_iwmmxt_movq_wRn_M0(wrd);
1980 gen_op_iwmmxt_set_mup();
1981 gen_op_iwmmxt_set_cup();
1982 break;
1983 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
1984 case 0x014: case 0x414: case 0x814: case 0xc14:
1985 if (((insn >> 22) & 3) == 0)
1986 return 1;
1987 wrd = (insn >> 12) & 0xf;
1988 rd0 = (insn >> 16) & 0xf;
1989 gen_op_iwmmxt_movq_M0_wRn(rd0);
1990 tmp = tcg_temp_new_i32();
1991 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
1992 tcg_temp_free_i32(tmp);
1993 return 1;
1995 switch ((insn >> 22) & 3) {
1996 case 1:
1997 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
1998 break;
1999 case 2:
2000 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2001 break;
2002 case 3:
2003 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2004 break;
2006 tcg_temp_free_i32(tmp);
2007 gen_op_iwmmxt_movq_wRn_M0(wrd);
2008 gen_op_iwmmxt_set_mup();
2009 gen_op_iwmmxt_set_cup();
2010 break;
2011 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2012 case 0x114: case 0x514: case 0x914: case 0xd14:
2013 if (((insn >> 22) & 3) == 0)
2014 return 1;
2015 wrd = (insn >> 12) & 0xf;
2016 rd0 = (insn >> 16) & 0xf;
2017 gen_op_iwmmxt_movq_M0_wRn(rd0);
2018 tmp = tcg_temp_new_i32();
2019 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2020 tcg_temp_free_i32(tmp);
2021 return 1;
2023 switch ((insn >> 22) & 3) {
2024 case 1:
2025 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2026 break;
2027 case 2:
2028 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2029 break;
2030 case 3:
2031 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2032 break;
2034 tcg_temp_free_i32(tmp);
2035 gen_op_iwmmxt_movq_wRn_M0(wrd);
2036 gen_op_iwmmxt_set_mup();
2037 gen_op_iwmmxt_set_cup();
2038 break;
2039 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2040 case 0x314: case 0x714: case 0xb14: case 0xf14:
2041 if (((insn >> 22) & 3) == 0)
2042 return 1;
2043 wrd = (insn >> 12) & 0xf;
2044 rd0 = (insn >> 16) & 0xf;
2045 gen_op_iwmmxt_movq_M0_wRn(rd0);
2046 tmp = tcg_temp_new_i32();
2047 switch ((insn >> 22) & 3) {
2048 case 1:
2049 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2050 tcg_temp_free_i32(tmp);
2051 return 1;
2053 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2054 break;
2055 case 2:
2056 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2057 tcg_temp_free_i32(tmp);
2058 return 1;
2060 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2061 break;
2062 case 3:
2063 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2064 tcg_temp_free_i32(tmp);
2065 return 1;
2067 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2068 break;
2070 tcg_temp_free_i32(tmp);
2071 gen_op_iwmmxt_movq_wRn_M0(wrd);
2072 gen_op_iwmmxt_set_mup();
2073 gen_op_iwmmxt_set_cup();
2074 break;
2075 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2076 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2077 wrd = (insn >> 12) & 0xf;
2078 rd0 = (insn >> 16) & 0xf;
2079 rd1 = (insn >> 0) & 0xf;
2080 gen_op_iwmmxt_movq_M0_wRn(rd0);
2081 switch ((insn >> 22) & 3) {
2082 case 0:
2083 if (insn & (1 << 21))
2084 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2085 else
2086 gen_op_iwmmxt_minub_M0_wRn(rd1);
2087 break;
2088 case 1:
2089 if (insn & (1 << 21))
2090 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2091 else
2092 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2093 break;
2094 case 2:
2095 if (insn & (1 << 21))
2096 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2097 else
2098 gen_op_iwmmxt_minul_M0_wRn(rd1);
2099 break;
2100 case 3:
2101 return 1;
2103 gen_op_iwmmxt_movq_wRn_M0(wrd);
2104 gen_op_iwmmxt_set_mup();
2105 break;
2106 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2107 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2108 wrd = (insn >> 12) & 0xf;
2109 rd0 = (insn >> 16) & 0xf;
2110 rd1 = (insn >> 0) & 0xf;
2111 gen_op_iwmmxt_movq_M0_wRn(rd0);
2112 switch ((insn >> 22) & 3) {
2113 case 0:
2114 if (insn & (1 << 21))
2115 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2116 else
2117 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2118 break;
2119 case 1:
2120 if (insn & (1 << 21))
2121 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2122 else
2123 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2124 break;
2125 case 2:
2126 if (insn & (1 << 21))
2127 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2128 else
2129 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2130 break;
2131 case 3:
2132 return 1;
2134 gen_op_iwmmxt_movq_wRn_M0(wrd);
2135 gen_op_iwmmxt_set_mup();
2136 break;
2137 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2138 case 0x402: case 0x502: case 0x602: case 0x702:
2139 wrd = (insn >> 12) & 0xf;
2140 rd0 = (insn >> 16) & 0xf;
2141 rd1 = (insn >> 0) & 0xf;
2142 gen_op_iwmmxt_movq_M0_wRn(rd0);
2143 tmp = tcg_const_i32((insn >> 20) & 3);
2144 iwmmxt_load_reg(cpu_V1, rd1);
2145 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2146 tcg_temp_free(tmp);
2147 gen_op_iwmmxt_movq_wRn_M0(wrd);
2148 gen_op_iwmmxt_set_mup();
2149 break;
2150 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2151 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2152 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2153 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2154 wrd = (insn >> 12) & 0xf;
2155 rd0 = (insn >> 16) & 0xf;
2156 rd1 = (insn >> 0) & 0xf;
2157 gen_op_iwmmxt_movq_M0_wRn(rd0);
2158 switch ((insn >> 20) & 0xf) {
2159 case 0x0:
2160 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2161 break;
2162 case 0x1:
2163 gen_op_iwmmxt_subub_M0_wRn(rd1);
2164 break;
2165 case 0x3:
2166 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2167 break;
2168 case 0x4:
2169 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2170 break;
2171 case 0x5:
2172 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2173 break;
2174 case 0x7:
2175 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2176 break;
2177 case 0x8:
2178 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2179 break;
2180 case 0x9:
2181 gen_op_iwmmxt_subul_M0_wRn(rd1);
2182 break;
2183 case 0xb:
2184 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2185 break;
2186 default:
2187 return 1;
2189 gen_op_iwmmxt_movq_wRn_M0(wrd);
2190 gen_op_iwmmxt_set_mup();
2191 gen_op_iwmmxt_set_cup();
2192 break;
2193 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2194 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2195 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2196 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2197 wrd = (insn >> 12) & 0xf;
2198 rd0 = (insn >> 16) & 0xf;
2199 gen_op_iwmmxt_movq_M0_wRn(rd0);
2200 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2201 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2202 tcg_temp_free(tmp);
2203 gen_op_iwmmxt_movq_wRn_M0(wrd);
2204 gen_op_iwmmxt_set_mup();
2205 gen_op_iwmmxt_set_cup();
2206 break;
2207 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2208 case 0x418: case 0x518: case 0x618: case 0x718:
2209 case 0x818: case 0x918: case 0xa18: case 0xb18:
2210 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2211 wrd = (insn >> 12) & 0xf;
2212 rd0 = (insn >> 16) & 0xf;
2213 rd1 = (insn >> 0) & 0xf;
2214 gen_op_iwmmxt_movq_M0_wRn(rd0);
2215 switch ((insn >> 20) & 0xf) {
2216 case 0x0:
2217 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2218 break;
2219 case 0x1:
2220 gen_op_iwmmxt_addub_M0_wRn(rd1);
2221 break;
2222 case 0x3:
2223 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2224 break;
2225 case 0x4:
2226 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2227 break;
2228 case 0x5:
2229 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2230 break;
2231 case 0x7:
2232 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2233 break;
2234 case 0x8:
2235 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2236 break;
2237 case 0x9:
2238 gen_op_iwmmxt_addul_M0_wRn(rd1);
2239 break;
2240 case 0xb:
2241 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2242 break;
2243 default:
2244 return 1;
2246 gen_op_iwmmxt_movq_wRn_M0(wrd);
2247 gen_op_iwmmxt_set_mup();
2248 gen_op_iwmmxt_set_cup();
2249 break;
2250 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2251 case 0x408: case 0x508: case 0x608: case 0x708:
2252 case 0x808: case 0x908: case 0xa08: case 0xb08:
2253 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2254 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2255 return 1;
2256 wrd = (insn >> 12) & 0xf;
2257 rd0 = (insn >> 16) & 0xf;
2258 rd1 = (insn >> 0) & 0xf;
2259 gen_op_iwmmxt_movq_M0_wRn(rd0);
2260 switch ((insn >> 22) & 3) {
2261 case 1:
2262 if (insn & (1 << 21))
2263 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2264 else
2265 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2266 break;
2267 case 2:
2268 if (insn & (1 << 21))
2269 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2270 else
2271 gen_op_iwmmxt_packul_M0_wRn(rd1);
2272 break;
2273 case 3:
2274 if (insn & (1 << 21))
2275 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2276 else
2277 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2278 break;
2280 gen_op_iwmmxt_movq_wRn_M0(wrd);
2281 gen_op_iwmmxt_set_mup();
2282 gen_op_iwmmxt_set_cup();
2283 break;
2284 case 0x201: case 0x203: case 0x205: case 0x207:
2285 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2286 case 0x211: case 0x213: case 0x215: case 0x217:
2287 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2288 wrd = (insn >> 5) & 0xf;
2289 rd0 = (insn >> 12) & 0xf;
2290 rd1 = (insn >> 0) & 0xf;
2291 if (rd0 == 0xf || rd1 == 0xf)
2292 return 1;
2293 gen_op_iwmmxt_movq_M0_wRn(wrd);
2294 tmp = load_reg(s, rd0);
2295 tmp2 = load_reg(s, rd1);
2296 switch ((insn >> 16) & 0xf) {
2297 case 0x0: /* TMIA */
2298 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2299 break;
2300 case 0x8: /* TMIAPH */
2301 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2302 break;
2303 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2304 if (insn & (1 << 16))
2305 tcg_gen_shri_i32(tmp, tmp, 16);
2306 if (insn & (1 << 17))
2307 tcg_gen_shri_i32(tmp2, tmp2, 16);
2308 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2309 break;
2310 default:
2311 tcg_temp_free_i32(tmp2);
2312 tcg_temp_free_i32(tmp);
2313 return 1;
2315 tcg_temp_free_i32(tmp2);
2316 tcg_temp_free_i32(tmp);
2317 gen_op_iwmmxt_movq_wRn_M0(wrd);
2318 gen_op_iwmmxt_set_mup();
2319 break;
2320 default:
2321 return 1;
2324 return 0;
2327 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2328 (ie. an undefined instruction). */
2329 static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2331 int acc, rd0, rd1, rdhi, rdlo;
2332 TCGv tmp, tmp2;
2334 if ((insn & 0x0ff00f10) == 0x0e200010) {
2335 /* Multiply with Internal Accumulate Format */
2336 rd0 = (insn >> 12) & 0xf;
2337 rd1 = insn & 0xf;
2338 acc = (insn >> 5) & 7;
2340 if (acc != 0)
2341 return 1;
2343 tmp = load_reg(s, rd0);
2344 tmp2 = load_reg(s, rd1);
2345 switch ((insn >> 16) & 0xf) {
2346 case 0x0: /* MIA */
2347 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2348 break;
2349 case 0x8: /* MIAPH */
2350 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2351 break;
2352 case 0xc: /* MIABB */
2353 case 0xd: /* MIABT */
2354 case 0xe: /* MIATB */
2355 case 0xf: /* MIATT */
2356 if (insn & (1 << 16))
2357 tcg_gen_shri_i32(tmp, tmp, 16);
2358 if (insn & (1 << 17))
2359 tcg_gen_shri_i32(tmp2, tmp2, 16);
2360 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2361 break;
2362 default:
2363 return 1;
2365 tcg_temp_free_i32(tmp2);
2366 tcg_temp_free_i32(tmp);
2368 gen_op_iwmmxt_movq_wRn_M0(acc);
2369 return 0;
2372 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2373 /* Internal Accumulator Access Format */
2374 rdhi = (insn >> 16) & 0xf;
2375 rdlo = (insn >> 12) & 0xf;
2376 acc = insn & 7;
2378 if (acc != 0)
2379 return 1;
2381 if (insn & ARM_CP_RW_BIT) { /* MRA */
2382 iwmmxt_load_reg(cpu_V0, acc);
2383 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
2384 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
2385 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
2386 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2387 } else { /* MAR */
2388 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2389 iwmmxt_store_reg(cpu_V0, acc);
2391 return 0;
2394 return 1;
2397 /* Disassemble system coprocessor instruction. Return nonzero if
2398 instruction is not defined. */
2399 static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2401 TCGv tmp, tmp2;
2402 uint32_t rd = (insn >> 12) & 0xf;
2403 uint32_t cp = (insn >> 8) & 0xf;
2404 if (IS_USER(s)) {
2405 return 1;
2408 if (insn & ARM_CP_RW_BIT) {
2409 if (!env->cp[cp].cp_read)
2410 return 1;
2411 gen_set_pc_im(s->pc);
2412 tmp = tcg_temp_new_i32();
2413 tmp2 = tcg_const_i32(insn);
2414 gen_helper_get_cp(tmp, cpu_env, tmp2);
2415 tcg_temp_free(tmp2);
2416 store_reg(s, rd, tmp);
2417 } else {
2418 if (!env->cp[cp].cp_write)
2419 return 1;
2420 gen_set_pc_im(s->pc);
2421 tmp = load_reg(s, rd);
2422 tmp2 = tcg_const_i32(insn);
2423 gen_helper_set_cp(cpu_env, tmp2, tmp);
2424 tcg_temp_free(tmp2);
2425 tcg_temp_free_i32(tmp);
2427 return 0;
2430 static int cp15_user_ok(uint32_t insn)
2432 int cpn = (insn >> 16) & 0xf;
2433 int cpm = insn & 0xf;
2434 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2436 if (cpn == 13 && cpm == 0) {
2437 /* TLS register. */
2438 if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2439 return 1;
2441 if (cpn == 7) {
2442 /* ISB, DSB, DMB. */
2443 if ((cpm == 5 && op == 4)
2444 || (cpm == 10 && (op == 4 || op == 5)))
2445 return 1;
2447 return 0;
2450 static int cp15_tls_load_store(CPUState *env, DisasContext *s, uint32_t insn, uint32_t rd)
2452 TCGv tmp;
2453 int cpn = (insn >> 16) & 0xf;
2454 int cpm = insn & 0xf;
2455 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2457 if (!arm_feature(env, ARM_FEATURE_V6K))
2458 return 0;
2460 if (!(cpn == 13 && cpm == 0))
2461 return 0;
2463 if (insn & ARM_CP_RW_BIT) {
2464 switch (op) {
2465 case 2:
2466 tmp = load_cpu_field(cp15.c13_tls1);
2467 break;
2468 case 3:
2469 tmp = load_cpu_field(cp15.c13_tls2);
2470 break;
2471 case 4:
2472 tmp = load_cpu_field(cp15.c13_tls3);
2473 break;
2474 default:
2475 return 0;
2477 store_reg(s, rd, tmp);
2479 } else {
2480 tmp = load_reg(s, rd);
2481 switch (op) {
2482 case 2:
2483 store_cpu_field(tmp, cp15.c13_tls1);
2484 break;
2485 case 3:
2486 store_cpu_field(tmp, cp15.c13_tls2);
2487 break;
2488 case 4:
2489 store_cpu_field(tmp, cp15.c13_tls3);
2490 break;
2491 default:
2492 tcg_temp_free_i32(tmp);
2493 return 0;
2496 return 1;
2499 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2500 instruction is not defined. */
2501 static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2503 uint32_t rd;
2504 TCGv tmp, tmp2;
2506 /* M profile cores use memory mapped registers instead of cp15. */
2507 if (arm_feature(env, ARM_FEATURE_M))
2508 return 1;
2510 if ((insn & (1 << 25)) == 0) {
2511 if (insn & (1 << 20)) {
2512 /* mrrc */
2513 return 1;
2515 /* mcrr. Used for block cache operations, so implement as no-op. */
2516 return 0;
2518 if ((insn & (1 << 4)) == 0) {
2519 /* cdp */
2520 return 1;
2522 if (IS_USER(s) && !cp15_user_ok(insn)) {
2523 return 1;
2526 /* Pre-v7 versions of the architecture implemented WFI via coprocessor
2527 * instructions rather than a separate instruction.
2529 if ((insn & 0x0fff0fff) == 0x0e070f90) {
2530 /* 0,c7,c0,4: Standard v6 WFI (also used in some pre-v6 cores).
2531 * In v7, this must NOP.
2533 if (!arm_feature(env, ARM_FEATURE_V7)) {
2534 /* Wait for interrupt. */
2535 gen_set_pc_im(s->pc);
2536 s->is_jmp = DISAS_WFI;
2538 return 0;
2541 if ((insn & 0x0fff0fff) == 0x0e070f58) {
2542 /* 0,c7,c8,2: Not all pre-v6 cores implemented this WFI,
2543 * so this is slightly over-broad.
2545 if (!arm_feature(env, ARM_FEATURE_V6)) {
2546 /* Wait for interrupt. */
2547 gen_set_pc_im(s->pc);
2548 s->is_jmp = DISAS_WFI;
2549 return 0;
2551 /* Otherwise fall through to handle via helper function.
2552 * In particular, on v7 and some v6 cores this is one of
2553 * the VA-PA registers.
2557 rd = (insn >> 12) & 0xf;
2559 if (cp15_tls_load_store(env, s, insn, rd))
2560 return 0;
2562 tmp2 = tcg_const_i32(insn);
2563 if (insn & ARM_CP_RW_BIT) {
2564 tmp = tcg_temp_new_i32();
2565 gen_helper_get_cp15(tmp, cpu_env, tmp2);
2566 /* If the destination register is r15 then sets condition codes. */
2567 if (rd != 15)
2568 store_reg(s, rd, tmp);
2569 else
2570 tcg_temp_free_i32(tmp);
2571 } else {
2572 tmp = load_reg(s, rd);
2573 gen_helper_set_cp15(cpu_env, tmp2, tmp);
2574 tcg_temp_free_i32(tmp);
2575 /* Normally we would always end the TB here, but Linux
2576 * arch/arm/mach-pxa/sleep.S expects two instructions following
2577 * an MMU enable to execute from cache. Imitate this behaviour. */
2578 if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2579 (insn & 0x0fff0fff) != 0x0e010f10)
2580 gen_lookup_tb(s);
2582 tcg_temp_free_i32(tmp2);
2583 return 0;
2586 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2587 #define VFP_SREG(insn, bigbit, smallbit) \
2588 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2589 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2590 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2591 reg = (((insn) >> (bigbit)) & 0x0f) \
2592 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2593 } else { \
2594 if (insn & (1 << (smallbit))) \
2595 return 1; \
2596 reg = ((insn) >> (bigbit)) & 0x0f; \
2597 }} while (0)
2599 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2600 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2601 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2602 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2603 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2604 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2606 /* Move between integer and VFP cores. */
2607 static TCGv gen_vfp_mrs(void)
2609 TCGv tmp = tcg_temp_new_i32();
2610 tcg_gen_mov_i32(tmp, cpu_F0s);
2611 return tmp;
2614 static void gen_vfp_msr(TCGv tmp)
2616 tcg_gen_mov_i32(cpu_F0s, tmp);
2617 tcg_temp_free_i32(tmp);
2620 static void gen_neon_dup_u8(TCGv var, int shift)
2622 TCGv tmp = tcg_temp_new_i32();
2623 if (shift)
2624 tcg_gen_shri_i32(var, var, shift);
2625 tcg_gen_ext8u_i32(var, var);
2626 tcg_gen_shli_i32(tmp, var, 8);
2627 tcg_gen_or_i32(var, var, tmp);
2628 tcg_gen_shli_i32(tmp, var, 16);
2629 tcg_gen_or_i32(var, var, tmp);
2630 tcg_temp_free_i32(tmp);
2633 static void gen_neon_dup_low16(TCGv var)
2635 TCGv tmp = tcg_temp_new_i32();
2636 tcg_gen_ext16u_i32(var, var);
2637 tcg_gen_shli_i32(tmp, var, 16);
2638 tcg_gen_or_i32(var, var, tmp);
2639 tcg_temp_free_i32(tmp);
2642 static void gen_neon_dup_high16(TCGv var)
2644 TCGv tmp = tcg_temp_new_i32();
2645 tcg_gen_andi_i32(var, var, 0xffff0000);
2646 tcg_gen_shri_i32(tmp, var, 16);
2647 tcg_gen_or_i32(var, var, tmp);
2648 tcg_temp_free_i32(tmp);
2651 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2652 (ie. an undefined instruction). */
2653 static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2655 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2656 int dp, veclen;
2657 TCGv addr;
2658 TCGv tmp;
2659 TCGv tmp2;
2661 if (!arm_feature(env, ARM_FEATURE_VFP))
2662 return 1;
2664 if (!s->vfp_enabled) {
2665 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2666 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2667 return 1;
2668 rn = (insn >> 16) & 0xf;
2669 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2670 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2671 return 1;
2673 dp = ((insn & 0xf00) == 0xb00);
2674 switch ((insn >> 24) & 0xf) {
2675 case 0xe:
2676 if (insn & (1 << 4)) {
2677 /* single register transfer */
2678 rd = (insn >> 12) & 0xf;
2679 if (dp) {
2680 int size;
2681 int pass;
2683 VFP_DREG_N(rn, insn);
2684 if (insn & 0xf)
2685 return 1;
2686 if (insn & 0x00c00060
2687 && !arm_feature(env, ARM_FEATURE_NEON))
2688 return 1;
2690 pass = (insn >> 21) & 1;
2691 if (insn & (1 << 22)) {
2692 size = 0;
2693 offset = ((insn >> 5) & 3) * 8;
2694 } else if (insn & (1 << 5)) {
2695 size = 1;
2696 offset = (insn & (1 << 6)) ? 16 : 0;
2697 } else {
2698 size = 2;
2699 offset = 0;
2701 if (insn & ARM_CP_RW_BIT) {
2702 /* vfp->arm */
2703 tmp = neon_load_reg(rn, pass);
2704 switch (size) {
2705 case 0:
2706 if (offset)
2707 tcg_gen_shri_i32(tmp, tmp, offset);
2708 if (insn & (1 << 23))
2709 gen_uxtb(tmp);
2710 else
2711 gen_sxtb(tmp);
2712 break;
2713 case 1:
2714 if (insn & (1 << 23)) {
2715 if (offset) {
2716 tcg_gen_shri_i32(tmp, tmp, 16);
2717 } else {
2718 gen_uxth(tmp);
2720 } else {
2721 if (offset) {
2722 tcg_gen_sari_i32(tmp, tmp, 16);
2723 } else {
2724 gen_sxth(tmp);
2727 break;
2728 case 2:
2729 break;
2731 store_reg(s, rd, tmp);
2732 } else {
2733 /* arm->vfp */
2734 tmp = load_reg(s, rd);
2735 if (insn & (1 << 23)) {
2736 /* VDUP */
2737 if (size == 0) {
2738 gen_neon_dup_u8(tmp, 0);
2739 } else if (size == 1) {
2740 gen_neon_dup_low16(tmp);
2742 for (n = 0; n <= pass * 2; n++) {
2743 tmp2 = tcg_temp_new_i32();
2744 tcg_gen_mov_i32(tmp2, tmp);
2745 neon_store_reg(rn, n, tmp2);
2747 neon_store_reg(rn, n, tmp);
2748 } else {
2749 /* VMOV */
2750 switch (size) {
2751 case 0:
2752 tmp2 = neon_load_reg(rn, pass);
2753 gen_bfi(tmp, tmp2, tmp, offset, 0xff);
2754 tcg_temp_free_i32(tmp2);
2755 break;
2756 case 1:
2757 tmp2 = neon_load_reg(rn, pass);
2758 gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
2759 tcg_temp_free_i32(tmp2);
2760 break;
2761 case 2:
2762 break;
2764 neon_store_reg(rn, pass, tmp);
2767 } else { /* !dp */
2768 if ((insn & 0x6f) != 0x00)
2769 return 1;
2770 rn = VFP_SREG_N(insn);
2771 if (insn & ARM_CP_RW_BIT) {
2772 /* vfp->arm */
2773 if (insn & (1 << 21)) {
2774 /* system register */
2775 rn >>= 1;
2777 switch (rn) {
2778 case ARM_VFP_FPSID:
2779 /* VFP2 allows access to FSID from userspace.
2780 VFP3 restricts all id registers to privileged
2781 accesses. */
2782 if (IS_USER(s)
2783 && arm_feature(env, ARM_FEATURE_VFP3))
2784 return 1;
2785 tmp = load_cpu_field(vfp.xregs[rn]);
2786 break;
2787 case ARM_VFP_FPEXC:
2788 if (IS_USER(s))
2789 return 1;
2790 tmp = load_cpu_field(vfp.xregs[rn]);
2791 break;
2792 case ARM_VFP_FPINST:
2793 case ARM_VFP_FPINST2:
2794 /* Not present in VFP3. */
2795 if (IS_USER(s)
2796 || arm_feature(env, ARM_FEATURE_VFP3))
2797 return 1;
2798 tmp = load_cpu_field(vfp.xregs[rn]);
2799 break;
2800 case ARM_VFP_FPSCR:
2801 if (rd == 15) {
2802 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2803 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2804 } else {
2805 tmp = tcg_temp_new_i32();
2806 gen_helper_vfp_get_fpscr(tmp, cpu_env);
2808 break;
2809 case ARM_VFP_MVFR0:
2810 case ARM_VFP_MVFR1:
2811 if (IS_USER(s)
2812 || !arm_feature(env, ARM_FEATURE_VFP3))
2813 return 1;
2814 tmp = load_cpu_field(vfp.xregs[rn]);
2815 break;
2816 default:
2817 return 1;
2819 } else {
2820 gen_mov_F0_vreg(0, rn);
2821 tmp = gen_vfp_mrs();
2823 if (rd == 15) {
2824 /* Set the 4 flag bits in the CPSR. */
2825 gen_set_nzcv(tmp);
2826 tcg_temp_free_i32(tmp);
2827 } else {
2828 store_reg(s, rd, tmp);
2830 } else {
2831 /* arm->vfp */
2832 tmp = load_reg(s, rd);
2833 if (insn & (1 << 21)) {
2834 rn >>= 1;
2835 /* system register */
2836 switch (rn) {
2837 case ARM_VFP_FPSID:
2838 case ARM_VFP_MVFR0:
2839 case ARM_VFP_MVFR1:
2840 /* Writes are ignored. */
2841 break;
2842 case ARM_VFP_FPSCR:
2843 gen_helper_vfp_set_fpscr(cpu_env, tmp);
2844 tcg_temp_free_i32(tmp);
2845 gen_lookup_tb(s);
2846 break;
2847 case ARM_VFP_FPEXC:
2848 if (IS_USER(s))
2849 return 1;
2850 /* TODO: VFP subarchitecture support.
2851 * For now, keep the EN bit only */
2852 tcg_gen_andi_i32(tmp, tmp, 1 << 30);
2853 store_cpu_field(tmp, vfp.xregs[rn]);
2854 gen_lookup_tb(s);
2855 break;
2856 case ARM_VFP_FPINST:
2857 case ARM_VFP_FPINST2:
2858 store_cpu_field(tmp, vfp.xregs[rn]);
2859 break;
2860 default:
2861 return 1;
2863 } else {
2864 gen_vfp_msr(tmp);
2865 gen_mov_vreg_F0(0, rn);
2869 } else {
2870 /* data processing */
2871 /* The opcode is in bits 23, 21, 20 and 6. */
2872 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2873 if (dp) {
2874 if (op == 15) {
2875 /* rn is opcode */
2876 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2877 } else {
2878 /* rn is register number */
2879 VFP_DREG_N(rn, insn);
2882 if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18))) {
2883 /* Integer or single precision destination. */
2884 rd = VFP_SREG_D(insn);
2885 } else {
2886 VFP_DREG_D(rd, insn);
2888 if (op == 15 &&
2889 (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14))) {
2890 /* VCVT from int is always from S reg regardless of dp bit.
2891 * VCVT with immediate frac_bits has same format as SREG_M
2893 rm = VFP_SREG_M(insn);
2894 } else {
2895 VFP_DREG_M(rm, insn);
2897 } else {
2898 rn = VFP_SREG_N(insn);
2899 if (op == 15 && rn == 15) {
2900 /* Double precision destination. */
2901 VFP_DREG_D(rd, insn);
2902 } else {
2903 rd = VFP_SREG_D(insn);
2905 /* NB that we implicitly rely on the encoding for the frac_bits
2906 * in VCVT of fixed to float being the same as that of an SREG_M
2908 rm = VFP_SREG_M(insn);
2911 veclen = s->vec_len;
2912 if (op == 15 && rn > 3)
2913 veclen = 0;
2915 /* Shut up compiler warnings. */
2916 delta_m = 0;
2917 delta_d = 0;
2918 bank_mask = 0;
2920 if (veclen > 0) {
2921 if (dp)
2922 bank_mask = 0xc;
2923 else
2924 bank_mask = 0x18;
2926 /* Figure out what type of vector operation this is. */
2927 if ((rd & bank_mask) == 0) {
2928 /* scalar */
2929 veclen = 0;
2930 } else {
2931 if (dp)
2932 delta_d = (s->vec_stride >> 1) + 1;
2933 else
2934 delta_d = s->vec_stride + 1;
2936 if ((rm & bank_mask) == 0) {
2937 /* mixed scalar/vector */
2938 delta_m = 0;
2939 } else {
2940 /* vector */
2941 delta_m = delta_d;
2946 /* Load the initial operands. */
2947 if (op == 15) {
2948 switch (rn) {
2949 case 16:
2950 case 17:
2951 /* Integer source */
2952 gen_mov_F0_vreg(0, rm);
2953 break;
2954 case 8:
2955 case 9:
2956 /* Compare */
2957 gen_mov_F0_vreg(dp, rd);
2958 gen_mov_F1_vreg(dp, rm);
2959 break;
2960 case 10:
2961 case 11:
2962 /* Compare with zero */
2963 gen_mov_F0_vreg(dp, rd);
2964 gen_vfp_F1_ld0(dp);
2965 break;
2966 case 20:
2967 case 21:
2968 case 22:
2969 case 23:
2970 case 28:
2971 case 29:
2972 case 30:
2973 case 31:
2974 /* Source and destination the same. */
2975 gen_mov_F0_vreg(dp, rd);
2976 break;
2977 default:
2978 /* One source operand. */
2979 gen_mov_F0_vreg(dp, rm);
2980 break;
2982 } else {
2983 /* Two source operands. */
2984 gen_mov_F0_vreg(dp, rn);
2985 gen_mov_F1_vreg(dp, rm);
2988 for (;;) {
2989 /* Perform the calculation. */
2990 switch (op) {
2991 case 0: /* mac: fd + (fn * fm) */
2992 gen_vfp_mul(dp);
2993 gen_mov_F1_vreg(dp, rd);
2994 gen_vfp_add(dp);
2995 break;
2996 case 1: /* nmac: fd - (fn * fm) */
2997 gen_vfp_mul(dp);
2998 gen_vfp_neg(dp);
2999 gen_mov_F1_vreg(dp, rd);
3000 gen_vfp_add(dp);
3001 break;
3002 case 2: /* msc: -fd + (fn * fm) */
3003 gen_vfp_mul(dp);
3004 gen_mov_F1_vreg(dp, rd);
3005 gen_vfp_sub(dp);
3006 break;
3007 case 3: /* nmsc: -fd - (fn * fm) */
3008 gen_vfp_mul(dp);
3009 gen_vfp_neg(dp);
3010 gen_mov_F1_vreg(dp, rd);
3011 gen_vfp_sub(dp);
3012 break;
3013 case 4: /* mul: fn * fm */
3014 gen_vfp_mul(dp);
3015 break;
3016 case 5: /* nmul: -(fn * fm) */
3017 gen_vfp_mul(dp);
3018 gen_vfp_neg(dp);
3019 break;
3020 case 6: /* add: fn + fm */
3021 gen_vfp_add(dp);
3022 break;
3023 case 7: /* sub: fn - fm */
3024 gen_vfp_sub(dp);
3025 break;
3026 case 8: /* div: fn / fm */
3027 gen_vfp_div(dp);
3028 break;
3029 case 14: /* fconst */
3030 if (!arm_feature(env, ARM_FEATURE_VFP3))
3031 return 1;
3033 n = (insn << 12) & 0x80000000;
3034 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3035 if (dp) {
3036 if (i & 0x40)
3037 i |= 0x3f80;
3038 else
3039 i |= 0x4000;
3040 n |= i << 16;
3041 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3042 } else {
3043 if (i & 0x40)
3044 i |= 0x780;
3045 else
3046 i |= 0x800;
3047 n |= i << 19;
3048 tcg_gen_movi_i32(cpu_F0s, n);
3050 break;
3051 case 15: /* extension space */
3052 switch (rn) {
3053 case 0: /* cpy */
3054 /* no-op */
3055 break;
3056 case 1: /* abs */
3057 gen_vfp_abs(dp);
3058 break;
3059 case 2: /* neg */
3060 gen_vfp_neg(dp);
3061 break;
3062 case 3: /* sqrt */
3063 gen_vfp_sqrt(dp);
3064 break;
3065 case 4: /* vcvtb.f32.f16 */
3066 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3067 return 1;
3068 tmp = gen_vfp_mrs();
3069 tcg_gen_ext16u_i32(tmp, tmp);
3070 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3071 tcg_temp_free_i32(tmp);
3072 break;
3073 case 5: /* vcvtt.f32.f16 */
3074 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3075 return 1;
3076 tmp = gen_vfp_mrs();
3077 tcg_gen_shri_i32(tmp, tmp, 16);
3078 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3079 tcg_temp_free_i32(tmp);
3080 break;
3081 case 6: /* vcvtb.f16.f32 */
3082 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3083 return 1;
3084 tmp = tcg_temp_new_i32();
3085 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3086 gen_mov_F0_vreg(0, rd);
3087 tmp2 = gen_vfp_mrs();
3088 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3089 tcg_gen_or_i32(tmp, tmp, tmp2);
3090 tcg_temp_free_i32(tmp2);
3091 gen_vfp_msr(tmp);
3092 break;
3093 case 7: /* vcvtt.f16.f32 */
3094 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3095 return 1;
3096 tmp = tcg_temp_new_i32();
3097 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3098 tcg_gen_shli_i32(tmp, tmp, 16);
3099 gen_mov_F0_vreg(0, rd);
3100 tmp2 = gen_vfp_mrs();
3101 tcg_gen_ext16u_i32(tmp2, tmp2);
3102 tcg_gen_or_i32(tmp, tmp, tmp2);
3103 tcg_temp_free_i32(tmp2);
3104 gen_vfp_msr(tmp);
3105 break;
3106 case 8: /* cmp */
3107 gen_vfp_cmp(dp);
3108 break;
3109 case 9: /* cmpe */
3110 gen_vfp_cmpe(dp);
3111 break;
3112 case 10: /* cmpz */
3113 gen_vfp_cmp(dp);
3114 break;
3115 case 11: /* cmpez */
3116 gen_vfp_F1_ld0(dp);
3117 gen_vfp_cmpe(dp);
3118 break;
3119 case 15: /* single<->double conversion */
3120 if (dp)
3121 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3122 else
3123 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3124 break;
3125 case 16: /* fuito */
3126 gen_vfp_uito(dp);
3127 break;
3128 case 17: /* fsito */
3129 gen_vfp_sito(dp);
3130 break;
3131 case 20: /* fshto */
3132 if (!arm_feature(env, ARM_FEATURE_VFP3))
3133 return 1;
3134 gen_vfp_shto(dp, 16 - rm);
3135 break;
3136 case 21: /* fslto */
3137 if (!arm_feature(env, ARM_FEATURE_VFP3))
3138 return 1;
3139 gen_vfp_slto(dp, 32 - rm);
3140 break;
3141 case 22: /* fuhto */
3142 if (!arm_feature(env, ARM_FEATURE_VFP3))
3143 return 1;
3144 gen_vfp_uhto(dp, 16 - rm);
3145 break;
3146 case 23: /* fulto */
3147 if (!arm_feature(env, ARM_FEATURE_VFP3))
3148 return 1;
3149 gen_vfp_ulto(dp, 32 - rm);
3150 break;
3151 case 24: /* ftoui */
3152 gen_vfp_toui(dp);
3153 break;
3154 case 25: /* ftouiz */
3155 gen_vfp_touiz(dp);
3156 break;
3157 case 26: /* ftosi */
3158 gen_vfp_tosi(dp);
3159 break;
3160 case 27: /* ftosiz */
3161 gen_vfp_tosiz(dp);
3162 break;
3163 case 28: /* ftosh */
3164 if (!arm_feature(env, ARM_FEATURE_VFP3))
3165 return 1;
3166 gen_vfp_tosh(dp, 16 - rm);
3167 break;
3168 case 29: /* ftosl */
3169 if (!arm_feature(env, ARM_FEATURE_VFP3))
3170 return 1;
3171 gen_vfp_tosl(dp, 32 - rm);
3172 break;
3173 case 30: /* ftouh */
3174 if (!arm_feature(env, ARM_FEATURE_VFP3))
3175 return 1;
3176 gen_vfp_touh(dp, 16 - rm);
3177 break;
3178 case 31: /* ftoul */
3179 if (!arm_feature(env, ARM_FEATURE_VFP3))
3180 return 1;
3181 gen_vfp_toul(dp, 32 - rm);
3182 break;
3183 default: /* undefined */
3184 printf ("rn:%d\n", rn);
3185 return 1;
3187 break;
3188 default: /* undefined */
3189 printf ("op:%d\n", op);
3190 return 1;
3193 /* Write back the result. */
3194 if (op == 15 && (rn >= 8 && rn <= 11))
3195 ; /* Comparison, do nothing. */
3196 else if (op == 15 && dp && ((rn & 0x1c) == 0x18))
3197 /* VCVT double to int: always integer result. */
3198 gen_mov_vreg_F0(0, rd);
3199 else if (op == 15 && rn == 15)
3200 /* conversion */
3201 gen_mov_vreg_F0(!dp, rd);
3202 else
3203 gen_mov_vreg_F0(dp, rd);
3205 /* break out of the loop if we have finished */
3206 if (veclen == 0)
3207 break;
3209 if (op == 15 && delta_m == 0) {
3210 /* single source one-many */
3211 while (veclen--) {
3212 rd = ((rd + delta_d) & (bank_mask - 1))
3213 | (rd & bank_mask);
3214 gen_mov_vreg_F0(dp, rd);
3216 break;
3218 /* Setup the next operands. */
3219 veclen--;
3220 rd = ((rd + delta_d) & (bank_mask - 1))
3221 | (rd & bank_mask);
3223 if (op == 15) {
3224 /* One source operand. */
3225 rm = ((rm + delta_m) & (bank_mask - 1))
3226 | (rm & bank_mask);
3227 gen_mov_F0_vreg(dp, rm);
3228 } else {
3229 /* Two source operands. */
3230 rn = ((rn + delta_d) & (bank_mask - 1))
3231 | (rn & bank_mask);
3232 gen_mov_F0_vreg(dp, rn);
3233 if (delta_m) {
3234 rm = ((rm + delta_m) & (bank_mask - 1))
3235 | (rm & bank_mask);
3236 gen_mov_F1_vreg(dp, rm);
3241 break;
3242 case 0xc:
3243 case 0xd:
3244 if ((insn & 0x03e00000) == 0x00400000) {
3245 /* two-register transfer */
3246 rn = (insn >> 16) & 0xf;
3247 rd = (insn >> 12) & 0xf;
3248 if (dp) {
3249 VFP_DREG_M(rm, insn);
3250 } else {
3251 rm = VFP_SREG_M(insn);
3254 if (insn & ARM_CP_RW_BIT) {
3255 /* vfp->arm */
3256 if (dp) {
3257 gen_mov_F0_vreg(0, rm * 2);
3258 tmp = gen_vfp_mrs();
3259 store_reg(s, rd, tmp);
3260 gen_mov_F0_vreg(0, rm * 2 + 1);
3261 tmp = gen_vfp_mrs();
3262 store_reg(s, rn, tmp);
3263 } else {
3264 gen_mov_F0_vreg(0, rm);
3265 tmp = gen_vfp_mrs();
3266 store_reg(s, rd, tmp);
3267 gen_mov_F0_vreg(0, rm + 1);
3268 tmp = gen_vfp_mrs();
3269 store_reg(s, rn, tmp);
3271 } else {
3272 /* arm->vfp */
3273 if (dp) {
3274 tmp = load_reg(s, rd);
3275 gen_vfp_msr(tmp);
3276 gen_mov_vreg_F0(0, rm * 2);
3277 tmp = load_reg(s, rn);
3278 gen_vfp_msr(tmp);
3279 gen_mov_vreg_F0(0, rm * 2 + 1);
3280 } else {
3281 tmp = load_reg(s, rd);
3282 gen_vfp_msr(tmp);
3283 gen_mov_vreg_F0(0, rm);
3284 tmp = load_reg(s, rn);
3285 gen_vfp_msr(tmp);
3286 gen_mov_vreg_F0(0, rm + 1);
3289 } else {
3290 /* Load/store */
3291 rn = (insn >> 16) & 0xf;
3292 if (dp)
3293 VFP_DREG_D(rd, insn);
3294 else
3295 rd = VFP_SREG_D(insn);
3296 if (s->thumb && rn == 15) {
3297 addr = tcg_temp_new_i32();
3298 tcg_gen_movi_i32(addr, s->pc & ~2);
3299 } else {
3300 addr = load_reg(s, rn);
3302 if ((insn & 0x01200000) == 0x01000000) {
3303 /* Single load/store */
3304 offset = (insn & 0xff) << 2;
3305 if ((insn & (1 << 23)) == 0)
3306 offset = -offset;
3307 tcg_gen_addi_i32(addr, addr, offset);
3308 if (insn & (1 << 20)) {
3309 gen_vfp_ld(s, dp, addr);
3310 gen_mov_vreg_F0(dp, rd);
3311 } else {
3312 gen_mov_F0_vreg(dp, rd);
3313 gen_vfp_st(s, dp, addr);
3315 tcg_temp_free_i32(addr);
3316 } else {
3317 /* load/store multiple */
3318 if (dp)
3319 n = (insn >> 1) & 0x7f;
3320 else
3321 n = insn & 0xff;
3323 if (insn & (1 << 24)) /* pre-decrement */
3324 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
3326 if (dp)
3327 offset = 8;
3328 else
3329 offset = 4;
3330 for (i = 0; i < n; i++) {
3331 if (insn & ARM_CP_RW_BIT) {
3332 /* load */
3333 gen_vfp_ld(s, dp, addr);
3334 gen_mov_vreg_F0(dp, rd + i);
3335 } else {
3336 /* store */
3337 gen_mov_F0_vreg(dp, rd + i);
3338 gen_vfp_st(s, dp, addr);
3340 tcg_gen_addi_i32(addr, addr, offset);
3342 if (insn & (1 << 21)) {
3343 /* writeback */
3344 if (insn & (1 << 24))
3345 offset = -offset * n;
3346 else if (dp && (insn & 1))
3347 offset = 4;
3348 else
3349 offset = 0;
3351 if (offset != 0)
3352 tcg_gen_addi_i32(addr, addr, offset);
3353 store_reg(s, rn, addr);
3354 } else {
3355 tcg_temp_free_i32(addr);
3359 break;
3360 default:
3361 /* Should never happen. */
3362 return 1;
3364 return 0;
3367 static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3369 TranslationBlock *tb;
3371 tb = s->tb;
3372 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3373 tcg_gen_goto_tb(n);
3374 gen_set_pc_im(dest);
3375 tcg_gen_exit_tb((long)tb + n);
3376 } else {
3377 gen_set_pc_im(dest);
3378 tcg_gen_exit_tb(0);
3382 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3384 if (unlikely(s->singlestep_enabled)) {
3385 /* An indirect jump so that we still trigger the debug exception. */
3386 if (s->thumb)
3387 dest |= 1;
3388 gen_bx_im(s, dest);
3389 } else {
3390 gen_goto_tb(s, 0, dest);
3391 s->is_jmp = DISAS_TB_JUMP;
3395 static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3397 if (x)
3398 tcg_gen_sari_i32(t0, t0, 16);
3399 else
3400 gen_sxth(t0);
3401 if (y)
3402 tcg_gen_sari_i32(t1, t1, 16);
3403 else
3404 gen_sxth(t1);
3405 tcg_gen_mul_i32(t0, t0, t1);
3408 /* Return the mask of PSR bits set by a MSR instruction. */
3409 static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3410 uint32_t mask;
3412 mask = 0;
3413 if (flags & (1 << 0))
3414 mask |= 0xff;
3415 if (flags & (1 << 1))
3416 mask |= 0xff00;
3417 if (flags & (1 << 2))
3418 mask |= 0xff0000;
3419 if (flags & (1 << 3))
3420 mask |= 0xff000000;
3422 /* Mask out undefined bits. */
3423 mask &= ~CPSR_RESERVED;
3424 if (!arm_feature(env, ARM_FEATURE_V6))
3425 mask &= ~(CPSR_E | CPSR_GE);
3426 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3427 mask &= ~CPSR_IT;
3428 /* Mask out execution state bits. */
3429 if (!spsr)
3430 mask &= ~CPSR_EXEC;
3431 /* Mask out privileged bits. */
3432 if (IS_USER(s))
3433 mask &= CPSR_USER;
3434 return mask;
3437 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3438 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0)
3440 TCGv tmp;
3441 if (spsr) {
3442 /* ??? This is also undefined in system mode. */
3443 if (IS_USER(s))
3444 return 1;
3446 tmp = load_cpu_field(spsr);
3447 tcg_gen_andi_i32(tmp, tmp, ~mask);
3448 tcg_gen_andi_i32(t0, t0, mask);
3449 tcg_gen_or_i32(tmp, tmp, t0);
3450 store_cpu_field(tmp, spsr);
3451 } else {
3452 gen_set_cpsr(t0, mask);
3454 tcg_temp_free_i32(t0);
3455 gen_lookup_tb(s);
3456 return 0;
3459 /* Returns nonzero if access to the PSR is not permitted. */
3460 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3462 TCGv tmp;
3463 tmp = tcg_temp_new_i32();
3464 tcg_gen_movi_i32(tmp, val);
3465 return gen_set_psr(s, mask, spsr, tmp);
3468 /* Generate an old-style exception return. Marks pc as dead. */
3469 static void gen_exception_return(DisasContext *s, TCGv pc)
3471 TCGv tmp;
3472 store_reg(s, 15, pc);
3473 tmp = load_cpu_field(spsr);
3474 gen_set_cpsr(tmp, 0xffffffff);
3475 tcg_temp_free_i32(tmp);
3476 s->is_jmp = DISAS_UPDATE;
3479 /* Generate a v6 exception return. Marks both values as dead. */
3480 static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3482 gen_set_cpsr(cpsr, 0xffffffff);
3483 tcg_temp_free_i32(cpsr);
3484 store_reg(s, 15, pc);
3485 s->is_jmp = DISAS_UPDATE;
3488 static inline void
3489 gen_set_condexec (DisasContext *s)
3491 if (s->condexec_mask) {
3492 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3493 TCGv tmp = tcg_temp_new_i32();
3494 tcg_gen_movi_i32(tmp, val);
3495 store_cpu_field(tmp, condexec_bits);
3499 static void gen_exception_insn(DisasContext *s, int offset, int excp)
3501 gen_set_condexec(s);
3502 gen_set_pc_im(s->pc - offset);
3503 gen_exception(excp);
3504 s->is_jmp = DISAS_JUMP;
3507 static void gen_nop_hint(DisasContext *s, int val)
3509 switch (val) {
3510 case 3: /* wfi */
3511 gen_set_pc_im(s->pc);
3512 s->is_jmp = DISAS_WFI;
3513 break;
3514 case 2: /* wfe */
3515 case 4: /* sev */
3516 /* TODO: Implement SEV and WFE. May help SMP performance. */
3517 default: /* nop */
3518 break;
3522 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3524 static inline int gen_neon_add(int size, TCGv t0, TCGv t1)
3526 switch (size) {
3527 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
3528 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
3529 case 2: tcg_gen_add_i32(t0, t0, t1); break;
3530 default: return 1;
3532 return 0;
3535 static inline void gen_neon_rsb(int size, TCGv t0, TCGv t1)
3537 switch (size) {
3538 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
3539 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
3540 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
3541 default: return;
3545 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3546 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3547 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3548 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3549 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3551 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3552 switch ((size << 1) | u) { \
3553 case 0: \
3554 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3555 break; \
3556 case 1: \
3557 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3558 break; \
3559 case 2: \
3560 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3561 break; \
3562 case 3: \
3563 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3564 break; \
3565 case 4: \
3566 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3567 break; \
3568 case 5: \
3569 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3570 break; \
3571 default: return 1; \
3572 }} while (0)
3574 #define GEN_NEON_INTEGER_OP(name) do { \
3575 switch ((size << 1) | u) { \
3576 case 0: \
3577 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3578 break; \
3579 case 1: \
3580 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3581 break; \
3582 case 2: \
3583 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3584 break; \
3585 case 3: \
3586 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3587 break; \
3588 case 4: \
3589 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3590 break; \
3591 case 5: \
3592 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3593 break; \
3594 default: return 1; \
3595 }} while (0)
3597 static TCGv neon_load_scratch(int scratch)
3599 TCGv tmp = tcg_temp_new_i32();
3600 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3601 return tmp;
3604 static void neon_store_scratch(int scratch, TCGv var)
3606 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3607 tcg_temp_free_i32(var);
3610 static inline TCGv neon_get_scalar(int size, int reg)
3612 TCGv tmp;
3613 if (size == 1) {
3614 tmp = neon_load_reg(reg & 7, reg >> 4);
3615 if (reg & 8) {
3616 gen_neon_dup_high16(tmp);
3617 } else {
3618 gen_neon_dup_low16(tmp);
3620 } else {
3621 tmp = neon_load_reg(reg & 15, reg >> 4);
3623 return tmp;
3626 static int gen_neon_unzip(int rd, int rm, int size, int q)
3628 TCGv tmp, tmp2;
3629 if (size == 3 || (!q && size == 2)) {
3630 return 1;
3632 tmp = tcg_const_i32(rd);
3633 tmp2 = tcg_const_i32(rm);
3634 if (q) {
3635 switch (size) {
3636 case 0:
3637 gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
3638 break;
3639 case 1:
3640 gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
3641 break;
3642 case 2:
3643 gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
3644 break;
3645 default:
3646 abort();
3648 } else {
3649 switch (size) {
3650 case 0:
3651 gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
3652 break;
3653 case 1:
3654 gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
3655 break;
3656 default:
3657 abort();
3660 tcg_temp_free_i32(tmp);
3661 tcg_temp_free_i32(tmp2);
3662 return 0;
3665 static int gen_neon_zip(int rd, int rm, int size, int q)
3667 TCGv tmp, tmp2;
3668 if (size == 3 || (!q && size == 2)) {
3669 return 1;
3671 tmp = tcg_const_i32(rd);
3672 tmp2 = tcg_const_i32(rm);
3673 if (q) {
3674 switch (size) {
3675 case 0:
3676 gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
3677 break;
3678 case 1:
3679 gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
3680 break;
3681 case 2:
3682 gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
3683 break;
3684 default:
3685 abort();
3687 } else {
3688 switch (size) {
3689 case 0:
3690 gen_helper_neon_zip8(cpu_env, tmp, tmp2);
3691 break;
3692 case 1:
3693 gen_helper_neon_zip16(cpu_env, tmp, tmp2);
3694 break;
3695 default:
3696 abort();
3699 tcg_temp_free_i32(tmp);
3700 tcg_temp_free_i32(tmp2);
3701 return 0;
3704 static void gen_neon_trn_u8(TCGv t0, TCGv t1)
3706 TCGv rd, tmp;
3708 rd = tcg_temp_new_i32();
3709 tmp = tcg_temp_new_i32();
3711 tcg_gen_shli_i32(rd, t0, 8);
3712 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3713 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3714 tcg_gen_or_i32(rd, rd, tmp);
3716 tcg_gen_shri_i32(t1, t1, 8);
3717 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3718 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3719 tcg_gen_or_i32(t1, t1, tmp);
3720 tcg_gen_mov_i32(t0, rd);
3722 tcg_temp_free_i32(tmp);
3723 tcg_temp_free_i32(rd);
3726 static void gen_neon_trn_u16(TCGv t0, TCGv t1)
3728 TCGv rd, tmp;
3730 rd = tcg_temp_new_i32();
3731 tmp = tcg_temp_new_i32();
3733 tcg_gen_shli_i32(rd, t0, 16);
3734 tcg_gen_andi_i32(tmp, t1, 0xffff);
3735 tcg_gen_or_i32(rd, rd, tmp);
3736 tcg_gen_shri_i32(t1, t1, 16);
3737 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3738 tcg_gen_or_i32(t1, t1, tmp);
3739 tcg_gen_mov_i32(t0, rd);
3741 tcg_temp_free_i32(tmp);
3742 tcg_temp_free_i32(rd);
3746 static struct {
3747 int nregs;
3748 int interleave;
3749 int spacing;
3750 } neon_ls_element_type[11] = {
3751 {4, 4, 1},
3752 {4, 4, 2},
3753 {4, 1, 1},
3754 {4, 2, 1},
3755 {3, 3, 1},
3756 {3, 3, 2},
3757 {3, 1, 1},
3758 {1, 1, 1},
3759 {2, 2, 1},
3760 {2, 2, 2},
3761 {2, 1, 1}
3764 /* Translate a NEON load/store element instruction. Return nonzero if the
3765 instruction is invalid. */
3766 static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3768 int rd, rn, rm;
3769 int op;
3770 int nregs;
3771 int interleave;
3772 int spacing;
3773 int stride;
3774 int size;
3775 int reg;
3776 int pass;
3777 int load;
3778 int shift;
3779 int n;
3780 TCGv addr;
3781 TCGv tmp;
3782 TCGv tmp2;
3783 TCGv_i64 tmp64;
3785 if (!s->vfp_enabled)
3786 return 1;
3787 VFP_DREG_D(rd, insn);
3788 rn = (insn >> 16) & 0xf;
3789 rm = insn & 0xf;
3790 load = (insn & (1 << 21)) != 0;
3791 addr = tcg_temp_new_i32();
3792 if ((insn & (1 << 23)) == 0) {
3793 /* Load store all elements. */
3794 op = (insn >> 8) & 0xf;
3795 size = (insn >> 6) & 3;
3796 if (op > 10)
3797 return 1;
3798 nregs = neon_ls_element_type[op].nregs;
3799 interleave = neon_ls_element_type[op].interleave;
3800 spacing = neon_ls_element_type[op].spacing;
3801 if (size == 3 && (interleave | spacing) != 1)
3802 return 1;
3803 load_reg_var(s, addr, rn);
3804 stride = (1 << size) * interleave;
3805 for (reg = 0; reg < nregs; reg++) {
3806 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3807 load_reg_var(s, addr, rn);
3808 tcg_gen_addi_i32(addr, addr, (1 << size) * reg);
3809 } else if (interleave == 2 && nregs == 4 && reg == 2) {
3810 load_reg_var(s, addr, rn);
3811 tcg_gen_addi_i32(addr, addr, 1 << size);
3813 if (size == 3) {
3814 if (load) {
3815 tmp64 = gen_ld64(addr, IS_USER(s));
3816 neon_store_reg64(tmp64, rd);
3817 tcg_temp_free_i64(tmp64);
3818 } else {
3819 tmp64 = tcg_temp_new_i64();
3820 neon_load_reg64(tmp64, rd);
3821 gen_st64(tmp64, addr, IS_USER(s));
3823 tcg_gen_addi_i32(addr, addr, stride);
3824 } else {
3825 for (pass = 0; pass < 2; pass++) {
3826 if (size == 2) {
3827 if (load) {
3828 tmp = gen_ld32(addr, IS_USER(s));
3829 neon_store_reg(rd, pass, tmp);
3830 } else {
3831 tmp = neon_load_reg(rd, pass);
3832 gen_st32(tmp, addr, IS_USER(s));
3834 tcg_gen_addi_i32(addr, addr, stride);
3835 } else if (size == 1) {
3836 if (load) {
3837 tmp = gen_ld16u(addr, IS_USER(s));
3838 tcg_gen_addi_i32(addr, addr, stride);
3839 tmp2 = gen_ld16u(addr, IS_USER(s));
3840 tcg_gen_addi_i32(addr, addr, stride);
3841 tcg_gen_shli_i32(tmp2, tmp2, 16);
3842 tcg_gen_or_i32(tmp, tmp, tmp2);
3843 tcg_temp_free_i32(tmp2);
3844 neon_store_reg(rd, pass, tmp);
3845 } else {
3846 tmp = neon_load_reg(rd, pass);
3847 tmp2 = tcg_temp_new_i32();
3848 tcg_gen_shri_i32(tmp2, tmp, 16);
3849 gen_st16(tmp, addr, IS_USER(s));
3850 tcg_gen_addi_i32(addr, addr, stride);
3851 gen_st16(tmp2, addr, IS_USER(s));
3852 tcg_gen_addi_i32(addr, addr, stride);
3854 } else /* size == 0 */ {
3855 if (load) {
3856 TCGV_UNUSED(tmp2);
3857 for (n = 0; n < 4; n++) {
3858 tmp = gen_ld8u(addr, IS_USER(s));
3859 tcg_gen_addi_i32(addr, addr, stride);
3860 if (n == 0) {
3861 tmp2 = tmp;
3862 } else {
3863 tcg_gen_shli_i32(tmp, tmp, n * 8);
3864 tcg_gen_or_i32(tmp2, tmp2, tmp);
3865 tcg_temp_free_i32(tmp);
3868 neon_store_reg(rd, pass, tmp2);
3869 } else {
3870 tmp2 = neon_load_reg(rd, pass);
3871 for (n = 0; n < 4; n++) {
3872 tmp = tcg_temp_new_i32();
3873 if (n == 0) {
3874 tcg_gen_mov_i32(tmp, tmp2);
3875 } else {
3876 tcg_gen_shri_i32(tmp, tmp2, n * 8);
3878 gen_st8(tmp, addr, IS_USER(s));
3879 tcg_gen_addi_i32(addr, addr, stride);
3881 tcg_temp_free_i32(tmp2);
3886 rd += spacing;
3888 stride = nregs * 8;
3889 } else {
3890 size = (insn >> 10) & 3;
3891 if (size == 3) {
3892 /* Load single element to all lanes. */
3893 if (!load)
3894 return 1;
3895 size = (insn >> 6) & 3;
3896 nregs = ((insn >> 8) & 3) + 1;
3897 stride = (insn & (1 << 5)) ? 2 : 1;
3898 load_reg_var(s, addr, rn);
3899 for (reg = 0; reg < nregs; reg++) {
3900 switch (size) {
3901 case 0:
3902 tmp = gen_ld8u(addr, IS_USER(s));
3903 gen_neon_dup_u8(tmp, 0);
3904 break;
3905 case 1:
3906 tmp = gen_ld16u(addr, IS_USER(s));
3907 gen_neon_dup_low16(tmp);
3908 break;
3909 case 2:
3910 tmp = gen_ld32(addr, IS_USER(s));
3911 break;
3912 case 3:
3913 return 1;
3914 default: /* Avoid compiler warnings. */
3915 abort();
3917 tcg_gen_addi_i32(addr, addr, 1 << size);
3918 tmp2 = tcg_temp_new_i32();
3919 tcg_gen_mov_i32(tmp2, tmp);
3920 neon_store_reg(rd, 0, tmp2);
3921 neon_store_reg(rd, 1, tmp);
3922 rd += stride;
3924 stride = (1 << size) * nregs;
3925 } else {
3926 /* Single element. */
3927 pass = (insn >> 7) & 1;
3928 switch (size) {
3929 case 0:
3930 shift = ((insn >> 5) & 3) * 8;
3931 stride = 1;
3932 break;
3933 case 1:
3934 shift = ((insn >> 6) & 1) * 16;
3935 stride = (insn & (1 << 5)) ? 2 : 1;
3936 break;
3937 case 2:
3938 shift = 0;
3939 stride = (insn & (1 << 6)) ? 2 : 1;
3940 break;
3941 default:
3942 abort();
3944 nregs = ((insn >> 8) & 3) + 1;
3945 load_reg_var(s, addr, rn);
3946 for (reg = 0; reg < nregs; reg++) {
3947 if (load) {
3948 switch (size) {
3949 case 0:
3950 tmp = gen_ld8u(addr, IS_USER(s));
3951 break;
3952 case 1:
3953 tmp = gen_ld16u(addr, IS_USER(s));
3954 break;
3955 case 2:
3956 tmp = gen_ld32(addr, IS_USER(s));
3957 break;
3958 default: /* Avoid compiler warnings. */
3959 abort();
3961 if (size != 2) {
3962 tmp2 = neon_load_reg(rd, pass);
3963 gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
3964 tcg_temp_free_i32(tmp2);
3966 neon_store_reg(rd, pass, tmp);
3967 } else { /* Store */
3968 tmp = neon_load_reg(rd, pass);
3969 if (shift)
3970 tcg_gen_shri_i32(tmp, tmp, shift);
3971 switch (size) {
3972 case 0:
3973 gen_st8(tmp, addr, IS_USER(s));
3974 break;
3975 case 1:
3976 gen_st16(tmp, addr, IS_USER(s));
3977 break;
3978 case 2:
3979 gen_st32(tmp, addr, IS_USER(s));
3980 break;
3983 rd += stride;
3984 tcg_gen_addi_i32(addr, addr, 1 << size);
3986 stride = nregs * (1 << size);
3989 tcg_temp_free_i32(addr);
3990 if (rm != 15) {
3991 TCGv base;
3993 base = load_reg(s, rn);
3994 if (rm == 13) {
3995 tcg_gen_addi_i32(base, base, stride);
3996 } else {
3997 TCGv index;
3998 index = load_reg(s, rm);
3999 tcg_gen_add_i32(base, base, index);
4000 tcg_temp_free_i32(index);
4002 store_reg(s, rn, base);
4004 return 0;
4007 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4008 static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
4010 tcg_gen_and_i32(t, t, c);
4011 tcg_gen_andc_i32(f, f, c);
4012 tcg_gen_or_i32(dest, t, f);
4015 static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
4017 switch (size) {
4018 case 0: gen_helper_neon_narrow_u8(dest, src); break;
4019 case 1: gen_helper_neon_narrow_u16(dest, src); break;
4020 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
4021 default: abort();
4025 static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
4027 switch (size) {
4028 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
4029 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
4030 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
4031 default: abort();
4035 static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
4037 switch (size) {
4038 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
4039 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
4040 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
4041 default: abort();
4045 static inline void gen_neon_unarrow_sats(int size, TCGv dest, TCGv_i64 src)
4047 switch (size) {
4048 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
4049 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
4050 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
4051 default: abort();
4055 static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
4056 int q, int u)
4058 if (q) {
4059 if (u) {
4060 switch (size) {
4061 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4062 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4063 default: abort();
4065 } else {
4066 switch (size) {
4067 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
4068 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
4069 default: abort();
4072 } else {
4073 if (u) {
4074 switch (size) {
4075 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
4076 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
4077 default: abort();
4079 } else {
4080 switch (size) {
4081 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
4082 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
4083 default: abort();
4089 static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
4091 if (u) {
4092 switch (size) {
4093 case 0: gen_helper_neon_widen_u8(dest, src); break;
4094 case 1: gen_helper_neon_widen_u16(dest, src); break;
4095 case 2: tcg_gen_extu_i32_i64(dest, src); break;
4096 default: abort();
4098 } else {
4099 switch (size) {
4100 case 0: gen_helper_neon_widen_s8(dest, src); break;
4101 case 1: gen_helper_neon_widen_s16(dest, src); break;
4102 case 2: tcg_gen_ext_i32_i64(dest, src); break;
4103 default: abort();
4106 tcg_temp_free_i32(src);
4109 static inline void gen_neon_addl(int size)
4111 switch (size) {
4112 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4113 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4114 case 2: tcg_gen_add_i64(CPU_V001); break;
4115 default: abort();
4119 static inline void gen_neon_subl(int size)
4121 switch (size) {
4122 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4123 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4124 case 2: tcg_gen_sub_i64(CPU_V001); break;
4125 default: abort();
4129 static inline void gen_neon_negl(TCGv_i64 var, int size)
4131 switch (size) {
4132 case 0: gen_helper_neon_negl_u16(var, var); break;
4133 case 1: gen_helper_neon_negl_u32(var, var); break;
4134 case 2: gen_helper_neon_negl_u64(var, var); break;
4135 default: abort();
4139 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4141 switch (size) {
4142 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4143 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4144 default: abort();
4148 static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
4150 TCGv_i64 tmp;
4152 switch ((size << 1) | u) {
4153 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4154 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4155 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4156 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4157 case 4:
4158 tmp = gen_muls_i64_i32(a, b);
4159 tcg_gen_mov_i64(dest, tmp);
4160 tcg_temp_free_i64(tmp);
4161 break;
4162 case 5:
4163 tmp = gen_mulu_i64_i32(a, b);
4164 tcg_gen_mov_i64(dest, tmp);
4165 tcg_temp_free_i64(tmp);
4166 break;
4167 default: abort();
4170 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
4171 Don't forget to clean them now. */
4172 if (size < 2) {
4173 tcg_temp_free_i32(a);
4174 tcg_temp_free_i32(b);
4178 static void gen_neon_narrow_op(int op, int u, int size, TCGv dest, TCGv_i64 src)
4180 if (op) {
4181 if (u) {
4182 gen_neon_unarrow_sats(size, dest, src);
4183 } else {
4184 gen_neon_narrow(size, dest, src);
4186 } else {
4187 if (u) {
4188 gen_neon_narrow_satu(size, dest, src);
4189 } else {
4190 gen_neon_narrow_sats(size, dest, src);
4195 /* Translate a NEON data processing instruction. Return nonzero if the
4196 instruction is invalid.
4197 We process data in a mixture of 32-bit and 64-bit chunks.
4198 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4200 static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4202 int op;
4203 int q;
4204 int rd, rn, rm;
4205 int size;
4206 int shift;
4207 int pass;
4208 int count;
4209 int pairwise;
4210 int u;
4211 int n;
4212 uint32_t imm, mask;
4213 TCGv tmp, tmp2, tmp3, tmp4, tmp5;
4214 TCGv_i64 tmp64;
4216 if (!s->vfp_enabled)
4217 return 1;
4218 q = (insn & (1 << 6)) != 0;
4219 u = (insn >> 24) & 1;
4220 VFP_DREG_D(rd, insn);
4221 VFP_DREG_N(rn, insn);
4222 VFP_DREG_M(rm, insn);
4223 size = (insn >> 20) & 3;
4224 if ((insn & (1 << 23)) == 0) {
4225 /* Three register same length. */
4226 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4227 if (size == 3 && (op == 1 || op == 5 || op == 8 || op == 9
4228 || op == 10 || op == 11 || op == 16)) {
4229 /* 64-bit element instructions. */
4230 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4231 neon_load_reg64(cpu_V0, rn + pass);
4232 neon_load_reg64(cpu_V1, rm + pass);
4233 switch (op) {
4234 case 1: /* VQADD */
4235 if (u) {
4236 gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
4237 cpu_V0, cpu_V1);
4238 } else {
4239 gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
4240 cpu_V0, cpu_V1);
4242 break;
4243 case 5: /* VQSUB */
4244 if (u) {
4245 gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
4246 cpu_V0, cpu_V1);
4247 } else {
4248 gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
4249 cpu_V0, cpu_V1);
4251 break;
4252 case 8: /* VSHL */
4253 if (u) {
4254 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4255 } else {
4256 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4258 break;
4259 case 9: /* VQSHL */
4260 if (u) {
4261 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4262 cpu_V1, cpu_V0);
4263 } else {
4264 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
4265 cpu_V1, cpu_V0);
4267 break;
4268 case 10: /* VRSHL */
4269 if (u) {
4270 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4271 } else {
4272 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4274 break;
4275 case 11: /* VQRSHL */
4276 if (u) {
4277 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4278 cpu_V1, cpu_V0);
4279 } else {
4280 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4281 cpu_V1, cpu_V0);
4283 break;
4284 case 16:
4285 if (u) {
4286 tcg_gen_sub_i64(CPU_V001);
4287 } else {
4288 tcg_gen_add_i64(CPU_V001);
4290 break;
4291 default:
4292 abort();
4294 neon_store_reg64(cpu_V0, rd + pass);
4296 return 0;
4298 switch (op) {
4299 case 8: /* VSHL */
4300 case 9: /* VQSHL */
4301 case 10: /* VRSHL */
4302 case 11: /* VQRSHL */
4304 int rtmp;
4305 /* Shift instruction operands are reversed. */
4306 rtmp = rn;
4307 rn = rm;
4308 rm = rtmp;
4309 pairwise = 0;
4311 break;
4312 case 20: /* VPMAX */
4313 case 21: /* VPMIN */
4314 case 23: /* VPADD */
4315 pairwise = 1;
4316 break;
4317 case 26: /* VPADD (float) */
4318 pairwise = (u && size < 2);
4319 break;
4320 case 30: /* VPMIN/VPMAX (float) */
4321 pairwise = u;
4322 break;
4323 default:
4324 pairwise = 0;
4325 break;
4328 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4330 if (pairwise) {
4331 /* Pairwise. */
4332 if (q)
4333 n = (pass & 1) * 2;
4334 else
4335 n = 0;
4336 if (pass < q + 1) {
4337 tmp = neon_load_reg(rn, n);
4338 tmp2 = neon_load_reg(rn, n + 1);
4339 } else {
4340 tmp = neon_load_reg(rm, n);
4341 tmp2 = neon_load_reg(rm, n + 1);
4343 } else {
4344 /* Elementwise. */
4345 tmp = neon_load_reg(rn, pass);
4346 tmp2 = neon_load_reg(rm, pass);
4348 switch (op) {
4349 case 0: /* VHADD */
4350 GEN_NEON_INTEGER_OP(hadd);
4351 break;
4352 case 1: /* VQADD */
4353 GEN_NEON_INTEGER_OP_ENV(qadd);
4354 break;
4355 case 2: /* VRHADD */
4356 GEN_NEON_INTEGER_OP(rhadd);
4357 break;
4358 case 3: /* Logic ops. */
4359 switch ((u << 2) | size) {
4360 case 0: /* VAND */
4361 tcg_gen_and_i32(tmp, tmp, tmp2);
4362 break;
4363 case 1: /* BIC */
4364 tcg_gen_andc_i32(tmp, tmp, tmp2);
4365 break;
4366 case 2: /* VORR */
4367 tcg_gen_or_i32(tmp, tmp, tmp2);
4368 break;
4369 case 3: /* VORN */
4370 tcg_gen_orc_i32(tmp, tmp, tmp2);
4371 break;
4372 case 4: /* VEOR */
4373 tcg_gen_xor_i32(tmp, tmp, tmp2);
4374 break;
4375 case 5: /* VBSL */
4376 tmp3 = neon_load_reg(rd, pass);
4377 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
4378 tcg_temp_free_i32(tmp3);
4379 break;
4380 case 6: /* VBIT */
4381 tmp3 = neon_load_reg(rd, pass);
4382 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
4383 tcg_temp_free_i32(tmp3);
4384 break;
4385 case 7: /* VBIF */
4386 tmp3 = neon_load_reg(rd, pass);
4387 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
4388 tcg_temp_free_i32(tmp3);
4389 break;
4391 break;
4392 case 4: /* VHSUB */
4393 GEN_NEON_INTEGER_OP(hsub);
4394 break;
4395 case 5: /* VQSUB */
4396 GEN_NEON_INTEGER_OP_ENV(qsub);
4397 break;
4398 case 6: /* VCGT */
4399 GEN_NEON_INTEGER_OP(cgt);
4400 break;
4401 case 7: /* VCGE */
4402 GEN_NEON_INTEGER_OP(cge);
4403 break;
4404 case 8: /* VSHL */
4405 GEN_NEON_INTEGER_OP(shl);
4406 break;
4407 case 9: /* VQSHL */
4408 GEN_NEON_INTEGER_OP_ENV(qshl);
4409 break;
4410 case 10: /* VRSHL */
4411 GEN_NEON_INTEGER_OP(rshl);
4412 break;
4413 case 11: /* VQRSHL */
4414 GEN_NEON_INTEGER_OP_ENV(qrshl);
4415 break;
4416 case 12: /* VMAX */
4417 GEN_NEON_INTEGER_OP(max);
4418 break;
4419 case 13: /* VMIN */
4420 GEN_NEON_INTEGER_OP(min);
4421 break;
4422 case 14: /* VABD */
4423 GEN_NEON_INTEGER_OP(abd);
4424 break;
4425 case 15: /* VABA */
4426 GEN_NEON_INTEGER_OP(abd);
4427 tcg_temp_free_i32(tmp2);
4428 tmp2 = neon_load_reg(rd, pass);
4429 gen_neon_add(size, tmp, tmp2);
4430 break;
4431 case 16:
4432 if (!u) { /* VADD */
4433 if (gen_neon_add(size, tmp, tmp2))
4434 return 1;
4435 } else { /* VSUB */
4436 switch (size) {
4437 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
4438 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
4439 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
4440 default: return 1;
4443 break;
4444 case 17:
4445 if (!u) { /* VTST */
4446 switch (size) {
4447 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
4448 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
4449 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
4450 default: return 1;
4452 } else { /* VCEQ */
4453 switch (size) {
4454 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
4455 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
4456 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
4457 default: return 1;
4460 break;
4461 case 18: /* Multiply. */
4462 switch (size) {
4463 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4464 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4465 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4466 default: return 1;
4468 tcg_temp_free_i32(tmp2);
4469 tmp2 = neon_load_reg(rd, pass);
4470 if (u) { /* VMLS */
4471 gen_neon_rsb(size, tmp, tmp2);
4472 } else { /* VMLA */
4473 gen_neon_add(size, tmp, tmp2);
4475 break;
4476 case 19: /* VMUL */
4477 if (u) { /* polynomial */
4478 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
4479 } else { /* Integer */
4480 switch (size) {
4481 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4482 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4483 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4484 default: return 1;
4487 break;
4488 case 20: /* VPMAX */
4489 GEN_NEON_INTEGER_OP(pmax);
4490 break;
4491 case 21: /* VPMIN */
4492 GEN_NEON_INTEGER_OP(pmin);
4493 break;
4494 case 22: /* Hultiply high. */
4495 if (!u) { /* VQDMULH */
4496 switch (size) {
4497 case 1: gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4498 case 2: gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4499 default: return 1;
4501 } else { /* VQRDHMUL */
4502 switch (size) {
4503 case 1: gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4504 case 2: gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4505 default: return 1;
4508 break;
4509 case 23: /* VPADD */
4510 if (u)
4511 return 1;
4512 switch (size) {
4513 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
4514 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
4515 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
4516 default: return 1;
4518 break;
4519 case 26: /* Floating point arithnetic. */
4520 switch ((u << 2) | size) {
4521 case 0: /* VADD */
4522 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4523 break;
4524 case 2: /* VSUB */
4525 gen_helper_neon_sub_f32(tmp, tmp, tmp2);
4526 break;
4527 case 4: /* VPADD */
4528 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4529 break;
4530 case 6: /* VABD */
4531 gen_helper_neon_abd_f32(tmp, tmp, tmp2);
4532 break;
4533 default:
4534 return 1;
4536 break;
4537 case 27: /* Float multiply. */
4538 gen_helper_neon_mul_f32(tmp, tmp, tmp2);
4539 if (!u) {
4540 tcg_temp_free_i32(tmp2);
4541 tmp2 = neon_load_reg(rd, pass);
4542 if (size == 0) {
4543 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4544 } else {
4545 gen_helper_neon_sub_f32(tmp, tmp2, tmp);
4548 break;
4549 case 28: /* Float compare. */
4550 if (!u) {
4551 gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
4552 } else {
4553 if (size == 0)
4554 gen_helper_neon_cge_f32(tmp, tmp, tmp2);
4555 else
4556 gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
4558 break;
4559 case 29: /* Float compare absolute. */
4560 if (!u)
4561 return 1;
4562 if (size == 0)
4563 gen_helper_neon_acge_f32(tmp, tmp, tmp2);
4564 else
4565 gen_helper_neon_acgt_f32(tmp, tmp, tmp2);
4566 break;
4567 case 30: /* Float min/max. */
4568 if (size == 0)
4569 gen_helper_neon_max_f32(tmp, tmp, tmp2);
4570 else
4571 gen_helper_neon_min_f32(tmp, tmp, tmp2);
4572 break;
4573 case 31:
4574 if (size == 0)
4575 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
4576 else
4577 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
4578 break;
4579 default:
4580 abort();
4582 tcg_temp_free_i32(tmp2);
4584 /* Save the result. For elementwise operations we can put it
4585 straight into the destination register. For pairwise operations
4586 we have to be careful to avoid clobbering the source operands. */
4587 if (pairwise && rd == rm) {
4588 neon_store_scratch(pass, tmp);
4589 } else {
4590 neon_store_reg(rd, pass, tmp);
4593 } /* for pass */
4594 if (pairwise && rd == rm) {
4595 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4596 tmp = neon_load_scratch(pass);
4597 neon_store_reg(rd, pass, tmp);
4600 /* End of 3 register same size operations. */
4601 } else if (insn & (1 << 4)) {
4602 if ((insn & 0x00380080) != 0) {
4603 /* Two registers and shift. */
4604 op = (insn >> 8) & 0xf;
4605 if (insn & (1 << 7)) {
4606 /* 64-bit shift. */
4607 size = 3;
4608 } else {
4609 size = 2;
4610 while ((insn & (1 << (size + 19))) == 0)
4611 size--;
4613 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4614 /* To avoid excessive dumplication of ops we implement shift
4615 by immediate using the variable shift operations. */
4616 if (op < 8) {
4617 /* Shift by immediate:
4618 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4619 /* Right shifts are encoded as N - shift, where N is the
4620 element size in bits. */
4621 if (op <= 4)
4622 shift = shift - (1 << (size + 3));
4623 if (size == 3) {
4624 count = q + 1;
4625 } else {
4626 count = q ? 4: 2;
4628 switch (size) {
4629 case 0:
4630 imm = (uint8_t) shift;
4631 imm |= imm << 8;
4632 imm |= imm << 16;
4633 break;
4634 case 1:
4635 imm = (uint16_t) shift;
4636 imm |= imm << 16;
4637 break;
4638 case 2:
4639 case 3:
4640 imm = shift;
4641 break;
4642 default:
4643 abort();
4646 for (pass = 0; pass < count; pass++) {
4647 if (size == 3) {
4648 neon_load_reg64(cpu_V0, rm + pass);
4649 tcg_gen_movi_i64(cpu_V1, imm);
4650 switch (op) {
4651 case 0: /* VSHR */
4652 case 1: /* VSRA */
4653 if (u)
4654 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4655 else
4656 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
4657 break;
4658 case 2: /* VRSHR */
4659 case 3: /* VRSRA */
4660 if (u)
4661 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
4662 else
4663 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
4664 break;
4665 case 4: /* VSRI */
4666 if (!u)
4667 return 1;
4668 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4669 break;
4670 case 5: /* VSHL, VSLI */
4671 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4672 break;
4673 case 6: /* VQSHLU */
4674 if (u) {
4675 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
4676 cpu_V0, cpu_V1);
4677 } else {
4678 return 1;
4680 break;
4681 case 7: /* VQSHL */
4682 if (u) {
4683 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4684 cpu_V0, cpu_V1);
4685 } else {
4686 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
4687 cpu_V0, cpu_V1);
4689 break;
4691 if (op == 1 || op == 3) {
4692 /* Accumulate. */
4693 neon_load_reg64(cpu_V1, rd + pass);
4694 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
4695 } else if (op == 4 || (op == 5 && u)) {
4696 /* Insert */
4697 neon_load_reg64(cpu_V1, rd + pass);
4698 uint64_t mask;
4699 if (shift < -63 || shift > 63) {
4700 mask = 0;
4701 } else {
4702 if (op == 4) {
4703 mask = 0xffffffffffffffffull >> -shift;
4704 } else {
4705 mask = 0xffffffffffffffffull << shift;
4708 tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask);
4709 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
4711 neon_store_reg64(cpu_V0, rd + pass);
4712 } else { /* size < 3 */
4713 /* Operands in T0 and T1. */
4714 tmp = neon_load_reg(rm, pass);
4715 tmp2 = tcg_temp_new_i32();
4716 tcg_gen_movi_i32(tmp2, imm);
4717 switch (op) {
4718 case 0: /* VSHR */
4719 case 1: /* VSRA */
4720 GEN_NEON_INTEGER_OP(shl);
4721 break;
4722 case 2: /* VRSHR */
4723 case 3: /* VRSRA */
4724 GEN_NEON_INTEGER_OP(rshl);
4725 break;
4726 case 4: /* VSRI */
4727 if (!u)
4728 return 1;
4729 GEN_NEON_INTEGER_OP(shl);
4730 break;
4731 case 5: /* VSHL, VSLI */
4732 switch (size) {
4733 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
4734 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
4735 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
4736 default: return 1;
4738 break;
4739 case 6: /* VQSHLU */
4740 if (!u) {
4741 return 1;
4743 switch (size) {
4744 case 0:
4745 gen_helper_neon_qshlu_s8(tmp, cpu_env,
4746 tmp, tmp2);
4747 break;
4748 case 1:
4749 gen_helper_neon_qshlu_s16(tmp, cpu_env,
4750 tmp, tmp2);
4751 break;
4752 case 2:
4753 gen_helper_neon_qshlu_s32(tmp, cpu_env,
4754 tmp, tmp2);
4755 break;
4756 default:
4757 return 1;
4759 break;
4760 case 7: /* VQSHL */
4761 GEN_NEON_INTEGER_OP_ENV(qshl);
4762 break;
4764 tcg_temp_free_i32(tmp2);
4766 if (op == 1 || op == 3) {
4767 /* Accumulate. */
4768 tmp2 = neon_load_reg(rd, pass);
4769 gen_neon_add(size, tmp, tmp2);
4770 tcg_temp_free_i32(tmp2);
4771 } else if (op == 4 || (op == 5 && u)) {
4772 /* Insert */
4773 switch (size) {
4774 case 0:
4775 if (op == 4)
4776 mask = 0xff >> -shift;
4777 else
4778 mask = (uint8_t)(0xff << shift);
4779 mask |= mask << 8;
4780 mask |= mask << 16;
4781 break;
4782 case 1:
4783 if (op == 4)
4784 mask = 0xffff >> -shift;
4785 else
4786 mask = (uint16_t)(0xffff << shift);
4787 mask |= mask << 16;
4788 break;
4789 case 2:
4790 if (shift < -31 || shift > 31) {
4791 mask = 0;
4792 } else {
4793 if (op == 4)
4794 mask = 0xffffffffu >> -shift;
4795 else
4796 mask = 0xffffffffu << shift;
4798 break;
4799 default:
4800 abort();
4802 tmp2 = neon_load_reg(rd, pass);
4803 tcg_gen_andi_i32(tmp, tmp, mask);
4804 tcg_gen_andi_i32(tmp2, tmp2, ~mask);
4805 tcg_gen_or_i32(tmp, tmp, tmp2);
4806 tcg_temp_free_i32(tmp2);
4808 neon_store_reg(rd, pass, tmp);
4810 } /* for pass */
4811 } else if (op < 10) {
4812 /* Shift by immediate and narrow:
4813 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4814 int input_unsigned = (op == 8) ? !u : u;
4816 shift = shift - (1 << (size + 3));
4817 size++;
4818 if (size == 3) {
4819 tmp64 = tcg_const_i64(shift);
4820 neon_load_reg64(cpu_V0, rm);
4821 neon_load_reg64(cpu_V1, rm + 1);
4822 for (pass = 0; pass < 2; pass++) {
4823 TCGv_i64 in;
4824 if (pass == 0) {
4825 in = cpu_V0;
4826 } else {
4827 in = cpu_V1;
4829 if (q) {
4830 if (input_unsigned) {
4831 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
4832 } else {
4833 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
4835 } else {
4836 if (input_unsigned) {
4837 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
4838 } else {
4839 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
4842 tmp = tcg_temp_new_i32();
4843 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
4844 neon_store_reg(rd, pass, tmp);
4845 } /* for pass */
4846 tcg_temp_free_i64(tmp64);
4847 } else {
4848 if (size == 1) {
4849 imm = (uint16_t)shift;
4850 imm |= imm << 16;
4851 } else {
4852 /* size == 2 */
4853 imm = (uint32_t)shift;
4855 tmp2 = tcg_const_i32(imm);
4856 tmp4 = neon_load_reg(rm + 1, 0);
4857 tmp5 = neon_load_reg(rm + 1, 1);
4858 for (pass = 0; pass < 2; pass++) {
4859 if (pass == 0) {
4860 tmp = neon_load_reg(rm, 0);
4861 } else {
4862 tmp = tmp4;
4864 gen_neon_shift_narrow(size, tmp, tmp2, q,
4865 input_unsigned);
4866 if (pass == 0) {
4867 tmp3 = neon_load_reg(rm, 1);
4868 } else {
4869 tmp3 = tmp5;
4871 gen_neon_shift_narrow(size, tmp3, tmp2, q,
4872 input_unsigned);
4873 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
4874 tcg_temp_free_i32(tmp);
4875 tcg_temp_free_i32(tmp3);
4876 tmp = tcg_temp_new_i32();
4877 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
4878 neon_store_reg(rd, pass, tmp);
4879 } /* for pass */
4880 tcg_temp_free_i32(tmp2);
4882 } else if (op == 10) {
4883 /* VSHLL */
4884 if (q || size == 3)
4885 return 1;
4886 tmp = neon_load_reg(rm, 0);
4887 tmp2 = neon_load_reg(rm, 1);
4888 for (pass = 0; pass < 2; pass++) {
4889 if (pass == 1)
4890 tmp = tmp2;
4892 gen_neon_widen(cpu_V0, tmp, size, u);
4894 if (shift != 0) {
4895 /* The shift is less than the width of the source
4896 type, so we can just shift the whole register. */
4897 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
4898 /* Widen the result of shift: we need to clear
4899 * the potential overflow bits resulting from
4900 * left bits of the narrow input appearing as
4901 * right bits of left the neighbour narrow
4902 * input. */
4903 if (size < 2 || !u) {
4904 uint64_t imm64;
4905 if (size == 0) {
4906 imm = (0xffu >> (8 - shift));
4907 imm |= imm << 16;
4908 } else if (size == 1) {
4909 imm = 0xffff >> (16 - shift);
4910 } else {
4911 /* size == 2 */
4912 imm = 0xffffffff >> (32 - shift);
4914 if (size < 2) {
4915 imm64 = imm | (((uint64_t)imm) << 32);
4916 } else {
4917 imm64 = imm;
4919 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
4922 neon_store_reg64(cpu_V0, rd + pass);
4924 } else if (op >= 14) {
4925 /* VCVT fixed-point. */
4926 /* We have already masked out the must-be-1 top bit of imm6,
4927 * hence this 32-shift where the ARM ARM has 64-imm6.
4929 shift = 32 - shift;
4930 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4931 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
4932 if (!(op & 1)) {
4933 if (u)
4934 gen_vfp_ulto(0, shift);
4935 else
4936 gen_vfp_slto(0, shift);
4937 } else {
4938 if (u)
4939 gen_vfp_toul(0, shift);
4940 else
4941 gen_vfp_tosl(0, shift);
4943 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
4945 } else {
4946 return 1;
4948 } else { /* (insn & 0x00380080) == 0 */
4949 int invert;
4951 op = (insn >> 8) & 0xf;
4952 /* One register and immediate. */
4953 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4954 invert = (insn & (1 << 5)) != 0;
4955 switch (op) {
4956 case 0: case 1:
4957 /* no-op */
4958 break;
4959 case 2: case 3:
4960 imm <<= 8;
4961 break;
4962 case 4: case 5:
4963 imm <<= 16;
4964 break;
4965 case 6: case 7:
4966 imm <<= 24;
4967 break;
4968 case 8: case 9:
4969 imm |= imm << 16;
4970 break;
4971 case 10: case 11:
4972 imm = (imm << 8) | (imm << 24);
4973 break;
4974 case 12:
4975 imm = (imm << 8) | 0xff;
4976 break;
4977 case 13:
4978 imm = (imm << 16) | 0xffff;
4979 break;
4980 case 14:
4981 imm |= (imm << 8) | (imm << 16) | (imm << 24);
4982 if (invert)
4983 imm = ~imm;
4984 break;
4985 case 15:
4986 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
4987 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
4988 break;
4990 if (invert)
4991 imm = ~imm;
4993 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4994 if (op & 1 && op < 12) {
4995 tmp = neon_load_reg(rd, pass);
4996 if (invert) {
4997 /* The immediate value has already been inverted, so
4998 BIC becomes AND. */
4999 tcg_gen_andi_i32(tmp, tmp, imm);
5000 } else {
5001 tcg_gen_ori_i32(tmp, tmp, imm);
5003 } else {
5004 /* VMOV, VMVN. */
5005 tmp = tcg_temp_new_i32();
5006 if (op == 14 && invert) {
5007 uint32_t val;
5008 val = 0;
5009 for (n = 0; n < 4; n++) {
5010 if (imm & (1 << (n + (pass & 1) * 4)))
5011 val |= 0xff << (n * 8);
5013 tcg_gen_movi_i32(tmp, val);
5014 } else {
5015 tcg_gen_movi_i32(tmp, imm);
5018 neon_store_reg(rd, pass, tmp);
5021 } else { /* (insn & 0x00800010 == 0x00800000) */
5022 if (size != 3) {
5023 op = (insn >> 8) & 0xf;
5024 if ((insn & (1 << 6)) == 0) {
5025 /* Three registers of different lengths. */
5026 int src1_wide;
5027 int src2_wide;
5028 int prewiden;
5029 /* prewiden, src1_wide, src2_wide */
5030 static const int neon_3reg_wide[16][3] = {
5031 {1, 0, 0}, /* VADDL */
5032 {1, 1, 0}, /* VADDW */
5033 {1, 0, 0}, /* VSUBL */
5034 {1, 1, 0}, /* VSUBW */
5035 {0, 1, 1}, /* VADDHN */
5036 {0, 0, 0}, /* VABAL */
5037 {0, 1, 1}, /* VSUBHN */
5038 {0, 0, 0}, /* VABDL */
5039 {0, 0, 0}, /* VMLAL */
5040 {0, 0, 0}, /* VQDMLAL */
5041 {0, 0, 0}, /* VMLSL */
5042 {0, 0, 0}, /* VQDMLSL */
5043 {0, 0, 0}, /* Integer VMULL */
5044 {0, 0, 0}, /* VQDMULL */
5045 {0, 0, 0} /* Polynomial VMULL */
5048 prewiden = neon_3reg_wide[op][0];
5049 src1_wide = neon_3reg_wide[op][1];
5050 src2_wide = neon_3reg_wide[op][2];
5052 if (size == 0 && (op == 9 || op == 11 || op == 13))
5053 return 1;
5055 /* Avoid overlapping operands. Wide source operands are
5056 always aligned so will never overlap with wide
5057 destinations in problematic ways. */
5058 if (rd == rm && !src2_wide) {
5059 tmp = neon_load_reg(rm, 1);
5060 neon_store_scratch(2, tmp);
5061 } else if (rd == rn && !src1_wide) {
5062 tmp = neon_load_reg(rn, 1);
5063 neon_store_scratch(2, tmp);
5065 TCGV_UNUSED(tmp3);
5066 for (pass = 0; pass < 2; pass++) {
5067 if (src1_wide) {
5068 neon_load_reg64(cpu_V0, rn + pass);
5069 TCGV_UNUSED(tmp);
5070 } else {
5071 if (pass == 1 && rd == rn) {
5072 tmp = neon_load_scratch(2);
5073 } else {
5074 tmp = neon_load_reg(rn, pass);
5076 if (prewiden) {
5077 gen_neon_widen(cpu_V0, tmp, size, u);
5080 if (src2_wide) {
5081 neon_load_reg64(cpu_V1, rm + pass);
5082 TCGV_UNUSED(tmp2);
5083 } else {
5084 if (pass == 1 && rd == rm) {
5085 tmp2 = neon_load_scratch(2);
5086 } else {
5087 tmp2 = neon_load_reg(rm, pass);
5089 if (prewiden) {
5090 gen_neon_widen(cpu_V1, tmp2, size, u);
5093 switch (op) {
5094 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5095 gen_neon_addl(size);
5096 break;
5097 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
5098 gen_neon_subl(size);
5099 break;
5100 case 5: case 7: /* VABAL, VABDL */
5101 switch ((size << 1) | u) {
5102 case 0:
5103 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
5104 break;
5105 case 1:
5106 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
5107 break;
5108 case 2:
5109 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
5110 break;
5111 case 3:
5112 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
5113 break;
5114 case 4:
5115 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
5116 break;
5117 case 5:
5118 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
5119 break;
5120 default: abort();
5122 tcg_temp_free_i32(tmp2);
5123 tcg_temp_free_i32(tmp);
5124 break;
5125 case 8: case 9: case 10: case 11: case 12: case 13:
5126 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5127 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5128 break;
5129 case 14: /* Polynomial VMULL */
5130 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
5131 tcg_temp_free_i32(tmp2);
5132 tcg_temp_free_i32(tmp);
5133 break;
5134 default: /* 15 is RESERVED. */
5135 return 1;
5137 if (op == 13) {
5138 /* VQDMULL */
5139 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5140 neon_store_reg64(cpu_V0, rd + pass);
5141 } else if (op == 5 || (op >= 8 && op <= 11)) {
5142 /* Accumulate. */
5143 neon_load_reg64(cpu_V1, rd + pass);
5144 switch (op) {
5145 case 10: /* VMLSL */
5146 gen_neon_negl(cpu_V0, size);
5147 /* Fall through */
5148 case 5: case 8: /* VABAL, VMLAL */
5149 gen_neon_addl(size);
5150 break;
5151 case 9: case 11: /* VQDMLAL, VQDMLSL */
5152 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5153 if (op == 11) {
5154 gen_neon_negl(cpu_V0, size);
5156 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5157 break;
5158 default:
5159 abort();
5161 neon_store_reg64(cpu_V0, rd + pass);
5162 } else if (op == 4 || op == 6) {
5163 /* Narrowing operation. */
5164 tmp = tcg_temp_new_i32();
5165 if (!u) {
5166 switch (size) {
5167 case 0:
5168 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
5169 break;
5170 case 1:
5171 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
5172 break;
5173 case 2:
5174 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5175 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5176 break;
5177 default: abort();
5179 } else {
5180 switch (size) {
5181 case 0:
5182 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
5183 break;
5184 case 1:
5185 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
5186 break;
5187 case 2:
5188 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
5189 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5190 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5191 break;
5192 default: abort();
5195 if (pass == 0) {
5196 tmp3 = tmp;
5197 } else {
5198 neon_store_reg(rd, 0, tmp3);
5199 neon_store_reg(rd, 1, tmp);
5201 } else {
5202 /* Write back the result. */
5203 neon_store_reg64(cpu_V0, rd + pass);
5206 } else {
5207 /* Two registers and a scalar. */
5208 switch (op) {
5209 case 0: /* Integer VMLA scalar */
5210 case 1: /* Float VMLA scalar */
5211 case 4: /* Integer VMLS scalar */
5212 case 5: /* Floating point VMLS scalar */
5213 case 8: /* Integer VMUL scalar */
5214 case 9: /* Floating point VMUL scalar */
5215 case 12: /* VQDMULH scalar */
5216 case 13: /* VQRDMULH scalar */
5217 tmp = neon_get_scalar(size, rm);
5218 neon_store_scratch(0, tmp);
5219 for (pass = 0; pass < (u ? 4 : 2); pass++) {
5220 tmp = neon_load_scratch(0);
5221 tmp2 = neon_load_reg(rn, pass);
5222 if (op == 12) {
5223 if (size == 1) {
5224 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5225 } else {
5226 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5228 } else if (op == 13) {
5229 if (size == 1) {
5230 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5231 } else {
5232 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5234 } else if (op & 1) {
5235 gen_helper_neon_mul_f32(tmp, tmp, tmp2);
5236 } else {
5237 switch (size) {
5238 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5239 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5240 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5241 default: return 1;
5244 tcg_temp_free_i32(tmp2);
5245 if (op < 8) {
5246 /* Accumulate. */
5247 tmp2 = neon_load_reg(rd, pass);
5248 switch (op) {
5249 case 0:
5250 gen_neon_add(size, tmp, tmp2);
5251 break;
5252 case 1:
5253 gen_helper_neon_add_f32(tmp, tmp, tmp2);
5254 break;
5255 case 4:
5256 gen_neon_rsb(size, tmp, tmp2);
5257 break;
5258 case 5:
5259 gen_helper_neon_sub_f32(tmp, tmp2, tmp);
5260 break;
5261 default:
5262 abort();
5264 tcg_temp_free_i32(tmp2);
5266 neon_store_reg(rd, pass, tmp);
5268 break;
5269 case 2: /* VMLAL sclar */
5270 case 3: /* VQDMLAL scalar */
5271 case 6: /* VMLSL scalar */
5272 case 7: /* VQDMLSL scalar */
5273 case 10: /* VMULL scalar */
5274 case 11: /* VQDMULL scalar */
5275 if (size == 0 && (op == 3 || op == 7 || op == 11))
5276 return 1;
5278 tmp2 = neon_get_scalar(size, rm);
5279 /* We need a copy of tmp2 because gen_neon_mull
5280 * deletes it during pass 0. */
5281 tmp4 = tcg_temp_new_i32();
5282 tcg_gen_mov_i32(tmp4, tmp2);
5283 tmp3 = neon_load_reg(rn, 1);
5285 for (pass = 0; pass < 2; pass++) {
5286 if (pass == 0) {
5287 tmp = neon_load_reg(rn, 0);
5288 } else {
5289 tmp = tmp3;
5290 tmp2 = tmp4;
5292 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5293 if (op != 11) {
5294 neon_load_reg64(cpu_V1, rd + pass);
5296 switch (op) {
5297 case 6:
5298 gen_neon_negl(cpu_V0, size);
5299 /* Fall through */
5300 case 2:
5301 gen_neon_addl(size);
5302 break;
5303 case 3: case 7:
5304 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5305 if (op == 7) {
5306 gen_neon_negl(cpu_V0, size);
5308 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5309 break;
5310 case 10:
5311 /* no-op */
5312 break;
5313 case 11:
5314 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5315 break;
5316 default:
5317 abort();
5319 neon_store_reg64(cpu_V0, rd + pass);
5323 break;
5324 default: /* 14 and 15 are RESERVED */
5325 return 1;
5328 } else { /* size == 3 */
5329 if (!u) {
5330 /* Extract. */
5331 imm = (insn >> 8) & 0xf;
5333 if (imm > 7 && !q)
5334 return 1;
5336 if (imm == 0) {
5337 neon_load_reg64(cpu_V0, rn);
5338 if (q) {
5339 neon_load_reg64(cpu_V1, rn + 1);
5341 } else if (imm == 8) {
5342 neon_load_reg64(cpu_V0, rn + 1);
5343 if (q) {
5344 neon_load_reg64(cpu_V1, rm);
5346 } else if (q) {
5347 tmp64 = tcg_temp_new_i64();
5348 if (imm < 8) {
5349 neon_load_reg64(cpu_V0, rn);
5350 neon_load_reg64(tmp64, rn + 1);
5351 } else {
5352 neon_load_reg64(cpu_V0, rn + 1);
5353 neon_load_reg64(tmp64, rm);
5355 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5356 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
5357 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5358 if (imm < 8) {
5359 neon_load_reg64(cpu_V1, rm);
5360 } else {
5361 neon_load_reg64(cpu_V1, rm + 1);
5362 imm -= 8;
5364 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5365 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
5366 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
5367 tcg_temp_free_i64(tmp64);
5368 } else {
5369 /* BUGFIX */
5370 neon_load_reg64(cpu_V0, rn);
5371 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
5372 neon_load_reg64(cpu_V1, rm);
5373 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5374 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5376 neon_store_reg64(cpu_V0, rd);
5377 if (q) {
5378 neon_store_reg64(cpu_V1, rd + 1);
5380 } else if ((insn & (1 << 11)) == 0) {
5381 /* Two register misc. */
5382 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5383 size = (insn >> 18) & 3;
5384 switch (op) {
5385 case 0: /* VREV64 */
5386 if (size == 3)
5387 return 1;
5388 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5389 tmp = neon_load_reg(rm, pass * 2);
5390 tmp2 = neon_load_reg(rm, pass * 2 + 1);
5391 switch (size) {
5392 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5393 case 1: gen_swap_half(tmp); break;
5394 case 2: /* no-op */ break;
5395 default: abort();
5397 neon_store_reg(rd, pass * 2 + 1, tmp);
5398 if (size == 2) {
5399 neon_store_reg(rd, pass * 2, tmp2);
5400 } else {
5401 switch (size) {
5402 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
5403 case 1: gen_swap_half(tmp2); break;
5404 default: abort();
5406 neon_store_reg(rd, pass * 2, tmp2);
5409 break;
5410 case 4: case 5: /* VPADDL */
5411 case 12: case 13: /* VPADAL */
5412 if (size == 3)
5413 return 1;
5414 for (pass = 0; pass < q + 1; pass++) {
5415 tmp = neon_load_reg(rm, pass * 2);
5416 gen_neon_widen(cpu_V0, tmp, size, op & 1);
5417 tmp = neon_load_reg(rm, pass * 2 + 1);
5418 gen_neon_widen(cpu_V1, tmp, size, op & 1);
5419 switch (size) {
5420 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5421 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5422 case 2: tcg_gen_add_i64(CPU_V001); break;
5423 default: abort();
5425 if (op >= 12) {
5426 /* Accumulate. */
5427 neon_load_reg64(cpu_V1, rd + pass);
5428 gen_neon_addl(size);
5430 neon_store_reg64(cpu_V0, rd + pass);
5432 break;
5433 case 33: /* VTRN */
5434 if (size == 2) {
5435 for (n = 0; n < (q ? 4 : 2); n += 2) {
5436 tmp = neon_load_reg(rm, n);
5437 tmp2 = neon_load_reg(rd, n + 1);
5438 neon_store_reg(rm, n, tmp2);
5439 neon_store_reg(rd, n + 1, tmp);
5441 } else {
5442 goto elementwise;
5444 break;
5445 case 34: /* VUZP */
5446 if (gen_neon_unzip(rd, rm, size, q)) {
5447 return 1;
5449 break;
5450 case 35: /* VZIP */
5451 if (gen_neon_zip(rd, rm, size, q)) {
5452 return 1;
5454 break;
5455 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5456 if (size == 3)
5457 return 1;
5458 TCGV_UNUSED(tmp2);
5459 for (pass = 0; pass < 2; pass++) {
5460 neon_load_reg64(cpu_V0, rm + pass);
5461 tmp = tcg_temp_new_i32();
5462 gen_neon_narrow_op(op == 36, q, size, tmp, cpu_V0);
5463 if (pass == 0) {
5464 tmp2 = tmp;
5465 } else {
5466 neon_store_reg(rd, 0, tmp2);
5467 neon_store_reg(rd, 1, tmp);
5470 break;
5471 case 38: /* VSHLL */
5472 if (q || size == 3)
5473 return 1;
5474 tmp = neon_load_reg(rm, 0);
5475 tmp2 = neon_load_reg(rm, 1);
5476 for (pass = 0; pass < 2; pass++) {
5477 if (pass == 1)
5478 tmp = tmp2;
5479 gen_neon_widen(cpu_V0, tmp, size, 1);
5480 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
5481 neon_store_reg64(cpu_V0, rd + pass);
5483 break;
5484 case 44: /* VCVT.F16.F32 */
5485 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
5486 return 1;
5487 tmp = tcg_temp_new_i32();
5488 tmp2 = tcg_temp_new_i32();
5489 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
5490 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5491 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
5492 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
5493 tcg_gen_shli_i32(tmp2, tmp2, 16);
5494 tcg_gen_or_i32(tmp2, tmp2, tmp);
5495 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
5496 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5497 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
5498 neon_store_reg(rd, 0, tmp2);
5499 tmp2 = tcg_temp_new_i32();
5500 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
5501 tcg_gen_shli_i32(tmp2, tmp2, 16);
5502 tcg_gen_or_i32(tmp2, tmp2, tmp);
5503 neon_store_reg(rd, 1, tmp2);
5504 tcg_temp_free_i32(tmp);
5505 break;
5506 case 46: /* VCVT.F32.F16 */
5507 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
5508 return 1;
5509 tmp3 = tcg_temp_new_i32();
5510 tmp = neon_load_reg(rm, 0);
5511 tmp2 = neon_load_reg(rm, 1);
5512 tcg_gen_ext16u_i32(tmp3, tmp);
5513 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5514 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
5515 tcg_gen_shri_i32(tmp3, tmp, 16);
5516 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5517 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
5518 tcg_temp_free_i32(tmp);
5519 tcg_gen_ext16u_i32(tmp3, tmp2);
5520 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5521 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
5522 tcg_gen_shri_i32(tmp3, tmp2, 16);
5523 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5524 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
5525 tcg_temp_free_i32(tmp2);
5526 tcg_temp_free_i32(tmp3);
5527 break;
5528 default:
5529 elementwise:
5530 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5531 if (op == 30 || op == 31 || op >= 58) {
5532 tcg_gen_ld_f32(cpu_F0s, cpu_env,
5533 neon_reg_offset(rm, pass));
5534 TCGV_UNUSED(tmp);
5535 } else {
5536 tmp = neon_load_reg(rm, pass);
5538 switch (op) {
5539 case 1: /* VREV32 */
5540 switch (size) {
5541 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5542 case 1: gen_swap_half(tmp); break;
5543 default: return 1;
5545 break;
5546 case 2: /* VREV16 */
5547 if (size != 0)
5548 return 1;
5549 gen_rev16(tmp);
5550 break;
5551 case 8: /* CLS */
5552 switch (size) {
5553 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
5554 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
5555 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
5556 default: return 1;
5558 break;
5559 case 9: /* CLZ */
5560 switch (size) {
5561 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
5562 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
5563 case 2: gen_helper_clz(tmp, tmp); break;
5564 default: return 1;
5566 break;
5567 case 10: /* CNT */
5568 if (size != 0)
5569 return 1;
5570 gen_helper_neon_cnt_u8(tmp, tmp);
5571 break;
5572 case 11: /* VNOT */
5573 if (size != 0)
5574 return 1;
5575 tcg_gen_not_i32(tmp, tmp);
5576 break;
5577 case 14: /* VQABS */
5578 switch (size) {
5579 case 0: gen_helper_neon_qabs_s8(tmp, cpu_env, tmp); break;
5580 case 1: gen_helper_neon_qabs_s16(tmp, cpu_env, tmp); break;
5581 case 2: gen_helper_neon_qabs_s32(tmp, cpu_env, tmp); break;
5582 default: return 1;
5584 break;
5585 case 15: /* VQNEG */
5586 switch (size) {
5587 case 0: gen_helper_neon_qneg_s8(tmp, cpu_env, tmp); break;
5588 case 1: gen_helper_neon_qneg_s16(tmp, cpu_env, tmp); break;
5589 case 2: gen_helper_neon_qneg_s32(tmp, cpu_env, tmp); break;
5590 default: return 1;
5592 break;
5593 case 16: case 19: /* VCGT #0, VCLE #0 */
5594 tmp2 = tcg_const_i32(0);
5595 switch(size) {
5596 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
5597 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
5598 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
5599 default: return 1;
5601 tcg_temp_free(tmp2);
5602 if (op == 19)
5603 tcg_gen_not_i32(tmp, tmp);
5604 break;
5605 case 17: case 20: /* VCGE #0, VCLT #0 */
5606 tmp2 = tcg_const_i32(0);
5607 switch(size) {
5608 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
5609 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
5610 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
5611 default: return 1;
5613 tcg_temp_free(tmp2);
5614 if (op == 20)
5615 tcg_gen_not_i32(tmp, tmp);
5616 break;
5617 case 18: /* VCEQ #0 */
5618 tmp2 = tcg_const_i32(0);
5619 switch(size) {
5620 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
5621 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
5622 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
5623 default: return 1;
5625 tcg_temp_free(tmp2);
5626 break;
5627 case 22: /* VABS */
5628 switch(size) {
5629 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
5630 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
5631 case 2: tcg_gen_abs_i32(tmp, tmp); break;
5632 default: return 1;
5634 break;
5635 case 23: /* VNEG */
5636 if (size == 3)
5637 return 1;
5638 tmp2 = tcg_const_i32(0);
5639 gen_neon_rsb(size, tmp, tmp2);
5640 tcg_temp_free(tmp2);
5641 break;
5642 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5643 tmp2 = tcg_const_i32(0);
5644 gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
5645 tcg_temp_free(tmp2);
5646 if (op == 27)
5647 tcg_gen_not_i32(tmp, tmp);
5648 break;
5649 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5650 tmp2 = tcg_const_i32(0);
5651 gen_helper_neon_cge_f32(tmp, tmp, tmp2);
5652 tcg_temp_free(tmp2);
5653 if (op == 28)
5654 tcg_gen_not_i32(tmp, tmp);
5655 break;
5656 case 26: /* Float VCEQ #0 */
5657 tmp2 = tcg_const_i32(0);
5658 gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
5659 tcg_temp_free(tmp2);
5660 break;
5661 case 30: /* Float VABS */
5662 gen_vfp_abs(0);
5663 break;
5664 case 31: /* Float VNEG */
5665 gen_vfp_neg(0);
5666 break;
5667 case 32: /* VSWP */
5668 tmp2 = neon_load_reg(rd, pass);
5669 neon_store_reg(rm, pass, tmp2);
5670 break;
5671 case 33: /* VTRN */
5672 tmp2 = neon_load_reg(rd, pass);
5673 switch (size) {
5674 case 0: gen_neon_trn_u8(tmp, tmp2); break;
5675 case 1: gen_neon_trn_u16(tmp, tmp2); break;
5676 case 2: abort();
5677 default: return 1;
5679 neon_store_reg(rm, pass, tmp2);
5680 break;
5681 case 56: /* Integer VRECPE */
5682 gen_helper_recpe_u32(tmp, tmp, cpu_env);
5683 break;
5684 case 57: /* Integer VRSQRTE */
5685 gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
5686 break;
5687 case 58: /* Float VRECPE */
5688 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
5689 break;
5690 case 59: /* Float VRSQRTE */
5691 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
5692 break;
5693 case 60: /* VCVT.F32.S32 */
5694 gen_vfp_sito(0);
5695 break;
5696 case 61: /* VCVT.F32.U32 */
5697 gen_vfp_uito(0);
5698 break;
5699 case 62: /* VCVT.S32.F32 */
5700 gen_vfp_tosiz(0);
5701 break;
5702 case 63: /* VCVT.U32.F32 */
5703 gen_vfp_touiz(0);
5704 break;
5705 default:
5706 /* Reserved: 21, 29, 39-56 */
5707 return 1;
5709 if (op == 30 || op == 31 || op >= 58) {
5710 tcg_gen_st_f32(cpu_F0s, cpu_env,
5711 neon_reg_offset(rd, pass));
5712 } else {
5713 neon_store_reg(rd, pass, tmp);
5716 break;
5718 } else if ((insn & (1 << 10)) == 0) {
5719 /* VTBL, VTBX. */
5720 n = ((insn >> 5) & 0x18) + 8;
5721 if (insn & (1 << 6)) {
5722 tmp = neon_load_reg(rd, 0);
5723 } else {
5724 tmp = tcg_temp_new_i32();
5725 tcg_gen_movi_i32(tmp, 0);
5727 tmp2 = neon_load_reg(rm, 0);
5728 tmp4 = tcg_const_i32(rn);
5729 tmp5 = tcg_const_i32(n);
5730 gen_helper_neon_tbl(tmp2, tmp2, tmp, tmp4, tmp5);
5731 tcg_temp_free_i32(tmp);
5732 if (insn & (1 << 6)) {
5733 tmp = neon_load_reg(rd, 1);
5734 } else {
5735 tmp = tcg_temp_new_i32();
5736 tcg_gen_movi_i32(tmp, 0);
5738 tmp3 = neon_load_reg(rm, 1);
5739 gen_helper_neon_tbl(tmp3, tmp3, tmp, tmp4, tmp5);
5740 tcg_temp_free_i32(tmp5);
5741 tcg_temp_free_i32(tmp4);
5742 neon_store_reg(rd, 0, tmp2);
5743 neon_store_reg(rd, 1, tmp3);
5744 tcg_temp_free_i32(tmp);
5745 } else if ((insn & 0x380) == 0) {
5746 /* VDUP */
5747 if (insn & (1 << 19)) {
5748 tmp = neon_load_reg(rm, 1);
5749 } else {
5750 tmp = neon_load_reg(rm, 0);
5752 if (insn & (1 << 16)) {
5753 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
5754 } else if (insn & (1 << 17)) {
5755 if ((insn >> 18) & 1)
5756 gen_neon_dup_high16(tmp);
5757 else
5758 gen_neon_dup_low16(tmp);
5760 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5761 tmp2 = tcg_temp_new_i32();
5762 tcg_gen_mov_i32(tmp2, tmp);
5763 neon_store_reg(rd, pass, tmp2);
5765 tcg_temp_free_i32(tmp);
5766 } else {
5767 return 1;
5771 return 0;
5774 static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
5776 int crn = (insn >> 16) & 0xf;
5777 int crm = insn & 0xf;
5778 int op1 = (insn >> 21) & 7;
5779 int op2 = (insn >> 5) & 7;
5780 int rt = (insn >> 12) & 0xf;
5781 TCGv tmp;
5783 /* Minimal set of debug registers, since we don't support debug */
5784 if (op1 == 0 && crn == 0 && op2 == 0) {
5785 switch (crm) {
5786 case 0:
5787 /* DBGDIDR: just RAZ. In particular this means the
5788 * "debug architecture version" bits will read as
5789 * a reserved value, which should cause Linux to
5790 * not try to use the debug hardware.
5792 tmp = tcg_const_i32(0);
5793 store_reg(s, rt, tmp);
5794 return 0;
5795 case 1:
5796 case 2:
5797 /* DBGDRAR and DBGDSAR: v7 only. Always RAZ since we
5798 * don't implement memory mapped debug components
5800 if (ENABLE_ARCH_7) {
5801 tmp = tcg_const_i32(0);
5802 store_reg(s, rt, tmp);
5803 return 0;
5805 break;
5806 default:
5807 break;
5811 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5812 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5813 /* TEECR */
5814 if (IS_USER(s))
5815 return 1;
5816 tmp = load_cpu_field(teecr);
5817 store_reg(s, rt, tmp);
5818 return 0;
5820 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5821 /* TEEHBR */
5822 if (IS_USER(s) && (env->teecr & 1))
5823 return 1;
5824 tmp = load_cpu_field(teehbr);
5825 store_reg(s, rt, tmp);
5826 return 0;
5829 fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5830 op1, crn, crm, op2);
5831 return 1;
5834 static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
5836 int crn = (insn >> 16) & 0xf;
5837 int crm = insn & 0xf;
5838 int op1 = (insn >> 21) & 7;
5839 int op2 = (insn >> 5) & 7;
5840 int rt = (insn >> 12) & 0xf;
5841 TCGv tmp;
5843 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5844 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5845 /* TEECR */
5846 if (IS_USER(s))
5847 return 1;
5848 tmp = load_reg(s, rt);
5849 gen_helper_set_teecr(cpu_env, tmp);
5850 tcg_temp_free_i32(tmp);
5851 return 0;
5853 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5854 /* TEEHBR */
5855 if (IS_USER(s) && (env->teecr & 1))
5856 return 1;
5857 tmp = load_reg(s, rt);
5858 store_cpu_field(tmp, teehbr);
5859 return 0;
5862 fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5863 op1, crn, crm, op2);
5864 return 1;
5867 static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
5869 int cpnum;
5871 cpnum = (insn >> 8) & 0xf;
5872 if (arm_feature(env, ARM_FEATURE_XSCALE)
5873 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
5874 return 1;
5876 switch (cpnum) {
5877 case 0:
5878 case 1:
5879 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5880 return disas_iwmmxt_insn(env, s, insn);
5881 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
5882 return disas_dsp_insn(env, s, insn);
5884 return 1;
5885 case 10:
5886 case 11:
5887 return disas_vfp_insn (env, s, insn);
5888 case 14:
5889 /* Coprocessors 7-15 are architecturally reserved by ARM.
5890 Unfortunately Intel decided to ignore this. */
5891 if (arm_feature(env, ARM_FEATURE_XSCALE))
5892 goto board;
5893 if (insn & (1 << 20))
5894 return disas_cp14_read(env, s, insn);
5895 else
5896 return disas_cp14_write(env, s, insn);
5897 case 15:
5898 return disas_cp15_insn (env, s, insn);
5899 default:
5900 board:
5901 /* Unknown coprocessor. See if the board has hooked it. */
5902 return disas_cp_insn (env, s, insn);
5907 /* Store a 64-bit value to a register pair. Clobbers val. */
5908 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5910 TCGv tmp;
5911 tmp = tcg_temp_new_i32();
5912 tcg_gen_trunc_i64_i32(tmp, val);
5913 store_reg(s, rlow, tmp);
5914 tmp = tcg_temp_new_i32();
5915 tcg_gen_shri_i64(val, val, 32);
5916 tcg_gen_trunc_i64_i32(tmp, val);
5917 store_reg(s, rhigh, tmp);
5920 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5921 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5923 TCGv_i64 tmp;
5924 TCGv tmp2;
5926 /* Load value and extend to 64 bits. */
5927 tmp = tcg_temp_new_i64();
5928 tmp2 = load_reg(s, rlow);
5929 tcg_gen_extu_i32_i64(tmp, tmp2);
5930 tcg_temp_free_i32(tmp2);
5931 tcg_gen_add_i64(val, val, tmp);
5932 tcg_temp_free_i64(tmp);
5935 /* load and add a 64-bit value from a register pair. */
5936 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5938 TCGv_i64 tmp;
5939 TCGv tmpl;
5940 TCGv tmph;
5942 /* Load 64-bit value rd:rn. */
5943 tmpl = load_reg(s, rlow);
5944 tmph = load_reg(s, rhigh);
5945 tmp = tcg_temp_new_i64();
5946 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
5947 tcg_temp_free_i32(tmpl);
5948 tcg_temp_free_i32(tmph);
5949 tcg_gen_add_i64(val, val, tmp);
5950 tcg_temp_free_i64(tmp);
5953 /* Set N and Z flags from a 64-bit value. */
5954 static void gen_logicq_cc(TCGv_i64 val)
5956 TCGv tmp = tcg_temp_new_i32();
5957 gen_helper_logicq_cc(tmp, val);
5958 gen_logic_CC(tmp);
5959 tcg_temp_free_i32(tmp);
5962 /* Load/Store exclusive instructions are implemented by remembering
5963 the value/address loaded, and seeing if these are the same
5964 when the store is performed. This should be is sufficient to implement
5965 the architecturally mandated semantics, and avoids having to monitor
5966 regular stores.
5968 In system emulation mode only one CPU will be running at once, so
5969 this sequence is effectively atomic. In user emulation mode we
5970 throw an exception and handle the atomic operation elsewhere. */
5971 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
5972 TCGv addr, int size)
5974 TCGv tmp;
5976 switch (size) {
5977 case 0:
5978 tmp = gen_ld8u(addr, IS_USER(s));
5979 break;
5980 case 1:
5981 tmp = gen_ld16u(addr, IS_USER(s));
5982 break;
5983 case 2:
5984 case 3:
5985 tmp = gen_ld32(addr, IS_USER(s));
5986 break;
5987 default:
5988 abort();
5990 tcg_gen_mov_i32(cpu_exclusive_val, tmp);
5991 store_reg(s, rt, tmp);
5992 if (size == 3) {
5993 TCGv tmp2 = tcg_temp_new_i32();
5994 tcg_gen_addi_i32(tmp2, addr, 4);
5995 tmp = gen_ld32(tmp2, IS_USER(s));
5996 tcg_temp_free_i32(tmp2);
5997 tcg_gen_mov_i32(cpu_exclusive_high, tmp);
5998 store_reg(s, rt2, tmp);
6000 tcg_gen_mov_i32(cpu_exclusive_addr, addr);
6003 static void gen_clrex(DisasContext *s)
6005 tcg_gen_movi_i32(cpu_exclusive_addr, -1);
6008 #ifdef CONFIG_USER_ONLY
6009 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
6010 TCGv addr, int size)
6012 tcg_gen_mov_i32(cpu_exclusive_test, addr);
6013 tcg_gen_movi_i32(cpu_exclusive_info,
6014 size | (rd << 4) | (rt << 8) | (rt2 << 12));
6015 gen_exception_insn(s, 4, EXCP_STREX);
6017 #else
6018 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
6019 TCGv addr, int size)
6021 TCGv tmp;
6022 int done_label;
6023 int fail_label;
6025 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
6026 [addr] = {Rt};
6027 {Rd} = 0;
6028 } else {
6029 {Rd} = 1;
6030 } */
6031 fail_label = gen_new_label();
6032 done_label = gen_new_label();
6033 tcg_gen_brcond_i32(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
6034 switch (size) {
6035 case 0:
6036 tmp = gen_ld8u(addr, IS_USER(s));
6037 break;
6038 case 1:
6039 tmp = gen_ld16u(addr, IS_USER(s));
6040 break;
6041 case 2:
6042 case 3:
6043 tmp = gen_ld32(addr, IS_USER(s));
6044 break;
6045 default:
6046 abort();
6048 tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label);
6049 tcg_temp_free_i32(tmp);
6050 if (size == 3) {
6051 TCGv tmp2 = tcg_temp_new_i32();
6052 tcg_gen_addi_i32(tmp2, addr, 4);
6053 tmp = gen_ld32(tmp2, IS_USER(s));
6054 tcg_temp_free_i32(tmp2);
6055 tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_high, fail_label);
6056 tcg_temp_free_i32(tmp);
6058 tmp = load_reg(s, rt);
6059 switch (size) {
6060 case 0:
6061 gen_st8(tmp, addr, IS_USER(s));
6062 break;
6063 case 1:
6064 gen_st16(tmp, addr, IS_USER(s));
6065 break;
6066 case 2:
6067 case 3:
6068 gen_st32(tmp, addr, IS_USER(s));
6069 break;
6070 default:
6071 abort();
6073 if (size == 3) {
6074 tcg_gen_addi_i32(addr, addr, 4);
6075 tmp = load_reg(s, rt2);
6076 gen_st32(tmp, addr, IS_USER(s));
6078 tcg_gen_movi_i32(cpu_R[rd], 0);
6079 tcg_gen_br(done_label);
6080 gen_set_label(fail_label);
6081 tcg_gen_movi_i32(cpu_R[rd], 1);
6082 gen_set_label(done_label);
6083 tcg_gen_movi_i32(cpu_exclusive_addr, -1);
6085 #endif
6087 static void disas_arm_insn(CPUState * env, DisasContext *s)
6089 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
6090 TCGv tmp;
6091 TCGv tmp2;
6092 TCGv tmp3;
6093 TCGv addr;
6094 TCGv_i64 tmp64;
6096 insn = ldl_code(s->pc);
6097 s->pc += 4;
6099 /* M variants do not implement ARM mode. */
6100 if (IS_M(env))
6101 goto illegal_op;
6102 cond = insn >> 28;
6103 if (cond == 0xf){
6104 /* Unconditional instructions. */
6105 if (((insn >> 25) & 7) == 1) {
6106 /* NEON Data processing. */
6107 if (!arm_feature(env, ARM_FEATURE_NEON))
6108 goto illegal_op;
6110 if (disas_neon_data_insn(env, s, insn))
6111 goto illegal_op;
6112 return;
6114 if ((insn & 0x0f100000) == 0x04000000) {
6115 /* NEON load/store. */
6116 if (!arm_feature(env, ARM_FEATURE_NEON))
6117 goto illegal_op;
6119 if (disas_neon_ls_insn(env, s, insn))
6120 goto illegal_op;
6121 return;
6123 if (((insn & 0x0f30f000) == 0x0510f000) ||
6124 ((insn & 0x0f30f010) == 0x0710f000)) {
6125 if ((insn & (1 << 22)) == 0) {
6126 /* PLDW; v7MP */
6127 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
6128 goto illegal_op;
6131 /* Otherwise PLD; v5TE+ */
6132 return;
6134 if (((insn & 0x0f70f000) == 0x0450f000) ||
6135 ((insn & 0x0f70f010) == 0x0650f000)) {
6136 ARCH(7);
6137 return; /* PLI; V7 */
6139 if (((insn & 0x0f700000) == 0x04100000) ||
6140 ((insn & 0x0f700010) == 0x06100000)) {
6141 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
6142 goto illegal_op;
6144 return; /* v7MP: Unallocated memory hint: must NOP */
6147 if ((insn & 0x0ffffdff) == 0x01010000) {
6148 ARCH(6);
6149 /* setend */
6150 if (insn & (1 << 9)) {
6151 /* BE8 mode not implemented. */
6152 goto illegal_op;
6154 return;
6155 } else if ((insn & 0x0fffff00) == 0x057ff000) {
6156 switch ((insn >> 4) & 0xf) {
6157 case 1: /* clrex */
6158 ARCH(6K);
6159 gen_clrex(s);
6160 return;
6161 case 4: /* dsb */
6162 case 5: /* dmb */
6163 case 6: /* isb */
6164 ARCH(7);
6165 /* We don't emulate caches so these are a no-op. */
6166 return;
6167 default:
6168 goto illegal_op;
6170 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
6171 /* srs */
6172 int32_t offset;
6173 if (IS_USER(s))
6174 goto illegal_op;
6175 ARCH(6);
6176 op1 = (insn & 0x1f);
6177 addr = tcg_temp_new_i32();
6178 tmp = tcg_const_i32(op1);
6179 gen_helper_get_r13_banked(addr, cpu_env, tmp);
6180 tcg_temp_free_i32(tmp);
6181 i = (insn >> 23) & 3;
6182 switch (i) {
6183 case 0: offset = -4; break; /* DA */
6184 case 1: offset = 0; break; /* IA */
6185 case 2: offset = -8; break; /* DB */
6186 case 3: offset = 4; break; /* IB */
6187 default: abort();
6189 if (offset)
6190 tcg_gen_addi_i32(addr, addr, offset);
6191 tmp = load_reg(s, 14);
6192 gen_st32(tmp, addr, 0);
6193 tmp = load_cpu_field(spsr);
6194 tcg_gen_addi_i32(addr, addr, 4);
6195 gen_st32(tmp, addr, 0);
6196 if (insn & (1 << 21)) {
6197 /* Base writeback. */
6198 switch (i) {
6199 case 0: offset = -8; break;
6200 case 1: offset = 4; break;
6201 case 2: offset = -4; break;
6202 case 3: offset = 0; break;
6203 default: abort();
6205 if (offset)
6206 tcg_gen_addi_i32(addr, addr, offset);
6207 tmp = tcg_const_i32(op1);
6208 gen_helper_set_r13_banked(cpu_env, tmp, addr);
6209 tcg_temp_free_i32(tmp);
6210 tcg_temp_free_i32(addr);
6211 } else {
6212 tcg_temp_free_i32(addr);
6214 return;
6215 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
6216 /* rfe */
6217 int32_t offset;
6218 if (IS_USER(s))
6219 goto illegal_op;
6220 ARCH(6);
6221 rn = (insn >> 16) & 0xf;
6222 addr = load_reg(s, rn);
6223 i = (insn >> 23) & 3;
6224 switch (i) {
6225 case 0: offset = -4; break; /* DA */
6226 case 1: offset = 0; break; /* IA */
6227 case 2: offset = -8; break; /* DB */
6228 case 3: offset = 4; break; /* IB */
6229 default: abort();
6231 if (offset)
6232 tcg_gen_addi_i32(addr, addr, offset);
6233 /* Load PC into tmp and CPSR into tmp2. */
6234 tmp = gen_ld32(addr, 0);
6235 tcg_gen_addi_i32(addr, addr, 4);
6236 tmp2 = gen_ld32(addr, 0);
6237 if (insn & (1 << 21)) {
6238 /* Base writeback. */
6239 switch (i) {
6240 case 0: offset = -8; break;
6241 case 1: offset = 4; break;
6242 case 2: offset = -4; break;
6243 case 3: offset = 0; break;
6244 default: abort();
6246 if (offset)
6247 tcg_gen_addi_i32(addr, addr, offset);
6248 store_reg(s, rn, addr);
6249 } else {
6250 tcg_temp_free_i32(addr);
6252 gen_rfe(s, tmp, tmp2);
6253 return;
6254 } else if ((insn & 0x0e000000) == 0x0a000000) {
6255 /* branch link and change to thumb (blx <offset>) */
6256 int32_t offset;
6258 val = (uint32_t)s->pc;
6259 tmp = tcg_temp_new_i32();
6260 tcg_gen_movi_i32(tmp, val);
6261 store_reg(s, 14, tmp);
6262 /* Sign-extend the 24-bit offset */
6263 offset = (((int32_t)insn) << 8) >> 8;
6264 /* offset * 4 + bit24 * 2 + (thumb bit) */
6265 val += (offset << 2) | ((insn >> 23) & 2) | 1;
6266 /* pipeline offset */
6267 val += 4;
6268 gen_bx_im(s, val);
6269 return;
6270 } else if ((insn & 0x0e000f00) == 0x0c000100) {
6271 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
6272 /* iWMMXt register transfer. */
6273 if (env->cp15.c15_cpar & (1 << 1))
6274 if (!disas_iwmmxt_insn(env, s, insn))
6275 return;
6277 } else if ((insn & 0x0fe00000) == 0x0c400000) {
6278 /* Coprocessor double register transfer. */
6279 } else if ((insn & 0x0f000010) == 0x0e000010) {
6280 /* Additional coprocessor register transfer. */
6281 } else if ((insn & 0x0ff10020) == 0x01000000) {
6282 uint32_t mask;
6283 uint32_t val;
6284 /* cps (privileged) */
6285 if (IS_USER(s))
6286 return;
6287 mask = val = 0;
6288 if (insn & (1 << 19)) {
6289 if (insn & (1 << 8))
6290 mask |= CPSR_A;
6291 if (insn & (1 << 7))
6292 mask |= CPSR_I;
6293 if (insn & (1 << 6))
6294 mask |= CPSR_F;
6295 if (insn & (1 << 18))
6296 val |= mask;
6298 if (insn & (1 << 17)) {
6299 mask |= CPSR_M;
6300 val |= (insn & 0x1f);
6302 if (mask) {
6303 gen_set_psr_im(s, mask, 0, val);
6305 return;
6307 goto illegal_op;
6309 if (cond != 0xe) {
6310 /* if not always execute, we generate a conditional jump to
6311 next instruction */
6312 s->condlabel = gen_new_label();
6313 gen_test_cc(cond ^ 1, s->condlabel);
6314 s->condjmp = 1;
6316 if ((insn & 0x0f900000) == 0x03000000) {
6317 if ((insn & (1 << 21)) == 0) {
6318 ARCH(6T2);
6319 rd = (insn >> 12) & 0xf;
6320 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
6321 if ((insn & (1 << 22)) == 0) {
6322 /* MOVW */
6323 tmp = tcg_temp_new_i32();
6324 tcg_gen_movi_i32(tmp, val);
6325 } else {
6326 /* MOVT */
6327 tmp = load_reg(s, rd);
6328 tcg_gen_ext16u_i32(tmp, tmp);
6329 tcg_gen_ori_i32(tmp, tmp, val << 16);
6331 store_reg(s, rd, tmp);
6332 } else {
6333 if (((insn >> 12) & 0xf) != 0xf)
6334 goto illegal_op;
6335 if (((insn >> 16) & 0xf) == 0) {
6336 gen_nop_hint(s, insn & 0xff);
6337 } else {
6338 /* CPSR = immediate */
6339 val = insn & 0xff;
6340 shift = ((insn >> 8) & 0xf) * 2;
6341 if (shift)
6342 val = (val >> shift) | (val << (32 - shift));
6343 i = ((insn & (1 << 22)) != 0);
6344 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
6345 goto illegal_op;
6348 } else if ((insn & 0x0f900000) == 0x01000000
6349 && (insn & 0x00000090) != 0x00000090) {
6350 /* miscellaneous instructions */
6351 op1 = (insn >> 21) & 3;
6352 sh = (insn >> 4) & 0xf;
6353 rm = insn & 0xf;
6354 switch (sh) {
6355 case 0x0: /* move program status register */
6356 if (op1 & 1) {
6357 /* PSR = reg */
6358 tmp = load_reg(s, rm);
6359 i = ((op1 & 2) != 0);
6360 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
6361 goto illegal_op;
6362 } else {
6363 /* reg = PSR */
6364 rd = (insn >> 12) & 0xf;
6365 if (op1 & 2) {
6366 if (IS_USER(s))
6367 goto illegal_op;
6368 tmp = load_cpu_field(spsr);
6369 } else {
6370 tmp = tcg_temp_new_i32();
6371 gen_helper_cpsr_read(tmp);
6373 store_reg(s, rd, tmp);
6375 break;
6376 case 0x1:
6377 if (op1 == 1) {
6378 /* branch/exchange thumb (bx). */
6379 tmp = load_reg(s, rm);
6380 gen_bx(s, tmp);
6381 } else if (op1 == 3) {
6382 /* clz */
6383 rd = (insn >> 12) & 0xf;
6384 tmp = load_reg(s, rm);
6385 gen_helper_clz(tmp, tmp);
6386 store_reg(s, rd, tmp);
6387 } else {
6388 goto illegal_op;
6390 break;
6391 case 0x2:
6392 if (op1 == 1) {
6393 ARCH(5J); /* bxj */
6394 /* Trivial implementation equivalent to bx. */
6395 tmp = load_reg(s, rm);
6396 gen_bx(s, tmp);
6397 } else {
6398 goto illegal_op;
6400 break;
6401 case 0x3:
6402 if (op1 != 1)
6403 goto illegal_op;
6405 /* branch link/exchange thumb (blx) */
6406 tmp = load_reg(s, rm);
6407 tmp2 = tcg_temp_new_i32();
6408 tcg_gen_movi_i32(tmp2, s->pc);
6409 store_reg(s, 14, tmp2);
6410 gen_bx(s, tmp);
6411 break;
6412 case 0x5: /* saturating add/subtract */
6413 rd = (insn >> 12) & 0xf;
6414 rn = (insn >> 16) & 0xf;
6415 tmp = load_reg(s, rm);
6416 tmp2 = load_reg(s, rn);
6417 if (op1 & 2)
6418 gen_helper_double_saturate(tmp2, tmp2);
6419 if (op1 & 1)
6420 gen_helper_sub_saturate(tmp, tmp, tmp2);
6421 else
6422 gen_helper_add_saturate(tmp, tmp, tmp2);
6423 tcg_temp_free_i32(tmp2);
6424 store_reg(s, rd, tmp);
6425 break;
6426 case 7:
6427 /* SMC instruction (op1 == 3)
6428 and undefined instructions (op1 == 0 || op1 == 2)
6429 will trap */
6430 if (op1 != 1) {
6431 goto illegal_op;
6433 /* bkpt */
6434 gen_exception_insn(s, 4, EXCP_BKPT);
6435 break;
6436 case 0x8: /* signed multiply */
6437 case 0xa:
6438 case 0xc:
6439 case 0xe:
6440 rs = (insn >> 8) & 0xf;
6441 rn = (insn >> 12) & 0xf;
6442 rd = (insn >> 16) & 0xf;
6443 if (op1 == 1) {
6444 /* (32 * 16) >> 16 */
6445 tmp = load_reg(s, rm);
6446 tmp2 = load_reg(s, rs);
6447 if (sh & 4)
6448 tcg_gen_sari_i32(tmp2, tmp2, 16);
6449 else
6450 gen_sxth(tmp2);
6451 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6452 tcg_gen_shri_i64(tmp64, tmp64, 16);
6453 tmp = tcg_temp_new_i32();
6454 tcg_gen_trunc_i64_i32(tmp, tmp64);
6455 tcg_temp_free_i64(tmp64);
6456 if ((sh & 2) == 0) {
6457 tmp2 = load_reg(s, rn);
6458 gen_helper_add_setq(tmp, tmp, tmp2);
6459 tcg_temp_free_i32(tmp2);
6461 store_reg(s, rd, tmp);
6462 } else {
6463 /* 16 * 16 */
6464 tmp = load_reg(s, rm);
6465 tmp2 = load_reg(s, rs);
6466 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
6467 tcg_temp_free_i32(tmp2);
6468 if (op1 == 2) {
6469 tmp64 = tcg_temp_new_i64();
6470 tcg_gen_ext_i32_i64(tmp64, tmp);
6471 tcg_temp_free_i32(tmp);
6472 gen_addq(s, tmp64, rn, rd);
6473 gen_storeq_reg(s, rn, rd, tmp64);
6474 tcg_temp_free_i64(tmp64);
6475 } else {
6476 if (op1 == 0) {
6477 tmp2 = load_reg(s, rn);
6478 gen_helper_add_setq(tmp, tmp, tmp2);
6479 tcg_temp_free_i32(tmp2);
6481 store_reg(s, rd, tmp);
6484 break;
6485 default:
6486 goto illegal_op;
6488 } else if (((insn & 0x0e000000) == 0 &&
6489 (insn & 0x00000090) != 0x90) ||
6490 ((insn & 0x0e000000) == (1 << 25))) {
6491 int set_cc, logic_cc, shiftop;
6493 op1 = (insn >> 21) & 0xf;
6494 set_cc = (insn >> 20) & 1;
6495 logic_cc = table_logic_cc[op1] & set_cc;
6497 /* data processing instruction */
6498 if (insn & (1 << 25)) {
6499 /* immediate operand */
6500 val = insn & 0xff;
6501 shift = ((insn >> 8) & 0xf) * 2;
6502 if (shift) {
6503 val = (val >> shift) | (val << (32 - shift));
6505 tmp2 = tcg_temp_new_i32();
6506 tcg_gen_movi_i32(tmp2, val);
6507 if (logic_cc && shift) {
6508 gen_set_CF_bit31(tmp2);
6510 } else {
6511 /* register */
6512 rm = (insn) & 0xf;
6513 tmp2 = load_reg(s, rm);
6514 shiftop = (insn >> 5) & 3;
6515 if (!(insn & (1 << 4))) {
6516 shift = (insn >> 7) & 0x1f;
6517 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
6518 } else {
6519 rs = (insn >> 8) & 0xf;
6520 tmp = load_reg(s, rs);
6521 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
6524 if (op1 != 0x0f && op1 != 0x0d) {
6525 rn = (insn >> 16) & 0xf;
6526 tmp = load_reg(s, rn);
6527 } else {
6528 TCGV_UNUSED(tmp);
6530 rd = (insn >> 12) & 0xf;
6531 switch(op1) {
6532 case 0x00:
6533 tcg_gen_and_i32(tmp, tmp, tmp2);
6534 if (logic_cc) {
6535 gen_logic_CC(tmp);
6537 store_reg_bx(env, s, rd, tmp);
6538 break;
6539 case 0x01:
6540 tcg_gen_xor_i32(tmp, tmp, tmp2);
6541 if (logic_cc) {
6542 gen_logic_CC(tmp);
6544 store_reg_bx(env, s, rd, tmp);
6545 break;
6546 case 0x02:
6547 if (set_cc && rd == 15) {
6548 /* SUBS r15, ... is used for exception return. */
6549 if (IS_USER(s)) {
6550 goto illegal_op;
6552 gen_helper_sub_cc(tmp, tmp, tmp2);
6553 gen_exception_return(s, tmp);
6554 } else {
6555 if (set_cc) {
6556 gen_helper_sub_cc(tmp, tmp, tmp2);
6557 } else {
6558 tcg_gen_sub_i32(tmp, tmp, tmp2);
6560 store_reg_bx(env, s, rd, tmp);
6562 break;
6563 case 0x03:
6564 if (set_cc) {
6565 gen_helper_sub_cc(tmp, tmp2, tmp);
6566 } else {
6567 tcg_gen_sub_i32(tmp, tmp2, tmp);
6569 store_reg_bx(env, s, rd, tmp);
6570 break;
6571 case 0x04:
6572 if (set_cc) {
6573 gen_helper_add_cc(tmp, tmp, tmp2);
6574 } else {
6575 tcg_gen_add_i32(tmp, tmp, tmp2);
6577 store_reg_bx(env, s, rd, tmp);
6578 break;
6579 case 0x05:
6580 if (set_cc) {
6581 gen_helper_adc_cc(tmp, tmp, tmp2);
6582 } else {
6583 gen_add_carry(tmp, tmp, tmp2);
6585 store_reg_bx(env, s, rd, tmp);
6586 break;
6587 case 0x06:
6588 if (set_cc) {
6589 gen_helper_sbc_cc(tmp, tmp, tmp2);
6590 } else {
6591 gen_sub_carry(tmp, tmp, tmp2);
6593 store_reg_bx(env, s, rd, tmp);
6594 break;
6595 case 0x07:
6596 if (set_cc) {
6597 gen_helper_sbc_cc(tmp, tmp2, tmp);
6598 } else {
6599 gen_sub_carry(tmp, tmp2, tmp);
6601 store_reg_bx(env, s, rd, tmp);
6602 break;
6603 case 0x08:
6604 if (set_cc) {
6605 tcg_gen_and_i32(tmp, tmp, tmp2);
6606 gen_logic_CC(tmp);
6608 tcg_temp_free_i32(tmp);
6609 break;
6610 case 0x09:
6611 if (set_cc) {
6612 tcg_gen_xor_i32(tmp, tmp, tmp2);
6613 gen_logic_CC(tmp);
6615 tcg_temp_free_i32(tmp);
6616 break;
6617 case 0x0a:
6618 if (set_cc) {
6619 gen_helper_sub_cc(tmp, tmp, tmp2);
6621 tcg_temp_free_i32(tmp);
6622 break;
6623 case 0x0b:
6624 if (set_cc) {
6625 gen_helper_add_cc(tmp, tmp, tmp2);
6627 tcg_temp_free_i32(tmp);
6628 break;
6629 case 0x0c:
6630 tcg_gen_or_i32(tmp, tmp, tmp2);
6631 if (logic_cc) {
6632 gen_logic_CC(tmp);
6634 store_reg_bx(env, s, rd, tmp);
6635 break;
6636 case 0x0d:
6637 if (logic_cc && rd == 15) {
6638 /* MOVS r15, ... is used for exception return. */
6639 if (IS_USER(s)) {
6640 goto illegal_op;
6642 gen_exception_return(s, tmp2);
6643 } else {
6644 if (logic_cc) {
6645 gen_logic_CC(tmp2);
6647 store_reg_bx(env, s, rd, tmp2);
6649 break;
6650 case 0x0e:
6651 tcg_gen_andc_i32(tmp, tmp, tmp2);
6652 if (logic_cc) {
6653 gen_logic_CC(tmp);
6655 store_reg_bx(env, s, rd, tmp);
6656 break;
6657 default:
6658 case 0x0f:
6659 tcg_gen_not_i32(tmp2, tmp2);
6660 if (logic_cc) {
6661 gen_logic_CC(tmp2);
6663 store_reg_bx(env, s, rd, tmp2);
6664 break;
6666 if (op1 != 0x0f && op1 != 0x0d) {
6667 tcg_temp_free_i32(tmp2);
6669 } else {
6670 /* other instructions */
6671 op1 = (insn >> 24) & 0xf;
6672 switch(op1) {
6673 case 0x0:
6674 case 0x1:
6675 /* multiplies, extra load/stores */
6676 sh = (insn >> 5) & 3;
6677 if (sh == 0) {
6678 if (op1 == 0x0) {
6679 rd = (insn >> 16) & 0xf;
6680 rn = (insn >> 12) & 0xf;
6681 rs = (insn >> 8) & 0xf;
6682 rm = (insn) & 0xf;
6683 op1 = (insn >> 20) & 0xf;
6684 switch (op1) {
6685 case 0: case 1: case 2: case 3: case 6:
6686 /* 32 bit mul */
6687 tmp = load_reg(s, rs);
6688 tmp2 = load_reg(s, rm);
6689 tcg_gen_mul_i32(tmp, tmp, tmp2);
6690 tcg_temp_free_i32(tmp2);
6691 if (insn & (1 << 22)) {
6692 /* Subtract (mls) */
6693 ARCH(6T2);
6694 tmp2 = load_reg(s, rn);
6695 tcg_gen_sub_i32(tmp, tmp2, tmp);
6696 tcg_temp_free_i32(tmp2);
6697 } else if (insn & (1 << 21)) {
6698 /* Add */
6699 tmp2 = load_reg(s, rn);
6700 tcg_gen_add_i32(tmp, tmp, tmp2);
6701 tcg_temp_free_i32(tmp2);
6703 if (insn & (1 << 20))
6704 gen_logic_CC(tmp);
6705 store_reg(s, rd, tmp);
6706 break;
6707 case 4:
6708 /* 64 bit mul double accumulate (UMAAL) */
6709 ARCH(6);
6710 tmp = load_reg(s, rs);
6711 tmp2 = load_reg(s, rm);
6712 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
6713 gen_addq_lo(s, tmp64, rn);
6714 gen_addq_lo(s, tmp64, rd);
6715 gen_storeq_reg(s, rn, rd, tmp64);
6716 tcg_temp_free_i64(tmp64);
6717 break;
6718 case 8: case 9: case 10: case 11:
6719 case 12: case 13: case 14: case 15:
6720 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
6721 tmp = load_reg(s, rs);
6722 tmp2 = load_reg(s, rm);
6723 if (insn & (1 << 22)) {
6724 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6725 } else {
6726 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
6728 if (insn & (1 << 21)) { /* mult accumulate */
6729 gen_addq(s, tmp64, rn, rd);
6731 if (insn & (1 << 20)) {
6732 gen_logicq_cc(tmp64);
6734 gen_storeq_reg(s, rn, rd, tmp64);
6735 tcg_temp_free_i64(tmp64);
6736 break;
6737 default:
6738 goto illegal_op;
6740 } else {
6741 rn = (insn >> 16) & 0xf;
6742 rd = (insn >> 12) & 0xf;
6743 if (insn & (1 << 23)) {
6744 /* load/store exclusive */
6745 op1 = (insn >> 21) & 0x3;
6746 if (op1)
6747 ARCH(6K);
6748 else
6749 ARCH(6);
6750 addr = tcg_temp_local_new_i32();
6751 load_reg_var(s, addr, rn);
6752 if (insn & (1 << 20)) {
6753 switch (op1) {
6754 case 0: /* ldrex */
6755 gen_load_exclusive(s, rd, 15, addr, 2);
6756 break;
6757 case 1: /* ldrexd */
6758 gen_load_exclusive(s, rd, rd + 1, addr, 3);
6759 break;
6760 case 2: /* ldrexb */
6761 gen_load_exclusive(s, rd, 15, addr, 0);
6762 break;
6763 case 3: /* ldrexh */
6764 gen_load_exclusive(s, rd, 15, addr, 1);
6765 break;
6766 default:
6767 abort();
6769 } else {
6770 rm = insn & 0xf;
6771 switch (op1) {
6772 case 0: /* strex */
6773 gen_store_exclusive(s, rd, rm, 15, addr, 2);
6774 break;
6775 case 1: /* strexd */
6776 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
6777 break;
6778 case 2: /* strexb */
6779 gen_store_exclusive(s, rd, rm, 15, addr, 0);
6780 break;
6781 case 3: /* strexh */
6782 gen_store_exclusive(s, rd, rm, 15, addr, 1);
6783 break;
6784 default:
6785 abort();
6788 tcg_temp_free(addr);
6789 } else {
6790 /* SWP instruction */
6791 rm = (insn) & 0xf;
6793 /* ??? This is not really atomic. However we know
6794 we never have multiple CPUs running in parallel,
6795 so it is good enough. */
6796 addr = load_reg(s, rn);
6797 tmp = load_reg(s, rm);
6798 if (insn & (1 << 22)) {
6799 tmp2 = gen_ld8u(addr, IS_USER(s));
6800 gen_st8(tmp, addr, IS_USER(s));
6801 } else {
6802 tmp2 = gen_ld32(addr, IS_USER(s));
6803 gen_st32(tmp, addr, IS_USER(s));
6805 tcg_temp_free_i32(addr);
6806 store_reg(s, rd, tmp2);
6809 } else {
6810 int address_offset;
6811 int load;
6812 /* Misc load/store */
6813 rn = (insn >> 16) & 0xf;
6814 rd = (insn >> 12) & 0xf;
6815 addr = load_reg(s, rn);
6816 if (insn & (1 << 24))
6817 gen_add_datah_offset(s, insn, 0, addr);
6818 address_offset = 0;
6819 if (insn & (1 << 20)) {
6820 /* load */
6821 switch(sh) {
6822 case 1:
6823 tmp = gen_ld16u(addr, IS_USER(s));
6824 break;
6825 case 2:
6826 tmp = gen_ld8s(addr, IS_USER(s));
6827 break;
6828 default:
6829 case 3:
6830 tmp = gen_ld16s(addr, IS_USER(s));
6831 break;
6833 load = 1;
6834 } else if (sh & 2) {
6835 /* doubleword */
6836 if (sh & 1) {
6837 /* store */
6838 tmp = load_reg(s, rd);
6839 gen_st32(tmp, addr, IS_USER(s));
6840 tcg_gen_addi_i32(addr, addr, 4);
6841 tmp = load_reg(s, rd + 1);
6842 gen_st32(tmp, addr, IS_USER(s));
6843 load = 0;
6844 } else {
6845 /* load */
6846 tmp = gen_ld32(addr, IS_USER(s));
6847 store_reg(s, rd, tmp);
6848 tcg_gen_addi_i32(addr, addr, 4);
6849 tmp = gen_ld32(addr, IS_USER(s));
6850 rd++;
6851 load = 1;
6853 address_offset = -4;
6854 } else {
6855 /* store */
6856 tmp = load_reg(s, rd);
6857 gen_st16(tmp, addr, IS_USER(s));
6858 load = 0;
6860 /* Perform base writeback before the loaded value to
6861 ensure correct behavior with overlapping index registers.
6862 ldrd with base writeback is is undefined if the
6863 destination and index registers overlap. */
6864 if (!(insn & (1 << 24))) {
6865 gen_add_datah_offset(s, insn, address_offset, addr);
6866 store_reg(s, rn, addr);
6867 } else if (insn & (1 << 21)) {
6868 if (address_offset)
6869 tcg_gen_addi_i32(addr, addr, address_offset);
6870 store_reg(s, rn, addr);
6871 } else {
6872 tcg_temp_free_i32(addr);
6874 if (load) {
6875 /* Complete the load. */
6876 store_reg(s, rd, tmp);
6879 break;
6880 case 0x4:
6881 case 0x5:
6882 goto do_ldst;
6883 case 0x6:
6884 case 0x7:
6885 if (insn & (1 << 4)) {
6886 ARCH(6);
6887 /* Armv6 Media instructions. */
6888 rm = insn & 0xf;
6889 rn = (insn >> 16) & 0xf;
6890 rd = (insn >> 12) & 0xf;
6891 rs = (insn >> 8) & 0xf;
6892 switch ((insn >> 23) & 3) {
6893 case 0: /* Parallel add/subtract. */
6894 op1 = (insn >> 20) & 7;
6895 tmp = load_reg(s, rn);
6896 tmp2 = load_reg(s, rm);
6897 sh = (insn >> 5) & 7;
6898 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
6899 goto illegal_op;
6900 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
6901 tcg_temp_free_i32(tmp2);
6902 store_reg(s, rd, tmp);
6903 break;
6904 case 1:
6905 if ((insn & 0x00700020) == 0) {
6906 /* Halfword pack. */
6907 tmp = load_reg(s, rn);
6908 tmp2 = load_reg(s, rm);
6909 shift = (insn >> 7) & 0x1f;
6910 if (insn & (1 << 6)) {
6911 /* pkhtb */
6912 if (shift == 0)
6913 shift = 31;
6914 tcg_gen_sari_i32(tmp2, tmp2, shift);
6915 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
6916 tcg_gen_ext16u_i32(tmp2, tmp2);
6917 } else {
6918 /* pkhbt */
6919 if (shift)
6920 tcg_gen_shli_i32(tmp2, tmp2, shift);
6921 tcg_gen_ext16u_i32(tmp, tmp);
6922 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
6924 tcg_gen_or_i32(tmp, tmp, tmp2);
6925 tcg_temp_free_i32(tmp2);
6926 store_reg(s, rd, tmp);
6927 } else if ((insn & 0x00200020) == 0x00200000) {
6928 /* [us]sat */
6929 tmp = load_reg(s, rm);
6930 shift = (insn >> 7) & 0x1f;
6931 if (insn & (1 << 6)) {
6932 if (shift == 0)
6933 shift = 31;
6934 tcg_gen_sari_i32(tmp, tmp, shift);
6935 } else {
6936 tcg_gen_shli_i32(tmp, tmp, shift);
6938 sh = (insn >> 16) & 0x1f;
6939 tmp2 = tcg_const_i32(sh);
6940 if (insn & (1 << 22))
6941 gen_helper_usat(tmp, tmp, tmp2);
6942 else
6943 gen_helper_ssat(tmp, tmp, tmp2);
6944 tcg_temp_free_i32(tmp2);
6945 store_reg(s, rd, tmp);
6946 } else if ((insn & 0x00300fe0) == 0x00200f20) {
6947 /* [us]sat16 */
6948 tmp = load_reg(s, rm);
6949 sh = (insn >> 16) & 0x1f;
6950 tmp2 = tcg_const_i32(sh);
6951 if (insn & (1 << 22))
6952 gen_helper_usat16(tmp, tmp, tmp2);
6953 else
6954 gen_helper_ssat16(tmp, tmp, tmp2);
6955 tcg_temp_free_i32(tmp2);
6956 store_reg(s, rd, tmp);
6957 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
6958 /* Select bytes. */
6959 tmp = load_reg(s, rn);
6960 tmp2 = load_reg(s, rm);
6961 tmp3 = tcg_temp_new_i32();
6962 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
6963 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
6964 tcg_temp_free_i32(tmp3);
6965 tcg_temp_free_i32(tmp2);
6966 store_reg(s, rd, tmp);
6967 } else if ((insn & 0x000003e0) == 0x00000060) {
6968 tmp = load_reg(s, rm);
6969 shift = (insn >> 10) & 3;
6970 /* ??? In many cases it's not neccessary to do a
6971 rotate, a shift is sufficient. */
6972 if (shift != 0)
6973 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
6974 op1 = (insn >> 20) & 7;
6975 switch (op1) {
6976 case 0: gen_sxtb16(tmp); break;
6977 case 2: gen_sxtb(tmp); break;
6978 case 3: gen_sxth(tmp); break;
6979 case 4: gen_uxtb16(tmp); break;
6980 case 6: gen_uxtb(tmp); break;
6981 case 7: gen_uxth(tmp); break;
6982 default: goto illegal_op;
6984 if (rn != 15) {
6985 tmp2 = load_reg(s, rn);
6986 if ((op1 & 3) == 0) {
6987 gen_add16(tmp, tmp2);
6988 } else {
6989 tcg_gen_add_i32(tmp, tmp, tmp2);
6990 tcg_temp_free_i32(tmp2);
6993 store_reg(s, rd, tmp);
6994 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
6995 /* rev */
6996 tmp = load_reg(s, rm);
6997 if (insn & (1 << 22)) {
6998 if (insn & (1 << 7)) {
6999 gen_revsh(tmp);
7000 } else {
7001 ARCH(6T2);
7002 gen_helper_rbit(tmp, tmp);
7004 } else {
7005 if (insn & (1 << 7))
7006 gen_rev16(tmp);
7007 else
7008 tcg_gen_bswap32_i32(tmp, tmp);
7010 store_reg(s, rd, tmp);
7011 } else {
7012 goto illegal_op;
7014 break;
7015 case 2: /* Multiplies (Type 3). */
7016 tmp = load_reg(s, rm);
7017 tmp2 = load_reg(s, rs);
7018 if (insn & (1 << 20)) {
7019 /* Signed multiply most significant [accumulate].
7020 (SMMUL, SMMLA, SMMLS) */
7021 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7023 if (rd != 15) {
7024 tmp = load_reg(s, rd);
7025 if (insn & (1 << 6)) {
7026 tmp64 = gen_subq_msw(tmp64, tmp);
7027 } else {
7028 tmp64 = gen_addq_msw(tmp64, tmp);
7031 if (insn & (1 << 5)) {
7032 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
7034 tcg_gen_shri_i64(tmp64, tmp64, 32);
7035 tmp = tcg_temp_new_i32();
7036 tcg_gen_trunc_i64_i32(tmp, tmp64);
7037 tcg_temp_free_i64(tmp64);
7038 store_reg(s, rn, tmp);
7039 } else {
7040 if (insn & (1 << 5))
7041 gen_swap_half(tmp2);
7042 gen_smul_dual(tmp, tmp2);
7043 if (insn & (1 << 6)) {
7044 /* This subtraction cannot overflow. */
7045 tcg_gen_sub_i32(tmp, tmp, tmp2);
7046 } else {
7047 /* This addition cannot overflow 32 bits;
7048 * however it may overflow considered as a signed
7049 * operation, in which case we must set the Q flag.
7051 gen_helper_add_setq(tmp, tmp, tmp2);
7053 tcg_temp_free_i32(tmp2);
7054 if (insn & (1 << 22)) {
7055 /* smlald, smlsld */
7056 tmp64 = tcg_temp_new_i64();
7057 tcg_gen_ext_i32_i64(tmp64, tmp);
7058 tcg_temp_free_i32(tmp);
7059 gen_addq(s, tmp64, rd, rn);
7060 gen_storeq_reg(s, rd, rn, tmp64);
7061 tcg_temp_free_i64(tmp64);
7062 } else {
7063 /* smuad, smusd, smlad, smlsd */
7064 if (rd != 15)
7066 tmp2 = load_reg(s, rd);
7067 gen_helper_add_setq(tmp, tmp, tmp2);
7068 tcg_temp_free_i32(tmp2);
7070 store_reg(s, rn, tmp);
7073 break;
7074 case 3:
7075 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
7076 switch (op1) {
7077 case 0: /* Unsigned sum of absolute differences. */
7078 ARCH(6);
7079 tmp = load_reg(s, rm);
7080 tmp2 = load_reg(s, rs);
7081 gen_helper_usad8(tmp, tmp, tmp2);
7082 tcg_temp_free_i32(tmp2);
7083 if (rd != 15) {
7084 tmp2 = load_reg(s, rd);
7085 tcg_gen_add_i32(tmp, tmp, tmp2);
7086 tcg_temp_free_i32(tmp2);
7088 store_reg(s, rn, tmp);
7089 break;
7090 case 0x20: case 0x24: case 0x28: case 0x2c:
7091 /* Bitfield insert/clear. */
7092 ARCH(6T2);
7093 shift = (insn >> 7) & 0x1f;
7094 i = (insn >> 16) & 0x1f;
7095 i = i + 1 - shift;
7096 if (rm == 15) {
7097 tmp = tcg_temp_new_i32();
7098 tcg_gen_movi_i32(tmp, 0);
7099 } else {
7100 tmp = load_reg(s, rm);
7102 if (i != 32) {
7103 tmp2 = load_reg(s, rd);
7104 gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
7105 tcg_temp_free_i32(tmp2);
7107 store_reg(s, rd, tmp);
7108 break;
7109 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
7110 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
7111 ARCH(6T2);
7112 tmp = load_reg(s, rm);
7113 shift = (insn >> 7) & 0x1f;
7114 i = ((insn >> 16) & 0x1f) + 1;
7115 if (shift + i > 32)
7116 goto illegal_op;
7117 if (i < 32) {
7118 if (op1 & 0x20) {
7119 gen_ubfx(tmp, shift, (1u << i) - 1);
7120 } else {
7121 gen_sbfx(tmp, shift, i);
7124 store_reg(s, rd, tmp);
7125 break;
7126 default:
7127 goto illegal_op;
7129 break;
7131 break;
7133 do_ldst:
7134 /* Check for undefined extension instructions
7135 * per the ARM Bible IE:
7136 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
7138 sh = (0xf << 20) | (0xf << 4);
7139 if (op1 == 0x7 && ((insn & sh) == sh))
7141 goto illegal_op;
7143 /* load/store byte/word */
7144 rn = (insn >> 16) & 0xf;
7145 rd = (insn >> 12) & 0xf;
7146 tmp2 = load_reg(s, rn);
7147 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
7148 if (insn & (1 << 24))
7149 gen_add_data_offset(s, insn, tmp2);
7150 if (insn & (1 << 20)) {
7151 /* load */
7152 if (insn & (1 << 22)) {
7153 tmp = gen_ld8u(tmp2, i);
7154 } else {
7155 tmp = gen_ld32(tmp2, i);
7157 } else {
7158 /* store */
7159 tmp = load_reg(s, rd);
7160 if (insn & (1 << 22))
7161 gen_st8(tmp, tmp2, i);
7162 else
7163 gen_st32(tmp, tmp2, i);
7165 if (!(insn & (1 << 24))) {
7166 gen_add_data_offset(s, insn, tmp2);
7167 store_reg(s, rn, tmp2);
7168 } else if (insn & (1 << 21)) {
7169 store_reg(s, rn, tmp2);
7170 } else {
7171 tcg_temp_free_i32(tmp2);
7173 if (insn & (1 << 20)) {
7174 /* Complete the load. */
7175 if (rd == 15)
7176 gen_bx(s, tmp);
7177 else
7178 store_reg(s, rd, tmp);
7180 break;
7181 case 0x08:
7182 case 0x09:
7184 int j, n, user, loaded_base;
7185 TCGv loaded_var;
7186 /* load/store multiple words */
7187 /* XXX: store correct base if write back */
7188 user = 0;
7189 if (insn & (1 << 22)) {
7190 if (IS_USER(s))
7191 goto illegal_op; /* only usable in supervisor mode */
7193 if ((insn & (1 << 15)) == 0)
7194 user = 1;
7196 rn = (insn >> 16) & 0xf;
7197 addr = load_reg(s, rn);
7199 /* compute total size */
7200 loaded_base = 0;
7201 TCGV_UNUSED(loaded_var);
7202 n = 0;
7203 for(i=0;i<16;i++) {
7204 if (insn & (1 << i))
7205 n++;
7207 /* XXX: test invalid n == 0 case ? */
7208 if (insn & (1 << 23)) {
7209 if (insn & (1 << 24)) {
7210 /* pre increment */
7211 tcg_gen_addi_i32(addr, addr, 4);
7212 } else {
7213 /* post increment */
7215 } else {
7216 if (insn & (1 << 24)) {
7217 /* pre decrement */
7218 tcg_gen_addi_i32(addr, addr, -(n * 4));
7219 } else {
7220 /* post decrement */
7221 if (n != 1)
7222 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7225 j = 0;
7226 for(i=0;i<16;i++) {
7227 if (insn & (1 << i)) {
7228 if (insn & (1 << 20)) {
7229 /* load */
7230 tmp = gen_ld32(addr, IS_USER(s));
7231 if (i == 15) {
7232 gen_bx(s, tmp);
7233 } else if (user) {
7234 tmp2 = tcg_const_i32(i);
7235 gen_helper_set_user_reg(tmp2, tmp);
7236 tcg_temp_free_i32(tmp2);
7237 tcg_temp_free_i32(tmp);
7238 } else if (i == rn) {
7239 loaded_var = tmp;
7240 loaded_base = 1;
7241 } else {
7242 store_reg(s, i, tmp);
7244 } else {
7245 /* store */
7246 if (i == 15) {
7247 /* special case: r15 = PC + 8 */
7248 val = (long)s->pc + 4;
7249 tmp = tcg_temp_new_i32();
7250 tcg_gen_movi_i32(tmp, val);
7251 } else if (user) {
7252 tmp = tcg_temp_new_i32();
7253 tmp2 = tcg_const_i32(i);
7254 gen_helper_get_user_reg(tmp, tmp2);
7255 tcg_temp_free_i32(tmp2);
7256 } else {
7257 tmp = load_reg(s, i);
7259 gen_st32(tmp, addr, IS_USER(s));
7261 j++;
7262 /* no need to add after the last transfer */
7263 if (j != n)
7264 tcg_gen_addi_i32(addr, addr, 4);
7267 if (insn & (1 << 21)) {
7268 /* write back */
7269 if (insn & (1 << 23)) {
7270 if (insn & (1 << 24)) {
7271 /* pre increment */
7272 } else {
7273 /* post increment */
7274 tcg_gen_addi_i32(addr, addr, 4);
7276 } else {
7277 if (insn & (1 << 24)) {
7278 /* pre decrement */
7279 if (n != 1)
7280 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7281 } else {
7282 /* post decrement */
7283 tcg_gen_addi_i32(addr, addr, -(n * 4));
7286 store_reg(s, rn, addr);
7287 } else {
7288 tcg_temp_free_i32(addr);
7290 if (loaded_base) {
7291 store_reg(s, rn, loaded_var);
7293 if ((insn & (1 << 22)) && !user) {
7294 /* Restore CPSR from SPSR. */
7295 tmp = load_cpu_field(spsr);
7296 gen_set_cpsr(tmp, 0xffffffff);
7297 tcg_temp_free_i32(tmp);
7298 s->is_jmp = DISAS_UPDATE;
7301 break;
7302 case 0xa:
7303 case 0xb:
7305 int32_t offset;
7307 /* branch (and link) */
7308 val = (int32_t)s->pc;
7309 if (insn & (1 << 24)) {
7310 tmp = tcg_temp_new_i32();
7311 tcg_gen_movi_i32(tmp, val);
7312 store_reg(s, 14, tmp);
7314 offset = (((int32_t)insn << 8) >> 8);
7315 val += (offset << 2) + 4;
7316 gen_jmp(s, val);
7318 break;
7319 case 0xc:
7320 case 0xd:
7321 case 0xe:
7322 /* Coprocessor. */
7323 if (disas_coproc_insn(env, s, insn))
7324 goto illegal_op;
7325 break;
7326 case 0xf:
7327 /* swi */
7328 gen_set_pc_im(s->pc);
7329 s->is_jmp = DISAS_SWI;
7330 break;
7331 default:
7332 illegal_op:
7333 gen_exception_insn(s, 4, EXCP_UDEF);
7334 break;
7339 /* Return true if this is a Thumb-2 logical op. */
7340 static int
7341 thumb2_logic_op(int op)
7343 return (op < 8);
7346 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7347 then set condition code flags based on the result of the operation.
7348 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7349 to the high bit of T1.
7350 Returns zero if the opcode is valid. */
7352 static int
7353 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCGv t0, TCGv t1)
7355 int logic_cc;
7357 logic_cc = 0;
7358 switch (op) {
7359 case 0: /* and */
7360 tcg_gen_and_i32(t0, t0, t1);
7361 logic_cc = conds;
7362 break;
7363 case 1: /* bic */
7364 tcg_gen_andc_i32(t0, t0, t1);
7365 logic_cc = conds;
7366 break;
7367 case 2: /* orr */
7368 tcg_gen_or_i32(t0, t0, t1);
7369 logic_cc = conds;
7370 break;
7371 case 3: /* orn */
7372 tcg_gen_orc_i32(t0, t0, t1);
7373 logic_cc = conds;
7374 break;
7375 case 4: /* eor */
7376 tcg_gen_xor_i32(t0, t0, t1);
7377 logic_cc = conds;
7378 break;
7379 case 8: /* add */
7380 if (conds)
7381 gen_helper_add_cc(t0, t0, t1);
7382 else
7383 tcg_gen_add_i32(t0, t0, t1);
7384 break;
7385 case 10: /* adc */
7386 if (conds)
7387 gen_helper_adc_cc(t0, t0, t1);
7388 else
7389 gen_adc(t0, t1);
7390 break;
7391 case 11: /* sbc */
7392 if (conds)
7393 gen_helper_sbc_cc(t0, t0, t1);
7394 else
7395 gen_sub_carry(t0, t0, t1);
7396 break;
7397 case 13: /* sub */
7398 if (conds)
7399 gen_helper_sub_cc(t0, t0, t1);
7400 else
7401 tcg_gen_sub_i32(t0, t0, t1);
7402 break;
7403 case 14: /* rsb */
7404 if (conds)
7405 gen_helper_sub_cc(t0, t1, t0);
7406 else
7407 tcg_gen_sub_i32(t0, t1, t0);
7408 break;
7409 default: /* 5, 6, 7, 9, 12, 15. */
7410 return 1;
7412 if (logic_cc) {
7413 gen_logic_CC(t0);
7414 if (shifter_out)
7415 gen_set_CF_bit31(t1);
7417 return 0;
7420 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7421 is not legal. */
7422 static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7424 uint32_t insn, imm, shift, offset;
7425 uint32_t rd, rn, rm, rs;
7426 TCGv tmp;
7427 TCGv tmp2;
7428 TCGv tmp3;
7429 TCGv addr;
7430 TCGv_i64 tmp64;
7431 int op;
7432 int shiftop;
7433 int conds;
7434 int logic_cc;
7436 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
7437 || arm_feature (env, ARM_FEATURE_M))) {
7438 /* Thumb-1 cores may need to treat bl and blx as a pair of
7439 16-bit instructions to get correct prefetch abort behavior. */
7440 insn = insn_hw1;
7441 if ((insn & (1 << 12)) == 0) {
7442 /* Second half of blx. */
7443 offset = ((insn & 0x7ff) << 1);
7444 tmp = load_reg(s, 14);
7445 tcg_gen_addi_i32(tmp, tmp, offset);
7446 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
7448 tmp2 = tcg_temp_new_i32();
7449 tcg_gen_movi_i32(tmp2, s->pc | 1);
7450 store_reg(s, 14, tmp2);
7451 gen_bx(s, tmp);
7452 return 0;
7454 if (insn & (1 << 11)) {
7455 /* Second half of bl. */
7456 offset = ((insn & 0x7ff) << 1) | 1;
7457 tmp = load_reg(s, 14);
7458 tcg_gen_addi_i32(tmp, tmp, offset);
7460 tmp2 = tcg_temp_new_i32();
7461 tcg_gen_movi_i32(tmp2, s->pc | 1);
7462 store_reg(s, 14, tmp2);
7463 gen_bx(s, tmp);
7464 return 0;
7466 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
7467 /* Instruction spans a page boundary. Implement it as two
7468 16-bit instructions in case the second half causes an
7469 prefetch abort. */
7470 offset = ((int32_t)insn << 21) >> 9;
7471 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
7472 return 0;
7474 /* Fall through to 32-bit decode. */
7477 insn = lduw_code(s->pc);
7478 s->pc += 2;
7479 insn |= (uint32_t)insn_hw1 << 16;
7481 if ((insn & 0xf800e800) != 0xf000e800) {
7482 ARCH(6T2);
7485 rn = (insn >> 16) & 0xf;
7486 rs = (insn >> 12) & 0xf;
7487 rd = (insn >> 8) & 0xf;
7488 rm = insn & 0xf;
7489 switch ((insn >> 25) & 0xf) {
7490 case 0: case 1: case 2: case 3:
7491 /* 16-bit instructions. Should never happen. */
7492 abort();
7493 case 4:
7494 if (insn & (1 << 22)) {
7495 /* Other load/store, table branch. */
7496 if (insn & 0x01200000) {
7497 /* Load/store doubleword. */
7498 if (rn == 15) {
7499 addr = tcg_temp_new_i32();
7500 tcg_gen_movi_i32(addr, s->pc & ~3);
7501 } else {
7502 addr = load_reg(s, rn);
7504 offset = (insn & 0xff) * 4;
7505 if ((insn & (1 << 23)) == 0)
7506 offset = -offset;
7507 if (insn & (1 << 24)) {
7508 tcg_gen_addi_i32(addr, addr, offset);
7509 offset = 0;
7511 if (insn & (1 << 20)) {
7512 /* ldrd */
7513 tmp = gen_ld32(addr, IS_USER(s));
7514 store_reg(s, rs, tmp);
7515 tcg_gen_addi_i32(addr, addr, 4);
7516 tmp = gen_ld32(addr, IS_USER(s));
7517 store_reg(s, rd, tmp);
7518 } else {
7519 /* strd */
7520 tmp = load_reg(s, rs);
7521 gen_st32(tmp, addr, IS_USER(s));
7522 tcg_gen_addi_i32(addr, addr, 4);
7523 tmp = load_reg(s, rd);
7524 gen_st32(tmp, addr, IS_USER(s));
7526 if (insn & (1 << 21)) {
7527 /* Base writeback. */
7528 if (rn == 15)
7529 goto illegal_op;
7530 tcg_gen_addi_i32(addr, addr, offset - 4);
7531 store_reg(s, rn, addr);
7532 } else {
7533 tcg_temp_free_i32(addr);
7535 } else if ((insn & (1 << 23)) == 0) {
7536 /* Load/store exclusive word. */
7537 addr = tcg_temp_local_new();
7538 load_reg_var(s, addr, rn);
7539 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
7540 if (insn & (1 << 20)) {
7541 gen_load_exclusive(s, rs, 15, addr, 2);
7542 } else {
7543 gen_store_exclusive(s, rd, rs, 15, addr, 2);
7545 tcg_temp_free(addr);
7546 } else if ((insn & (1 << 6)) == 0) {
7547 /* Table Branch. */
7548 if (rn == 15) {
7549 addr = tcg_temp_new_i32();
7550 tcg_gen_movi_i32(addr, s->pc);
7551 } else {
7552 addr = load_reg(s, rn);
7554 tmp = load_reg(s, rm);
7555 tcg_gen_add_i32(addr, addr, tmp);
7556 if (insn & (1 << 4)) {
7557 /* tbh */
7558 tcg_gen_add_i32(addr, addr, tmp);
7559 tcg_temp_free_i32(tmp);
7560 tmp = gen_ld16u(addr, IS_USER(s));
7561 } else { /* tbb */
7562 tcg_temp_free_i32(tmp);
7563 tmp = gen_ld8u(addr, IS_USER(s));
7565 tcg_temp_free_i32(addr);
7566 tcg_gen_shli_i32(tmp, tmp, 1);
7567 tcg_gen_addi_i32(tmp, tmp, s->pc);
7568 store_reg(s, 15, tmp);
7569 } else {
7570 /* Load/store exclusive byte/halfword/doubleword. */
7571 ARCH(7);
7572 op = (insn >> 4) & 0x3;
7573 if (op == 2) {
7574 goto illegal_op;
7576 addr = tcg_temp_local_new();
7577 load_reg_var(s, addr, rn);
7578 if (insn & (1 << 20)) {
7579 gen_load_exclusive(s, rs, rd, addr, op);
7580 } else {
7581 gen_store_exclusive(s, rm, rs, rd, addr, op);
7583 tcg_temp_free(addr);
7585 } else {
7586 /* Load/store multiple, RFE, SRS. */
7587 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
7588 /* Not available in user mode. */
7589 if (IS_USER(s))
7590 goto illegal_op;
7591 if (insn & (1 << 20)) {
7592 /* rfe */
7593 addr = load_reg(s, rn);
7594 if ((insn & (1 << 24)) == 0)
7595 tcg_gen_addi_i32(addr, addr, -8);
7596 /* Load PC into tmp and CPSR into tmp2. */
7597 tmp = gen_ld32(addr, 0);
7598 tcg_gen_addi_i32(addr, addr, 4);
7599 tmp2 = gen_ld32(addr, 0);
7600 if (insn & (1 << 21)) {
7601 /* Base writeback. */
7602 if (insn & (1 << 24)) {
7603 tcg_gen_addi_i32(addr, addr, 4);
7604 } else {
7605 tcg_gen_addi_i32(addr, addr, -4);
7607 store_reg(s, rn, addr);
7608 } else {
7609 tcg_temp_free_i32(addr);
7611 gen_rfe(s, tmp, tmp2);
7612 } else {
7613 /* srs */
7614 op = (insn & 0x1f);
7615 addr = tcg_temp_new_i32();
7616 tmp = tcg_const_i32(op);
7617 gen_helper_get_r13_banked(addr, cpu_env, tmp);
7618 tcg_temp_free_i32(tmp);
7619 if ((insn & (1 << 24)) == 0) {
7620 tcg_gen_addi_i32(addr, addr, -8);
7622 tmp = load_reg(s, 14);
7623 gen_st32(tmp, addr, 0);
7624 tcg_gen_addi_i32(addr, addr, 4);
7625 tmp = tcg_temp_new_i32();
7626 gen_helper_cpsr_read(tmp);
7627 gen_st32(tmp, addr, 0);
7628 if (insn & (1 << 21)) {
7629 if ((insn & (1 << 24)) == 0) {
7630 tcg_gen_addi_i32(addr, addr, -4);
7631 } else {
7632 tcg_gen_addi_i32(addr, addr, 4);
7634 tmp = tcg_const_i32(op);
7635 gen_helper_set_r13_banked(cpu_env, tmp, addr);
7636 tcg_temp_free_i32(tmp);
7637 } else {
7638 tcg_temp_free_i32(addr);
7641 } else {
7642 int i;
7643 /* Load/store multiple. */
7644 addr = load_reg(s, rn);
7645 offset = 0;
7646 for (i = 0; i < 16; i++) {
7647 if (insn & (1 << i))
7648 offset += 4;
7650 if (insn & (1 << 24)) {
7651 tcg_gen_addi_i32(addr, addr, -offset);
7654 for (i = 0; i < 16; i++) {
7655 if ((insn & (1 << i)) == 0)
7656 continue;
7657 if (insn & (1 << 20)) {
7658 /* Load. */
7659 tmp = gen_ld32(addr, IS_USER(s));
7660 if (i == 15) {
7661 gen_bx(s, tmp);
7662 } else {
7663 store_reg(s, i, tmp);
7665 } else {
7666 /* Store. */
7667 tmp = load_reg(s, i);
7668 gen_st32(tmp, addr, IS_USER(s));
7670 tcg_gen_addi_i32(addr, addr, 4);
7672 if (insn & (1 << 21)) {
7673 /* Base register writeback. */
7674 if (insn & (1 << 24)) {
7675 tcg_gen_addi_i32(addr, addr, -offset);
7677 /* Fault if writeback register is in register list. */
7678 if (insn & (1 << rn))
7679 goto illegal_op;
7680 store_reg(s, rn, addr);
7681 } else {
7682 tcg_temp_free_i32(addr);
7686 break;
7687 case 5:
7689 op = (insn >> 21) & 0xf;
7690 if (op == 6) {
7691 /* Halfword pack. */
7692 tmp = load_reg(s, rn);
7693 tmp2 = load_reg(s, rm);
7694 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
7695 if (insn & (1 << 5)) {
7696 /* pkhtb */
7697 if (shift == 0)
7698 shift = 31;
7699 tcg_gen_sari_i32(tmp2, tmp2, shift);
7700 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
7701 tcg_gen_ext16u_i32(tmp2, tmp2);
7702 } else {
7703 /* pkhbt */
7704 if (shift)
7705 tcg_gen_shli_i32(tmp2, tmp2, shift);
7706 tcg_gen_ext16u_i32(tmp, tmp);
7707 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
7709 tcg_gen_or_i32(tmp, tmp, tmp2);
7710 tcg_temp_free_i32(tmp2);
7711 store_reg(s, rd, tmp);
7712 } else {
7713 /* Data processing register constant shift. */
7714 if (rn == 15) {
7715 tmp = tcg_temp_new_i32();
7716 tcg_gen_movi_i32(tmp, 0);
7717 } else {
7718 tmp = load_reg(s, rn);
7720 tmp2 = load_reg(s, rm);
7722 shiftop = (insn >> 4) & 3;
7723 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7724 conds = (insn & (1 << 20)) != 0;
7725 logic_cc = (conds && thumb2_logic_op(op));
7726 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
7727 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
7728 goto illegal_op;
7729 tcg_temp_free_i32(tmp2);
7730 if (rd != 15) {
7731 store_reg(s, rd, tmp);
7732 } else {
7733 tcg_temp_free_i32(tmp);
7736 break;
7737 case 13: /* Misc data processing. */
7738 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
7739 if (op < 4 && (insn & 0xf000) != 0xf000)
7740 goto illegal_op;
7741 switch (op) {
7742 case 0: /* Register controlled shift. */
7743 tmp = load_reg(s, rn);
7744 tmp2 = load_reg(s, rm);
7745 if ((insn & 0x70) != 0)
7746 goto illegal_op;
7747 op = (insn >> 21) & 3;
7748 logic_cc = (insn & (1 << 20)) != 0;
7749 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
7750 if (logic_cc)
7751 gen_logic_CC(tmp);
7752 store_reg_bx(env, s, rd, tmp);
7753 break;
7754 case 1: /* Sign/zero extend. */
7755 tmp = load_reg(s, rm);
7756 shift = (insn >> 4) & 3;
7757 /* ??? In many cases it's not neccessary to do a
7758 rotate, a shift is sufficient. */
7759 if (shift != 0)
7760 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
7761 op = (insn >> 20) & 7;
7762 switch (op) {
7763 case 0: gen_sxth(tmp); break;
7764 case 1: gen_uxth(tmp); break;
7765 case 2: gen_sxtb16(tmp); break;
7766 case 3: gen_uxtb16(tmp); break;
7767 case 4: gen_sxtb(tmp); break;
7768 case 5: gen_uxtb(tmp); break;
7769 default: goto illegal_op;
7771 if (rn != 15) {
7772 tmp2 = load_reg(s, rn);
7773 if ((op >> 1) == 1) {
7774 gen_add16(tmp, tmp2);
7775 } else {
7776 tcg_gen_add_i32(tmp, tmp, tmp2);
7777 tcg_temp_free_i32(tmp2);
7780 store_reg(s, rd, tmp);
7781 break;
7782 case 2: /* SIMD add/subtract. */
7783 op = (insn >> 20) & 7;
7784 shift = (insn >> 4) & 7;
7785 if ((op & 3) == 3 || (shift & 3) == 3)
7786 goto illegal_op;
7787 tmp = load_reg(s, rn);
7788 tmp2 = load_reg(s, rm);
7789 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7790 tcg_temp_free_i32(tmp2);
7791 store_reg(s, rd, tmp);
7792 break;
7793 case 3: /* Other data processing. */
7794 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
7795 if (op < 4) {
7796 /* Saturating add/subtract. */
7797 tmp = load_reg(s, rn);
7798 tmp2 = load_reg(s, rm);
7799 if (op & 1)
7800 gen_helper_double_saturate(tmp, tmp);
7801 if (op & 2)
7802 gen_helper_sub_saturate(tmp, tmp2, tmp);
7803 else
7804 gen_helper_add_saturate(tmp, tmp, tmp2);
7805 tcg_temp_free_i32(tmp2);
7806 } else {
7807 tmp = load_reg(s, rn);
7808 switch (op) {
7809 case 0x0a: /* rbit */
7810 gen_helper_rbit(tmp, tmp);
7811 break;
7812 case 0x08: /* rev */
7813 tcg_gen_bswap32_i32(tmp, tmp);
7814 break;
7815 case 0x09: /* rev16 */
7816 gen_rev16(tmp);
7817 break;
7818 case 0x0b: /* revsh */
7819 gen_revsh(tmp);
7820 break;
7821 case 0x10: /* sel */
7822 tmp2 = load_reg(s, rm);
7823 tmp3 = tcg_temp_new_i32();
7824 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
7825 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7826 tcg_temp_free_i32(tmp3);
7827 tcg_temp_free_i32(tmp2);
7828 break;
7829 case 0x18: /* clz */
7830 gen_helper_clz(tmp, tmp);
7831 break;
7832 default:
7833 goto illegal_op;
7836 store_reg(s, rd, tmp);
7837 break;
7838 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7839 op = (insn >> 4) & 0xf;
7840 tmp = load_reg(s, rn);
7841 tmp2 = load_reg(s, rm);
7842 switch ((insn >> 20) & 7) {
7843 case 0: /* 32 x 32 -> 32 */
7844 tcg_gen_mul_i32(tmp, tmp, tmp2);
7845 tcg_temp_free_i32(tmp2);
7846 if (rs != 15) {
7847 tmp2 = load_reg(s, rs);
7848 if (op)
7849 tcg_gen_sub_i32(tmp, tmp2, tmp);
7850 else
7851 tcg_gen_add_i32(tmp, tmp, tmp2);
7852 tcg_temp_free_i32(tmp2);
7854 break;
7855 case 1: /* 16 x 16 -> 32 */
7856 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7857 tcg_temp_free_i32(tmp2);
7858 if (rs != 15) {
7859 tmp2 = load_reg(s, rs);
7860 gen_helper_add_setq(tmp, tmp, tmp2);
7861 tcg_temp_free_i32(tmp2);
7863 break;
7864 case 2: /* Dual multiply add. */
7865 case 4: /* Dual multiply subtract. */
7866 if (op)
7867 gen_swap_half(tmp2);
7868 gen_smul_dual(tmp, tmp2);
7869 if (insn & (1 << 22)) {
7870 /* This subtraction cannot overflow. */
7871 tcg_gen_sub_i32(tmp, tmp, tmp2);
7872 } else {
7873 /* This addition cannot overflow 32 bits;
7874 * however it may overflow considered as a signed
7875 * operation, in which case we must set the Q flag.
7877 gen_helper_add_setq(tmp, tmp, tmp2);
7879 tcg_temp_free_i32(tmp2);
7880 if (rs != 15)
7882 tmp2 = load_reg(s, rs);
7883 gen_helper_add_setq(tmp, tmp, tmp2);
7884 tcg_temp_free_i32(tmp2);
7886 break;
7887 case 3: /* 32 * 16 -> 32msb */
7888 if (op)
7889 tcg_gen_sari_i32(tmp2, tmp2, 16);
7890 else
7891 gen_sxth(tmp2);
7892 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7893 tcg_gen_shri_i64(tmp64, tmp64, 16);
7894 tmp = tcg_temp_new_i32();
7895 tcg_gen_trunc_i64_i32(tmp, tmp64);
7896 tcg_temp_free_i64(tmp64);
7897 if (rs != 15)
7899 tmp2 = load_reg(s, rs);
7900 gen_helper_add_setq(tmp, tmp, tmp2);
7901 tcg_temp_free_i32(tmp2);
7903 break;
7904 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
7905 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7906 if (rs != 15) {
7907 tmp = load_reg(s, rs);
7908 if (insn & (1 << 20)) {
7909 tmp64 = gen_addq_msw(tmp64, tmp);
7910 } else {
7911 tmp64 = gen_subq_msw(tmp64, tmp);
7914 if (insn & (1 << 4)) {
7915 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
7917 tcg_gen_shri_i64(tmp64, tmp64, 32);
7918 tmp = tcg_temp_new_i32();
7919 tcg_gen_trunc_i64_i32(tmp, tmp64);
7920 tcg_temp_free_i64(tmp64);
7921 break;
7922 case 7: /* Unsigned sum of absolute differences. */
7923 gen_helper_usad8(tmp, tmp, tmp2);
7924 tcg_temp_free_i32(tmp2);
7925 if (rs != 15) {
7926 tmp2 = load_reg(s, rs);
7927 tcg_gen_add_i32(tmp, tmp, tmp2);
7928 tcg_temp_free_i32(tmp2);
7930 break;
7932 store_reg(s, rd, tmp);
7933 break;
7934 case 6: case 7: /* 64-bit multiply, Divide. */
7935 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
7936 tmp = load_reg(s, rn);
7937 tmp2 = load_reg(s, rm);
7938 if ((op & 0x50) == 0x10) {
7939 /* sdiv, udiv */
7940 if (!arm_feature(env, ARM_FEATURE_DIV))
7941 goto illegal_op;
7942 if (op & 0x20)
7943 gen_helper_udiv(tmp, tmp, tmp2);
7944 else
7945 gen_helper_sdiv(tmp, tmp, tmp2);
7946 tcg_temp_free_i32(tmp2);
7947 store_reg(s, rd, tmp);
7948 } else if ((op & 0xe) == 0xc) {
7949 /* Dual multiply accumulate long. */
7950 if (op & 1)
7951 gen_swap_half(tmp2);
7952 gen_smul_dual(tmp, tmp2);
7953 if (op & 0x10) {
7954 tcg_gen_sub_i32(tmp, tmp, tmp2);
7955 } else {
7956 tcg_gen_add_i32(tmp, tmp, tmp2);
7958 tcg_temp_free_i32(tmp2);
7959 /* BUGFIX */
7960 tmp64 = tcg_temp_new_i64();
7961 tcg_gen_ext_i32_i64(tmp64, tmp);
7962 tcg_temp_free_i32(tmp);
7963 gen_addq(s, tmp64, rs, rd);
7964 gen_storeq_reg(s, rs, rd, tmp64);
7965 tcg_temp_free_i64(tmp64);
7966 } else {
7967 if (op & 0x20) {
7968 /* Unsigned 64-bit multiply */
7969 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7970 } else {
7971 if (op & 8) {
7972 /* smlalxy */
7973 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7974 tcg_temp_free_i32(tmp2);
7975 tmp64 = tcg_temp_new_i64();
7976 tcg_gen_ext_i32_i64(tmp64, tmp);
7977 tcg_temp_free_i32(tmp);
7978 } else {
7979 /* Signed 64-bit multiply */
7980 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7983 if (op & 4) {
7984 /* umaal */
7985 gen_addq_lo(s, tmp64, rs);
7986 gen_addq_lo(s, tmp64, rd);
7987 } else if (op & 0x40) {
7988 /* 64-bit accumulate. */
7989 gen_addq(s, tmp64, rs, rd);
7991 gen_storeq_reg(s, rs, rd, tmp64);
7992 tcg_temp_free_i64(tmp64);
7994 break;
7996 break;
7997 case 6: case 7: case 14: case 15:
7998 /* Coprocessor. */
7999 if (((insn >> 24) & 3) == 3) {
8000 /* Translate into the equivalent ARM encoding. */
8001 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
8002 if (disas_neon_data_insn(env, s, insn))
8003 goto illegal_op;
8004 } else {
8005 if (insn & (1 << 28))
8006 goto illegal_op;
8007 if (disas_coproc_insn (env, s, insn))
8008 goto illegal_op;
8010 break;
8011 case 8: case 9: case 10: case 11:
8012 if (insn & (1 << 15)) {
8013 /* Branches, misc control. */
8014 if (insn & 0x5000) {
8015 /* Unconditional branch. */
8016 /* signextend(hw1[10:0]) -> offset[:12]. */
8017 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
8018 /* hw1[10:0] -> offset[11:1]. */
8019 offset |= (insn & 0x7ff) << 1;
8020 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
8021 offset[24:22] already have the same value because of the
8022 sign extension above. */
8023 offset ^= ((~insn) & (1 << 13)) << 10;
8024 offset ^= ((~insn) & (1 << 11)) << 11;
8026 if (insn & (1 << 14)) {
8027 /* Branch and link. */
8028 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
8031 offset += s->pc;
8032 if (insn & (1 << 12)) {
8033 /* b/bl */
8034 gen_jmp(s, offset);
8035 } else {
8036 /* blx */
8037 offset &= ~(uint32_t)2;
8038 gen_bx_im(s, offset);
8040 } else if (((insn >> 23) & 7) == 7) {
8041 /* Misc control */
8042 if (insn & (1 << 13))
8043 goto illegal_op;
8045 if (insn & (1 << 26)) {
8046 /* Secure monitor call (v6Z) */
8047 goto illegal_op; /* not implemented. */
8048 } else {
8049 op = (insn >> 20) & 7;
8050 switch (op) {
8051 case 0: /* msr cpsr. */
8052 if (IS_M(env)) {
8053 tmp = load_reg(s, rn);
8054 addr = tcg_const_i32(insn & 0xff);
8055 gen_helper_v7m_msr(cpu_env, addr, tmp);
8056 tcg_temp_free_i32(addr);
8057 tcg_temp_free_i32(tmp);
8058 gen_lookup_tb(s);
8059 break;
8061 /* fall through */
8062 case 1: /* msr spsr. */
8063 if (IS_M(env))
8064 goto illegal_op;
8065 tmp = load_reg(s, rn);
8066 if (gen_set_psr(s,
8067 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
8068 op == 1, tmp))
8069 goto illegal_op;
8070 break;
8071 case 2: /* cps, nop-hint. */
8072 if (((insn >> 8) & 7) == 0) {
8073 gen_nop_hint(s, insn & 0xff);
8075 /* Implemented as NOP in user mode. */
8076 if (IS_USER(s))
8077 break;
8078 offset = 0;
8079 imm = 0;
8080 if (insn & (1 << 10)) {
8081 if (insn & (1 << 7))
8082 offset |= CPSR_A;
8083 if (insn & (1 << 6))
8084 offset |= CPSR_I;
8085 if (insn & (1 << 5))
8086 offset |= CPSR_F;
8087 if (insn & (1 << 9))
8088 imm = CPSR_A | CPSR_I | CPSR_F;
8090 if (insn & (1 << 8)) {
8091 offset |= 0x1f;
8092 imm |= (insn & 0x1f);
8094 if (offset) {
8095 gen_set_psr_im(s, offset, 0, imm);
8097 break;
8098 case 3: /* Special control operations. */
8099 ARCH(7);
8100 op = (insn >> 4) & 0xf;
8101 switch (op) {
8102 case 2: /* clrex */
8103 gen_clrex(s);
8104 break;
8105 case 4: /* dsb */
8106 case 5: /* dmb */
8107 case 6: /* isb */
8108 /* These execute as NOPs. */
8109 break;
8110 default:
8111 goto illegal_op;
8113 break;
8114 case 4: /* bxj */
8115 /* Trivial implementation equivalent to bx. */
8116 tmp = load_reg(s, rn);
8117 gen_bx(s, tmp);
8118 break;
8119 case 5: /* Exception return. */
8120 if (IS_USER(s)) {
8121 goto illegal_op;
8123 if (rn != 14 || rd != 15) {
8124 goto illegal_op;
8126 tmp = load_reg(s, rn);
8127 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
8128 gen_exception_return(s, tmp);
8129 break;
8130 case 6: /* mrs cpsr. */
8131 tmp = tcg_temp_new_i32();
8132 if (IS_M(env)) {
8133 addr = tcg_const_i32(insn & 0xff);
8134 gen_helper_v7m_mrs(tmp, cpu_env, addr);
8135 tcg_temp_free_i32(addr);
8136 } else {
8137 gen_helper_cpsr_read(tmp);
8139 store_reg(s, rd, tmp);
8140 break;
8141 case 7: /* mrs spsr. */
8142 /* Not accessible in user mode. */
8143 if (IS_USER(s) || IS_M(env))
8144 goto illegal_op;
8145 tmp = load_cpu_field(spsr);
8146 store_reg(s, rd, tmp);
8147 break;
8150 } else {
8151 /* Conditional branch. */
8152 op = (insn >> 22) & 0xf;
8153 /* Generate a conditional jump to next instruction. */
8154 s->condlabel = gen_new_label();
8155 gen_test_cc(op ^ 1, s->condlabel);
8156 s->condjmp = 1;
8158 /* offset[11:1] = insn[10:0] */
8159 offset = (insn & 0x7ff) << 1;
8160 /* offset[17:12] = insn[21:16]. */
8161 offset |= (insn & 0x003f0000) >> 4;
8162 /* offset[31:20] = insn[26]. */
8163 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
8164 /* offset[18] = insn[13]. */
8165 offset |= (insn & (1 << 13)) << 5;
8166 /* offset[19] = insn[11]. */
8167 offset |= (insn & (1 << 11)) << 8;
8169 /* jump to the offset */
8170 gen_jmp(s, s->pc + offset);
8172 } else {
8173 /* Data processing immediate. */
8174 if (insn & (1 << 25)) {
8175 if (insn & (1 << 24)) {
8176 if (insn & (1 << 20))
8177 goto illegal_op;
8178 /* Bitfield/Saturate. */
8179 op = (insn >> 21) & 7;
8180 imm = insn & 0x1f;
8181 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
8182 if (rn == 15) {
8183 tmp = tcg_temp_new_i32();
8184 tcg_gen_movi_i32(tmp, 0);
8185 } else {
8186 tmp = load_reg(s, rn);
8188 switch (op) {
8189 case 2: /* Signed bitfield extract. */
8190 imm++;
8191 if (shift + imm > 32)
8192 goto illegal_op;
8193 if (imm < 32)
8194 gen_sbfx(tmp, shift, imm);
8195 break;
8196 case 6: /* Unsigned bitfield extract. */
8197 imm++;
8198 if (shift + imm > 32)
8199 goto illegal_op;
8200 if (imm < 32)
8201 gen_ubfx(tmp, shift, (1u << imm) - 1);
8202 break;
8203 case 3: /* Bitfield insert/clear. */
8204 if (imm < shift)
8205 goto illegal_op;
8206 imm = imm + 1 - shift;
8207 if (imm != 32) {
8208 tmp2 = load_reg(s, rd);
8209 gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
8210 tcg_temp_free_i32(tmp2);
8212 break;
8213 case 7:
8214 goto illegal_op;
8215 default: /* Saturate. */
8216 if (shift) {
8217 if (op & 1)
8218 tcg_gen_sari_i32(tmp, tmp, shift);
8219 else
8220 tcg_gen_shli_i32(tmp, tmp, shift);
8222 tmp2 = tcg_const_i32(imm);
8223 if (op & 4) {
8224 /* Unsigned. */
8225 if ((op & 1) && shift == 0)
8226 gen_helper_usat16(tmp, tmp, tmp2);
8227 else
8228 gen_helper_usat(tmp, tmp, tmp2);
8229 } else {
8230 /* Signed. */
8231 if ((op & 1) && shift == 0)
8232 gen_helper_ssat16(tmp, tmp, tmp2);
8233 else
8234 gen_helper_ssat(tmp, tmp, tmp2);
8236 tcg_temp_free_i32(tmp2);
8237 break;
8239 store_reg(s, rd, tmp);
8240 } else {
8241 imm = ((insn & 0x04000000) >> 15)
8242 | ((insn & 0x7000) >> 4) | (insn & 0xff);
8243 if (insn & (1 << 22)) {
8244 /* 16-bit immediate. */
8245 imm |= (insn >> 4) & 0xf000;
8246 if (insn & (1 << 23)) {
8247 /* movt */
8248 tmp = load_reg(s, rd);
8249 tcg_gen_ext16u_i32(tmp, tmp);
8250 tcg_gen_ori_i32(tmp, tmp, imm << 16);
8251 } else {
8252 /* movw */
8253 tmp = tcg_temp_new_i32();
8254 tcg_gen_movi_i32(tmp, imm);
8256 } else {
8257 /* Add/sub 12-bit immediate. */
8258 if (rn == 15) {
8259 offset = s->pc & ~(uint32_t)3;
8260 if (insn & (1 << 23))
8261 offset -= imm;
8262 else
8263 offset += imm;
8264 tmp = tcg_temp_new_i32();
8265 tcg_gen_movi_i32(tmp, offset);
8266 } else {
8267 tmp = load_reg(s, rn);
8268 if (insn & (1 << 23))
8269 tcg_gen_subi_i32(tmp, tmp, imm);
8270 else
8271 tcg_gen_addi_i32(tmp, tmp, imm);
8274 store_reg(s, rd, tmp);
8276 } else {
8277 int shifter_out = 0;
8278 /* modified 12-bit immediate. */
8279 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
8280 imm = (insn & 0xff);
8281 switch (shift) {
8282 case 0: /* XY */
8283 /* Nothing to do. */
8284 break;
8285 case 1: /* 00XY00XY */
8286 imm |= imm << 16;
8287 break;
8288 case 2: /* XY00XY00 */
8289 imm |= imm << 16;
8290 imm <<= 8;
8291 break;
8292 case 3: /* XYXYXYXY */
8293 imm |= imm << 16;
8294 imm |= imm << 8;
8295 break;
8296 default: /* Rotated constant. */
8297 shift = (shift << 1) | (imm >> 7);
8298 imm |= 0x80;
8299 imm = imm << (32 - shift);
8300 shifter_out = 1;
8301 break;
8303 tmp2 = tcg_temp_new_i32();
8304 tcg_gen_movi_i32(tmp2, imm);
8305 rn = (insn >> 16) & 0xf;
8306 if (rn == 15) {
8307 tmp = tcg_temp_new_i32();
8308 tcg_gen_movi_i32(tmp, 0);
8309 } else {
8310 tmp = load_reg(s, rn);
8312 op = (insn >> 21) & 0xf;
8313 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
8314 shifter_out, tmp, tmp2))
8315 goto illegal_op;
8316 tcg_temp_free_i32(tmp2);
8317 rd = (insn >> 8) & 0xf;
8318 if (rd != 15) {
8319 store_reg(s, rd, tmp);
8320 } else {
8321 tcg_temp_free_i32(tmp);
8325 break;
8326 case 12: /* Load/store single data item. */
8328 int postinc = 0;
8329 int writeback = 0;
8330 int user;
8331 if ((insn & 0x01100000) == 0x01000000) {
8332 if (disas_neon_ls_insn(env, s, insn))
8333 goto illegal_op;
8334 break;
8336 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
8337 if (rs == 15) {
8338 if (!(insn & (1 << 20))) {
8339 goto illegal_op;
8341 if (op != 2) {
8342 /* Byte or halfword load space with dest == r15 : memory hints.
8343 * Catch them early so we don't emit pointless addressing code.
8344 * This space is a mix of:
8345 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
8346 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
8347 * cores)
8348 * unallocated hints, which must be treated as NOPs
8349 * UNPREDICTABLE space, which we NOP or UNDEF depending on
8350 * which is easiest for the decoding logic
8351 * Some space which must UNDEF
8353 int op1 = (insn >> 23) & 3;
8354 int op2 = (insn >> 6) & 0x3f;
8355 if (op & 2) {
8356 goto illegal_op;
8358 if (rn == 15) {
8359 /* UNPREDICTABLE or unallocated hint */
8360 return 0;
8362 if (op1 & 1) {
8363 return 0; /* PLD* or unallocated hint */
8365 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
8366 return 0; /* PLD* or unallocated hint */
8368 /* UNDEF space, or an UNPREDICTABLE */
8369 return 1;
8372 user = IS_USER(s);
8373 if (rn == 15) {
8374 addr = tcg_temp_new_i32();
8375 /* PC relative. */
8376 /* s->pc has already been incremented by 4. */
8377 imm = s->pc & 0xfffffffc;
8378 if (insn & (1 << 23))
8379 imm += insn & 0xfff;
8380 else
8381 imm -= insn & 0xfff;
8382 tcg_gen_movi_i32(addr, imm);
8383 } else {
8384 addr = load_reg(s, rn);
8385 if (insn & (1 << 23)) {
8386 /* Positive offset. */
8387 imm = insn & 0xfff;
8388 tcg_gen_addi_i32(addr, addr, imm);
8389 } else {
8390 imm = insn & 0xff;
8391 switch ((insn >> 8) & 0xf) {
8392 case 0x0: /* Shifted Register. */
8393 shift = (insn >> 4) & 0xf;
8394 if (shift > 3) {
8395 tcg_temp_free_i32(addr);
8396 goto illegal_op;
8398 tmp = load_reg(s, rm);
8399 if (shift)
8400 tcg_gen_shli_i32(tmp, tmp, shift);
8401 tcg_gen_add_i32(addr, addr, tmp);
8402 tcg_temp_free_i32(tmp);
8403 break;
8404 case 0xc: /* Negative offset. */
8405 tcg_gen_addi_i32(addr, addr, -imm);
8406 break;
8407 case 0xe: /* User privilege. */
8408 tcg_gen_addi_i32(addr, addr, imm);
8409 user = 1;
8410 break;
8411 case 0x9: /* Post-decrement. */
8412 imm = -imm;
8413 /* Fall through. */
8414 case 0xb: /* Post-increment. */
8415 postinc = 1;
8416 writeback = 1;
8417 break;
8418 case 0xd: /* Pre-decrement. */
8419 imm = -imm;
8420 /* Fall through. */
8421 case 0xf: /* Pre-increment. */
8422 tcg_gen_addi_i32(addr, addr, imm);
8423 writeback = 1;
8424 break;
8425 default:
8426 tcg_temp_free_i32(addr);
8427 goto illegal_op;
8431 if (insn & (1 << 20)) {
8432 /* Load. */
8433 switch (op) {
8434 case 0: tmp = gen_ld8u(addr, user); break;
8435 case 4: tmp = gen_ld8s(addr, user); break;
8436 case 1: tmp = gen_ld16u(addr, user); break;
8437 case 5: tmp = gen_ld16s(addr, user); break;
8438 case 2: tmp = gen_ld32(addr, user); break;
8439 default:
8440 tcg_temp_free_i32(addr);
8441 goto illegal_op;
8443 if (rs == 15) {
8444 gen_bx(s, tmp);
8445 } else {
8446 store_reg(s, rs, tmp);
8448 } else {
8449 /* Store. */
8450 tmp = load_reg(s, rs);
8451 switch (op) {
8452 case 0: gen_st8(tmp, addr, user); break;
8453 case 1: gen_st16(tmp, addr, user); break;
8454 case 2: gen_st32(tmp, addr, user); break;
8455 default:
8456 tcg_temp_free_i32(addr);
8457 goto illegal_op;
8460 if (postinc)
8461 tcg_gen_addi_i32(addr, addr, imm);
8462 if (writeback) {
8463 store_reg(s, rn, addr);
8464 } else {
8465 tcg_temp_free_i32(addr);
8468 break;
8469 default:
8470 goto illegal_op;
8472 return 0;
8473 illegal_op:
8474 return 1;
8477 static void disas_thumb_insn(CPUState *env, DisasContext *s)
8479 uint32_t val, insn, op, rm, rn, rd, shift, cond;
8480 int32_t offset;
8481 int i;
8482 TCGv tmp;
8483 TCGv tmp2;
8484 TCGv addr;
8486 if (s->condexec_mask) {
8487 cond = s->condexec_cond;
8488 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
8489 s->condlabel = gen_new_label();
8490 gen_test_cc(cond ^ 1, s->condlabel);
8491 s->condjmp = 1;
8495 insn = lduw_code(s->pc);
8496 s->pc += 2;
8498 switch (insn >> 12) {
8499 case 0: case 1:
8501 rd = insn & 7;
8502 op = (insn >> 11) & 3;
8503 if (op == 3) {
8504 /* add/subtract */
8505 rn = (insn >> 3) & 7;
8506 tmp = load_reg(s, rn);
8507 if (insn & (1 << 10)) {
8508 /* immediate */
8509 tmp2 = tcg_temp_new_i32();
8510 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
8511 } else {
8512 /* reg */
8513 rm = (insn >> 6) & 7;
8514 tmp2 = load_reg(s, rm);
8516 if (insn & (1 << 9)) {
8517 if (s->condexec_mask)
8518 tcg_gen_sub_i32(tmp, tmp, tmp2);
8519 else
8520 gen_helper_sub_cc(tmp, tmp, tmp2);
8521 } else {
8522 if (s->condexec_mask)
8523 tcg_gen_add_i32(tmp, tmp, tmp2);
8524 else
8525 gen_helper_add_cc(tmp, tmp, tmp2);
8527 tcg_temp_free_i32(tmp2);
8528 store_reg(s, rd, tmp);
8529 } else {
8530 /* shift immediate */
8531 rm = (insn >> 3) & 7;
8532 shift = (insn >> 6) & 0x1f;
8533 tmp = load_reg(s, rm);
8534 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
8535 if (!s->condexec_mask)
8536 gen_logic_CC(tmp);
8537 store_reg(s, rd, tmp);
8539 break;
8540 case 2: case 3:
8541 /* arithmetic large immediate */
8542 op = (insn >> 11) & 3;
8543 rd = (insn >> 8) & 0x7;
8544 if (op == 0) { /* mov */
8545 tmp = tcg_temp_new_i32();
8546 tcg_gen_movi_i32(tmp, insn & 0xff);
8547 if (!s->condexec_mask)
8548 gen_logic_CC(tmp);
8549 store_reg(s, rd, tmp);
8550 } else {
8551 tmp = load_reg(s, rd);
8552 tmp2 = tcg_temp_new_i32();
8553 tcg_gen_movi_i32(tmp2, insn & 0xff);
8554 switch (op) {
8555 case 1: /* cmp */
8556 gen_helper_sub_cc(tmp, tmp, tmp2);
8557 tcg_temp_free_i32(tmp);
8558 tcg_temp_free_i32(tmp2);
8559 break;
8560 case 2: /* add */
8561 if (s->condexec_mask)
8562 tcg_gen_add_i32(tmp, tmp, tmp2);
8563 else
8564 gen_helper_add_cc(tmp, tmp, tmp2);
8565 tcg_temp_free_i32(tmp2);
8566 store_reg(s, rd, tmp);
8567 break;
8568 case 3: /* sub */
8569 if (s->condexec_mask)
8570 tcg_gen_sub_i32(tmp, tmp, tmp2);
8571 else
8572 gen_helper_sub_cc(tmp, tmp, tmp2);
8573 tcg_temp_free_i32(tmp2);
8574 store_reg(s, rd, tmp);
8575 break;
8578 break;
8579 case 4:
8580 if (insn & (1 << 11)) {
8581 rd = (insn >> 8) & 7;
8582 /* load pc-relative. Bit 1 of PC is ignored. */
8583 val = s->pc + 2 + ((insn & 0xff) * 4);
8584 val &= ~(uint32_t)2;
8585 addr = tcg_temp_new_i32();
8586 tcg_gen_movi_i32(addr, val);
8587 tmp = gen_ld32(addr, IS_USER(s));
8588 tcg_temp_free_i32(addr);
8589 store_reg(s, rd, tmp);
8590 break;
8592 if (insn & (1 << 10)) {
8593 /* data processing extended or blx */
8594 rd = (insn & 7) | ((insn >> 4) & 8);
8595 rm = (insn >> 3) & 0xf;
8596 op = (insn >> 8) & 3;
8597 switch (op) {
8598 case 0: /* add */
8599 tmp = load_reg(s, rd);
8600 tmp2 = load_reg(s, rm);
8601 tcg_gen_add_i32(tmp, tmp, tmp2);
8602 tcg_temp_free_i32(tmp2);
8603 store_reg(s, rd, tmp);
8604 break;
8605 case 1: /* cmp */
8606 tmp = load_reg(s, rd);
8607 tmp2 = load_reg(s, rm);
8608 gen_helper_sub_cc(tmp, tmp, tmp2);
8609 tcg_temp_free_i32(tmp2);
8610 tcg_temp_free_i32(tmp);
8611 break;
8612 case 2: /* mov/cpy */
8613 tmp = load_reg(s, rm);
8614 store_reg(s, rd, tmp);
8615 break;
8616 case 3:/* branch [and link] exchange thumb register */
8617 tmp = load_reg(s, rm);
8618 if (insn & (1 << 7)) {
8619 val = (uint32_t)s->pc | 1;
8620 tmp2 = tcg_temp_new_i32();
8621 tcg_gen_movi_i32(tmp2, val);
8622 store_reg(s, 14, tmp2);
8624 gen_bx(s, tmp);
8625 break;
8627 break;
8630 /* data processing register */
8631 rd = insn & 7;
8632 rm = (insn >> 3) & 7;
8633 op = (insn >> 6) & 0xf;
8634 if (op == 2 || op == 3 || op == 4 || op == 7) {
8635 /* the shift/rotate ops want the operands backwards */
8636 val = rm;
8637 rm = rd;
8638 rd = val;
8639 val = 1;
8640 } else {
8641 val = 0;
8644 if (op == 9) { /* neg */
8645 tmp = tcg_temp_new_i32();
8646 tcg_gen_movi_i32(tmp, 0);
8647 } else if (op != 0xf) { /* mvn doesn't read its first operand */
8648 tmp = load_reg(s, rd);
8649 } else {
8650 TCGV_UNUSED(tmp);
8653 tmp2 = load_reg(s, rm);
8654 switch (op) {
8655 case 0x0: /* and */
8656 tcg_gen_and_i32(tmp, tmp, tmp2);
8657 if (!s->condexec_mask)
8658 gen_logic_CC(tmp);
8659 break;
8660 case 0x1: /* eor */
8661 tcg_gen_xor_i32(tmp, tmp, tmp2);
8662 if (!s->condexec_mask)
8663 gen_logic_CC(tmp);
8664 break;
8665 case 0x2: /* lsl */
8666 if (s->condexec_mask) {
8667 gen_helper_shl(tmp2, tmp2, tmp);
8668 } else {
8669 gen_helper_shl_cc(tmp2, tmp2, tmp);
8670 gen_logic_CC(tmp2);
8672 break;
8673 case 0x3: /* lsr */
8674 if (s->condexec_mask) {
8675 gen_helper_shr(tmp2, tmp2, tmp);
8676 } else {
8677 gen_helper_shr_cc(tmp2, tmp2, tmp);
8678 gen_logic_CC(tmp2);
8680 break;
8681 case 0x4: /* asr */
8682 if (s->condexec_mask) {
8683 gen_helper_sar(tmp2, tmp2, tmp);
8684 } else {
8685 gen_helper_sar_cc(tmp2, tmp2, tmp);
8686 gen_logic_CC(tmp2);
8688 break;
8689 case 0x5: /* adc */
8690 if (s->condexec_mask)
8691 gen_adc(tmp, tmp2);
8692 else
8693 gen_helper_adc_cc(tmp, tmp, tmp2);
8694 break;
8695 case 0x6: /* sbc */
8696 if (s->condexec_mask)
8697 gen_sub_carry(tmp, tmp, tmp2);
8698 else
8699 gen_helper_sbc_cc(tmp, tmp, tmp2);
8700 break;
8701 case 0x7: /* ror */
8702 if (s->condexec_mask) {
8703 tcg_gen_andi_i32(tmp, tmp, 0x1f);
8704 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
8705 } else {
8706 gen_helper_ror_cc(tmp2, tmp2, tmp);
8707 gen_logic_CC(tmp2);
8709 break;
8710 case 0x8: /* tst */
8711 tcg_gen_and_i32(tmp, tmp, tmp2);
8712 gen_logic_CC(tmp);
8713 rd = 16;
8714 break;
8715 case 0x9: /* neg */
8716 if (s->condexec_mask)
8717 tcg_gen_neg_i32(tmp, tmp2);
8718 else
8719 gen_helper_sub_cc(tmp, tmp, tmp2);
8720 break;
8721 case 0xa: /* cmp */
8722 gen_helper_sub_cc(tmp, tmp, tmp2);
8723 rd = 16;
8724 break;
8725 case 0xb: /* cmn */
8726 gen_helper_add_cc(tmp, tmp, tmp2);
8727 rd = 16;
8728 break;
8729 case 0xc: /* orr */
8730 tcg_gen_or_i32(tmp, tmp, tmp2);
8731 if (!s->condexec_mask)
8732 gen_logic_CC(tmp);
8733 break;
8734 case 0xd: /* mul */
8735 tcg_gen_mul_i32(tmp, tmp, tmp2);
8736 if (!s->condexec_mask)
8737 gen_logic_CC(tmp);
8738 break;
8739 case 0xe: /* bic */
8740 tcg_gen_andc_i32(tmp, tmp, tmp2);
8741 if (!s->condexec_mask)
8742 gen_logic_CC(tmp);
8743 break;
8744 case 0xf: /* mvn */
8745 tcg_gen_not_i32(tmp2, tmp2);
8746 if (!s->condexec_mask)
8747 gen_logic_CC(tmp2);
8748 val = 1;
8749 rm = rd;
8750 break;
8752 if (rd != 16) {
8753 if (val) {
8754 store_reg(s, rm, tmp2);
8755 if (op != 0xf)
8756 tcg_temp_free_i32(tmp);
8757 } else {
8758 store_reg(s, rd, tmp);
8759 tcg_temp_free_i32(tmp2);
8761 } else {
8762 tcg_temp_free_i32(tmp);
8763 tcg_temp_free_i32(tmp2);
8765 break;
8767 case 5:
8768 /* load/store register offset. */
8769 rd = insn & 7;
8770 rn = (insn >> 3) & 7;
8771 rm = (insn >> 6) & 7;
8772 op = (insn >> 9) & 7;
8773 addr = load_reg(s, rn);
8774 tmp = load_reg(s, rm);
8775 tcg_gen_add_i32(addr, addr, tmp);
8776 tcg_temp_free_i32(tmp);
8778 if (op < 3) /* store */
8779 tmp = load_reg(s, rd);
8781 switch (op) {
8782 case 0: /* str */
8783 gen_st32(tmp, addr, IS_USER(s));
8784 break;
8785 case 1: /* strh */
8786 gen_st16(tmp, addr, IS_USER(s));
8787 break;
8788 case 2: /* strb */
8789 gen_st8(tmp, addr, IS_USER(s));
8790 break;
8791 case 3: /* ldrsb */
8792 tmp = gen_ld8s(addr, IS_USER(s));
8793 break;
8794 case 4: /* ldr */
8795 tmp = gen_ld32(addr, IS_USER(s));
8796 break;
8797 case 5: /* ldrh */
8798 tmp = gen_ld16u(addr, IS_USER(s));
8799 break;
8800 case 6: /* ldrb */
8801 tmp = gen_ld8u(addr, IS_USER(s));
8802 break;
8803 case 7: /* ldrsh */
8804 tmp = gen_ld16s(addr, IS_USER(s));
8805 break;
8807 if (op >= 3) /* load */
8808 store_reg(s, rd, tmp);
8809 tcg_temp_free_i32(addr);
8810 break;
8812 case 6:
8813 /* load/store word immediate offset */
8814 rd = insn & 7;
8815 rn = (insn >> 3) & 7;
8816 addr = load_reg(s, rn);
8817 val = (insn >> 4) & 0x7c;
8818 tcg_gen_addi_i32(addr, addr, val);
8820 if (insn & (1 << 11)) {
8821 /* load */
8822 tmp = gen_ld32(addr, IS_USER(s));
8823 store_reg(s, rd, tmp);
8824 } else {
8825 /* store */
8826 tmp = load_reg(s, rd);
8827 gen_st32(tmp, addr, IS_USER(s));
8829 tcg_temp_free_i32(addr);
8830 break;
8832 case 7:
8833 /* load/store byte immediate offset */
8834 rd = insn & 7;
8835 rn = (insn >> 3) & 7;
8836 addr = load_reg(s, rn);
8837 val = (insn >> 6) & 0x1f;
8838 tcg_gen_addi_i32(addr, addr, val);
8840 if (insn & (1 << 11)) {
8841 /* load */
8842 tmp = gen_ld8u(addr, IS_USER(s));
8843 store_reg(s, rd, tmp);
8844 } else {
8845 /* store */
8846 tmp = load_reg(s, rd);
8847 gen_st8(tmp, addr, IS_USER(s));
8849 tcg_temp_free_i32(addr);
8850 break;
8852 case 8:
8853 /* load/store halfword immediate offset */
8854 rd = insn & 7;
8855 rn = (insn >> 3) & 7;
8856 addr = load_reg(s, rn);
8857 val = (insn >> 5) & 0x3e;
8858 tcg_gen_addi_i32(addr, addr, val);
8860 if (insn & (1 << 11)) {
8861 /* load */
8862 tmp = gen_ld16u(addr, IS_USER(s));
8863 store_reg(s, rd, tmp);
8864 } else {
8865 /* store */
8866 tmp = load_reg(s, rd);
8867 gen_st16(tmp, addr, IS_USER(s));
8869 tcg_temp_free_i32(addr);
8870 break;
8872 case 9:
8873 /* load/store from stack */
8874 rd = (insn >> 8) & 7;
8875 addr = load_reg(s, 13);
8876 val = (insn & 0xff) * 4;
8877 tcg_gen_addi_i32(addr, addr, val);
8879 if (insn & (1 << 11)) {
8880 /* load */
8881 tmp = gen_ld32(addr, IS_USER(s));
8882 store_reg(s, rd, tmp);
8883 } else {
8884 /* store */
8885 tmp = load_reg(s, rd);
8886 gen_st32(tmp, addr, IS_USER(s));
8888 tcg_temp_free_i32(addr);
8889 break;
8891 case 10:
8892 /* add to high reg */
8893 rd = (insn >> 8) & 7;
8894 if (insn & (1 << 11)) {
8895 /* SP */
8896 tmp = load_reg(s, 13);
8897 } else {
8898 /* PC. bit 1 is ignored. */
8899 tmp = tcg_temp_new_i32();
8900 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
8902 val = (insn & 0xff) * 4;
8903 tcg_gen_addi_i32(tmp, tmp, val);
8904 store_reg(s, rd, tmp);
8905 break;
8907 case 11:
8908 /* misc */
8909 op = (insn >> 8) & 0xf;
8910 switch (op) {
8911 case 0:
8912 /* adjust stack pointer */
8913 tmp = load_reg(s, 13);
8914 val = (insn & 0x7f) * 4;
8915 if (insn & (1 << 7))
8916 val = -(int32_t)val;
8917 tcg_gen_addi_i32(tmp, tmp, val);
8918 store_reg(s, 13, tmp);
8919 break;
8921 case 2: /* sign/zero extend. */
8922 ARCH(6);
8923 rd = insn & 7;
8924 rm = (insn >> 3) & 7;
8925 tmp = load_reg(s, rm);
8926 switch ((insn >> 6) & 3) {
8927 case 0: gen_sxth(tmp); break;
8928 case 1: gen_sxtb(tmp); break;
8929 case 2: gen_uxth(tmp); break;
8930 case 3: gen_uxtb(tmp); break;
8932 store_reg(s, rd, tmp);
8933 break;
8934 case 4: case 5: case 0xc: case 0xd:
8935 /* push/pop */
8936 addr = load_reg(s, 13);
8937 if (insn & (1 << 8))
8938 offset = 4;
8939 else
8940 offset = 0;
8941 for (i = 0; i < 8; i++) {
8942 if (insn & (1 << i))
8943 offset += 4;
8945 if ((insn & (1 << 11)) == 0) {
8946 tcg_gen_addi_i32(addr, addr, -offset);
8948 for (i = 0; i < 8; i++) {
8949 if (insn & (1 << i)) {
8950 if (insn & (1 << 11)) {
8951 /* pop */
8952 tmp = gen_ld32(addr, IS_USER(s));
8953 store_reg(s, i, tmp);
8954 } else {
8955 /* push */
8956 tmp = load_reg(s, i);
8957 gen_st32(tmp, addr, IS_USER(s));
8959 /* advance to the next address. */
8960 tcg_gen_addi_i32(addr, addr, 4);
8963 TCGV_UNUSED(tmp);
8964 if (insn & (1 << 8)) {
8965 if (insn & (1 << 11)) {
8966 /* pop pc */
8967 tmp = gen_ld32(addr, IS_USER(s));
8968 /* don't set the pc until the rest of the instruction
8969 has completed */
8970 } else {
8971 /* push lr */
8972 tmp = load_reg(s, 14);
8973 gen_st32(tmp, addr, IS_USER(s));
8975 tcg_gen_addi_i32(addr, addr, 4);
8977 if ((insn & (1 << 11)) == 0) {
8978 tcg_gen_addi_i32(addr, addr, -offset);
8980 /* write back the new stack pointer */
8981 store_reg(s, 13, addr);
8982 /* set the new PC value */
8983 if ((insn & 0x0900) == 0x0900)
8984 gen_bx(s, tmp);
8985 break;
8987 case 1: case 3: case 9: case 11: /* czb */
8988 rm = insn & 7;
8989 tmp = load_reg(s, rm);
8990 s->condlabel = gen_new_label();
8991 s->condjmp = 1;
8992 if (insn & (1 << 11))
8993 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
8994 else
8995 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
8996 tcg_temp_free_i32(tmp);
8997 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
8998 val = (uint32_t)s->pc + 2;
8999 val += offset;
9000 gen_jmp(s, val);
9001 break;
9003 case 15: /* IT, nop-hint. */
9004 if ((insn & 0xf) == 0) {
9005 gen_nop_hint(s, (insn >> 4) & 0xf);
9006 break;
9008 /* If Then. */
9009 s->condexec_cond = (insn >> 4) & 0xe;
9010 s->condexec_mask = insn & 0x1f;
9011 /* No actual code generated for this insn, just setup state. */
9012 break;
9014 case 0xe: /* bkpt */
9015 gen_exception_insn(s, 2, EXCP_BKPT);
9016 break;
9018 case 0xa: /* rev */
9019 ARCH(6);
9020 rn = (insn >> 3) & 0x7;
9021 rd = insn & 0x7;
9022 tmp = load_reg(s, rn);
9023 switch ((insn >> 6) & 3) {
9024 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
9025 case 1: gen_rev16(tmp); break;
9026 case 3: gen_revsh(tmp); break;
9027 default: goto illegal_op;
9029 store_reg(s, rd, tmp);
9030 break;
9032 case 6: /* cps */
9033 ARCH(6);
9034 if (IS_USER(s))
9035 break;
9036 if (IS_M(env)) {
9037 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
9038 /* PRIMASK */
9039 if (insn & 1) {
9040 addr = tcg_const_i32(16);
9041 gen_helper_v7m_msr(cpu_env, addr, tmp);
9042 tcg_temp_free_i32(addr);
9044 /* FAULTMASK */
9045 if (insn & 2) {
9046 addr = tcg_const_i32(17);
9047 gen_helper_v7m_msr(cpu_env, addr, tmp);
9048 tcg_temp_free_i32(addr);
9050 tcg_temp_free_i32(tmp);
9051 gen_lookup_tb(s);
9052 } else {
9053 if (insn & (1 << 4))
9054 shift = CPSR_A | CPSR_I | CPSR_F;
9055 else
9056 shift = 0;
9057 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
9059 break;
9061 default:
9062 goto undef;
9064 break;
9066 case 12:
9067 /* load/store multiple */
9068 rn = (insn >> 8) & 0x7;
9069 addr = load_reg(s, rn);
9070 for (i = 0; i < 8; i++) {
9071 if (insn & (1 << i)) {
9072 if (insn & (1 << 11)) {
9073 /* load */
9074 tmp = gen_ld32(addr, IS_USER(s));
9075 store_reg(s, i, tmp);
9076 } else {
9077 /* store */
9078 tmp = load_reg(s, i);
9079 gen_st32(tmp, addr, IS_USER(s));
9081 /* advance to the next address */
9082 tcg_gen_addi_i32(addr, addr, 4);
9085 /* Base register writeback. */
9086 if ((insn & (1 << rn)) == 0) {
9087 store_reg(s, rn, addr);
9088 } else {
9089 tcg_temp_free_i32(addr);
9091 break;
9093 case 13:
9094 /* conditional branch or swi */
9095 cond = (insn >> 8) & 0xf;
9096 if (cond == 0xe)
9097 goto undef;
9099 if (cond == 0xf) {
9100 /* swi */
9101 gen_set_pc_im(s->pc);
9102 s->is_jmp = DISAS_SWI;
9103 break;
9105 /* generate a conditional jump to next instruction */
9106 s->condlabel = gen_new_label();
9107 gen_test_cc(cond ^ 1, s->condlabel);
9108 s->condjmp = 1;
9110 /* jump to the offset */
9111 val = (uint32_t)s->pc + 2;
9112 offset = ((int32_t)insn << 24) >> 24;
9113 val += offset << 1;
9114 gen_jmp(s, val);
9115 break;
9117 case 14:
9118 if (insn & (1 << 11)) {
9119 if (disas_thumb2_insn(env, s, insn))
9120 goto undef32;
9121 break;
9123 /* unconditional branch */
9124 val = (uint32_t)s->pc;
9125 offset = ((int32_t)insn << 21) >> 21;
9126 val += (offset << 1) + 2;
9127 gen_jmp(s, val);
9128 break;
9130 case 15:
9131 if (disas_thumb2_insn(env, s, insn))
9132 goto undef32;
9133 break;
9135 return;
9136 undef32:
9137 gen_exception_insn(s, 4, EXCP_UDEF);
9138 return;
9139 illegal_op:
9140 undef:
9141 gen_exception_insn(s, 2, EXCP_UDEF);
9144 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
9145 basic block 'tb'. If search_pc is TRUE, also generate PC
9146 information for each intermediate instruction. */
9147 static inline void gen_intermediate_code_internal(CPUState *env,
9148 TranslationBlock *tb,
9149 int search_pc)
9151 DisasContext dc1, *dc = &dc1;
9152 CPUBreakpoint *bp;
9153 uint16_t *gen_opc_end;
9154 int j, lj;
9155 target_ulong pc_start;
9156 uint32_t next_page_start;
9157 int num_insns;
9158 int max_insns;
9160 /* generate intermediate code */
9161 pc_start = tb->pc;
9163 dc->tb = tb;
9165 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
9167 dc->is_jmp = DISAS_NEXT;
9168 dc->pc = pc_start;
9169 dc->singlestep_enabled = env->singlestep_enabled;
9170 dc->condjmp = 0;
9171 dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
9172 dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
9173 dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
9174 #if !defined(CONFIG_USER_ONLY)
9175 dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
9176 #endif
9177 dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
9178 dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
9179 dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
9180 cpu_F0s = tcg_temp_new_i32();
9181 cpu_F1s = tcg_temp_new_i32();
9182 cpu_F0d = tcg_temp_new_i64();
9183 cpu_F1d = tcg_temp_new_i64();
9184 cpu_V0 = cpu_F0d;
9185 cpu_V1 = cpu_F1d;
9186 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
9187 cpu_M0 = tcg_temp_new_i64();
9188 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
9189 lj = -1;
9190 num_insns = 0;
9191 max_insns = tb->cflags & CF_COUNT_MASK;
9192 if (max_insns == 0)
9193 max_insns = CF_COUNT_MASK;
9195 gen_icount_start();
9197 tcg_clear_temp_count();
9199 /* A note on handling of the condexec (IT) bits:
9201 * We want to avoid the overhead of having to write the updated condexec
9202 * bits back to the CPUState for every instruction in an IT block. So:
9203 * (1) if the condexec bits are not already zero then we write
9204 * zero back into the CPUState now. This avoids complications trying
9205 * to do it at the end of the block. (For example if we don't do this
9206 * it's hard to identify whether we can safely skip writing condexec
9207 * at the end of the TB, which we definitely want to do for the case
9208 * where a TB doesn't do anything with the IT state at all.)
9209 * (2) if we are going to leave the TB then we call gen_set_condexec()
9210 * which will write the correct value into CPUState if zero is wrong.
9211 * This is done both for leaving the TB at the end, and for leaving
9212 * it because of an exception we know will happen, which is done in
9213 * gen_exception_insn(). The latter is necessary because we need to
9214 * leave the TB with the PC/IT state just prior to execution of the
9215 * instruction which caused the exception.
9216 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
9217 * then the CPUState will be wrong and we need to reset it.
9218 * This is handled in the same way as restoration of the
9219 * PC in these situations: we will be called again with search_pc=1
9220 * and generate a mapping of the condexec bits for each PC in
9221 * gen_opc_condexec_bits[]. gen_pc_load[] then uses this to restore
9222 * the condexec bits.
9224 * Note that there are no instructions which can read the condexec
9225 * bits, and none which can write non-static values to them, so
9226 * we don't need to care about whether CPUState is correct in the
9227 * middle of a TB.
9230 /* Reset the conditional execution bits immediately. This avoids
9231 complications trying to do it at the end of the block. */
9232 if (dc->condexec_mask || dc->condexec_cond)
9234 TCGv tmp = tcg_temp_new_i32();
9235 tcg_gen_movi_i32(tmp, 0);
9236 store_cpu_field(tmp, condexec_bits);
9238 do {
9239 #ifdef CONFIG_USER_ONLY
9240 /* Intercept jump to the magic kernel page. */
9241 if (dc->pc >= 0xffff0000) {
9242 /* We always get here via a jump, so know we are not in a
9243 conditional execution block. */
9244 gen_exception(EXCP_KERNEL_TRAP);
9245 dc->is_jmp = DISAS_UPDATE;
9246 break;
9248 #else
9249 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
9250 /* We always get here via a jump, so know we are not in a
9251 conditional execution block. */
9252 gen_exception(EXCP_EXCEPTION_EXIT);
9253 dc->is_jmp = DISAS_UPDATE;
9254 break;
9256 #endif
9258 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
9259 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
9260 if (bp->pc == dc->pc) {
9261 gen_exception_insn(dc, 0, EXCP_DEBUG);
9262 /* Advance PC so that clearing the breakpoint will
9263 invalidate this TB. */
9264 dc->pc += 2;
9265 goto done_generating;
9266 break;
9270 if (search_pc) {
9271 j = gen_opc_ptr - gen_opc_buf;
9272 if (lj < j) {
9273 lj++;
9274 while (lj < j)
9275 gen_opc_instr_start[lj++] = 0;
9277 gen_opc_pc[lj] = dc->pc;
9278 gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
9279 gen_opc_instr_start[lj] = 1;
9280 gen_opc_icount[lj] = num_insns;
9283 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
9284 gen_io_start();
9286 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
9287 tcg_gen_debug_insn_start(dc->pc);
9290 if (dc->thumb) {
9291 disas_thumb_insn(env, dc);
9292 if (dc->condexec_mask) {
9293 dc->condexec_cond = (dc->condexec_cond & 0xe)
9294 | ((dc->condexec_mask >> 4) & 1);
9295 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
9296 if (dc->condexec_mask == 0) {
9297 dc->condexec_cond = 0;
9300 } else {
9301 disas_arm_insn(env, dc);
9304 if (dc->condjmp && !dc->is_jmp) {
9305 gen_set_label(dc->condlabel);
9306 dc->condjmp = 0;
9309 if (tcg_check_temp_count()) {
9310 fprintf(stderr, "TCG temporary leak before %08x\n", dc->pc);
9313 /* Translation stops when a conditional branch is encountered.
9314 * Otherwise the subsequent code could get translated several times.
9315 * Also stop translation when a page boundary is reached. This
9316 * ensures prefetch aborts occur at the right place. */
9317 num_insns ++;
9318 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
9319 !env->singlestep_enabled &&
9320 !singlestep &&
9321 dc->pc < next_page_start &&
9322 num_insns < max_insns);
9324 if (tb->cflags & CF_LAST_IO) {
9325 if (dc->condjmp) {
9326 /* FIXME: This can theoretically happen with self-modifying
9327 code. */
9328 cpu_abort(env, "IO on conditional branch instruction");
9330 gen_io_end();
9333 /* At this stage dc->condjmp will only be set when the skipped
9334 instruction was a conditional branch or trap, and the PC has
9335 already been written. */
9336 if (unlikely(env->singlestep_enabled)) {
9337 /* Make sure the pc is updated, and raise a debug exception. */
9338 if (dc->condjmp) {
9339 gen_set_condexec(dc);
9340 if (dc->is_jmp == DISAS_SWI) {
9341 gen_exception(EXCP_SWI);
9342 } else {
9343 gen_exception(EXCP_DEBUG);
9345 gen_set_label(dc->condlabel);
9347 if (dc->condjmp || !dc->is_jmp) {
9348 gen_set_pc_im(dc->pc);
9349 dc->condjmp = 0;
9351 gen_set_condexec(dc);
9352 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
9353 gen_exception(EXCP_SWI);
9354 } else {
9355 /* FIXME: Single stepping a WFI insn will not halt
9356 the CPU. */
9357 gen_exception(EXCP_DEBUG);
9359 } else {
9360 /* While branches must always occur at the end of an IT block,
9361 there are a few other things that can cause us to terminate
9362 the TB in the middel of an IT block:
9363 - Exception generating instructions (bkpt, swi, undefined).
9364 - Page boundaries.
9365 - Hardware watchpoints.
9366 Hardware breakpoints have already been handled and skip this code.
9368 gen_set_condexec(dc);
9369 switch(dc->is_jmp) {
9370 case DISAS_NEXT:
9371 gen_goto_tb(dc, 1, dc->pc);
9372 break;
9373 default:
9374 case DISAS_JUMP:
9375 case DISAS_UPDATE:
9376 /* indicate that the hash table must be used to find the next TB */
9377 tcg_gen_exit_tb(0);
9378 break;
9379 case DISAS_TB_JUMP:
9380 /* nothing more to generate */
9381 break;
9382 case DISAS_WFI:
9383 gen_helper_wfi();
9384 break;
9385 case DISAS_SWI:
9386 gen_exception(EXCP_SWI);
9387 break;
9389 if (dc->condjmp) {
9390 gen_set_label(dc->condlabel);
9391 gen_set_condexec(dc);
9392 gen_goto_tb(dc, 1, dc->pc);
9393 dc->condjmp = 0;
9397 done_generating:
9398 gen_icount_end(tb, num_insns);
9399 *gen_opc_ptr = INDEX_op_end;
9401 #ifdef DEBUG_DISAS
9402 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9403 qemu_log("----------------\n");
9404 qemu_log("IN: %s\n", lookup_symbol(pc_start));
9405 log_target_disas(pc_start, dc->pc - pc_start, dc->thumb);
9406 qemu_log("\n");
9408 #endif
9409 if (search_pc) {
9410 j = gen_opc_ptr - gen_opc_buf;
9411 lj++;
9412 while (lj <= j)
9413 gen_opc_instr_start[lj++] = 0;
9414 } else {
9415 tb->size = dc->pc - pc_start;
9416 tb->icount = num_insns;
9420 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
9422 gen_intermediate_code_internal(env, tb, 0);
9425 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
9427 gen_intermediate_code_internal(env, tb, 1);
9430 static const char *cpu_mode_names[16] = {
9431 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9432 "???", "???", "???", "und", "???", "???", "???", "sys"
9435 void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
9436 int flags)
9438 int i;
9439 #if 0
9440 union {
9441 uint32_t i;
9442 float s;
9443 } s0, s1;
9444 CPU_DoubleU d;
9445 /* ??? This assumes float64 and double have the same layout.
9446 Oh well, it's only debug dumps. */
9447 union {
9448 float64 f64;
9449 double d;
9450 } d0;
9451 #endif
9452 uint32_t psr;
9454 for(i=0;i<16;i++) {
9455 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
9456 if ((i % 4) == 3)
9457 cpu_fprintf(f, "\n");
9458 else
9459 cpu_fprintf(f, " ");
9461 psr = cpsr_read(env);
9462 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
9463 psr,
9464 psr & (1 << 31) ? 'N' : '-',
9465 psr & (1 << 30) ? 'Z' : '-',
9466 psr & (1 << 29) ? 'C' : '-',
9467 psr & (1 << 28) ? 'V' : '-',
9468 psr & CPSR_T ? 'T' : 'A',
9469 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
9471 #if 0
9472 for (i = 0; i < 16; i++) {
9473 d.d = env->vfp.regs[i];
9474 s0.i = d.l.lower;
9475 s1.i = d.l.upper;
9476 d0.f64 = d.d;
9477 cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9478 i * 2, (int)s0.i, s0.s,
9479 i * 2 + 1, (int)s1.i, s1.s,
9480 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
9481 d0.d);
9483 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
9484 #endif
9487 void gen_pc_load(CPUState *env, TranslationBlock *tb,
9488 unsigned long searched_pc, int pc_pos, void *puc)
9490 env->regs[15] = gen_opc_pc[pc_pos];
9491 env->condexec_bits = gen_opc_condexec_bits[pc_pos];