gdbstub: Catch and report more vmstop reasons
[qemu/stefanha.git] / target-arm / translate.c
blob33417e6825a542352d265b8f3b859c63ac9d26d9
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 static TCGv gen_load_and_replicate(DisasContext *s, TCGv addr, int size)
2653 /* Load a single Neon element and replicate into a 32 bit TCG reg */
2654 TCGv tmp;
2655 switch (size) {
2656 case 0:
2657 tmp = gen_ld8u(addr, IS_USER(s));
2658 gen_neon_dup_u8(tmp, 0);
2659 break;
2660 case 1:
2661 tmp = gen_ld16u(addr, IS_USER(s));
2662 gen_neon_dup_low16(tmp);
2663 break;
2664 case 2:
2665 tmp = gen_ld32(addr, IS_USER(s));
2666 break;
2667 default: /* Avoid compiler warnings. */
2668 abort();
2670 return tmp;
2673 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2674 (ie. an undefined instruction). */
2675 static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2677 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2678 int dp, veclen;
2679 TCGv addr;
2680 TCGv tmp;
2681 TCGv tmp2;
2683 if (!arm_feature(env, ARM_FEATURE_VFP))
2684 return 1;
2686 if (!s->vfp_enabled) {
2687 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2688 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2689 return 1;
2690 rn = (insn >> 16) & 0xf;
2691 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2692 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2693 return 1;
2695 dp = ((insn & 0xf00) == 0xb00);
2696 switch ((insn >> 24) & 0xf) {
2697 case 0xe:
2698 if (insn & (1 << 4)) {
2699 /* single register transfer */
2700 rd = (insn >> 12) & 0xf;
2701 if (dp) {
2702 int size;
2703 int pass;
2705 VFP_DREG_N(rn, insn);
2706 if (insn & 0xf)
2707 return 1;
2708 if (insn & 0x00c00060
2709 && !arm_feature(env, ARM_FEATURE_NEON))
2710 return 1;
2712 pass = (insn >> 21) & 1;
2713 if (insn & (1 << 22)) {
2714 size = 0;
2715 offset = ((insn >> 5) & 3) * 8;
2716 } else if (insn & (1 << 5)) {
2717 size = 1;
2718 offset = (insn & (1 << 6)) ? 16 : 0;
2719 } else {
2720 size = 2;
2721 offset = 0;
2723 if (insn & ARM_CP_RW_BIT) {
2724 /* vfp->arm */
2725 tmp = neon_load_reg(rn, pass);
2726 switch (size) {
2727 case 0:
2728 if (offset)
2729 tcg_gen_shri_i32(tmp, tmp, offset);
2730 if (insn & (1 << 23))
2731 gen_uxtb(tmp);
2732 else
2733 gen_sxtb(tmp);
2734 break;
2735 case 1:
2736 if (insn & (1 << 23)) {
2737 if (offset) {
2738 tcg_gen_shri_i32(tmp, tmp, 16);
2739 } else {
2740 gen_uxth(tmp);
2742 } else {
2743 if (offset) {
2744 tcg_gen_sari_i32(tmp, tmp, 16);
2745 } else {
2746 gen_sxth(tmp);
2749 break;
2750 case 2:
2751 break;
2753 store_reg(s, rd, tmp);
2754 } else {
2755 /* arm->vfp */
2756 tmp = load_reg(s, rd);
2757 if (insn & (1 << 23)) {
2758 /* VDUP */
2759 if (size == 0) {
2760 gen_neon_dup_u8(tmp, 0);
2761 } else if (size == 1) {
2762 gen_neon_dup_low16(tmp);
2764 for (n = 0; n <= pass * 2; n++) {
2765 tmp2 = tcg_temp_new_i32();
2766 tcg_gen_mov_i32(tmp2, tmp);
2767 neon_store_reg(rn, n, tmp2);
2769 neon_store_reg(rn, n, tmp);
2770 } else {
2771 /* VMOV */
2772 switch (size) {
2773 case 0:
2774 tmp2 = neon_load_reg(rn, pass);
2775 gen_bfi(tmp, tmp2, tmp, offset, 0xff);
2776 tcg_temp_free_i32(tmp2);
2777 break;
2778 case 1:
2779 tmp2 = neon_load_reg(rn, pass);
2780 gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
2781 tcg_temp_free_i32(tmp2);
2782 break;
2783 case 2:
2784 break;
2786 neon_store_reg(rn, pass, tmp);
2789 } else { /* !dp */
2790 if ((insn & 0x6f) != 0x00)
2791 return 1;
2792 rn = VFP_SREG_N(insn);
2793 if (insn & ARM_CP_RW_BIT) {
2794 /* vfp->arm */
2795 if (insn & (1 << 21)) {
2796 /* system register */
2797 rn >>= 1;
2799 switch (rn) {
2800 case ARM_VFP_FPSID:
2801 /* VFP2 allows access to FSID from userspace.
2802 VFP3 restricts all id registers to privileged
2803 accesses. */
2804 if (IS_USER(s)
2805 && arm_feature(env, ARM_FEATURE_VFP3))
2806 return 1;
2807 tmp = load_cpu_field(vfp.xregs[rn]);
2808 break;
2809 case ARM_VFP_FPEXC:
2810 if (IS_USER(s))
2811 return 1;
2812 tmp = load_cpu_field(vfp.xregs[rn]);
2813 break;
2814 case ARM_VFP_FPINST:
2815 case ARM_VFP_FPINST2:
2816 /* Not present in VFP3. */
2817 if (IS_USER(s)
2818 || arm_feature(env, ARM_FEATURE_VFP3))
2819 return 1;
2820 tmp = load_cpu_field(vfp.xregs[rn]);
2821 break;
2822 case ARM_VFP_FPSCR:
2823 if (rd == 15) {
2824 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2825 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2826 } else {
2827 tmp = tcg_temp_new_i32();
2828 gen_helper_vfp_get_fpscr(tmp, cpu_env);
2830 break;
2831 case ARM_VFP_MVFR0:
2832 case ARM_VFP_MVFR1:
2833 if (IS_USER(s)
2834 || !arm_feature(env, ARM_FEATURE_VFP3))
2835 return 1;
2836 tmp = load_cpu_field(vfp.xregs[rn]);
2837 break;
2838 default:
2839 return 1;
2841 } else {
2842 gen_mov_F0_vreg(0, rn);
2843 tmp = gen_vfp_mrs();
2845 if (rd == 15) {
2846 /* Set the 4 flag bits in the CPSR. */
2847 gen_set_nzcv(tmp);
2848 tcg_temp_free_i32(tmp);
2849 } else {
2850 store_reg(s, rd, tmp);
2852 } else {
2853 /* arm->vfp */
2854 tmp = load_reg(s, rd);
2855 if (insn & (1 << 21)) {
2856 rn >>= 1;
2857 /* system register */
2858 switch (rn) {
2859 case ARM_VFP_FPSID:
2860 case ARM_VFP_MVFR0:
2861 case ARM_VFP_MVFR1:
2862 /* Writes are ignored. */
2863 break;
2864 case ARM_VFP_FPSCR:
2865 gen_helper_vfp_set_fpscr(cpu_env, tmp);
2866 tcg_temp_free_i32(tmp);
2867 gen_lookup_tb(s);
2868 break;
2869 case ARM_VFP_FPEXC:
2870 if (IS_USER(s))
2871 return 1;
2872 /* TODO: VFP subarchitecture support.
2873 * For now, keep the EN bit only */
2874 tcg_gen_andi_i32(tmp, tmp, 1 << 30);
2875 store_cpu_field(tmp, vfp.xregs[rn]);
2876 gen_lookup_tb(s);
2877 break;
2878 case ARM_VFP_FPINST:
2879 case ARM_VFP_FPINST2:
2880 store_cpu_field(tmp, vfp.xregs[rn]);
2881 break;
2882 default:
2883 return 1;
2885 } else {
2886 gen_vfp_msr(tmp);
2887 gen_mov_vreg_F0(0, rn);
2891 } else {
2892 /* data processing */
2893 /* The opcode is in bits 23, 21, 20 and 6. */
2894 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2895 if (dp) {
2896 if (op == 15) {
2897 /* rn is opcode */
2898 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2899 } else {
2900 /* rn is register number */
2901 VFP_DREG_N(rn, insn);
2904 if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18))) {
2905 /* Integer or single precision destination. */
2906 rd = VFP_SREG_D(insn);
2907 } else {
2908 VFP_DREG_D(rd, insn);
2910 if (op == 15 &&
2911 (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14))) {
2912 /* VCVT from int is always from S reg regardless of dp bit.
2913 * VCVT with immediate frac_bits has same format as SREG_M
2915 rm = VFP_SREG_M(insn);
2916 } else {
2917 VFP_DREG_M(rm, insn);
2919 } else {
2920 rn = VFP_SREG_N(insn);
2921 if (op == 15 && rn == 15) {
2922 /* Double precision destination. */
2923 VFP_DREG_D(rd, insn);
2924 } else {
2925 rd = VFP_SREG_D(insn);
2927 /* NB that we implicitly rely on the encoding for the frac_bits
2928 * in VCVT of fixed to float being the same as that of an SREG_M
2930 rm = VFP_SREG_M(insn);
2933 veclen = s->vec_len;
2934 if (op == 15 && rn > 3)
2935 veclen = 0;
2937 /* Shut up compiler warnings. */
2938 delta_m = 0;
2939 delta_d = 0;
2940 bank_mask = 0;
2942 if (veclen > 0) {
2943 if (dp)
2944 bank_mask = 0xc;
2945 else
2946 bank_mask = 0x18;
2948 /* Figure out what type of vector operation this is. */
2949 if ((rd & bank_mask) == 0) {
2950 /* scalar */
2951 veclen = 0;
2952 } else {
2953 if (dp)
2954 delta_d = (s->vec_stride >> 1) + 1;
2955 else
2956 delta_d = s->vec_stride + 1;
2958 if ((rm & bank_mask) == 0) {
2959 /* mixed scalar/vector */
2960 delta_m = 0;
2961 } else {
2962 /* vector */
2963 delta_m = delta_d;
2968 /* Load the initial operands. */
2969 if (op == 15) {
2970 switch (rn) {
2971 case 16:
2972 case 17:
2973 /* Integer source */
2974 gen_mov_F0_vreg(0, rm);
2975 break;
2976 case 8:
2977 case 9:
2978 /* Compare */
2979 gen_mov_F0_vreg(dp, rd);
2980 gen_mov_F1_vreg(dp, rm);
2981 break;
2982 case 10:
2983 case 11:
2984 /* Compare with zero */
2985 gen_mov_F0_vreg(dp, rd);
2986 gen_vfp_F1_ld0(dp);
2987 break;
2988 case 20:
2989 case 21:
2990 case 22:
2991 case 23:
2992 case 28:
2993 case 29:
2994 case 30:
2995 case 31:
2996 /* Source and destination the same. */
2997 gen_mov_F0_vreg(dp, rd);
2998 break;
2999 default:
3000 /* One source operand. */
3001 gen_mov_F0_vreg(dp, rm);
3002 break;
3004 } else {
3005 /* Two source operands. */
3006 gen_mov_F0_vreg(dp, rn);
3007 gen_mov_F1_vreg(dp, rm);
3010 for (;;) {
3011 /* Perform the calculation. */
3012 switch (op) {
3013 case 0: /* mac: fd + (fn * fm) */
3014 gen_vfp_mul(dp);
3015 gen_mov_F1_vreg(dp, rd);
3016 gen_vfp_add(dp);
3017 break;
3018 case 1: /* nmac: fd - (fn * fm) */
3019 gen_vfp_mul(dp);
3020 gen_vfp_neg(dp);
3021 gen_mov_F1_vreg(dp, rd);
3022 gen_vfp_add(dp);
3023 break;
3024 case 2: /* msc: -fd + (fn * fm) */
3025 gen_vfp_mul(dp);
3026 gen_mov_F1_vreg(dp, rd);
3027 gen_vfp_sub(dp);
3028 break;
3029 case 3: /* nmsc: -fd - (fn * fm) */
3030 gen_vfp_mul(dp);
3031 gen_vfp_neg(dp);
3032 gen_mov_F1_vreg(dp, rd);
3033 gen_vfp_sub(dp);
3034 break;
3035 case 4: /* mul: fn * fm */
3036 gen_vfp_mul(dp);
3037 break;
3038 case 5: /* nmul: -(fn * fm) */
3039 gen_vfp_mul(dp);
3040 gen_vfp_neg(dp);
3041 break;
3042 case 6: /* add: fn + fm */
3043 gen_vfp_add(dp);
3044 break;
3045 case 7: /* sub: fn - fm */
3046 gen_vfp_sub(dp);
3047 break;
3048 case 8: /* div: fn / fm */
3049 gen_vfp_div(dp);
3050 break;
3051 case 14: /* fconst */
3052 if (!arm_feature(env, ARM_FEATURE_VFP3))
3053 return 1;
3055 n = (insn << 12) & 0x80000000;
3056 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3057 if (dp) {
3058 if (i & 0x40)
3059 i |= 0x3f80;
3060 else
3061 i |= 0x4000;
3062 n |= i << 16;
3063 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3064 } else {
3065 if (i & 0x40)
3066 i |= 0x780;
3067 else
3068 i |= 0x800;
3069 n |= i << 19;
3070 tcg_gen_movi_i32(cpu_F0s, n);
3072 break;
3073 case 15: /* extension space */
3074 switch (rn) {
3075 case 0: /* cpy */
3076 /* no-op */
3077 break;
3078 case 1: /* abs */
3079 gen_vfp_abs(dp);
3080 break;
3081 case 2: /* neg */
3082 gen_vfp_neg(dp);
3083 break;
3084 case 3: /* sqrt */
3085 gen_vfp_sqrt(dp);
3086 break;
3087 case 4: /* vcvtb.f32.f16 */
3088 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3089 return 1;
3090 tmp = gen_vfp_mrs();
3091 tcg_gen_ext16u_i32(tmp, tmp);
3092 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3093 tcg_temp_free_i32(tmp);
3094 break;
3095 case 5: /* vcvtt.f32.f16 */
3096 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3097 return 1;
3098 tmp = gen_vfp_mrs();
3099 tcg_gen_shri_i32(tmp, tmp, 16);
3100 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3101 tcg_temp_free_i32(tmp);
3102 break;
3103 case 6: /* vcvtb.f16.f32 */
3104 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3105 return 1;
3106 tmp = tcg_temp_new_i32();
3107 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3108 gen_mov_F0_vreg(0, rd);
3109 tmp2 = gen_vfp_mrs();
3110 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3111 tcg_gen_or_i32(tmp, tmp, tmp2);
3112 tcg_temp_free_i32(tmp2);
3113 gen_vfp_msr(tmp);
3114 break;
3115 case 7: /* vcvtt.f16.f32 */
3116 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
3117 return 1;
3118 tmp = tcg_temp_new_i32();
3119 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3120 tcg_gen_shli_i32(tmp, tmp, 16);
3121 gen_mov_F0_vreg(0, rd);
3122 tmp2 = gen_vfp_mrs();
3123 tcg_gen_ext16u_i32(tmp2, tmp2);
3124 tcg_gen_or_i32(tmp, tmp, tmp2);
3125 tcg_temp_free_i32(tmp2);
3126 gen_vfp_msr(tmp);
3127 break;
3128 case 8: /* cmp */
3129 gen_vfp_cmp(dp);
3130 break;
3131 case 9: /* cmpe */
3132 gen_vfp_cmpe(dp);
3133 break;
3134 case 10: /* cmpz */
3135 gen_vfp_cmp(dp);
3136 break;
3137 case 11: /* cmpez */
3138 gen_vfp_F1_ld0(dp);
3139 gen_vfp_cmpe(dp);
3140 break;
3141 case 15: /* single<->double conversion */
3142 if (dp)
3143 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3144 else
3145 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3146 break;
3147 case 16: /* fuito */
3148 gen_vfp_uito(dp);
3149 break;
3150 case 17: /* fsito */
3151 gen_vfp_sito(dp);
3152 break;
3153 case 20: /* fshto */
3154 if (!arm_feature(env, ARM_FEATURE_VFP3))
3155 return 1;
3156 gen_vfp_shto(dp, 16 - rm);
3157 break;
3158 case 21: /* fslto */
3159 if (!arm_feature(env, ARM_FEATURE_VFP3))
3160 return 1;
3161 gen_vfp_slto(dp, 32 - rm);
3162 break;
3163 case 22: /* fuhto */
3164 if (!arm_feature(env, ARM_FEATURE_VFP3))
3165 return 1;
3166 gen_vfp_uhto(dp, 16 - rm);
3167 break;
3168 case 23: /* fulto */
3169 if (!arm_feature(env, ARM_FEATURE_VFP3))
3170 return 1;
3171 gen_vfp_ulto(dp, 32 - rm);
3172 break;
3173 case 24: /* ftoui */
3174 gen_vfp_toui(dp);
3175 break;
3176 case 25: /* ftouiz */
3177 gen_vfp_touiz(dp);
3178 break;
3179 case 26: /* ftosi */
3180 gen_vfp_tosi(dp);
3181 break;
3182 case 27: /* ftosiz */
3183 gen_vfp_tosiz(dp);
3184 break;
3185 case 28: /* ftosh */
3186 if (!arm_feature(env, ARM_FEATURE_VFP3))
3187 return 1;
3188 gen_vfp_tosh(dp, 16 - rm);
3189 break;
3190 case 29: /* ftosl */
3191 if (!arm_feature(env, ARM_FEATURE_VFP3))
3192 return 1;
3193 gen_vfp_tosl(dp, 32 - rm);
3194 break;
3195 case 30: /* ftouh */
3196 if (!arm_feature(env, ARM_FEATURE_VFP3))
3197 return 1;
3198 gen_vfp_touh(dp, 16 - rm);
3199 break;
3200 case 31: /* ftoul */
3201 if (!arm_feature(env, ARM_FEATURE_VFP3))
3202 return 1;
3203 gen_vfp_toul(dp, 32 - rm);
3204 break;
3205 default: /* undefined */
3206 printf ("rn:%d\n", rn);
3207 return 1;
3209 break;
3210 default: /* undefined */
3211 printf ("op:%d\n", op);
3212 return 1;
3215 /* Write back the result. */
3216 if (op == 15 && (rn >= 8 && rn <= 11))
3217 ; /* Comparison, do nothing. */
3218 else if (op == 15 && dp && ((rn & 0x1c) == 0x18))
3219 /* VCVT double to int: always integer result. */
3220 gen_mov_vreg_F0(0, rd);
3221 else if (op == 15 && rn == 15)
3222 /* conversion */
3223 gen_mov_vreg_F0(!dp, rd);
3224 else
3225 gen_mov_vreg_F0(dp, rd);
3227 /* break out of the loop if we have finished */
3228 if (veclen == 0)
3229 break;
3231 if (op == 15 && delta_m == 0) {
3232 /* single source one-many */
3233 while (veclen--) {
3234 rd = ((rd + delta_d) & (bank_mask - 1))
3235 | (rd & bank_mask);
3236 gen_mov_vreg_F0(dp, rd);
3238 break;
3240 /* Setup the next operands. */
3241 veclen--;
3242 rd = ((rd + delta_d) & (bank_mask - 1))
3243 | (rd & bank_mask);
3245 if (op == 15) {
3246 /* One source operand. */
3247 rm = ((rm + delta_m) & (bank_mask - 1))
3248 | (rm & bank_mask);
3249 gen_mov_F0_vreg(dp, rm);
3250 } else {
3251 /* Two source operands. */
3252 rn = ((rn + delta_d) & (bank_mask - 1))
3253 | (rn & bank_mask);
3254 gen_mov_F0_vreg(dp, rn);
3255 if (delta_m) {
3256 rm = ((rm + delta_m) & (bank_mask - 1))
3257 | (rm & bank_mask);
3258 gen_mov_F1_vreg(dp, rm);
3263 break;
3264 case 0xc:
3265 case 0xd:
3266 if ((insn & 0x03e00000) == 0x00400000) {
3267 /* two-register transfer */
3268 rn = (insn >> 16) & 0xf;
3269 rd = (insn >> 12) & 0xf;
3270 if (dp) {
3271 VFP_DREG_M(rm, insn);
3272 } else {
3273 rm = VFP_SREG_M(insn);
3276 if (insn & ARM_CP_RW_BIT) {
3277 /* vfp->arm */
3278 if (dp) {
3279 gen_mov_F0_vreg(0, rm * 2);
3280 tmp = gen_vfp_mrs();
3281 store_reg(s, rd, tmp);
3282 gen_mov_F0_vreg(0, rm * 2 + 1);
3283 tmp = gen_vfp_mrs();
3284 store_reg(s, rn, tmp);
3285 } else {
3286 gen_mov_F0_vreg(0, rm);
3287 tmp = gen_vfp_mrs();
3288 store_reg(s, rd, tmp);
3289 gen_mov_F0_vreg(0, rm + 1);
3290 tmp = gen_vfp_mrs();
3291 store_reg(s, rn, tmp);
3293 } else {
3294 /* arm->vfp */
3295 if (dp) {
3296 tmp = load_reg(s, rd);
3297 gen_vfp_msr(tmp);
3298 gen_mov_vreg_F0(0, rm * 2);
3299 tmp = load_reg(s, rn);
3300 gen_vfp_msr(tmp);
3301 gen_mov_vreg_F0(0, rm * 2 + 1);
3302 } else {
3303 tmp = load_reg(s, rd);
3304 gen_vfp_msr(tmp);
3305 gen_mov_vreg_F0(0, rm);
3306 tmp = load_reg(s, rn);
3307 gen_vfp_msr(tmp);
3308 gen_mov_vreg_F0(0, rm + 1);
3311 } else {
3312 /* Load/store */
3313 rn = (insn >> 16) & 0xf;
3314 if (dp)
3315 VFP_DREG_D(rd, insn);
3316 else
3317 rd = VFP_SREG_D(insn);
3318 if (s->thumb && rn == 15) {
3319 addr = tcg_temp_new_i32();
3320 tcg_gen_movi_i32(addr, s->pc & ~2);
3321 } else {
3322 addr = load_reg(s, rn);
3324 if ((insn & 0x01200000) == 0x01000000) {
3325 /* Single load/store */
3326 offset = (insn & 0xff) << 2;
3327 if ((insn & (1 << 23)) == 0)
3328 offset = -offset;
3329 tcg_gen_addi_i32(addr, addr, offset);
3330 if (insn & (1 << 20)) {
3331 gen_vfp_ld(s, dp, addr);
3332 gen_mov_vreg_F0(dp, rd);
3333 } else {
3334 gen_mov_F0_vreg(dp, rd);
3335 gen_vfp_st(s, dp, addr);
3337 tcg_temp_free_i32(addr);
3338 } else {
3339 /* load/store multiple */
3340 if (dp)
3341 n = (insn >> 1) & 0x7f;
3342 else
3343 n = insn & 0xff;
3345 if (insn & (1 << 24)) /* pre-decrement */
3346 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
3348 if (dp)
3349 offset = 8;
3350 else
3351 offset = 4;
3352 for (i = 0; i < n; i++) {
3353 if (insn & ARM_CP_RW_BIT) {
3354 /* load */
3355 gen_vfp_ld(s, dp, addr);
3356 gen_mov_vreg_F0(dp, rd + i);
3357 } else {
3358 /* store */
3359 gen_mov_F0_vreg(dp, rd + i);
3360 gen_vfp_st(s, dp, addr);
3362 tcg_gen_addi_i32(addr, addr, offset);
3364 if (insn & (1 << 21)) {
3365 /* writeback */
3366 if (insn & (1 << 24))
3367 offset = -offset * n;
3368 else if (dp && (insn & 1))
3369 offset = 4;
3370 else
3371 offset = 0;
3373 if (offset != 0)
3374 tcg_gen_addi_i32(addr, addr, offset);
3375 store_reg(s, rn, addr);
3376 } else {
3377 tcg_temp_free_i32(addr);
3381 break;
3382 default:
3383 /* Should never happen. */
3384 return 1;
3386 return 0;
3389 static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3391 TranslationBlock *tb;
3393 tb = s->tb;
3394 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3395 tcg_gen_goto_tb(n);
3396 gen_set_pc_im(dest);
3397 tcg_gen_exit_tb((long)tb + n);
3398 } else {
3399 gen_set_pc_im(dest);
3400 tcg_gen_exit_tb(0);
3404 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3406 if (unlikely(s->singlestep_enabled)) {
3407 /* An indirect jump so that we still trigger the debug exception. */
3408 if (s->thumb)
3409 dest |= 1;
3410 gen_bx_im(s, dest);
3411 } else {
3412 gen_goto_tb(s, 0, dest);
3413 s->is_jmp = DISAS_TB_JUMP;
3417 static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3419 if (x)
3420 tcg_gen_sari_i32(t0, t0, 16);
3421 else
3422 gen_sxth(t0);
3423 if (y)
3424 tcg_gen_sari_i32(t1, t1, 16);
3425 else
3426 gen_sxth(t1);
3427 tcg_gen_mul_i32(t0, t0, t1);
3430 /* Return the mask of PSR bits set by a MSR instruction. */
3431 static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3432 uint32_t mask;
3434 mask = 0;
3435 if (flags & (1 << 0))
3436 mask |= 0xff;
3437 if (flags & (1 << 1))
3438 mask |= 0xff00;
3439 if (flags & (1 << 2))
3440 mask |= 0xff0000;
3441 if (flags & (1 << 3))
3442 mask |= 0xff000000;
3444 /* Mask out undefined bits. */
3445 mask &= ~CPSR_RESERVED;
3446 if (!arm_feature(env, ARM_FEATURE_V6))
3447 mask &= ~(CPSR_E | CPSR_GE);
3448 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3449 mask &= ~CPSR_IT;
3450 /* Mask out execution state bits. */
3451 if (!spsr)
3452 mask &= ~CPSR_EXEC;
3453 /* Mask out privileged bits. */
3454 if (IS_USER(s))
3455 mask &= CPSR_USER;
3456 return mask;
3459 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3460 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0)
3462 TCGv tmp;
3463 if (spsr) {
3464 /* ??? This is also undefined in system mode. */
3465 if (IS_USER(s))
3466 return 1;
3468 tmp = load_cpu_field(spsr);
3469 tcg_gen_andi_i32(tmp, tmp, ~mask);
3470 tcg_gen_andi_i32(t0, t0, mask);
3471 tcg_gen_or_i32(tmp, tmp, t0);
3472 store_cpu_field(tmp, spsr);
3473 } else {
3474 gen_set_cpsr(t0, mask);
3476 tcg_temp_free_i32(t0);
3477 gen_lookup_tb(s);
3478 return 0;
3481 /* Returns nonzero if access to the PSR is not permitted. */
3482 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3484 TCGv tmp;
3485 tmp = tcg_temp_new_i32();
3486 tcg_gen_movi_i32(tmp, val);
3487 return gen_set_psr(s, mask, spsr, tmp);
3490 /* Generate an old-style exception return. Marks pc as dead. */
3491 static void gen_exception_return(DisasContext *s, TCGv pc)
3493 TCGv tmp;
3494 store_reg(s, 15, pc);
3495 tmp = load_cpu_field(spsr);
3496 gen_set_cpsr(tmp, 0xffffffff);
3497 tcg_temp_free_i32(tmp);
3498 s->is_jmp = DISAS_UPDATE;
3501 /* Generate a v6 exception return. Marks both values as dead. */
3502 static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3504 gen_set_cpsr(cpsr, 0xffffffff);
3505 tcg_temp_free_i32(cpsr);
3506 store_reg(s, 15, pc);
3507 s->is_jmp = DISAS_UPDATE;
3510 static inline void
3511 gen_set_condexec (DisasContext *s)
3513 if (s->condexec_mask) {
3514 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3515 TCGv tmp = tcg_temp_new_i32();
3516 tcg_gen_movi_i32(tmp, val);
3517 store_cpu_field(tmp, condexec_bits);
3521 static void gen_exception_insn(DisasContext *s, int offset, int excp)
3523 gen_set_condexec(s);
3524 gen_set_pc_im(s->pc - offset);
3525 gen_exception(excp);
3526 s->is_jmp = DISAS_JUMP;
3529 static void gen_nop_hint(DisasContext *s, int val)
3531 switch (val) {
3532 case 3: /* wfi */
3533 gen_set_pc_im(s->pc);
3534 s->is_jmp = DISAS_WFI;
3535 break;
3536 case 2: /* wfe */
3537 case 4: /* sev */
3538 /* TODO: Implement SEV and WFE. May help SMP performance. */
3539 default: /* nop */
3540 break;
3544 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3546 static inline int gen_neon_add(int size, TCGv t0, TCGv t1)
3548 switch (size) {
3549 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
3550 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
3551 case 2: tcg_gen_add_i32(t0, t0, t1); break;
3552 default: return 1;
3554 return 0;
3557 static inline void gen_neon_rsb(int size, TCGv t0, TCGv t1)
3559 switch (size) {
3560 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
3561 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
3562 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
3563 default: return;
3567 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3568 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3569 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3570 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3571 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3573 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3574 switch ((size << 1) | u) { \
3575 case 0: \
3576 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3577 break; \
3578 case 1: \
3579 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3580 break; \
3581 case 2: \
3582 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3583 break; \
3584 case 3: \
3585 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3586 break; \
3587 case 4: \
3588 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3589 break; \
3590 case 5: \
3591 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3592 break; \
3593 default: return 1; \
3594 }} while (0)
3596 #define GEN_NEON_INTEGER_OP(name) do { \
3597 switch ((size << 1) | u) { \
3598 case 0: \
3599 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3600 break; \
3601 case 1: \
3602 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3603 break; \
3604 case 2: \
3605 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3606 break; \
3607 case 3: \
3608 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3609 break; \
3610 case 4: \
3611 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3612 break; \
3613 case 5: \
3614 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3615 break; \
3616 default: return 1; \
3617 }} while (0)
3619 static TCGv neon_load_scratch(int scratch)
3621 TCGv tmp = tcg_temp_new_i32();
3622 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3623 return tmp;
3626 static void neon_store_scratch(int scratch, TCGv var)
3628 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3629 tcg_temp_free_i32(var);
3632 static inline TCGv neon_get_scalar(int size, int reg)
3634 TCGv tmp;
3635 if (size == 1) {
3636 tmp = neon_load_reg(reg & 7, reg >> 4);
3637 if (reg & 8) {
3638 gen_neon_dup_high16(tmp);
3639 } else {
3640 gen_neon_dup_low16(tmp);
3642 } else {
3643 tmp = neon_load_reg(reg & 15, reg >> 4);
3645 return tmp;
3648 static int gen_neon_unzip(int rd, int rm, int size, int q)
3650 TCGv tmp, tmp2;
3651 if (size == 3 || (!q && size == 2)) {
3652 return 1;
3654 tmp = tcg_const_i32(rd);
3655 tmp2 = tcg_const_i32(rm);
3656 if (q) {
3657 switch (size) {
3658 case 0:
3659 gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
3660 break;
3661 case 1:
3662 gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
3663 break;
3664 case 2:
3665 gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
3666 break;
3667 default:
3668 abort();
3670 } else {
3671 switch (size) {
3672 case 0:
3673 gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
3674 break;
3675 case 1:
3676 gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
3677 break;
3678 default:
3679 abort();
3682 tcg_temp_free_i32(tmp);
3683 tcg_temp_free_i32(tmp2);
3684 return 0;
3687 static int gen_neon_zip(int rd, int rm, int size, int q)
3689 TCGv tmp, tmp2;
3690 if (size == 3 || (!q && size == 2)) {
3691 return 1;
3693 tmp = tcg_const_i32(rd);
3694 tmp2 = tcg_const_i32(rm);
3695 if (q) {
3696 switch (size) {
3697 case 0:
3698 gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
3699 break;
3700 case 1:
3701 gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
3702 break;
3703 case 2:
3704 gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
3705 break;
3706 default:
3707 abort();
3709 } else {
3710 switch (size) {
3711 case 0:
3712 gen_helper_neon_zip8(cpu_env, tmp, tmp2);
3713 break;
3714 case 1:
3715 gen_helper_neon_zip16(cpu_env, tmp, tmp2);
3716 break;
3717 default:
3718 abort();
3721 tcg_temp_free_i32(tmp);
3722 tcg_temp_free_i32(tmp2);
3723 return 0;
3726 static void gen_neon_trn_u8(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, 8);
3734 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3735 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3736 tcg_gen_or_i32(rd, rd, tmp);
3738 tcg_gen_shri_i32(t1, t1, 8);
3739 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3740 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3741 tcg_gen_or_i32(t1, t1, tmp);
3742 tcg_gen_mov_i32(t0, rd);
3744 tcg_temp_free_i32(tmp);
3745 tcg_temp_free_i32(rd);
3748 static void gen_neon_trn_u16(TCGv t0, TCGv t1)
3750 TCGv rd, tmp;
3752 rd = tcg_temp_new_i32();
3753 tmp = tcg_temp_new_i32();
3755 tcg_gen_shli_i32(rd, t0, 16);
3756 tcg_gen_andi_i32(tmp, t1, 0xffff);
3757 tcg_gen_or_i32(rd, rd, tmp);
3758 tcg_gen_shri_i32(t1, t1, 16);
3759 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3760 tcg_gen_or_i32(t1, t1, tmp);
3761 tcg_gen_mov_i32(t0, rd);
3763 tcg_temp_free_i32(tmp);
3764 tcg_temp_free_i32(rd);
3768 static struct {
3769 int nregs;
3770 int interleave;
3771 int spacing;
3772 } neon_ls_element_type[11] = {
3773 {4, 4, 1},
3774 {4, 4, 2},
3775 {4, 1, 1},
3776 {4, 2, 1},
3777 {3, 3, 1},
3778 {3, 3, 2},
3779 {3, 1, 1},
3780 {1, 1, 1},
3781 {2, 2, 1},
3782 {2, 2, 2},
3783 {2, 1, 1}
3786 /* Translate a NEON load/store element instruction. Return nonzero if the
3787 instruction is invalid. */
3788 static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3790 int rd, rn, rm;
3791 int op;
3792 int nregs;
3793 int interleave;
3794 int spacing;
3795 int stride;
3796 int size;
3797 int reg;
3798 int pass;
3799 int load;
3800 int shift;
3801 int n;
3802 TCGv addr;
3803 TCGv tmp;
3804 TCGv tmp2;
3805 TCGv_i64 tmp64;
3807 if (!s->vfp_enabled)
3808 return 1;
3809 VFP_DREG_D(rd, insn);
3810 rn = (insn >> 16) & 0xf;
3811 rm = insn & 0xf;
3812 load = (insn & (1 << 21)) != 0;
3813 if ((insn & (1 << 23)) == 0) {
3814 /* Load store all elements. */
3815 op = (insn >> 8) & 0xf;
3816 size = (insn >> 6) & 3;
3817 if (op > 10)
3818 return 1;
3819 nregs = neon_ls_element_type[op].nregs;
3820 interleave = neon_ls_element_type[op].interleave;
3821 spacing = neon_ls_element_type[op].spacing;
3822 if (size == 3 && (interleave | spacing) != 1)
3823 return 1;
3824 addr = tcg_temp_new_i32();
3825 load_reg_var(s, addr, rn);
3826 stride = (1 << size) * interleave;
3827 for (reg = 0; reg < nregs; reg++) {
3828 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3829 load_reg_var(s, addr, rn);
3830 tcg_gen_addi_i32(addr, addr, (1 << size) * reg);
3831 } else if (interleave == 2 && nregs == 4 && reg == 2) {
3832 load_reg_var(s, addr, rn);
3833 tcg_gen_addi_i32(addr, addr, 1 << size);
3835 if (size == 3) {
3836 if (load) {
3837 tmp64 = gen_ld64(addr, IS_USER(s));
3838 neon_store_reg64(tmp64, rd);
3839 tcg_temp_free_i64(tmp64);
3840 } else {
3841 tmp64 = tcg_temp_new_i64();
3842 neon_load_reg64(tmp64, rd);
3843 gen_st64(tmp64, addr, IS_USER(s));
3845 tcg_gen_addi_i32(addr, addr, stride);
3846 } else {
3847 for (pass = 0; pass < 2; pass++) {
3848 if (size == 2) {
3849 if (load) {
3850 tmp = gen_ld32(addr, IS_USER(s));
3851 neon_store_reg(rd, pass, tmp);
3852 } else {
3853 tmp = neon_load_reg(rd, pass);
3854 gen_st32(tmp, addr, IS_USER(s));
3856 tcg_gen_addi_i32(addr, addr, stride);
3857 } else if (size == 1) {
3858 if (load) {
3859 tmp = gen_ld16u(addr, IS_USER(s));
3860 tcg_gen_addi_i32(addr, addr, stride);
3861 tmp2 = gen_ld16u(addr, IS_USER(s));
3862 tcg_gen_addi_i32(addr, addr, stride);
3863 tcg_gen_shli_i32(tmp2, tmp2, 16);
3864 tcg_gen_or_i32(tmp, tmp, tmp2);
3865 tcg_temp_free_i32(tmp2);
3866 neon_store_reg(rd, pass, tmp);
3867 } else {
3868 tmp = neon_load_reg(rd, pass);
3869 tmp2 = tcg_temp_new_i32();
3870 tcg_gen_shri_i32(tmp2, tmp, 16);
3871 gen_st16(tmp, addr, IS_USER(s));
3872 tcg_gen_addi_i32(addr, addr, stride);
3873 gen_st16(tmp2, addr, IS_USER(s));
3874 tcg_gen_addi_i32(addr, addr, stride);
3876 } else /* size == 0 */ {
3877 if (load) {
3878 TCGV_UNUSED(tmp2);
3879 for (n = 0; n < 4; n++) {
3880 tmp = gen_ld8u(addr, IS_USER(s));
3881 tcg_gen_addi_i32(addr, addr, stride);
3882 if (n == 0) {
3883 tmp2 = tmp;
3884 } else {
3885 tcg_gen_shli_i32(tmp, tmp, n * 8);
3886 tcg_gen_or_i32(tmp2, tmp2, tmp);
3887 tcg_temp_free_i32(tmp);
3890 neon_store_reg(rd, pass, tmp2);
3891 } else {
3892 tmp2 = neon_load_reg(rd, pass);
3893 for (n = 0; n < 4; n++) {
3894 tmp = tcg_temp_new_i32();
3895 if (n == 0) {
3896 tcg_gen_mov_i32(tmp, tmp2);
3897 } else {
3898 tcg_gen_shri_i32(tmp, tmp2, n * 8);
3900 gen_st8(tmp, addr, IS_USER(s));
3901 tcg_gen_addi_i32(addr, addr, stride);
3903 tcg_temp_free_i32(tmp2);
3908 rd += spacing;
3910 tcg_temp_free_i32(addr);
3911 stride = nregs * 8;
3912 } else {
3913 size = (insn >> 10) & 3;
3914 if (size == 3) {
3915 /* Load single element to all lanes. */
3916 int a = (insn >> 4) & 1;
3917 if (!load) {
3918 return 1;
3920 size = (insn >> 6) & 3;
3921 nregs = ((insn >> 8) & 3) + 1;
3923 if (size == 3) {
3924 if (nregs != 4 || a == 0) {
3925 return 1;
3927 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
3928 size = 2;
3930 if (nregs == 1 && a == 1 && size == 0) {
3931 return 1;
3933 if (nregs == 3 && a == 1) {
3934 return 1;
3936 addr = tcg_temp_new_i32();
3937 load_reg_var(s, addr, rn);
3938 if (nregs == 1) {
3939 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */
3940 tmp = gen_load_and_replicate(s, addr, size);
3941 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
3942 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
3943 if (insn & (1 << 5)) {
3944 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 0));
3945 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 1));
3947 tcg_temp_free_i32(tmp);
3948 } else {
3949 /* VLD2/3/4 to all lanes: bit 5 indicates register stride */
3950 stride = (insn & (1 << 5)) ? 2 : 1;
3951 for (reg = 0; reg < nregs; reg++) {
3952 tmp = gen_load_and_replicate(s, addr, size);
3953 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
3954 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
3955 tcg_temp_free_i32(tmp);
3956 tcg_gen_addi_i32(addr, addr, 1 << size);
3957 rd += stride;
3960 tcg_temp_free_i32(addr);
3961 stride = (1 << size) * nregs;
3962 } else {
3963 /* Single element. */
3964 pass = (insn >> 7) & 1;
3965 switch (size) {
3966 case 0:
3967 shift = ((insn >> 5) & 3) * 8;
3968 stride = 1;
3969 break;
3970 case 1:
3971 shift = ((insn >> 6) & 1) * 16;
3972 stride = (insn & (1 << 5)) ? 2 : 1;
3973 break;
3974 case 2:
3975 shift = 0;
3976 stride = (insn & (1 << 6)) ? 2 : 1;
3977 break;
3978 default:
3979 abort();
3981 nregs = ((insn >> 8) & 3) + 1;
3982 addr = tcg_temp_new_i32();
3983 load_reg_var(s, addr, rn);
3984 for (reg = 0; reg < nregs; reg++) {
3985 if (load) {
3986 switch (size) {
3987 case 0:
3988 tmp = gen_ld8u(addr, IS_USER(s));
3989 break;
3990 case 1:
3991 tmp = gen_ld16u(addr, IS_USER(s));
3992 break;
3993 case 2:
3994 tmp = gen_ld32(addr, IS_USER(s));
3995 break;
3996 default: /* Avoid compiler warnings. */
3997 abort();
3999 if (size != 2) {
4000 tmp2 = neon_load_reg(rd, pass);
4001 gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
4002 tcg_temp_free_i32(tmp2);
4004 neon_store_reg(rd, pass, tmp);
4005 } else { /* Store */
4006 tmp = neon_load_reg(rd, pass);
4007 if (shift)
4008 tcg_gen_shri_i32(tmp, tmp, shift);
4009 switch (size) {
4010 case 0:
4011 gen_st8(tmp, addr, IS_USER(s));
4012 break;
4013 case 1:
4014 gen_st16(tmp, addr, IS_USER(s));
4015 break;
4016 case 2:
4017 gen_st32(tmp, addr, IS_USER(s));
4018 break;
4021 rd += stride;
4022 tcg_gen_addi_i32(addr, addr, 1 << size);
4024 tcg_temp_free_i32(addr);
4025 stride = nregs * (1 << size);
4028 if (rm != 15) {
4029 TCGv base;
4031 base = load_reg(s, rn);
4032 if (rm == 13) {
4033 tcg_gen_addi_i32(base, base, stride);
4034 } else {
4035 TCGv index;
4036 index = load_reg(s, rm);
4037 tcg_gen_add_i32(base, base, index);
4038 tcg_temp_free_i32(index);
4040 store_reg(s, rn, base);
4042 return 0;
4045 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4046 static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
4048 tcg_gen_and_i32(t, t, c);
4049 tcg_gen_andc_i32(f, f, c);
4050 tcg_gen_or_i32(dest, t, f);
4053 static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
4055 switch (size) {
4056 case 0: gen_helper_neon_narrow_u8(dest, src); break;
4057 case 1: gen_helper_neon_narrow_u16(dest, src); break;
4058 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
4059 default: abort();
4063 static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
4065 switch (size) {
4066 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
4067 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
4068 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
4069 default: abort();
4073 static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
4075 switch (size) {
4076 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
4077 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
4078 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
4079 default: abort();
4083 static inline void gen_neon_unarrow_sats(int size, TCGv dest, TCGv_i64 src)
4085 switch (size) {
4086 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
4087 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
4088 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
4089 default: abort();
4093 static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
4094 int q, int u)
4096 if (q) {
4097 if (u) {
4098 switch (size) {
4099 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4100 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4101 default: abort();
4103 } else {
4104 switch (size) {
4105 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
4106 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
4107 default: abort();
4110 } else {
4111 if (u) {
4112 switch (size) {
4113 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
4114 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
4115 default: abort();
4117 } else {
4118 switch (size) {
4119 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
4120 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
4121 default: abort();
4127 static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
4129 if (u) {
4130 switch (size) {
4131 case 0: gen_helper_neon_widen_u8(dest, src); break;
4132 case 1: gen_helper_neon_widen_u16(dest, src); break;
4133 case 2: tcg_gen_extu_i32_i64(dest, src); break;
4134 default: abort();
4136 } else {
4137 switch (size) {
4138 case 0: gen_helper_neon_widen_s8(dest, src); break;
4139 case 1: gen_helper_neon_widen_s16(dest, src); break;
4140 case 2: tcg_gen_ext_i32_i64(dest, src); break;
4141 default: abort();
4144 tcg_temp_free_i32(src);
4147 static inline void gen_neon_addl(int size)
4149 switch (size) {
4150 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4151 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4152 case 2: tcg_gen_add_i64(CPU_V001); break;
4153 default: abort();
4157 static inline void gen_neon_subl(int size)
4159 switch (size) {
4160 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4161 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4162 case 2: tcg_gen_sub_i64(CPU_V001); break;
4163 default: abort();
4167 static inline void gen_neon_negl(TCGv_i64 var, int size)
4169 switch (size) {
4170 case 0: gen_helper_neon_negl_u16(var, var); break;
4171 case 1: gen_helper_neon_negl_u32(var, var); break;
4172 case 2: gen_helper_neon_negl_u64(var, var); break;
4173 default: abort();
4177 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4179 switch (size) {
4180 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4181 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4182 default: abort();
4186 static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
4188 TCGv_i64 tmp;
4190 switch ((size << 1) | u) {
4191 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4192 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4193 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4194 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4195 case 4:
4196 tmp = gen_muls_i64_i32(a, b);
4197 tcg_gen_mov_i64(dest, tmp);
4198 tcg_temp_free_i64(tmp);
4199 break;
4200 case 5:
4201 tmp = gen_mulu_i64_i32(a, b);
4202 tcg_gen_mov_i64(dest, tmp);
4203 tcg_temp_free_i64(tmp);
4204 break;
4205 default: abort();
4208 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
4209 Don't forget to clean them now. */
4210 if (size < 2) {
4211 tcg_temp_free_i32(a);
4212 tcg_temp_free_i32(b);
4216 static void gen_neon_narrow_op(int op, int u, int size, TCGv dest, TCGv_i64 src)
4218 if (op) {
4219 if (u) {
4220 gen_neon_unarrow_sats(size, dest, src);
4221 } else {
4222 gen_neon_narrow(size, dest, src);
4224 } else {
4225 if (u) {
4226 gen_neon_narrow_satu(size, dest, src);
4227 } else {
4228 gen_neon_narrow_sats(size, dest, src);
4233 /* Translate a NEON data processing instruction. Return nonzero if the
4234 instruction is invalid.
4235 We process data in a mixture of 32-bit and 64-bit chunks.
4236 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4238 static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4240 int op;
4241 int q;
4242 int rd, rn, rm;
4243 int size;
4244 int shift;
4245 int pass;
4246 int count;
4247 int pairwise;
4248 int u;
4249 int n;
4250 uint32_t imm, mask;
4251 TCGv tmp, tmp2, tmp3, tmp4, tmp5;
4252 TCGv_i64 tmp64;
4254 if (!s->vfp_enabled)
4255 return 1;
4256 q = (insn & (1 << 6)) != 0;
4257 u = (insn >> 24) & 1;
4258 VFP_DREG_D(rd, insn);
4259 VFP_DREG_N(rn, insn);
4260 VFP_DREG_M(rm, insn);
4261 size = (insn >> 20) & 3;
4262 if ((insn & (1 << 23)) == 0) {
4263 /* Three register same length. */
4264 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4265 if (size == 3 && (op == 1 || op == 5 || op == 8 || op == 9
4266 || op == 10 || op == 11 || op == 16)) {
4267 /* 64-bit element instructions. */
4268 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4269 neon_load_reg64(cpu_V0, rn + pass);
4270 neon_load_reg64(cpu_V1, rm + pass);
4271 switch (op) {
4272 case 1: /* VQADD */
4273 if (u) {
4274 gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
4275 cpu_V0, cpu_V1);
4276 } else {
4277 gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
4278 cpu_V0, cpu_V1);
4280 break;
4281 case 5: /* VQSUB */
4282 if (u) {
4283 gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
4284 cpu_V0, cpu_V1);
4285 } else {
4286 gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
4287 cpu_V0, cpu_V1);
4289 break;
4290 case 8: /* VSHL */
4291 if (u) {
4292 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4293 } else {
4294 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4296 break;
4297 case 9: /* VQSHL */
4298 if (u) {
4299 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4300 cpu_V1, cpu_V0);
4301 } else {
4302 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
4303 cpu_V1, cpu_V0);
4305 break;
4306 case 10: /* VRSHL */
4307 if (u) {
4308 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4309 } else {
4310 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4312 break;
4313 case 11: /* VQRSHL */
4314 if (u) {
4315 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4316 cpu_V1, cpu_V0);
4317 } else {
4318 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4319 cpu_V1, cpu_V0);
4321 break;
4322 case 16:
4323 if (u) {
4324 tcg_gen_sub_i64(CPU_V001);
4325 } else {
4326 tcg_gen_add_i64(CPU_V001);
4328 break;
4329 default:
4330 abort();
4332 neon_store_reg64(cpu_V0, rd + pass);
4334 return 0;
4336 switch (op) {
4337 case 8: /* VSHL */
4338 case 9: /* VQSHL */
4339 case 10: /* VRSHL */
4340 case 11: /* VQRSHL */
4342 int rtmp;
4343 /* Shift instruction operands are reversed. */
4344 rtmp = rn;
4345 rn = rm;
4346 rm = rtmp;
4347 pairwise = 0;
4349 break;
4350 case 20: /* VPMAX */
4351 case 21: /* VPMIN */
4352 case 23: /* VPADD */
4353 pairwise = 1;
4354 break;
4355 case 26: /* VPADD (float) */
4356 pairwise = (u && size < 2);
4357 break;
4358 case 30: /* VPMIN/VPMAX (float) */
4359 pairwise = u;
4360 break;
4361 default:
4362 pairwise = 0;
4363 break;
4366 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4368 if (pairwise) {
4369 /* Pairwise. */
4370 if (q)
4371 n = (pass & 1) * 2;
4372 else
4373 n = 0;
4374 if (pass < q + 1) {
4375 tmp = neon_load_reg(rn, n);
4376 tmp2 = neon_load_reg(rn, n + 1);
4377 } else {
4378 tmp = neon_load_reg(rm, n);
4379 tmp2 = neon_load_reg(rm, n + 1);
4381 } else {
4382 /* Elementwise. */
4383 tmp = neon_load_reg(rn, pass);
4384 tmp2 = neon_load_reg(rm, pass);
4386 switch (op) {
4387 case 0: /* VHADD */
4388 GEN_NEON_INTEGER_OP(hadd);
4389 break;
4390 case 1: /* VQADD */
4391 GEN_NEON_INTEGER_OP_ENV(qadd);
4392 break;
4393 case 2: /* VRHADD */
4394 GEN_NEON_INTEGER_OP(rhadd);
4395 break;
4396 case 3: /* Logic ops. */
4397 switch ((u << 2) | size) {
4398 case 0: /* VAND */
4399 tcg_gen_and_i32(tmp, tmp, tmp2);
4400 break;
4401 case 1: /* BIC */
4402 tcg_gen_andc_i32(tmp, tmp, tmp2);
4403 break;
4404 case 2: /* VORR */
4405 tcg_gen_or_i32(tmp, tmp, tmp2);
4406 break;
4407 case 3: /* VORN */
4408 tcg_gen_orc_i32(tmp, tmp, tmp2);
4409 break;
4410 case 4: /* VEOR */
4411 tcg_gen_xor_i32(tmp, tmp, tmp2);
4412 break;
4413 case 5: /* VBSL */
4414 tmp3 = neon_load_reg(rd, pass);
4415 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
4416 tcg_temp_free_i32(tmp3);
4417 break;
4418 case 6: /* VBIT */
4419 tmp3 = neon_load_reg(rd, pass);
4420 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
4421 tcg_temp_free_i32(tmp3);
4422 break;
4423 case 7: /* VBIF */
4424 tmp3 = neon_load_reg(rd, pass);
4425 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
4426 tcg_temp_free_i32(tmp3);
4427 break;
4429 break;
4430 case 4: /* VHSUB */
4431 GEN_NEON_INTEGER_OP(hsub);
4432 break;
4433 case 5: /* VQSUB */
4434 GEN_NEON_INTEGER_OP_ENV(qsub);
4435 break;
4436 case 6: /* VCGT */
4437 GEN_NEON_INTEGER_OP(cgt);
4438 break;
4439 case 7: /* VCGE */
4440 GEN_NEON_INTEGER_OP(cge);
4441 break;
4442 case 8: /* VSHL */
4443 GEN_NEON_INTEGER_OP(shl);
4444 break;
4445 case 9: /* VQSHL */
4446 GEN_NEON_INTEGER_OP_ENV(qshl);
4447 break;
4448 case 10: /* VRSHL */
4449 GEN_NEON_INTEGER_OP(rshl);
4450 break;
4451 case 11: /* VQRSHL */
4452 GEN_NEON_INTEGER_OP_ENV(qrshl);
4453 break;
4454 case 12: /* VMAX */
4455 GEN_NEON_INTEGER_OP(max);
4456 break;
4457 case 13: /* VMIN */
4458 GEN_NEON_INTEGER_OP(min);
4459 break;
4460 case 14: /* VABD */
4461 GEN_NEON_INTEGER_OP(abd);
4462 break;
4463 case 15: /* VABA */
4464 GEN_NEON_INTEGER_OP(abd);
4465 tcg_temp_free_i32(tmp2);
4466 tmp2 = neon_load_reg(rd, pass);
4467 gen_neon_add(size, tmp, tmp2);
4468 break;
4469 case 16:
4470 if (!u) { /* VADD */
4471 if (gen_neon_add(size, tmp, tmp2))
4472 return 1;
4473 } else { /* VSUB */
4474 switch (size) {
4475 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
4476 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
4477 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
4478 default: return 1;
4481 break;
4482 case 17:
4483 if (!u) { /* VTST */
4484 switch (size) {
4485 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
4486 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
4487 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
4488 default: return 1;
4490 } else { /* VCEQ */
4491 switch (size) {
4492 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
4493 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
4494 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
4495 default: return 1;
4498 break;
4499 case 18: /* Multiply. */
4500 switch (size) {
4501 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4502 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4503 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4504 default: return 1;
4506 tcg_temp_free_i32(tmp2);
4507 tmp2 = neon_load_reg(rd, pass);
4508 if (u) { /* VMLS */
4509 gen_neon_rsb(size, tmp, tmp2);
4510 } else { /* VMLA */
4511 gen_neon_add(size, tmp, tmp2);
4513 break;
4514 case 19: /* VMUL */
4515 if (u) { /* polynomial */
4516 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
4517 } else { /* Integer */
4518 switch (size) {
4519 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4520 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4521 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4522 default: return 1;
4525 break;
4526 case 20: /* VPMAX */
4527 GEN_NEON_INTEGER_OP(pmax);
4528 break;
4529 case 21: /* VPMIN */
4530 GEN_NEON_INTEGER_OP(pmin);
4531 break;
4532 case 22: /* Hultiply high. */
4533 if (!u) { /* VQDMULH */
4534 switch (size) {
4535 case 1: gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4536 case 2: gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4537 default: return 1;
4539 } else { /* VQRDHMUL */
4540 switch (size) {
4541 case 1: gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4542 case 2: gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4543 default: return 1;
4546 break;
4547 case 23: /* VPADD */
4548 if (u)
4549 return 1;
4550 switch (size) {
4551 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
4552 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
4553 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
4554 default: return 1;
4556 break;
4557 case 26: /* Floating point arithnetic. */
4558 switch ((u << 2) | size) {
4559 case 0: /* VADD */
4560 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4561 break;
4562 case 2: /* VSUB */
4563 gen_helper_neon_sub_f32(tmp, tmp, tmp2);
4564 break;
4565 case 4: /* VPADD */
4566 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4567 break;
4568 case 6: /* VABD */
4569 gen_helper_neon_abd_f32(tmp, tmp, tmp2);
4570 break;
4571 default:
4572 return 1;
4574 break;
4575 case 27: /* Float multiply. */
4576 gen_helper_neon_mul_f32(tmp, tmp, tmp2);
4577 if (!u) {
4578 tcg_temp_free_i32(tmp2);
4579 tmp2 = neon_load_reg(rd, pass);
4580 if (size == 0) {
4581 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4582 } else {
4583 gen_helper_neon_sub_f32(tmp, tmp2, tmp);
4586 break;
4587 case 28: /* Float compare. */
4588 if (!u) {
4589 gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
4590 } else {
4591 if (size == 0)
4592 gen_helper_neon_cge_f32(tmp, tmp, tmp2);
4593 else
4594 gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
4596 break;
4597 case 29: /* Float compare absolute. */
4598 if (!u)
4599 return 1;
4600 if (size == 0)
4601 gen_helper_neon_acge_f32(tmp, tmp, tmp2);
4602 else
4603 gen_helper_neon_acgt_f32(tmp, tmp, tmp2);
4604 break;
4605 case 30: /* Float min/max. */
4606 if (size == 0)
4607 gen_helper_neon_max_f32(tmp, tmp, tmp2);
4608 else
4609 gen_helper_neon_min_f32(tmp, tmp, tmp2);
4610 break;
4611 case 31:
4612 if (size == 0)
4613 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
4614 else
4615 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
4616 break;
4617 default:
4618 abort();
4620 tcg_temp_free_i32(tmp2);
4622 /* Save the result. For elementwise operations we can put it
4623 straight into the destination register. For pairwise operations
4624 we have to be careful to avoid clobbering the source operands. */
4625 if (pairwise && rd == rm) {
4626 neon_store_scratch(pass, tmp);
4627 } else {
4628 neon_store_reg(rd, pass, tmp);
4631 } /* for pass */
4632 if (pairwise && rd == rm) {
4633 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4634 tmp = neon_load_scratch(pass);
4635 neon_store_reg(rd, pass, tmp);
4638 /* End of 3 register same size operations. */
4639 } else if (insn & (1 << 4)) {
4640 if ((insn & 0x00380080) != 0) {
4641 /* Two registers and shift. */
4642 op = (insn >> 8) & 0xf;
4643 if (insn & (1 << 7)) {
4644 /* 64-bit shift. */
4645 size = 3;
4646 } else {
4647 size = 2;
4648 while ((insn & (1 << (size + 19))) == 0)
4649 size--;
4651 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4652 /* To avoid excessive dumplication of ops we implement shift
4653 by immediate using the variable shift operations. */
4654 if (op < 8) {
4655 /* Shift by immediate:
4656 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4657 /* Right shifts are encoded as N - shift, where N is the
4658 element size in bits. */
4659 if (op <= 4)
4660 shift = shift - (1 << (size + 3));
4661 if (size == 3) {
4662 count = q + 1;
4663 } else {
4664 count = q ? 4: 2;
4666 switch (size) {
4667 case 0:
4668 imm = (uint8_t) shift;
4669 imm |= imm << 8;
4670 imm |= imm << 16;
4671 break;
4672 case 1:
4673 imm = (uint16_t) shift;
4674 imm |= imm << 16;
4675 break;
4676 case 2:
4677 case 3:
4678 imm = shift;
4679 break;
4680 default:
4681 abort();
4684 for (pass = 0; pass < count; pass++) {
4685 if (size == 3) {
4686 neon_load_reg64(cpu_V0, rm + pass);
4687 tcg_gen_movi_i64(cpu_V1, imm);
4688 switch (op) {
4689 case 0: /* VSHR */
4690 case 1: /* VSRA */
4691 if (u)
4692 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4693 else
4694 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
4695 break;
4696 case 2: /* VRSHR */
4697 case 3: /* VRSRA */
4698 if (u)
4699 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
4700 else
4701 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
4702 break;
4703 case 4: /* VSRI */
4704 if (!u)
4705 return 1;
4706 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4707 break;
4708 case 5: /* VSHL, VSLI */
4709 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4710 break;
4711 case 6: /* VQSHLU */
4712 if (u) {
4713 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
4714 cpu_V0, cpu_V1);
4715 } else {
4716 return 1;
4718 break;
4719 case 7: /* VQSHL */
4720 if (u) {
4721 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4722 cpu_V0, cpu_V1);
4723 } else {
4724 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
4725 cpu_V0, cpu_V1);
4727 break;
4729 if (op == 1 || op == 3) {
4730 /* Accumulate. */
4731 neon_load_reg64(cpu_V1, rd + pass);
4732 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
4733 } else if (op == 4 || (op == 5 && u)) {
4734 /* Insert */
4735 neon_load_reg64(cpu_V1, rd + pass);
4736 uint64_t mask;
4737 if (shift < -63 || shift > 63) {
4738 mask = 0;
4739 } else {
4740 if (op == 4) {
4741 mask = 0xffffffffffffffffull >> -shift;
4742 } else {
4743 mask = 0xffffffffffffffffull << shift;
4746 tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask);
4747 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
4749 neon_store_reg64(cpu_V0, rd + pass);
4750 } else { /* size < 3 */
4751 /* Operands in T0 and T1. */
4752 tmp = neon_load_reg(rm, pass);
4753 tmp2 = tcg_temp_new_i32();
4754 tcg_gen_movi_i32(tmp2, imm);
4755 switch (op) {
4756 case 0: /* VSHR */
4757 case 1: /* VSRA */
4758 GEN_NEON_INTEGER_OP(shl);
4759 break;
4760 case 2: /* VRSHR */
4761 case 3: /* VRSRA */
4762 GEN_NEON_INTEGER_OP(rshl);
4763 break;
4764 case 4: /* VSRI */
4765 if (!u)
4766 return 1;
4767 GEN_NEON_INTEGER_OP(shl);
4768 break;
4769 case 5: /* VSHL, VSLI */
4770 switch (size) {
4771 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
4772 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
4773 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
4774 default: return 1;
4776 break;
4777 case 6: /* VQSHLU */
4778 if (!u) {
4779 return 1;
4781 switch (size) {
4782 case 0:
4783 gen_helper_neon_qshlu_s8(tmp, cpu_env,
4784 tmp, tmp2);
4785 break;
4786 case 1:
4787 gen_helper_neon_qshlu_s16(tmp, cpu_env,
4788 tmp, tmp2);
4789 break;
4790 case 2:
4791 gen_helper_neon_qshlu_s32(tmp, cpu_env,
4792 tmp, tmp2);
4793 break;
4794 default:
4795 return 1;
4797 break;
4798 case 7: /* VQSHL */
4799 GEN_NEON_INTEGER_OP_ENV(qshl);
4800 break;
4802 tcg_temp_free_i32(tmp2);
4804 if (op == 1 || op == 3) {
4805 /* Accumulate. */
4806 tmp2 = neon_load_reg(rd, pass);
4807 gen_neon_add(size, tmp, tmp2);
4808 tcg_temp_free_i32(tmp2);
4809 } else if (op == 4 || (op == 5 && u)) {
4810 /* Insert */
4811 switch (size) {
4812 case 0:
4813 if (op == 4)
4814 mask = 0xff >> -shift;
4815 else
4816 mask = (uint8_t)(0xff << shift);
4817 mask |= mask << 8;
4818 mask |= mask << 16;
4819 break;
4820 case 1:
4821 if (op == 4)
4822 mask = 0xffff >> -shift;
4823 else
4824 mask = (uint16_t)(0xffff << shift);
4825 mask |= mask << 16;
4826 break;
4827 case 2:
4828 if (shift < -31 || shift > 31) {
4829 mask = 0;
4830 } else {
4831 if (op == 4)
4832 mask = 0xffffffffu >> -shift;
4833 else
4834 mask = 0xffffffffu << shift;
4836 break;
4837 default:
4838 abort();
4840 tmp2 = neon_load_reg(rd, pass);
4841 tcg_gen_andi_i32(tmp, tmp, mask);
4842 tcg_gen_andi_i32(tmp2, tmp2, ~mask);
4843 tcg_gen_or_i32(tmp, tmp, tmp2);
4844 tcg_temp_free_i32(tmp2);
4846 neon_store_reg(rd, pass, tmp);
4848 } /* for pass */
4849 } else if (op < 10) {
4850 /* Shift by immediate and narrow:
4851 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4852 int input_unsigned = (op == 8) ? !u : u;
4854 shift = shift - (1 << (size + 3));
4855 size++;
4856 if (size == 3) {
4857 tmp64 = tcg_const_i64(shift);
4858 neon_load_reg64(cpu_V0, rm);
4859 neon_load_reg64(cpu_V1, rm + 1);
4860 for (pass = 0; pass < 2; pass++) {
4861 TCGv_i64 in;
4862 if (pass == 0) {
4863 in = cpu_V0;
4864 } else {
4865 in = cpu_V1;
4867 if (q) {
4868 if (input_unsigned) {
4869 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
4870 } else {
4871 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
4873 } else {
4874 if (input_unsigned) {
4875 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
4876 } else {
4877 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
4880 tmp = tcg_temp_new_i32();
4881 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
4882 neon_store_reg(rd, pass, tmp);
4883 } /* for pass */
4884 tcg_temp_free_i64(tmp64);
4885 } else {
4886 if (size == 1) {
4887 imm = (uint16_t)shift;
4888 imm |= imm << 16;
4889 } else {
4890 /* size == 2 */
4891 imm = (uint32_t)shift;
4893 tmp2 = tcg_const_i32(imm);
4894 tmp4 = neon_load_reg(rm + 1, 0);
4895 tmp5 = neon_load_reg(rm + 1, 1);
4896 for (pass = 0; pass < 2; pass++) {
4897 if (pass == 0) {
4898 tmp = neon_load_reg(rm, 0);
4899 } else {
4900 tmp = tmp4;
4902 gen_neon_shift_narrow(size, tmp, tmp2, q,
4903 input_unsigned);
4904 if (pass == 0) {
4905 tmp3 = neon_load_reg(rm, 1);
4906 } else {
4907 tmp3 = tmp5;
4909 gen_neon_shift_narrow(size, tmp3, tmp2, q,
4910 input_unsigned);
4911 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
4912 tcg_temp_free_i32(tmp);
4913 tcg_temp_free_i32(tmp3);
4914 tmp = tcg_temp_new_i32();
4915 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
4916 neon_store_reg(rd, pass, tmp);
4917 } /* for pass */
4918 tcg_temp_free_i32(tmp2);
4920 } else if (op == 10) {
4921 /* VSHLL */
4922 if (q || size == 3)
4923 return 1;
4924 tmp = neon_load_reg(rm, 0);
4925 tmp2 = neon_load_reg(rm, 1);
4926 for (pass = 0; pass < 2; pass++) {
4927 if (pass == 1)
4928 tmp = tmp2;
4930 gen_neon_widen(cpu_V0, tmp, size, u);
4932 if (shift != 0) {
4933 /* The shift is less than the width of the source
4934 type, so we can just shift the whole register. */
4935 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
4936 /* Widen the result of shift: we need to clear
4937 * the potential overflow bits resulting from
4938 * left bits of the narrow input appearing as
4939 * right bits of left the neighbour narrow
4940 * input. */
4941 if (size < 2 || !u) {
4942 uint64_t imm64;
4943 if (size == 0) {
4944 imm = (0xffu >> (8 - shift));
4945 imm |= imm << 16;
4946 } else if (size == 1) {
4947 imm = 0xffff >> (16 - shift);
4948 } else {
4949 /* size == 2 */
4950 imm = 0xffffffff >> (32 - shift);
4952 if (size < 2) {
4953 imm64 = imm | (((uint64_t)imm) << 32);
4954 } else {
4955 imm64 = imm;
4957 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
4960 neon_store_reg64(cpu_V0, rd + pass);
4962 } else if (op >= 14) {
4963 /* VCVT fixed-point. */
4964 /* We have already masked out the must-be-1 top bit of imm6,
4965 * hence this 32-shift where the ARM ARM has 64-imm6.
4967 shift = 32 - shift;
4968 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4969 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
4970 if (!(op & 1)) {
4971 if (u)
4972 gen_vfp_ulto(0, shift);
4973 else
4974 gen_vfp_slto(0, shift);
4975 } else {
4976 if (u)
4977 gen_vfp_toul(0, shift);
4978 else
4979 gen_vfp_tosl(0, shift);
4981 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
4983 } else {
4984 return 1;
4986 } else { /* (insn & 0x00380080) == 0 */
4987 int invert;
4989 op = (insn >> 8) & 0xf;
4990 /* One register and immediate. */
4991 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4992 invert = (insn & (1 << 5)) != 0;
4993 switch (op) {
4994 case 0: case 1:
4995 /* no-op */
4996 break;
4997 case 2: case 3:
4998 imm <<= 8;
4999 break;
5000 case 4: case 5:
5001 imm <<= 16;
5002 break;
5003 case 6: case 7:
5004 imm <<= 24;
5005 break;
5006 case 8: case 9:
5007 imm |= imm << 16;
5008 break;
5009 case 10: case 11:
5010 imm = (imm << 8) | (imm << 24);
5011 break;
5012 case 12:
5013 imm = (imm << 8) | 0xff;
5014 break;
5015 case 13:
5016 imm = (imm << 16) | 0xffff;
5017 break;
5018 case 14:
5019 imm |= (imm << 8) | (imm << 16) | (imm << 24);
5020 if (invert)
5021 imm = ~imm;
5022 break;
5023 case 15:
5024 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
5025 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
5026 break;
5028 if (invert)
5029 imm = ~imm;
5031 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5032 if (op & 1 && op < 12) {
5033 tmp = neon_load_reg(rd, pass);
5034 if (invert) {
5035 /* The immediate value has already been inverted, so
5036 BIC becomes AND. */
5037 tcg_gen_andi_i32(tmp, tmp, imm);
5038 } else {
5039 tcg_gen_ori_i32(tmp, tmp, imm);
5041 } else {
5042 /* VMOV, VMVN. */
5043 tmp = tcg_temp_new_i32();
5044 if (op == 14 && invert) {
5045 uint32_t val;
5046 val = 0;
5047 for (n = 0; n < 4; n++) {
5048 if (imm & (1 << (n + (pass & 1) * 4)))
5049 val |= 0xff << (n * 8);
5051 tcg_gen_movi_i32(tmp, val);
5052 } else {
5053 tcg_gen_movi_i32(tmp, imm);
5056 neon_store_reg(rd, pass, tmp);
5059 } else { /* (insn & 0x00800010 == 0x00800000) */
5060 if (size != 3) {
5061 op = (insn >> 8) & 0xf;
5062 if ((insn & (1 << 6)) == 0) {
5063 /* Three registers of different lengths. */
5064 int src1_wide;
5065 int src2_wide;
5066 int prewiden;
5067 /* prewiden, src1_wide, src2_wide */
5068 static const int neon_3reg_wide[16][3] = {
5069 {1, 0, 0}, /* VADDL */
5070 {1, 1, 0}, /* VADDW */
5071 {1, 0, 0}, /* VSUBL */
5072 {1, 1, 0}, /* VSUBW */
5073 {0, 1, 1}, /* VADDHN */
5074 {0, 0, 0}, /* VABAL */
5075 {0, 1, 1}, /* VSUBHN */
5076 {0, 0, 0}, /* VABDL */
5077 {0, 0, 0}, /* VMLAL */
5078 {0, 0, 0}, /* VQDMLAL */
5079 {0, 0, 0}, /* VMLSL */
5080 {0, 0, 0}, /* VQDMLSL */
5081 {0, 0, 0}, /* Integer VMULL */
5082 {0, 0, 0}, /* VQDMULL */
5083 {0, 0, 0} /* Polynomial VMULL */
5086 prewiden = neon_3reg_wide[op][0];
5087 src1_wide = neon_3reg_wide[op][1];
5088 src2_wide = neon_3reg_wide[op][2];
5090 if (size == 0 && (op == 9 || op == 11 || op == 13))
5091 return 1;
5093 /* Avoid overlapping operands. Wide source operands are
5094 always aligned so will never overlap with wide
5095 destinations in problematic ways. */
5096 if (rd == rm && !src2_wide) {
5097 tmp = neon_load_reg(rm, 1);
5098 neon_store_scratch(2, tmp);
5099 } else if (rd == rn && !src1_wide) {
5100 tmp = neon_load_reg(rn, 1);
5101 neon_store_scratch(2, tmp);
5103 TCGV_UNUSED(tmp3);
5104 for (pass = 0; pass < 2; pass++) {
5105 if (src1_wide) {
5106 neon_load_reg64(cpu_V0, rn + pass);
5107 TCGV_UNUSED(tmp);
5108 } else {
5109 if (pass == 1 && rd == rn) {
5110 tmp = neon_load_scratch(2);
5111 } else {
5112 tmp = neon_load_reg(rn, pass);
5114 if (prewiden) {
5115 gen_neon_widen(cpu_V0, tmp, size, u);
5118 if (src2_wide) {
5119 neon_load_reg64(cpu_V1, rm + pass);
5120 TCGV_UNUSED(tmp2);
5121 } else {
5122 if (pass == 1 && rd == rm) {
5123 tmp2 = neon_load_scratch(2);
5124 } else {
5125 tmp2 = neon_load_reg(rm, pass);
5127 if (prewiden) {
5128 gen_neon_widen(cpu_V1, tmp2, size, u);
5131 switch (op) {
5132 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5133 gen_neon_addl(size);
5134 break;
5135 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
5136 gen_neon_subl(size);
5137 break;
5138 case 5: case 7: /* VABAL, VABDL */
5139 switch ((size << 1) | u) {
5140 case 0:
5141 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
5142 break;
5143 case 1:
5144 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
5145 break;
5146 case 2:
5147 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
5148 break;
5149 case 3:
5150 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
5151 break;
5152 case 4:
5153 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
5154 break;
5155 case 5:
5156 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
5157 break;
5158 default: abort();
5160 tcg_temp_free_i32(tmp2);
5161 tcg_temp_free_i32(tmp);
5162 break;
5163 case 8: case 9: case 10: case 11: case 12: case 13:
5164 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5165 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5166 break;
5167 case 14: /* Polynomial VMULL */
5168 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
5169 tcg_temp_free_i32(tmp2);
5170 tcg_temp_free_i32(tmp);
5171 break;
5172 default: /* 15 is RESERVED. */
5173 return 1;
5175 if (op == 13) {
5176 /* VQDMULL */
5177 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5178 neon_store_reg64(cpu_V0, rd + pass);
5179 } else if (op == 5 || (op >= 8 && op <= 11)) {
5180 /* Accumulate. */
5181 neon_load_reg64(cpu_V1, rd + pass);
5182 switch (op) {
5183 case 10: /* VMLSL */
5184 gen_neon_negl(cpu_V0, size);
5185 /* Fall through */
5186 case 5: case 8: /* VABAL, VMLAL */
5187 gen_neon_addl(size);
5188 break;
5189 case 9: case 11: /* VQDMLAL, VQDMLSL */
5190 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5191 if (op == 11) {
5192 gen_neon_negl(cpu_V0, size);
5194 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5195 break;
5196 default:
5197 abort();
5199 neon_store_reg64(cpu_V0, rd + pass);
5200 } else if (op == 4 || op == 6) {
5201 /* Narrowing operation. */
5202 tmp = tcg_temp_new_i32();
5203 if (!u) {
5204 switch (size) {
5205 case 0:
5206 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
5207 break;
5208 case 1:
5209 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
5210 break;
5211 case 2:
5212 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5213 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5214 break;
5215 default: abort();
5217 } else {
5218 switch (size) {
5219 case 0:
5220 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
5221 break;
5222 case 1:
5223 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
5224 break;
5225 case 2:
5226 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
5227 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5228 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5229 break;
5230 default: abort();
5233 if (pass == 0) {
5234 tmp3 = tmp;
5235 } else {
5236 neon_store_reg(rd, 0, tmp3);
5237 neon_store_reg(rd, 1, tmp);
5239 } else {
5240 /* Write back the result. */
5241 neon_store_reg64(cpu_V0, rd + pass);
5244 } else {
5245 /* Two registers and a scalar. */
5246 switch (op) {
5247 case 0: /* Integer VMLA scalar */
5248 case 1: /* Float VMLA scalar */
5249 case 4: /* Integer VMLS scalar */
5250 case 5: /* Floating point VMLS scalar */
5251 case 8: /* Integer VMUL scalar */
5252 case 9: /* Floating point VMUL scalar */
5253 case 12: /* VQDMULH scalar */
5254 case 13: /* VQRDMULH scalar */
5255 tmp = neon_get_scalar(size, rm);
5256 neon_store_scratch(0, tmp);
5257 for (pass = 0; pass < (u ? 4 : 2); pass++) {
5258 tmp = neon_load_scratch(0);
5259 tmp2 = neon_load_reg(rn, pass);
5260 if (op == 12) {
5261 if (size == 1) {
5262 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5263 } else {
5264 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5266 } else if (op == 13) {
5267 if (size == 1) {
5268 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5269 } else {
5270 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5272 } else if (op & 1) {
5273 gen_helper_neon_mul_f32(tmp, tmp, tmp2);
5274 } else {
5275 switch (size) {
5276 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5277 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5278 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5279 default: return 1;
5282 tcg_temp_free_i32(tmp2);
5283 if (op < 8) {
5284 /* Accumulate. */
5285 tmp2 = neon_load_reg(rd, pass);
5286 switch (op) {
5287 case 0:
5288 gen_neon_add(size, tmp, tmp2);
5289 break;
5290 case 1:
5291 gen_helper_neon_add_f32(tmp, tmp, tmp2);
5292 break;
5293 case 4:
5294 gen_neon_rsb(size, tmp, tmp2);
5295 break;
5296 case 5:
5297 gen_helper_neon_sub_f32(tmp, tmp2, tmp);
5298 break;
5299 default:
5300 abort();
5302 tcg_temp_free_i32(tmp2);
5304 neon_store_reg(rd, pass, tmp);
5306 break;
5307 case 2: /* VMLAL sclar */
5308 case 3: /* VQDMLAL scalar */
5309 case 6: /* VMLSL scalar */
5310 case 7: /* VQDMLSL scalar */
5311 case 10: /* VMULL scalar */
5312 case 11: /* VQDMULL scalar */
5313 if (size == 0 && (op == 3 || op == 7 || op == 11))
5314 return 1;
5316 tmp2 = neon_get_scalar(size, rm);
5317 /* We need a copy of tmp2 because gen_neon_mull
5318 * deletes it during pass 0. */
5319 tmp4 = tcg_temp_new_i32();
5320 tcg_gen_mov_i32(tmp4, tmp2);
5321 tmp3 = neon_load_reg(rn, 1);
5323 for (pass = 0; pass < 2; pass++) {
5324 if (pass == 0) {
5325 tmp = neon_load_reg(rn, 0);
5326 } else {
5327 tmp = tmp3;
5328 tmp2 = tmp4;
5330 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5331 if (op != 11) {
5332 neon_load_reg64(cpu_V1, rd + pass);
5334 switch (op) {
5335 case 6:
5336 gen_neon_negl(cpu_V0, size);
5337 /* Fall through */
5338 case 2:
5339 gen_neon_addl(size);
5340 break;
5341 case 3: case 7:
5342 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5343 if (op == 7) {
5344 gen_neon_negl(cpu_V0, size);
5346 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5347 break;
5348 case 10:
5349 /* no-op */
5350 break;
5351 case 11:
5352 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5353 break;
5354 default:
5355 abort();
5357 neon_store_reg64(cpu_V0, rd + pass);
5361 break;
5362 default: /* 14 and 15 are RESERVED */
5363 return 1;
5366 } else { /* size == 3 */
5367 if (!u) {
5368 /* Extract. */
5369 imm = (insn >> 8) & 0xf;
5371 if (imm > 7 && !q)
5372 return 1;
5374 if (imm == 0) {
5375 neon_load_reg64(cpu_V0, rn);
5376 if (q) {
5377 neon_load_reg64(cpu_V1, rn + 1);
5379 } else if (imm == 8) {
5380 neon_load_reg64(cpu_V0, rn + 1);
5381 if (q) {
5382 neon_load_reg64(cpu_V1, rm);
5384 } else if (q) {
5385 tmp64 = tcg_temp_new_i64();
5386 if (imm < 8) {
5387 neon_load_reg64(cpu_V0, rn);
5388 neon_load_reg64(tmp64, rn + 1);
5389 } else {
5390 neon_load_reg64(cpu_V0, rn + 1);
5391 neon_load_reg64(tmp64, rm);
5393 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5394 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
5395 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5396 if (imm < 8) {
5397 neon_load_reg64(cpu_V1, rm);
5398 } else {
5399 neon_load_reg64(cpu_V1, rm + 1);
5400 imm -= 8;
5402 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5403 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
5404 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
5405 tcg_temp_free_i64(tmp64);
5406 } else {
5407 /* BUGFIX */
5408 neon_load_reg64(cpu_V0, rn);
5409 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
5410 neon_load_reg64(cpu_V1, rm);
5411 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5412 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5414 neon_store_reg64(cpu_V0, rd);
5415 if (q) {
5416 neon_store_reg64(cpu_V1, rd + 1);
5418 } else if ((insn & (1 << 11)) == 0) {
5419 /* Two register misc. */
5420 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5421 size = (insn >> 18) & 3;
5422 switch (op) {
5423 case 0: /* VREV64 */
5424 if (size == 3)
5425 return 1;
5426 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5427 tmp = neon_load_reg(rm, pass * 2);
5428 tmp2 = neon_load_reg(rm, pass * 2 + 1);
5429 switch (size) {
5430 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5431 case 1: gen_swap_half(tmp); break;
5432 case 2: /* no-op */ break;
5433 default: abort();
5435 neon_store_reg(rd, pass * 2 + 1, tmp);
5436 if (size == 2) {
5437 neon_store_reg(rd, pass * 2, tmp2);
5438 } else {
5439 switch (size) {
5440 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
5441 case 1: gen_swap_half(tmp2); break;
5442 default: abort();
5444 neon_store_reg(rd, pass * 2, tmp2);
5447 break;
5448 case 4: case 5: /* VPADDL */
5449 case 12: case 13: /* VPADAL */
5450 if (size == 3)
5451 return 1;
5452 for (pass = 0; pass < q + 1; pass++) {
5453 tmp = neon_load_reg(rm, pass * 2);
5454 gen_neon_widen(cpu_V0, tmp, size, op & 1);
5455 tmp = neon_load_reg(rm, pass * 2 + 1);
5456 gen_neon_widen(cpu_V1, tmp, size, op & 1);
5457 switch (size) {
5458 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5459 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5460 case 2: tcg_gen_add_i64(CPU_V001); break;
5461 default: abort();
5463 if (op >= 12) {
5464 /* Accumulate. */
5465 neon_load_reg64(cpu_V1, rd + pass);
5466 gen_neon_addl(size);
5468 neon_store_reg64(cpu_V0, rd + pass);
5470 break;
5471 case 33: /* VTRN */
5472 if (size == 2) {
5473 for (n = 0; n < (q ? 4 : 2); n += 2) {
5474 tmp = neon_load_reg(rm, n);
5475 tmp2 = neon_load_reg(rd, n + 1);
5476 neon_store_reg(rm, n, tmp2);
5477 neon_store_reg(rd, n + 1, tmp);
5479 } else {
5480 goto elementwise;
5482 break;
5483 case 34: /* VUZP */
5484 if (gen_neon_unzip(rd, rm, size, q)) {
5485 return 1;
5487 break;
5488 case 35: /* VZIP */
5489 if (gen_neon_zip(rd, rm, size, q)) {
5490 return 1;
5492 break;
5493 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5494 if (size == 3)
5495 return 1;
5496 TCGV_UNUSED(tmp2);
5497 for (pass = 0; pass < 2; pass++) {
5498 neon_load_reg64(cpu_V0, rm + pass);
5499 tmp = tcg_temp_new_i32();
5500 gen_neon_narrow_op(op == 36, q, size, tmp, cpu_V0);
5501 if (pass == 0) {
5502 tmp2 = tmp;
5503 } else {
5504 neon_store_reg(rd, 0, tmp2);
5505 neon_store_reg(rd, 1, tmp);
5508 break;
5509 case 38: /* VSHLL */
5510 if (q || size == 3)
5511 return 1;
5512 tmp = neon_load_reg(rm, 0);
5513 tmp2 = neon_load_reg(rm, 1);
5514 for (pass = 0; pass < 2; pass++) {
5515 if (pass == 1)
5516 tmp = tmp2;
5517 gen_neon_widen(cpu_V0, tmp, size, 1);
5518 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
5519 neon_store_reg64(cpu_V0, rd + pass);
5521 break;
5522 case 44: /* VCVT.F16.F32 */
5523 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
5524 return 1;
5525 tmp = tcg_temp_new_i32();
5526 tmp2 = tcg_temp_new_i32();
5527 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
5528 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5529 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
5530 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
5531 tcg_gen_shli_i32(tmp2, tmp2, 16);
5532 tcg_gen_or_i32(tmp2, tmp2, tmp);
5533 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
5534 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5535 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
5536 neon_store_reg(rd, 0, tmp2);
5537 tmp2 = tcg_temp_new_i32();
5538 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
5539 tcg_gen_shli_i32(tmp2, tmp2, 16);
5540 tcg_gen_or_i32(tmp2, tmp2, tmp);
5541 neon_store_reg(rd, 1, tmp2);
5542 tcg_temp_free_i32(tmp);
5543 break;
5544 case 46: /* VCVT.F32.F16 */
5545 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
5546 return 1;
5547 tmp3 = tcg_temp_new_i32();
5548 tmp = neon_load_reg(rm, 0);
5549 tmp2 = neon_load_reg(rm, 1);
5550 tcg_gen_ext16u_i32(tmp3, tmp);
5551 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5552 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
5553 tcg_gen_shri_i32(tmp3, tmp, 16);
5554 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5555 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
5556 tcg_temp_free_i32(tmp);
5557 tcg_gen_ext16u_i32(tmp3, tmp2);
5558 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5559 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
5560 tcg_gen_shri_i32(tmp3, tmp2, 16);
5561 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5562 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
5563 tcg_temp_free_i32(tmp2);
5564 tcg_temp_free_i32(tmp3);
5565 break;
5566 default:
5567 elementwise:
5568 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5569 if (op == 30 || op == 31 || op >= 58) {
5570 tcg_gen_ld_f32(cpu_F0s, cpu_env,
5571 neon_reg_offset(rm, pass));
5572 TCGV_UNUSED(tmp);
5573 } else {
5574 tmp = neon_load_reg(rm, pass);
5576 switch (op) {
5577 case 1: /* VREV32 */
5578 switch (size) {
5579 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5580 case 1: gen_swap_half(tmp); break;
5581 default: return 1;
5583 break;
5584 case 2: /* VREV16 */
5585 if (size != 0)
5586 return 1;
5587 gen_rev16(tmp);
5588 break;
5589 case 8: /* CLS */
5590 switch (size) {
5591 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
5592 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
5593 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
5594 default: return 1;
5596 break;
5597 case 9: /* CLZ */
5598 switch (size) {
5599 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
5600 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
5601 case 2: gen_helper_clz(tmp, tmp); break;
5602 default: return 1;
5604 break;
5605 case 10: /* CNT */
5606 if (size != 0)
5607 return 1;
5608 gen_helper_neon_cnt_u8(tmp, tmp);
5609 break;
5610 case 11: /* VNOT */
5611 if (size != 0)
5612 return 1;
5613 tcg_gen_not_i32(tmp, tmp);
5614 break;
5615 case 14: /* VQABS */
5616 switch (size) {
5617 case 0: gen_helper_neon_qabs_s8(tmp, cpu_env, tmp); break;
5618 case 1: gen_helper_neon_qabs_s16(tmp, cpu_env, tmp); break;
5619 case 2: gen_helper_neon_qabs_s32(tmp, cpu_env, tmp); break;
5620 default: return 1;
5622 break;
5623 case 15: /* VQNEG */
5624 switch (size) {
5625 case 0: gen_helper_neon_qneg_s8(tmp, cpu_env, tmp); break;
5626 case 1: gen_helper_neon_qneg_s16(tmp, cpu_env, tmp); break;
5627 case 2: gen_helper_neon_qneg_s32(tmp, cpu_env, tmp); break;
5628 default: return 1;
5630 break;
5631 case 16: case 19: /* VCGT #0, VCLE #0 */
5632 tmp2 = tcg_const_i32(0);
5633 switch(size) {
5634 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
5635 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
5636 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
5637 default: return 1;
5639 tcg_temp_free(tmp2);
5640 if (op == 19)
5641 tcg_gen_not_i32(tmp, tmp);
5642 break;
5643 case 17: case 20: /* VCGE #0, VCLT #0 */
5644 tmp2 = tcg_const_i32(0);
5645 switch(size) {
5646 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
5647 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
5648 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
5649 default: return 1;
5651 tcg_temp_free(tmp2);
5652 if (op == 20)
5653 tcg_gen_not_i32(tmp, tmp);
5654 break;
5655 case 18: /* VCEQ #0 */
5656 tmp2 = tcg_const_i32(0);
5657 switch(size) {
5658 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
5659 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
5660 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
5661 default: return 1;
5663 tcg_temp_free(tmp2);
5664 break;
5665 case 22: /* VABS */
5666 switch(size) {
5667 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
5668 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
5669 case 2: tcg_gen_abs_i32(tmp, tmp); break;
5670 default: return 1;
5672 break;
5673 case 23: /* VNEG */
5674 if (size == 3)
5675 return 1;
5676 tmp2 = tcg_const_i32(0);
5677 gen_neon_rsb(size, tmp, tmp2);
5678 tcg_temp_free(tmp2);
5679 break;
5680 case 24: /* Float VCGT #0 */
5681 tmp2 = tcg_const_i32(0);
5682 gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
5683 tcg_temp_free(tmp2);
5684 break;
5685 case 25: /* Float VCGE #0 */
5686 tmp2 = tcg_const_i32(0);
5687 gen_helper_neon_cge_f32(tmp, tmp, tmp2);
5688 tcg_temp_free(tmp2);
5689 break;
5690 case 26: /* Float VCEQ #0 */
5691 tmp2 = tcg_const_i32(0);
5692 gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
5693 tcg_temp_free(tmp2);
5694 break;
5695 case 27: /* Float VCLE #0 */
5696 tmp2 = tcg_const_i32(0);
5697 gen_helper_neon_cge_f32(tmp, tmp2, tmp);
5698 tcg_temp_free(tmp2);
5699 break;
5700 case 28: /* Float VCLT #0 */
5701 tmp2 = tcg_const_i32(0);
5702 gen_helper_neon_cgt_f32(tmp, tmp2, tmp);
5703 tcg_temp_free(tmp2);
5704 break;
5705 case 30: /* Float VABS */
5706 gen_vfp_abs(0);
5707 break;
5708 case 31: /* Float VNEG */
5709 gen_vfp_neg(0);
5710 break;
5711 case 32: /* VSWP */
5712 tmp2 = neon_load_reg(rd, pass);
5713 neon_store_reg(rm, pass, tmp2);
5714 break;
5715 case 33: /* VTRN */
5716 tmp2 = neon_load_reg(rd, pass);
5717 switch (size) {
5718 case 0: gen_neon_trn_u8(tmp, tmp2); break;
5719 case 1: gen_neon_trn_u16(tmp, tmp2); break;
5720 case 2: abort();
5721 default: return 1;
5723 neon_store_reg(rm, pass, tmp2);
5724 break;
5725 case 56: /* Integer VRECPE */
5726 gen_helper_recpe_u32(tmp, tmp, cpu_env);
5727 break;
5728 case 57: /* Integer VRSQRTE */
5729 gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
5730 break;
5731 case 58: /* Float VRECPE */
5732 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
5733 break;
5734 case 59: /* Float VRSQRTE */
5735 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
5736 break;
5737 case 60: /* VCVT.F32.S32 */
5738 gen_vfp_sito(0);
5739 break;
5740 case 61: /* VCVT.F32.U32 */
5741 gen_vfp_uito(0);
5742 break;
5743 case 62: /* VCVT.S32.F32 */
5744 gen_vfp_tosiz(0);
5745 break;
5746 case 63: /* VCVT.U32.F32 */
5747 gen_vfp_touiz(0);
5748 break;
5749 default:
5750 /* Reserved: 21, 29, 39-56 */
5751 return 1;
5753 if (op == 30 || op == 31 || op >= 58) {
5754 tcg_gen_st_f32(cpu_F0s, cpu_env,
5755 neon_reg_offset(rd, pass));
5756 } else {
5757 neon_store_reg(rd, pass, tmp);
5760 break;
5762 } else if ((insn & (1 << 10)) == 0) {
5763 /* VTBL, VTBX. */
5764 n = ((insn >> 5) & 0x18) + 8;
5765 if (insn & (1 << 6)) {
5766 tmp = neon_load_reg(rd, 0);
5767 } else {
5768 tmp = tcg_temp_new_i32();
5769 tcg_gen_movi_i32(tmp, 0);
5771 tmp2 = neon_load_reg(rm, 0);
5772 tmp4 = tcg_const_i32(rn);
5773 tmp5 = tcg_const_i32(n);
5774 gen_helper_neon_tbl(tmp2, tmp2, tmp, tmp4, tmp5);
5775 tcg_temp_free_i32(tmp);
5776 if (insn & (1 << 6)) {
5777 tmp = neon_load_reg(rd, 1);
5778 } else {
5779 tmp = tcg_temp_new_i32();
5780 tcg_gen_movi_i32(tmp, 0);
5782 tmp3 = neon_load_reg(rm, 1);
5783 gen_helper_neon_tbl(tmp3, tmp3, tmp, tmp4, tmp5);
5784 tcg_temp_free_i32(tmp5);
5785 tcg_temp_free_i32(tmp4);
5786 neon_store_reg(rd, 0, tmp2);
5787 neon_store_reg(rd, 1, tmp3);
5788 tcg_temp_free_i32(tmp);
5789 } else if ((insn & 0x380) == 0) {
5790 /* VDUP */
5791 if (insn & (1 << 19)) {
5792 tmp = neon_load_reg(rm, 1);
5793 } else {
5794 tmp = neon_load_reg(rm, 0);
5796 if (insn & (1 << 16)) {
5797 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
5798 } else if (insn & (1 << 17)) {
5799 if ((insn >> 18) & 1)
5800 gen_neon_dup_high16(tmp);
5801 else
5802 gen_neon_dup_low16(tmp);
5804 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5805 tmp2 = tcg_temp_new_i32();
5806 tcg_gen_mov_i32(tmp2, tmp);
5807 neon_store_reg(rd, pass, tmp2);
5809 tcg_temp_free_i32(tmp);
5810 } else {
5811 return 1;
5815 return 0;
5818 static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
5820 int crn = (insn >> 16) & 0xf;
5821 int crm = insn & 0xf;
5822 int op1 = (insn >> 21) & 7;
5823 int op2 = (insn >> 5) & 7;
5824 int rt = (insn >> 12) & 0xf;
5825 TCGv tmp;
5827 /* Minimal set of debug registers, since we don't support debug */
5828 if (op1 == 0 && crn == 0 && op2 == 0) {
5829 switch (crm) {
5830 case 0:
5831 /* DBGDIDR: just RAZ. In particular this means the
5832 * "debug architecture version" bits will read as
5833 * a reserved value, which should cause Linux to
5834 * not try to use the debug hardware.
5836 tmp = tcg_const_i32(0);
5837 store_reg(s, rt, tmp);
5838 return 0;
5839 case 1:
5840 case 2:
5841 /* DBGDRAR and DBGDSAR: v7 only. Always RAZ since we
5842 * don't implement memory mapped debug components
5844 if (ENABLE_ARCH_7) {
5845 tmp = tcg_const_i32(0);
5846 store_reg(s, rt, tmp);
5847 return 0;
5849 break;
5850 default:
5851 break;
5855 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5856 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5857 /* TEECR */
5858 if (IS_USER(s))
5859 return 1;
5860 tmp = load_cpu_field(teecr);
5861 store_reg(s, rt, tmp);
5862 return 0;
5864 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5865 /* TEEHBR */
5866 if (IS_USER(s) && (env->teecr & 1))
5867 return 1;
5868 tmp = load_cpu_field(teehbr);
5869 store_reg(s, rt, tmp);
5870 return 0;
5873 fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5874 op1, crn, crm, op2);
5875 return 1;
5878 static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
5880 int crn = (insn >> 16) & 0xf;
5881 int crm = insn & 0xf;
5882 int op1 = (insn >> 21) & 7;
5883 int op2 = (insn >> 5) & 7;
5884 int rt = (insn >> 12) & 0xf;
5885 TCGv tmp;
5887 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5888 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5889 /* TEECR */
5890 if (IS_USER(s))
5891 return 1;
5892 tmp = load_reg(s, rt);
5893 gen_helper_set_teecr(cpu_env, tmp);
5894 tcg_temp_free_i32(tmp);
5895 return 0;
5897 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5898 /* TEEHBR */
5899 if (IS_USER(s) && (env->teecr & 1))
5900 return 1;
5901 tmp = load_reg(s, rt);
5902 store_cpu_field(tmp, teehbr);
5903 return 0;
5906 fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5907 op1, crn, crm, op2);
5908 return 1;
5911 static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
5913 int cpnum;
5915 cpnum = (insn >> 8) & 0xf;
5916 if (arm_feature(env, ARM_FEATURE_XSCALE)
5917 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
5918 return 1;
5920 switch (cpnum) {
5921 case 0:
5922 case 1:
5923 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5924 return disas_iwmmxt_insn(env, s, insn);
5925 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
5926 return disas_dsp_insn(env, s, insn);
5928 return 1;
5929 case 10:
5930 case 11:
5931 return disas_vfp_insn (env, s, insn);
5932 case 14:
5933 /* Coprocessors 7-15 are architecturally reserved by ARM.
5934 Unfortunately Intel decided to ignore this. */
5935 if (arm_feature(env, ARM_FEATURE_XSCALE))
5936 goto board;
5937 if (insn & (1 << 20))
5938 return disas_cp14_read(env, s, insn);
5939 else
5940 return disas_cp14_write(env, s, insn);
5941 case 15:
5942 return disas_cp15_insn (env, s, insn);
5943 default:
5944 board:
5945 /* Unknown coprocessor. See if the board has hooked it. */
5946 return disas_cp_insn (env, s, insn);
5951 /* Store a 64-bit value to a register pair. Clobbers val. */
5952 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5954 TCGv tmp;
5955 tmp = tcg_temp_new_i32();
5956 tcg_gen_trunc_i64_i32(tmp, val);
5957 store_reg(s, rlow, tmp);
5958 tmp = tcg_temp_new_i32();
5959 tcg_gen_shri_i64(val, val, 32);
5960 tcg_gen_trunc_i64_i32(tmp, val);
5961 store_reg(s, rhigh, tmp);
5964 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5965 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5967 TCGv_i64 tmp;
5968 TCGv tmp2;
5970 /* Load value and extend to 64 bits. */
5971 tmp = tcg_temp_new_i64();
5972 tmp2 = load_reg(s, rlow);
5973 tcg_gen_extu_i32_i64(tmp, tmp2);
5974 tcg_temp_free_i32(tmp2);
5975 tcg_gen_add_i64(val, val, tmp);
5976 tcg_temp_free_i64(tmp);
5979 /* load and add a 64-bit value from a register pair. */
5980 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5982 TCGv_i64 tmp;
5983 TCGv tmpl;
5984 TCGv tmph;
5986 /* Load 64-bit value rd:rn. */
5987 tmpl = load_reg(s, rlow);
5988 tmph = load_reg(s, rhigh);
5989 tmp = tcg_temp_new_i64();
5990 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
5991 tcg_temp_free_i32(tmpl);
5992 tcg_temp_free_i32(tmph);
5993 tcg_gen_add_i64(val, val, tmp);
5994 tcg_temp_free_i64(tmp);
5997 /* Set N and Z flags from a 64-bit value. */
5998 static void gen_logicq_cc(TCGv_i64 val)
6000 TCGv tmp = tcg_temp_new_i32();
6001 gen_helper_logicq_cc(tmp, val);
6002 gen_logic_CC(tmp);
6003 tcg_temp_free_i32(tmp);
6006 /* Load/Store exclusive instructions are implemented by remembering
6007 the value/address loaded, and seeing if these are the same
6008 when the store is performed. This should be is sufficient to implement
6009 the architecturally mandated semantics, and avoids having to monitor
6010 regular stores.
6012 In system emulation mode only one CPU will be running at once, so
6013 this sequence is effectively atomic. In user emulation mode we
6014 throw an exception and handle the atomic operation elsewhere. */
6015 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
6016 TCGv addr, int size)
6018 TCGv tmp;
6020 switch (size) {
6021 case 0:
6022 tmp = gen_ld8u(addr, IS_USER(s));
6023 break;
6024 case 1:
6025 tmp = gen_ld16u(addr, IS_USER(s));
6026 break;
6027 case 2:
6028 case 3:
6029 tmp = gen_ld32(addr, IS_USER(s));
6030 break;
6031 default:
6032 abort();
6034 tcg_gen_mov_i32(cpu_exclusive_val, tmp);
6035 store_reg(s, rt, tmp);
6036 if (size == 3) {
6037 TCGv tmp2 = tcg_temp_new_i32();
6038 tcg_gen_addi_i32(tmp2, addr, 4);
6039 tmp = gen_ld32(tmp2, IS_USER(s));
6040 tcg_temp_free_i32(tmp2);
6041 tcg_gen_mov_i32(cpu_exclusive_high, tmp);
6042 store_reg(s, rt2, tmp);
6044 tcg_gen_mov_i32(cpu_exclusive_addr, addr);
6047 static void gen_clrex(DisasContext *s)
6049 tcg_gen_movi_i32(cpu_exclusive_addr, -1);
6052 #ifdef CONFIG_USER_ONLY
6053 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
6054 TCGv addr, int size)
6056 tcg_gen_mov_i32(cpu_exclusive_test, addr);
6057 tcg_gen_movi_i32(cpu_exclusive_info,
6058 size | (rd << 4) | (rt << 8) | (rt2 << 12));
6059 gen_exception_insn(s, 4, EXCP_STREX);
6061 #else
6062 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
6063 TCGv addr, int size)
6065 TCGv tmp;
6066 int done_label;
6067 int fail_label;
6069 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
6070 [addr] = {Rt};
6071 {Rd} = 0;
6072 } else {
6073 {Rd} = 1;
6074 } */
6075 fail_label = gen_new_label();
6076 done_label = gen_new_label();
6077 tcg_gen_brcond_i32(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
6078 switch (size) {
6079 case 0:
6080 tmp = gen_ld8u(addr, IS_USER(s));
6081 break;
6082 case 1:
6083 tmp = gen_ld16u(addr, IS_USER(s));
6084 break;
6085 case 2:
6086 case 3:
6087 tmp = gen_ld32(addr, IS_USER(s));
6088 break;
6089 default:
6090 abort();
6092 tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label);
6093 tcg_temp_free_i32(tmp);
6094 if (size == 3) {
6095 TCGv tmp2 = tcg_temp_new_i32();
6096 tcg_gen_addi_i32(tmp2, addr, 4);
6097 tmp = gen_ld32(tmp2, IS_USER(s));
6098 tcg_temp_free_i32(tmp2);
6099 tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_high, fail_label);
6100 tcg_temp_free_i32(tmp);
6102 tmp = load_reg(s, rt);
6103 switch (size) {
6104 case 0:
6105 gen_st8(tmp, addr, IS_USER(s));
6106 break;
6107 case 1:
6108 gen_st16(tmp, addr, IS_USER(s));
6109 break;
6110 case 2:
6111 case 3:
6112 gen_st32(tmp, addr, IS_USER(s));
6113 break;
6114 default:
6115 abort();
6117 if (size == 3) {
6118 tcg_gen_addi_i32(addr, addr, 4);
6119 tmp = load_reg(s, rt2);
6120 gen_st32(tmp, addr, IS_USER(s));
6122 tcg_gen_movi_i32(cpu_R[rd], 0);
6123 tcg_gen_br(done_label);
6124 gen_set_label(fail_label);
6125 tcg_gen_movi_i32(cpu_R[rd], 1);
6126 gen_set_label(done_label);
6127 tcg_gen_movi_i32(cpu_exclusive_addr, -1);
6129 #endif
6131 static void disas_arm_insn(CPUState * env, DisasContext *s)
6133 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
6134 TCGv tmp;
6135 TCGv tmp2;
6136 TCGv tmp3;
6137 TCGv addr;
6138 TCGv_i64 tmp64;
6140 insn = ldl_code(s->pc);
6141 s->pc += 4;
6143 /* M variants do not implement ARM mode. */
6144 if (IS_M(env))
6145 goto illegal_op;
6146 cond = insn >> 28;
6147 if (cond == 0xf){
6148 /* Unconditional instructions. */
6149 if (((insn >> 25) & 7) == 1) {
6150 /* NEON Data processing. */
6151 if (!arm_feature(env, ARM_FEATURE_NEON))
6152 goto illegal_op;
6154 if (disas_neon_data_insn(env, s, insn))
6155 goto illegal_op;
6156 return;
6158 if ((insn & 0x0f100000) == 0x04000000) {
6159 /* NEON load/store. */
6160 if (!arm_feature(env, ARM_FEATURE_NEON))
6161 goto illegal_op;
6163 if (disas_neon_ls_insn(env, s, insn))
6164 goto illegal_op;
6165 return;
6167 if (((insn & 0x0f30f000) == 0x0510f000) ||
6168 ((insn & 0x0f30f010) == 0x0710f000)) {
6169 if ((insn & (1 << 22)) == 0) {
6170 /* PLDW; v7MP */
6171 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
6172 goto illegal_op;
6175 /* Otherwise PLD; v5TE+ */
6176 return;
6178 if (((insn & 0x0f70f000) == 0x0450f000) ||
6179 ((insn & 0x0f70f010) == 0x0650f000)) {
6180 ARCH(7);
6181 return; /* PLI; V7 */
6183 if (((insn & 0x0f700000) == 0x04100000) ||
6184 ((insn & 0x0f700010) == 0x06100000)) {
6185 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
6186 goto illegal_op;
6188 return; /* v7MP: Unallocated memory hint: must NOP */
6191 if ((insn & 0x0ffffdff) == 0x01010000) {
6192 ARCH(6);
6193 /* setend */
6194 if (insn & (1 << 9)) {
6195 /* BE8 mode not implemented. */
6196 goto illegal_op;
6198 return;
6199 } else if ((insn & 0x0fffff00) == 0x057ff000) {
6200 switch ((insn >> 4) & 0xf) {
6201 case 1: /* clrex */
6202 ARCH(6K);
6203 gen_clrex(s);
6204 return;
6205 case 4: /* dsb */
6206 case 5: /* dmb */
6207 case 6: /* isb */
6208 ARCH(7);
6209 /* We don't emulate caches so these are a no-op. */
6210 return;
6211 default:
6212 goto illegal_op;
6214 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
6215 /* srs */
6216 int32_t offset;
6217 if (IS_USER(s))
6218 goto illegal_op;
6219 ARCH(6);
6220 op1 = (insn & 0x1f);
6221 addr = tcg_temp_new_i32();
6222 tmp = tcg_const_i32(op1);
6223 gen_helper_get_r13_banked(addr, cpu_env, tmp);
6224 tcg_temp_free_i32(tmp);
6225 i = (insn >> 23) & 3;
6226 switch (i) {
6227 case 0: offset = -4; break; /* DA */
6228 case 1: offset = 0; break; /* IA */
6229 case 2: offset = -8; break; /* DB */
6230 case 3: offset = 4; break; /* IB */
6231 default: abort();
6233 if (offset)
6234 tcg_gen_addi_i32(addr, addr, offset);
6235 tmp = load_reg(s, 14);
6236 gen_st32(tmp, addr, 0);
6237 tmp = load_cpu_field(spsr);
6238 tcg_gen_addi_i32(addr, addr, 4);
6239 gen_st32(tmp, addr, 0);
6240 if (insn & (1 << 21)) {
6241 /* Base writeback. */
6242 switch (i) {
6243 case 0: offset = -8; break;
6244 case 1: offset = 4; break;
6245 case 2: offset = -4; break;
6246 case 3: offset = 0; break;
6247 default: abort();
6249 if (offset)
6250 tcg_gen_addi_i32(addr, addr, offset);
6251 tmp = tcg_const_i32(op1);
6252 gen_helper_set_r13_banked(cpu_env, tmp, addr);
6253 tcg_temp_free_i32(tmp);
6254 tcg_temp_free_i32(addr);
6255 } else {
6256 tcg_temp_free_i32(addr);
6258 return;
6259 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
6260 /* rfe */
6261 int32_t offset;
6262 if (IS_USER(s))
6263 goto illegal_op;
6264 ARCH(6);
6265 rn = (insn >> 16) & 0xf;
6266 addr = load_reg(s, rn);
6267 i = (insn >> 23) & 3;
6268 switch (i) {
6269 case 0: offset = -4; break; /* DA */
6270 case 1: offset = 0; break; /* IA */
6271 case 2: offset = -8; break; /* DB */
6272 case 3: offset = 4; break; /* IB */
6273 default: abort();
6275 if (offset)
6276 tcg_gen_addi_i32(addr, addr, offset);
6277 /* Load PC into tmp and CPSR into tmp2. */
6278 tmp = gen_ld32(addr, 0);
6279 tcg_gen_addi_i32(addr, addr, 4);
6280 tmp2 = gen_ld32(addr, 0);
6281 if (insn & (1 << 21)) {
6282 /* Base writeback. */
6283 switch (i) {
6284 case 0: offset = -8; break;
6285 case 1: offset = 4; break;
6286 case 2: offset = -4; break;
6287 case 3: offset = 0; break;
6288 default: abort();
6290 if (offset)
6291 tcg_gen_addi_i32(addr, addr, offset);
6292 store_reg(s, rn, addr);
6293 } else {
6294 tcg_temp_free_i32(addr);
6296 gen_rfe(s, tmp, tmp2);
6297 return;
6298 } else if ((insn & 0x0e000000) == 0x0a000000) {
6299 /* branch link and change to thumb (blx <offset>) */
6300 int32_t offset;
6302 val = (uint32_t)s->pc;
6303 tmp = tcg_temp_new_i32();
6304 tcg_gen_movi_i32(tmp, val);
6305 store_reg(s, 14, tmp);
6306 /* Sign-extend the 24-bit offset */
6307 offset = (((int32_t)insn) << 8) >> 8;
6308 /* offset * 4 + bit24 * 2 + (thumb bit) */
6309 val += (offset << 2) | ((insn >> 23) & 2) | 1;
6310 /* pipeline offset */
6311 val += 4;
6312 gen_bx_im(s, val);
6313 return;
6314 } else if ((insn & 0x0e000f00) == 0x0c000100) {
6315 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
6316 /* iWMMXt register transfer. */
6317 if (env->cp15.c15_cpar & (1 << 1))
6318 if (!disas_iwmmxt_insn(env, s, insn))
6319 return;
6321 } else if ((insn & 0x0fe00000) == 0x0c400000) {
6322 /* Coprocessor double register transfer. */
6323 } else if ((insn & 0x0f000010) == 0x0e000010) {
6324 /* Additional coprocessor register transfer. */
6325 } else if ((insn & 0x0ff10020) == 0x01000000) {
6326 uint32_t mask;
6327 uint32_t val;
6328 /* cps (privileged) */
6329 if (IS_USER(s))
6330 return;
6331 mask = val = 0;
6332 if (insn & (1 << 19)) {
6333 if (insn & (1 << 8))
6334 mask |= CPSR_A;
6335 if (insn & (1 << 7))
6336 mask |= CPSR_I;
6337 if (insn & (1 << 6))
6338 mask |= CPSR_F;
6339 if (insn & (1 << 18))
6340 val |= mask;
6342 if (insn & (1 << 17)) {
6343 mask |= CPSR_M;
6344 val |= (insn & 0x1f);
6346 if (mask) {
6347 gen_set_psr_im(s, mask, 0, val);
6349 return;
6351 goto illegal_op;
6353 if (cond != 0xe) {
6354 /* if not always execute, we generate a conditional jump to
6355 next instruction */
6356 s->condlabel = gen_new_label();
6357 gen_test_cc(cond ^ 1, s->condlabel);
6358 s->condjmp = 1;
6360 if ((insn & 0x0f900000) == 0x03000000) {
6361 if ((insn & (1 << 21)) == 0) {
6362 ARCH(6T2);
6363 rd = (insn >> 12) & 0xf;
6364 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
6365 if ((insn & (1 << 22)) == 0) {
6366 /* MOVW */
6367 tmp = tcg_temp_new_i32();
6368 tcg_gen_movi_i32(tmp, val);
6369 } else {
6370 /* MOVT */
6371 tmp = load_reg(s, rd);
6372 tcg_gen_ext16u_i32(tmp, tmp);
6373 tcg_gen_ori_i32(tmp, tmp, val << 16);
6375 store_reg(s, rd, tmp);
6376 } else {
6377 if (((insn >> 12) & 0xf) != 0xf)
6378 goto illegal_op;
6379 if (((insn >> 16) & 0xf) == 0) {
6380 gen_nop_hint(s, insn & 0xff);
6381 } else {
6382 /* CPSR = immediate */
6383 val = insn & 0xff;
6384 shift = ((insn >> 8) & 0xf) * 2;
6385 if (shift)
6386 val = (val >> shift) | (val << (32 - shift));
6387 i = ((insn & (1 << 22)) != 0);
6388 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
6389 goto illegal_op;
6392 } else if ((insn & 0x0f900000) == 0x01000000
6393 && (insn & 0x00000090) != 0x00000090) {
6394 /* miscellaneous instructions */
6395 op1 = (insn >> 21) & 3;
6396 sh = (insn >> 4) & 0xf;
6397 rm = insn & 0xf;
6398 switch (sh) {
6399 case 0x0: /* move program status register */
6400 if (op1 & 1) {
6401 /* PSR = reg */
6402 tmp = load_reg(s, rm);
6403 i = ((op1 & 2) != 0);
6404 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
6405 goto illegal_op;
6406 } else {
6407 /* reg = PSR */
6408 rd = (insn >> 12) & 0xf;
6409 if (op1 & 2) {
6410 if (IS_USER(s))
6411 goto illegal_op;
6412 tmp = load_cpu_field(spsr);
6413 } else {
6414 tmp = tcg_temp_new_i32();
6415 gen_helper_cpsr_read(tmp);
6417 store_reg(s, rd, tmp);
6419 break;
6420 case 0x1:
6421 if (op1 == 1) {
6422 /* branch/exchange thumb (bx). */
6423 tmp = load_reg(s, rm);
6424 gen_bx(s, tmp);
6425 } else if (op1 == 3) {
6426 /* clz */
6427 rd = (insn >> 12) & 0xf;
6428 tmp = load_reg(s, rm);
6429 gen_helper_clz(tmp, tmp);
6430 store_reg(s, rd, tmp);
6431 } else {
6432 goto illegal_op;
6434 break;
6435 case 0x2:
6436 if (op1 == 1) {
6437 ARCH(5J); /* bxj */
6438 /* Trivial implementation equivalent to bx. */
6439 tmp = load_reg(s, rm);
6440 gen_bx(s, tmp);
6441 } else {
6442 goto illegal_op;
6444 break;
6445 case 0x3:
6446 if (op1 != 1)
6447 goto illegal_op;
6449 /* branch link/exchange thumb (blx) */
6450 tmp = load_reg(s, rm);
6451 tmp2 = tcg_temp_new_i32();
6452 tcg_gen_movi_i32(tmp2, s->pc);
6453 store_reg(s, 14, tmp2);
6454 gen_bx(s, tmp);
6455 break;
6456 case 0x5: /* saturating add/subtract */
6457 rd = (insn >> 12) & 0xf;
6458 rn = (insn >> 16) & 0xf;
6459 tmp = load_reg(s, rm);
6460 tmp2 = load_reg(s, rn);
6461 if (op1 & 2)
6462 gen_helper_double_saturate(tmp2, tmp2);
6463 if (op1 & 1)
6464 gen_helper_sub_saturate(tmp, tmp, tmp2);
6465 else
6466 gen_helper_add_saturate(tmp, tmp, tmp2);
6467 tcg_temp_free_i32(tmp2);
6468 store_reg(s, rd, tmp);
6469 break;
6470 case 7:
6471 /* SMC instruction (op1 == 3)
6472 and undefined instructions (op1 == 0 || op1 == 2)
6473 will trap */
6474 if (op1 != 1) {
6475 goto illegal_op;
6477 /* bkpt */
6478 gen_exception_insn(s, 4, EXCP_BKPT);
6479 break;
6480 case 0x8: /* signed multiply */
6481 case 0xa:
6482 case 0xc:
6483 case 0xe:
6484 rs = (insn >> 8) & 0xf;
6485 rn = (insn >> 12) & 0xf;
6486 rd = (insn >> 16) & 0xf;
6487 if (op1 == 1) {
6488 /* (32 * 16) >> 16 */
6489 tmp = load_reg(s, rm);
6490 tmp2 = load_reg(s, rs);
6491 if (sh & 4)
6492 tcg_gen_sari_i32(tmp2, tmp2, 16);
6493 else
6494 gen_sxth(tmp2);
6495 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6496 tcg_gen_shri_i64(tmp64, tmp64, 16);
6497 tmp = tcg_temp_new_i32();
6498 tcg_gen_trunc_i64_i32(tmp, tmp64);
6499 tcg_temp_free_i64(tmp64);
6500 if ((sh & 2) == 0) {
6501 tmp2 = load_reg(s, rn);
6502 gen_helper_add_setq(tmp, tmp, tmp2);
6503 tcg_temp_free_i32(tmp2);
6505 store_reg(s, rd, tmp);
6506 } else {
6507 /* 16 * 16 */
6508 tmp = load_reg(s, rm);
6509 tmp2 = load_reg(s, rs);
6510 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
6511 tcg_temp_free_i32(tmp2);
6512 if (op1 == 2) {
6513 tmp64 = tcg_temp_new_i64();
6514 tcg_gen_ext_i32_i64(tmp64, tmp);
6515 tcg_temp_free_i32(tmp);
6516 gen_addq(s, tmp64, rn, rd);
6517 gen_storeq_reg(s, rn, rd, tmp64);
6518 tcg_temp_free_i64(tmp64);
6519 } else {
6520 if (op1 == 0) {
6521 tmp2 = load_reg(s, rn);
6522 gen_helper_add_setq(tmp, tmp, tmp2);
6523 tcg_temp_free_i32(tmp2);
6525 store_reg(s, rd, tmp);
6528 break;
6529 default:
6530 goto illegal_op;
6532 } else if (((insn & 0x0e000000) == 0 &&
6533 (insn & 0x00000090) != 0x90) ||
6534 ((insn & 0x0e000000) == (1 << 25))) {
6535 int set_cc, logic_cc, shiftop;
6537 op1 = (insn >> 21) & 0xf;
6538 set_cc = (insn >> 20) & 1;
6539 logic_cc = table_logic_cc[op1] & set_cc;
6541 /* data processing instruction */
6542 if (insn & (1 << 25)) {
6543 /* immediate operand */
6544 val = insn & 0xff;
6545 shift = ((insn >> 8) & 0xf) * 2;
6546 if (shift) {
6547 val = (val >> shift) | (val << (32 - shift));
6549 tmp2 = tcg_temp_new_i32();
6550 tcg_gen_movi_i32(tmp2, val);
6551 if (logic_cc && shift) {
6552 gen_set_CF_bit31(tmp2);
6554 } else {
6555 /* register */
6556 rm = (insn) & 0xf;
6557 tmp2 = load_reg(s, rm);
6558 shiftop = (insn >> 5) & 3;
6559 if (!(insn & (1 << 4))) {
6560 shift = (insn >> 7) & 0x1f;
6561 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
6562 } else {
6563 rs = (insn >> 8) & 0xf;
6564 tmp = load_reg(s, rs);
6565 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
6568 if (op1 != 0x0f && op1 != 0x0d) {
6569 rn = (insn >> 16) & 0xf;
6570 tmp = load_reg(s, rn);
6571 } else {
6572 TCGV_UNUSED(tmp);
6574 rd = (insn >> 12) & 0xf;
6575 switch(op1) {
6576 case 0x00:
6577 tcg_gen_and_i32(tmp, tmp, tmp2);
6578 if (logic_cc) {
6579 gen_logic_CC(tmp);
6581 store_reg_bx(env, s, rd, tmp);
6582 break;
6583 case 0x01:
6584 tcg_gen_xor_i32(tmp, tmp, tmp2);
6585 if (logic_cc) {
6586 gen_logic_CC(tmp);
6588 store_reg_bx(env, s, rd, tmp);
6589 break;
6590 case 0x02:
6591 if (set_cc && rd == 15) {
6592 /* SUBS r15, ... is used for exception return. */
6593 if (IS_USER(s)) {
6594 goto illegal_op;
6596 gen_helper_sub_cc(tmp, tmp, tmp2);
6597 gen_exception_return(s, tmp);
6598 } else {
6599 if (set_cc) {
6600 gen_helper_sub_cc(tmp, tmp, tmp2);
6601 } else {
6602 tcg_gen_sub_i32(tmp, tmp, tmp2);
6604 store_reg_bx(env, s, rd, tmp);
6606 break;
6607 case 0x03:
6608 if (set_cc) {
6609 gen_helper_sub_cc(tmp, tmp2, tmp);
6610 } else {
6611 tcg_gen_sub_i32(tmp, tmp2, tmp);
6613 store_reg_bx(env, s, rd, tmp);
6614 break;
6615 case 0x04:
6616 if (set_cc) {
6617 gen_helper_add_cc(tmp, tmp, tmp2);
6618 } else {
6619 tcg_gen_add_i32(tmp, tmp, tmp2);
6621 store_reg_bx(env, s, rd, tmp);
6622 break;
6623 case 0x05:
6624 if (set_cc) {
6625 gen_helper_adc_cc(tmp, tmp, tmp2);
6626 } else {
6627 gen_add_carry(tmp, tmp, tmp2);
6629 store_reg_bx(env, s, rd, tmp);
6630 break;
6631 case 0x06:
6632 if (set_cc) {
6633 gen_helper_sbc_cc(tmp, tmp, tmp2);
6634 } else {
6635 gen_sub_carry(tmp, tmp, tmp2);
6637 store_reg_bx(env, s, rd, tmp);
6638 break;
6639 case 0x07:
6640 if (set_cc) {
6641 gen_helper_sbc_cc(tmp, tmp2, tmp);
6642 } else {
6643 gen_sub_carry(tmp, tmp2, tmp);
6645 store_reg_bx(env, s, rd, tmp);
6646 break;
6647 case 0x08:
6648 if (set_cc) {
6649 tcg_gen_and_i32(tmp, tmp, tmp2);
6650 gen_logic_CC(tmp);
6652 tcg_temp_free_i32(tmp);
6653 break;
6654 case 0x09:
6655 if (set_cc) {
6656 tcg_gen_xor_i32(tmp, tmp, tmp2);
6657 gen_logic_CC(tmp);
6659 tcg_temp_free_i32(tmp);
6660 break;
6661 case 0x0a:
6662 if (set_cc) {
6663 gen_helper_sub_cc(tmp, tmp, tmp2);
6665 tcg_temp_free_i32(tmp);
6666 break;
6667 case 0x0b:
6668 if (set_cc) {
6669 gen_helper_add_cc(tmp, tmp, tmp2);
6671 tcg_temp_free_i32(tmp);
6672 break;
6673 case 0x0c:
6674 tcg_gen_or_i32(tmp, tmp, tmp2);
6675 if (logic_cc) {
6676 gen_logic_CC(tmp);
6678 store_reg_bx(env, s, rd, tmp);
6679 break;
6680 case 0x0d:
6681 if (logic_cc && rd == 15) {
6682 /* MOVS r15, ... is used for exception return. */
6683 if (IS_USER(s)) {
6684 goto illegal_op;
6686 gen_exception_return(s, tmp2);
6687 } else {
6688 if (logic_cc) {
6689 gen_logic_CC(tmp2);
6691 store_reg_bx(env, s, rd, tmp2);
6693 break;
6694 case 0x0e:
6695 tcg_gen_andc_i32(tmp, tmp, tmp2);
6696 if (logic_cc) {
6697 gen_logic_CC(tmp);
6699 store_reg_bx(env, s, rd, tmp);
6700 break;
6701 default:
6702 case 0x0f:
6703 tcg_gen_not_i32(tmp2, tmp2);
6704 if (logic_cc) {
6705 gen_logic_CC(tmp2);
6707 store_reg_bx(env, s, rd, tmp2);
6708 break;
6710 if (op1 != 0x0f && op1 != 0x0d) {
6711 tcg_temp_free_i32(tmp2);
6713 } else {
6714 /* other instructions */
6715 op1 = (insn >> 24) & 0xf;
6716 switch(op1) {
6717 case 0x0:
6718 case 0x1:
6719 /* multiplies, extra load/stores */
6720 sh = (insn >> 5) & 3;
6721 if (sh == 0) {
6722 if (op1 == 0x0) {
6723 rd = (insn >> 16) & 0xf;
6724 rn = (insn >> 12) & 0xf;
6725 rs = (insn >> 8) & 0xf;
6726 rm = (insn) & 0xf;
6727 op1 = (insn >> 20) & 0xf;
6728 switch (op1) {
6729 case 0: case 1: case 2: case 3: case 6:
6730 /* 32 bit mul */
6731 tmp = load_reg(s, rs);
6732 tmp2 = load_reg(s, rm);
6733 tcg_gen_mul_i32(tmp, tmp, tmp2);
6734 tcg_temp_free_i32(tmp2);
6735 if (insn & (1 << 22)) {
6736 /* Subtract (mls) */
6737 ARCH(6T2);
6738 tmp2 = load_reg(s, rn);
6739 tcg_gen_sub_i32(tmp, tmp2, tmp);
6740 tcg_temp_free_i32(tmp2);
6741 } else if (insn & (1 << 21)) {
6742 /* Add */
6743 tmp2 = load_reg(s, rn);
6744 tcg_gen_add_i32(tmp, tmp, tmp2);
6745 tcg_temp_free_i32(tmp2);
6747 if (insn & (1 << 20))
6748 gen_logic_CC(tmp);
6749 store_reg(s, rd, tmp);
6750 break;
6751 case 4:
6752 /* 64 bit mul double accumulate (UMAAL) */
6753 ARCH(6);
6754 tmp = load_reg(s, rs);
6755 tmp2 = load_reg(s, rm);
6756 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
6757 gen_addq_lo(s, tmp64, rn);
6758 gen_addq_lo(s, tmp64, rd);
6759 gen_storeq_reg(s, rn, rd, tmp64);
6760 tcg_temp_free_i64(tmp64);
6761 break;
6762 case 8: case 9: case 10: case 11:
6763 case 12: case 13: case 14: case 15:
6764 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
6765 tmp = load_reg(s, rs);
6766 tmp2 = load_reg(s, rm);
6767 if (insn & (1 << 22)) {
6768 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6769 } else {
6770 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
6772 if (insn & (1 << 21)) { /* mult accumulate */
6773 gen_addq(s, tmp64, rn, rd);
6775 if (insn & (1 << 20)) {
6776 gen_logicq_cc(tmp64);
6778 gen_storeq_reg(s, rn, rd, tmp64);
6779 tcg_temp_free_i64(tmp64);
6780 break;
6781 default:
6782 goto illegal_op;
6784 } else {
6785 rn = (insn >> 16) & 0xf;
6786 rd = (insn >> 12) & 0xf;
6787 if (insn & (1 << 23)) {
6788 /* load/store exclusive */
6789 op1 = (insn >> 21) & 0x3;
6790 if (op1)
6791 ARCH(6K);
6792 else
6793 ARCH(6);
6794 addr = tcg_temp_local_new_i32();
6795 load_reg_var(s, addr, rn);
6796 if (insn & (1 << 20)) {
6797 switch (op1) {
6798 case 0: /* ldrex */
6799 gen_load_exclusive(s, rd, 15, addr, 2);
6800 break;
6801 case 1: /* ldrexd */
6802 gen_load_exclusive(s, rd, rd + 1, addr, 3);
6803 break;
6804 case 2: /* ldrexb */
6805 gen_load_exclusive(s, rd, 15, addr, 0);
6806 break;
6807 case 3: /* ldrexh */
6808 gen_load_exclusive(s, rd, 15, addr, 1);
6809 break;
6810 default:
6811 abort();
6813 } else {
6814 rm = insn & 0xf;
6815 switch (op1) {
6816 case 0: /* strex */
6817 gen_store_exclusive(s, rd, rm, 15, addr, 2);
6818 break;
6819 case 1: /* strexd */
6820 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
6821 break;
6822 case 2: /* strexb */
6823 gen_store_exclusive(s, rd, rm, 15, addr, 0);
6824 break;
6825 case 3: /* strexh */
6826 gen_store_exclusive(s, rd, rm, 15, addr, 1);
6827 break;
6828 default:
6829 abort();
6832 tcg_temp_free(addr);
6833 } else {
6834 /* SWP instruction */
6835 rm = (insn) & 0xf;
6837 /* ??? This is not really atomic. However we know
6838 we never have multiple CPUs running in parallel,
6839 so it is good enough. */
6840 addr = load_reg(s, rn);
6841 tmp = load_reg(s, rm);
6842 if (insn & (1 << 22)) {
6843 tmp2 = gen_ld8u(addr, IS_USER(s));
6844 gen_st8(tmp, addr, IS_USER(s));
6845 } else {
6846 tmp2 = gen_ld32(addr, IS_USER(s));
6847 gen_st32(tmp, addr, IS_USER(s));
6849 tcg_temp_free_i32(addr);
6850 store_reg(s, rd, tmp2);
6853 } else {
6854 int address_offset;
6855 int load;
6856 /* Misc load/store */
6857 rn = (insn >> 16) & 0xf;
6858 rd = (insn >> 12) & 0xf;
6859 addr = load_reg(s, rn);
6860 if (insn & (1 << 24))
6861 gen_add_datah_offset(s, insn, 0, addr);
6862 address_offset = 0;
6863 if (insn & (1 << 20)) {
6864 /* load */
6865 switch(sh) {
6866 case 1:
6867 tmp = gen_ld16u(addr, IS_USER(s));
6868 break;
6869 case 2:
6870 tmp = gen_ld8s(addr, IS_USER(s));
6871 break;
6872 default:
6873 case 3:
6874 tmp = gen_ld16s(addr, IS_USER(s));
6875 break;
6877 load = 1;
6878 } else if (sh & 2) {
6879 /* doubleword */
6880 if (sh & 1) {
6881 /* store */
6882 tmp = load_reg(s, rd);
6883 gen_st32(tmp, addr, IS_USER(s));
6884 tcg_gen_addi_i32(addr, addr, 4);
6885 tmp = load_reg(s, rd + 1);
6886 gen_st32(tmp, addr, IS_USER(s));
6887 load = 0;
6888 } else {
6889 /* load */
6890 tmp = gen_ld32(addr, IS_USER(s));
6891 store_reg(s, rd, tmp);
6892 tcg_gen_addi_i32(addr, addr, 4);
6893 tmp = gen_ld32(addr, IS_USER(s));
6894 rd++;
6895 load = 1;
6897 address_offset = -4;
6898 } else {
6899 /* store */
6900 tmp = load_reg(s, rd);
6901 gen_st16(tmp, addr, IS_USER(s));
6902 load = 0;
6904 /* Perform base writeback before the loaded value to
6905 ensure correct behavior with overlapping index registers.
6906 ldrd with base writeback is is undefined if the
6907 destination and index registers overlap. */
6908 if (!(insn & (1 << 24))) {
6909 gen_add_datah_offset(s, insn, address_offset, addr);
6910 store_reg(s, rn, addr);
6911 } else if (insn & (1 << 21)) {
6912 if (address_offset)
6913 tcg_gen_addi_i32(addr, addr, address_offset);
6914 store_reg(s, rn, addr);
6915 } else {
6916 tcg_temp_free_i32(addr);
6918 if (load) {
6919 /* Complete the load. */
6920 store_reg(s, rd, tmp);
6923 break;
6924 case 0x4:
6925 case 0x5:
6926 goto do_ldst;
6927 case 0x6:
6928 case 0x7:
6929 if (insn & (1 << 4)) {
6930 ARCH(6);
6931 /* Armv6 Media instructions. */
6932 rm = insn & 0xf;
6933 rn = (insn >> 16) & 0xf;
6934 rd = (insn >> 12) & 0xf;
6935 rs = (insn >> 8) & 0xf;
6936 switch ((insn >> 23) & 3) {
6937 case 0: /* Parallel add/subtract. */
6938 op1 = (insn >> 20) & 7;
6939 tmp = load_reg(s, rn);
6940 tmp2 = load_reg(s, rm);
6941 sh = (insn >> 5) & 7;
6942 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
6943 goto illegal_op;
6944 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
6945 tcg_temp_free_i32(tmp2);
6946 store_reg(s, rd, tmp);
6947 break;
6948 case 1:
6949 if ((insn & 0x00700020) == 0) {
6950 /* Halfword pack. */
6951 tmp = load_reg(s, rn);
6952 tmp2 = load_reg(s, rm);
6953 shift = (insn >> 7) & 0x1f;
6954 if (insn & (1 << 6)) {
6955 /* pkhtb */
6956 if (shift == 0)
6957 shift = 31;
6958 tcg_gen_sari_i32(tmp2, tmp2, shift);
6959 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
6960 tcg_gen_ext16u_i32(tmp2, tmp2);
6961 } else {
6962 /* pkhbt */
6963 if (shift)
6964 tcg_gen_shli_i32(tmp2, tmp2, shift);
6965 tcg_gen_ext16u_i32(tmp, tmp);
6966 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
6968 tcg_gen_or_i32(tmp, tmp, tmp2);
6969 tcg_temp_free_i32(tmp2);
6970 store_reg(s, rd, tmp);
6971 } else if ((insn & 0x00200020) == 0x00200000) {
6972 /* [us]sat */
6973 tmp = load_reg(s, rm);
6974 shift = (insn >> 7) & 0x1f;
6975 if (insn & (1 << 6)) {
6976 if (shift == 0)
6977 shift = 31;
6978 tcg_gen_sari_i32(tmp, tmp, shift);
6979 } else {
6980 tcg_gen_shli_i32(tmp, tmp, shift);
6982 sh = (insn >> 16) & 0x1f;
6983 tmp2 = tcg_const_i32(sh);
6984 if (insn & (1 << 22))
6985 gen_helper_usat(tmp, tmp, tmp2);
6986 else
6987 gen_helper_ssat(tmp, tmp, tmp2);
6988 tcg_temp_free_i32(tmp2);
6989 store_reg(s, rd, tmp);
6990 } else if ((insn & 0x00300fe0) == 0x00200f20) {
6991 /* [us]sat16 */
6992 tmp = load_reg(s, rm);
6993 sh = (insn >> 16) & 0x1f;
6994 tmp2 = tcg_const_i32(sh);
6995 if (insn & (1 << 22))
6996 gen_helper_usat16(tmp, tmp, tmp2);
6997 else
6998 gen_helper_ssat16(tmp, tmp, tmp2);
6999 tcg_temp_free_i32(tmp2);
7000 store_reg(s, rd, tmp);
7001 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
7002 /* Select bytes. */
7003 tmp = load_reg(s, rn);
7004 tmp2 = load_reg(s, rm);
7005 tmp3 = tcg_temp_new_i32();
7006 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
7007 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7008 tcg_temp_free_i32(tmp3);
7009 tcg_temp_free_i32(tmp2);
7010 store_reg(s, rd, tmp);
7011 } else if ((insn & 0x000003e0) == 0x00000060) {
7012 tmp = load_reg(s, rm);
7013 shift = (insn >> 10) & 3;
7014 /* ??? In many cases it's not neccessary to do a
7015 rotate, a shift is sufficient. */
7016 if (shift != 0)
7017 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
7018 op1 = (insn >> 20) & 7;
7019 switch (op1) {
7020 case 0: gen_sxtb16(tmp); break;
7021 case 2: gen_sxtb(tmp); break;
7022 case 3: gen_sxth(tmp); break;
7023 case 4: gen_uxtb16(tmp); break;
7024 case 6: gen_uxtb(tmp); break;
7025 case 7: gen_uxth(tmp); break;
7026 default: goto illegal_op;
7028 if (rn != 15) {
7029 tmp2 = load_reg(s, rn);
7030 if ((op1 & 3) == 0) {
7031 gen_add16(tmp, tmp2);
7032 } else {
7033 tcg_gen_add_i32(tmp, tmp, tmp2);
7034 tcg_temp_free_i32(tmp2);
7037 store_reg(s, rd, tmp);
7038 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
7039 /* rev */
7040 tmp = load_reg(s, rm);
7041 if (insn & (1 << 22)) {
7042 if (insn & (1 << 7)) {
7043 gen_revsh(tmp);
7044 } else {
7045 ARCH(6T2);
7046 gen_helper_rbit(tmp, tmp);
7048 } else {
7049 if (insn & (1 << 7))
7050 gen_rev16(tmp);
7051 else
7052 tcg_gen_bswap32_i32(tmp, tmp);
7054 store_reg(s, rd, tmp);
7055 } else {
7056 goto illegal_op;
7058 break;
7059 case 2: /* Multiplies (Type 3). */
7060 tmp = load_reg(s, rm);
7061 tmp2 = load_reg(s, rs);
7062 if (insn & (1 << 20)) {
7063 /* Signed multiply most significant [accumulate].
7064 (SMMUL, SMMLA, SMMLS) */
7065 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7067 if (rd != 15) {
7068 tmp = load_reg(s, rd);
7069 if (insn & (1 << 6)) {
7070 tmp64 = gen_subq_msw(tmp64, tmp);
7071 } else {
7072 tmp64 = gen_addq_msw(tmp64, tmp);
7075 if (insn & (1 << 5)) {
7076 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
7078 tcg_gen_shri_i64(tmp64, tmp64, 32);
7079 tmp = tcg_temp_new_i32();
7080 tcg_gen_trunc_i64_i32(tmp, tmp64);
7081 tcg_temp_free_i64(tmp64);
7082 store_reg(s, rn, tmp);
7083 } else {
7084 if (insn & (1 << 5))
7085 gen_swap_half(tmp2);
7086 gen_smul_dual(tmp, tmp2);
7087 if (insn & (1 << 6)) {
7088 /* This subtraction cannot overflow. */
7089 tcg_gen_sub_i32(tmp, tmp, tmp2);
7090 } else {
7091 /* This addition cannot overflow 32 bits;
7092 * however it may overflow considered as a signed
7093 * operation, in which case we must set the Q flag.
7095 gen_helper_add_setq(tmp, tmp, tmp2);
7097 tcg_temp_free_i32(tmp2);
7098 if (insn & (1 << 22)) {
7099 /* smlald, smlsld */
7100 tmp64 = tcg_temp_new_i64();
7101 tcg_gen_ext_i32_i64(tmp64, tmp);
7102 tcg_temp_free_i32(tmp);
7103 gen_addq(s, tmp64, rd, rn);
7104 gen_storeq_reg(s, rd, rn, tmp64);
7105 tcg_temp_free_i64(tmp64);
7106 } else {
7107 /* smuad, smusd, smlad, smlsd */
7108 if (rd != 15)
7110 tmp2 = load_reg(s, rd);
7111 gen_helper_add_setq(tmp, tmp, tmp2);
7112 tcg_temp_free_i32(tmp2);
7114 store_reg(s, rn, tmp);
7117 break;
7118 case 3:
7119 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
7120 switch (op1) {
7121 case 0: /* Unsigned sum of absolute differences. */
7122 ARCH(6);
7123 tmp = load_reg(s, rm);
7124 tmp2 = load_reg(s, rs);
7125 gen_helper_usad8(tmp, tmp, tmp2);
7126 tcg_temp_free_i32(tmp2);
7127 if (rd != 15) {
7128 tmp2 = load_reg(s, rd);
7129 tcg_gen_add_i32(tmp, tmp, tmp2);
7130 tcg_temp_free_i32(tmp2);
7132 store_reg(s, rn, tmp);
7133 break;
7134 case 0x20: case 0x24: case 0x28: case 0x2c:
7135 /* Bitfield insert/clear. */
7136 ARCH(6T2);
7137 shift = (insn >> 7) & 0x1f;
7138 i = (insn >> 16) & 0x1f;
7139 i = i + 1 - shift;
7140 if (rm == 15) {
7141 tmp = tcg_temp_new_i32();
7142 tcg_gen_movi_i32(tmp, 0);
7143 } else {
7144 tmp = load_reg(s, rm);
7146 if (i != 32) {
7147 tmp2 = load_reg(s, rd);
7148 gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
7149 tcg_temp_free_i32(tmp2);
7151 store_reg(s, rd, tmp);
7152 break;
7153 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
7154 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
7155 ARCH(6T2);
7156 tmp = load_reg(s, rm);
7157 shift = (insn >> 7) & 0x1f;
7158 i = ((insn >> 16) & 0x1f) + 1;
7159 if (shift + i > 32)
7160 goto illegal_op;
7161 if (i < 32) {
7162 if (op1 & 0x20) {
7163 gen_ubfx(tmp, shift, (1u << i) - 1);
7164 } else {
7165 gen_sbfx(tmp, shift, i);
7168 store_reg(s, rd, tmp);
7169 break;
7170 default:
7171 goto illegal_op;
7173 break;
7175 break;
7177 do_ldst:
7178 /* Check for undefined extension instructions
7179 * per the ARM Bible IE:
7180 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
7182 sh = (0xf << 20) | (0xf << 4);
7183 if (op1 == 0x7 && ((insn & sh) == sh))
7185 goto illegal_op;
7187 /* load/store byte/word */
7188 rn = (insn >> 16) & 0xf;
7189 rd = (insn >> 12) & 0xf;
7190 tmp2 = load_reg(s, rn);
7191 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
7192 if (insn & (1 << 24))
7193 gen_add_data_offset(s, insn, tmp2);
7194 if (insn & (1 << 20)) {
7195 /* load */
7196 if (insn & (1 << 22)) {
7197 tmp = gen_ld8u(tmp2, i);
7198 } else {
7199 tmp = gen_ld32(tmp2, i);
7201 } else {
7202 /* store */
7203 tmp = load_reg(s, rd);
7204 if (insn & (1 << 22))
7205 gen_st8(tmp, tmp2, i);
7206 else
7207 gen_st32(tmp, tmp2, i);
7209 if (!(insn & (1 << 24))) {
7210 gen_add_data_offset(s, insn, tmp2);
7211 store_reg(s, rn, tmp2);
7212 } else if (insn & (1 << 21)) {
7213 store_reg(s, rn, tmp2);
7214 } else {
7215 tcg_temp_free_i32(tmp2);
7217 if (insn & (1 << 20)) {
7218 /* Complete the load. */
7219 if (rd == 15)
7220 gen_bx(s, tmp);
7221 else
7222 store_reg(s, rd, tmp);
7224 break;
7225 case 0x08:
7226 case 0x09:
7228 int j, n, user, loaded_base;
7229 TCGv loaded_var;
7230 /* load/store multiple words */
7231 /* XXX: store correct base if write back */
7232 user = 0;
7233 if (insn & (1 << 22)) {
7234 if (IS_USER(s))
7235 goto illegal_op; /* only usable in supervisor mode */
7237 if ((insn & (1 << 15)) == 0)
7238 user = 1;
7240 rn = (insn >> 16) & 0xf;
7241 addr = load_reg(s, rn);
7243 /* compute total size */
7244 loaded_base = 0;
7245 TCGV_UNUSED(loaded_var);
7246 n = 0;
7247 for(i=0;i<16;i++) {
7248 if (insn & (1 << i))
7249 n++;
7251 /* XXX: test invalid n == 0 case ? */
7252 if (insn & (1 << 23)) {
7253 if (insn & (1 << 24)) {
7254 /* pre increment */
7255 tcg_gen_addi_i32(addr, addr, 4);
7256 } else {
7257 /* post increment */
7259 } else {
7260 if (insn & (1 << 24)) {
7261 /* pre decrement */
7262 tcg_gen_addi_i32(addr, addr, -(n * 4));
7263 } else {
7264 /* post decrement */
7265 if (n != 1)
7266 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7269 j = 0;
7270 for(i=0;i<16;i++) {
7271 if (insn & (1 << i)) {
7272 if (insn & (1 << 20)) {
7273 /* load */
7274 tmp = gen_ld32(addr, IS_USER(s));
7275 if (i == 15) {
7276 gen_bx(s, tmp);
7277 } else if (user) {
7278 tmp2 = tcg_const_i32(i);
7279 gen_helper_set_user_reg(tmp2, tmp);
7280 tcg_temp_free_i32(tmp2);
7281 tcg_temp_free_i32(tmp);
7282 } else if (i == rn) {
7283 loaded_var = tmp;
7284 loaded_base = 1;
7285 } else {
7286 store_reg(s, i, tmp);
7288 } else {
7289 /* store */
7290 if (i == 15) {
7291 /* special case: r15 = PC + 8 */
7292 val = (long)s->pc + 4;
7293 tmp = tcg_temp_new_i32();
7294 tcg_gen_movi_i32(tmp, val);
7295 } else if (user) {
7296 tmp = tcg_temp_new_i32();
7297 tmp2 = tcg_const_i32(i);
7298 gen_helper_get_user_reg(tmp, tmp2);
7299 tcg_temp_free_i32(tmp2);
7300 } else {
7301 tmp = load_reg(s, i);
7303 gen_st32(tmp, addr, IS_USER(s));
7305 j++;
7306 /* no need to add after the last transfer */
7307 if (j != n)
7308 tcg_gen_addi_i32(addr, addr, 4);
7311 if (insn & (1 << 21)) {
7312 /* write back */
7313 if (insn & (1 << 23)) {
7314 if (insn & (1 << 24)) {
7315 /* pre increment */
7316 } else {
7317 /* post increment */
7318 tcg_gen_addi_i32(addr, addr, 4);
7320 } else {
7321 if (insn & (1 << 24)) {
7322 /* pre decrement */
7323 if (n != 1)
7324 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7325 } else {
7326 /* post decrement */
7327 tcg_gen_addi_i32(addr, addr, -(n * 4));
7330 store_reg(s, rn, addr);
7331 } else {
7332 tcg_temp_free_i32(addr);
7334 if (loaded_base) {
7335 store_reg(s, rn, loaded_var);
7337 if ((insn & (1 << 22)) && !user) {
7338 /* Restore CPSR from SPSR. */
7339 tmp = load_cpu_field(spsr);
7340 gen_set_cpsr(tmp, 0xffffffff);
7341 tcg_temp_free_i32(tmp);
7342 s->is_jmp = DISAS_UPDATE;
7345 break;
7346 case 0xa:
7347 case 0xb:
7349 int32_t offset;
7351 /* branch (and link) */
7352 val = (int32_t)s->pc;
7353 if (insn & (1 << 24)) {
7354 tmp = tcg_temp_new_i32();
7355 tcg_gen_movi_i32(tmp, val);
7356 store_reg(s, 14, tmp);
7358 offset = (((int32_t)insn << 8) >> 8);
7359 val += (offset << 2) + 4;
7360 gen_jmp(s, val);
7362 break;
7363 case 0xc:
7364 case 0xd:
7365 case 0xe:
7366 /* Coprocessor. */
7367 if (disas_coproc_insn(env, s, insn))
7368 goto illegal_op;
7369 break;
7370 case 0xf:
7371 /* swi */
7372 gen_set_pc_im(s->pc);
7373 s->is_jmp = DISAS_SWI;
7374 break;
7375 default:
7376 illegal_op:
7377 gen_exception_insn(s, 4, EXCP_UDEF);
7378 break;
7383 /* Return true if this is a Thumb-2 logical op. */
7384 static int
7385 thumb2_logic_op(int op)
7387 return (op < 8);
7390 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7391 then set condition code flags based on the result of the operation.
7392 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7393 to the high bit of T1.
7394 Returns zero if the opcode is valid. */
7396 static int
7397 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCGv t0, TCGv t1)
7399 int logic_cc;
7401 logic_cc = 0;
7402 switch (op) {
7403 case 0: /* and */
7404 tcg_gen_and_i32(t0, t0, t1);
7405 logic_cc = conds;
7406 break;
7407 case 1: /* bic */
7408 tcg_gen_andc_i32(t0, t0, t1);
7409 logic_cc = conds;
7410 break;
7411 case 2: /* orr */
7412 tcg_gen_or_i32(t0, t0, t1);
7413 logic_cc = conds;
7414 break;
7415 case 3: /* orn */
7416 tcg_gen_orc_i32(t0, t0, t1);
7417 logic_cc = conds;
7418 break;
7419 case 4: /* eor */
7420 tcg_gen_xor_i32(t0, t0, t1);
7421 logic_cc = conds;
7422 break;
7423 case 8: /* add */
7424 if (conds)
7425 gen_helper_add_cc(t0, t0, t1);
7426 else
7427 tcg_gen_add_i32(t0, t0, t1);
7428 break;
7429 case 10: /* adc */
7430 if (conds)
7431 gen_helper_adc_cc(t0, t0, t1);
7432 else
7433 gen_adc(t0, t1);
7434 break;
7435 case 11: /* sbc */
7436 if (conds)
7437 gen_helper_sbc_cc(t0, t0, t1);
7438 else
7439 gen_sub_carry(t0, t0, t1);
7440 break;
7441 case 13: /* sub */
7442 if (conds)
7443 gen_helper_sub_cc(t0, t0, t1);
7444 else
7445 tcg_gen_sub_i32(t0, t0, t1);
7446 break;
7447 case 14: /* rsb */
7448 if (conds)
7449 gen_helper_sub_cc(t0, t1, t0);
7450 else
7451 tcg_gen_sub_i32(t0, t1, t0);
7452 break;
7453 default: /* 5, 6, 7, 9, 12, 15. */
7454 return 1;
7456 if (logic_cc) {
7457 gen_logic_CC(t0);
7458 if (shifter_out)
7459 gen_set_CF_bit31(t1);
7461 return 0;
7464 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7465 is not legal. */
7466 static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7468 uint32_t insn, imm, shift, offset;
7469 uint32_t rd, rn, rm, rs;
7470 TCGv tmp;
7471 TCGv tmp2;
7472 TCGv tmp3;
7473 TCGv addr;
7474 TCGv_i64 tmp64;
7475 int op;
7476 int shiftop;
7477 int conds;
7478 int logic_cc;
7480 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
7481 || arm_feature (env, ARM_FEATURE_M))) {
7482 /* Thumb-1 cores may need to treat bl and blx as a pair of
7483 16-bit instructions to get correct prefetch abort behavior. */
7484 insn = insn_hw1;
7485 if ((insn & (1 << 12)) == 0) {
7486 /* Second half of blx. */
7487 offset = ((insn & 0x7ff) << 1);
7488 tmp = load_reg(s, 14);
7489 tcg_gen_addi_i32(tmp, tmp, offset);
7490 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
7492 tmp2 = tcg_temp_new_i32();
7493 tcg_gen_movi_i32(tmp2, s->pc | 1);
7494 store_reg(s, 14, tmp2);
7495 gen_bx(s, tmp);
7496 return 0;
7498 if (insn & (1 << 11)) {
7499 /* Second half of bl. */
7500 offset = ((insn & 0x7ff) << 1) | 1;
7501 tmp = load_reg(s, 14);
7502 tcg_gen_addi_i32(tmp, tmp, offset);
7504 tmp2 = tcg_temp_new_i32();
7505 tcg_gen_movi_i32(tmp2, s->pc | 1);
7506 store_reg(s, 14, tmp2);
7507 gen_bx(s, tmp);
7508 return 0;
7510 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
7511 /* Instruction spans a page boundary. Implement it as two
7512 16-bit instructions in case the second half causes an
7513 prefetch abort. */
7514 offset = ((int32_t)insn << 21) >> 9;
7515 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
7516 return 0;
7518 /* Fall through to 32-bit decode. */
7521 insn = lduw_code(s->pc);
7522 s->pc += 2;
7523 insn |= (uint32_t)insn_hw1 << 16;
7525 if ((insn & 0xf800e800) != 0xf000e800) {
7526 ARCH(6T2);
7529 rn = (insn >> 16) & 0xf;
7530 rs = (insn >> 12) & 0xf;
7531 rd = (insn >> 8) & 0xf;
7532 rm = insn & 0xf;
7533 switch ((insn >> 25) & 0xf) {
7534 case 0: case 1: case 2: case 3:
7535 /* 16-bit instructions. Should never happen. */
7536 abort();
7537 case 4:
7538 if (insn & (1 << 22)) {
7539 /* Other load/store, table branch. */
7540 if (insn & 0x01200000) {
7541 /* Load/store doubleword. */
7542 if (rn == 15) {
7543 addr = tcg_temp_new_i32();
7544 tcg_gen_movi_i32(addr, s->pc & ~3);
7545 } else {
7546 addr = load_reg(s, rn);
7548 offset = (insn & 0xff) * 4;
7549 if ((insn & (1 << 23)) == 0)
7550 offset = -offset;
7551 if (insn & (1 << 24)) {
7552 tcg_gen_addi_i32(addr, addr, offset);
7553 offset = 0;
7555 if (insn & (1 << 20)) {
7556 /* ldrd */
7557 tmp = gen_ld32(addr, IS_USER(s));
7558 store_reg(s, rs, tmp);
7559 tcg_gen_addi_i32(addr, addr, 4);
7560 tmp = gen_ld32(addr, IS_USER(s));
7561 store_reg(s, rd, tmp);
7562 } else {
7563 /* strd */
7564 tmp = load_reg(s, rs);
7565 gen_st32(tmp, addr, IS_USER(s));
7566 tcg_gen_addi_i32(addr, addr, 4);
7567 tmp = load_reg(s, rd);
7568 gen_st32(tmp, addr, IS_USER(s));
7570 if (insn & (1 << 21)) {
7571 /* Base writeback. */
7572 if (rn == 15)
7573 goto illegal_op;
7574 tcg_gen_addi_i32(addr, addr, offset - 4);
7575 store_reg(s, rn, addr);
7576 } else {
7577 tcg_temp_free_i32(addr);
7579 } else if ((insn & (1 << 23)) == 0) {
7580 /* Load/store exclusive word. */
7581 addr = tcg_temp_local_new();
7582 load_reg_var(s, addr, rn);
7583 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
7584 if (insn & (1 << 20)) {
7585 gen_load_exclusive(s, rs, 15, addr, 2);
7586 } else {
7587 gen_store_exclusive(s, rd, rs, 15, addr, 2);
7589 tcg_temp_free(addr);
7590 } else if ((insn & (1 << 6)) == 0) {
7591 /* Table Branch. */
7592 if (rn == 15) {
7593 addr = tcg_temp_new_i32();
7594 tcg_gen_movi_i32(addr, s->pc);
7595 } else {
7596 addr = load_reg(s, rn);
7598 tmp = load_reg(s, rm);
7599 tcg_gen_add_i32(addr, addr, tmp);
7600 if (insn & (1 << 4)) {
7601 /* tbh */
7602 tcg_gen_add_i32(addr, addr, tmp);
7603 tcg_temp_free_i32(tmp);
7604 tmp = gen_ld16u(addr, IS_USER(s));
7605 } else { /* tbb */
7606 tcg_temp_free_i32(tmp);
7607 tmp = gen_ld8u(addr, IS_USER(s));
7609 tcg_temp_free_i32(addr);
7610 tcg_gen_shli_i32(tmp, tmp, 1);
7611 tcg_gen_addi_i32(tmp, tmp, s->pc);
7612 store_reg(s, 15, tmp);
7613 } else {
7614 /* Load/store exclusive byte/halfword/doubleword. */
7615 ARCH(7);
7616 op = (insn >> 4) & 0x3;
7617 if (op == 2) {
7618 goto illegal_op;
7620 addr = tcg_temp_local_new();
7621 load_reg_var(s, addr, rn);
7622 if (insn & (1 << 20)) {
7623 gen_load_exclusive(s, rs, rd, addr, op);
7624 } else {
7625 gen_store_exclusive(s, rm, rs, rd, addr, op);
7627 tcg_temp_free(addr);
7629 } else {
7630 /* Load/store multiple, RFE, SRS. */
7631 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
7632 /* Not available in user mode. */
7633 if (IS_USER(s))
7634 goto illegal_op;
7635 if (insn & (1 << 20)) {
7636 /* rfe */
7637 addr = load_reg(s, rn);
7638 if ((insn & (1 << 24)) == 0)
7639 tcg_gen_addi_i32(addr, addr, -8);
7640 /* Load PC into tmp and CPSR into tmp2. */
7641 tmp = gen_ld32(addr, 0);
7642 tcg_gen_addi_i32(addr, addr, 4);
7643 tmp2 = gen_ld32(addr, 0);
7644 if (insn & (1 << 21)) {
7645 /* Base writeback. */
7646 if (insn & (1 << 24)) {
7647 tcg_gen_addi_i32(addr, addr, 4);
7648 } else {
7649 tcg_gen_addi_i32(addr, addr, -4);
7651 store_reg(s, rn, addr);
7652 } else {
7653 tcg_temp_free_i32(addr);
7655 gen_rfe(s, tmp, tmp2);
7656 } else {
7657 /* srs */
7658 op = (insn & 0x1f);
7659 addr = tcg_temp_new_i32();
7660 tmp = tcg_const_i32(op);
7661 gen_helper_get_r13_banked(addr, cpu_env, tmp);
7662 tcg_temp_free_i32(tmp);
7663 if ((insn & (1 << 24)) == 0) {
7664 tcg_gen_addi_i32(addr, addr, -8);
7666 tmp = load_reg(s, 14);
7667 gen_st32(tmp, addr, 0);
7668 tcg_gen_addi_i32(addr, addr, 4);
7669 tmp = tcg_temp_new_i32();
7670 gen_helper_cpsr_read(tmp);
7671 gen_st32(tmp, addr, 0);
7672 if (insn & (1 << 21)) {
7673 if ((insn & (1 << 24)) == 0) {
7674 tcg_gen_addi_i32(addr, addr, -4);
7675 } else {
7676 tcg_gen_addi_i32(addr, addr, 4);
7678 tmp = tcg_const_i32(op);
7679 gen_helper_set_r13_banked(cpu_env, tmp, addr);
7680 tcg_temp_free_i32(tmp);
7681 } else {
7682 tcg_temp_free_i32(addr);
7685 } else {
7686 int i;
7687 /* Load/store multiple. */
7688 addr = load_reg(s, rn);
7689 offset = 0;
7690 for (i = 0; i < 16; i++) {
7691 if (insn & (1 << i))
7692 offset += 4;
7694 if (insn & (1 << 24)) {
7695 tcg_gen_addi_i32(addr, addr, -offset);
7698 for (i = 0; i < 16; i++) {
7699 if ((insn & (1 << i)) == 0)
7700 continue;
7701 if (insn & (1 << 20)) {
7702 /* Load. */
7703 tmp = gen_ld32(addr, IS_USER(s));
7704 if (i == 15) {
7705 gen_bx(s, tmp);
7706 } else {
7707 store_reg(s, i, tmp);
7709 } else {
7710 /* Store. */
7711 tmp = load_reg(s, i);
7712 gen_st32(tmp, addr, IS_USER(s));
7714 tcg_gen_addi_i32(addr, addr, 4);
7716 if (insn & (1 << 21)) {
7717 /* Base register writeback. */
7718 if (insn & (1 << 24)) {
7719 tcg_gen_addi_i32(addr, addr, -offset);
7721 /* Fault if writeback register is in register list. */
7722 if (insn & (1 << rn))
7723 goto illegal_op;
7724 store_reg(s, rn, addr);
7725 } else {
7726 tcg_temp_free_i32(addr);
7730 break;
7731 case 5:
7733 op = (insn >> 21) & 0xf;
7734 if (op == 6) {
7735 /* Halfword pack. */
7736 tmp = load_reg(s, rn);
7737 tmp2 = load_reg(s, rm);
7738 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
7739 if (insn & (1 << 5)) {
7740 /* pkhtb */
7741 if (shift == 0)
7742 shift = 31;
7743 tcg_gen_sari_i32(tmp2, tmp2, shift);
7744 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
7745 tcg_gen_ext16u_i32(tmp2, tmp2);
7746 } else {
7747 /* pkhbt */
7748 if (shift)
7749 tcg_gen_shli_i32(tmp2, tmp2, shift);
7750 tcg_gen_ext16u_i32(tmp, tmp);
7751 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
7753 tcg_gen_or_i32(tmp, tmp, tmp2);
7754 tcg_temp_free_i32(tmp2);
7755 store_reg(s, rd, tmp);
7756 } else {
7757 /* Data processing register constant shift. */
7758 if (rn == 15) {
7759 tmp = tcg_temp_new_i32();
7760 tcg_gen_movi_i32(tmp, 0);
7761 } else {
7762 tmp = load_reg(s, rn);
7764 tmp2 = load_reg(s, rm);
7766 shiftop = (insn >> 4) & 3;
7767 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7768 conds = (insn & (1 << 20)) != 0;
7769 logic_cc = (conds && thumb2_logic_op(op));
7770 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
7771 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
7772 goto illegal_op;
7773 tcg_temp_free_i32(tmp2);
7774 if (rd != 15) {
7775 store_reg(s, rd, tmp);
7776 } else {
7777 tcg_temp_free_i32(tmp);
7780 break;
7781 case 13: /* Misc data processing. */
7782 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
7783 if (op < 4 && (insn & 0xf000) != 0xf000)
7784 goto illegal_op;
7785 switch (op) {
7786 case 0: /* Register controlled shift. */
7787 tmp = load_reg(s, rn);
7788 tmp2 = load_reg(s, rm);
7789 if ((insn & 0x70) != 0)
7790 goto illegal_op;
7791 op = (insn >> 21) & 3;
7792 logic_cc = (insn & (1 << 20)) != 0;
7793 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
7794 if (logic_cc)
7795 gen_logic_CC(tmp);
7796 store_reg_bx(env, s, rd, tmp);
7797 break;
7798 case 1: /* Sign/zero extend. */
7799 tmp = load_reg(s, rm);
7800 shift = (insn >> 4) & 3;
7801 /* ??? In many cases it's not neccessary to do a
7802 rotate, a shift is sufficient. */
7803 if (shift != 0)
7804 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
7805 op = (insn >> 20) & 7;
7806 switch (op) {
7807 case 0: gen_sxth(tmp); break;
7808 case 1: gen_uxth(tmp); break;
7809 case 2: gen_sxtb16(tmp); break;
7810 case 3: gen_uxtb16(tmp); break;
7811 case 4: gen_sxtb(tmp); break;
7812 case 5: gen_uxtb(tmp); break;
7813 default: goto illegal_op;
7815 if (rn != 15) {
7816 tmp2 = load_reg(s, rn);
7817 if ((op >> 1) == 1) {
7818 gen_add16(tmp, tmp2);
7819 } else {
7820 tcg_gen_add_i32(tmp, tmp, tmp2);
7821 tcg_temp_free_i32(tmp2);
7824 store_reg(s, rd, tmp);
7825 break;
7826 case 2: /* SIMD add/subtract. */
7827 op = (insn >> 20) & 7;
7828 shift = (insn >> 4) & 7;
7829 if ((op & 3) == 3 || (shift & 3) == 3)
7830 goto illegal_op;
7831 tmp = load_reg(s, rn);
7832 tmp2 = load_reg(s, rm);
7833 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7834 tcg_temp_free_i32(tmp2);
7835 store_reg(s, rd, tmp);
7836 break;
7837 case 3: /* Other data processing. */
7838 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
7839 if (op < 4) {
7840 /* Saturating add/subtract. */
7841 tmp = load_reg(s, rn);
7842 tmp2 = load_reg(s, rm);
7843 if (op & 1)
7844 gen_helper_double_saturate(tmp, tmp);
7845 if (op & 2)
7846 gen_helper_sub_saturate(tmp, tmp2, tmp);
7847 else
7848 gen_helper_add_saturate(tmp, tmp, tmp2);
7849 tcg_temp_free_i32(tmp2);
7850 } else {
7851 tmp = load_reg(s, rn);
7852 switch (op) {
7853 case 0x0a: /* rbit */
7854 gen_helper_rbit(tmp, tmp);
7855 break;
7856 case 0x08: /* rev */
7857 tcg_gen_bswap32_i32(tmp, tmp);
7858 break;
7859 case 0x09: /* rev16 */
7860 gen_rev16(tmp);
7861 break;
7862 case 0x0b: /* revsh */
7863 gen_revsh(tmp);
7864 break;
7865 case 0x10: /* sel */
7866 tmp2 = load_reg(s, rm);
7867 tmp3 = tcg_temp_new_i32();
7868 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
7869 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7870 tcg_temp_free_i32(tmp3);
7871 tcg_temp_free_i32(tmp2);
7872 break;
7873 case 0x18: /* clz */
7874 gen_helper_clz(tmp, tmp);
7875 break;
7876 default:
7877 goto illegal_op;
7880 store_reg(s, rd, tmp);
7881 break;
7882 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7883 op = (insn >> 4) & 0xf;
7884 tmp = load_reg(s, rn);
7885 tmp2 = load_reg(s, rm);
7886 switch ((insn >> 20) & 7) {
7887 case 0: /* 32 x 32 -> 32 */
7888 tcg_gen_mul_i32(tmp, tmp, tmp2);
7889 tcg_temp_free_i32(tmp2);
7890 if (rs != 15) {
7891 tmp2 = load_reg(s, rs);
7892 if (op)
7893 tcg_gen_sub_i32(tmp, tmp2, tmp);
7894 else
7895 tcg_gen_add_i32(tmp, tmp, tmp2);
7896 tcg_temp_free_i32(tmp2);
7898 break;
7899 case 1: /* 16 x 16 -> 32 */
7900 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7901 tcg_temp_free_i32(tmp2);
7902 if (rs != 15) {
7903 tmp2 = load_reg(s, rs);
7904 gen_helper_add_setq(tmp, tmp, tmp2);
7905 tcg_temp_free_i32(tmp2);
7907 break;
7908 case 2: /* Dual multiply add. */
7909 case 4: /* Dual multiply subtract. */
7910 if (op)
7911 gen_swap_half(tmp2);
7912 gen_smul_dual(tmp, tmp2);
7913 if (insn & (1 << 22)) {
7914 /* This subtraction cannot overflow. */
7915 tcg_gen_sub_i32(tmp, tmp, tmp2);
7916 } else {
7917 /* This addition cannot overflow 32 bits;
7918 * however it may overflow considered as a signed
7919 * operation, in which case we must set the Q flag.
7921 gen_helper_add_setq(tmp, tmp, tmp2);
7923 tcg_temp_free_i32(tmp2);
7924 if (rs != 15)
7926 tmp2 = load_reg(s, rs);
7927 gen_helper_add_setq(tmp, tmp, tmp2);
7928 tcg_temp_free_i32(tmp2);
7930 break;
7931 case 3: /* 32 * 16 -> 32msb */
7932 if (op)
7933 tcg_gen_sari_i32(tmp2, tmp2, 16);
7934 else
7935 gen_sxth(tmp2);
7936 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7937 tcg_gen_shri_i64(tmp64, tmp64, 16);
7938 tmp = tcg_temp_new_i32();
7939 tcg_gen_trunc_i64_i32(tmp, tmp64);
7940 tcg_temp_free_i64(tmp64);
7941 if (rs != 15)
7943 tmp2 = load_reg(s, rs);
7944 gen_helper_add_setq(tmp, tmp, tmp2);
7945 tcg_temp_free_i32(tmp2);
7947 break;
7948 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
7949 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7950 if (rs != 15) {
7951 tmp = load_reg(s, rs);
7952 if (insn & (1 << 20)) {
7953 tmp64 = gen_addq_msw(tmp64, tmp);
7954 } else {
7955 tmp64 = gen_subq_msw(tmp64, tmp);
7958 if (insn & (1 << 4)) {
7959 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
7961 tcg_gen_shri_i64(tmp64, tmp64, 32);
7962 tmp = tcg_temp_new_i32();
7963 tcg_gen_trunc_i64_i32(tmp, tmp64);
7964 tcg_temp_free_i64(tmp64);
7965 break;
7966 case 7: /* Unsigned sum of absolute differences. */
7967 gen_helper_usad8(tmp, tmp, tmp2);
7968 tcg_temp_free_i32(tmp2);
7969 if (rs != 15) {
7970 tmp2 = load_reg(s, rs);
7971 tcg_gen_add_i32(tmp, tmp, tmp2);
7972 tcg_temp_free_i32(tmp2);
7974 break;
7976 store_reg(s, rd, tmp);
7977 break;
7978 case 6: case 7: /* 64-bit multiply, Divide. */
7979 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
7980 tmp = load_reg(s, rn);
7981 tmp2 = load_reg(s, rm);
7982 if ((op & 0x50) == 0x10) {
7983 /* sdiv, udiv */
7984 if (!arm_feature(env, ARM_FEATURE_DIV))
7985 goto illegal_op;
7986 if (op & 0x20)
7987 gen_helper_udiv(tmp, tmp, tmp2);
7988 else
7989 gen_helper_sdiv(tmp, tmp, tmp2);
7990 tcg_temp_free_i32(tmp2);
7991 store_reg(s, rd, tmp);
7992 } else if ((op & 0xe) == 0xc) {
7993 /* Dual multiply accumulate long. */
7994 if (op & 1)
7995 gen_swap_half(tmp2);
7996 gen_smul_dual(tmp, tmp2);
7997 if (op & 0x10) {
7998 tcg_gen_sub_i32(tmp, tmp, tmp2);
7999 } else {
8000 tcg_gen_add_i32(tmp, tmp, tmp2);
8002 tcg_temp_free_i32(tmp2);
8003 /* BUGFIX */
8004 tmp64 = tcg_temp_new_i64();
8005 tcg_gen_ext_i32_i64(tmp64, tmp);
8006 tcg_temp_free_i32(tmp);
8007 gen_addq(s, tmp64, rs, rd);
8008 gen_storeq_reg(s, rs, rd, tmp64);
8009 tcg_temp_free_i64(tmp64);
8010 } else {
8011 if (op & 0x20) {
8012 /* Unsigned 64-bit multiply */
8013 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
8014 } else {
8015 if (op & 8) {
8016 /* smlalxy */
8017 gen_mulxy(tmp, tmp2, op & 2, op & 1);
8018 tcg_temp_free_i32(tmp2);
8019 tmp64 = tcg_temp_new_i64();
8020 tcg_gen_ext_i32_i64(tmp64, tmp);
8021 tcg_temp_free_i32(tmp);
8022 } else {
8023 /* Signed 64-bit multiply */
8024 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8027 if (op & 4) {
8028 /* umaal */
8029 gen_addq_lo(s, tmp64, rs);
8030 gen_addq_lo(s, tmp64, rd);
8031 } else if (op & 0x40) {
8032 /* 64-bit accumulate. */
8033 gen_addq(s, tmp64, rs, rd);
8035 gen_storeq_reg(s, rs, rd, tmp64);
8036 tcg_temp_free_i64(tmp64);
8038 break;
8040 break;
8041 case 6: case 7: case 14: case 15:
8042 /* Coprocessor. */
8043 if (((insn >> 24) & 3) == 3) {
8044 /* Translate into the equivalent ARM encoding. */
8045 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
8046 if (disas_neon_data_insn(env, s, insn))
8047 goto illegal_op;
8048 } else {
8049 if (insn & (1 << 28))
8050 goto illegal_op;
8051 if (disas_coproc_insn (env, s, insn))
8052 goto illegal_op;
8054 break;
8055 case 8: case 9: case 10: case 11:
8056 if (insn & (1 << 15)) {
8057 /* Branches, misc control. */
8058 if (insn & 0x5000) {
8059 /* Unconditional branch. */
8060 /* signextend(hw1[10:0]) -> offset[:12]. */
8061 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
8062 /* hw1[10:0] -> offset[11:1]. */
8063 offset |= (insn & 0x7ff) << 1;
8064 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
8065 offset[24:22] already have the same value because of the
8066 sign extension above. */
8067 offset ^= ((~insn) & (1 << 13)) << 10;
8068 offset ^= ((~insn) & (1 << 11)) << 11;
8070 if (insn & (1 << 14)) {
8071 /* Branch and link. */
8072 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
8075 offset += s->pc;
8076 if (insn & (1 << 12)) {
8077 /* b/bl */
8078 gen_jmp(s, offset);
8079 } else {
8080 /* blx */
8081 offset &= ~(uint32_t)2;
8082 gen_bx_im(s, offset);
8084 } else if (((insn >> 23) & 7) == 7) {
8085 /* Misc control */
8086 if (insn & (1 << 13))
8087 goto illegal_op;
8089 if (insn & (1 << 26)) {
8090 /* Secure monitor call (v6Z) */
8091 goto illegal_op; /* not implemented. */
8092 } else {
8093 op = (insn >> 20) & 7;
8094 switch (op) {
8095 case 0: /* msr cpsr. */
8096 if (IS_M(env)) {
8097 tmp = load_reg(s, rn);
8098 addr = tcg_const_i32(insn & 0xff);
8099 gen_helper_v7m_msr(cpu_env, addr, tmp);
8100 tcg_temp_free_i32(addr);
8101 tcg_temp_free_i32(tmp);
8102 gen_lookup_tb(s);
8103 break;
8105 /* fall through */
8106 case 1: /* msr spsr. */
8107 if (IS_M(env))
8108 goto illegal_op;
8109 tmp = load_reg(s, rn);
8110 if (gen_set_psr(s,
8111 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
8112 op == 1, tmp))
8113 goto illegal_op;
8114 break;
8115 case 2: /* cps, nop-hint. */
8116 if (((insn >> 8) & 7) == 0) {
8117 gen_nop_hint(s, insn & 0xff);
8119 /* Implemented as NOP in user mode. */
8120 if (IS_USER(s))
8121 break;
8122 offset = 0;
8123 imm = 0;
8124 if (insn & (1 << 10)) {
8125 if (insn & (1 << 7))
8126 offset |= CPSR_A;
8127 if (insn & (1 << 6))
8128 offset |= CPSR_I;
8129 if (insn & (1 << 5))
8130 offset |= CPSR_F;
8131 if (insn & (1 << 9))
8132 imm = CPSR_A | CPSR_I | CPSR_F;
8134 if (insn & (1 << 8)) {
8135 offset |= 0x1f;
8136 imm |= (insn & 0x1f);
8138 if (offset) {
8139 gen_set_psr_im(s, offset, 0, imm);
8141 break;
8142 case 3: /* Special control operations. */
8143 ARCH(7);
8144 op = (insn >> 4) & 0xf;
8145 switch (op) {
8146 case 2: /* clrex */
8147 gen_clrex(s);
8148 break;
8149 case 4: /* dsb */
8150 case 5: /* dmb */
8151 case 6: /* isb */
8152 /* These execute as NOPs. */
8153 break;
8154 default:
8155 goto illegal_op;
8157 break;
8158 case 4: /* bxj */
8159 /* Trivial implementation equivalent to bx. */
8160 tmp = load_reg(s, rn);
8161 gen_bx(s, tmp);
8162 break;
8163 case 5: /* Exception return. */
8164 if (IS_USER(s)) {
8165 goto illegal_op;
8167 if (rn != 14 || rd != 15) {
8168 goto illegal_op;
8170 tmp = load_reg(s, rn);
8171 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
8172 gen_exception_return(s, tmp);
8173 break;
8174 case 6: /* mrs cpsr. */
8175 tmp = tcg_temp_new_i32();
8176 if (IS_M(env)) {
8177 addr = tcg_const_i32(insn & 0xff);
8178 gen_helper_v7m_mrs(tmp, cpu_env, addr);
8179 tcg_temp_free_i32(addr);
8180 } else {
8181 gen_helper_cpsr_read(tmp);
8183 store_reg(s, rd, tmp);
8184 break;
8185 case 7: /* mrs spsr. */
8186 /* Not accessible in user mode. */
8187 if (IS_USER(s) || IS_M(env))
8188 goto illegal_op;
8189 tmp = load_cpu_field(spsr);
8190 store_reg(s, rd, tmp);
8191 break;
8194 } else {
8195 /* Conditional branch. */
8196 op = (insn >> 22) & 0xf;
8197 /* Generate a conditional jump to next instruction. */
8198 s->condlabel = gen_new_label();
8199 gen_test_cc(op ^ 1, s->condlabel);
8200 s->condjmp = 1;
8202 /* offset[11:1] = insn[10:0] */
8203 offset = (insn & 0x7ff) << 1;
8204 /* offset[17:12] = insn[21:16]. */
8205 offset |= (insn & 0x003f0000) >> 4;
8206 /* offset[31:20] = insn[26]. */
8207 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
8208 /* offset[18] = insn[13]. */
8209 offset |= (insn & (1 << 13)) << 5;
8210 /* offset[19] = insn[11]. */
8211 offset |= (insn & (1 << 11)) << 8;
8213 /* jump to the offset */
8214 gen_jmp(s, s->pc + offset);
8216 } else {
8217 /* Data processing immediate. */
8218 if (insn & (1 << 25)) {
8219 if (insn & (1 << 24)) {
8220 if (insn & (1 << 20))
8221 goto illegal_op;
8222 /* Bitfield/Saturate. */
8223 op = (insn >> 21) & 7;
8224 imm = insn & 0x1f;
8225 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
8226 if (rn == 15) {
8227 tmp = tcg_temp_new_i32();
8228 tcg_gen_movi_i32(tmp, 0);
8229 } else {
8230 tmp = load_reg(s, rn);
8232 switch (op) {
8233 case 2: /* Signed bitfield extract. */
8234 imm++;
8235 if (shift + imm > 32)
8236 goto illegal_op;
8237 if (imm < 32)
8238 gen_sbfx(tmp, shift, imm);
8239 break;
8240 case 6: /* Unsigned bitfield extract. */
8241 imm++;
8242 if (shift + imm > 32)
8243 goto illegal_op;
8244 if (imm < 32)
8245 gen_ubfx(tmp, shift, (1u << imm) - 1);
8246 break;
8247 case 3: /* Bitfield insert/clear. */
8248 if (imm < shift)
8249 goto illegal_op;
8250 imm = imm + 1 - shift;
8251 if (imm != 32) {
8252 tmp2 = load_reg(s, rd);
8253 gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
8254 tcg_temp_free_i32(tmp2);
8256 break;
8257 case 7:
8258 goto illegal_op;
8259 default: /* Saturate. */
8260 if (shift) {
8261 if (op & 1)
8262 tcg_gen_sari_i32(tmp, tmp, shift);
8263 else
8264 tcg_gen_shli_i32(tmp, tmp, shift);
8266 tmp2 = tcg_const_i32(imm);
8267 if (op & 4) {
8268 /* Unsigned. */
8269 if ((op & 1) && shift == 0)
8270 gen_helper_usat16(tmp, tmp, tmp2);
8271 else
8272 gen_helper_usat(tmp, tmp, tmp2);
8273 } else {
8274 /* Signed. */
8275 if ((op & 1) && shift == 0)
8276 gen_helper_ssat16(tmp, tmp, tmp2);
8277 else
8278 gen_helper_ssat(tmp, tmp, tmp2);
8280 tcg_temp_free_i32(tmp2);
8281 break;
8283 store_reg(s, rd, tmp);
8284 } else {
8285 imm = ((insn & 0x04000000) >> 15)
8286 | ((insn & 0x7000) >> 4) | (insn & 0xff);
8287 if (insn & (1 << 22)) {
8288 /* 16-bit immediate. */
8289 imm |= (insn >> 4) & 0xf000;
8290 if (insn & (1 << 23)) {
8291 /* movt */
8292 tmp = load_reg(s, rd);
8293 tcg_gen_ext16u_i32(tmp, tmp);
8294 tcg_gen_ori_i32(tmp, tmp, imm << 16);
8295 } else {
8296 /* movw */
8297 tmp = tcg_temp_new_i32();
8298 tcg_gen_movi_i32(tmp, imm);
8300 } else {
8301 /* Add/sub 12-bit immediate. */
8302 if (rn == 15) {
8303 offset = s->pc & ~(uint32_t)3;
8304 if (insn & (1 << 23))
8305 offset -= imm;
8306 else
8307 offset += imm;
8308 tmp = tcg_temp_new_i32();
8309 tcg_gen_movi_i32(tmp, offset);
8310 } else {
8311 tmp = load_reg(s, rn);
8312 if (insn & (1 << 23))
8313 tcg_gen_subi_i32(tmp, tmp, imm);
8314 else
8315 tcg_gen_addi_i32(tmp, tmp, imm);
8318 store_reg(s, rd, tmp);
8320 } else {
8321 int shifter_out = 0;
8322 /* modified 12-bit immediate. */
8323 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
8324 imm = (insn & 0xff);
8325 switch (shift) {
8326 case 0: /* XY */
8327 /* Nothing to do. */
8328 break;
8329 case 1: /* 00XY00XY */
8330 imm |= imm << 16;
8331 break;
8332 case 2: /* XY00XY00 */
8333 imm |= imm << 16;
8334 imm <<= 8;
8335 break;
8336 case 3: /* XYXYXYXY */
8337 imm |= imm << 16;
8338 imm |= imm << 8;
8339 break;
8340 default: /* Rotated constant. */
8341 shift = (shift << 1) | (imm >> 7);
8342 imm |= 0x80;
8343 imm = imm << (32 - shift);
8344 shifter_out = 1;
8345 break;
8347 tmp2 = tcg_temp_new_i32();
8348 tcg_gen_movi_i32(tmp2, imm);
8349 rn = (insn >> 16) & 0xf;
8350 if (rn == 15) {
8351 tmp = tcg_temp_new_i32();
8352 tcg_gen_movi_i32(tmp, 0);
8353 } else {
8354 tmp = load_reg(s, rn);
8356 op = (insn >> 21) & 0xf;
8357 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
8358 shifter_out, tmp, tmp2))
8359 goto illegal_op;
8360 tcg_temp_free_i32(tmp2);
8361 rd = (insn >> 8) & 0xf;
8362 if (rd != 15) {
8363 store_reg(s, rd, tmp);
8364 } else {
8365 tcg_temp_free_i32(tmp);
8369 break;
8370 case 12: /* Load/store single data item. */
8372 int postinc = 0;
8373 int writeback = 0;
8374 int user;
8375 if ((insn & 0x01100000) == 0x01000000) {
8376 if (disas_neon_ls_insn(env, s, insn))
8377 goto illegal_op;
8378 break;
8380 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
8381 if (rs == 15) {
8382 if (!(insn & (1 << 20))) {
8383 goto illegal_op;
8385 if (op != 2) {
8386 /* Byte or halfword load space with dest == r15 : memory hints.
8387 * Catch them early so we don't emit pointless addressing code.
8388 * This space is a mix of:
8389 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
8390 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
8391 * cores)
8392 * unallocated hints, which must be treated as NOPs
8393 * UNPREDICTABLE space, which we NOP or UNDEF depending on
8394 * which is easiest for the decoding logic
8395 * Some space which must UNDEF
8397 int op1 = (insn >> 23) & 3;
8398 int op2 = (insn >> 6) & 0x3f;
8399 if (op & 2) {
8400 goto illegal_op;
8402 if (rn == 15) {
8403 /* UNPREDICTABLE or unallocated hint */
8404 return 0;
8406 if (op1 & 1) {
8407 return 0; /* PLD* or unallocated hint */
8409 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
8410 return 0; /* PLD* or unallocated hint */
8412 /* UNDEF space, or an UNPREDICTABLE */
8413 return 1;
8416 user = IS_USER(s);
8417 if (rn == 15) {
8418 addr = tcg_temp_new_i32();
8419 /* PC relative. */
8420 /* s->pc has already been incremented by 4. */
8421 imm = s->pc & 0xfffffffc;
8422 if (insn & (1 << 23))
8423 imm += insn & 0xfff;
8424 else
8425 imm -= insn & 0xfff;
8426 tcg_gen_movi_i32(addr, imm);
8427 } else {
8428 addr = load_reg(s, rn);
8429 if (insn & (1 << 23)) {
8430 /* Positive offset. */
8431 imm = insn & 0xfff;
8432 tcg_gen_addi_i32(addr, addr, imm);
8433 } else {
8434 imm = insn & 0xff;
8435 switch ((insn >> 8) & 0xf) {
8436 case 0x0: /* Shifted Register. */
8437 shift = (insn >> 4) & 0xf;
8438 if (shift > 3) {
8439 tcg_temp_free_i32(addr);
8440 goto illegal_op;
8442 tmp = load_reg(s, rm);
8443 if (shift)
8444 tcg_gen_shli_i32(tmp, tmp, shift);
8445 tcg_gen_add_i32(addr, addr, tmp);
8446 tcg_temp_free_i32(tmp);
8447 break;
8448 case 0xc: /* Negative offset. */
8449 tcg_gen_addi_i32(addr, addr, -imm);
8450 break;
8451 case 0xe: /* User privilege. */
8452 tcg_gen_addi_i32(addr, addr, imm);
8453 user = 1;
8454 break;
8455 case 0x9: /* Post-decrement. */
8456 imm = -imm;
8457 /* Fall through. */
8458 case 0xb: /* Post-increment. */
8459 postinc = 1;
8460 writeback = 1;
8461 break;
8462 case 0xd: /* Pre-decrement. */
8463 imm = -imm;
8464 /* Fall through. */
8465 case 0xf: /* Pre-increment. */
8466 tcg_gen_addi_i32(addr, addr, imm);
8467 writeback = 1;
8468 break;
8469 default:
8470 tcg_temp_free_i32(addr);
8471 goto illegal_op;
8475 if (insn & (1 << 20)) {
8476 /* Load. */
8477 switch (op) {
8478 case 0: tmp = gen_ld8u(addr, user); break;
8479 case 4: tmp = gen_ld8s(addr, user); break;
8480 case 1: tmp = gen_ld16u(addr, user); break;
8481 case 5: tmp = gen_ld16s(addr, user); break;
8482 case 2: tmp = gen_ld32(addr, user); break;
8483 default:
8484 tcg_temp_free_i32(addr);
8485 goto illegal_op;
8487 if (rs == 15) {
8488 gen_bx(s, tmp);
8489 } else {
8490 store_reg(s, rs, tmp);
8492 } else {
8493 /* Store. */
8494 tmp = load_reg(s, rs);
8495 switch (op) {
8496 case 0: gen_st8(tmp, addr, user); break;
8497 case 1: gen_st16(tmp, addr, user); break;
8498 case 2: gen_st32(tmp, addr, user); break;
8499 default:
8500 tcg_temp_free_i32(addr);
8501 goto illegal_op;
8504 if (postinc)
8505 tcg_gen_addi_i32(addr, addr, imm);
8506 if (writeback) {
8507 store_reg(s, rn, addr);
8508 } else {
8509 tcg_temp_free_i32(addr);
8512 break;
8513 default:
8514 goto illegal_op;
8516 return 0;
8517 illegal_op:
8518 return 1;
8521 static void disas_thumb_insn(CPUState *env, DisasContext *s)
8523 uint32_t val, insn, op, rm, rn, rd, shift, cond;
8524 int32_t offset;
8525 int i;
8526 TCGv tmp;
8527 TCGv tmp2;
8528 TCGv addr;
8530 if (s->condexec_mask) {
8531 cond = s->condexec_cond;
8532 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
8533 s->condlabel = gen_new_label();
8534 gen_test_cc(cond ^ 1, s->condlabel);
8535 s->condjmp = 1;
8539 insn = lduw_code(s->pc);
8540 s->pc += 2;
8542 switch (insn >> 12) {
8543 case 0: case 1:
8545 rd = insn & 7;
8546 op = (insn >> 11) & 3;
8547 if (op == 3) {
8548 /* add/subtract */
8549 rn = (insn >> 3) & 7;
8550 tmp = load_reg(s, rn);
8551 if (insn & (1 << 10)) {
8552 /* immediate */
8553 tmp2 = tcg_temp_new_i32();
8554 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
8555 } else {
8556 /* reg */
8557 rm = (insn >> 6) & 7;
8558 tmp2 = load_reg(s, rm);
8560 if (insn & (1 << 9)) {
8561 if (s->condexec_mask)
8562 tcg_gen_sub_i32(tmp, tmp, tmp2);
8563 else
8564 gen_helper_sub_cc(tmp, tmp, tmp2);
8565 } else {
8566 if (s->condexec_mask)
8567 tcg_gen_add_i32(tmp, tmp, tmp2);
8568 else
8569 gen_helper_add_cc(tmp, tmp, tmp2);
8571 tcg_temp_free_i32(tmp2);
8572 store_reg(s, rd, tmp);
8573 } else {
8574 /* shift immediate */
8575 rm = (insn >> 3) & 7;
8576 shift = (insn >> 6) & 0x1f;
8577 tmp = load_reg(s, rm);
8578 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
8579 if (!s->condexec_mask)
8580 gen_logic_CC(tmp);
8581 store_reg(s, rd, tmp);
8583 break;
8584 case 2: case 3:
8585 /* arithmetic large immediate */
8586 op = (insn >> 11) & 3;
8587 rd = (insn >> 8) & 0x7;
8588 if (op == 0) { /* mov */
8589 tmp = tcg_temp_new_i32();
8590 tcg_gen_movi_i32(tmp, insn & 0xff);
8591 if (!s->condexec_mask)
8592 gen_logic_CC(tmp);
8593 store_reg(s, rd, tmp);
8594 } else {
8595 tmp = load_reg(s, rd);
8596 tmp2 = tcg_temp_new_i32();
8597 tcg_gen_movi_i32(tmp2, insn & 0xff);
8598 switch (op) {
8599 case 1: /* cmp */
8600 gen_helper_sub_cc(tmp, tmp, tmp2);
8601 tcg_temp_free_i32(tmp);
8602 tcg_temp_free_i32(tmp2);
8603 break;
8604 case 2: /* add */
8605 if (s->condexec_mask)
8606 tcg_gen_add_i32(tmp, tmp, tmp2);
8607 else
8608 gen_helper_add_cc(tmp, tmp, tmp2);
8609 tcg_temp_free_i32(tmp2);
8610 store_reg(s, rd, tmp);
8611 break;
8612 case 3: /* sub */
8613 if (s->condexec_mask)
8614 tcg_gen_sub_i32(tmp, tmp, tmp2);
8615 else
8616 gen_helper_sub_cc(tmp, tmp, tmp2);
8617 tcg_temp_free_i32(tmp2);
8618 store_reg(s, rd, tmp);
8619 break;
8622 break;
8623 case 4:
8624 if (insn & (1 << 11)) {
8625 rd = (insn >> 8) & 7;
8626 /* load pc-relative. Bit 1 of PC is ignored. */
8627 val = s->pc + 2 + ((insn & 0xff) * 4);
8628 val &= ~(uint32_t)2;
8629 addr = tcg_temp_new_i32();
8630 tcg_gen_movi_i32(addr, val);
8631 tmp = gen_ld32(addr, IS_USER(s));
8632 tcg_temp_free_i32(addr);
8633 store_reg(s, rd, tmp);
8634 break;
8636 if (insn & (1 << 10)) {
8637 /* data processing extended or blx */
8638 rd = (insn & 7) | ((insn >> 4) & 8);
8639 rm = (insn >> 3) & 0xf;
8640 op = (insn >> 8) & 3;
8641 switch (op) {
8642 case 0: /* add */
8643 tmp = load_reg(s, rd);
8644 tmp2 = load_reg(s, rm);
8645 tcg_gen_add_i32(tmp, tmp, tmp2);
8646 tcg_temp_free_i32(tmp2);
8647 store_reg(s, rd, tmp);
8648 break;
8649 case 1: /* cmp */
8650 tmp = load_reg(s, rd);
8651 tmp2 = load_reg(s, rm);
8652 gen_helper_sub_cc(tmp, tmp, tmp2);
8653 tcg_temp_free_i32(tmp2);
8654 tcg_temp_free_i32(tmp);
8655 break;
8656 case 2: /* mov/cpy */
8657 tmp = load_reg(s, rm);
8658 store_reg(s, rd, tmp);
8659 break;
8660 case 3:/* branch [and link] exchange thumb register */
8661 tmp = load_reg(s, rm);
8662 if (insn & (1 << 7)) {
8663 val = (uint32_t)s->pc | 1;
8664 tmp2 = tcg_temp_new_i32();
8665 tcg_gen_movi_i32(tmp2, val);
8666 store_reg(s, 14, tmp2);
8668 gen_bx(s, tmp);
8669 break;
8671 break;
8674 /* data processing register */
8675 rd = insn & 7;
8676 rm = (insn >> 3) & 7;
8677 op = (insn >> 6) & 0xf;
8678 if (op == 2 || op == 3 || op == 4 || op == 7) {
8679 /* the shift/rotate ops want the operands backwards */
8680 val = rm;
8681 rm = rd;
8682 rd = val;
8683 val = 1;
8684 } else {
8685 val = 0;
8688 if (op == 9) { /* neg */
8689 tmp = tcg_temp_new_i32();
8690 tcg_gen_movi_i32(tmp, 0);
8691 } else if (op != 0xf) { /* mvn doesn't read its first operand */
8692 tmp = load_reg(s, rd);
8693 } else {
8694 TCGV_UNUSED(tmp);
8697 tmp2 = load_reg(s, rm);
8698 switch (op) {
8699 case 0x0: /* and */
8700 tcg_gen_and_i32(tmp, tmp, tmp2);
8701 if (!s->condexec_mask)
8702 gen_logic_CC(tmp);
8703 break;
8704 case 0x1: /* eor */
8705 tcg_gen_xor_i32(tmp, tmp, tmp2);
8706 if (!s->condexec_mask)
8707 gen_logic_CC(tmp);
8708 break;
8709 case 0x2: /* lsl */
8710 if (s->condexec_mask) {
8711 gen_helper_shl(tmp2, tmp2, tmp);
8712 } else {
8713 gen_helper_shl_cc(tmp2, tmp2, tmp);
8714 gen_logic_CC(tmp2);
8716 break;
8717 case 0x3: /* lsr */
8718 if (s->condexec_mask) {
8719 gen_helper_shr(tmp2, tmp2, tmp);
8720 } else {
8721 gen_helper_shr_cc(tmp2, tmp2, tmp);
8722 gen_logic_CC(tmp2);
8724 break;
8725 case 0x4: /* asr */
8726 if (s->condexec_mask) {
8727 gen_helper_sar(tmp2, tmp2, tmp);
8728 } else {
8729 gen_helper_sar_cc(tmp2, tmp2, tmp);
8730 gen_logic_CC(tmp2);
8732 break;
8733 case 0x5: /* adc */
8734 if (s->condexec_mask)
8735 gen_adc(tmp, tmp2);
8736 else
8737 gen_helper_adc_cc(tmp, tmp, tmp2);
8738 break;
8739 case 0x6: /* sbc */
8740 if (s->condexec_mask)
8741 gen_sub_carry(tmp, tmp, tmp2);
8742 else
8743 gen_helper_sbc_cc(tmp, tmp, tmp2);
8744 break;
8745 case 0x7: /* ror */
8746 if (s->condexec_mask) {
8747 tcg_gen_andi_i32(tmp, tmp, 0x1f);
8748 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
8749 } else {
8750 gen_helper_ror_cc(tmp2, tmp2, tmp);
8751 gen_logic_CC(tmp2);
8753 break;
8754 case 0x8: /* tst */
8755 tcg_gen_and_i32(tmp, tmp, tmp2);
8756 gen_logic_CC(tmp);
8757 rd = 16;
8758 break;
8759 case 0x9: /* neg */
8760 if (s->condexec_mask)
8761 tcg_gen_neg_i32(tmp, tmp2);
8762 else
8763 gen_helper_sub_cc(tmp, tmp, tmp2);
8764 break;
8765 case 0xa: /* cmp */
8766 gen_helper_sub_cc(tmp, tmp, tmp2);
8767 rd = 16;
8768 break;
8769 case 0xb: /* cmn */
8770 gen_helper_add_cc(tmp, tmp, tmp2);
8771 rd = 16;
8772 break;
8773 case 0xc: /* orr */
8774 tcg_gen_or_i32(tmp, tmp, tmp2);
8775 if (!s->condexec_mask)
8776 gen_logic_CC(tmp);
8777 break;
8778 case 0xd: /* mul */
8779 tcg_gen_mul_i32(tmp, tmp, tmp2);
8780 if (!s->condexec_mask)
8781 gen_logic_CC(tmp);
8782 break;
8783 case 0xe: /* bic */
8784 tcg_gen_andc_i32(tmp, tmp, tmp2);
8785 if (!s->condexec_mask)
8786 gen_logic_CC(tmp);
8787 break;
8788 case 0xf: /* mvn */
8789 tcg_gen_not_i32(tmp2, tmp2);
8790 if (!s->condexec_mask)
8791 gen_logic_CC(tmp2);
8792 val = 1;
8793 rm = rd;
8794 break;
8796 if (rd != 16) {
8797 if (val) {
8798 store_reg(s, rm, tmp2);
8799 if (op != 0xf)
8800 tcg_temp_free_i32(tmp);
8801 } else {
8802 store_reg(s, rd, tmp);
8803 tcg_temp_free_i32(tmp2);
8805 } else {
8806 tcg_temp_free_i32(tmp);
8807 tcg_temp_free_i32(tmp2);
8809 break;
8811 case 5:
8812 /* load/store register offset. */
8813 rd = insn & 7;
8814 rn = (insn >> 3) & 7;
8815 rm = (insn >> 6) & 7;
8816 op = (insn >> 9) & 7;
8817 addr = load_reg(s, rn);
8818 tmp = load_reg(s, rm);
8819 tcg_gen_add_i32(addr, addr, tmp);
8820 tcg_temp_free_i32(tmp);
8822 if (op < 3) /* store */
8823 tmp = load_reg(s, rd);
8825 switch (op) {
8826 case 0: /* str */
8827 gen_st32(tmp, addr, IS_USER(s));
8828 break;
8829 case 1: /* strh */
8830 gen_st16(tmp, addr, IS_USER(s));
8831 break;
8832 case 2: /* strb */
8833 gen_st8(tmp, addr, IS_USER(s));
8834 break;
8835 case 3: /* ldrsb */
8836 tmp = gen_ld8s(addr, IS_USER(s));
8837 break;
8838 case 4: /* ldr */
8839 tmp = gen_ld32(addr, IS_USER(s));
8840 break;
8841 case 5: /* ldrh */
8842 tmp = gen_ld16u(addr, IS_USER(s));
8843 break;
8844 case 6: /* ldrb */
8845 tmp = gen_ld8u(addr, IS_USER(s));
8846 break;
8847 case 7: /* ldrsh */
8848 tmp = gen_ld16s(addr, IS_USER(s));
8849 break;
8851 if (op >= 3) /* load */
8852 store_reg(s, rd, tmp);
8853 tcg_temp_free_i32(addr);
8854 break;
8856 case 6:
8857 /* load/store word immediate offset */
8858 rd = insn & 7;
8859 rn = (insn >> 3) & 7;
8860 addr = load_reg(s, rn);
8861 val = (insn >> 4) & 0x7c;
8862 tcg_gen_addi_i32(addr, addr, val);
8864 if (insn & (1 << 11)) {
8865 /* load */
8866 tmp = gen_ld32(addr, IS_USER(s));
8867 store_reg(s, rd, tmp);
8868 } else {
8869 /* store */
8870 tmp = load_reg(s, rd);
8871 gen_st32(tmp, addr, IS_USER(s));
8873 tcg_temp_free_i32(addr);
8874 break;
8876 case 7:
8877 /* load/store byte immediate offset */
8878 rd = insn & 7;
8879 rn = (insn >> 3) & 7;
8880 addr = load_reg(s, rn);
8881 val = (insn >> 6) & 0x1f;
8882 tcg_gen_addi_i32(addr, addr, val);
8884 if (insn & (1 << 11)) {
8885 /* load */
8886 tmp = gen_ld8u(addr, IS_USER(s));
8887 store_reg(s, rd, tmp);
8888 } else {
8889 /* store */
8890 tmp = load_reg(s, rd);
8891 gen_st8(tmp, addr, IS_USER(s));
8893 tcg_temp_free_i32(addr);
8894 break;
8896 case 8:
8897 /* load/store halfword immediate offset */
8898 rd = insn & 7;
8899 rn = (insn >> 3) & 7;
8900 addr = load_reg(s, rn);
8901 val = (insn >> 5) & 0x3e;
8902 tcg_gen_addi_i32(addr, addr, val);
8904 if (insn & (1 << 11)) {
8905 /* load */
8906 tmp = gen_ld16u(addr, IS_USER(s));
8907 store_reg(s, rd, tmp);
8908 } else {
8909 /* store */
8910 tmp = load_reg(s, rd);
8911 gen_st16(tmp, addr, IS_USER(s));
8913 tcg_temp_free_i32(addr);
8914 break;
8916 case 9:
8917 /* load/store from stack */
8918 rd = (insn >> 8) & 7;
8919 addr = load_reg(s, 13);
8920 val = (insn & 0xff) * 4;
8921 tcg_gen_addi_i32(addr, addr, val);
8923 if (insn & (1 << 11)) {
8924 /* load */
8925 tmp = gen_ld32(addr, IS_USER(s));
8926 store_reg(s, rd, tmp);
8927 } else {
8928 /* store */
8929 tmp = load_reg(s, rd);
8930 gen_st32(tmp, addr, IS_USER(s));
8932 tcg_temp_free_i32(addr);
8933 break;
8935 case 10:
8936 /* add to high reg */
8937 rd = (insn >> 8) & 7;
8938 if (insn & (1 << 11)) {
8939 /* SP */
8940 tmp = load_reg(s, 13);
8941 } else {
8942 /* PC. bit 1 is ignored. */
8943 tmp = tcg_temp_new_i32();
8944 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
8946 val = (insn & 0xff) * 4;
8947 tcg_gen_addi_i32(tmp, tmp, val);
8948 store_reg(s, rd, tmp);
8949 break;
8951 case 11:
8952 /* misc */
8953 op = (insn >> 8) & 0xf;
8954 switch (op) {
8955 case 0:
8956 /* adjust stack pointer */
8957 tmp = load_reg(s, 13);
8958 val = (insn & 0x7f) * 4;
8959 if (insn & (1 << 7))
8960 val = -(int32_t)val;
8961 tcg_gen_addi_i32(tmp, tmp, val);
8962 store_reg(s, 13, tmp);
8963 break;
8965 case 2: /* sign/zero extend. */
8966 ARCH(6);
8967 rd = insn & 7;
8968 rm = (insn >> 3) & 7;
8969 tmp = load_reg(s, rm);
8970 switch ((insn >> 6) & 3) {
8971 case 0: gen_sxth(tmp); break;
8972 case 1: gen_sxtb(tmp); break;
8973 case 2: gen_uxth(tmp); break;
8974 case 3: gen_uxtb(tmp); break;
8976 store_reg(s, rd, tmp);
8977 break;
8978 case 4: case 5: case 0xc: case 0xd:
8979 /* push/pop */
8980 addr = load_reg(s, 13);
8981 if (insn & (1 << 8))
8982 offset = 4;
8983 else
8984 offset = 0;
8985 for (i = 0; i < 8; i++) {
8986 if (insn & (1 << i))
8987 offset += 4;
8989 if ((insn & (1 << 11)) == 0) {
8990 tcg_gen_addi_i32(addr, addr, -offset);
8992 for (i = 0; i < 8; i++) {
8993 if (insn & (1 << i)) {
8994 if (insn & (1 << 11)) {
8995 /* pop */
8996 tmp = gen_ld32(addr, IS_USER(s));
8997 store_reg(s, i, tmp);
8998 } else {
8999 /* push */
9000 tmp = load_reg(s, i);
9001 gen_st32(tmp, addr, IS_USER(s));
9003 /* advance to the next address. */
9004 tcg_gen_addi_i32(addr, addr, 4);
9007 TCGV_UNUSED(tmp);
9008 if (insn & (1 << 8)) {
9009 if (insn & (1 << 11)) {
9010 /* pop pc */
9011 tmp = gen_ld32(addr, IS_USER(s));
9012 /* don't set the pc until the rest of the instruction
9013 has completed */
9014 } else {
9015 /* push lr */
9016 tmp = load_reg(s, 14);
9017 gen_st32(tmp, addr, IS_USER(s));
9019 tcg_gen_addi_i32(addr, addr, 4);
9021 if ((insn & (1 << 11)) == 0) {
9022 tcg_gen_addi_i32(addr, addr, -offset);
9024 /* write back the new stack pointer */
9025 store_reg(s, 13, addr);
9026 /* set the new PC value */
9027 if ((insn & 0x0900) == 0x0900)
9028 gen_bx(s, tmp);
9029 break;
9031 case 1: case 3: case 9: case 11: /* czb */
9032 rm = insn & 7;
9033 tmp = load_reg(s, rm);
9034 s->condlabel = gen_new_label();
9035 s->condjmp = 1;
9036 if (insn & (1 << 11))
9037 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
9038 else
9039 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
9040 tcg_temp_free_i32(tmp);
9041 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
9042 val = (uint32_t)s->pc + 2;
9043 val += offset;
9044 gen_jmp(s, val);
9045 break;
9047 case 15: /* IT, nop-hint. */
9048 if ((insn & 0xf) == 0) {
9049 gen_nop_hint(s, (insn >> 4) & 0xf);
9050 break;
9052 /* If Then. */
9053 s->condexec_cond = (insn >> 4) & 0xe;
9054 s->condexec_mask = insn & 0x1f;
9055 /* No actual code generated for this insn, just setup state. */
9056 break;
9058 case 0xe: /* bkpt */
9059 gen_exception_insn(s, 2, EXCP_BKPT);
9060 break;
9062 case 0xa: /* rev */
9063 ARCH(6);
9064 rn = (insn >> 3) & 0x7;
9065 rd = insn & 0x7;
9066 tmp = load_reg(s, rn);
9067 switch ((insn >> 6) & 3) {
9068 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
9069 case 1: gen_rev16(tmp); break;
9070 case 3: gen_revsh(tmp); break;
9071 default: goto illegal_op;
9073 store_reg(s, rd, tmp);
9074 break;
9076 case 6: /* cps */
9077 ARCH(6);
9078 if (IS_USER(s))
9079 break;
9080 if (IS_M(env)) {
9081 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
9082 /* PRIMASK */
9083 if (insn & 1) {
9084 addr = tcg_const_i32(16);
9085 gen_helper_v7m_msr(cpu_env, addr, tmp);
9086 tcg_temp_free_i32(addr);
9088 /* FAULTMASK */
9089 if (insn & 2) {
9090 addr = tcg_const_i32(17);
9091 gen_helper_v7m_msr(cpu_env, addr, tmp);
9092 tcg_temp_free_i32(addr);
9094 tcg_temp_free_i32(tmp);
9095 gen_lookup_tb(s);
9096 } else {
9097 if (insn & (1 << 4))
9098 shift = CPSR_A | CPSR_I | CPSR_F;
9099 else
9100 shift = 0;
9101 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
9103 break;
9105 default:
9106 goto undef;
9108 break;
9110 case 12:
9111 /* load/store multiple */
9112 rn = (insn >> 8) & 0x7;
9113 addr = load_reg(s, rn);
9114 for (i = 0; i < 8; i++) {
9115 if (insn & (1 << i)) {
9116 if (insn & (1 << 11)) {
9117 /* load */
9118 tmp = gen_ld32(addr, IS_USER(s));
9119 store_reg(s, i, tmp);
9120 } else {
9121 /* store */
9122 tmp = load_reg(s, i);
9123 gen_st32(tmp, addr, IS_USER(s));
9125 /* advance to the next address */
9126 tcg_gen_addi_i32(addr, addr, 4);
9129 /* Base register writeback. */
9130 if ((insn & (1 << rn)) == 0) {
9131 store_reg(s, rn, addr);
9132 } else {
9133 tcg_temp_free_i32(addr);
9135 break;
9137 case 13:
9138 /* conditional branch or swi */
9139 cond = (insn >> 8) & 0xf;
9140 if (cond == 0xe)
9141 goto undef;
9143 if (cond == 0xf) {
9144 /* swi */
9145 gen_set_pc_im(s->pc);
9146 s->is_jmp = DISAS_SWI;
9147 break;
9149 /* generate a conditional jump to next instruction */
9150 s->condlabel = gen_new_label();
9151 gen_test_cc(cond ^ 1, s->condlabel);
9152 s->condjmp = 1;
9154 /* jump to the offset */
9155 val = (uint32_t)s->pc + 2;
9156 offset = ((int32_t)insn << 24) >> 24;
9157 val += offset << 1;
9158 gen_jmp(s, val);
9159 break;
9161 case 14:
9162 if (insn & (1 << 11)) {
9163 if (disas_thumb2_insn(env, s, insn))
9164 goto undef32;
9165 break;
9167 /* unconditional branch */
9168 val = (uint32_t)s->pc;
9169 offset = ((int32_t)insn << 21) >> 21;
9170 val += (offset << 1) + 2;
9171 gen_jmp(s, val);
9172 break;
9174 case 15:
9175 if (disas_thumb2_insn(env, s, insn))
9176 goto undef32;
9177 break;
9179 return;
9180 undef32:
9181 gen_exception_insn(s, 4, EXCP_UDEF);
9182 return;
9183 illegal_op:
9184 undef:
9185 gen_exception_insn(s, 2, EXCP_UDEF);
9188 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
9189 basic block 'tb'. If search_pc is TRUE, also generate PC
9190 information for each intermediate instruction. */
9191 static inline void gen_intermediate_code_internal(CPUState *env,
9192 TranslationBlock *tb,
9193 int search_pc)
9195 DisasContext dc1, *dc = &dc1;
9196 CPUBreakpoint *bp;
9197 uint16_t *gen_opc_end;
9198 int j, lj;
9199 target_ulong pc_start;
9200 uint32_t next_page_start;
9201 int num_insns;
9202 int max_insns;
9204 /* generate intermediate code */
9205 pc_start = tb->pc;
9207 dc->tb = tb;
9209 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
9211 dc->is_jmp = DISAS_NEXT;
9212 dc->pc = pc_start;
9213 dc->singlestep_enabled = env->singlestep_enabled;
9214 dc->condjmp = 0;
9215 dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
9216 dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
9217 dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
9218 #if !defined(CONFIG_USER_ONLY)
9219 dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
9220 #endif
9221 dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
9222 dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
9223 dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
9224 cpu_F0s = tcg_temp_new_i32();
9225 cpu_F1s = tcg_temp_new_i32();
9226 cpu_F0d = tcg_temp_new_i64();
9227 cpu_F1d = tcg_temp_new_i64();
9228 cpu_V0 = cpu_F0d;
9229 cpu_V1 = cpu_F1d;
9230 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
9231 cpu_M0 = tcg_temp_new_i64();
9232 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
9233 lj = -1;
9234 num_insns = 0;
9235 max_insns = tb->cflags & CF_COUNT_MASK;
9236 if (max_insns == 0)
9237 max_insns = CF_COUNT_MASK;
9239 gen_icount_start();
9241 tcg_clear_temp_count();
9243 /* A note on handling of the condexec (IT) bits:
9245 * We want to avoid the overhead of having to write the updated condexec
9246 * bits back to the CPUState for every instruction in an IT block. So:
9247 * (1) if the condexec bits are not already zero then we write
9248 * zero back into the CPUState now. This avoids complications trying
9249 * to do it at the end of the block. (For example if we don't do this
9250 * it's hard to identify whether we can safely skip writing condexec
9251 * at the end of the TB, which we definitely want to do for the case
9252 * where a TB doesn't do anything with the IT state at all.)
9253 * (2) if we are going to leave the TB then we call gen_set_condexec()
9254 * which will write the correct value into CPUState if zero is wrong.
9255 * This is done both for leaving the TB at the end, and for leaving
9256 * it because of an exception we know will happen, which is done in
9257 * gen_exception_insn(). The latter is necessary because we need to
9258 * leave the TB with the PC/IT state just prior to execution of the
9259 * instruction which caused the exception.
9260 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
9261 * then the CPUState will be wrong and we need to reset it.
9262 * This is handled in the same way as restoration of the
9263 * PC in these situations: we will be called again with search_pc=1
9264 * and generate a mapping of the condexec bits for each PC in
9265 * gen_opc_condexec_bits[]. gen_pc_load[] then uses this to restore
9266 * the condexec bits.
9268 * Note that there are no instructions which can read the condexec
9269 * bits, and none which can write non-static values to them, so
9270 * we don't need to care about whether CPUState is correct in the
9271 * middle of a TB.
9274 /* Reset the conditional execution bits immediately. This avoids
9275 complications trying to do it at the end of the block. */
9276 if (dc->condexec_mask || dc->condexec_cond)
9278 TCGv tmp = tcg_temp_new_i32();
9279 tcg_gen_movi_i32(tmp, 0);
9280 store_cpu_field(tmp, condexec_bits);
9282 do {
9283 #ifdef CONFIG_USER_ONLY
9284 /* Intercept jump to the magic kernel page. */
9285 if (dc->pc >= 0xffff0000) {
9286 /* We always get here via a jump, so know we are not in a
9287 conditional execution block. */
9288 gen_exception(EXCP_KERNEL_TRAP);
9289 dc->is_jmp = DISAS_UPDATE;
9290 break;
9292 #else
9293 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
9294 /* We always get here via a jump, so know we are not in a
9295 conditional execution block. */
9296 gen_exception(EXCP_EXCEPTION_EXIT);
9297 dc->is_jmp = DISAS_UPDATE;
9298 break;
9300 #endif
9302 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
9303 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
9304 if (bp->pc == dc->pc) {
9305 gen_exception_insn(dc, 0, EXCP_DEBUG);
9306 /* Advance PC so that clearing the breakpoint will
9307 invalidate this TB. */
9308 dc->pc += 2;
9309 goto done_generating;
9310 break;
9314 if (search_pc) {
9315 j = gen_opc_ptr - gen_opc_buf;
9316 if (lj < j) {
9317 lj++;
9318 while (lj < j)
9319 gen_opc_instr_start[lj++] = 0;
9321 gen_opc_pc[lj] = dc->pc;
9322 gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
9323 gen_opc_instr_start[lj] = 1;
9324 gen_opc_icount[lj] = num_insns;
9327 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
9328 gen_io_start();
9330 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
9331 tcg_gen_debug_insn_start(dc->pc);
9334 if (dc->thumb) {
9335 disas_thumb_insn(env, dc);
9336 if (dc->condexec_mask) {
9337 dc->condexec_cond = (dc->condexec_cond & 0xe)
9338 | ((dc->condexec_mask >> 4) & 1);
9339 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
9340 if (dc->condexec_mask == 0) {
9341 dc->condexec_cond = 0;
9344 } else {
9345 disas_arm_insn(env, dc);
9348 if (dc->condjmp && !dc->is_jmp) {
9349 gen_set_label(dc->condlabel);
9350 dc->condjmp = 0;
9353 if (tcg_check_temp_count()) {
9354 fprintf(stderr, "TCG temporary leak before %08x\n", dc->pc);
9357 /* Translation stops when a conditional branch is encountered.
9358 * Otherwise the subsequent code could get translated several times.
9359 * Also stop translation when a page boundary is reached. This
9360 * ensures prefetch aborts occur at the right place. */
9361 num_insns ++;
9362 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
9363 !env->singlestep_enabled &&
9364 !singlestep &&
9365 dc->pc < next_page_start &&
9366 num_insns < max_insns);
9368 if (tb->cflags & CF_LAST_IO) {
9369 if (dc->condjmp) {
9370 /* FIXME: This can theoretically happen with self-modifying
9371 code. */
9372 cpu_abort(env, "IO on conditional branch instruction");
9374 gen_io_end();
9377 /* At this stage dc->condjmp will only be set when the skipped
9378 instruction was a conditional branch or trap, and the PC has
9379 already been written. */
9380 if (unlikely(env->singlestep_enabled)) {
9381 /* Make sure the pc is updated, and raise a debug exception. */
9382 if (dc->condjmp) {
9383 gen_set_condexec(dc);
9384 if (dc->is_jmp == DISAS_SWI) {
9385 gen_exception(EXCP_SWI);
9386 } else {
9387 gen_exception(EXCP_DEBUG);
9389 gen_set_label(dc->condlabel);
9391 if (dc->condjmp || !dc->is_jmp) {
9392 gen_set_pc_im(dc->pc);
9393 dc->condjmp = 0;
9395 gen_set_condexec(dc);
9396 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
9397 gen_exception(EXCP_SWI);
9398 } else {
9399 /* FIXME: Single stepping a WFI insn will not halt
9400 the CPU. */
9401 gen_exception(EXCP_DEBUG);
9403 } else {
9404 /* While branches must always occur at the end of an IT block,
9405 there are a few other things that can cause us to terminate
9406 the TB in the middel of an IT block:
9407 - Exception generating instructions (bkpt, swi, undefined).
9408 - Page boundaries.
9409 - Hardware watchpoints.
9410 Hardware breakpoints have already been handled and skip this code.
9412 gen_set_condexec(dc);
9413 switch(dc->is_jmp) {
9414 case DISAS_NEXT:
9415 gen_goto_tb(dc, 1, dc->pc);
9416 break;
9417 default:
9418 case DISAS_JUMP:
9419 case DISAS_UPDATE:
9420 /* indicate that the hash table must be used to find the next TB */
9421 tcg_gen_exit_tb(0);
9422 break;
9423 case DISAS_TB_JUMP:
9424 /* nothing more to generate */
9425 break;
9426 case DISAS_WFI:
9427 gen_helper_wfi();
9428 break;
9429 case DISAS_SWI:
9430 gen_exception(EXCP_SWI);
9431 break;
9433 if (dc->condjmp) {
9434 gen_set_label(dc->condlabel);
9435 gen_set_condexec(dc);
9436 gen_goto_tb(dc, 1, dc->pc);
9437 dc->condjmp = 0;
9441 done_generating:
9442 gen_icount_end(tb, num_insns);
9443 *gen_opc_ptr = INDEX_op_end;
9445 #ifdef DEBUG_DISAS
9446 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9447 qemu_log("----------------\n");
9448 qemu_log("IN: %s\n", lookup_symbol(pc_start));
9449 log_target_disas(pc_start, dc->pc - pc_start, dc->thumb);
9450 qemu_log("\n");
9452 #endif
9453 if (search_pc) {
9454 j = gen_opc_ptr - gen_opc_buf;
9455 lj++;
9456 while (lj <= j)
9457 gen_opc_instr_start[lj++] = 0;
9458 } else {
9459 tb->size = dc->pc - pc_start;
9460 tb->icount = num_insns;
9464 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
9466 gen_intermediate_code_internal(env, tb, 0);
9469 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
9471 gen_intermediate_code_internal(env, tb, 1);
9474 static const char *cpu_mode_names[16] = {
9475 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9476 "???", "???", "???", "und", "???", "???", "???", "sys"
9479 void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
9480 int flags)
9482 int i;
9483 #if 0
9484 union {
9485 uint32_t i;
9486 float s;
9487 } s0, s1;
9488 CPU_DoubleU d;
9489 /* ??? This assumes float64 and double have the same layout.
9490 Oh well, it's only debug dumps. */
9491 union {
9492 float64 f64;
9493 double d;
9494 } d0;
9495 #endif
9496 uint32_t psr;
9498 for(i=0;i<16;i++) {
9499 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
9500 if ((i % 4) == 3)
9501 cpu_fprintf(f, "\n");
9502 else
9503 cpu_fprintf(f, " ");
9505 psr = cpsr_read(env);
9506 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
9507 psr,
9508 psr & (1 << 31) ? 'N' : '-',
9509 psr & (1 << 30) ? 'Z' : '-',
9510 psr & (1 << 29) ? 'C' : '-',
9511 psr & (1 << 28) ? 'V' : '-',
9512 psr & CPSR_T ? 'T' : 'A',
9513 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
9515 #if 0
9516 for (i = 0; i < 16; i++) {
9517 d.d = env->vfp.regs[i];
9518 s0.i = d.l.lower;
9519 s1.i = d.l.upper;
9520 d0.f64 = d.d;
9521 cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9522 i * 2, (int)s0.i, s0.s,
9523 i * 2 + 1, (int)s1.i, s1.s,
9524 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
9525 d0.d);
9527 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
9528 #endif
9531 void gen_pc_load(CPUState *env, TranslationBlock *tb,
9532 unsigned long searched_pc, int pc_pos, void *puc)
9534 env->regs[15] = gen_opc_pc[pc_pos];
9535 env->condexec_bits = gen_opc_condexec_bits[pc_pos];