target-arm: Fix VLD of single element to all lanes
[qemu/cris-port.git] / target-arm / translate.c
blob1dfd4823f5faeaec35ef20d10333bf274cbc29ce
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 addr = tcg_temp_new_i32();
3814 if ((insn & (1 << 23)) == 0) {
3815 /* Load store all elements. */
3816 op = (insn >> 8) & 0xf;
3817 size = (insn >> 6) & 3;
3818 if (op > 10)
3819 return 1;
3820 nregs = neon_ls_element_type[op].nregs;
3821 interleave = neon_ls_element_type[op].interleave;
3822 spacing = neon_ls_element_type[op].spacing;
3823 if (size == 3 && (interleave | spacing) != 1)
3824 return 1;
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 stride = nregs * 8;
3911 } else {
3912 size = (insn >> 10) & 3;
3913 if (size == 3) {
3914 /* Load single element to all lanes. */
3915 int a = (insn >> 4) & 1;
3916 if (!load) {
3917 return 1;
3919 size = (insn >> 6) & 3;
3920 nregs = ((insn >> 8) & 3) + 1;
3922 if (size == 3) {
3923 if (nregs != 4 || a == 0) {
3924 return 1;
3926 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
3927 size = 2;
3929 if (nregs == 1 && a == 1 && size == 0) {
3930 return 1;
3932 if (nregs == 3 && a == 1) {
3933 return 1;
3935 load_reg_var(s, addr, rn);
3936 if (nregs == 1) {
3937 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */
3938 tmp = gen_load_and_replicate(s, addr, size);
3939 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
3940 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
3941 if (insn & (1 << 5)) {
3942 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 0));
3943 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 1));
3945 tcg_temp_free_i32(tmp);
3946 } else {
3947 /* VLD2/3/4 to all lanes: bit 5 indicates register stride */
3948 stride = (insn & (1 << 5)) ? 2 : 1;
3949 for (reg = 0; reg < nregs; reg++) {
3950 tmp = gen_load_and_replicate(s, addr, size);
3951 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
3952 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
3953 tcg_temp_free_i32(tmp);
3954 tcg_gen_addi_i32(addr, addr, 1 << size);
3955 rd += stride;
3958 stride = (1 << size) * nregs;
3959 } else {
3960 /* Single element. */
3961 pass = (insn >> 7) & 1;
3962 switch (size) {
3963 case 0:
3964 shift = ((insn >> 5) & 3) * 8;
3965 stride = 1;
3966 break;
3967 case 1:
3968 shift = ((insn >> 6) & 1) * 16;
3969 stride = (insn & (1 << 5)) ? 2 : 1;
3970 break;
3971 case 2:
3972 shift = 0;
3973 stride = (insn & (1 << 6)) ? 2 : 1;
3974 break;
3975 default:
3976 abort();
3978 nregs = ((insn >> 8) & 3) + 1;
3979 load_reg_var(s, addr, rn);
3980 for (reg = 0; reg < nregs; reg++) {
3981 if (load) {
3982 switch (size) {
3983 case 0:
3984 tmp = gen_ld8u(addr, IS_USER(s));
3985 break;
3986 case 1:
3987 tmp = gen_ld16u(addr, IS_USER(s));
3988 break;
3989 case 2:
3990 tmp = gen_ld32(addr, IS_USER(s));
3991 break;
3992 default: /* Avoid compiler warnings. */
3993 abort();
3995 if (size != 2) {
3996 tmp2 = neon_load_reg(rd, pass);
3997 gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
3998 tcg_temp_free_i32(tmp2);
4000 neon_store_reg(rd, pass, tmp);
4001 } else { /* Store */
4002 tmp = neon_load_reg(rd, pass);
4003 if (shift)
4004 tcg_gen_shri_i32(tmp, tmp, shift);
4005 switch (size) {
4006 case 0:
4007 gen_st8(tmp, addr, IS_USER(s));
4008 break;
4009 case 1:
4010 gen_st16(tmp, addr, IS_USER(s));
4011 break;
4012 case 2:
4013 gen_st32(tmp, addr, IS_USER(s));
4014 break;
4017 rd += stride;
4018 tcg_gen_addi_i32(addr, addr, 1 << size);
4020 stride = nregs * (1 << size);
4023 tcg_temp_free_i32(addr);
4024 if (rm != 15) {
4025 TCGv base;
4027 base = load_reg(s, rn);
4028 if (rm == 13) {
4029 tcg_gen_addi_i32(base, base, stride);
4030 } else {
4031 TCGv index;
4032 index = load_reg(s, rm);
4033 tcg_gen_add_i32(base, base, index);
4034 tcg_temp_free_i32(index);
4036 store_reg(s, rn, base);
4038 return 0;
4041 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4042 static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
4044 tcg_gen_and_i32(t, t, c);
4045 tcg_gen_andc_i32(f, f, c);
4046 tcg_gen_or_i32(dest, t, f);
4049 static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
4051 switch (size) {
4052 case 0: gen_helper_neon_narrow_u8(dest, src); break;
4053 case 1: gen_helper_neon_narrow_u16(dest, src); break;
4054 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
4055 default: abort();
4059 static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
4061 switch (size) {
4062 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
4063 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
4064 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
4065 default: abort();
4069 static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
4071 switch (size) {
4072 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
4073 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
4074 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
4075 default: abort();
4079 static inline void gen_neon_unarrow_sats(int size, TCGv dest, TCGv_i64 src)
4081 switch (size) {
4082 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
4083 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
4084 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
4085 default: abort();
4089 static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
4090 int q, int u)
4092 if (q) {
4093 if (u) {
4094 switch (size) {
4095 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4096 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4097 default: abort();
4099 } else {
4100 switch (size) {
4101 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
4102 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
4103 default: abort();
4106 } else {
4107 if (u) {
4108 switch (size) {
4109 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
4110 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
4111 default: abort();
4113 } else {
4114 switch (size) {
4115 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
4116 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
4117 default: abort();
4123 static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
4125 if (u) {
4126 switch (size) {
4127 case 0: gen_helper_neon_widen_u8(dest, src); break;
4128 case 1: gen_helper_neon_widen_u16(dest, src); break;
4129 case 2: tcg_gen_extu_i32_i64(dest, src); break;
4130 default: abort();
4132 } else {
4133 switch (size) {
4134 case 0: gen_helper_neon_widen_s8(dest, src); break;
4135 case 1: gen_helper_neon_widen_s16(dest, src); break;
4136 case 2: tcg_gen_ext_i32_i64(dest, src); break;
4137 default: abort();
4140 tcg_temp_free_i32(src);
4143 static inline void gen_neon_addl(int size)
4145 switch (size) {
4146 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4147 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4148 case 2: tcg_gen_add_i64(CPU_V001); break;
4149 default: abort();
4153 static inline void gen_neon_subl(int size)
4155 switch (size) {
4156 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4157 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4158 case 2: tcg_gen_sub_i64(CPU_V001); break;
4159 default: abort();
4163 static inline void gen_neon_negl(TCGv_i64 var, int size)
4165 switch (size) {
4166 case 0: gen_helper_neon_negl_u16(var, var); break;
4167 case 1: gen_helper_neon_negl_u32(var, var); break;
4168 case 2: gen_helper_neon_negl_u64(var, var); break;
4169 default: abort();
4173 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4175 switch (size) {
4176 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4177 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4178 default: abort();
4182 static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
4184 TCGv_i64 tmp;
4186 switch ((size << 1) | u) {
4187 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4188 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4189 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4190 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4191 case 4:
4192 tmp = gen_muls_i64_i32(a, b);
4193 tcg_gen_mov_i64(dest, tmp);
4194 tcg_temp_free_i64(tmp);
4195 break;
4196 case 5:
4197 tmp = gen_mulu_i64_i32(a, b);
4198 tcg_gen_mov_i64(dest, tmp);
4199 tcg_temp_free_i64(tmp);
4200 break;
4201 default: abort();
4204 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
4205 Don't forget to clean them now. */
4206 if (size < 2) {
4207 tcg_temp_free_i32(a);
4208 tcg_temp_free_i32(b);
4212 static void gen_neon_narrow_op(int op, int u, int size, TCGv dest, TCGv_i64 src)
4214 if (op) {
4215 if (u) {
4216 gen_neon_unarrow_sats(size, dest, src);
4217 } else {
4218 gen_neon_narrow(size, dest, src);
4220 } else {
4221 if (u) {
4222 gen_neon_narrow_satu(size, dest, src);
4223 } else {
4224 gen_neon_narrow_sats(size, dest, src);
4229 /* Translate a NEON data processing instruction. Return nonzero if the
4230 instruction is invalid.
4231 We process data in a mixture of 32-bit and 64-bit chunks.
4232 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4234 static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4236 int op;
4237 int q;
4238 int rd, rn, rm;
4239 int size;
4240 int shift;
4241 int pass;
4242 int count;
4243 int pairwise;
4244 int u;
4245 int n;
4246 uint32_t imm, mask;
4247 TCGv tmp, tmp2, tmp3, tmp4, tmp5;
4248 TCGv_i64 tmp64;
4250 if (!s->vfp_enabled)
4251 return 1;
4252 q = (insn & (1 << 6)) != 0;
4253 u = (insn >> 24) & 1;
4254 VFP_DREG_D(rd, insn);
4255 VFP_DREG_N(rn, insn);
4256 VFP_DREG_M(rm, insn);
4257 size = (insn >> 20) & 3;
4258 if ((insn & (1 << 23)) == 0) {
4259 /* Three register same length. */
4260 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4261 if (size == 3 && (op == 1 || op == 5 || op == 8 || op == 9
4262 || op == 10 || op == 11 || op == 16)) {
4263 /* 64-bit element instructions. */
4264 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4265 neon_load_reg64(cpu_V0, rn + pass);
4266 neon_load_reg64(cpu_V1, rm + pass);
4267 switch (op) {
4268 case 1: /* VQADD */
4269 if (u) {
4270 gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
4271 cpu_V0, cpu_V1);
4272 } else {
4273 gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
4274 cpu_V0, cpu_V1);
4276 break;
4277 case 5: /* VQSUB */
4278 if (u) {
4279 gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
4280 cpu_V0, cpu_V1);
4281 } else {
4282 gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
4283 cpu_V0, cpu_V1);
4285 break;
4286 case 8: /* VSHL */
4287 if (u) {
4288 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4289 } else {
4290 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4292 break;
4293 case 9: /* VQSHL */
4294 if (u) {
4295 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4296 cpu_V1, cpu_V0);
4297 } else {
4298 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
4299 cpu_V1, cpu_V0);
4301 break;
4302 case 10: /* VRSHL */
4303 if (u) {
4304 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4305 } else {
4306 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4308 break;
4309 case 11: /* VQRSHL */
4310 if (u) {
4311 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4312 cpu_V1, cpu_V0);
4313 } else {
4314 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4315 cpu_V1, cpu_V0);
4317 break;
4318 case 16:
4319 if (u) {
4320 tcg_gen_sub_i64(CPU_V001);
4321 } else {
4322 tcg_gen_add_i64(CPU_V001);
4324 break;
4325 default:
4326 abort();
4328 neon_store_reg64(cpu_V0, rd + pass);
4330 return 0;
4332 switch (op) {
4333 case 8: /* VSHL */
4334 case 9: /* VQSHL */
4335 case 10: /* VRSHL */
4336 case 11: /* VQRSHL */
4338 int rtmp;
4339 /* Shift instruction operands are reversed. */
4340 rtmp = rn;
4341 rn = rm;
4342 rm = rtmp;
4343 pairwise = 0;
4345 break;
4346 case 20: /* VPMAX */
4347 case 21: /* VPMIN */
4348 case 23: /* VPADD */
4349 pairwise = 1;
4350 break;
4351 case 26: /* VPADD (float) */
4352 pairwise = (u && size < 2);
4353 break;
4354 case 30: /* VPMIN/VPMAX (float) */
4355 pairwise = u;
4356 break;
4357 default:
4358 pairwise = 0;
4359 break;
4362 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4364 if (pairwise) {
4365 /* Pairwise. */
4366 if (q)
4367 n = (pass & 1) * 2;
4368 else
4369 n = 0;
4370 if (pass < q + 1) {
4371 tmp = neon_load_reg(rn, n);
4372 tmp2 = neon_load_reg(rn, n + 1);
4373 } else {
4374 tmp = neon_load_reg(rm, n);
4375 tmp2 = neon_load_reg(rm, n + 1);
4377 } else {
4378 /* Elementwise. */
4379 tmp = neon_load_reg(rn, pass);
4380 tmp2 = neon_load_reg(rm, pass);
4382 switch (op) {
4383 case 0: /* VHADD */
4384 GEN_NEON_INTEGER_OP(hadd);
4385 break;
4386 case 1: /* VQADD */
4387 GEN_NEON_INTEGER_OP_ENV(qadd);
4388 break;
4389 case 2: /* VRHADD */
4390 GEN_NEON_INTEGER_OP(rhadd);
4391 break;
4392 case 3: /* Logic ops. */
4393 switch ((u << 2) | size) {
4394 case 0: /* VAND */
4395 tcg_gen_and_i32(tmp, tmp, tmp2);
4396 break;
4397 case 1: /* BIC */
4398 tcg_gen_andc_i32(tmp, tmp, tmp2);
4399 break;
4400 case 2: /* VORR */
4401 tcg_gen_or_i32(tmp, tmp, tmp2);
4402 break;
4403 case 3: /* VORN */
4404 tcg_gen_orc_i32(tmp, tmp, tmp2);
4405 break;
4406 case 4: /* VEOR */
4407 tcg_gen_xor_i32(tmp, tmp, tmp2);
4408 break;
4409 case 5: /* VBSL */
4410 tmp3 = neon_load_reg(rd, pass);
4411 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
4412 tcg_temp_free_i32(tmp3);
4413 break;
4414 case 6: /* VBIT */
4415 tmp3 = neon_load_reg(rd, pass);
4416 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
4417 tcg_temp_free_i32(tmp3);
4418 break;
4419 case 7: /* VBIF */
4420 tmp3 = neon_load_reg(rd, pass);
4421 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
4422 tcg_temp_free_i32(tmp3);
4423 break;
4425 break;
4426 case 4: /* VHSUB */
4427 GEN_NEON_INTEGER_OP(hsub);
4428 break;
4429 case 5: /* VQSUB */
4430 GEN_NEON_INTEGER_OP_ENV(qsub);
4431 break;
4432 case 6: /* VCGT */
4433 GEN_NEON_INTEGER_OP(cgt);
4434 break;
4435 case 7: /* VCGE */
4436 GEN_NEON_INTEGER_OP(cge);
4437 break;
4438 case 8: /* VSHL */
4439 GEN_NEON_INTEGER_OP(shl);
4440 break;
4441 case 9: /* VQSHL */
4442 GEN_NEON_INTEGER_OP_ENV(qshl);
4443 break;
4444 case 10: /* VRSHL */
4445 GEN_NEON_INTEGER_OP(rshl);
4446 break;
4447 case 11: /* VQRSHL */
4448 GEN_NEON_INTEGER_OP_ENV(qrshl);
4449 break;
4450 case 12: /* VMAX */
4451 GEN_NEON_INTEGER_OP(max);
4452 break;
4453 case 13: /* VMIN */
4454 GEN_NEON_INTEGER_OP(min);
4455 break;
4456 case 14: /* VABD */
4457 GEN_NEON_INTEGER_OP(abd);
4458 break;
4459 case 15: /* VABA */
4460 GEN_NEON_INTEGER_OP(abd);
4461 tcg_temp_free_i32(tmp2);
4462 tmp2 = neon_load_reg(rd, pass);
4463 gen_neon_add(size, tmp, tmp2);
4464 break;
4465 case 16:
4466 if (!u) { /* VADD */
4467 if (gen_neon_add(size, tmp, tmp2))
4468 return 1;
4469 } else { /* VSUB */
4470 switch (size) {
4471 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
4472 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
4473 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
4474 default: return 1;
4477 break;
4478 case 17:
4479 if (!u) { /* VTST */
4480 switch (size) {
4481 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
4482 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
4483 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
4484 default: return 1;
4486 } else { /* VCEQ */
4487 switch (size) {
4488 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
4489 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
4490 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
4491 default: return 1;
4494 break;
4495 case 18: /* Multiply. */
4496 switch (size) {
4497 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4498 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4499 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4500 default: return 1;
4502 tcg_temp_free_i32(tmp2);
4503 tmp2 = neon_load_reg(rd, pass);
4504 if (u) { /* VMLS */
4505 gen_neon_rsb(size, tmp, tmp2);
4506 } else { /* VMLA */
4507 gen_neon_add(size, tmp, tmp2);
4509 break;
4510 case 19: /* VMUL */
4511 if (u) { /* polynomial */
4512 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
4513 } else { /* Integer */
4514 switch (size) {
4515 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4516 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4517 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4518 default: return 1;
4521 break;
4522 case 20: /* VPMAX */
4523 GEN_NEON_INTEGER_OP(pmax);
4524 break;
4525 case 21: /* VPMIN */
4526 GEN_NEON_INTEGER_OP(pmin);
4527 break;
4528 case 22: /* Hultiply high. */
4529 if (!u) { /* VQDMULH */
4530 switch (size) {
4531 case 1: gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4532 case 2: gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4533 default: return 1;
4535 } else { /* VQRDHMUL */
4536 switch (size) {
4537 case 1: gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2); break;
4538 case 2: gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2); break;
4539 default: return 1;
4542 break;
4543 case 23: /* VPADD */
4544 if (u)
4545 return 1;
4546 switch (size) {
4547 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
4548 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
4549 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
4550 default: return 1;
4552 break;
4553 case 26: /* Floating point arithnetic. */
4554 switch ((u << 2) | size) {
4555 case 0: /* VADD */
4556 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4557 break;
4558 case 2: /* VSUB */
4559 gen_helper_neon_sub_f32(tmp, tmp, tmp2);
4560 break;
4561 case 4: /* VPADD */
4562 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4563 break;
4564 case 6: /* VABD */
4565 gen_helper_neon_abd_f32(tmp, tmp, tmp2);
4566 break;
4567 default:
4568 return 1;
4570 break;
4571 case 27: /* Float multiply. */
4572 gen_helper_neon_mul_f32(tmp, tmp, tmp2);
4573 if (!u) {
4574 tcg_temp_free_i32(tmp2);
4575 tmp2 = neon_load_reg(rd, pass);
4576 if (size == 0) {
4577 gen_helper_neon_add_f32(tmp, tmp, tmp2);
4578 } else {
4579 gen_helper_neon_sub_f32(tmp, tmp2, tmp);
4582 break;
4583 case 28: /* Float compare. */
4584 if (!u) {
4585 gen_helper_neon_ceq_f32(tmp, tmp, tmp2);
4586 } else {
4587 if (size == 0)
4588 gen_helper_neon_cge_f32(tmp, tmp, tmp2);
4589 else
4590 gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
4592 break;
4593 case 29: /* Float compare absolute. */
4594 if (!u)
4595 return 1;
4596 if (size == 0)
4597 gen_helper_neon_acge_f32(tmp, tmp, tmp2);
4598 else
4599 gen_helper_neon_acgt_f32(tmp, tmp, tmp2);
4600 break;
4601 case 30: /* Float min/max. */
4602 if (size == 0)
4603 gen_helper_neon_max_f32(tmp, tmp, tmp2);
4604 else
4605 gen_helper_neon_min_f32(tmp, tmp, tmp2);
4606 break;
4607 case 31:
4608 if (size == 0)
4609 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
4610 else
4611 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
4612 break;
4613 default:
4614 abort();
4616 tcg_temp_free_i32(tmp2);
4618 /* Save the result. For elementwise operations we can put it
4619 straight into the destination register. For pairwise operations
4620 we have to be careful to avoid clobbering the source operands. */
4621 if (pairwise && rd == rm) {
4622 neon_store_scratch(pass, tmp);
4623 } else {
4624 neon_store_reg(rd, pass, tmp);
4627 } /* for pass */
4628 if (pairwise && rd == rm) {
4629 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4630 tmp = neon_load_scratch(pass);
4631 neon_store_reg(rd, pass, tmp);
4634 /* End of 3 register same size operations. */
4635 } else if (insn & (1 << 4)) {
4636 if ((insn & 0x00380080) != 0) {
4637 /* Two registers and shift. */
4638 op = (insn >> 8) & 0xf;
4639 if (insn & (1 << 7)) {
4640 /* 64-bit shift. */
4641 size = 3;
4642 } else {
4643 size = 2;
4644 while ((insn & (1 << (size + 19))) == 0)
4645 size--;
4647 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
4648 /* To avoid excessive dumplication of ops we implement shift
4649 by immediate using the variable shift operations. */
4650 if (op < 8) {
4651 /* Shift by immediate:
4652 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4653 /* Right shifts are encoded as N - shift, where N is the
4654 element size in bits. */
4655 if (op <= 4)
4656 shift = shift - (1 << (size + 3));
4657 if (size == 3) {
4658 count = q + 1;
4659 } else {
4660 count = q ? 4: 2;
4662 switch (size) {
4663 case 0:
4664 imm = (uint8_t) shift;
4665 imm |= imm << 8;
4666 imm |= imm << 16;
4667 break;
4668 case 1:
4669 imm = (uint16_t) shift;
4670 imm |= imm << 16;
4671 break;
4672 case 2:
4673 case 3:
4674 imm = shift;
4675 break;
4676 default:
4677 abort();
4680 for (pass = 0; pass < count; pass++) {
4681 if (size == 3) {
4682 neon_load_reg64(cpu_V0, rm + pass);
4683 tcg_gen_movi_i64(cpu_V1, imm);
4684 switch (op) {
4685 case 0: /* VSHR */
4686 case 1: /* VSRA */
4687 if (u)
4688 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4689 else
4690 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
4691 break;
4692 case 2: /* VRSHR */
4693 case 3: /* VRSRA */
4694 if (u)
4695 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
4696 else
4697 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
4698 break;
4699 case 4: /* VSRI */
4700 if (!u)
4701 return 1;
4702 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4703 break;
4704 case 5: /* VSHL, VSLI */
4705 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
4706 break;
4707 case 6: /* VQSHLU */
4708 if (u) {
4709 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
4710 cpu_V0, cpu_V1);
4711 } else {
4712 return 1;
4714 break;
4715 case 7: /* VQSHL */
4716 if (u) {
4717 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4718 cpu_V0, cpu_V1);
4719 } else {
4720 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
4721 cpu_V0, cpu_V1);
4723 break;
4725 if (op == 1 || op == 3) {
4726 /* Accumulate. */
4727 neon_load_reg64(cpu_V1, rd + pass);
4728 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
4729 } else if (op == 4 || (op == 5 && u)) {
4730 /* Insert */
4731 neon_load_reg64(cpu_V1, rd + pass);
4732 uint64_t mask;
4733 if (shift < -63 || shift > 63) {
4734 mask = 0;
4735 } else {
4736 if (op == 4) {
4737 mask = 0xffffffffffffffffull >> -shift;
4738 } else {
4739 mask = 0xffffffffffffffffull << shift;
4742 tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask);
4743 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
4745 neon_store_reg64(cpu_V0, rd + pass);
4746 } else { /* size < 3 */
4747 /* Operands in T0 and T1. */
4748 tmp = neon_load_reg(rm, pass);
4749 tmp2 = tcg_temp_new_i32();
4750 tcg_gen_movi_i32(tmp2, imm);
4751 switch (op) {
4752 case 0: /* VSHR */
4753 case 1: /* VSRA */
4754 GEN_NEON_INTEGER_OP(shl);
4755 break;
4756 case 2: /* VRSHR */
4757 case 3: /* VRSRA */
4758 GEN_NEON_INTEGER_OP(rshl);
4759 break;
4760 case 4: /* VSRI */
4761 if (!u)
4762 return 1;
4763 GEN_NEON_INTEGER_OP(shl);
4764 break;
4765 case 5: /* VSHL, VSLI */
4766 switch (size) {
4767 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
4768 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
4769 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
4770 default: return 1;
4772 break;
4773 case 6: /* VQSHLU */
4774 if (!u) {
4775 return 1;
4777 switch (size) {
4778 case 0:
4779 gen_helper_neon_qshlu_s8(tmp, cpu_env,
4780 tmp, tmp2);
4781 break;
4782 case 1:
4783 gen_helper_neon_qshlu_s16(tmp, cpu_env,
4784 tmp, tmp2);
4785 break;
4786 case 2:
4787 gen_helper_neon_qshlu_s32(tmp, cpu_env,
4788 tmp, tmp2);
4789 break;
4790 default:
4791 return 1;
4793 break;
4794 case 7: /* VQSHL */
4795 GEN_NEON_INTEGER_OP_ENV(qshl);
4796 break;
4798 tcg_temp_free_i32(tmp2);
4800 if (op == 1 || op == 3) {
4801 /* Accumulate. */
4802 tmp2 = neon_load_reg(rd, pass);
4803 gen_neon_add(size, tmp, tmp2);
4804 tcg_temp_free_i32(tmp2);
4805 } else if (op == 4 || (op == 5 && u)) {
4806 /* Insert */
4807 switch (size) {
4808 case 0:
4809 if (op == 4)
4810 mask = 0xff >> -shift;
4811 else
4812 mask = (uint8_t)(0xff << shift);
4813 mask |= mask << 8;
4814 mask |= mask << 16;
4815 break;
4816 case 1:
4817 if (op == 4)
4818 mask = 0xffff >> -shift;
4819 else
4820 mask = (uint16_t)(0xffff << shift);
4821 mask |= mask << 16;
4822 break;
4823 case 2:
4824 if (shift < -31 || shift > 31) {
4825 mask = 0;
4826 } else {
4827 if (op == 4)
4828 mask = 0xffffffffu >> -shift;
4829 else
4830 mask = 0xffffffffu << shift;
4832 break;
4833 default:
4834 abort();
4836 tmp2 = neon_load_reg(rd, pass);
4837 tcg_gen_andi_i32(tmp, tmp, mask);
4838 tcg_gen_andi_i32(tmp2, tmp2, ~mask);
4839 tcg_gen_or_i32(tmp, tmp, tmp2);
4840 tcg_temp_free_i32(tmp2);
4842 neon_store_reg(rd, pass, tmp);
4844 } /* for pass */
4845 } else if (op < 10) {
4846 /* Shift by immediate and narrow:
4847 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4848 int input_unsigned = (op == 8) ? !u : u;
4850 shift = shift - (1 << (size + 3));
4851 size++;
4852 if (size == 3) {
4853 tmp64 = tcg_const_i64(shift);
4854 neon_load_reg64(cpu_V0, rm);
4855 neon_load_reg64(cpu_V1, rm + 1);
4856 for (pass = 0; pass < 2; pass++) {
4857 TCGv_i64 in;
4858 if (pass == 0) {
4859 in = cpu_V0;
4860 } else {
4861 in = cpu_V1;
4863 if (q) {
4864 if (input_unsigned) {
4865 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
4866 } else {
4867 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
4869 } else {
4870 if (input_unsigned) {
4871 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
4872 } else {
4873 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
4876 tmp = tcg_temp_new_i32();
4877 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
4878 neon_store_reg(rd, pass, tmp);
4879 } /* for pass */
4880 tcg_temp_free_i64(tmp64);
4881 } else {
4882 if (size == 1) {
4883 imm = (uint16_t)shift;
4884 imm |= imm << 16;
4885 } else {
4886 /* size == 2 */
4887 imm = (uint32_t)shift;
4889 tmp2 = tcg_const_i32(imm);
4890 tmp4 = neon_load_reg(rm + 1, 0);
4891 tmp5 = neon_load_reg(rm + 1, 1);
4892 for (pass = 0; pass < 2; pass++) {
4893 if (pass == 0) {
4894 tmp = neon_load_reg(rm, 0);
4895 } else {
4896 tmp = tmp4;
4898 gen_neon_shift_narrow(size, tmp, tmp2, q,
4899 input_unsigned);
4900 if (pass == 0) {
4901 tmp3 = neon_load_reg(rm, 1);
4902 } else {
4903 tmp3 = tmp5;
4905 gen_neon_shift_narrow(size, tmp3, tmp2, q,
4906 input_unsigned);
4907 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
4908 tcg_temp_free_i32(tmp);
4909 tcg_temp_free_i32(tmp3);
4910 tmp = tcg_temp_new_i32();
4911 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
4912 neon_store_reg(rd, pass, tmp);
4913 } /* for pass */
4914 tcg_temp_free_i32(tmp2);
4916 } else if (op == 10) {
4917 /* VSHLL */
4918 if (q || size == 3)
4919 return 1;
4920 tmp = neon_load_reg(rm, 0);
4921 tmp2 = neon_load_reg(rm, 1);
4922 for (pass = 0; pass < 2; pass++) {
4923 if (pass == 1)
4924 tmp = tmp2;
4926 gen_neon_widen(cpu_V0, tmp, size, u);
4928 if (shift != 0) {
4929 /* The shift is less than the width of the source
4930 type, so we can just shift the whole register. */
4931 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
4932 /* Widen the result of shift: we need to clear
4933 * the potential overflow bits resulting from
4934 * left bits of the narrow input appearing as
4935 * right bits of left the neighbour narrow
4936 * input. */
4937 if (size < 2 || !u) {
4938 uint64_t imm64;
4939 if (size == 0) {
4940 imm = (0xffu >> (8 - shift));
4941 imm |= imm << 16;
4942 } else if (size == 1) {
4943 imm = 0xffff >> (16 - shift);
4944 } else {
4945 /* size == 2 */
4946 imm = 0xffffffff >> (32 - shift);
4948 if (size < 2) {
4949 imm64 = imm | (((uint64_t)imm) << 32);
4950 } else {
4951 imm64 = imm;
4953 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
4956 neon_store_reg64(cpu_V0, rd + pass);
4958 } else if (op >= 14) {
4959 /* VCVT fixed-point. */
4960 /* We have already masked out the must-be-1 top bit of imm6,
4961 * hence this 32-shift where the ARM ARM has 64-imm6.
4963 shift = 32 - shift;
4964 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4965 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
4966 if (!(op & 1)) {
4967 if (u)
4968 gen_vfp_ulto(0, shift);
4969 else
4970 gen_vfp_slto(0, shift);
4971 } else {
4972 if (u)
4973 gen_vfp_toul(0, shift);
4974 else
4975 gen_vfp_tosl(0, shift);
4977 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
4979 } else {
4980 return 1;
4982 } else { /* (insn & 0x00380080) == 0 */
4983 int invert;
4985 op = (insn >> 8) & 0xf;
4986 /* One register and immediate. */
4987 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
4988 invert = (insn & (1 << 5)) != 0;
4989 switch (op) {
4990 case 0: case 1:
4991 /* no-op */
4992 break;
4993 case 2: case 3:
4994 imm <<= 8;
4995 break;
4996 case 4: case 5:
4997 imm <<= 16;
4998 break;
4999 case 6: case 7:
5000 imm <<= 24;
5001 break;
5002 case 8: case 9:
5003 imm |= imm << 16;
5004 break;
5005 case 10: case 11:
5006 imm = (imm << 8) | (imm << 24);
5007 break;
5008 case 12:
5009 imm = (imm << 8) | 0xff;
5010 break;
5011 case 13:
5012 imm = (imm << 16) | 0xffff;
5013 break;
5014 case 14:
5015 imm |= (imm << 8) | (imm << 16) | (imm << 24);
5016 if (invert)
5017 imm = ~imm;
5018 break;
5019 case 15:
5020 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
5021 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
5022 break;
5024 if (invert)
5025 imm = ~imm;
5027 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5028 if (op & 1 && op < 12) {
5029 tmp = neon_load_reg(rd, pass);
5030 if (invert) {
5031 /* The immediate value has already been inverted, so
5032 BIC becomes AND. */
5033 tcg_gen_andi_i32(tmp, tmp, imm);
5034 } else {
5035 tcg_gen_ori_i32(tmp, tmp, imm);
5037 } else {
5038 /* VMOV, VMVN. */
5039 tmp = tcg_temp_new_i32();
5040 if (op == 14 && invert) {
5041 uint32_t val;
5042 val = 0;
5043 for (n = 0; n < 4; n++) {
5044 if (imm & (1 << (n + (pass & 1) * 4)))
5045 val |= 0xff << (n * 8);
5047 tcg_gen_movi_i32(tmp, val);
5048 } else {
5049 tcg_gen_movi_i32(tmp, imm);
5052 neon_store_reg(rd, pass, tmp);
5055 } else { /* (insn & 0x00800010 == 0x00800000) */
5056 if (size != 3) {
5057 op = (insn >> 8) & 0xf;
5058 if ((insn & (1 << 6)) == 0) {
5059 /* Three registers of different lengths. */
5060 int src1_wide;
5061 int src2_wide;
5062 int prewiden;
5063 /* prewiden, src1_wide, src2_wide */
5064 static const int neon_3reg_wide[16][3] = {
5065 {1, 0, 0}, /* VADDL */
5066 {1, 1, 0}, /* VADDW */
5067 {1, 0, 0}, /* VSUBL */
5068 {1, 1, 0}, /* VSUBW */
5069 {0, 1, 1}, /* VADDHN */
5070 {0, 0, 0}, /* VABAL */
5071 {0, 1, 1}, /* VSUBHN */
5072 {0, 0, 0}, /* VABDL */
5073 {0, 0, 0}, /* VMLAL */
5074 {0, 0, 0}, /* VQDMLAL */
5075 {0, 0, 0}, /* VMLSL */
5076 {0, 0, 0}, /* VQDMLSL */
5077 {0, 0, 0}, /* Integer VMULL */
5078 {0, 0, 0}, /* VQDMULL */
5079 {0, 0, 0} /* Polynomial VMULL */
5082 prewiden = neon_3reg_wide[op][0];
5083 src1_wide = neon_3reg_wide[op][1];
5084 src2_wide = neon_3reg_wide[op][2];
5086 if (size == 0 && (op == 9 || op == 11 || op == 13))
5087 return 1;
5089 /* Avoid overlapping operands. Wide source operands are
5090 always aligned so will never overlap with wide
5091 destinations in problematic ways. */
5092 if (rd == rm && !src2_wide) {
5093 tmp = neon_load_reg(rm, 1);
5094 neon_store_scratch(2, tmp);
5095 } else if (rd == rn && !src1_wide) {
5096 tmp = neon_load_reg(rn, 1);
5097 neon_store_scratch(2, tmp);
5099 TCGV_UNUSED(tmp3);
5100 for (pass = 0; pass < 2; pass++) {
5101 if (src1_wide) {
5102 neon_load_reg64(cpu_V0, rn + pass);
5103 TCGV_UNUSED(tmp);
5104 } else {
5105 if (pass == 1 && rd == rn) {
5106 tmp = neon_load_scratch(2);
5107 } else {
5108 tmp = neon_load_reg(rn, pass);
5110 if (prewiden) {
5111 gen_neon_widen(cpu_V0, tmp, size, u);
5114 if (src2_wide) {
5115 neon_load_reg64(cpu_V1, rm + pass);
5116 TCGV_UNUSED(tmp2);
5117 } else {
5118 if (pass == 1 && rd == rm) {
5119 tmp2 = neon_load_scratch(2);
5120 } else {
5121 tmp2 = neon_load_reg(rm, pass);
5123 if (prewiden) {
5124 gen_neon_widen(cpu_V1, tmp2, size, u);
5127 switch (op) {
5128 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5129 gen_neon_addl(size);
5130 break;
5131 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
5132 gen_neon_subl(size);
5133 break;
5134 case 5: case 7: /* VABAL, VABDL */
5135 switch ((size << 1) | u) {
5136 case 0:
5137 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
5138 break;
5139 case 1:
5140 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
5141 break;
5142 case 2:
5143 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
5144 break;
5145 case 3:
5146 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
5147 break;
5148 case 4:
5149 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
5150 break;
5151 case 5:
5152 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
5153 break;
5154 default: abort();
5156 tcg_temp_free_i32(tmp2);
5157 tcg_temp_free_i32(tmp);
5158 break;
5159 case 8: case 9: case 10: case 11: case 12: case 13:
5160 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5161 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5162 break;
5163 case 14: /* Polynomial VMULL */
5164 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
5165 tcg_temp_free_i32(tmp2);
5166 tcg_temp_free_i32(tmp);
5167 break;
5168 default: /* 15 is RESERVED. */
5169 return 1;
5171 if (op == 13) {
5172 /* VQDMULL */
5173 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5174 neon_store_reg64(cpu_V0, rd + pass);
5175 } else if (op == 5 || (op >= 8 && op <= 11)) {
5176 /* Accumulate. */
5177 neon_load_reg64(cpu_V1, rd + pass);
5178 switch (op) {
5179 case 10: /* VMLSL */
5180 gen_neon_negl(cpu_V0, size);
5181 /* Fall through */
5182 case 5: case 8: /* VABAL, VMLAL */
5183 gen_neon_addl(size);
5184 break;
5185 case 9: case 11: /* VQDMLAL, VQDMLSL */
5186 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5187 if (op == 11) {
5188 gen_neon_negl(cpu_V0, size);
5190 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5191 break;
5192 default:
5193 abort();
5195 neon_store_reg64(cpu_V0, rd + pass);
5196 } else if (op == 4 || op == 6) {
5197 /* Narrowing operation. */
5198 tmp = tcg_temp_new_i32();
5199 if (!u) {
5200 switch (size) {
5201 case 0:
5202 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
5203 break;
5204 case 1:
5205 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
5206 break;
5207 case 2:
5208 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5209 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5210 break;
5211 default: abort();
5213 } else {
5214 switch (size) {
5215 case 0:
5216 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
5217 break;
5218 case 1:
5219 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
5220 break;
5221 case 2:
5222 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
5223 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5224 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5225 break;
5226 default: abort();
5229 if (pass == 0) {
5230 tmp3 = tmp;
5231 } else {
5232 neon_store_reg(rd, 0, tmp3);
5233 neon_store_reg(rd, 1, tmp);
5235 } else {
5236 /* Write back the result. */
5237 neon_store_reg64(cpu_V0, rd + pass);
5240 } else {
5241 /* Two registers and a scalar. */
5242 switch (op) {
5243 case 0: /* Integer VMLA scalar */
5244 case 1: /* Float VMLA scalar */
5245 case 4: /* Integer VMLS scalar */
5246 case 5: /* Floating point VMLS scalar */
5247 case 8: /* Integer VMUL scalar */
5248 case 9: /* Floating point VMUL scalar */
5249 case 12: /* VQDMULH scalar */
5250 case 13: /* VQRDMULH scalar */
5251 tmp = neon_get_scalar(size, rm);
5252 neon_store_scratch(0, tmp);
5253 for (pass = 0; pass < (u ? 4 : 2); pass++) {
5254 tmp = neon_load_scratch(0);
5255 tmp2 = neon_load_reg(rn, pass);
5256 if (op == 12) {
5257 if (size == 1) {
5258 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5259 } else {
5260 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5262 } else if (op == 13) {
5263 if (size == 1) {
5264 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5265 } else {
5266 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5268 } else if (op & 1) {
5269 gen_helper_neon_mul_f32(tmp, tmp, tmp2);
5270 } else {
5271 switch (size) {
5272 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5273 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5274 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5275 default: return 1;
5278 tcg_temp_free_i32(tmp2);
5279 if (op < 8) {
5280 /* Accumulate. */
5281 tmp2 = neon_load_reg(rd, pass);
5282 switch (op) {
5283 case 0:
5284 gen_neon_add(size, tmp, tmp2);
5285 break;
5286 case 1:
5287 gen_helper_neon_add_f32(tmp, tmp, tmp2);
5288 break;
5289 case 4:
5290 gen_neon_rsb(size, tmp, tmp2);
5291 break;
5292 case 5:
5293 gen_helper_neon_sub_f32(tmp, tmp2, tmp);
5294 break;
5295 default:
5296 abort();
5298 tcg_temp_free_i32(tmp2);
5300 neon_store_reg(rd, pass, tmp);
5302 break;
5303 case 2: /* VMLAL sclar */
5304 case 3: /* VQDMLAL scalar */
5305 case 6: /* VMLSL scalar */
5306 case 7: /* VQDMLSL scalar */
5307 case 10: /* VMULL scalar */
5308 case 11: /* VQDMULL scalar */
5309 if (size == 0 && (op == 3 || op == 7 || op == 11))
5310 return 1;
5312 tmp2 = neon_get_scalar(size, rm);
5313 /* We need a copy of tmp2 because gen_neon_mull
5314 * deletes it during pass 0. */
5315 tmp4 = tcg_temp_new_i32();
5316 tcg_gen_mov_i32(tmp4, tmp2);
5317 tmp3 = neon_load_reg(rn, 1);
5319 for (pass = 0; pass < 2; pass++) {
5320 if (pass == 0) {
5321 tmp = neon_load_reg(rn, 0);
5322 } else {
5323 tmp = tmp3;
5324 tmp2 = tmp4;
5326 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5327 if (op != 11) {
5328 neon_load_reg64(cpu_V1, rd + pass);
5330 switch (op) {
5331 case 6:
5332 gen_neon_negl(cpu_V0, size);
5333 /* Fall through */
5334 case 2:
5335 gen_neon_addl(size);
5336 break;
5337 case 3: case 7:
5338 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5339 if (op == 7) {
5340 gen_neon_negl(cpu_V0, size);
5342 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5343 break;
5344 case 10:
5345 /* no-op */
5346 break;
5347 case 11:
5348 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5349 break;
5350 default:
5351 abort();
5353 neon_store_reg64(cpu_V0, rd + pass);
5357 break;
5358 default: /* 14 and 15 are RESERVED */
5359 return 1;
5362 } else { /* size == 3 */
5363 if (!u) {
5364 /* Extract. */
5365 imm = (insn >> 8) & 0xf;
5367 if (imm > 7 && !q)
5368 return 1;
5370 if (imm == 0) {
5371 neon_load_reg64(cpu_V0, rn);
5372 if (q) {
5373 neon_load_reg64(cpu_V1, rn + 1);
5375 } else if (imm == 8) {
5376 neon_load_reg64(cpu_V0, rn + 1);
5377 if (q) {
5378 neon_load_reg64(cpu_V1, rm);
5380 } else if (q) {
5381 tmp64 = tcg_temp_new_i64();
5382 if (imm < 8) {
5383 neon_load_reg64(cpu_V0, rn);
5384 neon_load_reg64(tmp64, rn + 1);
5385 } else {
5386 neon_load_reg64(cpu_V0, rn + 1);
5387 neon_load_reg64(tmp64, rm);
5389 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5390 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
5391 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5392 if (imm < 8) {
5393 neon_load_reg64(cpu_V1, rm);
5394 } else {
5395 neon_load_reg64(cpu_V1, rm + 1);
5396 imm -= 8;
5398 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5399 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
5400 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
5401 tcg_temp_free_i64(tmp64);
5402 } else {
5403 /* BUGFIX */
5404 neon_load_reg64(cpu_V0, rn);
5405 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
5406 neon_load_reg64(cpu_V1, rm);
5407 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5408 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5410 neon_store_reg64(cpu_V0, rd);
5411 if (q) {
5412 neon_store_reg64(cpu_V1, rd + 1);
5414 } else if ((insn & (1 << 11)) == 0) {
5415 /* Two register misc. */
5416 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5417 size = (insn >> 18) & 3;
5418 switch (op) {
5419 case 0: /* VREV64 */
5420 if (size == 3)
5421 return 1;
5422 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5423 tmp = neon_load_reg(rm, pass * 2);
5424 tmp2 = neon_load_reg(rm, pass * 2 + 1);
5425 switch (size) {
5426 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5427 case 1: gen_swap_half(tmp); break;
5428 case 2: /* no-op */ break;
5429 default: abort();
5431 neon_store_reg(rd, pass * 2 + 1, tmp);
5432 if (size == 2) {
5433 neon_store_reg(rd, pass * 2, tmp2);
5434 } else {
5435 switch (size) {
5436 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
5437 case 1: gen_swap_half(tmp2); break;
5438 default: abort();
5440 neon_store_reg(rd, pass * 2, tmp2);
5443 break;
5444 case 4: case 5: /* VPADDL */
5445 case 12: case 13: /* VPADAL */
5446 if (size == 3)
5447 return 1;
5448 for (pass = 0; pass < q + 1; pass++) {
5449 tmp = neon_load_reg(rm, pass * 2);
5450 gen_neon_widen(cpu_V0, tmp, size, op & 1);
5451 tmp = neon_load_reg(rm, pass * 2 + 1);
5452 gen_neon_widen(cpu_V1, tmp, size, op & 1);
5453 switch (size) {
5454 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5455 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5456 case 2: tcg_gen_add_i64(CPU_V001); break;
5457 default: abort();
5459 if (op >= 12) {
5460 /* Accumulate. */
5461 neon_load_reg64(cpu_V1, rd + pass);
5462 gen_neon_addl(size);
5464 neon_store_reg64(cpu_V0, rd + pass);
5466 break;
5467 case 33: /* VTRN */
5468 if (size == 2) {
5469 for (n = 0; n < (q ? 4 : 2); n += 2) {
5470 tmp = neon_load_reg(rm, n);
5471 tmp2 = neon_load_reg(rd, n + 1);
5472 neon_store_reg(rm, n, tmp2);
5473 neon_store_reg(rd, n + 1, tmp);
5475 } else {
5476 goto elementwise;
5478 break;
5479 case 34: /* VUZP */
5480 if (gen_neon_unzip(rd, rm, size, q)) {
5481 return 1;
5483 break;
5484 case 35: /* VZIP */
5485 if (gen_neon_zip(rd, rm, size, q)) {
5486 return 1;
5488 break;
5489 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5490 if (size == 3)
5491 return 1;
5492 TCGV_UNUSED(tmp2);
5493 for (pass = 0; pass < 2; pass++) {
5494 neon_load_reg64(cpu_V0, rm + pass);
5495 tmp = tcg_temp_new_i32();
5496 gen_neon_narrow_op(op == 36, q, size, tmp, cpu_V0);
5497 if (pass == 0) {
5498 tmp2 = tmp;
5499 } else {
5500 neon_store_reg(rd, 0, tmp2);
5501 neon_store_reg(rd, 1, tmp);
5504 break;
5505 case 38: /* VSHLL */
5506 if (q || size == 3)
5507 return 1;
5508 tmp = neon_load_reg(rm, 0);
5509 tmp2 = neon_load_reg(rm, 1);
5510 for (pass = 0; pass < 2; pass++) {
5511 if (pass == 1)
5512 tmp = tmp2;
5513 gen_neon_widen(cpu_V0, tmp, size, 1);
5514 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
5515 neon_store_reg64(cpu_V0, rd + pass);
5517 break;
5518 case 44: /* VCVT.F16.F32 */
5519 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
5520 return 1;
5521 tmp = tcg_temp_new_i32();
5522 tmp2 = tcg_temp_new_i32();
5523 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
5524 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5525 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
5526 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
5527 tcg_gen_shli_i32(tmp2, tmp2, 16);
5528 tcg_gen_or_i32(tmp2, tmp2, tmp);
5529 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
5530 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5531 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
5532 neon_store_reg(rd, 0, tmp2);
5533 tmp2 = tcg_temp_new_i32();
5534 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
5535 tcg_gen_shli_i32(tmp2, tmp2, 16);
5536 tcg_gen_or_i32(tmp2, tmp2, tmp);
5537 neon_store_reg(rd, 1, tmp2);
5538 tcg_temp_free_i32(tmp);
5539 break;
5540 case 46: /* VCVT.F32.F16 */
5541 if (!arm_feature(env, ARM_FEATURE_VFP_FP16))
5542 return 1;
5543 tmp3 = tcg_temp_new_i32();
5544 tmp = neon_load_reg(rm, 0);
5545 tmp2 = neon_load_reg(rm, 1);
5546 tcg_gen_ext16u_i32(tmp3, tmp);
5547 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5548 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
5549 tcg_gen_shri_i32(tmp3, tmp, 16);
5550 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5551 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
5552 tcg_temp_free_i32(tmp);
5553 tcg_gen_ext16u_i32(tmp3, tmp2);
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, 2));
5556 tcg_gen_shri_i32(tmp3, tmp2, 16);
5557 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
5558 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
5559 tcg_temp_free_i32(tmp2);
5560 tcg_temp_free_i32(tmp3);
5561 break;
5562 default:
5563 elementwise:
5564 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5565 if (op == 30 || op == 31 || op >= 58) {
5566 tcg_gen_ld_f32(cpu_F0s, cpu_env,
5567 neon_reg_offset(rm, pass));
5568 TCGV_UNUSED(tmp);
5569 } else {
5570 tmp = neon_load_reg(rm, pass);
5572 switch (op) {
5573 case 1: /* VREV32 */
5574 switch (size) {
5575 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5576 case 1: gen_swap_half(tmp); break;
5577 default: return 1;
5579 break;
5580 case 2: /* VREV16 */
5581 if (size != 0)
5582 return 1;
5583 gen_rev16(tmp);
5584 break;
5585 case 8: /* CLS */
5586 switch (size) {
5587 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
5588 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
5589 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
5590 default: return 1;
5592 break;
5593 case 9: /* CLZ */
5594 switch (size) {
5595 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
5596 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
5597 case 2: gen_helper_clz(tmp, tmp); break;
5598 default: return 1;
5600 break;
5601 case 10: /* CNT */
5602 if (size != 0)
5603 return 1;
5604 gen_helper_neon_cnt_u8(tmp, tmp);
5605 break;
5606 case 11: /* VNOT */
5607 if (size != 0)
5608 return 1;
5609 tcg_gen_not_i32(tmp, tmp);
5610 break;
5611 case 14: /* VQABS */
5612 switch (size) {
5613 case 0: gen_helper_neon_qabs_s8(tmp, cpu_env, tmp); break;
5614 case 1: gen_helper_neon_qabs_s16(tmp, cpu_env, tmp); break;
5615 case 2: gen_helper_neon_qabs_s32(tmp, cpu_env, tmp); break;
5616 default: return 1;
5618 break;
5619 case 15: /* VQNEG */
5620 switch (size) {
5621 case 0: gen_helper_neon_qneg_s8(tmp, cpu_env, tmp); break;
5622 case 1: gen_helper_neon_qneg_s16(tmp, cpu_env, tmp); break;
5623 case 2: gen_helper_neon_qneg_s32(tmp, cpu_env, tmp); break;
5624 default: return 1;
5626 break;
5627 case 16: case 19: /* VCGT #0, VCLE #0 */
5628 tmp2 = tcg_const_i32(0);
5629 switch(size) {
5630 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
5631 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
5632 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
5633 default: return 1;
5635 tcg_temp_free(tmp2);
5636 if (op == 19)
5637 tcg_gen_not_i32(tmp, tmp);
5638 break;
5639 case 17: case 20: /* VCGE #0, VCLT #0 */
5640 tmp2 = tcg_const_i32(0);
5641 switch(size) {
5642 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
5643 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
5644 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
5645 default: return 1;
5647 tcg_temp_free(tmp2);
5648 if (op == 20)
5649 tcg_gen_not_i32(tmp, tmp);
5650 break;
5651 case 18: /* VCEQ #0 */
5652 tmp2 = tcg_const_i32(0);
5653 switch(size) {
5654 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
5655 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
5656 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
5657 default: return 1;
5659 tcg_temp_free(tmp2);
5660 break;
5661 case 22: /* VABS */
5662 switch(size) {
5663 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
5664 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
5665 case 2: tcg_gen_abs_i32(tmp, tmp); break;
5666 default: return 1;
5668 break;
5669 case 23: /* VNEG */
5670 if (size == 3)
5671 return 1;
5672 tmp2 = tcg_const_i32(0);
5673 gen_neon_rsb(size, tmp, tmp2);
5674 tcg_temp_free(tmp2);
5675 break;
5676 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5677 tmp2 = tcg_const_i32(0);
5678 gen_helper_neon_cgt_f32(tmp, tmp, tmp2);
5679 tcg_temp_free(tmp2);
5680 if (op == 27)
5681 tcg_gen_not_i32(tmp, tmp);
5682 break;
5683 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5684 tmp2 = tcg_const_i32(0);
5685 gen_helper_neon_cge_f32(tmp, tmp, tmp2);
5686 tcg_temp_free(tmp2);
5687 if (op == 28)
5688 tcg_gen_not_i32(tmp, tmp);
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 30: /* Float VABS */
5696 gen_vfp_abs(0);
5697 break;
5698 case 31: /* Float VNEG */
5699 gen_vfp_neg(0);
5700 break;
5701 case 32: /* VSWP */
5702 tmp2 = neon_load_reg(rd, pass);
5703 neon_store_reg(rm, pass, tmp2);
5704 break;
5705 case 33: /* VTRN */
5706 tmp2 = neon_load_reg(rd, pass);
5707 switch (size) {
5708 case 0: gen_neon_trn_u8(tmp, tmp2); break;
5709 case 1: gen_neon_trn_u16(tmp, tmp2); break;
5710 case 2: abort();
5711 default: return 1;
5713 neon_store_reg(rm, pass, tmp2);
5714 break;
5715 case 56: /* Integer VRECPE */
5716 gen_helper_recpe_u32(tmp, tmp, cpu_env);
5717 break;
5718 case 57: /* Integer VRSQRTE */
5719 gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
5720 break;
5721 case 58: /* Float VRECPE */
5722 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
5723 break;
5724 case 59: /* Float VRSQRTE */
5725 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
5726 break;
5727 case 60: /* VCVT.F32.S32 */
5728 gen_vfp_sito(0);
5729 break;
5730 case 61: /* VCVT.F32.U32 */
5731 gen_vfp_uito(0);
5732 break;
5733 case 62: /* VCVT.S32.F32 */
5734 gen_vfp_tosiz(0);
5735 break;
5736 case 63: /* VCVT.U32.F32 */
5737 gen_vfp_touiz(0);
5738 break;
5739 default:
5740 /* Reserved: 21, 29, 39-56 */
5741 return 1;
5743 if (op == 30 || op == 31 || op >= 58) {
5744 tcg_gen_st_f32(cpu_F0s, cpu_env,
5745 neon_reg_offset(rd, pass));
5746 } else {
5747 neon_store_reg(rd, pass, tmp);
5750 break;
5752 } else if ((insn & (1 << 10)) == 0) {
5753 /* VTBL, VTBX. */
5754 n = ((insn >> 5) & 0x18) + 8;
5755 if (insn & (1 << 6)) {
5756 tmp = neon_load_reg(rd, 0);
5757 } else {
5758 tmp = tcg_temp_new_i32();
5759 tcg_gen_movi_i32(tmp, 0);
5761 tmp2 = neon_load_reg(rm, 0);
5762 tmp4 = tcg_const_i32(rn);
5763 tmp5 = tcg_const_i32(n);
5764 gen_helper_neon_tbl(tmp2, tmp2, tmp, tmp4, tmp5);
5765 tcg_temp_free_i32(tmp);
5766 if (insn & (1 << 6)) {
5767 tmp = neon_load_reg(rd, 1);
5768 } else {
5769 tmp = tcg_temp_new_i32();
5770 tcg_gen_movi_i32(tmp, 0);
5772 tmp3 = neon_load_reg(rm, 1);
5773 gen_helper_neon_tbl(tmp3, tmp3, tmp, tmp4, tmp5);
5774 tcg_temp_free_i32(tmp5);
5775 tcg_temp_free_i32(tmp4);
5776 neon_store_reg(rd, 0, tmp2);
5777 neon_store_reg(rd, 1, tmp3);
5778 tcg_temp_free_i32(tmp);
5779 } else if ((insn & 0x380) == 0) {
5780 /* VDUP */
5781 if (insn & (1 << 19)) {
5782 tmp = neon_load_reg(rm, 1);
5783 } else {
5784 tmp = neon_load_reg(rm, 0);
5786 if (insn & (1 << 16)) {
5787 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
5788 } else if (insn & (1 << 17)) {
5789 if ((insn >> 18) & 1)
5790 gen_neon_dup_high16(tmp);
5791 else
5792 gen_neon_dup_low16(tmp);
5794 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5795 tmp2 = tcg_temp_new_i32();
5796 tcg_gen_mov_i32(tmp2, tmp);
5797 neon_store_reg(rd, pass, tmp2);
5799 tcg_temp_free_i32(tmp);
5800 } else {
5801 return 1;
5805 return 0;
5808 static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
5810 int crn = (insn >> 16) & 0xf;
5811 int crm = insn & 0xf;
5812 int op1 = (insn >> 21) & 7;
5813 int op2 = (insn >> 5) & 7;
5814 int rt = (insn >> 12) & 0xf;
5815 TCGv tmp;
5817 /* Minimal set of debug registers, since we don't support debug */
5818 if (op1 == 0 && crn == 0 && op2 == 0) {
5819 switch (crm) {
5820 case 0:
5821 /* DBGDIDR: just RAZ. In particular this means the
5822 * "debug architecture version" bits will read as
5823 * a reserved value, which should cause Linux to
5824 * not try to use the debug hardware.
5826 tmp = tcg_const_i32(0);
5827 store_reg(s, rt, tmp);
5828 return 0;
5829 case 1:
5830 case 2:
5831 /* DBGDRAR and DBGDSAR: v7 only. Always RAZ since we
5832 * don't implement memory mapped debug components
5834 if (ENABLE_ARCH_7) {
5835 tmp = tcg_const_i32(0);
5836 store_reg(s, rt, tmp);
5837 return 0;
5839 break;
5840 default:
5841 break;
5845 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5846 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5847 /* TEECR */
5848 if (IS_USER(s))
5849 return 1;
5850 tmp = load_cpu_field(teecr);
5851 store_reg(s, rt, tmp);
5852 return 0;
5854 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5855 /* TEEHBR */
5856 if (IS_USER(s) && (env->teecr & 1))
5857 return 1;
5858 tmp = load_cpu_field(teehbr);
5859 store_reg(s, rt, tmp);
5860 return 0;
5863 fprintf(stderr, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5864 op1, crn, crm, op2);
5865 return 1;
5868 static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
5870 int crn = (insn >> 16) & 0xf;
5871 int crm = insn & 0xf;
5872 int op1 = (insn >> 21) & 7;
5873 int op2 = (insn >> 5) & 7;
5874 int rt = (insn >> 12) & 0xf;
5875 TCGv tmp;
5877 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
5878 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
5879 /* TEECR */
5880 if (IS_USER(s))
5881 return 1;
5882 tmp = load_reg(s, rt);
5883 gen_helper_set_teecr(cpu_env, tmp);
5884 tcg_temp_free_i32(tmp);
5885 return 0;
5887 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
5888 /* TEEHBR */
5889 if (IS_USER(s) && (env->teecr & 1))
5890 return 1;
5891 tmp = load_reg(s, rt);
5892 store_cpu_field(tmp, teehbr);
5893 return 0;
5896 fprintf(stderr, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5897 op1, crn, crm, op2);
5898 return 1;
5901 static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
5903 int cpnum;
5905 cpnum = (insn >> 8) & 0xf;
5906 if (arm_feature(env, ARM_FEATURE_XSCALE)
5907 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
5908 return 1;
5910 switch (cpnum) {
5911 case 0:
5912 case 1:
5913 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
5914 return disas_iwmmxt_insn(env, s, insn);
5915 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
5916 return disas_dsp_insn(env, s, insn);
5918 return 1;
5919 case 10:
5920 case 11:
5921 return disas_vfp_insn (env, s, insn);
5922 case 14:
5923 /* Coprocessors 7-15 are architecturally reserved by ARM.
5924 Unfortunately Intel decided to ignore this. */
5925 if (arm_feature(env, ARM_FEATURE_XSCALE))
5926 goto board;
5927 if (insn & (1 << 20))
5928 return disas_cp14_read(env, s, insn);
5929 else
5930 return disas_cp14_write(env, s, insn);
5931 case 15:
5932 return disas_cp15_insn (env, s, insn);
5933 default:
5934 board:
5935 /* Unknown coprocessor. See if the board has hooked it. */
5936 return disas_cp_insn (env, s, insn);
5941 /* Store a 64-bit value to a register pair. Clobbers val. */
5942 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
5944 TCGv tmp;
5945 tmp = tcg_temp_new_i32();
5946 tcg_gen_trunc_i64_i32(tmp, val);
5947 store_reg(s, rlow, tmp);
5948 tmp = tcg_temp_new_i32();
5949 tcg_gen_shri_i64(val, val, 32);
5950 tcg_gen_trunc_i64_i32(tmp, val);
5951 store_reg(s, rhigh, tmp);
5954 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5955 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
5957 TCGv_i64 tmp;
5958 TCGv tmp2;
5960 /* Load value and extend to 64 bits. */
5961 tmp = tcg_temp_new_i64();
5962 tmp2 = load_reg(s, rlow);
5963 tcg_gen_extu_i32_i64(tmp, tmp2);
5964 tcg_temp_free_i32(tmp2);
5965 tcg_gen_add_i64(val, val, tmp);
5966 tcg_temp_free_i64(tmp);
5969 /* load and add a 64-bit value from a register pair. */
5970 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
5972 TCGv_i64 tmp;
5973 TCGv tmpl;
5974 TCGv tmph;
5976 /* Load 64-bit value rd:rn. */
5977 tmpl = load_reg(s, rlow);
5978 tmph = load_reg(s, rhigh);
5979 tmp = tcg_temp_new_i64();
5980 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
5981 tcg_temp_free_i32(tmpl);
5982 tcg_temp_free_i32(tmph);
5983 tcg_gen_add_i64(val, val, tmp);
5984 tcg_temp_free_i64(tmp);
5987 /* Set N and Z flags from a 64-bit value. */
5988 static void gen_logicq_cc(TCGv_i64 val)
5990 TCGv tmp = tcg_temp_new_i32();
5991 gen_helper_logicq_cc(tmp, val);
5992 gen_logic_CC(tmp);
5993 tcg_temp_free_i32(tmp);
5996 /* Load/Store exclusive instructions are implemented by remembering
5997 the value/address loaded, and seeing if these are the same
5998 when the store is performed. This should be is sufficient to implement
5999 the architecturally mandated semantics, and avoids having to monitor
6000 regular stores.
6002 In system emulation mode only one CPU will be running at once, so
6003 this sequence is effectively atomic. In user emulation mode we
6004 throw an exception and handle the atomic operation elsewhere. */
6005 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
6006 TCGv addr, int size)
6008 TCGv tmp;
6010 switch (size) {
6011 case 0:
6012 tmp = gen_ld8u(addr, IS_USER(s));
6013 break;
6014 case 1:
6015 tmp = gen_ld16u(addr, IS_USER(s));
6016 break;
6017 case 2:
6018 case 3:
6019 tmp = gen_ld32(addr, IS_USER(s));
6020 break;
6021 default:
6022 abort();
6024 tcg_gen_mov_i32(cpu_exclusive_val, tmp);
6025 store_reg(s, rt, tmp);
6026 if (size == 3) {
6027 TCGv tmp2 = tcg_temp_new_i32();
6028 tcg_gen_addi_i32(tmp2, addr, 4);
6029 tmp = gen_ld32(tmp2, IS_USER(s));
6030 tcg_temp_free_i32(tmp2);
6031 tcg_gen_mov_i32(cpu_exclusive_high, tmp);
6032 store_reg(s, rt2, tmp);
6034 tcg_gen_mov_i32(cpu_exclusive_addr, addr);
6037 static void gen_clrex(DisasContext *s)
6039 tcg_gen_movi_i32(cpu_exclusive_addr, -1);
6042 #ifdef CONFIG_USER_ONLY
6043 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
6044 TCGv addr, int size)
6046 tcg_gen_mov_i32(cpu_exclusive_test, addr);
6047 tcg_gen_movi_i32(cpu_exclusive_info,
6048 size | (rd << 4) | (rt << 8) | (rt2 << 12));
6049 gen_exception_insn(s, 4, EXCP_STREX);
6051 #else
6052 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
6053 TCGv addr, int size)
6055 TCGv tmp;
6056 int done_label;
6057 int fail_label;
6059 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
6060 [addr] = {Rt};
6061 {Rd} = 0;
6062 } else {
6063 {Rd} = 1;
6064 } */
6065 fail_label = gen_new_label();
6066 done_label = gen_new_label();
6067 tcg_gen_brcond_i32(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
6068 switch (size) {
6069 case 0:
6070 tmp = gen_ld8u(addr, IS_USER(s));
6071 break;
6072 case 1:
6073 tmp = gen_ld16u(addr, IS_USER(s));
6074 break;
6075 case 2:
6076 case 3:
6077 tmp = gen_ld32(addr, IS_USER(s));
6078 break;
6079 default:
6080 abort();
6082 tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label);
6083 tcg_temp_free_i32(tmp);
6084 if (size == 3) {
6085 TCGv tmp2 = tcg_temp_new_i32();
6086 tcg_gen_addi_i32(tmp2, addr, 4);
6087 tmp = gen_ld32(tmp2, IS_USER(s));
6088 tcg_temp_free_i32(tmp2);
6089 tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_high, fail_label);
6090 tcg_temp_free_i32(tmp);
6092 tmp = load_reg(s, rt);
6093 switch (size) {
6094 case 0:
6095 gen_st8(tmp, addr, IS_USER(s));
6096 break;
6097 case 1:
6098 gen_st16(tmp, addr, IS_USER(s));
6099 break;
6100 case 2:
6101 case 3:
6102 gen_st32(tmp, addr, IS_USER(s));
6103 break;
6104 default:
6105 abort();
6107 if (size == 3) {
6108 tcg_gen_addi_i32(addr, addr, 4);
6109 tmp = load_reg(s, rt2);
6110 gen_st32(tmp, addr, IS_USER(s));
6112 tcg_gen_movi_i32(cpu_R[rd], 0);
6113 tcg_gen_br(done_label);
6114 gen_set_label(fail_label);
6115 tcg_gen_movi_i32(cpu_R[rd], 1);
6116 gen_set_label(done_label);
6117 tcg_gen_movi_i32(cpu_exclusive_addr, -1);
6119 #endif
6121 static void disas_arm_insn(CPUState * env, DisasContext *s)
6123 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
6124 TCGv tmp;
6125 TCGv tmp2;
6126 TCGv tmp3;
6127 TCGv addr;
6128 TCGv_i64 tmp64;
6130 insn = ldl_code(s->pc);
6131 s->pc += 4;
6133 /* M variants do not implement ARM mode. */
6134 if (IS_M(env))
6135 goto illegal_op;
6136 cond = insn >> 28;
6137 if (cond == 0xf){
6138 /* Unconditional instructions. */
6139 if (((insn >> 25) & 7) == 1) {
6140 /* NEON Data processing. */
6141 if (!arm_feature(env, ARM_FEATURE_NEON))
6142 goto illegal_op;
6144 if (disas_neon_data_insn(env, s, insn))
6145 goto illegal_op;
6146 return;
6148 if ((insn & 0x0f100000) == 0x04000000) {
6149 /* NEON load/store. */
6150 if (!arm_feature(env, ARM_FEATURE_NEON))
6151 goto illegal_op;
6153 if (disas_neon_ls_insn(env, s, insn))
6154 goto illegal_op;
6155 return;
6157 if (((insn & 0x0f30f000) == 0x0510f000) ||
6158 ((insn & 0x0f30f010) == 0x0710f000)) {
6159 if ((insn & (1 << 22)) == 0) {
6160 /* PLDW; v7MP */
6161 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
6162 goto illegal_op;
6165 /* Otherwise PLD; v5TE+ */
6166 return;
6168 if (((insn & 0x0f70f000) == 0x0450f000) ||
6169 ((insn & 0x0f70f010) == 0x0650f000)) {
6170 ARCH(7);
6171 return; /* PLI; V7 */
6173 if (((insn & 0x0f700000) == 0x04100000) ||
6174 ((insn & 0x0f700010) == 0x06100000)) {
6175 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
6176 goto illegal_op;
6178 return; /* v7MP: Unallocated memory hint: must NOP */
6181 if ((insn & 0x0ffffdff) == 0x01010000) {
6182 ARCH(6);
6183 /* setend */
6184 if (insn & (1 << 9)) {
6185 /* BE8 mode not implemented. */
6186 goto illegal_op;
6188 return;
6189 } else if ((insn & 0x0fffff00) == 0x057ff000) {
6190 switch ((insn >> 4) & 0xf) {
6191 case 1: /* clrex */
6192 ARCH(6K);
6193 gen_clrex(s);
6194 return;
6195 case 4: /* dsb */
6196 case 5: /* dmb */
6197 case 6: /* isb */
6198 ARCH(7);
6199 /* We don't emulate caches so these are a no-op. */
6200 return;
6201 default:
6202 goto illegal_op;
6204 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
6205 /* srs */
6206 int32_t offset;
6207 if (IS_USER(s))
6208 goto illegal_op;
6209 ARCH(6);
6210 op1 = (insn & 0x1f);
6211 addr = tcg_temp_new_i32();
6212 tmp = tcg_const_i32(op1);
6213 gen_helper_get_r13_banked(addr, cpu_env, tmp);
6214 tcg_temp_free_i32(tmp);
6215 i = (insn >> 23) & 3;
6216 switch (i) {
6217 case 0: offset = -4; break; /* DA */
6218 case 1: offset = 0; break; /* IA */
6219 case 2: offset = -8; break; /* DB */
6220 case 3: offset = 4; break; /* IB */
6221 default: abort();
6223 if (offset)
6224 tcg_gen_addi_i32(addr, addr, offset);
6225 tmp = load_reg(s, 14);
6226 gen_st32(tmp, addr, 0);
6227 tmp = load_cpu_field(spsr);
6228 tcg_gen_addi_i32(addr, addr, 4);
6229 gen_st32(tmp, addr, 0);
6230 if (insn & (1 << 21)) {
6231 /* Base writeback. */
6232 switch (i) {
6233 case 0: offset = -8; break;
6234 case 1: offset = 4; break;
6235 case 2: offset = -4; break;
6236 case 3: offset = 0; break;
6237 default: abort();
6239 if (offset)
6240 tcg_gen_addi_i32(addr, addr, offset);
6241 tmp = tcg_const_i32(op1);
6242 gen_helper_set_r13_banked(cpu_env, tmp, addr);
6243 tcg_temp_free_i32(tmp);
6244 tcg_temp_free_i32(addr);
6245 } else {
6246 tcg_temp_free_i32(addr);
6248 return;
6249 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
6250 /* rfe */
6251 int32_t offset;
6252 if (IS_USER(s))
6253 goto illegal_op;
6254 ARCH(6);
6255 rn = (insn >> 16) & 0xf;
6256 addr = load_reg(s, rn);
6257 i = (insn >> 23) & 3;
6258 switch (i) {
6259 case 0: offset = -4; break; /* DA */
6260 case 1: offset = 0; break; /* IA */
6261 case 2: offset = -8; break; /* DB */
6262 case 3: offset = 4; break; /* IB */
6263 default: abort();
6265 if (offset)
6266 tcg_gen_addi_i32(addr, addr, offset);
6267 /* Load PC into tmp and CPSR into tmp2. */
6268 tmp = gen_ld32(addr, 0);
6269 tcg_gen_addi_i32(addr, addr, 4);
6270 tmp2 = gen_ld32(addr, 0);
6271 if (insn & (1 << 21)) {
6272 /* Base writeback. */
6273 switch (i) {
6274 case 0: offset = -8; break;
6275 case 1: offset = 4; break;
6276 case 2: offset = -4; break;
6277 case 3: offset = 0; break;
6278 default: abort();
6280 if (offset)
6281 tcg_gen_addi_i32(addr, addr, offset);
6282 store_reg(s, rn, addr);
6283 } else {
6284 tcg_temp_free_i32(addr);
6286 gen_rfe(s, tmp, tmp2);
6287 return;
6288 } else if ((insn & 0x0e000000) == 0x0a000000) {
6289 /* branch link and change to thumb (blx <offset>) */
6290 int32_t offset;
6292 val = (uint32_t)s->pc;
6293 tmp = tcg_temp_new_i32();
6294 tcg_gen_movi_i32(tmp, val);
6295 store_reg(s, 14, tmp);
6296 /* Sign-extend the 24-bit offset */
6297 offset = (((int32_t)insn) << 8) >> 8;
6298 /* offset * 4 + bit24 * 2 + (thumb bit) */
6299 val += (offset << 2) | ((insn >> 23) & 2) | 1;
6300 /* pipeline offset */
6301 val += 4;
6302 gen_bx_im(s, val);
6303 return;
6304 } else if ((insn & 0x0e000f00) == 0x0c000100) {
6305 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
6306 /* iWMMXt register transfer. */
6307 if (env->cp15.c15_cpar & (1 << 1))
6308 if (!disas_iwmmxt_insn(env, s, insn))
6309 return;
6311 } else if ((insn & 0x0fe00000) == 0x0c400000) {
6312 /* Coprocessor double register transfer. */
6313 } else if ((insn & 0x0f000010) == 0x0e000010) {
6314 /* Additional coprocessor register transfer. */
6315 } else if ((insn & 0x0ff10020) == 0x01000000) {
6316 uint32_t mask;
6317 uint32_t val;
6318 /* cps (privileged) */
6319 if (IS_USER(s))
6320 return;
6321 mask = val = 0;
6322 if (insn & (1 << 19)) {
6323 if (insn & (1 << 8))
6324 mask |= CPSR_A;
6325 if (insn & (1 << 7))
6326 mask |= CPSR_I;
6327 if (insn & (1 << 6))
6328 mask |= CPSR_F;
6329 if (insn & (1 << 18))
6330 val |= mask;
6332 if (insn & (1 << 17)) {
6333 mask |= CPSR_M;
6334 val |= (insn & 0x1f);
6336 if (mask) {
6337 gen_set_psr_im(s, mask, 0, val);
6339 return;
6341 goto illegal_op;
6343 if (cond != 0xe) {
6344 /* if not always execute, we generate a conditional jump to
6345 next instruction */
6346 s->condlabel = gen_new_label();
6347 gen_test_cc(cond ^ 1, s->condlabel);
6348 s->condjmp = 1;
6350 if ((insn & 0x0f900000) == 0x03000000) {
6351 if ((insn & (1 << 21)) == 0) {
6352 ARCH(6T2);
6353 rd = (insn >> 12) & 0xf;
6354 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
6355 if ((insn & (1 << 22)) == 0) {
6356 /* MOVW */
6357 tmp = tcg_temp_new_i32();
6358 tcg_gen_movi_i32(tmp, val);
6359 } else {
6360 /* MOVT */
6361 tmp = load_reg(s, rd);
6362 tcg_gen_ext16u_i32(tmp, tmp);
6363 tcg_gen_ori_i32(tmp, tmp, val << 16);
6365 store_reg(s, rd, tmp);
6366 } else {
6367 if (((insn >> 12) & 0xf) != 0xf)
6368 goto illegal_op;
6369 if (((insn >> 16) & 0xf) == 0) {
6370 gen_nop_hint(s, insn & 0xff);
6371 } else {
6372 /* CPSR = immediate */
6373 val = insn & 0xff;
6374 shift = ((insn >> 8) & 0xf) * 2;
6375 if (shift)
6376 val = (val >> shift) | (val << (32 - shift));
6377 i = ((insn & (1 << 22)) != 0);
6378 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
6379 goto illegal_op;
6382 } else if ((insn & 0x0f900000) == 0x01000000
6383 && (insn & 0x00000090) != 0x00000090) {
6384 /* miscellaneous instructions */
6385 op1 = (insn >> 21) & 3;
6386 sh = (insn >> 4) & 0xf;
6387 rm = insn & 0xf;
6388 switch (sh) {
6389 case 0x0: /* move program status register */
6390 if (op1 & 1) {
6391 /* PSR = reg */
6392 tmp = load_reg(s, rm);
6393 i = ((op1 & 2) != 0);
6394 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
6395 goto illegal_op;
6396 } else {
6397 /* reg = PSR */
6398 rd = (insn >> 12) & 0xf;
6399 if (op1 & 2) {
6400 if (IS_USER(s))
6401 goto illegal_op;
6402 tmp = load_cpu_field(spsr);
6403 } else {
6404 tmp = tcg_temp_new_i32();
6405 gen_helper_cpsr_read(tmp);
6407 store_reg(s, rd, tmp);
6409 break;
6410 case 0x1:
6411 if (op1 == 1) {
6412 /* branch/exchange thumb (bx). */
6413 tmp = load_reg(s, rm);
6414 gen_bx(s, tmp);
6415 } else if (op1 == 3) {
6416 /* clz */
6417 rd = (insn >> 12) & 0xf;
6418 tmp = load_reg(s, rm);
6419 gen_helper_clz(tmp, tmp);
6420 store_reg(s, rd, tmp);
6421 } else {
6422 goto illegal_op;
6424 break;
6425 case 0x2:
6426 if (op1 == 1) {
6427 ARCH(5J); /* bxj */
6428 /* Trivial implementation equivalent to bx. */
6429 tmp = load_reg(s, rm);
6430 gen_bx(s, tmp);
6431 } else {
6432 goto illegal_op;
6434 break;
6435 case 0x3:
6436 if (op1 != 1)
6437 goto illegal_op;
6439 /* branch link/exchange thumb (blx) */
6440 tmp = load_reg(s, rm);
6441 tmp2 = tcg_temp_new_i32();
6442 tcg_gen_movi_i32(tmp2, s->pc);
6443 store_reg(s, 14, tmp2);
6444 gen_bx(s, tmp);
6445 break;
6446 case 0x5: /* saturating add/subtract */
6447 rd = (insn >> 12) & 0xf;
6448 rn = (insn >> 16) & 0xf;
6449 tmp = load_reg(s, rm);
6450 tmp2 = load_reg(s, rn);
6451 if (op1 & 2)
6452 gen_helper_double_saturate(tmp2, tmp2);
6453 if (op1 & 1)
6454 gen_helper_sub_saturate(tmp, tmp, tmp2);
6455 else
6456 gen_helper_add_saturate(tmp, tmp, tmp2);
6457 tcg_temp_free_i32(tmp2);
6458 store_reg(s, rd, tmp);
6459 break;
6460 case 7:
6461 /* SMC instruction (op1 == 3)
6462 and undefined instructions (op1 == 0 || op1 == 2)
6463 will trap */
6464 if (op1 != 1) {
6465 goto illegal_op;
6467 /* bkpt */
6468 gen_exception_insn(s, 4, EXCP_BKPT);
6469 break;
6470 case 0x8: /* signed multiply */
6471 case 0xa:
6472 case 0xc:
6473 case 0xe:
6474 rs = (insn >> 8) & 0xf;
6475 rn = (insn >> 12) & 0xf;
6476 rd = (insn >> 16) & 0xf;
6477 if (op1 == 1) {
6478 /* (32 * 16) >> 16 */
6479 tmp = load_reg(s, rm);
6480 tmp2 = load_reg(s, rs);
6481 if (sh & 4)
6482 tcg_gen_sari_i32(tmp2, tmp2, 16);
6483 else
6484 gen_sxth(tmp2);
6485 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6486 tcg_gen_shri_i64(tmp64, tmp64, 16);
6487 tmp = tcg_temp_new_i32();
6488 tcg_gen_trunc_i64_i32(tmp, tmp64);
6489 tcg_temp_free_i64(tmp64);
6490 if ((sh & 2) == 0) {
6491 tmp2 = load_reg(s, rn);
6492 gen_helper_add_setq(tmp, tmp, tmp2);
6493 tcg_temp_free_i32(tmp2);
6495 store_reg(s, rd, tmp);
6496 } else {
6497 /* 16 * 16 */
6498 tmp = load_reg(s, rm);
6499 tmp2 = load_reg(s, rs);
6500 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
6501 tcg_temp_free_i32(tmp2);
6502 if (op1 == 2) {
6503 tmp64 = tcg_temp_new_i64();
6504 tcg_gen_ext_i32_i64(tmp64, tmp);
6505 tcg_temp_free_i32(tmp);
6506 gen_addq(s, tmp64, rn, rd);
6507 gen_storeq_reg(s, rn, rd, tmp64);
6508 tcg_temp_free_i64(tmp64);
6509 } else {
6510 if (op1 == 0) {
6511 tmp2 = load_reg(s, rn);
6512 gen_helper_add_setq(tmp, tmp, tmp2);
6513 tcg_temp_free_i32(tmp2);
6515 store_reg(s, rd, tmp);
6518 break;
6519 default:
6520 goto illegal_op;
6522 } else if (((insn & 0x0e000000) == 0 &&
6523 (insn & 0x00000090) != 0x90) ||
6524 ((insn & 0x0e000000) == (1 << 25))) {
6525 int set_cc, logic_cc, shiftop;
6527 op1 = (insn >> 21) & 0xf;
6528 set_cc = (insn >> 20) & 1;
6529 logic_cc = table_logic_cc[op1] & set_cc;
6531 /* data processing instruction */
6532 if (insn & (1 << 25)) {
6533 /* immediate operand */
6534 val = insn & 0xff;
6535 shift = ((insn >> 8) & 0xf) * 2;
6536 if (shift) {
6537 val = (val >> shift) | (val << (32 - shift));
6539 tmp2 = tcg_temp_new_i32();
6540 tcg_gen_movi_i32(tmp2, val);
6541 if (logic_cc && shift) {
6542 gen_set_CF_bit31(tmp2);
6544 } else {
6545 /* register */
6546 rm = (insn) & 0xf;
6547 tmp2 = load_reg(s, rm);
6548 shiftop = (insn >> 5) & 3;
6549 if (!(insn & (1 << 4))) {
6550 shift = (insn >> 7) & 0x1f;
6551 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
6552 } else {
6553 rs = (insn >> 8) & 0xf;
6554 tmp = load_reg(s, rs);
6555 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
6558 if (op1 != 0x0f && op1 != 0x0d) {
6559 rn = (insn >> 16) & 0xf;
6560 tmp = load_reg(s, rn);
6561 } else {
6562 TCGV_UNUSED(tmp);
6564 rd = (insn >> 12) & 0xf;
6565 switch(op1) {
6566 case 0x00:
6567 tcg_gen_and_i32(tmp, tmp, tmp2);
6568 if (logic_cc) {
6569 gen_logic_CC(tmp);
6571 store_reg_bx(env, s, rd, tmp);
6572 break;
6573 case 0x01:
6574 tcg_gen_xor_i32(tmp, tmp, tmp2);
6575 if (logic_cc) {
6576 gen_logic_CC(tmp);
6578 store_reg_bx(env, s, rd, tmp);
6579 break;
6580 case 0x02:
6581 if (set_cc && rd == 15) {
6582 /* SUBS r15, ... is used for exception return. */
6583 if (IS_USER(s)) {
6584 goto illegal_op;
6586 gen_helper_sub_cc(tmp, tmp, tmp2);
6587 gen_exception_return(s, tmp);
6588 } else {
6589 if (set_cc) {
6590 gen_helper_sub_cc(tmp, tmp, tmp2);
6591 } else {
6592 tcg_gen_sub_i32(tmp, tmp, tmp2);
6594 store_reg_bx(env, s, rd, tmp);
6596 break;
6597 case 0x03:
6598 if (set_cc) {
6599 gen_helper_sub_cc(tmp, tmp2, tmp);
6600 } else {
6601 tcg_gen_sub_i32(tmp, tmp2, tmp);
6603 store_reg_bx(env, s, rd, tmp);
6604 break;
6605 case 0x04:
6606 if (set_cc) {
6607 gen_helper_add_cc(tmp, tmp, tmp2);
6608 } else {
6609 tcg_gen_add_i32(tmp, tmp, tmp2);
6611 store_reg_bx(env, s, rd, tmp);
6612 break;
6613 case 0x05:
6614 if (set_cc) {
6615 gen_helper_adc_cc(tmp, tmp, tmp2);
6616 } else {
6617 gen_add_carry(tmp, tmp, tmp2);
6619 store_reg_bx(env, s, rd, tmp);
6620 break;
6621 case 0x06:
6622 if (set_cc) {
6623 gen_helper_sbc_cc(tmp, tmp, tmp2);
6624 } else {
6625 gen_sub_carry(tmp, tmp, tmp2);
6627 store_reg_bx(env, s, rd, tmp);
6628 break;
6629 case 0x07:
6630 if (set_cc) {
6631 gen_helper_sbc_cc(tmp, tmp2, tmp);
6632 } else {
6633 gen_sub_carry(tmp, tmp2, tmp);
6635 store_reg_bx(env, s, rd, tmp);
6636 break;
6637 case 0x08:
6638 if (set_cc) {
6639 tcg_gen_and_i32(tmp, tmp, tmp2);
6640 gen_logic_CC(tmp);
6642 tcg_temp_free_i32(tmp);
6643 break;
6644 case 0x09:
6645 if (set_cc) {
6646 tcg_gen_xor_i32(tmp, tmp, tmp2);
6647 gen_logic_CC(tmp);
6649 tcg_temp_free_i32(tmp);
6650 break;
6651 case 0x0a:
6652 if (set_cc) {
6653 gen_helper_sub_cc(tmp, tmp, tmp2);
6655 tcg_temp_free_i32(tmp);
6656 break;
6657 case 0x0b:
6658 if (set_cc) {
6659 gen_helper_add_cc(tmp, tmp, tmp2);
6661 tcg_temp_free_i32(tmp);
6662 break;
6663 case 0x0c:
6664 tcg_gen_or_i32(tmp, tmp, tmp2);
6665 if (logic_cc) {
6666 gen_logic_CC(tmp);
6668 store_reg_bx(env, s, rd, tmp);
6669 break;
6670 case 0x0d:
6671 if (logic_cc && rd == 15) {
6672 /* MOVS r15, ... is used for exception return. */
6673 if (IS_USER(s)) {
6674 goto illegal_op;
6676 gen_exception_return(s, tmp2);
6677 } else {
6678 if (logic_cc) {
6679 gen_logic_CC(tmp2);
6681 store_reg_bx(env, s, rd, tmp2);
6683 break;
6684 case 0x0e:
6685 tcg_gen_andc_i32(tmp, tmp, tmp2);
6686 if (logic_cc) {
6687 gen_logic_CC(tmp);
6689 store_reg_bx(env, s, rd, tmp);
6690 break;
6691 default:
6692 case 0x0f:
6693 tcg_gen_not_i32(tmp2, tmp2);
6694 if (logic_cc) {
6695 gen_logic_CC(tmp2);
6697 store_reg_bx(env, s, rd, tmp2);
6698 break;
6700 if (op1 != 0x0f && op1 != 0x0d) {
6701 tcg_temp_free_i32(tmp2);
6703 } else {
6704 /* other instructions */
6705 op1 = (insn >> 24) & 0xf;
6706 switch(op1) {
6707 case 0x0:
6708 case 0x1:
6709 /* multiplies, extra load/stores */
6710 sh = (insn >> 5) & 3;
6711 if (sh == 0) {
6712 if (op1 == 0x0) {
6713 rd = (insn >> 16) & 0xf;
6714 rn = (insn >> 12) & 0xf;
6715 rs = (insn >> 8) & 0xf;
6716 rm = (insn) & 0xf;
6717 op1 = (insn >> 20) & 0xf;
6718 switch (op1) {
6719 case 0: case 1: case 2: case 3: case 6:
6720 /* 32 bit mul */
6721 tmp = load_reg(s, rs);
6722 tmp2 = load_reg(s, rm);
6723 tcg_gen_mul_i32(tmp, tmp, tmp2);
6724 tcg_temp_free_i32(tmp2);
6725 if (insn & (1 << 22)) {
6726 /* Subtract (mls) */
6727 ARCH(6T2);
6728 tmp2 = load_reg(s, rn);
6729 tcg_gen_sub_i32(tmp, tmp2, tmp);
6730 tcg_temp_free_i32(tmp2);
6731 } else if (insn & (1 << 21)) {
6732 /* Add */
6733 tmp2 = load_reg(s, rn);
6734 tcg_gen_add_i32(tmp, tmp, tmp2);
6735 tcg_temp_free_i32(tmp2);
6737 if (insn & (1 << 20))
6738 gen_logic_CC(tmp);
6739 store_reg(s, rd, tmp);
6740 break;
6741 case 4:
6742 /* 64 bit mul double accumulate (UMAAL) */
6743 ARCH(6);
6744 tmp = load_reg(s, rs);
6745 tmp2 = load_reg(s, rm);
6746 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
6747 gen_addq_lo(s, tmp64, rn);
6748 gen_addq_lo(s, tmp64, rd);
6749 gen_storeq_reg(s, rn, rd, tmp64);
6750 tcg_temp_free_i64(tmp64);
6751 break;
6752 case 8: case 9: case 10: case 11:
6753 case 12: case 13: case 14: case 15:
6754 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
6755 tmp = load_reg(s, rs);
6756 tmp2 = load_reg(s, rm);
6757 if (insn & (1 << 22)) {
6758 tmp64 = gen_muls_i64_i32(tmp, tmp2);
6759 } else {
6760 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
6762 if (insn & (1 << 21)) { /* mult accumulate */
6763 gen_addq(s, tmp64, rn, rd);
6765 if (insn & (1 << 20)) {
6766 gen_logicq_cc(tmp64);
6768 gen_storeq_reg(s, rn, rd, tmp64);
6769 tcg_temp_free_i64(tmp64);
6770 break;
6771 default:
6772 goto illegal_op;
6774 } else {
6775 rn = (insn >> 16) & 0xf;
6776 rd = (insn >> 12) & 0xf;
6777 if (insn & (1 << 23)) {
6778 /* load/store exclusive */
6779 op1 = (insn >> 21) & 0x3;
6780 if (op1)
6781 ARCH(6K);
6782 else
6783 ARCH(6);
6784 addr = tcg_temp_local_new_i32();
6785 load_reg_var(s, addr, rn);
6786 if (insn & (1 << 20)) {
6787 switch (op1) {
6788 case 0: /* ldrex */
6789 gen_load_exclusive(s, rd, 15, addr, 2);
6790 break;
6791 case 1: /* ldrexd */
6792 gen_load_exclusive(s, rd, rd + 1, addr, 3);
6793 break;
6794 case 2: /* ldrexb */
6795 gen_load_exclusive(s, rd, 15, addr, 0);
6796 break;
6797 case 3: /* ldrexh */
6798 gen_load_exclusive(s, rd, 15, addr, 1);
6799 break;
6800 default:
6801 abort();
6803 } else {
6804 rm = insn & 0xf;
6805 switch (op1) {
6806 case 0: /* strex */
6807 gen_store_exclusive(s, rd, rm, 15, addr, 2);
6808 break;
6809 case 1: /* strexd */
6810 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
6811 break;
6812 case 2: /* strexb */
6813 gen_store_exclusive(s, rd, rm, 15, addr, 0);
6814 break;
6815 case 3: /* strexh */
6816 gen_store_exclusive(s, rd, rm, 15, addr, 1);
6817 break;
6818 default:
6819 abort();
6822 tcg_temp_free(addr);
6823 } else {
6824 /* SWP instruction */
6825 rm = (insn) & 0xf;
6827 /* ??? This is not really atomic. However we know
6828 we never have multiple CPUs running in parallel,
6829 so it is good enough. */
6830 addr = load_reg(s, rn);
6831 tmp = load_reg(s, rm);
6832 if (insn & (1 << 22)) {
6833 tmp2 = gen_ld8u(addr, IS_USER(s));
6834 gen_st8(tmp, addr, IS_USER(s));
6835 } else {
6836 tmp2 = gen_ld32(addr, IS_USER(s));
6837 gen_st32(tmp, addr, IS_USER(s));
6839 tcg_temp_free_i32(addr);
6840 store_reg(s, rd, tmp2);
6843 } else {
6844 int address_offset;
6845 int load;
6846 /* Misc load/store */
6847 rn = (insn >> 16) & 0xf;
6848 rd = (insn >> 12) & 0xf;
6849 addr = load_reg(s, rn);
6850 if (insn & (1 << 24))
6851 gen_add_datah_offset(s, insn, 0, addr);
6852 address_offset = 0;
6853 if (insn & (1 << 20)) {
6854 /* load */
6855 switch(sh) {
6856 case 1:
6857 tmp = gen_ld16u(addr, IS_USER(s));
6858 break;
6859 case 2:
6860 tmp = gen_ld8s(addr, IS_USER(s));
6861 break;
6862 default:
6863 case 3:
6864 tmp = gen_ld16s(addr, IS_USER(s));
6865 break;
6867 load = 1;
6868 } else if (sh & 2) {
6869 /* doubleword */
6870 if (sh & 1) {
6871 /* store */
6872 tmp = load_reg(s, rd);
6873 gen_st32(tmp, addr, IS_USER(s));
6874 tcg_gen_addi_i32(addr, addr, 4);
6875 tmp = load_reg(s, rd + 1);
6876 gen_st32(tmp, addr, IS_USER(s));
6877 load = 0;
6878 } else {
6879 /* load */
6880 tmp = gen_ld32(addr, IS_USER(s));
6881 store_reg(s, rd, tmp);
6882 tcg_gen_addi_i32(addr, addr, 4);
6883 tmp = gen_ld32(addr, IS_USER(s));
6884 rd++;
6885 load = 1;
6887 address_offset = -4;
6888 } else {
6889 /* store */
6890 tmp = load_reg(s, rd);
6891 gen_st16(tmp, addr, IS_USER(s));
6892 load = 0;
6894 /* Perform base writeback before the loaded value to
6895 ensure correct behavior with overlapping index registers.
6896 ldrd with base writeback is is undefined if the
6897 destination and index registers overlap. */
6898 if (!(insn & (1 << 24))) {
6899 gen_add_datah_offset(s, insn, address_offset, addr);
6900 store_reg(s, rn, addr);
6901 } else if (insn & (1 << 21)) {
6902 if (address_offset)
6903 tcg_gen_addi_i32(addr, addr, address_offset);
6904 store_reg(s, rn, addr);
6905 } else {
6906 tcg_temp_free_i32(addr);
6908 if (load) {
6909 /* Complete the load. */
6910 store_reg(s, rd, tmp);
6913 break;
6914 case 0x4:
6915 case 0x5:
6916 goto do_ldst;
6917 case 0x6:
6918 case 0x7:
6919 if (insn & (1 << 4)) {
6920 ARCH(6);
6921 /* Armv6 Media instructions. */
6922 rm = insn & 0xf;
6923 rn = (insn >> 16) & 0xf;
6924 rd = (insn >> 12) & 0xf;
6925 rs = (insn >> 8) & 0xf;
6926 switch ((insn >> 23) & 3) {
6927 case 0: /* Parallel add/subtract. */
6928 op1 = (insn >> 20) & 7;
6929 tmp = load_reg(s, rn);
6930 tmp2 = load_reg(s, rm);
6931 sh = (insn >> 5) & 7;
6932 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
6933 goto illegal_op;
6934 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
6935 tcg_temp_free_i32(tmp2);
6936 store_reg(s, rd, tmp);
6937 break;
6938 case 1:
6939 if ((insn & 0x00700020) == 0) {
6940 /* Halfword pack. */
6941 tmp = load_reg(s, rn);
6942 tmp2 = load_reg(s, rm);
6943 shift = (insn >> 7) & 0x1f;
6944 if (insn & (1 << 6)) {
6945 /* pkhtb */
6946 if (shift == 0)
6947 shift = 31;
6948 tcg_gen_sari_i32(tmp2, tmp2, shift);
6949 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
6950 tcg_gen_ext16u_i32(tmp2, tmp2);
6951 } else {
6952 /* pkhbt */
6953 if (shift)
6954 tcg_gen_shli_i32(tmp2, tmp2, shift);
6955 tcg_gen_ext16u_i32(tmp, tmp);
6956 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
6958 tcg_gen_or_i32(tmp, tmp, tmp2);
6959 tcg_temp_free_i32(tmp2);
6960 store_reg(s, rd, tmp);
6961 } else if ((insn & 0x00200020) == 0x00200000) {
6962 /* [us]sat */
6963 tmp = load_reg(s, rm);
6964 shift = (insn >> 7) & 0x1f;
6965 if (insn & (1 << 6)) {
6966 if (shift == 0)
6967 shift = 31;
6968 tcg_gen_sari_i32(tmp, tmp, shift);
6969 } else {
6970 tcg_gen_shli_i32(tmp, tmp, shift);
6972 sh = (insn >> 16) & 0x1f;
6973 tmp2 = tcg_const_i32(sh);
6974 if (insn & (1 << 22))
6975 gen_helper_usat(tmp, tmp, tmp2);
6976 else
6977 gen_helper_ssat(tmp, tmp, tmp2);
6978 tcg_temp_free_i32(tmp2);
6979 store_reg(s, rd, tmp);
6980 } else if ((insn & 0x00300fe0) == 0x00200f20) {
6981 /* [us]sat16 */
6982 tmp = load_reg(s, rm);
6983 sh = (insn >> 16) & 0x1f;
6984 tmp2 = tcg_const_i32(sh);
6985 if (insn & (1 << 22))
6986 gen_helper_usat16(tmp, tmp, tmp2);
6987 else
6988 gen_helper_ssat16(tmp, tmp, tmp2);
6989 tcg_temp_free_i32(tmp2);
6990 store_reg(s, rd, tmp);
6991 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
6992 /* Select bytes. */
6993 tmp = load_reg(s, rn);
6994 tmp2 = load_reg(s, rm);
6995 tmp3 = tcg_temp_new_i32();
6996 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
6997 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
6998 tcg_temp_free_i32(tmp3);
6999 tcg_temp_free_i32(tmp2);
7000 store_reg(s, rd, tmp);
7001 } else if ((insn & 0x000003e0) == 0x00000060) {
7002 tmp = load_reg(s, rm);
7003 shift = (insn >> 10) & 3;
7004 /* ??? In many cases it's not neccessary to do a
7005 rotate, a shift is sufficient. */
7006 if (shift != 0)
7007 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
7008 op1 = (insn >> 20) & 7;
7009 switch (op1) {
7010 case 0: gen_sxtb16(tmp); break;
7011 case 2: gen_sxtb(tmp); break;
7012 case 3: gen_sxth(tmp); break;
7013 case 4: gen_uxtb16(tmp); break;
7014 case 6: gen_uxtb(tmp); break;
7015 case 7: gen_uxth(tmp); break;
7016 default: goto illegal_op;
7018 if (rn != 15) {
7019 tmp2 = load_reg(s, rn);
7020 if ((op1 & 3) == 0) {
7021 gen_add16(tmp, tmp2);
7022 } else {
7023 tcg_gen_add_i32(tmp, tmp, tmp2);
7024 tcg_temp_free_i32(tmp2);
7027 store_reg(s, rd, tmp);
7028 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
7029 /* rev */
7030 tmp = load_reg(s, rm);
7031 if (insn & (1 << 22)) {
7032 if (insn & (1 << 7)) {
7033 gen_revsh(tmp);
7034 } else {
7035 ARCH(6T2);
7036 gen_helper_rbit(tmp, tmp);
7038 } else {
7039 if (insn & (1 << 7))
7040 gen_rev16(tmp);
7041 else
7042 tcg_gen_bswap32_i32(tmp, tmp);
7044 store_reg(s, rd, tmp);
7045 } else {
7046 goto illegal_op;
7048 break;
7049 case 2: /* Multiplies (Type 3). */
7050 tmp = load_reg(s, rm);
7051 tmp2 = load_reg(s, rs);
7052 if (insn & (1 << 20)) {
7053 /* Signed multiply most significant [accumulate].
7054 (SMMUL, SMMLA, SMMLS) */
7055 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7057 if (rd != 15) {
7058 tmp = load_reg(s, rd);
7059 if (insn & (1 << 6)) {
7060 tmp64 = gen_subq_msw(tmp64, tmp);
7061 } else {
7062 tmp64 = gen_addq_msw(tmp64, tmp);
7065 if (insn & (1 << 5)) {
7066 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
7068 tcg_gen_shri_i64(tmp64, tmp64, 32);
7069 tmp = tcg_temp_new_i32();
7070 tcg_gen_trunc_i64_i32(tmp, tmp64);
7071 tcg_temp_free_i64(tmp64);
7072 store_reg(s, rn, tmp);
7073 } else {
7074 if (insn & (1 << 5))
7075 gen_swap_half(tmp2);
7076 gen_smul_dual(tmp, tmp2);
7077 if (insn & (1 << 6)) {
7078 /* This subtraction cannot overflow. */
7079 tcg_gen_sub_i32(tmp, tmp, tmp2);
7080 } else {
7081 /* This addition cannot overflow 32 bits;
7082 * however it may overflow considered as a signed
7083 * operation, in which case we must set the Q flag.
7085 gen_helper_add_setq(tmp, tmp, tmp2);
7087 tcg_temp_free_i32(tmp2);
7088 if (insn & (1 << 22)) {
7089 /* smlald, smlsld */
7090 tmp64 = tcg_temp_new_i64();
7091 tcg_gen_ext_i32_i64(tmp64, tmp);
7092 tcg_temp_free_i32(tmp);
7093 gen_addq(s, tmp64, rd, rn);
7094 gen_storeq_reg(s, rd, rn, tmp64);
7095 tcg_temp_free_i64(tmp64);
7096 } else {
7097 /* smuad, smusd, smlad, smlsd */
7098 if (rd != 15)
7100 tmp2 = load_reg(s, rd);
7101 gen_helper_add_setq(tmp, tmp, tmp2);
7102 tcg_temp_free_i32(tmp2);
7104 store_reg(s, rn, tmp);
7107 break;
7108 case 3:
7109 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
7110 switch (op1) {
7111 case 0: /* Unsigned sum of absolute differences. */
7112 ARCH(6);
7113 tmp = load_reg(s, rm);
7114 tmp2 = load_reg(s, rs);
7115 gen_helper_usad8(tmp, tmp, tmp2);
7116 tcg_temp_free_i32(tmp2);
7117 if (rd != 15) {
7118 tmp2 = load_reg(s, rd);
7119 tcg_gen_add_i32(tmp, tmp, tmp2);
7120 tcg_temp_free_i32(tmp2);
7122 store_reg(s, rn, tmp);
7123 break;
7124 case 0x20: case 0x24: case 0x28: case 0x2c:
7125 /* Bitfield insert/clear. */
7126 ARCH(6T2);
7127 shift = (insn >> 7) & 0x1f;
7128 i = (insn >> 16) & 0x1f;
7129 i = i + 1 - shift;
7130 if (rm == 15) {
7131 tmp = tcg_temp_new_i32();
7132 tcg_gen_movi_i32(tmp, 0);
7133 } else {
7134 tmp = load_reg(s, rm);
7136 if (i != 32) {
7137 tmp2 = load_reg(s, rd);
7138 gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
7139 tcg_temp_free_i32(tmp2);
7141 store_reg(s, rd, tmp);
7142 break;
7143 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
7144 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
7145 ARCH(6T2);
7146 tmp = load_reg(s, rm);
7147 shift = (insn >> 7) & 0x1f;
7148 i = ((insn >> 16) & 0x1f) + 1;
7149 if (shift + i > 32)
7150 goto illegal_op;
7151 if (i < 32) {
7152 if (op1 & 0x20) {
7153 gen_ubfx(tmp, shift, (1u << i) - 1);
7154 } else {
7155 gen_sbfx(tmp, shift, i);
7158 store_reg(s, rd, tmp);
7159 break;
7160 default:
7161 goto illegal_op;
7163 break;
7165 break;
7167 do_ldst:
7168 /* Check for undefined extension instructions
7169 * per the ARM Bible IE:
7170 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
7172 sh = (0xf << 20) | (0xf << 4);
7173 if (op1 == 0x7 && ((insn & sh) == sh))
7175 goto illegal_op;
7177 /* load/store byte/word */
7178 rn = (insn >> 16) & 0xf;
7179 rd = (insn >> 12) & 0xf;
7180 tmp2 = load_reg(s, rn);
7181 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
7182 if (insn & (1 << 24))
7183 gen_add_data_offset(s, insn, tmp2);
7184 if (insn & (1 << 20)) {
7185 /* load */
7186 if (insn & (1 << 22)) {
7187 tmp = gen_ld8u(tmp2, i);
7188 } else {
7189 tmp = gen_ld32(tmp2, i);
7191 } else {
7192 /* store */
7193 tmp = load_reg(s, rd);
7194 if (insn & (1 << 22))
7195 gen_st8(tmp, tmp2, i);
7196 else
7197 gen_st32(tmp, tmp2, i);
7199 if (!(insn & (1 << 24))) {
7200 gen_add_data_offset(s, insn, tmp2);
7201 store_reg(s, rn, tmp2);
7202 } else if (insn & (1 << 21)) {
7203 store_reg(s, rn, tmp2);
7204 } else {
7205 tcg_temp_free_i32(tmp2);
7207 if (insn & (1 << 20)) {
7208 /* Complete the load. */
7209 if (rd == 15)
7210 gen_bx(s, tmp);
7211 else
7212 store_reg(s, rd, tmp);
7214 break;
7215 case 0x08:
7216 case 0x09:
7218 int j, n, user, loaded_base;
7219 TCGv loaded_var;
7220 /* load/store multiple words */
7221 /* XXX: store correct base if write back */
7222 user = 0;
7223 if (insn & (1 << 22)) {
7224 if (IS_USER(s))
7225 goto illegal_op; /* only usable in supervisor mode */
7227 if ((insn & (1 << 15)) == 0)
7228 user = 1;
7230 rn = (insn >> 16) & 0xf;
7231 addr = load_reg(s, rn);
7233 /* compute total size */
7234 loaded_base = 0;
7235 TCGV_UNUSED(loaded_var);
7236 n = 0;
7237 for(i=0;i<16;i++) {
7238 if (insn & (1 << i))
7239 n++;
7241 /* XXX: test invalid n == 0 case ? */
7242 if (insn & (1 << 23)) {
7243 if (insn & (1 << 24)) {
7244 /* pre increment */
7245 tcg_gen_addi_i32(addr, addr, 4);
7246 } else {
7247 /* post increment */
7249 } else {
7250 if (insn & (1 << 24)) {
7251 /* pre decrement */
7252 tcg_gen_addi_i32(addr, addr, -(n * 4));
7253 } else {
7254 /* post decrement */
7255 if (n != 1)
7256 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7259 j = 0;
7260 for(i=0;i<16;i++) {
7261 if (insn & (1 << i)) {
7262 if (insn & (1 << 20)) {
7263 /* load */
7264 tmp = gen_ld32(addr, IS_USER(s));
7265 if (i == 15) {
7266 gen_bx(s, tmp);
7267 } else if (user) {
7268 tmp2 = tcg_const_i32(i);
7269 gen_helper_set_user_reg(tmp2, tmp);
7270 tcg_temp_free_i32(tmp2);
7271 tcg_temp_free_i32(tmp);
7272 } else if (i == rn) {
7273 loaded_var = tmp;
7274 loaded_base = 1;
7275 } else {
7276 store_reg(s, i, tmp);
7278 } else {
7279 /* store */
7280 if (i == 15) {
7281 /* special case: r15 = PC + 8 */
7282 val = (long)s->pc + 4;
7283 tmp = tcg_temp_new_i32();
7284 tcg_gen_movi_i32(tmp, val);
7285 } else if (user) {
7286 tmp = tcg_temp_new_i32();
7287 tmp2 = tcg_const_i32(i);
7288 gen_helper_get_user_reg(tmp, tmp2);
7289 tcg_temp_free_i32(tmp2);
7290 } else {
7291 tmp = load_reg(s, i);
7293 gen_st32(tmp, addr, IS_USER(s));
7295 j++;
7296 /* no need to add after the last transfer */
7297 if (j != n)
7298 tcg_gen_addi_i32(addr, addr, 4);
7301 if (insn & (1 << 21)) {
7302 /* write back */
7303 if (insn & (1 << 23)) {
7304 if (insn & (1 << 24)) {
7305 /* pre increment */
7306 } else {
7307 /* post increment */
7308 tcg_gen_addi_i32(addr, addr, 4);
7310 } else {
7311 if (insn & (1 << 24)) {
7312 /* pre decrement */
7313 if (n != 1)
7314 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7315 } else {
7316 /* post decrement */
7317 tcg_gen_addi_i32(addr, addr, -(n * 4));
7320 store_reg(s, rn, addr);
7321 } else {
7322 tcg_temp_free_i32(addr);
7324 if (loaded_base) {
7325 store_reg(s, rn, loaded_var);
7327 if ((insn & (1 << 22)) && !user) {
7328 /* Restore CPSR from SPSR. */
7329 tmp = load_cpu_field(spsr);
7330 gen_set_cpsr(tmp, 0xffffffff);
7331 tcg_temp_free_i32(tmp);
7332 s->is_jmp = DISAS_UPDATE;
7335 break;
7336 case 0xa:
7337 case 0xb:
7339 int32_t offset;
7341 /* branch (and link) */
7342 val = (int32_t)s->pc;
7343 if (insn & (1 << 24)) {
7344 tmp = tcg_temp_new_i32();
7345 tcg_gen_movi_i32(tmp, val);
7346 store_reg(s, 14, tmp);
7348 offset = (((int32_t)insn << 8) >> 8);
7349 val += (offset << 2) + 4;
7350 gen_jmp(s, val);
7352 break;
7353 case 0xc:
7354 case 0xd:
7355 case 0xe:
7356 /* Coprocessor. */
7357 if (disas_coproc_insn(env, s, insn))
7358 goto illegal_op;
7359 break;
7360 case 0xf:
7361 /* swi */
7362 gen_set_pc_im(s->pc);
7363 s->is_jmp = DISAS_SWI;
7364 break;
7365 default:
7366 illegal_op:
7367 gen_exception_insn(s, 4, EXCP_UDEF);
7368 break;
7373 /* Return true if this is a Thumb-2 logical op. */
7374 static int
7375 thumb2_logic_op(int op)
7377 return (op < 8);
7380 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7381 then set condition code flags based on the result of the operation.
7382 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7383 to the high bit of T1.
7384 Returns zero if the opcode is valid. */
7386 static int
7387 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCGv t0, TCGv t1)
7389 int logic_cc;
7391 logic_cc = 0;
7392 switch (op) {
7393 case 0: /* and */
7394 tcg_gen_and_i32(t0, t0, t1);
7395 logic_cc = conds;
7396 break;
7397 case 1: /* bic */
7398 tcg_gen_andc_i32(t0, t0, t1);
7399 logic_cc = conds;
7400 break;
7401 case 2: /* orr */
7402 tcg_gen_or_i32(t0, t0, t1);
7403 logic_cc = conds;
7404 break;
7405 case 3: /* orn */
7406 tcg_gen_orc_i32(t0, t0, t1);
7407 logic_cc = conds;
7408 break;
7409 case 4: /* eor */
7410 tcg_gen_xor_i32(t0, t0, t1);
7411 logic_cc = conds;
7412 break;
7413 case 8: /* add */
7414 if (conds)
7415 gen_helper_add_cc(t0, t0, t1);
7416 else
7417 tcg_gen_add_i32(t0, t0, t1);
7418 break;
7419 case 10: /* adc */
7420 if (conds)
7421 gen_helper_adc_cc(t0, t0, t1);
7422 else
7423 gen_adc(t0, t1);
7424 break;
7425 case 11: /* sbc */
7426 if (conds)
7427 gen_helper_sbc_cc(t0, t0, t1);
7428 else
7429 gen_sub_carry(t0, t0, t1);
7430 break;
7431 case 13: /* sub */
7432 if (conds)
7433 gen_helper_sub_cc(t0, t0, t1);
7434 else
7435 tcg_gen_sub_i32(t0, t0, t1);
7436 break;
7437 case 14: /* rsb */
7438 if (conds)
7439 gen_helper_sub_cc(t0, t1, t0);
7440 else
7441 tcg_gen_sub_i32(t0, t1, t0);
7442 break;
7443 default: /* 5, 6, 7, 9, 12, 15. */
7444 return 1;
7446 if (logic_cc) {
7447 gen_logic_CC(t0);
7448 if (shifter_out)
7449 gen_set_CF_bit31(t1);
7451 return 0;
7454 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7455 is not legal. */
7456 static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7458 uint32_t insn, imm, shift, offset;
7459 uint32_t rd, rn, rm, rs;
7460 TCGv tmp;
7461 TCGv tmp2;
7462 TCGv tmp3;
7463 TCGv addr;
7464 TCGv_i64 tmp64;
7465 int op;
7466 int shiftop;
7467 int conds;
7468 int logic_cc;
7470 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
7471 || arm_feature (env, ARM_FEATURE_M))) {
7472 /* Thumb-1 cores may need to treat bl and blx as a pair of
7473 16-bit instructions to get correct prefetch abort behavior. */
7474 insn = insn_hw1;
7475 if ((insn & (1 << 12)) == 0) {
7476 /* Second half of blx. */
7477 offset = ((insn & 0x7ff) << 1);
7478 tmp = load_reg(s, 14);
7479 tcg_gen_addi_i32(tmp, tmp, offset);
7480 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
7482 tmp2 = tcg_temp_new_i32();
7483 tcg_gen_movi_i32(tmp2, s->pc | 1);
7484 store_reg(s, 14, tmp2);
7485 gen_bx(s, tmp);
7486 return 0;
7488 if (insn & (1 << 11)) {
7489 /* Second half of bl. */
7490 offset = ((insn & 0x7ff) << 1) | 1;
7491 tmp = load_reg(s, 14);
7492 tcg_gen_addi_i32(tmp, tmp, offset);
7494 tmp2 = tcg_temp_new_i32();
7495 tcg_gen_movi_i32(tmp2, s->pc | 1);
7496 store_reg(s, 14, tmp2);
7497 gen_bx(s, tmp);
7498 return 0;
7500 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
7501 /* Instruction spans a page boundary. Implement it as two
7502 16-bit instructions in case the second half causes an
7503 prefetch abort. */
7504 offset = ((int32_t)insn << 21) >> 9;
7505 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
7506 return 0;
7508 /* Fall through to 32-bit decode. */
7511 insn = lduw_code(s->pc);
7512 s->pc += 2;
7513 insn |= (uint32_t)insn_hw1 << 16;
7515 if ((insn & 0xf800e800) != 0xf000e800) {
7516 ARCH(6T2);
7519 rn = (insn >> 16) & 0xf;
7520 rs = (insn >> 12) & 0xf;
7521 rd = (insn >> 8) & 0xf;
7522 rm = insn & 0xf;
7523 switch ((insn >> 25) & 0xf) {
7524 case 0: case 1: case 2: case 3:
7525 /* 16-bit instructions. Should never happen. */
7526 abort();
7527 case 4:
7528 if (insn & (1 << 22)) {
7529 /* Other load/store, table branch. */
7530 if (insn & 0x01200000) {
7531 /* Load/store doubleword. */
7532 if (rn == 15) {
7533 addr = tcg_temp_new_i32();
7534 tcg_gen_movi_i32(addr, s->pc & ~3);
7535 } else {
7536 addr = load_reg(s, rn);
7538 offset = (insn & 0xff) * 4;
7539 if ((insn & (1 << 23)) == 0)
7540 offset = -offset;
7541 if (insn & (1 << 24)) {
7542 tcg_gen_addi_i32(addr, addr, offset);
7543 offset = 0;
7545 if (insn & (1 << 20)) {
7546 /* ldrd */
7547 tmp = gen_ld32(addr, IS_USER(s));
7548 store_reg(s, rs, tmp);
7549 tcg_gen_addi_i32(addr, addr, 4);
7550 tmp = gen_ld32(addr, IS_USER(s));
7551 store_reg(s, rd, tmp);
7552 } else {
7553 /* strd */
7554 tmp = load_reg(s, rs);
7555 gen_st32(tmp, addr, IS_USER(s));
7556 tcg_gen_addi_i32(addr, addr, 4);
7557 tmp = load_reg(s, rd);
7558 gen_st32(tmp, addr, IS_USER(s));
7560 if (insn & (1 << 21)) {
7561 /* Base writeback. */
7562 if (rn == 15)
7563 goto illegal_op;
7564 tcg_gen_addi_i32(addr, addr, offset - 4);
7565 store_reg(s, rn, addr);
7566 } else {
7567 tcg_temp_free_i32(addr);
7569 } else if ((insn & (1 << 23)) == 0) {
7570 /* Load/store exclusive word. */
7571 addr = tcg_temp_local_new();
7572 load_reg_var(s, addr, rn);
7573 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
7574 if (insn & (1 << 20)) {
7575 gen_load_exclusive(s, rs, 15, addr, 2);
7576 } else {
7577 gen_store_exclusive(s, rd, rs, 15, addr, 2);
7579 tcg_temp_free(addr);
7580 } else if ((insn & (1 << 6)) == 0) {
7581 /* Table Branch. */
7582 if (rn == 15) {
7583 addr = tcg_temp_new_i32();
7584 tcg_gen_movi_i32(addr, s->pc);
7585 } else {
7586 addr = load_reg(s, rn);
7588 tmp = load_reg(s, rm);
7589 tcg_gen_add_i32(addr, addr, tmp);
7590 if (insn & (1 << 4)) {
7591 /* tbh */
7592 tcg_gen_add_i32(addr, addr, tmp);
7593 tcg_temp_free_i32(tmp);
7594 tmp = gen_ld16u(addr, IS_USER(s));
7595 } else { /* tbb */
7596 tcg_temp_free_i32(tmp);
7597 tmp = gen_ld8u(addr, IS_USER(s));
7599 tcg_temp_free_i32(addr);
7600 tcg_gen_shli_i32(tmp, tmp, 1);
7601 tcg_gen_addi_i32(tmp, tmp, s->pc);
7602 store_reg(s, 15, tmp);
7603 } else {
7604 /* Load/store exclusive byte/halfword/doubleword. */
7605 ARCH(7);
7606 op = (insn >> 4) & 0x3;
7607 if (op == 2) {
7608 goto illegal_op;
7610 addr = tcg_temp_local_new();
7611 load_reg_var(s, addr, rn);
7612 if (insn & (1 << 20)) {
7613 gen_load_exclusive(s, rs, rd, addr, op);
7614 } else {
7615 gen_store_exclusive(s, rm, rs, rd, addr, op);
7617 tcg_temp_free(addr);
7619 } else {
7620 /* Load/store multiple, RFE, SRS. */
7621 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
7622 /* Not available in user mode. */
7623 if (IS_USER(s))
7624 goto illegal_op;
7625 if (insn & (1 << 20)) {
7626 /* rfe */
7627 addr = load_reg(s, rn);
7628 if ((insn & (1 << 24)) == 0)
7629 tcg_gen_addi_i32(addr, addr, -8);
7630 /* Load PC into tmp and CPSR into tmp2. */
7631 tmp = gen_ld32(addr, 0);
7632 tcg_gen_addi_i32(addr, addr, 4);
7633 tmp2 = gen_ld32(addr, 0);
7634 if (insn & (1 << 21)) {
7635 /* Base writeback. */
7636 if (insn & (1 << 24)) {
7637 tcg_gen_addi_i32(addr, addr, 4);
7638 } else {
7639 tcg_gen_addi_i32(addr, addr, -4);
7641 store_reg(s, rn, addr);
7642 } else {
7643 tcg_temp_free_i32(addr);
7645 gen_rfe(s, tmp, tmp2);
7646 } else {
7647 /* srs */
7648 op = (insn & 0x1f);
7649 addr = tcg_temp_new_i32();
7650 tmp = tcg_const_i32(op);
7651 gen_helper_get_r13_banked(addr, cpu_env, tmp);
7652 tcg_temp_free_i32(tmp);
7653 if ((insn & (1 << 24)) == 0) {
7654 tcg_gen_addi_i32(addr, addr, -8);
7656 tmp = load_reg(s, 14);
7657 gen_st32(tmp, addr, 0);
7658 tcg_gen_addi_i32(addr, addr, 4);
7659 tmp = tcg_temp_new_i32();
7660 gen_helper_cpsr_read(tmp);
7661 gen_st32(tmp, addr, 0);
7662 if (insn & (1 << 21)) {
7663 if ((insn & (1 << 24)) == 0) {
7664 tcg_gen_addi_i32(addr, addr, -4);
7665 } else {
7666 tcg_gen_addi_i32(addr, addr, 4);
7668 tmp = tcg_const_i32(op);
7669 gen_helper_set_r13_banked(cpu_env, tmp, addr);
7670 tcg_temp_free_i32(tmp);
7671 } else {
7672 tcg_temp_free_i32(addr);
7675 } else {
7676 int i;
7677 /* Load/store multiple. */
7678 addr = load_reg(s, rn);
7679 offset = 0;
7680 for (i = 0; i < 16; i++) {
7681 if (insn & (1 << i))
7682 offset += 4;
7684 if (insn & (1 << 24)) {
7685 tcg_gen_addi_i32(addr, addr, -offset);
7688 for (i = 0; i < 16; i++) {
7689 if ((insn & (1 << i)) == 0)
7690 continue;
7691 if (insn & (1 << 20)) {
7692 /* Load. */
7693 tmp = gen_ld32(addr, IS_USER(s));
7694 if (i == 15) {
7695 gen_bx(s, tmp);
7696 } else {
7697 store_reg(s, i, tmp);
7699 } else {
7700 /* Store. */
7701 tmp = load_reg(s, i);
7702 gen_st32(tmp, addr, IS_USER(s));
7704 tcg_gen_addi_i32(addr, addr, 4);
7706 if (insn & (1 << 21)) {
7707 /* Base register writeback. */
7708 if (insn & (1 << 24)) {
7709 tcg_gen_addi_i32(addr, addr, -offset);
7711 /* Fault if writeback register is in register list. */
7712 if (insn & (1 << rn))
7713 goto illegal_op;
7714 store_reg(s, rn, addr);
7715 } else {
7716 tcg_temp_free_i32(addr);
7720 break;
7721 case 5:
7723 op = (insn >> 21) & 0xf;
7724 if (op == 6) {
7725 /* Halfword pack. */
7726 tmp = load_reg(s, rn);
7727 tmp2 = load_reg(s, rm);
7728 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
7729 if (insn & (1 << 5)) {
7730 /* pkhtb */
7731 if (shift == 0)
7732 shift = 31;
7733 tcg_gen_sari_i32(tmp2, tmp2, shift);
7734 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
7735 tcg_gen_ext16u_i32(tmp2, tmp2);
7736 } else {
7737 /* pkhbt */
7738 if (shift)
7739 tcg_gen_shli_i32(tmp2, tmp2, shift);
7740 tcg_gen_ext16u_i32(tmp, tmp);
7741 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
7743 tcg_gen_or_i32(tmp, tmp, tmp2);
7744 tcg_temp_free_i32(tmp2);
7745 store_reg(s, rd, tmp);
7746 } else {
7747 /* Data processing register constant shift. */
7748 if (rn == 15) {
7749 tmp = tcg_temp_new_i32();
7750 tcg_gen_movi_i32(tmp, 0);
7751 } else {
7752 tmp = load_reg(s, rn);
7754 tmp2 = load_reg(s, rm);
7756 shiftop = (insn >> 4) & 3;
7757 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
7758 conds = (insn & (1 << 20)) != 0;
7759 logic_cc = (conds && thumb2_logic_op(op));
7760 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
7761 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
7762 goto illegal_op;
7763 tcg_temp_free_i32(tmp2);
7764 if (rd != 15) {
7765 store_reg(s, rd, tmp);
7766 } else {
7767 tcg_temp_free_i32(tmp);
7770 break;
7771 case 13: /* Misc data processing. */
7772 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
7773 if (op < 4 && (insn & 0xf000) != 0xf000)
7774 goto illegal_op;
7775 switch (op) {
7776 case 0: /* Register controlled shift. */
7777 tmp = load_reg(s, rn);
7778 tmp2 = load_reg(s, rm);
7779 if ((insn & 0x70) != 0)
7780 goto illegal_op;
7781 op = (insn >> 21) & 3;
7782 logic_cc = (insn & (1 << 20)) != 0;
7783 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
7784 if (logic_cc)
7785 gen_logic_CC(tmp);
7786 store_reg_bx(env, s, rd, tmp);
7787 break;
7788 case 1: /* Sign/zero extend. */
7789 tmp = load_reg(s, rm);
7790 shift = (insn >> 4) & 3;
7791 /* ??? In many cases it's not neccessary to do a
7792 rotate, a shift is sufficient. */
7793 if (shift != 0)
7794 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
7795 op = (insn >> 20) & 7;
7796 switch (op) {
7797 case 0: gen_sxth(tmp); break;
7798 case 1: gen_uxth(tmp); break;
7799 case 2: gen_sxtb16(tmp); break;
7800 case 3: gen_uxtb16(tmp); break;
7801 case 4: gen_sxtb(tmp); break;
7802 case 5: gen_uxtb(tmp); break;
7803 default: goto illegal_op;
7805 if (rn != 15) {
7806 tmp2 = load_reg(s, rn);
7807 if ((op >> 1) == 1) {
7808 gen_add16(tmp, tmp2);
7809 } else {
7810 tcg_gen_add_i32(tmp, tmp, tmp2);
7811 tcg_temp_free_i32(tmp2);
7814 store_reg(s, rd, tmp);
7815 break;
7816 case 2: /* SIMD add/subtract. */
7817 op = (insn >> 20) & 7;
7818 shift = (insn >> 4) & 7;
7819 if ((op & 3) == 3 || (shift & 3) == 3)
7820 goto illegal_op;
7821 tmp = load_reg(s, rn);
7822 tmp2 = load_reg(s, rm);
7823 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
7824 tcg_temp_free_i32(tmp2);
7825 store_reg(s, rd, tmp);
7826 break;
7827 case 3: /* Other data processing. */
7828 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
7829 if (op < 4) {
7830 /* Saturating add/subtract. */
7831 tmp = load_reg(s, rn);
7832 tmp2 = load_reg(s, rm);
7833 if (op & 1)
7834 gen_helper_double_saturate(tmp, tmp);
7835 if (op & 2)
7836 gen_helper_sub_saturate(tmp, tmp2, tmp);
7837 else
7838 gen_helper_add_saturate(tmp, tmp, tmp2);
7839 tcg_temp_free_i32(tmp2);
7840 } else {
7841 tmp = load_reg(s, rn);
7842 switch (op) {
7843 case 0x0a: /* rbit */
7844 gen_helper_rbit(tmp, tmp);
7845 break;
7846 case 0x08: /* rev */
7847 tcg_gen_bswap32_i32(tmp, tmp);
7848 break;
7849 case 0x09: /* rev16 */
7850 gen_rev16(tmp);
7851 break;
7852 case 0x0b: /* revsh */
7853 gen_revsh(tmp);
7854 break;
7855 case 0x10: /* sel */
7856 tmp2 = load_reg(s, rm);
7857 tmp3 = tcg_temp_new_i32();
7858 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
7859 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7860 tcg_temp_free_i32(tmp3);
7861 tcg_temp_free_i32(tmp2);
7862 break;
7863 case 0x18: /* clz */
7864 gen_helper_clz(tmp, tmp);
7865 break;
7866 default:
7867 goto illegal_op;
7870 store_reg(s, rd, tmp);
7871 break;
7872 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7873 op = (insn >> 4) & 0xf;
7874 tmp = load_reg(s, rn);
7875 tmp2 = load_reg(s, rm);
7876 switch ((insn >> 20) & 7) {
7877 case 0: /* 32 x 32 -> 32 */
7878 tcg_gen_mul_i32(tmp, tmp, tmp2);
7879 tcg_temp_free_i32(tmp2);
7880 if (rs != 15) {
7881 tmp2 = load_reg(s, rs);
7882 if (op)
7883 tcg_gen_sub_i32(tmp, tmp2, tmp);
7884 else
7885 tcg_gen_add_i32(tmp, tmp, tmp2);
7886 tcg_temp_free_i32(tmp2);
7888 break;
7889 case 1: /* 16 x 16 -> 32 */
7890 gen_mulxy(tmp, tmp2, op & 2, op & 1);
7891 tcg_temp_free_i32(tmp2);
7892 if (rs != 15) {
7893 tmp2 = load_reg(s, rs);
7894 gen_helper_add_setq(tmp, tmp, tmp2);
7895 tcg_temp_free_i32(tmp2);
7897 break;
7898 case 2: /* Dual multiply add. */
7899 case 4: /* Dual multiply subtract. */
7900 if (op)
7901 gen_swap_half(tmp2);
7902 gen_smul_dual(tmp, tmp2);
7903 if (insn & (1 << 22)) {
7904 /* This subtraction cannot overflow. */
7905 tcg_gen_sub_i32(tmp, tmp, tmp2);
7906 } else {
7907 /* This addition cannot overflow 32 bits;
7908 * however it may overflow considered as a signed
7909 * operation, in which case we must set the Q flag.
7911 gen_helper_add_setq(tmp, tmp, tmp2);
7913 tcg_temp_free_i32(tmp2);
7914 if (rs != 15)
7916 tmp2 = load_reg(s, rs);
7917 gen_helper_add_setq(tmp, tmp, tmp2);
7918 tcg_temp_free_i32(tmp2);
7920 break;
7921 case 3: /* 32 * 16 -> 32msb */
7922 if (op)
7923 tcg_gen_sari_i32(tmp2, tmp2, 16);
7924 else
7925 gen_sxth(tmp2);
7926 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7927 tcg_gen_shri_i64(tmp64, tmp64, 16);
7928 tmp = tcg_temp_new_i32();
7929 tcg_gen_trunc_i64_i32(tmp, tmp64);
7930 tcg_temp_free_i64(tmp64);
7931 if (rs != 15)
7933 tmp2 = load_reg(s, rs);
7934 gen_helper_add_setq(tmp, tmp, tmp2);
7935 tcg_temp_free_i32(tmp2);
7937 break;
7938 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
7939 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7940 if (rs != 15) {
7941 tmp = load_reg(s, rs);
7942 if (insn & (1 << 20)) {
7943 tmp64 = gen_addq_msw(tmp64, tmp);
7944 } else {
7945 tmp64 = gen_subq_msw(tmp64, tmp);
7948 if (insn & (1 << 4)) {
7949 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
7951 tcg_gen_shri_i64(tmp64, tmp64, 32);
7952 tmp = tcg_temp_new_i32();
7953 tcg_gen_trunc_i64_i32(tmp, tmp64);
7954 tcg_temp_free_i64(tmp64);
7955 break;
7956 case 7: /* Unsigned sum of absolute differences. */
7957 gen_helper_usad8(tmp, tmp, tmp2);
7958 tcg_temp_free_i32(tmp2);
7959 if (rs != 15) {
7960 tmp2 = load_reg(s, rs);
7961 tcg_gen_add_i32(tmp, tmp, tmp2);
7962 tcg_temp_free_i32(tmp2);
7964 break;
7966 store_reg(s, rd, tmp);
7967 break;
7968 case 6: case 7: /* 64-bit multiply, Divide. */
7969 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
7970 tmp = load_reg(s, rn);
7971 tmp2 = load_reg(s, rm);
7972 if ((op & 0x50) == 0x10) {
7973 /* sdiv, udiv */
7974 if (!arm_feature(env, ARM_FEATURE_DIV))
7975 goto illegal_op;
7976 if (op & 0x20)
7977 gen_helper_udiv(tmp, tmp, tmp2);
7978 else
7979 gen_helper_sdiv(tmp, tmp, tmp2);
7980 tcg_temp_free_i32(tmp2);
7981 store_reg(s, rd, tmp);
7982 } else if ((op & 0xe) == 0xc) {
7983 /* Dual multiply accumulate long. */
7984 if (op & 1)
7985 gen_swap_half(tmp2);
7986 gen_smul_dual(tmp, tmp2);
7987 if (op & 0x10) {
7988 tcg_gen_sub_i32(tmp, tmp, tmp2);
7989 } else {
7990 tcg_gen_add_i32(tmp, tmp, tmp2);
7992 tcg_temp_free_i32(tmp2);
7993 /* BUGFIX */
7994 tmp64 = tcg_temp_new_i64();
7995 tcg_gen_ext_i32_i64(tmp64, tmp);
7996 tcg_temp_free_i32(tmp);
7997 gen_addq(s, tmp64, rs, rd);
7998 gen_storeq_reg(s, rs, rd, tmp64);
7999 tcg_temp_free_i64(tmp64);
8000 } else {
8001 if (op & 0x20) {
8002 /* Unsigned 64-bit multiply */
8003 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
8004 } else {
8005 if (op & 8) {
8006 /* smlalxy */
8007 gen_mulxy(tmp, tmp2, op & 2, op & 1);
8008 tcg_temp_free_i32(tmp2);
8009 tmp64 = tcg_temp_new_i64();
8010 tcg_gen_ext_i32_i64(tmp64, tmp);
8011 tcg_temp_free_i32(tmp);
8012 } else {
8013 /* Signed 64-bit multiply */
8014 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8017 if (op & 4) {
8018 /* umaal */
8019 gen_addq_lo(s, tmp64, rs);
8020 gen_addq_lo(s, tmp64, rd);
8021 } else if (op & 0x40) {
8022 /* 64-bit accumulate. */
8023 gen_addq(s, tmp64, rs, rd);
8025 gen_storeq_reg(s, rs, rd, tmp64);
8026 tcg_temp_free_i64(tmp64);
8028 break;
8030 break;
8031 case 6: case 7: case 14: case 15:
8032 /* Coprocessor. */
8033 if (((insn >> 24) & 3) == 3) {
8034 /* Translate into the equivalent ARM encoding. */
8035 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
8036 if (disas_neon_data_insn(env, s, insn))
8037 goto illegal_op;
8038 } else {
8039 if (insn & (1 << 28))
8040 goto illegal_op;
8041 if (disas_coproc_insn (env, s, insn))
8042 goto illegal_op;
8044 break;
8045 case 8: case 9: case 10: case 11:
8046 if (insn & (1 << 15)) {
8047 /* Branches, misc control. */
8048 if (insn & 0x5000) {
8049 /* Unconditional branch. */
8050 /* signextend(hw1[10:0]) -> offset[:12]. */
8051 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
8052 /* hw1[10:0] -> offset[11:1]. */
8053 offset |= (insn & 0x7ff) << 1;
8054 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
8055 offset[24:22] already have the same value because of the
8056 sign extension above. */
8057 offset ^= ((~insn) & (1 << 13)) << 10;
8058 offset ^= ((~insn) & (1 << 11)) << 11;
8060 if (insn & (1 << 14)) {
8061 /* Branch and link. */
8062 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
8065 offset += s->pc;
8066 if (insn & (1 << 12)) {
8067 /* b/bl */
8068 gen_jmp(s, offset);
8069 } else {
8070 /* blx */
8071 offset &= ~(uint32_t)2;
8072 gen_bx_im(s, offset);
8074 } else if (((insn >> 23) & 7) == 7) {
8075 /* Misc control */
8076 if (insn & (1 << 13))
8077 goto illegal_op;
8079 if (insn & (1 << 26)) {
8080 /* Secure monitor call (v6Z) */
8081 goto illegal_op; /* not implemented. */
8082 } else {
8083 op = (insn >> 20) & 7;
8084 switch (op) {
8085 case 0: /* msr cpsr. */
8086 if (IS_M(env)) {
8087 tmp = load_reg(s, rn);
8088 addr = tcg_const_i32(insn & 0xff);
8089 gen_helper_v7m_msr(cpu_env, addr, tmp);
8090 tcg_temp_free_i32(addr);
8091 tcg_temp_free_i32(tmp);
8092 gen_lookup_tb(s);
8093 break;
8095 /* fall through */
8096 case 1: /* msr spsr. */
8097 if (IS_M(env))
8098 goto illegal_op;
8099 tmp = load_reg(s, rn);
8100 if (gen_set_psr(s,
8101 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
8102 op == 1, tmp))
8103 goto illegal_op;
8104 break;
8105 case 2: /* cps, nop-hint. */
8106 if (((insn >> 8) & 7) == 0) {
8107 gen_nop_hint(s, insn & 0xff);
8109 /* Implemented as NOP in user mode. */
8110 if (IS_USER(s))
8111 break;
8112 offset = 0;
8113 imm = 0;
8114 if (insn & (1 << 10)) {
8115 if (insn & (1 << 7))
8116 offset |= CPSR_A;
8117 if (insn & (1 << 6))
8118 offset |= CPSR_I;
8119 if (insn & (1 << 5))
8120 offset |= CPSR_F;
8121 if (insn & (1 << 9))
8122 imm = CPSR_A | CPSR_I | CPSR_F;
8124 if (insn & (1 << 8)) {
8125 offset |= 0x1f;
8126 imm |= (insn & 0x1f);
8128 if (offset) {
8129 gen_set_psr_im(s, offset, 0, imm);
8131 break;
8132 case 3: /* Special control operations. */
8133 ARCH(7);
8134 op = (insn >> 4) & 0xf;
8135 switch (op) {
8136 case 2: /* clrex */
8137 gen_clrex(s);
8138 break;
8139 case 4: /* dsb */
8140 case 5: /* dmb */
8141 case 6: /* isb */
8142 /* These execute as NOPs. */
8143 break;
8144 default:
8145 goto illegal_op;
8147 break;
8148 case 4: /* bxj */
8149 /* Trivial implementation equivalent to bx. */
8150 tmp = load_reg(s, rn);
8151 gen_bx(s, tmp);
8152 break;
8153 case 5: /* Exception return. */
8154 if (IS_USER(s)) {
8155 goto illegal_op;
8157 if (rn != 14 || rd != 15) {
8158 goto illegal_op;
8160 tmp = load_reg(s, rn);
8161 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
8162 gen_exception_return(s, tmp);
8163 break;
8164 case 6: /* mrs cpsr. */
8165 tmp = tcg_temp_new_i32();
8166 if (IS_M(env)) {
8167 addr = tcg_const_i32(insn & 0xff);
8168 gen_helper_v7m_mrs(tmp, cpu_env, addr);
8169 tcg_temp_free_i32(addr);
8170 } else {
8171 gen_helper_cpsr_read(tmp);
8173 store_reg(s, rd, tmp);
8174 break;
8175 case 7: /* mrs spsr. */
8176 /* Not accessible in user mode. */
8177 if (IS_USER(s) || IS_M(env))
8178 goto illegal_op;
8179 tmp = load_cpu_field(spsr);
8180 store_reg(s, rd, tmp);
8181 break;
8184 } else {
8185 /* Conditional branch. */
8186 op = (insn >> 22) & 0xf;
8187 /* Generate a conditional jump to next instruction. */
8188 s->condlabel = gen_new_label();
8189 gen_test_cc(op ^ 1, s->condlabel);
8190 s->condjmp = 1;
8192 /* offset[11:1] = insn[10:0] */
8193 offset = (insn & 0x7ff) << 1;
8194 /* offset[17:12] = insn[21:16]. */
8195 offset |= (insn & 0x003f0000) >> 4;
8196 /* offset[31:20] = insn[26]. */
8197 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
8198 /* offset[18] = insn[13]. */
8199 offset |= (insn & (1 << 13)) << 5;
8200 /* offset[19] = insn[11]. */
8201 offset |= (insn & (1 << 11)) << 8;
8203 /* jump to the offset */
8204 gen_jmp(s, s->pc + offset);
8206 } else {
8207 /* Data processing immediate. */
8208 if (insn & (1 << 25)) {
8209 if (insn & (1 << 24)) {
8210 if (insn & (1 << 20))
8211 goto illegal_op;
8212 /* Bitfield/Saturate. */
8213 op = (insn >> 21) & 7;
8214 imm = insn & 0x1f;
8215 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
8216 if (rn == 15) {
8217 tmp = tcg_temp_new_i32();
8218 tcg_gen_movi_i32(tmp, 0);
8219 } else {
8220 tmp = load_reg(s, rn);
8222 switch (op) {
8223 case 2: /* Signed bitfield extract. */
8224 imm++;
8225 if (shift + imm > 32)
8226 goto illegal_op;
8227 if (imm < 32)
8228 gen_sbfx(tmp, shift, imm);
8229 break;
8230 case 6: /* Unsigned bitfield extract. */
8231 imm++;
8232 if (shift + imm > 32)
8233 goto illegal_op;
8234 if (imm < 32)
8235 gen_ubfx(tmp, shift, (1u << imm) - 1);
8236 break;
8237 case 3: /* Bitfield insert/clear. */
8238 if (imm < shift)
8239 goto illegal_op;
8240 imm = imm + 1 - shift;
8241 if (imm != 32) {
8242 tmp2 = load_reg(s, rd);
8243 gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
8244 tcg_temp_free_i32(tmp2);
8246 break;
8247 case 7:
8248 goto illegal_op;
8249 default: /* Saturate. */
8250 if (shift) {
8251 if (op & 1)
8252 tcg_gen_sari_i32(tmp, tmp, shift);
8253 else
8254 tcg_gen_shli_i32(tmp, tmp, shift);
8256 tmp2 = tcg_const_i32(imm);
8257 if (op & 4) {
8258 /* Unsigned. */
8259 if ((op & 1) && shift == 0)
8260 gen_helper_usat16(tmp, tmp, tmp2);
8261 else
8262 gen_helper_usat(tmp, tmp, tmp2);
8263 } else {
8264 /* Signed. */
8265 if ((op & 1) && shift == 0)
8266 gen_helper_ssat16(tmp, tmp, tmp2);
8267 else
8268 gen_helper_ssat(tmp, tmp, tmp2);
8270 tcg_temp_free_i32(tmp2);
8271 break;
8273 store_reg(s, rd, tmp);
8274 } else {
8275 imm = ((insn & 0x04000000) >> 15)
8276 | ((insn & 0x7000) >> 4) | (insn & 0xff);
8277 if (insn & (1 << 22)) {
8278 /* 16-bit immediate. */
8279 imm |= (insn >> 4) & 0xf000;
8280 if (insn & (1 << 23)) {
8281 /* movt */
8282 tmp = load_reg(s, rd);
8283 tcg_gen_ext16u_i32(tmp, tmp);
8284 tcg_gen_ori_i32(tmp, tmp, imm << 16);
8285 } else {
8286 /* movw */
8287 tmp = tcg_temp_new_i32();
8288 tcg_gen_movi_i32(tmp, imm);
8290 } else {
8291 /* Add/sub 12-bit immediate. */
8292 if (rn == 15) {
8293 offset = s->pc & ~(uint32_t)3;
8294 if (insn & (1 << 23))
8295 offset -= imm;
8296 else
8297 offset += imm;
8298 tmp = tcg_temp_new_i32();
8299 tcg_gen_movi_i32(tmp, offset);
8300 } else {
8301 tmp = load_reg(s, rn);
8302 if (insn & (1 << 23))
8303 tcg_gen_subi_i32(tmp, tmp, imm);
8304 else
8305 tcg_gen_addi_i32(tmp, tmp, imm);
8308 store_reg(s, rd, tmp);
8310 } else {
8311 int shifter_out = 0;
8312 /* modified 12-bit immediate. */
8313 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
8314 imm = (insn & 0xff);
8315 switch (shift) {
8316 case 0: /* XY */
8317 /* Nothing to do. */
8318 break;
8319 case 1: /* 00XY00XY */
8320 imm |= imm << 16;
8321 break;
8322 case 2: /* XY00XY00 */
8323 imm |= imm << 16;
8324 imm <<= 8;
8325 break;
8326 case 3: /* XYXYXYXY */
8327 imm |= imm << 16;
8328 imm |= imm << 8;
8329 break;
8330 default: /* Rotated constant. */
8331 shift = (shift << 1) | (imm >> 7);
8332 imm |= 0x80;
8333 imm = imm << (32 - shift);
8334 shifter_out = 1;
8335 break;
8337 tmp2 = tcg_temp_new_i32();
8338 tcg_gen_movi_i32(tmp2, imm);
8339 rn = (insn >> 16) & 0xf;
8340 if (rn == 15) {
8341 tmp = tcg_temp_new_i32();
8342 tcg_gen_movi_i32(tmp, 0);
8343 } else {
8344 tmp = load_reg(s, rn);
8346 op = (insn >> 21) & 0xf;
8347 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
8348 shifter_out, tmp, tmp2))
8349 goto illegal_op;
8350 tcg_temp_free_i32(tmp2);
8351 rd = (insn >> 8) & 0xf;
8352 if (rd != 15) {
8353 store_reg(s, rd, tmp);
8354 } else {
8355 tcg_temp_free_i32(tmp);
8359 break;
8360 case 12: /* Load/store single data item. */
8362 int postinc = 0;
8363 int writeback = 0;
8364 int user;
8365 if ((insn & 0x01100000) == 0x01000000) {
8366 if (disas_neon_ls_insn(env, s, insn))
8367 goto illegal_op;
8368 break;
8370 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
8371 if (rs == 15) {
8372 if (!(insn & (1 << 20))) {
8373 goto illegal_op;
8375 if (op != 2) {
8376 /* Byte or halfword load space with dest == r15 : memory hints.
8377 * Catch them early so we don't emit pointless addressing code.
8378 * This space is a mix of:
8379 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
8380 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
8381 * cores)
8382 * unallocated hints, which must be treated as NOPs
8383 * UNPREDICTABLE space, which we NOP or UNDEF depending on
8384 * which is easiest for the decoding logic
8385 * Some space which must UNDEF
8387 int op1 = (insn >> 23) & 3;
8388 int op2 = (insn >> 6) & 0x3f;
8389 if (op & 2) {
8390 goto illegal_op;
8392 if (rn == 15) {
8393 /* UNPREDICTABLE or unallocated hint */
8394 return 0;
8396 if (op1 & 1) {
8397 return 0; /* PLD* or unallocated hint */
8399 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
8400 return 0; /* PLD* or unallocated hint */
8402 /* UNDEF space, or an UNPREDICTABLE */
8403 return 1;
8406 user = IS_USER(s);
8407 if (rn == 15) {
8408 addr = tcg_temp_new_i32();
8409 /* PC relative. */
8410 /* s->pc has already been incremented by 4. */
8411 imm = s->pc & 0xfffffffc;
8412 if (insn & (1 << 23))
8413 imm += insn & 0xfff;
8414 else
8415 imm -= insn & 0xfff;
8416 tcg_gen_movi_i32(addr, imm);
8417 } else {
8418 addr = load_reg(s, rn);
8419 if (insn & (1 << 23)) {
8420 /* Positive offset. */
8421 imm = insn & 0xfff;
8422 tcg_gen_addi_i32(addr, addr, imm);
8423 } else {
8424 imm = insn & 0xff;
8425 switch ((insn >> 8) & 0xf) {
8426 case 0x0: /* Shifted Register. */
8427 shift = (insn >> 4) & 0xf;
8428 if (shift > 3) {
8429 tcg_temp_free_i32(addr);
8430 goto illegal_op;
8432 tmp = load_reg(s, rm);
8433 if (shift)
8434 tcg_gen_shli_i32(tmp, tmp, shift);
8435 tcg_gen_add_i32(addr, addr, tmp);
8436 tcg_temp_free_i32(tmp);
8437 break;
8438 case 0xc: /* Negative offset. */
8439 tcg_gen_addi_i32(addr, addr, -imm);
8440 break;
8441 case 0xe: /* User privilege. */
8442 tcg_gen_addi_i32(addr, addr, imm);
8443 user = 1;
8444 break;
8445 case 0x9: /* Post-decrement. */
8446 imm = -imm;
8447 /* Fall through. */
8448 case 0xb: /* Post-increment. */
8449 postinc = 1;
8450 writeback = 1;
8451 break;
8452 case 0xd: /* Pre-decrement. */
8453 imm = -imm;
8454 /* Fall through. */
8455 case 0xf: /* Pre-increment. */
8456 tcg_gen_addi_i32(addr, addr, imm);
8457 writeback = 1;
8458 break;
8459 default:
8460 tcg_temp_free_i32(addr);
8461 goto illegal_op;
8465 if (insn & (1 << 20)) {
8466 /* Load. */
8467 switch (op) {
8468 case 0: tmp = gen_ld8u(addr, user); break;
8469 case 4: tmp = gen_ld8s(addr, user); break;
8470 case 1: tmp = gen_ld16u(addr, user); break;
8471 case 5: tmp = gen_ld16s(addr, user); break;
8472 case 2: tmp = gen_ld32(addr, user); break;
8473 default:
8474 tcg_temp_free_i32(addr);
8475 goto illegal_op;
8477 if (rs == 15) {
8478 gen_bx(s, tmp);
8479 } else {
8480 store_reg(s, rs, tmp);
8482 } else {
8483 /* Store. */
8484 tmp = load_reg(s, rs);
8485 switch (op) {
8486 case 0: gen_st8(tmp, addr, user); break;
8487 case 1: gen_st16(tmp, addr, user); break;
8488 case 2: gen_st32(tmp, addr, user); break;
8489 default:
8490 tcg_temp_free_i32(addr);
8491 goto illegal_op;
8494 if (postinc)
8495 tcg_gen_addi_i32(addr, addr, imm);
8496 if (writeback) {
8497 store_reg(s, rn, addr);
8498 } else {
8499 tcg_temp_free_i32(addr);
8502 break;
8503 default:
8504 goto illegal_op;
8506 return 0;
8507 illegal_op:
8508 return 1;
8511 static void disas_thumb_insn(CPUState *env, DisasContext *s)
8513 uint32_t val, insn, op, rm, rn, rd, shift, cond;
8514 int32_t offset;
8515 int i;
8516 TCGv tmp;
8517 TCGv tmp2;
8518 TCGv addr;
8520 if (s->condexec_mask) {
8521 cond = s->condexec_cond;
8522 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
8523 s->condlabel = gen_new_label();
8524 gen_test_cc(cond ^ 1, s->condlabel);
8525 s->condjmp = 1;
8529 insn = lduw_code(s->pc);
8530 s->pc += 2;
8532 switch (insn >> 12) {
8533 case 0: case 1:
8535 rd = insn & 7;
8536 op = (insn >> 11) & 3;
8537 if (op == 3) {
8538 /* add/subtract */
8539 rn = (insn >> 3) & 7;
8540 tmp = load_reg(s, rn);
8541 if (insn & (1 << 10)) {
8542 /* immediate */
8543 tmp2 = tcg_temp_new_i32();
8544 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
8545 } else {
8546 /* reg */
8547 rm = (insn >> 6) & 7;
8548 tmp2 = load_reg(s, rm);
8550 if (insn & (1 << 9)) {
8551 if (s->condexec_mask)
8552 tcg_gen_sub_i32(tmp, tmp, tmp2);
8553 else
8554 gen_helper_sub_cc(tmp, tmp, tmp2);
8555 } else {
8556 if (s->condexec_mask)
8557 tcg_gen_add_i32(tmp, tmp, tmp2);
8558 else
8559 gen_helper_add_cc(tmp, tmp, tmp2);
8561 tcg_temp_free_i32(tmp2);
8562 store_reg(s, rd, tmp);
8563 } else {
8564 /* shift immediate */
8565 rm = (insn >> 3) & 7;
8566 shift = (insn >> 6) & 0x1f;
8567 tmp = load_reg(s, rm);
8568 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
8569 if (!s->condexec_mask)
8570 gen_logic_CC(tmp);
8571 store_reg(s, rd, tmp);
8573 break;
8574 case 2: case 3:
8575 /* arithmetic large immediate */
8576 op = (insn >> 11) & 3;
8577 rd = (insn >> 8) & 0x7;
8578 if (op == 0) { /* mov */
8579 tmp = tcg_temp_new_i32();
8580 tcg_gen_movi_i32(tmp, insn & 0xff);
8581 if (!s->condexec_mask)
8582 gen_logic_CC(tmp);
8583 store_reg(s, rd, tmp);
8584 } else {
8585 tmp = load_reg(s, rd);
8586 tmp2 = tcg_temp_new_i32();
8587 tcg_gen_movi_i32(tmp2, insn & 0xff);
8588 switch (op) {
8589 case 1: /* cmp */
8590 gen_helper_sub_cc(tmp, tmp, tmp2);
8591 tcg_temp_free_i32(tmp);
8592 tcg_temp_free_i32(tmp2);
8593 break;
8594 case 2: /* add */
8595 if (s->condexec_mask)
8596 tcg_gen_add_i32(tmp, tmp, tmp2);
8597 else
8598 gen_helper_add_cc(tmp, tmp, tmp2);
8599 tcg_temp_free_i32(tmp2);
8600 store_reg(s, rd, tmp);
8601 break;
8602 case 3: /* sub */
8603 if (s->condexec_mask)
8604 tcg_gen_sub_i32(tmp, tmp, tmp2);
8605 else
8606 gen_helper_sub_cc(tmp, tmp, tmp2);
8607 tcg_temp_free_i32(tmp2);
8608 store_reg(s, rd, tmp);
8609 break;
8612 break;
8613 case 4:
8614 if (insn & (1 << 11)) {
8615 rd = (insn >> 8) & 7;
8616 /* load pc-relative. Bit 1 of PC is ignored. */
8617 val = s->pc + 2 + ((insn & 0xff) * 4);
8618 val &= ~(uint32_t)2;
8619 addr = tcg_temp_new_i32();
8620 tcg_gen_movi_i32(addr, val);
8621 tmp = gen_ld32(addr, IS_USER(s));
8622 tcg_temp_free_i32(addr);
8623 store_reg(s, rd, tmp);
8624 break;
8626 if (insn & (1 << 10)) {
8627 /* data processing extended or blx */
8628 rd = (insn & 7) | ((insn >> 4) & 8);
8629 rm = (insn >> 3) & 0xf;
8630 op = (insn >> 8) & 3;
8631 switch (op) {
8632 case 0: /* add */
8633 tmp = load_reg(s, rd);
8634 tmp2 = load_reg(s, rm);
8635 tcg_gen_add_i32(tmp, tmp, tmp2);
8636 tcg_temp_free_i32(tmp2);
8637 store_reg(s, rd, tmp);
8638 break;
8639 case 1: /* cmp */
8640 tmp = load_reg(s, rd);
8641 tmp2 = load_reg(s, rm);
8642 gen_helper_sub_cc(tmp, tmp, tmp2);
8643 tcg_temp_free_i32(tmp2);
8644 tcg_temp_free_i32(tmp);
8645 break;
8646 case 2: /* mov/cpy */
8647 tmp = load_reg(s, rm);
8648 store_reg(s, rd, tmp);
8649 break;
8650 case 3:/* branch [and link] exchange thumb register */
8651 tmp = load_reg(s, rm);
8652 if (insn & (1 << 7)) {
8653 val = (uint32_t)s->pc | 1;
8654 tmp2 = tcg_temp_new_i32();
8655 tcg_gen_movi_i32(tmp2, val);
8656 store_reg(s, 14, tmp2);
8658 gen_bx(s, tmp);
8659 break;
8661 break;
8664 /* data processing register */
8665 rd = insn & 7;
8666 rm = (insn >> 3) & 7;
8667 op = (insn >> 6) & 0xf;
8668 if (op == 2 || op == 3 || op == 4 || op == 7) {
8669 /* the shift/rotate ops want the operands backwards */
8670 val = rm;
8671 rm = rd;
8672 rd = val;
8673 val = 1;
8674 } else {
8675 val = 0;
8678 if (op == 9) { /* neg */
8679 tmp = tcg_temp_new_i32();
8680 tcg_gen_movi_i32(tmp, 0);
8681 } else if (op != 0xf) { /* mvn doesn't read its first operand */
8682 tmp = load_reg(s, rd);
8683 } else {
8684 TCGV_UNUSED(tmp);
8687 tmp2 = load_reg(s, rm);
8688 switch (op) {
8689 case 0x0: /* and */
8690 tcg_gen_and_i32(tmp, tmp, tmp2);
8691 if (!s->condexec_mask)
8692 gen_logic_CC(tmp);
8693 break;
8694 case 0x1: /* eor */
8695 tcg_gen_xor_i32(tmp, tmp, tmp2);
8696 if (!s->condexec_mask)
8697 gen_logic_CC(tmp);
8698 break;
8699 case 0x2: /* lsl */
8700 if (s->condexec_mask) {
8701 gen_helper_shl(tmp2, tmp2, tmp);
8702 } else {
8703 gen_helper_shl_cc(tmp2, tmp2, tmp);
8704 gen_logic_CC(tmp2);
8706 break;
8707 case 0x3: /* lsr */
8708 if (s->condexec_mask) {
8709 gen_helper_shr(tmp2, tmp2, tmp);
8710 } else {
8711 gen_helper_shr_cc(tmp2, tmp2, tmp);
8712 gen_logic_CC(tmp2);
8714 break;
8715 case 0x4: /* asr */
8716 if (s->condexec_mask) {
8717 gen_helper_sar(tmp2, tmp2, tmp);
8718 } else {
8719 gen_helper_sar_cc(tmp2, tmp2, tmp);
8720 gen_logic_CC(tmp2);
8722 break;
8723 case 0x5: /* adc */
8724 if (s->condexec_mask)
8725 gen_adc(tmp, tmp2);
8726 else
8727 gen_helper_adc_cc(tmp, tmp, tmp2);
8728 break;
8729 case 0x6: /* sbc */
8730 if (s->condexec_mask)
8731 gen_sub_carry(tmp, tmp, tmp2);
8732 else
8733 gen_helper_sbc_cc(tmp, tmp, tmp2);
8734 break;
8735 case 0x7: /* ror */
8736 if (s->condexec_mask) {
8737 tcg_gen_andi_i32(tmp, tmp, 0x1f);
8738 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
8739 } else {
8740 gen_helper_ror_cc(tmp2, tmp2, tmp);
8741 gen_logic_CC(tmp2);
8743 break;
8744 case 0x8: /* tst */
8745 tcg_gen_and_i32(tmp, tmp, tmp2);
8746 gen_logic_CC(tmp);
8747 rd = 16;
8748 break;
8749 case 0x9: /* neg */
8750 if (s->condexec_mask)
8751 tcg_gen_neg_i32(tmp, tmp2);
8752 else
8753 gen_helper_sub_cc(tmp, tmp, tmp2);
8754 break;
8755 case 0xa: /* cmp */
8756 gen_helper_sub_cc(tmp, tmp, tmp2);
8757 rd = 16;
8758 break;
8759 case 0xb: /* cmn */
8760 gen_helper_add_cc(tmp, tmp, tmp2);
8761 rd = 16;
8762 break;
8763 case 0xc: /* orr */
8764 tcg_gen_or_i32(tmp, tmp, tmp2);
8765 if (!s->condexec_mask)
8766 gen_logic_CC(tmp);
8767 break;
8768 case 0xd: /* mul */
8769 tcg_gen_mul_i32(tmp, tmp, tmp2);
8770 if (!s->condexec_mask)
8771 gen_logic_CC(tmp);
8772 break;
8773 case 0xe: /* bic */
8774 tcg_gen_andc_i32(tmp, tmp, tmp2);
8775 if (!s->condexec_mask)
8776 gen_logic_CC(tmp);
8777 break;
8778 case 0xf: /* mvn */
8779 tcg_gen_not_i32(tmp2, tmp2);
8780 if (!s->condexec_mask)
8781 gen_logic_CC(tmp2);
8782 val = 1;
8783 rm = rd;
8784 break;
8786 if (rd != 16) {
8787 if (val) {
8788 store_reg(s, rm, tmp2);
8789 if (op != 0xf)
8790 tcg_temp_free_i32(tmp);
8791 } else {
8792 store_reg(s, rd, tmp);
8793 tcg_temp_free_i32(tmp2);
8795 } else {
8796 tcg_temp_free_i32(tmp);
8797 tcg_temp_free_i32(tmp2);
8799 break;
8801 case 5:
8802 /* load/store register offset. */
8803 rd = insn & 7;
8804 rn = (insn >> 3) & 7;
8805 rm = (insn >> 6) & 7;
8806 op = (insn >> 9) & 7;
8807 addr = load_reg(s, rn);
8808 tmp = load_reg(s, rm);
8809 tcg_gen_add_i32(addr, addr, tmp);
8810 tcg_temp_free_i32(tmp);
8812 if (op < 3) /* store */
8813 tmp = load_reg(s, rd);
8815 switch (op) {
8816 case 0: /* str */
8817 gen_st32(tmp, addr, IS_USER(s));
8818 break;
8819 case 1: /* strh */
8820 gen_st16(tmp, addr, IS_USER(s));
8821 break;
8822 case 2: /* strb */
8823 gen_st8(tmp, addr, IS_USER(s));
8824 break;
8825 case 3: /* ldrsb */
8826 tmp = gen_ld8s(addr, IS_USER(s));
8827 break;
8828 case 4: /* ldr */
8829 tmp = gen_ld32(addr, IS_USER(s));
8830 break;
8831 case 5: /* ldrh */
8832 tmp = gen_ld16u(addr, IS_USER(s));
8833 break;
8834 case 6: /* ldrb */
8835 tmp = gen_ld8u(addr, IS_USER(s));
8836 break;
8837 case 7: /* ldrsh */
8838 tmp = gen_ld16s(addr, IS_USER(s));
8839 break;
8841 if (op >= 3) /* load */
8842 store_reg(s, rd, tmp);
8843 tcg_temp_free_i32(addr);
8844 break;
8846 case 6:
8847 /* load/store word immediate offset */
8848 rd = insn & 7;
8849 rn = (insn >> 3) & 7;
8850 addr = load_reg(s, rn);
8851 val = (insn >> 4) & 0x7c;
8852 tcg_gen_addi_i32(addr, addr, val);
8854 if (insn & (1 << 11)) {
8855 /* load */
8856 tmp = gen_ld32(addr, IS_USER(s));
8857 store_reg(s, rd, tmp);
8858 } else {
8859 /* store */
8860 tmp = load_reg(s, rd);
8861 gen_st32(tmp, addr, IS_USER(s));
8863 tcg_temp_free_i32(addr);
8864 break;
8866 case 7:
8867 /* load/store byte immediate offset */
8868 rd = insn & 7;
8869 rn = (insn >> 3) & 7;
8870 addr = load_reg(s, rn);
8871 val = (insn >> 6) & 0x1f;
8872 tcg_gen_addi_i32(addr, addr, val);
8874 if (insn & (1 << 11)) {
8875 /* load */
8876 tmp = gen_ld8u(addr, IS_USER(s));
8877 store_reg(s, rd, tmp);
8878 } else {
8879 /* store */
8880 tmp = load_reg(s, rd);
8881 gen_st8(tmp, addr, IS_USER(s));
8883 tcg_temp_free_i32(addr);
8884 break;
8886 case 8:
8887 /* load/store halfword immediate offset */
8888 rd = insn & 7;
8889 rn = (insn >> 3) & 7;
8890 addr = load_reg(s, rn);
8891 val = (insn >> 5) & 0x3e;
8892 tcg_gen_addi_i32(addr, addr, val);
8894 if (insn & (1 << 11)) {
8895 /* load */
8896 tmp = gen_ld16u(addr, IS_USER(s));
8897 store_reg(s, rd, tmp);
8898 } else {
8899 /* store */
8900 tmp = load_reg(s, rd);
8901 gen_st16(tmp, addr, IS_USER(s));
8903 tcg_temp_free_i32(addr);
8904 break;
8906 case 9:
8907 /* load/store from stack */
8908 rd = (insn >> 8) & 7;
8909 addr = load_reg(s, 13);
8910 val = (insn & 0xff) * 4;
8911 tcg_gen_addi_i32(addr, addr, val);
8913 if (insn & (1 << 11)) {
8914 /* load */
8915 tmp = gen_ld32(addr, IS_USER(s));
8916 store_reg(s, rd, tmp);
8917 } else {
8918 /* store */
8919 tmp = load_reg(s, rd);
8920 gen_st32(tmp, addr, IS_USER(s));
8922 tcg_temp_free_i32(addr);
8923 break;
8925 case 10:
8926 /* add to high reg */
8927 rd = (insn >> 8) & 7;
8928 if (insn & (1 << 11)) {
8929 /* SP */
8930 tmp = load_reg(s, 13);
8931 } else {
8932 /* PC. bit 1 is ignored. */
8933 tmp = tcg_temp_new_i32();
8934 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
8936 val = (insn & 0xff) * 4;
8937 tcg_gen_addi_i32(tmp, tmp, val);
8938 store_reg(s, rd, tmp);
8939 break;
8941 case 11:
8942 /* misc */
8943 op = (insn >> 8) & 0xf;
8944 switch (op) {
8945 case 0:
8946 /* adjust stack pointer */
8947 tmp = load_reg(s, 13);
8948 val = (insn & 0x7f) * 4;
8949 if (insn & (1 << 7))
8950 val = -(int32_t)val;
8951 tcg_gen_addi_i32(tmp, tmp, val);
8952 store_reg(s, 13, tmp);
8953 break;
8955 case 2: /* sign/zero extend. */
8956 ARCH(6);
8957 rd = insn & 7;
8958 rm = (insn >> 3) & 7;
8959 tmp = load_reg(s, rm);
8960 switch ((insn >> 6) & 3) {
8961 case 0: gen_sxth(tmp); break;
8962 case 1: gen_sxtb(tmp); break;
8963 case 2: gen_uxth(tmp); break;
8964 case 3: gen_uxtb(tmp); break;
8966 store_reg(s, rd, tmp);
8967 break;
8968 case 4: case 5: case 0xc: case 0xd:
8969 /* push/pop */
8970 addr = load_reg(s, 13);
8971 if (insn & (1 << 8))
8972 offset = 4;
8973 else
8974 offset = 0;
8975 for (i = 0; i < 8; i++) {
8976 if (insn & (1 << i))
8977 offset += 4;
8979 if ((insn & (1 << 11)) == 0) {
8980 tcg_gen_addi_i32(addr, addr, -offset);
8982 for (i = 0; i < 8; i++) {
8983 if (insn & (1 << i)) {
8984 if (insn & (1 << 11)) {
8985 /* pop */
8986 tmp = gen_ld32(addr, IS_USER(s));
8987 store_reg(s, i, tmp);
8988 } else {
8989 /* push */
8990 tmp = load_reg(s, i);
8991 gen_st32(tmp, addr, IS_USER(s));
8993 /* advance to the next address. */
8994 tcg_gen_addi_i32(addr, addr, 4);
8997 TCGV_UNUSED(tmp);
8998 if (insn & (1 << 8)) {
8999 if (insn & (1 << 11)) {
9000 /* pop pc */
9001 tmp = gen_ld32(addr, IS_USER(s));
9002 /* don't set the pc until the rest of the instruction
9003 has completed */
9004 } else {
9005 /* push lr */
9006 tmp = load_reg(s, 14);
9007 gen_st32(tmp, addr, IS_USER(s));
9009 tcg_gen_addi_i32(addr, addr, 4);
9011 if ((insn & (1 << 11)) == 0) {
9012 tcg_gen_addi_i32(addr, addr, -offset);
9014 /* write back the new stack pointer */
9015 store_reg(s, 13, addr);
9016 /* set the new PC value */
9017 if ((insn & 0x0900) == 0x0900)
9018 gen_bx(s, tmp);
9019 break;
9021 case 1: case 3: case 9: case 11: /* czb */
9022 rm = insn & 7;
9023 tmp = load_reg(s, rm);
9024 s->condlabel = gen_new_label();
9025 s->condjmp = 1;
9026 if (insn & (1 << 11))
9027 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
9028 else
9029 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
9030 tcg_temp_free_i32(tmp);
9031 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
9032 val = (uint32_t)s->pc + 2;
9033 val += offset;
9034 gen_jmp(s, val);
9035 break;
9037 case 15: /* IT, nop-hint. */
9038 if ((insn & 0xf) == 0) {
9039 gen_nop_hint(s, (insn >> 4) & 0xf);
9040 break;
9042 /* If Then. */
9043 s->condexec_cond = (insn >> 4) & 0xe;
9044 s->condexec_mask = insn & 0x1f;
9045 /* No actual code generated for this insn, just setup state. */
9046 break;
9048 case 0xe: /* bkpt */
9049 gen_exception_insn(s, 2, EXCP_BKPT);
9050 break;
9052 case 0xa: /* rev */
9053 ARCH(6);
9054 rn = (insn >> 3) & 0x7;
9055 rd = insn & 0x7;
9056 tmp = load_reg(s, rn);
9057 switch ((insn >> 6) & 3) {
9058 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
9059 case 1: gen_rev16(tmp); break;
9060 case 3: gen_revsh(tmp); break;
9061 default: goto illegal_op;
9063 store_reg(s, rd, tmp);
9064 break;
9066 case 6: /* cps */
9067 ARCH(6);
9068 if (IS_USER(s))
9069 break;
9070 if (IS_M(env)) {
9071 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
9072 /* PRIMASK */
9073 if (insn & 1) {
9074 addr = tcg_const_i32(16);
9075 gen_helper_v7m_msr(cpu_env, addr, tmp);
9076 tcg_temp_free_i32(addr);
9078 /* FAULTMASK */
9079 if (insn & 2) {
9080 addr = tcg_const_i32(17);
9081 gen_helper_v7m_msr(cpu_env, addr, tmp);
9082 tcg_temp_free_i32(addr);
9084 tcg_temp_free_i32(tmp);
9085 gen_lookup_tb(s);
9086 } else {
9087 if (insn & (1 << 4))
9088 shift = CPSR_A | CPSR_I | CPSR_F;
9089 else
9090 shift = 0;
9091 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
9093 break;
9095 default:
9096 goto undef;
9098 break;
9100 case 12:
9101 /* load/store multiple */
9102 rn = (insn >> 8) & 0x7;
9103 addr = load_reg(s, rn);
9104 for (i = 0; i < 8; i++) {
9105 if (insn & (1 << i)) {
9106 if (insn & (1 << 11)) {
9107 /* load */
9108 tmp = gen_ld32(addr, IS_USER(s));
9109 store_reg(s, i, tmp);
9110 } else {
9111 /* store */
9112 tmp = load_reg(s, i);
9113 gen_st32(tmp, addr, IS_USER(s));
9115 /* advance to the next address */
9116 tcg_gen_addi_i32(addr, addr, 4);
9119 /* Base register writeback. */
9120 if ((insn & (1 << rn)) == 0) {
9121 store_reg(s, rn, addr);
9122 } else {
9123 tcg_temp_free_i32(addr);
9125 break;
9127 case 13:
9128 /* conditional branch or swi */
9129 cond = (insn >> 8) & 0xf;
9130 if (cond == 0xe)
9131 goto undef;
9133 if (cond == 0xf) {
9134 /* swi */
9135 gen_set_pc_im(s->pc);
9136 s->is_jmp = DISAS_SWI;
9137 break;
9139 /* generate a conditional jump to next instruction */
9140 s->condlabel = gen_new_label();
9141 gen_test_cc(cond ^ 1, s->condlabel);
9142 s->condjmp = 1;
9144 /* jump to the offset */
9145 val = (uint32_t)s->pc + 2;
9146 offset = ((int32_t)insn << 24) >> 24;
9147 val += offset << 1;
9148 gen_jmp(s, val);
9149 break;
9151 case 14:
9152 if (insn & (1 << 11)) {
9153 if (disas_thumb2_insn(env, s, insn))
9154 goto undef32;
9155 break;
9157 /* unconditional branch */
9158 val = (uint32_t)s->pc;
9159 offset = ((int32_t)insn << 21) >> 21;
9160 val += (offset << 1) + 2;
9161 gen_jmp(s, val);
9162 break;
9164 case 15:
9165 if (disas_thumb2_insn(env, s, insn))
9166 goto undef32;
9167 break;
9169 return;
9170 undef32:
9171 gen_exception_insn(s, 4, EXCP_UDEF);
9172 return;
9173 illegal_op:
9174 undef:
9175 gen_exception_insn(s, 2, EXCP_UDEF);
9178 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
9179 basic block 'tb'. If search_pc is TRUE, also generate PC
9180 information for each intermediate instruction. */
9181 static inline void gen_intermediate_code_internal(CPUState *env,
9182 TranslationBlock *tb,
9183 int search_pc)
9185 DisasContext dc1, *dc = &dc1;
9186 CPUBreakpoint *bp;
9187 uint16_t *gen_opc_end;
9188 int j, lj;
9189 target_ulong pc_start;
9190 uint32_t next_page_start;
9191 int num_insns;
9192 int max_insns;
9194 /* generate intermediate code */
9195 pc_start = tb->pc;
9197 dc->tb = tb;
9199 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
9201 dc->is_jmp = DISAS_NEXT;
9202 dc->pc = pc_start;
9203 dc->singlestep_enabled = env->singlestep_enabled;
9204 dc->condjmp = 0;
9205 dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
9206 dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
9207 dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
9208 #if !defined(CONFIG_USER_ONLY)
9209 dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
9210 #endif
9211 dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
9212 dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
9213 dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
9214 cpu_F0s = tcg_temp_new_i32();
9215 cpu_F1s = tcg_temp_new_i32();
9216 cpu_F0d = tcg_temp_new_i64();
9217 cpu_F1d = tcg_temp_new_i64();
9218 cpu_V0 = cpu_F0d;
9219 cpu_V1 = cpu_F1d;
9220 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
9221 cpu_M0 = tcg_temp_new_i64();
9222 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
9223 lj = -1;
9224 num_insns = 0;
9225 max_insns = tb->cflags & CF_COUNT_MASK;
9226 if (max_insns == 0)
9227 max_insns = CF_COUNT_MASK;
9229 gen_icount_start();
9231 tcg_clear_temp_count();
9233 /* A note on handling of the condexec (IT) bits:
9235 * We want to avoid the overhead of having to write the updated condexec
9236 * bits back to the CPUState for every instruction in an IT block. So:
9237 * (1) if the condexec bits are not already zero then we write
9238 * zero back into the CPUState now. This avoids complications trying
9239 * to do it at the end of the block. (For example if we don't do this
9240 * it's hard to identify whether we can safely skip writing condexec
9241 * at the end of the TB, which we definitely want to do for the case
9242 * where a TB doesn't do anything with the IT state at all.)
9243 * (2) if we are going to leave the TB then we call gen_set_condexec()
9244 * which will write the correct value into CPUState if zero is wrong.
9245 * This is done both for leaving the TB at the end, and for leaving
9246 * it because of an exception we know will happen, which is done in
9247 * gen_exception_insn(). The latter is necessary because we need to
9248 * leave the TB with the PC/IT state just prior to execution of the
9249 * instruction which caused the exception.
9250 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
9251 * then the CPUState will be wrong and we need to reset it.
9252 * This is handled in the same way as restoration of the
9253 * PC in these situations: we will be called again with search_pc=1
9254 * and generate a mapping of the condexec bits for each PC in
9255 * gen_opc_condexec_bits[]. gen_pc_load[] then uses this to restore
9256 * the condexec bits.
9258 * Note that there are no instructions which can read the condexec
9259 * bits, and none which can write non-static values to them, so
9260 * we don't need to care about whether CPUState is correct in the
9261 * middle of a TB.
9264 /* Reset the conditional execution bits immediately. This avoids
9265 complications trying to do it at the end of the block. */
9266 if (dc->condexec_mask || dc->condexec_cond)
9268 TCGv tmp = tcg_temp_new_i32();
9269 tcg_gen_movi_i32(tmp, 0);
9270 store_cpu_field(tmp, condexec_bits);
9272 do {
9273 #ifdef CONFIG_USER_ONLY
9274 /* Intercept jump to the magic kernel page. */
9275 if (dc->pc >= 0xffff0000) {
9276 /* We always get here via a jump, so know we are not in a
9277 conditional execution block. */
9278 gen_exception(EXCP_KERNEL_TRAP);
9279 dc->is_jmp = DISAS_UPDATE;
9280 break;
9282 #else
9283 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
9284 /* We always get here via a jump, so know we are not in a
9285 conditional execution block. */
9286 gen_exception(EXCP_EXCEPTION_EXIT);
9287 dc->is_jmp = DISAS_UPDATE;
9288 break;
9290 #endif
9292 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
9293 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
9294 if (bp->pc == dc->pc) {
9295 gen_exception_insn(dc, 0, EXCP_DEBUG);
9296 /* Advance PC so that clearing the breakpoint will
9297 invalidate this TB. */
9298 dc->pc += 2;
9299 goto done_generating;
9300 break;
9304 if (search_pc) {
9305 j = gen_opc_ptr - gen_opc_buf;
9306 if (lj < j) {
9307 lj++;
9308 while (lj < j)
9309 gen_opc_instr_start[lj++] = 0;
9311 gen_opc_pc[lj] = dc->pc;
9312 gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
9313 gen_opc_instr_start[lj] = 1;
9314 gen_opc_icount[lj] = num_insns;
9317 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
9318 gen_io_start();
9320 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
9321 tcg_gen_debug_insn_start(dc->pc);
9324 if (dc->thumb) {
9325 disas_thumb_insn(env, dc);
9326 if (dc->condexec_mask) {
9327 dc->condexec_cond = (dc->condexec_cond & 0xe)
9328 | ((dc->condexec_mask >> 4) & 1);
9329 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
9330 if (dc->condexec_mask == 0) {
9331 dc->condexec_cond = 0;
9334 } else {
9335 disas_arm_insn(env, dc);
9338 if (dc->condjmp && !dc->is_jmp) {
9339 gen_set_label(dc->condlabel);
9340 dc->condjmp = 0;
9343 if (tcg_check_temp_count()) {
9344 fprintf(stderr, "TCG temporary leak before %08x\n", dc->pc);
9347 /* Translation stops when a conditional branch is encountered.
9348 * Otherwise the subsequent code could get translated several times.
9349 * Also stop translation when a page boundary is reached. This
9350 * ensures prefetch aborts occur at the right place. */
9351 num_insns ++;
9352 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
9353 !env->singlestep_enabled &&
9354 !singlestep &&
9355 dc->pc < next_page_start &&
9356 num_insns < max_insns);
9358 if (tb->cflags & CF_LAST_IO) {
9359 if (dc->condjmp) {
9360 /* FIXME: This can theoretically happen with self-modifying
9361 code. */
9362 cpu_abort(env, "IO on conditional branch instruction");
9364 gen_io_end();
9367 /* At this stage dc->condjmp will only be set when the skipped
9368 instruction was a conditional branch or trap, and the PC has
9369 already been written. */
9370 if (unlikely(env->singlestep_enabled)) {
9371 /* Make sure the pc is updated, and raise a debug exception. */
9372 if (dc->condjmp) {
9373 gen_set_condexec(dc);
9374 if (dc->is_jmp == DISAS_SWI) {
9375 gen_exception(EXCP_SWI);
9376 } else {
9377 gen_exception(EXCP_DEBUG);
9379 gen_set_label(dc->condlabel);
9381 if (dc->condjmp || !dc->is_jmp) {
9382 gen_set_pc_im(dc->pc);
9383 dc->condjmp = 0;
9385 gen_set_condexec(dc);
9386 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
9387 gen_exception(EXCP_SWI);
9388 } else {
9389 /* FIXME: Single stepping a WFI insn will not halt
9390 the CPU. */
9391 gen_exception(EXCP_DEBUG);
9393 } else {
9394 /* While branches must always occur at the end of an IT block,
9395 there are a few other things that can cause us to terminate
9396 the TB in the middel of an IT block:
9397 - Exception generating instructions (bkpt, swi, undefined).
9398 - Page boundaries.
9399 - Hardware watchpoints.
9400 Hardware breakpoints have already been handled and skip this code.
9402 gen_set_condexec(dc);
9403 switch(dc->is_jmp) {
9404 case DISAS_NEXT:
9405 gen_goto_tb(dc, 1, dc->pc);
9406 break;
9407 default:
9408 case DISAS_JUMP:
9409 case DISAS_UPDATE:
9410 /* indicate that the hash table must be used to find the next TB */
9411 tcg_gen_exit_tb(0);
9412 break;
9413 case DISAS_TB_JUMP:
9414 /* nothing more to generate */
9415 break;
9416 case DISAS_WFI:
9417 gen_helper_wfi();
9418 break;
9419 case DISAS_SWI:
9420 gen_exception(EXCP_SWI);
9421 break;
9423 if (dc->condjmp) {
9424 gen_set_label(dc->condlabel);
9425 gen_set_condexec(dc);
9426 gen_goto_tb(dc, 1, dc->pc);
9427 dc->condjmp = 0;
9431 done_generating:
9432 gen_icount_end(tb, num_insns);
9433 *gen_opc_ptr = INDEX_op_end;
9435 #ifdef DEBUG_DISAS
9436 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9437 qemu_log("----------------\n");
9438 qemu_log("IN: %s\n", lookup_symbol(pc_start));
9439 log_target_disas(pc_start, dc->pc - pc_start, dc->thumb);
9440 qemu_log("\n");
9442 #endif
9443 if (search_pc) {
9444 j = gen_opc_ptr - gen_opc_buf;
9445 lj++;
9446 while (lj <= j)
9447 gen_opc_instr_start[lj++] = 0;
9448 } else {
9449 tb->size = dc->pc - pc_start;
9450 tb->icount = num_insns;
9454 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
9456 gen_intermediate_code_internal(env, tb, 0);
9459 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
9461 gen_intermediate_code_internal(env, tb, 1);
9464 static const char *cpu_mode_names[16] = {
9465 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
9466 "???", "???", "???", "und", "???", "???", "???", "sys"
9469 void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
9470 int flags)
9472 int i;
9473 #if 0
9474 union {
9475 uint32_t i;
9476 float s;
9477 } s0, s1;
9478 CPU_DoubleU d;
9479 /* ??? This assumes float64 and double have the same layout.
9480 Oh well, it's only debug dumps. */
9481 union {
9482 float64 f64;
9483 double d;
9484 } d0;
9485 #endif
9486 uint32_t psr;
9488 for(i=0;i<16;i++) {
9489 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
9490 if ((i % 4) == 3)
9491 cpu_fprintf(f, "\n");
9492 else
9493 cpu_fprintf(f, " ");
9495 psr = cpsr_read(env);
9496 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
9497 psr,
9498 psr & (1 << 31) ? 'N' : '-',
9499 psr & (1 << 30) ? 'Z' : '-',
9500 psr & (1 << 29) ? 'C' : '-',
9501 psr & (1 << 28) ? 'V' : '-',
9502 psr & CPSR_T ? 'T' : 'A',
9503 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
9505 #if 0
9506 for (i = 0; i < 16; i++) {
9507 d.d = env->vfp.regs[i];
9508 s0.i = d.l.lower;
9509 s1.i = d.l.upper;
9510 d0.f64 = d.d;
9511 cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9512 i * 2, (int)s0.i, s0.s,
9513 i * 2 + 1, (int)s1.i, s1.s,
9514 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
9515 d0.d);
9517 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
9518 #endif
9521 void gen_pc_load(CPUState *env, TranslationBlock *tb,
9522 unsigned long searched_pc, int pc_pos, void *puc)
9524 env->regs[15] = gen_opc_pc[pc_pos];
9525 env->condexec_bits = gen_opc_condexec_bits[pc_pos];