char: convert usb-serial.c
[qemu/aliguori.git] / target-arm / translate.c
blob75c0ad413a4b909f67ad7b2c9c8f6abe92fdd49d
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 "disas.h"
29 #include "tcg-op.h"
30 #include "qemu-log.h"
32 #include "helper.h"
33 #define GEN_HELPER 1
34 #include "helper.h"
36 #define ENABLE_ARCH_4T arm_feature(env, ARM_FEATURE_V4T)
37 #define ENABLE_ARCH_5 arm_feature(env, ARM_FEATURE_V5)
38 /* currently all emulated v5 cores are also v5TE, so don't bother */
39 #define ENABLE_ARCH_5TE arm_feature(env, ARM_FEATURE_V5)
40 #define ENABLE_ARCH_5J 0
41 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
42 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
43 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
44 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
46 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
48 /* internal defines */
49 typedef struct DisasContext {
50 target_ulong pc;
51 int is_jmp;
52 /* Nonzero if this instruction has been conditionally skipped. */
53 int condjmp;
54 /* The label that will be jumped to when the instruction is skipped. */
55 int condlabel;
56 /* Thumb-2 condtional execution bits. */
57 int condexec_mask;
58 int condexec_cond;
59 struct TranslationBlock *tb;
60 int singlestep_enabled;
61 int thumb;
62 #if !defined(CONFIG_USER_ONLY)
63 int user;
64 #endif
65 int vfp_enabled;
66 int vec_len;
67 int vec_stride;
68 } DisasContext;
70 static uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE];
72 #if defined(CONFIG_USER_ONLY)
73 #define IS_USER(s) 1
74 #else
75 #define IS_USER(s) (s->user)
76 #endif
78 /* These instructions trap after executing, so defer them until after the
79 conditional executions state has been updated. */
80 #define DISAS_WFI 4
81 #define DISAS_SWI 5
83 static TCGv_ptr cpu_env;
84 /* We reuse the same 64-bit temporaries for efficiency. */
85 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
86 static TCGv_i32 cpu_R[16];
87 static TCGv_i32 cpu_exclusive_addr;
88 static TCGv_i32 cpu_exclusive_val;
89 static TCGv_i32 cpu_exclusive_high;
90 #ifdef CONFIG_USER_ONLY
91 static TCGv_i32 cpu_exclusive_test;
92 static TCGv_i32 cpu_exclusive_info;
93 #endif
95 /* FIXME: These should be removed. */
96 static TCGv cpu_F0s, cpu_F1s;
97 static TCGv_i64 cpu_F0d, cpu_F1d;
99 #include "gen-icount.h"
101 static const char *regnames[] =
102 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
103 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
105 /* initialize TCG globals. */
106 void arm_translate_init(void)
108 int i;
110 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
112 for (i = 0; i < 16; i++) {
113 cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
114 offsetof(CPUState, regs[i]),
115 regnames[i]);
117 cpu_exclusive_addr = tcg_global_mem_new_i32(TCG_AREG0,
118 offsetof(CPUState, exclusive_addr), "exclusive_addr");
119 cpu_exclusive_val = tcg_global_mem_new_i32(TCG_AREG0,
120 offsetof(CPUState, exclusive_val), "exclusive_val");
121 cpu_exclusive_high = tcg_global_mem_new_i32(TCG_AREG0,
122 offsetof(CPUState, exclusive_high), "exclusive_high");
123 #ifdef CONFIG_USER_ONLY
124 cpu_exclusive_test = tcg_global_mem_new_i32(TCG_AREG0,
125 offsetof(CPUState, exclusive_test), "exclusive_test");
126 cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0,
127 offsetof(CPUState, exclusive_info), "exclusive_info");
128 #endif
130 #define GEN_HELPER 2
131 #include "helper.h"
134 static inline TCGv load_cpu_offset(int offset)
136 TCGv tmp = tcg_temp_new_i32();
137 tcg_gen_ld_i32(tmp, cpu_env, offset);
138 return tmp;
141 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
143 static inline void store_cpu_offset(TCGv var, int offset)
145 tcg_gen_st_i32(var, cpu_env, offset);
146 tcg_temp_free_i32(var);
149 #define store_cpu_field(var, name) \
150 store_cpu_offset(var, offsetof(CPUState, name))
152 /* Set a variable to the value of a CPU register. */
153 static void load_reg_var(DisasContext *s, TCGv var, int reg)
155 if (reg == 15) {
156 uint32_t addr;
157 /* normaly, since we updated PC, we need only to add one insn */
158 if (s->thumb)
159 addr = (long)s->pc + 2;
160 else
161 addr = (long)s->pc + 4;
162 tcg_gen_movi_i32(var, addr);
163 } else {
164 tcg_gen_mov_i32(var, cpu_R[reg]);
168 /* Create a new temporary and set it to the value of a CPU register. */
169 static inline TCGv load_reg(DisasContext *s, int reg)
171 TCGv tmp = tcg_temp_new_i32();
172 load_reg_var(s, tmp, reg);
173 return tmp;
176 /* Set a CPU register. The source must be a temporary and will be
177 marked as dead. */
178 static void store_reg(DisasContext *s, int reg, TCGv var)
180 if (reg == 15) {
181 tcg_gen_andi_i32(var, var, ~1);
182 s->is_jmp = DISAS_JUMP;
184 tcg_gen_mov_i32(cpu_R[reg], var);
185 tcg_temp_free_i32(var);
188 /* Value extensions. */
189 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
190 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
191 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
192 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
194 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
195 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
198 static inline void gen_set_cpsr(TCGv var, uint32_t mask)
200 TCGv tmp_mask = tcg_const_i32(mask);
201 gen_helper_cpsr_write(var, tmp_mask);
202 tcg_temp_free_i32(tmp_mask);
204 /* Set NZCV flags from the high 4 bits of var. */
205 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
207 static void gen_exception(int excp)
209 TCGv tmp = tcg_temp_new_i32();
210 tcg_gen_movi_i32(tmp, excp);
211 gen_helper_exception(tmp);
212 tcg_temp_free_i32(tmp);
215 static void gen_smul_dual(TCGv a, TCGv b)
217 TCGv tmp1 = tcg_temp_new_i32();
218 TCGv tmp2 = tcg_temp_new_i32();
219 tcg_gen_ext16s_i32(tmp1, a);
220 tcg_gen_ext16s_i32(tmp2, b);
221 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
222 tcg_temp_free_i32(tmp2);
223 tcg_gen_sari_i32(a, a, 16);
224 tcg_gen_sari_i32(b, b, 16);
225 tcg_gen_mul_i32(b, b, a);
226 tcg_gen_mov_i32(a, tmp1);
227 tcg_temp_free_i32(tmp1);
230 /* Byteswap each halfword. */
231 static void gen_rev16(TCGv var)
233 TCGv tmp = tcg_temp_new_i32();
234 tcg_gen_shri_i32(tmp, var, 8);
235 tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
236 tcg_gen_shli_i32(var, var, 8);
237 tcg_gen_andi_i32(var, var, 0xff00ff00);
238 tcg_gen_or_i32(var, var, tmp);
239 tcg_temp_free_i32(tmp);
242 /* Byteswap low halfword and sign extend. */
243 static void gen_revsh(TCGv var)
245 tcg_gen_ext16u_i32(var, var);
246 tcg_gen_bswap16_i32(var, var);
247 tcg_gen_ext16s_i32(var, var);
250 /* Unsigned bitfield extract. */
251 static void gen_ubfx(TCGv var, int shift, uint32_t mask)
253 if (shift)
254 tcg_gen_shri_i32(var, var, shift);
255 tcg_gen_andi_i32(var, var, mask);
258 /* Signed bitfield extract. */
259 static void gen_sbfx(TCGv var, int shift, int width)
261 uint32_t signbit;
263 if (shift)
264 tcg_gen_sari_i32(var, var, shift);
265 if (shift + width < 32) {
266 signbit = 1u << (width - 1);
267 tcg_gen_andi_i32(var, var, (1u << width) - 1);
268 tcg_gen_xori_i32(var, var, signbit);
269 tcg_gen_subi_i32(var, var, signbit);
273 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
274 static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
276 tcg_gen_andi_i32(val, val, mask);
277 tcg_gen_shli_i32(val, val, shift);
278 tcg_gen_andi_i32(base, base, ~(mask << shift));
279 tcg_gen_or_i32(dest, base, val);
282 /* Return (b << 32) + a. Mark inputs as dead */
283 static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv b)
285 TCGv_i64 tmp64 = tcg_temp_new_i64();
287 tcg_gen_extu_i32_i64(tmp64, b);
288 tcg_temp_free_i32(b);
289 tcg_gen_shli_i64(tmp64, tmp64, 32);
290 tcg_gen_add_i64(a, tmp64, a);
292 tcg_temp_free_i64(tmp64);
293 return a;
296 /* Return (b << 32) - a. Mark inputs as dead. */
297 static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv b)
299 TCGv_i64 tmp64 = tcg_temp_new_i64();
301 tcg_gen_extu_i32_i64(tmp64, b);
302 tcg_temp_free_i32(b);
303 tcg_gen_shli_i64(tmp64, tmp64, 32);
304 tcg_gen_sub_i64(a, tmp64, a);
306 tcg_temp_free_i64(tmp64);
307 return a;
310 /* FIXME: Most targets have native widening multiplication.
311 It would be good to use that instead of a full wide multiply. */
312 /* 32x32->64 multiply. Marks inputs as dead. */
313 static TCGv_i64 gen_mulu_i64_i32(TCGv a, TCGv b)
315 TCGv_i64 tmp1 = tcg_temp_new_i64();
316 TCGv_i64 tmp2 = tcg_temp_new_i64();
318 tcg_gen_extu_i32_i64(tmp1, a);
319 tcg_temp_free_i32(a);
320 tcg_gen_extu_i32_i64(tmp2, b);
321 tcg_temp_free_i32(b);
322 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
323 tcg_temp_free_i64(tmp2);
324 return tmp1;
327 static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
329 TCGv_i64 tmp1 = tcg_temp_new_i64();
330 TCGv_i64 tmp2 = tcg_temp_new_i64();
332 tcg_gen_ext_i32_i64(tmp1, a);
333 tcg_temp_free_i32(a);
334 tcg_gen_ext_i32_i64(tmp2, b);
335 tcg_temp_free_i32(b);
336 tcg_gen_mul_i64(tmp1, tmp1, tmp2);
337 tcg_temp_free_i64(tmp2);
338 return tmp1;
341 /* Swap low and high halfwords. */
342 static void gen_swap_half(TCGv var)
344 TCGv tmp = tcg_temp_new_i32();
345 tcg_gen_shri_i32(tmp, var, 16);
346 tcg_gen_shli_i32(var, var, 16);
347 tcg_gen_or_i32(var, var, tmp);
348 tcg_temp_free_i32(tmp);
351 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
352 tmp = (t0 ^ t1) & 0x8000;
353 t0 &= ~0x8000;
354 t1 &= ~0x8000;
355 t0 = (t0 + t1) ^ tmp;
358 static void gen_add16(TCGv t0, TCGv t1)
360 TCGv tmp = tcg_temp_new_i32();
361 tcg_gen_xor_i32(tmp, t0, t1);
362 tcg_gen_andi_i32(tmp, tmp, 0x8000);
363 tcg_gen_andi_i32(t0, t0, ~0x8000);
364 tcg_gen_andi_i32(t1, t1, ~0x8000);
365 tcg_gen_add_i32(t0, t0, t1);
366 tcg_gen_xor_i32(t0, t0, tmp);
367 tcg_temp_free_i32(tmp);
368 tcg_temp_free_i32(t1);
371 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
373 /* Set CF to the top bit of var. */
374 static void gen_set_CF_bit31(TCGv var)
376 TCGv tmp = tcg_temp_new_i32();
377 tcg_gen_shri_i32(tmp, var, 31);
378 gen_set_CF(tmp);
379 tcg_temp_free_i32(tmp);
382 /* Set N and Z flags from var. */
383 static inline void gen_logic_CC(TCGv var)
385 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, NF));
386 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, ZF));
389 /* T0 += T1 + CF. */
390 static void gen_adc(TCGv t0, TCGv t1)
392 TCGv tmp;
393 tcg_gen_add_i32(t0, t0, t1);
394 tmp = load_cpu_field(CF);
395 tcg_gen_add_i32(t0, t0, tmp);
396 tcg_temp_free_i32(tmp);
399 /* dest = T0 + T1 + CF. */
400 static void gen_add_carry(TCGv dest, TCGv t0, TCGv t1)
402 TCGv tmp;
403 tcg_gen_add_i32(dest, t0, t1);
404 tmp = load_cpu_field(CF);
405 tcg_gen_add_i32(dest, dest, tmp);
406 tcg_temp_free_i32(tmp);
409 /* dest = T0 - T1 + CF - 1. */
410 static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1)
412 TCGv tmp;
413 tcg_gen_sub_i32(dest, t0, t1);
414 tmp = load_cpu_field(CF);
415 tcg_gen_add_i32(dest, dest, tmp);
416 tcg_gen_subi_i32(dest, dest, 1);
417 tcg_temp_free_i32(tmp);
420 /* FIXME: Implement this natively. */
421 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
423 static void shifter_out_im(TCGv var, int shift)
425 TCGv tmp = tcg_temp_new_i32();
426 if (shift == 0) {
427 tcg_gen_andi_i32(tmp, var, 1);
428 } else {
429 tcg_gen_shri_i32(tmp, var, shift);
430 if (shift != 31)
431 tcg_gen_andi_i32(tmp, tmp, 1);
433 gen_set_CF(tmp);
434 tcg_temp_free_i32(tmp);
437 /* Shift by immediate. Includes special handling for shift == 0. */
438 static inline void gen_arm_shift_im(TCGv var, int shiftop, int shift, int flags)
440 switch (shiftop) {
441 case 0: /* LSL */
442 if (shift != 0) {
443 if (flags)
444 shifter_out_im(var, 32 - shift);
445 tcg_gen_shli_i32(var, var, shift);
447 break;
448 case 1: /* LSR */
449 if (shift == 0) {
450 if (flags) {
451 tcg_gen_shri_i32(var, var, 31);
452 gen_set_CF(var);
454 tcg_gen_movi_i32(var, 0);
455 } else {
456 if (flags)
457 shifter_out_im(var, shift - 1);
458 tcg_gen_shri_i32(var, var, shift);
460 break;
461 case 2: /* ASR */
462 if (shift == 0)
463 shift = 32;
464 if (flags)
465 shifter_out_im(var, shift - 1);
466 if (shift == 32)
467 shift = 31;
468 tcg_gen_sari_i32(var, var, shift);
469 break;
470 case 3: /* ROR/RRX */
471 if (shift != 0) {
472 if (flags)
473 shifter_out_im(var, shift - 1);
474 tcg_gen_rotri_i32(var, var, shift); break;
475 } else {
476 TCGv tmp = load_cpu_field(CF);
477 if (flags)
478 shifter_out_im(var, 0);
479 tcg_gen_shri_i32(var, var, 1);
480 tcg_gen_shli_i32(tmp, tmp, 31);
481 tcg_gen_or_i32(var, var, tmp);
482 tcg_temp_free_i32(tmp);
487 static inline void gen_arm_shift_reg(TCGv var, int shiftop,
488 TCGv shift, int flags)
490 if (flags) {
491 switch (shiftop) {
492 case 0: gen_helper_shl_cc(var, var, shift); break;
493 case 1: gen_helper_shr_cc(var, var, shift); break;
494 case 2: gen_helper_sar_cc(var, var, shift); break;
495 case 3: gen_helper_ror_cc(var, var, shift); break;
497 } else {
498 switch (shiftop) {
499 case 0: gen_helper_shl(var, var, shift); break;
500 case 1: gen_helper_shr(var, var, shift); break;
501 case 2: gen_helper_sar(var, var, shift); break;
502 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
503 tcg_gen_rotr_i32(var, var, shift); break;
506 tcg_temp_free_i32(shift);
509 #define PAS_OP(pfx) \
510 switch (op2) { \
511 case 0: gen_pas_helper(glue(pfx,add16)); break; \
512 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
513 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
514 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
515 case 4: gen_pas_helper(glue(pfx,add8)); break; \
516 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
518 static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
520 TCGv_ptr tmp;
522 switch (op1) {
523 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
524 case 1:
525 tmp = tcg_temp_new_ptr();
526 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
527 PAS_OP(s)
528 tcg_temp_free_ptr(tmp);
529 break;
530 case 5:
531 tmp = tcg_temp_new_ptr();
532 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
533 PAS_OP(u)
534 tcg_temp_free_ptr(tmp);
535 break;
536 #undef gen_pas_helper
537 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
538 case 2:
539 PAS_OP(q);
540 break;
541 case 3:
542 PAS_OP(sh);
543 break;
544 case 6:
545 PAS_OP(uq);
546 break;
547 case 7:
548 PAS_OP(uh);
549 break;
550 #undef gen_pas_helper
553 #undef PAS_OP
555 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
556 #define PAS_OP(pfx) \
557 switch (op1) { \
558 case 0: gen_pas_helper(glue(pfx,add8)); break; \
559 case 1: gen_pas_helper(glue(pfx,add16)); break; \
560 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
561 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
562 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
563 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
565 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
567 TCGv_ptr tmp;
569 switch (op2) {
570 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
571 case 0:
572 tmp = tcg_temp_new_ptr();
573 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
574 PAS_OP(s)
575 tcg_temp_free_ptr(tmp);
576 break;
577 case 4:
578 tmp = tcg_temp_new_ptr();
579 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUState, GE));
580 PAS_OP(u)
581 tcg_temp_free_ptr(tmp);
582 break;
583 #undef gen_pas_helper
584 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
585 case 1:
586 PAS_OP(q);
587 break;
588 case 2:
589 PAS_OP(sh);
590 break;
591 case 5:
592 PAS_OP(uq);
593 break;
594 case 6:
595 PAS_OP(uh);
596 break;
597 #undef gen_pas_helper
600 #undef PAS_OP
602 static void gen_test_cc(int cc, int label)
604 TCGv tmp;
605 TCGv tmp2;
606 int inv;
608 switch (cc) {
609 case 0: /* eq: Z */
610 tmp = load_cpu_field(ZF);
611 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
612 break;
613 case 1: /* ne: !Z */
614 tmp = load_cpu_field(ZF);
615 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
616 break;
617 case 2: /* cs: C */
618 tmp = load_cpu_field(CF);
619 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
620 break;
621 case 3: /* cc: !C */
622 tmp = load_cpu_field(CF);
623 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
624 break;
625 case 4: /* mi: N */
626 tmp = load_cpu_field(NF);
627 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
628 break;
629 case 5: /* pl: !N */
630 tmp = load_cpu_field(NF);
631 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
632 break;
633 case 6: /* vs: V */
634 tmp = load_cpu_field(VF);
635 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
636 break;
637 case 7: /* vc: !V */
638 tmp = load_cpu_field(VF);
639 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
640 break;
641 case 8: /* hi: C && !Z */
642 inv = gen_new_label();
643 tmp = load_cpu_field(CF);
644 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
645 tcg_temp_free_i32(tmp);
646 tmp = load_cpu_field(ZF);
647 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, label);
648 gen_set_label(inv);
649 break;
650 case 9: /* ls: !C || Z */
651 tmp = load_cpu_field(CF);
652 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
653 tcg_temp_free_i32(tmp);
654 tmp = load_cpu_field(ZF);
655 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
656 break;
657 case 10: /* ge: N == V -> N ^ V == 0 */
658 tmp = load_cpu_field(VF);
659 tmp2 = load_cpu_field(NF);
660 tcg_gen_xor_i32(tmp, tmp, tmp2);
661 tcg_temp_free_i32(tmp2);
662 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
663 break;
664 case 11: /* lt: N != V -> N ^ V != 0 */
665 tmp = load_cpu_field(VF);
666 tmp2 = load_cpu_field(NF);
667 tcg_gen_xor_i32(tmp, tmp, tmp2);
668 tcg_temp_free_i32(tmp2);
669 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
670 break;
671 case 12: /* gt: !Z && N == V */
672 inv = gen_new_label();
673 tmp = load_cpu_field(ZF);
674 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, inv);
675 tcg_temp_free_i32(tmp);
676 tmp = load_cpu_field(VF);
677 tmp2 = load_cpu_field(NF);
678 tcg_gen_xor_i32(tmp, tmp, tmp2);
679 tcg_temp_free_i32(tmp2);
680 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
681 gen_set_label(inv);
682 break;
683 case 13: /* le: Z || N != V */
684 tmp = load_cpu_field(ZF);
685 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, label);
686 tcg_temp_free_i32(tmp);
687 tmp = load_cpu_field(VF);
688 tmp2 = load_cpu_field(NF);
689 tcg_gen_xor_i32(tmp, tmp, tmp2);
690 tcg_temp_free_i32(tmp2);
691 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
692 break;
693 default:
694 fprintf(stderr, "Bad condition code 0x%x\n", cc);
695 abort();
697 tcg_temp_free_i32(tmp);
700 static const uint8_t table_logic_cc[16] = {
701 1, /* and */
702 1, /* xor */
703 0, /* sub */
704 0, /* rsb */
705 0, /* add */
706 0, /* adc */
707 0, /* sbc */
708 0, /* rsc */
709 1, /* andl */
710 1, /* xorl */
711 0, /* cmp */
712 0, /* cmn */
713 1, /* orr */
714 1, /* mov */
715 1, /* bic */
716 1, /* mvn */
719 /* Set PC and Thumb state from an immediate address. */
720 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
722 TCGv tmp;
724 s->is_jmp = DISAS_UPDATE;
725 if (s->thumb != (addr & 1)) {
726 tmp = tcg_temp_new_i32();
727 tcg_gen_movi_i32(tmp, addr & 1);
728 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb));
729 tcg_temp_free_i32(tmp);
731 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
734 /* Set PC and Thumb state from var. var is marked as dead. */
735 static inline void gen_bx(DisasContext *s, TCGv var)
737 s->is_jmp = DISAS_UPDATE;
738 tcg_gen_andi_i32(cpu_R[15], var, ~1);
739 tcg_gen_andi_i32(var, var, 1);
740 store_cpu_field(var, thumb);
743 /* Variant of store_reg which uses branch&exchange logic when storing
744 to r15 in ARM architecture v7 and above. The source must be a temporary
745 and will be marked as dead. */
746 static inline void store_reg_bx(CPUState *env, DisasContext *s,
747 int reg, TCGv var)
749 if (reg == 15 && ENABLE_ARCH_7) {
750 gen_bx(s, var);
751 } else {
752 store_reg(s, reg, var);
756 /* Variant of store_reg which uses branch&exchange logic when storing
757 * to r15 in ARM architecture v5T and above. This is used for storing
758 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
759 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
760 static inline void store_reg_from_load(CPUState *env, DisasContext *s,
761 int reg, TCGv var)
763 if (reg == 15 && ENABLE_ARCH_5) {
764 gen_bx(s, var);
765 } else {
766 store_reg(s, reg, var);
770 static inline TCGv gen_ld8s(TCGv addr, int index)
772 TCGv tmp = tcg_temp_new_i32();
773 tcg_gen_qemu_ld8s(tmp, addr, index);
774 return tmp;
776 static inline TCGv gen_ld8u(TCGv addr, int index)
778 TCGv tmp = tcg_temp_new_i32();
779 tcg_gen_qemu_ld8u(tmp, addr, index);
780 return tmp;
782 static inline TCGv gen_ld16s(TCGv addr, int index)
784 TCGv tmp = tcg_temp_new_i32();
785 tcg_gen_qemu_ld16s(tmp, addr, index);
786 return tmp;
788 static inline TCGv gen_ld16u(TCGv addr, int index)
790 TCGv tmp = tcg_temp_new_i32();
791 tcg_gen_qemu_ld16u(tmp, addr, index);
792 return tmp;
794 static inline TCGv gen_ld32(TCGv addr, int index)
796 TCGv tmp = tcg_temp_new_i32();
797 tcg_gen_qemu_ld32u(tmp, addr, index);
798 return tmp;
800 static inline TCGv_i64 gen_ld64(TCGv addr, int index)
802 TCGv_i64 tmp = tcg_temp_new_i64();
803 tcg_gen_qemu_ld64(tmp, addr, index);
804 return tmp;
806 static inline void gen_st8(TCGv val, TCGv addr, int index)
808 tcg_gen_qemu_st8(val, addr, index);
809 tcg_temp_free_i32(val);
811 static inline void gen_st16(TCGv val, TCGv addr, int index)
813 tcg_gen_qemu_st16(val, addr, index);
814 tcg_temp_free_i32(val);
816 static inline void gen_st32(TCGv val, TCGv addr, int index)
818 tcg_gen_qemu_st32(val, addr, index);
819 tcg_temp_free_i32(val);
821 static inline void gen_st64(TCGv_i64 val, TCGv addr, int index)
823 tcg_gen_qemu_st64(val, addr, index);
824 tcg_temp_free_i64(val);
827 static inline void gen_set_pc_im(uint32_t val)
829 tcg_gen_movi_i32(cpu_R[15], val);
832 /* Force a TB lookup after an instruction that changes the CPU state. */
833 static inline void gen_lookup_tb(DisasContext *s)
835 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
836 s->is_jmp = DISAS_UPDATE;
839 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
840 TCGv var)
842 int val, rm, shift, shiftop;
843 TCGv offset;
845 if (!(insn & (1 << 25))) {
846 /* immediate */
847 val = insn & 0xfff;
848 if (!(insn & (1 << 23)))
849 val = -val;
850 if (val != 0)
851 tcg_gen_addi_i32(var, var, val);
852 } else {
853 /* shift/register */
854 rm = (insn) & 0xf;
855 shift = (insn >> 7) & 0x1f;
856 shiftop = (insn >> 5) & 3;
857 offset = load_reg(s, rm);
858 gen_arm_shift_im(offset, shiftop, shift, 0);
859 if (!(insn & (1 << 23)))
860 tcg_gen_sub_i32(var, var, offset);
861 else
862 tcg_gen_add_i32(var, var, offset);
863 tcg_temp_free_i32(offset);
867 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
868 int extra, TCGv var)
870 int val, rm;
871 TCGv offset;
873 if (insn & (1 << 22)) {
874 /* immediate */
875 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
876 if (!(insn & (1 << 23)))
877 val = -val;
878 val += extra;
879 if (val != 0)
880 tcg_gen_addi_i32(var, var, val);
881 } else {
882 /* register */
883 if (extra)
884 tcg_gen_addi_i32(var, var, extra);
885 rm = (insn) & 0xf;
886 offset = load_reg(s, rm);
887 if (!(insn & (1 << 23)))
888 tcg_gen_sub_i32(var, var, offset);
889 else
890 tcg_gen_add_i32(var, var, offset);
891 tcg_temp_free_i32(offset);
895 static TCGv_ptr get_fpstatus_ptr(int neon)
897 TCGv_ptr statusptr = tcg_temp_new_ptr();
898 int offset;
899 if (neon) {
900 offset = offsetof(CPUState, vfp.standard_fp_status);
901 } else {
902 offset = offsetof(CPUState, vfp.fp_status);
904 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
905 return statusptr;
908 #define VFP_OP2(name) \
909 static inline void gen_vfp_##name(int dp) \
911 TCGv_ptr fpst = get_fpstatus_ptr(0); \
912 if (dp) { \
913 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, fpst); \
914 } else { \
915 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, fpst); \
917 tcg_temp_free_ptr(fpst); \
920 VFP_OP2(add)
921 VFP_OP2(sub)
922 VFP_OP2(mul)
923 VFP_OP2(div)
925 #undef VFP_OP2
927 static inline void gen_vfp_F1_mul(int dp)
929 /* Like gen_vfp_mul() but put result in F1 */
930 TCGv_ptr fpst = get_fpstatus_ptr(0);
931 if (dp) {
932 gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, fpst);
933 } else {
934 gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, fpst);
936 tcg_temp_free_ptr(fpst);
939 static inline void gen_vfp_F1_neg(int dp)
941 /* Like gen_vfp_neg() but put result in F1 */
942 if (dp) {
943 gen_helper_vfp_negd(cpu_F1d, cpu_F0d);
944 } else {
945 gen_helper_vfp_negs(cpu_F1s, cpu_F0s);
949 static inline void gen_vfp_abs(int dp)
951 if (dp)
952 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
953 else
954 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
957 static inline void gen_vfp_neg(int dp)
959 if (dp)
960 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
961 else
962 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
965 static inline void gen_vfp_sqrt(int dp)
967 if (dp)
968 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
969 else
970 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
973 static inline void gen_vfp_cmp(int dp)
975 if (dp)
976 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
977 else
978 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
981 static inline void gen_vfp_cmpe(int dp)
983 if (dp)
984 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
985 else
986 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
989 static inline void gen_vfp_F1_ld0(int dp)
991 if (dp)
992 tcg_gen_movi_i64(cpu_F1d, 0);
993 else
994 tcg_gen_movi_i32(cpu_F1s, 0);
997 #define VFP_GEN_ITOF(name) \
998 static inline void gen_vfp_##name(int dp, int neon) \
1000 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1001 if (dp) { \
1002 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
1003 } else { \
1004 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1006 tcg_temp_free_ptr(statusptr); \
1009 VFP_GEN_ITOF(uito)
1010 VFP_GEN_ITOF(sito)
1011 #undef VFP_GEN_ITOF
1013 #define VFP_GEN_FTOI(name) \
1014 static inline void gen_vfp_##name(int dp, int neon) \
1016 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1017 if (dp) { \
1018 gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
1019 } else { \
1020 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1022 tcg_temp_free_ptr(statusptr); \
1025 VFP_GEN_FTOI(toui)
1026 VFP_GEN_FTOI(touiz)
1027 VFP_GEN_FTOI(tosi)
1028 VFP_GEN_FTOI(tosiz)
1029 #undef VFP_GEN_FTOI
1031 #define VFP_GEN_FIX(name) \
1032 static inline void gen_vfp_##name(int dp, int shift, int neon) \
1034 TCGv tmp_shift = tcg_const_i32(shift); \
1035 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1036 if (dp) { \
1037 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, statusptr); \
1038 } else { \
1039 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, statusptr); \
1041 tcg_temp_free_i32(tmp_shift); \
1042 tcg_temp_free_ptr(statusptr); \
1044 VFP_GEN_FIX(tosh)
1045 VFP_GEN_FIX(tosl)
1046 VFP_GEN_FIX(touh)
1047 VFP_GEN_FIX(toul)
1048 VFP_GEN_FIX(shto)
1049 VFP_GEN_FIX(slto)
1050 VFP_GEN_FIX(uhto)
1051 VFP_GEN_FIX(ulto)
1052 #undef VFP_GEN_FIX
1054 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv addr)
1056 if (dp)
1057 tcg_gen_qemu_ld64(cpu_F0d, addr, IS_USER(s));
1058 else
1059 tcg_gen_qemu_ld32u(cpu_F0s, addr, IS_USER(s));
1062 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv addr)
1064 if (dp)
1065 tcg_gen_qemu_st64(cpu_F0d, addr, IS_USER(s));
1066 else
1067 tcg_gen_qemu_st32(cpu_F0s, addr, IS_USER(s));
1070 static inline long
1071 vfp_reg_offset (int dp, int reg)
1073 if (dp)
1074 return offsetof(CPUARMState, vfp.regs[reg]);
1075 else if (reg & 1) {
1076 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1077 + offsetof(CPU_DoubleU, l.upper);
1078 } else {
1079 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1080 + offsetof(CPU_DoubleU, l.lower);
1084 /* Return the offset of a 32-bit piece of a NEON register.
1085 zero is the least significant end of the register. */
1086 static inline long
1087 neon_reg_offset (int reg, int n)
1089 int sreg;
1090 sreg = reg * 2 + n;
1091 return vfp_reg_offset(0, sreg);
1094 static TCGv neon_load_reg(int reg, int pass)
1096 TCGv tmp = tcg_temp_new_i32();
1097 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1098 return tmp;
1101 static void neon_store_reg(int reg, int pass, TCGv var)
1103 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1104 tcg_temp_free_i32(var);
1107 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1109 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1112 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1114 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1117 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1118 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1119 #define tcg_gen_st_f32 tcg_gen_st_i32
1120 #define tcg_gen_st_f64 tcg_gen_st_i64
1122 static inline void gen_mov_F0_vreg(int dp, int reg)
1124 if (dp)
1125 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1126 else
1127 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1130 static inline void gen_mov_F1_vreg(int dp, int reg)
1132 if (dp)
1133 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1134 else
1135 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1138 static inline void gen_mov_vreg_F0(int dp, int reg)
1140 if (dp)
1141 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1142 else
1143 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1146 #define ARM_CP_RW_BIT (1 << 20)
1148 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1150 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1153 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1155 tcg_gen_st_i64(var, cpu_env, offsetof(CPUState, iwmmxt.regs[reg]));
1158 static inline TCGv iwmmxt_load_creg(int reg)
1160 TCGv var = tcg_temp_new_i32();
1161 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1162 return var;
1165 static inline void iwmmxt_store_creg(int reg, TCGv var)
1167 tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, iwmmxt.cregs[reg]));
1168 tcg_temp_free_i32(var);
1171 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1173 iwmmxt_store_reg(cpu_M0, rn);
1176 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1178 iwmmxt_load_reg(cpu_M0, rn);
1181 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1183 iwmmxt_load_reg(cpu_V1, rn);
1184 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1187 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1189 iwmmxt_load_reg(cpu_V1, rn);
1190 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1193 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1195 iwmmxt_load_reg(cpu_V1, rn);
1196 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1199 #define IWMMXT_OP(name) \
1200 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1202 iwmmxt_load_reg(cpu_V1, rn); \
1203 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1206 #define IWMMXT_OP_ENV(name) \
1207 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1209 iwmmxt_load_reg(cpu_V1, rn); \
1210 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1213 #define IWMMXT_OP_ENV_SIZE(name) \
1214 IWMMXT_OP_ENV(name##b) \
1215 IWMMXT_OP_ENV(name##w) \
1216 IWMMXT_OP_ENV(name##l)
1218 #define IWMMXT_OP_ENV1(name) \
1219 static inline void gen_op_iwmmxt_##name##_M0(void) \
1221 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1224 IWMMXT_OP(maddsq)
1225 IWMMXT_OP(madduq)
1226 IWMMXT_OP(sadb)
1227 IWMMXT_OP(sadw)
1228 IWMMXT_OP(mulslw)
1229 IWMMXT_OP(mulshw)
1230 IWMMXT_OP(mululw)
1231 IWMMXT_OP(muluhw)
1232 IWMMXT_OP(macsw)
1233 IWMMXT_OP(macuw)
1235 IWMMXT_OP_ENV_SIZE(unpackl)
1236 IWMMXT_OP_ENV_SIZE(unpackh)
1238 IWMMXT_OP_ENV1(unpacklub)
1239 IWMMXT_OP_ENV1(unpackluw)
1240 IWMMXT_OP_ENV1(unpacklul)
1241 IWMMXT_OP_ENV1(unpackhub)
1242 IWMMXT_OP_ENV1(unpackhuw)
1243 IWMMXT_OP_ENV1(unpackhul)
1244 IWMMXT_OP_ENV1(unpacklsb)
1245 IWMMXT_OP_ENV1(unpacklsw)
1246 IWMMXT_OP_ENV1(unpacklsl)
1247 IWMMXT_OP_ENV1(unpackhsb)
1248 IWMMXT_OP_ENV1(unpackhsw)
1249 IWMMXT_OP_ENV1(unpackhsl)
1251 IWMMXT_OP_ENV_SIZE(cmpeq)
1252 IWMMXT_OP_ENV_SIZE(cmpgtu)
1253 IWMMXT_OP_ENV_SIZE(cmpgts)
1255 IWMMXT_OP_ENV_SIZE(mins)
1256 IWMMXT_OP_ENV_SIZE(minu)
1257 IWMMXT_OP_ENV_SIZE(maxs)
1258 IWMMXT_OP_ENV_SIZE(maxu)
1260 IWMMXT_OP_ENV_SIZE(subn)
1261 IWMMXT_OP_ENV_SIZE(addn)
1262 IWMMXT_OP_ENV_SIZE(subu)
1263 IWMMXT_OP_ENV_SIZE(addu)
1264 IWMMXT_OP_ENV_SIZE(subs)
1265 IWMMXT_OP_ENV_SIZE(adds)
1267 IWMMXT_OP_ENV(avgb0)
1268 IWMMXT_OP_ENV(avgb1)
1269 IWMMXT_OP_ENV(avgw0)
1270 IWMMXT_OP_ENV(avgw1)
1272 IWMMXT_OP(msadb)
1274 IWMMXT_OP_ENV(packuw)
1275 IWMMXT_OP_ENV(packul)
1276 IWMMXT_OP_ENV(packuq)
1277 IWMMXT_OP_ENV(packsw)
1278 IWMMXT_OP_ENV(packsl)
1279 IWMMXT_OP_ENV(packsq)
1281 static void gen_op_iwmmxt_set_mup(void)
1283 TCGv tmp;
1284 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1285 tcg_gen_ori_i32(tmp, tmp, 2);
1286 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1289 static void gen_op_iwmmxt_set_cup(void)
1291 TCGv tmp;
1292 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1293 tcg_gen_ori_i32(tmp, tmp, 1);
1294 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1297 static void gen_op_iwmmxt_setpsr_nz(void)
1299 TCGv tmp = tcg_temp_new_i32();
1300 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1301 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1304 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1306 iwmmxt_load_reg(cpu_V1, rn);
1307 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1308 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1311 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn, TCGv dest)
1313 int rd;
1314 uint32_t offset;
1315 TCGv tmp;
1317 rd = (insn >> 16) & 0xf;
1318 tmp = load_reg(s, rd);
1320 offset = (insn & 0xff) << ((insn >> 7) & 2);
1321 if (insn & (1 << 24)) {
1322 /* Pre indexed */
1323 if (insn & (1 << 23))
1324 tcg_gen_addi_i32(tmp, tmp, offset);
1325 else
1326 tcg_gen_addi_i32(tmp, tmp, -offset);
1327 tcg_gen_mov_i32(dest, tmp);
1328 if (insn & (1 << 21))
1329 store_reg(s, rd, tmp);
1330 else
1331 tcg_temp_free_i32(tmp);
1332 } else if (insn & (1 << 21)) {
1333 /* Post indexed */
1334 tcg_gen_mov_i32(dest, tmp);
1335 if (insn & (1 << 23))
1336 tcg_gen_addi_i32(tmp, tmp, offset);
1337 else
1338 tcg_gen_addi_i32(tmp, tmp, -offset);
1339 store_reg(s, rd, tmp);
1340 } else if (!(insn & (1 << 23)))
1341 return 1;
1342 return 0;
1345 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv dest)
1347 int rd = (insn >> 0) & 0xf;
1348 TCGv tmp;
1350 if (insn & (1 << 8)) {
1351 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1352 return 1;
1353 } else {
1354 tmp = iwmmxt_load_creg(rd);
1356 } else {
1357 tmp = tcg_temp_new_i32();
1358 iwmmxt_load_reg(cpu_V0, rd);
1359 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
1361 tcg_gen_andi_i32(tmp, tmp, mask);
1362 tcg_gen_mov_i32(dest, tmp);
1363 tcg_temp_free_i32(tmp);
1364 return 0;
1367 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
1368 (ie. an undefined instruction). */
1369 static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn)
1371 int rd, wrd;
1372 int rdhi, rdlo, rd0, rd1, i;
1373 TCGv addr;
1374 TCGv tmp, tmp2, tmp3;
1376 if ((insn & 0x0e000e00) == 0x0c000000) {
1377 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1378 wrd = insn & 0xf;
1379 rdlo = (insn >> 12) & 0xf;
1380 rdhi = (insn >> 16) & 0xf;
1381 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1382 iwmmxt_load_reg(cpu_V0, wrd);
1383 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
1384 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1385 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
1386 } else { /* TMCRR */
1387 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1388 iwmmxt_store_reg(cpu_V0, wrd);
1389 gen_op_iwmmxt_set_mup();
1391 return 0;
1394 wrd = (insn >> 12) & 0xf;
1395 addr = tcg_temp_new_i32();
1396 if (gen_iwmmxt_address(s, insn, addr)) {
1397 tcg_temp_free_i32(addr);
1398 return 1;
1400 if (insn & ARM_CP_RW_BIT) {
1401 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1402 tmp = tcg_temp_new_i32();
1403 tcg_gen_qemu_ld32u(tmp, addr, IS_USER(s));
1404 iwmmxt_store_creg(wrd, tmp);
1405 } else {
1406 i = 1;
1407 if (insn & (1 << 8)) {
1408 if (insn & (1 << 22)) { /* WLDRD */
1409 tcg_gen_qemu_ld64(cpu_M0, addr, IS_USER(s));
1410 i = 0;
1411 } else { /* WLDRW wRd */
1412 tmp = gen_ld32(addr, IS_USER(s));
1414 } else {
1415 if (insn & (1 << 22)) { /* WLDRH */
1416 tmp = gen_ld16u(addr, IS_USER(s));
1417 } else { /* WLDRB */
1418 tmp = gen_ld8u(addr, IS_USER(s));
1421 if (i) {
1422 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1423 tcg_temp_free_i32(tmp);
1425 gen_op_iwmmxt_movq_wRn_M0(wrd);
1427 } else {
1428 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1429 tmp = iwmmxt_load_creg(wrd);
1430 gen_st32(tmp, addr, IS_USER(s));
1431 } else {
1432 gen_op_iwmmxt_movq_M0_wRn(wrd);
1433 tmp = tcg_temp_new_i32();
1434 if (insn & (1 << 8)) {
1435 if (insn & (1 << 22)) { /* WSTRD */
1436 tcg_temp_free_i32(tmp);
1437 tcg_gen_qemu_st64(cpu_M0, addr, IS_USER(s));
1438 } else { /* WSTRW wRd */
1439 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1440 gen_st32(tmp, addr, IS_USER(s));
1442 } else {
1443 if (insn & (1 << 22)) { /* WSTRH */
1444 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1445 gen_st16(tmp, addr, IS_USER(s));
1446 } else { /* WSTRB */
1447 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1448 gen_st8(tmp, addr, IS_USER(s));
1453 tcg_temp_free_i32(addr);
1454 return 0;
1457 if ((insn & 0x0f000000) != 0x0e000000)
1458 return 1;
1460 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1461 case 0x000: /* WOR */
1462 wrd = (insn >> 12) & 0xf;
1463 rd0 = (insn >> 0) & 0xf;
1464 rd1 = (insn >> 16) & 0xf;
1465 gen_op_iwmmxt_movq_M0_wRn(rd0);
1466 gen_op_iwmmxt_orq_M0_wRn(rd1);
1467 gen_op_iwmmxt_setpsr_nz();
1468 gen_op_iwmmxt_movq_wRn_M0(wrd);
1469 gen_op_iwmmxt_set_mup();
1470 gen_op_iwmmxt_set_cup();
1471 break;
1472 case 0x011: /* TMCR */
1473 if (insn & 0xf)
1474 return 1;
1475 rd = (insn >> 12) & 0xf;
1476 wrd = (insn >> 16) & 0xf;
1477 switch (wrd) {
1478 case ARM_IWMMXT_wCID:
1479 case ARM_IWMMXT_wCASF:
1480 break;
1481 case ARM_IWMMXT_wCon:
1482 gen_op_iwmmxt_set_cup();
1483 /* Fall through. */
1484 case ARM_IWMMXT_wCSSF:
1485 tmp = iwmmxt_load_creg(wrd);
1486 tmp2 = load_reg(s, rd);
1487 tcg_gen_andc_i32(tmp, tmp, tmp2);
1488 tcg_temp_free_i32(tmp2);
1489 iwmmxt_store_creg(wrd, tmp);
1490 break;
1491 case ARM_IWMMXT_wCGR0:
1492 case ARM_IWMMXT_wCGR1:
1493 case ARM_IWMMXT_wCGR2:
1494 case ARM_IWMMXT_wCGR3:
1495 gen_op_iwmmxt_set_cup();
1496 tmp = load_reg(s, rd);
1497 iwmmxt_store_creg(wrd, tmp);
1498 break;
1499 default:
1500 return 1;
1502 break;
1503 case 0x100: /* WXOR */
1504 wrd = (insn >> 12) & 0xf;
1505 rd0 = (insn >> 0) & 0xf;
1506 rd1 = (insn >> 16) & 0xf;
1507 gen_op_iwmmxt_movq_M0_wRn(rd0);
1508 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1509 gen_op_iwmmxt_setpsr_nz();
1510 gen_op_iwmmxt_movq_wRn_M0(wrd);
1511 gen_op_iwmmxt_set_mup();
1512 gen_op_iwmmxt_set_cup();
1513 break;
1514 case 0x111: /* TMRC */
1515 if (insn & 0xf)
1516 return 1;
1517 rd = (insn >> 12) & 0xf;
1518 wrd = (insn >> 16) & 0xf;
1519 tmp = iwmmxt_load_creg(wrd);
1520 store_reg(s, rd, tmp);
1521 break;
1522 case 0x300: /* WANDN */
1523 wrd = (insn >> 12) & 0xf;
1524 rd0 = (insn >> 0) & 0xf;
1525 rd1 = (insn >> 16) & 0xf;
1526 gen_op_iwmmxt_movq_M0_wRn(rd0);
1527 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1528 gen_op_iwmmxt_andq_M0_wRn(rd1);
1529 gen_op_iwmmxt_setpsr_nz();
1530 gen_op_iwmmxt_movq_wRn_M0(wrd);
1531 gen_op_iwmmxt_set_mup();
1532 gen_op_iwmmxt_set_cup();
1533 break;
1534 case 0x200: /* WAND */
1535 wrd = (insn >> 12) & 0xf;
1536 rd0 = (insn >> 0) & 0xf;
1537 rd1 = (insn >> 16) & 0xf;
1538 gen_op_iwmmxt_movq_M0_wRn(rd0);
1539 gen_op_iwmmxt_andq_M0_wRn(rd1);
1540 gen_op_iwmmxt_setpsr_nz();
1541 gen_op_iwmmxt_movq_wRn_M0(wrd);
1542 gen_op_iwmmxt_set_mup();
1543 gen_op_iwmmxt_set_cup();
1544 break;
1545 case 0x810: case 0xa10: /* WMADD */
1546 wrd = (insn >> 12) & 0xf;
1547 rd0 = (insn >> 0) & 0xf;
1548 rd1 = (insn >> 16) & 0xf;
1549 gen_op_iwmmxt_movq_M0_wRn(rd0);
1550 if (insn & (1 << 21))
1551 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1552 else
1553 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1554 gen_op_iwmmxt_movq_wRn_M0(wrd);
1555 gen_op_iwmmxt_set_mup();
1556 break;
1557 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1558 wrd = (insn >> 12) & 0xf;
1559 rd0 = (insn >> 16) & 0xf;
1560 rd1 = (insn >> 0) & 0xf;
1561 gen_op_iwmmxt_movq_M0_wRn(rd0);
1562 switch ((insn >> 22) & 3) {
1563 case 0:
1564 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1565 break;
1566 case 1:
1567 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1568 break;
1569 case 2:
1570 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1571 break;
1572 case 3:
1573 return 1;
1575 gen_op_iwmmxt_movq_wRn_M0(wrd);
1576 gen_op_iwmmxt_set_mup();
1577 gen_op_iwmmxt_set_cup();
1578 break;
1579 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1580 wrd = (insn >> 12) & 0xf;
1581 rd0 = (insn >> 16) & 0xf;
1582 rd1 = (insn >> 0) & 0xf;
1583 gen_op_iwmmxt_movq_M0_wRn(rd0);
1584 switch ((insn >> 22) & 3) {
1585 case 0:
1586 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1587 break;
1588 case 1:
1589 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1590 break;
1591 case 2:
1592 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1593 break;
1594 case 3:
1595 return 1;
1597 gen_op_iwmmxt_movq_wRn_M0(wrd);
1598 gen_op_iwmmxt_set_mup();
1599 gen_op_iwmmxt_set_cup();
1600 break;
1601 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1602 wrd = (insn >> 12) & 0xf;
1603 rd0 = (insn >> 16) & 0xf;
1604 rd1 = (insn >> 0) & 0xf;
1605 gen_op_iwmmxt_movq_M0_wRn(rd0);
1606 if (insn & (1 << 22))
1607 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1608 else
1609 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1610 if (!(insn & (1 << 20)))
1611 gen_op_iwmmxt_addl_M0_wRn(wrd);
1612 gen_op_iwmmxt_movq_wRn_M0(wrd);
1613 gen_op_iwmmxt_set_mup();
1614 break;
1615 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1616 wrd = (insn >> 12) & 0xf;
1617 rd0 = (insn >> 16) & 0xf;
1618 rd1 = (insn >> 0) & 0xf;
1619 gen_op_iwmmxt_movq_M0_wRn(rd0);
1620 if (insn & (1 << 21)) {
1621 if (insn & (1 << 20))
1622 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1623 else
1624 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1625 } else {
1626 if (insn & (1 << 20))
1627 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1628 else
1629 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1631 gen_op_iwmmxt_movq_wRn_M0(wrd);
1632 gen_op_iwmmxt_set_mup();
1633 break;
1634 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1635 wrd = (insn >> 12) & 0xf;
1636 rd0 = (insn >> 16) & 0xf;
1637 rd1 = (insn >> 0) & 0xf;
1638 gen_op_iwmmxt_movq_M0_wRn(rd0);
1639 if (insn & (1 << 21))
1640 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1641 else
1642 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1643 if (!(insn & (1 << 20))) {
1644 iwmmxt_load_reg(cpu_V1, wrd);
1645 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1647 gen_op_iwmmxt_movq_wRn_M0(wrd);
1648 gen_op_iwmmxt_set_mup();
1649 break;
1650 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1651 wrd = (insn >> 12) & 0xf;
1652 rd0 = (insn >> 16) & 0xf;
1653 rd1 = (insn >> 0) & 0xf;
1654 gen_op_iwmmxt_movq_M0_wRn(rd0);
1655 switch ((insn >> 22) & 3) {
1656 case 0:
1657 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1658 break;
1659 case 1:
1660 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1661 break;
1662 case 2:
1663 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1664 break;
1665 case 3:
1666 return 1;
1668 gen_op_iwmmxt_movq_wRn_M0(wrd);
1669 gen_op_iwmmxt_set_mup();
1670 gen_op_iwmmxt_set_cup();
1671 break;
1672 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1673 wrd = (insn >> 12) & 0xf;
1674 rd0 = (insn >> 16) & 0xf;
1675 rd1 = (insn >> 0) & 0xf;
1676 gen_op_iwmmxt_movq_M0_wRn(rd0);
1677 if (insn & (1 << 22)) {
1678 if (insn & (1 << 20))
1679 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1680 else
1681 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1682 } else {
1683 if (insn & (1 << 20))
1684 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1685 else
1686 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1688 gen_op_iwmmxt_movq_wRn_M0(wrd);
1689 gen_op_iwmmxt_set_mup();
1690 gen_op_iwmmxt_set_cup();
1691 break;
1692 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1693 wrd = (insn >> 12) & 0xf;
1694 rd0 = (insn >> 16) & 0xf;
1695 rd1 = (insn >> 0) & 0xf;
1696 gen_op_iwmmxt_movq_M0_wRn(rd0);
1697 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1698 tcg_gen_andi_i32(tmp, tmp, 7);
1699 iwmmxt_load_reg(cpu_V1, rd1);
1700 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
1701 tcg_temp_free_i32(tmp);
1702 gen_op_iwmmxt_movq_wRn_M0(wrd);
1703 gen_op_iwmmxt_set_mup();
1704 break;
1705 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1706 if (((insn >> 6) & 3) == 3)
1707 return 1;
1708 rd = (insn >> 12) & 0xf;
1709 wrd = (insn >> 16) & 0xf;
1710 tmp = load_reg(s, rd);
1711 gen_op_iwmmxt_movq_M0_wRn(wrd);
1712 switch ((insn >> 6) & 3) {
1713 case 0:
1714 tmp2 = tcg_const_i32(0xff);
1715 tmp3 = tcg_const_i32((insn & 7) << 3);
1716 break;
1717 case 1:
1718 tmp2 = tcg_const_i32(0xffff);
1719 tmp3 = tcg_const_i32((insn & 3) << 4);
1720 break;
1721 case 2:
1722 tmp2 = tcg_const_i32(0xffffffff);
1723 tmp3 = tcg_const_i32((insn & 1) << 5);
1724 break;
1725 default:
1726 TCGV_UNUSED(tmp2);
1727 TCGV_UNUSED(tmp3);
1729 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
1730 tcg_temp_free(tmp3);
1731 tcg_temp_free(tmp2);
1732 tcg_temp_free_i32(tmp);
1733 gen_op_iwmmxt_movq_wRn_M0(wrd);
1734 gen_op_iwmmxt_set_mup();
1735 break;
1736 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1737 rd = (insn >> 12) & 0xf;
1738 wrd = (insn >> 16) & 0xf;
1739 if (rd == 15 || ((insn >> 22) & 3) == 3)
1740 return 1;
1741 gen_op_iwmmxt_movq_M0_wRn(wrd);
1742 tmp = tcg_temp_new_i32();
1743 switch ((insn >> 22) & 3) {
1744 case 0:
1745 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
1746 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1747 if (insn & 8) {
1748 tcg_gen_ext8s_i32(tmp, tmp);
1749 } else {
1750 tcg_gen_andi_i32(tmp, tmp, 0xff);
1752 break;
1753 case 1:
1754 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
1755 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1756 if (insn & 8) {
1757 tcg_gen_ext16s_i32(tmp, tmp);
1758 } else {
1759 tcg_gen_andi_i32(tmp, tmp, 0xffff);
1761 break;
1762 case 2:
1763 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
1764 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1765 break;
1767 store_reg(s, rd, tmp);
1768 break;
1769 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1770 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1771 return 1;
1772 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1773 switch ((insn >> 22) & 3) {
1774 case 0:
1775 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
1776 break;
1777 case 1:
1778 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
1779 break;
1780 case 2:
1781 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
1782 break;
1784 tcg_gen_shli_i32(tmp, tmp, 28);
1785 gen_set_nzcv(tmp);
1786 tcg_temp_free_i32(tmp);
1787 break;
1788 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1789 if (((insn >> 6) & 3) == 3)
1790 return 1;
1791 rd = (insn >> 12) & 0xf;
1792 wrd = (insn >> 16) & 0xf;
1793 tmp = load_reg(s, rd);
1794 switch ((insn >> 6) & 3) {
1795 case 0:
1796 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
1797 break;
1798 case 1:
1799 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
1800 break;
1801 case 2:
1802 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
1803 break;
1805 tcg_temp_free_i32(tmp);
1806 gen_op_iwmmxt_movq_wRn_M0(wrd);
1807 gen_op_iwmmxt_set_mup();
1808 break;
1809 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1810 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1811 return 1;
1812 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1813 tmp2 = tcg_temp_new_i32();
1814 tcg_gen_mov_i32(tmp2, tmp);
1815 switch ((insn >> 22) & 3) {
1816 case 0:
1817 for (i = 0; i < 7; i ++) {
1818 tcg_gen_shli_i32(tmp2, tmp2, 4);
1819 tcg_gen_and_i32(tmp, tmp, tmp2);
1821 break;
1822 case 1:
1823 for (i = 0; i < 3; i ++) {
1824 tcg_gen_shli_i32(tmp2, tmp2, 8);
1825 tcg_gen_and_i32(tmp, tmp, tmp2);
1827 break;
1828 case 2:
1829 tcg_gen_shli_i32(tmp2, tmp2, 16);
1830 tcg_gen_and_i32(tmp, tmp, tmp2);
1831 break;
1833 gen_set_nzcv(tmp);
1834 tcg_temp_free_i32(tmp2);
1835 tcg_temp_free_i32(tmp);
1836 break;
1837 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1838 wrd = (insn >> 12) & 0xf;
1839 rd0 = (insn >> 16) & 0xf;
1840 gen_op_iwmmxt_movq_M0_wRn(rd0);
1841 switch ((insn >> 22) & 3) {
1842 case 0:
1843 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1844 break;
1845 case 1:
1846 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1847 break;
1848 case 2:
1849 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1850 break;
1851 case 3:
1852 return 1;
1854 gen_op_iwmmxt_movq_wRn_M0(wrd);
1855 gen_op_iwmmxt_set_mup();
1856 break;
1857 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1858 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1859 return 1;
1860 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1861 tmp2 = tcg_temp_new_i32();
1862 tcg_gen_mov_i32(tmp2, tmp);
1863 switch ((insn >> 22) & 3) {
1864 case 0:
1865 for (i = 0; i < 7; i ++) {
1866 tcg_gen_shli_i32(tmp2, tmp2, 4);
1867 tcg_gen_or_i32(tmp, tmp, tmp2);
1869 break;
1870 case 1:
1871 for (i = 0; i < 3; i ++) {
1872 tcg_gen_shli_i32(tmp2, tmp2, 8);
1873 tcg_gen_or_i32(tmp, tmp, tmp2);
1875 break;
1876 case 2:
1877 tcg_gen_shli_i32(tmp2, tmp2, 16);
1878 tcg_gen_or_i32(tmp, tmp, tmp2);
1879 break;
1881 gen_set_nzcv(tmp);
1882 tcg_temp_free_i32(tmp2);
1883 tcg_temp_free_i32(tmp);
1884 break;
1885 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1886 rd = (insn >> 12) & 0xf;
1887 rd0 = (insn >> 16) & 0xf;
1888 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
1889 return 1;
1890 gen_op_iwmmxt_movq_M0_wRn(rd0);
1891 tmp = tcg_temp_new_i32();
1892 switch ((insn >> 22) & 3) {
1893 case 0:
1894 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
1895 break;
1896 case 1:
1897 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
1898 break;
1899 case 2:
1900 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
1901 break;
1903 store_reg(s, rd, tmp);
1904 break;
1905 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1906 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1907 wrd = (insn >> 12) & 0xf;
1908 rd0 = (insn >> 16) & 0xf;
1909 rd1 = (insn >> 0) & 0xf;
1910 gen_op_iwmmxt_movq_M0_wRn(rd0);
1911 switch ((insn >> 22) & 3) {
1912 case 0:
1913 if (insn & (1 << 21))
1914 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1915 else
1916 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1917 break;
1918 case 1:
1919 if (insn & (1 << 21))
1920 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1921 else
1922 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
1923 break;
1924 case 2:
1925 if (insn & (1 << 21))
1926 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
1927 else
1928 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
1929 break;
1930 case 3:
1931 return 1;
1933 gen_op_iwmmxt_movq_wRn_M0(wrd);
1934 gen_op_iwmmxt_set_mup();
1935 gen_op_iwmmxt_set_cup();
1936 break;
1937 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1938 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1939 wrd = (insn >> 12) & 0xf;
1940 rd0 = (insn >> 16) & 0xf;
1941 gen_op_iwmmxt_movq_M0_wRn(rd0);
1942 switch ((insn >> 22) & 3) {
1943 case 0:
1944 if (insn & (1 << 21))
1945 gen_op_iwmmxt_unpacklsb_M0();
1946 else
1947 gen_op_iwmmxt_unpacklub_M0();
1948 break;
1949 case 1:
1950 if (insn & (1 << 21))
1951 gen_op_iwmmxt_unpacklsw_M0();
1952 else
1953 gen_op_iwmmxt_unpackluw_M0();
1954 break;
1955 case 2:
1956 if (insn & (1 << 21))
1957 gen_op_iwmmxt_unpacklsl_M0();
1958 else
1959 gen_op_iwmmxt_unpacklul_M0();
1960 break;
1961 case 3:
1962 return 1;
1964 gen_op_iwmmxt_movq_wRn_M0(wrd);
1965 gen_op_iwmmxt_set_mup();
1966 gen_op_iwmmxt_set_cup();
1967 break;
1968 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
1969 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1970 wrd = (insn >> 12) & 0xf;
1971 rd0 = (insn >> 16) & 0xf;
1972 gen_op_iwmmxt_movq_M0_wRn(rd0);
1973 switch ((insn >> 22) & 3) {
1974 case 0:
1975 if (insn & (1 << 21))
1976 gen_op_iwmmxt_unpackhsb_M0();
1977 else
1978 gen_op_iwmmxt_unpackhub_M0();
1979 break;
1980 case 1:
1981 if (insn & (1 << 21))
1982 gen_op_iwmmxt_unpackhsw_M0();
1983 else
1984 gen_op_iwmmxt_unpackhuw_M0();
1985 break;
1986 case 2:
1987 if (insn & (1 << 21))
1988 gen_op_iwmmxt_unpackhsl_M0();
1989 else
1990 gen_op_iwmmxt_unpackhul_M0();
1991 break;
1992 case 3:
1993 return 1;
1995 gen_op_iwmmxt_movq_wRn_M0(wrd);
1996 gen_op_iwmmxt_set_mup();
1997 gen_op_iwmmxt_set_cup();
1998 break;
1999 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2000 case 0x214: case 0x614: case 0xa14: case 0xe14:
2001 if (((insn >> 22) & 3) == 0)
2002 return 1;
2003 wrd = (insn >> 12) & 0xf;
2004 rd0 = (insn >> 16) & 0xf;
2005 gen_op_iwmmxt_movq_M0_wRn(rd0);
2006 tmp = tcg_temp_new_i32();
2007 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2008 tcg_temp_free_i32(tmp);
2009 return 1;
2011 switch ((insn >> 22) & 3) {
2012 case 1:
2013 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
2014 break;
2015 case 2:
2016 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
2017 break;
2018 case 3:
2019 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
2020 break;
2022 tcg_temp_free_i32(tmp);
2023 gen_op_iwmmxt_movq_wRn_M0(wrd);
2024 gen_op_iwmmxt_set_mup();
2025 gen_op_iwmmxt_set_cup();
2026 break;
2027 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2028 case 0x014: case 0x414: case 0x814: case 0xc14:
2029 if (((insn >> 22) & 3) == 0)
2030 return 1;
2031 wrd = (insn >> 12) & 0xf;
2032 rd0 = (insn >> 16) & 0xf;
2033 gen_op_iwmmxt_movq_M0_wRn(rd0);
2034 tmp = tcg_temp_new_i32();
2035 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2036 tcg_temp_free_i32(tmp);
2037 return 1;
2039 switch ((insn >> 22) & 3) {
2040 case 1:
2041 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2042 break;
2043 case 2:
2044 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2045 break;
2046 case 3:
2047 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2048 break;
2050 tcg_temp_free_i32(tmp);
2051 gen_op_iwmmxt_movq_wRn_M0(wrd);
2052 gen_op_iwmmxt_set_mup();
2053 gen_op_iwmmxt_set_cup();
2054 break;
2055 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2056 case 0x114: case 0x514: case 0x914: case 0xd14:
2057 if (((insn >> 22) & 3) == 0)
2058 return 1;
2059 wrd = (insn >> 12) & 0xf;
2060 rd0 = (insn >> 16) & 0xf;
2061 gen_op_iwmmxt_movq_M0_wRn(rd0);
2062 tmp = tcg_temp_new_i32();
2063 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2064 tcg_temp_free_i32(tmp);
2065 return 1;
2067 switch ((insn >> 22) & 3) {
2068 case 1:
2069 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2070 break;
2071 case 2:
2072 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2073 break;
2074 case 3:
2075 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2076 break;
2078 tcg_temp_free_i32(tmp);
2079 gen_op_iwmmxt_movq_wRn_M0(wrd);
2080 gen_op_iwmmxt_set_mup();
2081 gen_op_iwmmxt_set_cup();
2082 break;
2083 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2084 case 0x314: case 0x714: case 0xb14: case 0xf14:
2085 if (((insn >> 22) & 3) == 0)
2086 return 1;
2087 wrd = (insn >> 12) & 0xf;
2088 rd0 = (insn >> 16) & 0xf;
2089 gen_op_iwmmxt_movq_M0_wRn(rd0);
2090 tmp = tcg_temp_new_i32();
2091 switch ((insn >> 22) & 3) {
2092 case 1:
2093 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2094 tcg_temp_free_i32(tmp);
2095 return 1;
2097 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2098 break;
2099 case 2:
2100 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2101 tcg_temp_free_i32(tmp);
2102 return 1;
2104 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2105 break;
2106 case 3:
2107 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2108 tcg_temp_free_i32(tmp);
2109 return 1;
2111 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2112 break;
2114 tcg_temp_free_i32(tmp);
2115 gen_op_iwmmxt_movq_wRn_M0(wrd);
2116 gen_op_iwmmxt_set_mup();
2117 gen_op_iwmmxt_set_cup();
2118 break;
2119 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2120 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2121 wrd = (insn >> 12) & 0xf;
2122 rd0 = (insn >> 16) & 0xf;
2123 rd1 = (insn >> 0) & 0xf;
2124 gen_op_iwmmxt_movq_M0_wRn(rd0);
2125 switch ((insn >> 22) & 3) {
2126 case 0:
2127 if (insn & (1 << 21))
2128 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2129 else
2130 gen_op_iwmmxt_minub_M0_wRn(rd1);
2131 break;
2132 case 1:
2133 if (insn & (1 << 21))
2134 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2135 else
2136 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2137 break;
2138 case 2:
2139 if (insn & (1 << 21))
2140 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2141 else
2142 gen_op_iwmmxt_minul_M0_wRn(rd1);
2143 break;
2144 case 3:
2145 return 1;
2147 gen_op_iwmmxt_movq_wRn_M0(wrd);
2148 gen_op_iwmmxt_set_mup();
2149 break;
2150 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2151 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2152 wrd = (insn >> 12) & 0xf;
2153 rd0 = (insn >> 16) & 0xf;
2154 rd1 = (insn >> 0) & 0xf;
2155 gen_op_iwmmxt_movq_M0_wRn(rd0);
2156 switch ((insn >> 22) & 3) {
2157 case 0:
2158 if (insn & (1 << 21))
2159 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2160 else
2161 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2162 break;
2163 case 1:
2164 if (insn & (1 << 21))
2165 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2166 else
2167 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2168 break;
2169 case 2:
2170 if (insn & (1 << 21))
2171 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2172 else
2173 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2174 break;
2175 case 3:
2176 return 1;
2178 gen_op_iwmmxt_movq_wRn_M0(wrd);
2179 gen_op_iwmmxt_set_mup();
2180 break;
2181 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2182 case 0x402: case 0x502: case 0x602: case 0x702:
2183 wrd = (insn >> 12) & 0xf;
2184 rd0 = (insn >> 16) & 0xf;
2185 rd1 = (insn >> 0) & 0xf;
2186 gen_op_iwmmxt_movq_M0_wRn(rd0);
2187 tmp = tcg_const_i32((insn >> 20) & 3);
2188 iwmmxt_load_reg(cpu_V1, rd1);
2189 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2190 tcg_temp_free(tmp);
2191 gen_op_iwmmxt_movq_wRn_M0(wrd);
2192 gen_op_iwmmxt_set_mup();
2193 break;
2194 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2195 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2196 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2197 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2198 wrd = (insn >> 12) & 0xf;
2199 rd0 = (insn >> 16) & 0xf;
2200 rd1 = (insn >> 0) & 0xf;
2201 gen_op_iwmmxt_movq_M0_wRn(rd0);
2202 switch ((insn >> 20) & 0xf) {
2203 case 0x0:
2204 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2205 break;
2206 case 0x1:
2207 gen_op_iwmmxt_subub_M0_wRn(rd1);
2208 break;
2209 case 0x3:
2210 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2211 break;
2212 case 0x4:
2213 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2214 break;
2215 case 0x5:
2216 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2217 break;
2218 case 0x7:
2219 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2220 break;
2221 case 0x8:
2222 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2223 break;
2224 case 0x9:
2225 gen_op_iwmmxt_subul_M0_wRn(rd1);
2226 break;
2227 case 0xb:
2228 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2229 break;
2230 default:
2231 return 1;
2233 gen_op_iwmmxt_movq_wRn_M0(wrd);
2234 gen_op_iwmmxt_set_mup();
2235 gen_op_iwmmxt_set_cup();
2236 break;
2237 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2238 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2239 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2240 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2241 wrd = (insn >> 12) & 0xf;
2242 rd0 = (insn >> 16) & 0xf;
2243 gen_op_iwmmxt_movq_M0_wRn(rd0);
2244 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2245 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2246 tcg_temp_free(tmp);
2247 gen_op_iwmmxt_movq_wRn_M0(wrd);
2248 gen_op_iwmmxt_set_mup();
2249 gen_op_iwmmxt_set_cup();
2250 break;
2251 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2252 case 0x418: case 0x518: case 0x618: case 0x718:
2253 case 0x818: case 0x918: case 0xa18: case 0xb18:
2254 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2255 wrd = (insn >> 12) & 0xf;
2256 rd0 = (insn >> 16) & 0xf;
2257 rd1 = (insn >> 0) & 0xf;
2258 gen_op_iwmmxt_movq_M0_wRn(rd0);
2259 switch ((insn >> 20) & 0xf) {
2260 case 0x0:
2261 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2262 break;
2263 case 0x1:
2264 gen_op_iwmmxt_addub_M0_wRn(rd1);
2265 break;
2266 case 0x3:
2267 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2268 break;
2269 case 0x4:
2270 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2271 break;
2272 case 0x5:
2273 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2274 break;
2275 case 0x7:
2276 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2277 break;
2278 case 0x8:
2279 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2280 break;
2281 case 0x9:
2282 gen_op_iwmmxt_addul_M0_wRn(rd1);
2283 break;
2284 case 0xb:
2285 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2286 break;
2287 default:
2288 return 1;
2290 gen_op_iwmmxt_movq_wRn_M0(wrd);
2291 gen_op_iwmmxt_set_mup();
2292 gen_op_iwmmxt_set_cup();
2293 break;
2294 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2295 case 0x408: case 0x508: case 0x608: case 0x708:
2296 case 0x808: case 0x908: case 0xa08: case 0xb08:
2297 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2298 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2299 return 1;
2300 wrd = (insn >> 12) & 0xf;
2301 rd0 = (insn >> 16) & 0xf;
2302 rd1 = (insn >> 0) & 0xf;
2303 gen_op_iwmmxt_movq_M0_wRn(rd0);
2304 switch ((insn >> 22) & 3) {
2305 case 1:
2306 if (insn & (1 << 21))
2307 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2308 else
2309 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2310 break;
2311 case 2:
2312 if (insn & (1 << 21))
2313 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2314 else
2315 gen_op_iwmmxt_packul_M0_wRn(rd1);
2316 break;
2317 case 3:
2318 if (insn & (1 << 21))
2319 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2320 else
2321 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2322 break;
2324 gen_op_iwmmxt_movq_wRn_M0(wrd);
2325 gen_op_iwmmxt_set_mup();
2326 gen_op_iwmmxt_set_cup();
2327 break;
2328 case 0x201: case 0x203: case 0x205: case 0x207:
2329 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2330 case 0x211: case 0x213: case 0x215: case 0x217:
2331 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2332 wrd = (insn >> 5) & 0xf;
2333 rd0 = (insn >> 12) & 0xf;
2334 rd1 = (insn >> 0) & 0xf;
2335 if (rd0 == 0xf || rd1 == 0xf)
2336 return 1;
2337 gen_op_iwmmxt_movq_M0_wRn(wrd);
2338 tmp = load_reg(s, rd0);
2339 tmp2 = load_reg(s, rd1);
2340 switch ((insn >> 16) & 0xf) {
2341 case 0x0: /* TMIA */
2342 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2343 break;
2344 case 0x8: /* TMIAPH */
2345 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2346 break;
2347 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2348 if (insn & (1 << 16))
2349 tcg_gen_shri_i32(tmp, tmp, 16);
2350 if (insn & (1 << 17))
2351 tcg_gen_shri_i32(tmp2, tmp2, 16);
2352 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2353 break;
2354 default:
2355 tcg_temp_free_i32(tmp2);
2356 tcg_temp_free_i32(tmp);
2357 return 1;
2359 tcg_temp_free_i32(tmp2);
2360 tcg_temp_free_i32(tmp);
2361 gen_op_iwmmxt_movq_wRn_M0(wrd);
2362 gen_op_iwmmxt_set_mup();
2363 break;
2364 default:
2365 return 1;
2368 return 0;
2371 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
2372 (ie. an undefined instruction). */
2373 static int disas_dsp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2375 int acc, rd0, rd1, rdhi, rdlo;
2376 TCGv tmp, tmp2;
2378 if ((insn & 0x0ff00f10) == 0x0e200010) {
2379 /* Multiply with Internal Accumulate Format */
2380 rd0 = (insn >> 12) & 0xf;
2381 rd1 = insn & 0xf;
2382 acc = (insn >> 5) & 7;
2384 if (acc != 0)
2385 return 1;
2387 tmp = load_reg(s, rd0);
2388 tmp2 = load_reg(s, rd1);
2389 switch ((insn >> 16) & 0xf) {
2390 case 0x0: /* MIA */
2391 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2392 break;
2393 case 0x8: /* MIAPH */
2394 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2395 break;
2396 case 0xc: /* MIABB */
2397 case 0xd: /* MIABT */
2398 case 0xe: /* MIATB */
2399 case 0xf: /* MIATT */
2400 if (insn & (1 << 16))
2401 tcg_gen_shri_i32(tmp, tmp, 16);
2402 if (insn & (1 << 17))
2403 tcg_gen_shri_i32(tmp2, tmp2, 16);
2404 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2405 break;
2406 default:
2407 return 1;
2409 tcg_temp_free_i32(tmp2);
2410 tcg_temp_free_i32(tmp);
2412 gen_op_iwmmxt_movq_wRn_M0(acc);
2413 return 0;
2416 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2417 /* Internal Accumulator Access Format */
2418 rdhi = (insn >> 16) & 0xf;
2419 rdlo = (insn >> 12) & 0xf;
2420 acc = insn & 7;
2422 if (acc != 0)
2423 return 1;
2425 if (insn & ARM_CP_RW_BIT) { /* MRA */
2426 iwmmxt_load_reg(cpu_V0, acc);
2427 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
2428 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
2429 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
2430 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2431 } else { /* MAR */
2432 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2433 iwmmxt_store_reg(cpu_V0, acc);
2435 return 0;
2438 return 1;
2441 /* Disassemble system coprocessor instruction. Return nonzero if
2442 instruction is not defined. */
2443 static int disas_cp_insn(CPUState *env, DisasContext *s, uint32_t insn)
2445 TCGv tmp, tmp2;
2446 uint32_t rd = (insn >> 12) & 0xf;
2447 uint32_t cp = (insn >> 8) & 0xf;
2448 if (IS_USER(s)) {
2449 return 1;
2452 if (insn & ARM_CP_RW_BIT) {
2453 if (!env->cp[cp].cp_read)
2454 return 1;
2455 gen_set_pc_im(s->pc);
2456 tmp = tcg_temp_new_i32();
2457 tmp2 = tcg_const_i32(insn);
2458 gen_helper_get_cp(tmp, cpu_env, tmp2);
2459 tcg_temp_free(tmp2);
2460 store_reg(s, rd, tmp);
2461 } else {
2462 if (!env->cp[cp].cp_write)
2463 return 1;
2464 gen_set_pc_im(s->pc);
2465 tmp = load_reg(s, rd);
2466 tmp2 = tcg_const_i32(insn);
2467 gen_helper_set_cp(cpu_env, tmp2, tmp);
2468 tcg_temp_free(tmp2);
2469 tcg_temp_free_i32(tmp);
2471 return 0;
2474 static int cp15_user_ok(CPUState *env, uint32_t insn)
2476 int cpn = (insn >> 16) & 0xf;
2477 int cpm = insn & 0xf;
2478 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2480 if (arm_feature(env, ARM_FEATURE_V7) && cpn == 9) {
2481 /* Performance monitor registers fall into three categories:
2482 * (a) always UNDEF in usermode
2483 * (b) UNDEF only if PMUSERENR.EN is 0
2484 * (c) always read OK and UNDEF on write (PMUSERENR only)
2486 if ((cpm == 12 && (op < 6)) ||
2487 (cpm == 13 && (op < 3))) {
2488 return env->cp15.c9_pmuserenr;
2489 } else if (cpm == 14 && op == 0 && (insn & ARM_CP_RW_BIT)) {
2490 /* PMUSERENR, read only */
2491 return 1;
2493 return 0;
2496 if (cpn == 13 && cpm == 0) {
2497 /* TLS register. */
2498 if (op == 2 || (op == 3 && (insn & ARM_CP_RW_BIT)))
2499 return 1;
2501 return 0;
2504 static int cp15_tls_load_store(CPUState *env, DisasContext *s, uint32_t insn, uint32_t rd)
2506 TCGv tmp;
2507 int cpn = (insn >> 16) & 0xf;
2508 int cpm = insn & 0xf;
2509 int op = ((insn >> 5) & 7) | ((insn >> 18) & 0x38);
2511 if (!arm_feature(env, ARM_FEATURE_V6K))
2512 return 0;
2514 if (!(cpn == 13 && cpm == 0))
2515 return 0;
2517 if (insn & ARM_CP_RW_BIT) {
2518 switch (op) {
2519 case 2:
2520 tmp = load_cpu_field(cp15.c13_tls1);
2521 break;
2522 case 3:
2523 tmp = load_cpu_field(cp15.c13_tls2);
2524 break;
2525 case 4:
2526 tmp = load_cpu_field(cp15.c13_tls3);
2527 break;
2528 default:
2529 return 0;
2531 store_reg(s, rd, tmp);
2533 } else {
2534 tmp = load_reg(s, rd);
2535 switch (op) {
2536 case 2:
2537 store_cpu_field(tmp, cp15.c13_tls1);
2538 break;
2539 case 3:
2540 store_cpu_field(tmp, cp15.c13_tls2);
2541 break;
2542 case 4:
2543 store_cpu_field(tmp, cp15.c13_tls3);
2544 break;
2545 default:
2546 tcg_temp_free_i32(tmp);
2547 return 0;
2550 return 1;
2553 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2554 instruction is not defined. */
2555 static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2557 uint32_t rd;
2558 TCGv tmp, tmp2;
2560 /* M profile cores use memory mapped registers instead of cp15. */
2561 if (arm_feature(env, ARM_FEATURE_M))
2562 return 1;
2564 if ((insn & (1 << 25)) == 0) {
2565 if (insn & (1 << 20)) {
2566 /* mrrc */
2567 return 1;
2569 /* mcrr. Used for block cache operations, so implement as no-op. */
2570 return 0;
2572 if ((insn & (1 << 4)) == 0) {
2573 /* cdp */
2574 return 1;
2576 /* We special case a number of cp15 instructions which were used
2577 * for things which are real instructions in ARMv7. This allows
2578 * them to work in linux-user mode which doesn't provide functional
2579 * get_cp15/set_cp15 helpers, and is more efficient anyway.
2581 switch ((insn & 0x0fff0fff)) {
2582 case 0x0e070f90:
2583 /* 0,c7,c0,4: Standard v6 WFI (also used in some pre-v6 cores).
2584 * In v7, this must NOP.
2586 if (IS_USER(s)) {
2587 return 1;
2589 if (!arm_feature(env, ARM_FEATURE_V7)) {
2590 /* Wait for interrupt. */
2591 gen_set_pc_im(s->pc);
2592 s->is_jmp = DISAS_WFI;
2594 return 0;
2595 case 0x0e070f58:
2596 /* 0,c7,c8,2: Not all pre-v6 cores implemented this WFI,
2597 * so this is slightly over-broad.
2599 if (!IS_USER(s) && !arm_feature(env, ARM_FEATURE_V6)) {
2600 /* Wait for interrupt. */
2601 gen_set_pc_im(s->pc);
2602 s->is_jmp = DISAS_WFI;
2603 return 0;
2605 /* Otherwise continue to handle via helper function.
2606 * In particular, on v7 and some v6 cores this is one of
2607 * the VA-PA registers.
2609 break;
2610 case 0x0e070f3d:
2611 /* 0,c7,c13,1: prefetch-by-MVA in v6, NOP in v7 */
2612 if (arm_feature(env, ARM_FEATURE_V6)) {
2613 return IS_USER(s) ? 1 : 0;
2615 break;
2616 case 0x0e070f95: /* 0,c7,c5,4 : ISB */
2617 case 0x0e070f9a: /* 0,c7,c10,4: DSB */
2618 case 0x0e070fba: /* 0,c7,c10,5: DMB */
2619 /* Barriers in both v6 and v7 */
2620 if (arm_feature(env, ARM_FEATURE_V6)) {
2621 return 0;
2623 break;
2624 default:
2625 break;
2628 if (IS_USER(s) && !cp15_user_ok(env, insn)) {
2629 return 1;
2632 rd = (insn >> 12) & 0xf;
2634 if (cp15_tls_load_store(env, s, insn, rd))
2635 return 0;
2637 tmp2 = tcg_const_i32(insn);
2638 if (insn & ARM_CP_RW_BIT) {
2639 tmp = tcg_temp_new_i32();
2640 gen_helper_get_cp15(tmp, cpu_env, tmp2);
2641 /* If the destination register is r15 then sets condition codes. */
2642 if (rd != 15)
2643 store_reg(s, rd, tmp);
2644 else
2645 tcg_temp_free_i32(tmp);
2646 } else {
2647 tmp = load_reg(s, rd);
2648 gen_helper_set_cp15(cpu_env, tmp2, tmp);
2649 tcg_temp_free_i32(tmp);
2650 /* Normally we would always end the TB here, but Linux
2651 * arch/arm/mach-pxa/sleep.S expects two instructions following
2652 * an MMU enable to execute from cache. Imitate this behaviour. */
2653 if (!arm_feature(env, ARM_FEATURE_XSCALE) ||
2654 (insn & 0x0fff0fff) != 0x0e010f10)
2655 gen_lookup_tb(s);
2657 tcg_temp_free_i32(tmp2);
2658 return 0;
2661 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2662 #define VFP_SREG(insn, bigbit, smallbit) \
2663 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2664 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2665 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2666 reg = (((insn) >> (bigbit)) & 0x0f) \
2667 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2668 } else { \
2669 if (insn & (1 << (smallbit))) \
2670 return 1; \
2671 reg = ((insn) >> (bigbit)) & 0x0f; \
2672 }} while (0)
2674 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2675 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2676 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2677 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2678 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2679 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2681 /* Move between integer and VFP cores. */
2682 static TCGv gen_vfp_mrs(void)
2684 TCGv tmp = tcg_temp_new_i32();
2685 tcg_gen_mov_i32(tmp, cpu_F0s);
2686 return tmp;
2689 static void gen_vfp_msr(TCGv tmp)
2691 tcg_gen_mov_i32(cpu_F0s, tmp);
2692 tcg_temp_free_i32(tmp);
2695 static void gen_neon_dup_u8(TCGv var, int shift)
2697 TCGv tmp = tcg_temp_new_i32();
2698 if (shift)
2699 tcg_gen_shri_i32(var, var, shift);
2700 tcg_gen_ext8u_i32(var, var);
2701 tcg_gen_shli_i32(tmp, var, 8);
2702 tcg_gen_or_i32(var, var, tmp);
2703 tcg_gen_shli_i32(tmp, var, 16);
2704 tcg_gen_or_i32(var, var, tmp);
2705 tcg_temp_free_i32(tmp);
2708 static void gen_neon_dup_low16(TCGv var)
2710 TCGv tmp = tcg_temp_new_i32();
2711 tcg_gen_ext16u_i32(var, var);
2712 tcg_gen_shli_i32(tmp, var, 16);
2713 tcg_gen_or_i32(var, var, tmp);
2714 tcg_temp_free_i32(tmp);
2717 static void gen_neon_dup_high16(TCGv var)
2719 TCGv tmp = tcg_temp_new_i32();
2720 tcg_gen_andi_i32(var, var, 0xffff0000);
2721 tcg_gen_shri_i32(tmp, var, 16);
2722 tcg_gen_or_i32(var, var, tmp);
2723 tcg_temp_free_i32(tmp);
2726 static TCGv gen_load_and_replicate(DisasContext *s, TCGv addr, int size)
2728 /* Load a single Neon element and replicate into a 32 bit TCG reg */
2729 TCGv tmp;
2730 switch (size) {
2731 case 0:
2732 tmp = gen_ld8u(addr, IS_USER(s));
2733 gen_neon_dup_u8(tmp, 0);
2734 break;
2735 case 1:
2736 tmp = gen_ld16u(addr, IS_USER(s));
2737 gen_neon_dup_low16(tmp);
2738 break;
2739 case 2:
2740 tmp = gen_ld32(addr, IS_USER(s));
2741 break;
2742 default: /* Avoid compiler warnings. */
2743 abort();
2745 return tmp;
2748 /* Disassemble a VFP instruction. Returns nonzero if an error occurred
2749 (ie. an undefined instruction). */
2750 static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
2752 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2753 int dp, veclen;
2754 TCGv addr;
2755 TCGv tmp;
2756 TCGv tmp2;
2758 if (!arm_feature(env, ARM_FEATURE_VFP))
2759 return 1;
2761 if (!s->vfp_enabled) {
2762 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2763 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2764 return 1;
2765 rn = (insn >> 16) & 0xf;
2766 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2767 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2768 return 1;
2770 dp = ((insn & 0xf00) == 0xb00);
2771 switch ((insn >> 24) & 0xf) {
2772 case 0xe:
2773 if (insn & (1 << 4)) {
2774 /* single register transfer */
2775 rd = (insn >> 12) & 0xf;
2776 if (dp) {
2777 int size;
2778 int pass;
2780 VFP_DREG_N(rn, insn);
2781 if (insn & 0xf)
2782 return 1;
2783 if (insn & 0x00c00060
2784 && !arm_feature(env, ARM_FEATURE_NEON))
2785 return 1;
2787 pass = (insn >> 21) & 1;
2788 if (insn & (1 << 22)) {
2789 size = 0;
2790 offset = ((insn >> 5) & 3) * 8;
2791 } else if (insn & (1 << 5)) {
2792 size = 1;
2793 offset = (insn & (1 << 6)) ? 16 : 0;
2794 } else {
2795 size = 2;
2796 offset = 0;
2798 if (insn & ARM_CP_RW_BIT) {
2799 /* vfp->arm */
2800 tmp = neon_load_reg(rn, pass);
2801 switch (size) {
2802 case 0:
2803 if (offset)
2804 tcg_gen_shri_i32(tmp, tmp, offset);
2805 if (insn & (1 << 23))
2806 gen_uxtb(tmp);
2807 else
2808 gen_sxtb(tmp);
2809 break;
2810 case 1:
2811 if (insn & (1 << 23)) {
2812 if (offset) {
2813 tcg_gen_shri_i32(tmp, tmp, 16);
2814 } else {
2815 gen_uxth(tmp);
2817 } else {
2818 if (offset) {
2819 tcg_gen_sari_i32(tmp, tmp, 16);
2820 } else {
2821 gen_sxth(tmp);
2824 break;
2825 case 2:
2826 break;
2828 store_reg(s, rd, tmp);
2829 } else {
2830 /* arm->vfp */
2831 tmp = load_reg(s, rd);
2832 if (insn & (1 << 23)) {
2833 /* VDUP */
2834 if (size == 0) {
2835 gen_neon_dup_u8(tmp, 0);
2836 } else if (size == 1) {
2837 gen_neon_dup_low16(tmp);
2839 for (n = 0; n <= pass * 2; n++) {
2840 tmp2 = tcg_temp_new_i32();
2841 tcg_gen_mov_i32(tmp2, tmp);
2842 neon_store_reg(rn, n, tmp2);
2844 neon_store_reg(rn, n, tmp);
2845 } else {
2846 /* VMOV */
2847 switch (size) {
2848 case 0:
2849 tmp2 = neon_load_reg(rn, pass);
2850 gen_bfi(tmp, tmp2, tmp, offset, 0xff);
2851 tcg_temp_free_i32(tmp2);
2852 break;
2853 case 1:
2854 tmp2 = neon_load_reg(rn, pass);
2855 gen_bfi(tmp, tmp2, tmp, offset, 0xffff);
2856 tcg_temp_free_i32(tmp2);
2857 break;
2858 case 2:
2859 break;
2861 neon_store_reg(rn, pass, tmp);
2864 } else { /* !dp */
2865 if ((insn & 0x6f) != 0x00)
2866 return 1;
2867 rn = VFP_SREG_N(insn);
2868 if (insn & ARM_CP_RW_BIT) {
2869 /* vfp->arm */
2870 if (insn & (1 << 21)) {
2871 /* system register */
2872 rn >>= 1;
2874 switch (rn) {
2875 case ARM_VFP_FPSID:
2876 /* VFP2 allows access to FSID from userspace.
2877 VFP3 restricts all id registers to privileged
2878 accesses. */
2879 if (IS_USER(s)
2880 && arm_feature(env, ARM_FEATURE_VFP3))
2881 return 1;
2882 tmp = load_cpu_field(vfp.xregs[rn]);
2883 break;
2884 case ARM_VFP_FPEXC:
2885 if (IS_USER(s))
2886 return 1;
2887 tmp = load_cpu_field(vfp.xregs[rn]);
2888 break;
2889 case ARM_VFP_FPINST:
2890 case ARM_VFP_FPINST2:
2891 /* Not present in VFP3. */
2892 if (IS_USER(s)
2893 || arm_feature(env, ARM_FEATURE_VFP3))
2894 return 1;
2895 tmp = load_cpu_field(vfp.xregs[rn]);
2896 break;
2897 case ARM_VFP_FPSCR:
2898 if (rd == 15) {
2899 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2900 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2901 } else {
2902 tmp = tcg_temp_new_i32();
2903 gen_helper_vfp_get_fpscr(tmp, cpu_env);
2905 break;
2906 case ARM_VFP_MVFR0:
2907 case ARM_VFP_MVFR1:
2908 if (IS_USER(s)
2909 || !arm_feature(env, ARM_FEATURE_VFP3))
2910 return 1;
2911 tmp = load_cpu_field(vfp.xregs[rn]);
2912 break;
2913 default:
2914 return 1;
2916 } else {
2917 gen_mov_F0_vreg(0, rn);
2918 tmp = gen_vfp_mrs();
2920 if (rd == 15) {
2921 /* Set the 4 flag bits in the CPSR. */
2922 gen_set_nzcv(tmp);
2923 tcg_temp_free_i32(tmp);
2924 } else {
2925 store_reg(s, rd, tmp);
2927 } else {
2928 /* arm->vfp */
2929 tmp = load_reg(s, rd);
2930 if (insn & (1 << 21)) {
2931 rn >>= 1;
2932 /* system register */
2933 switch (rn) {
2934 case ARM_VFP_FPSID:
2935 case ARM_VFP_MVFR0:
2936 case ARM_VFP_MVFR1:
2937 /* Writes are ignored. */
2938 break;
2939 case ARM_VFP_FPSCR:
2940 gen_helper_vfp_set_fpscr(cpu_env, tmp);
2941 tcg_temp_free_i32(tmp);
2942 gen_lookup_tb(s);
2943 break;
2944 case ARM_VFP_FPEXC:
2945 if (IS_USER(s))
2946 return 1;
2947 /* TODO: VFP subarchitecture support.
2948 * For now, keep the EN bit only */
2949 tcg_gen_andi_i32(tmp, tmp, 1 << 30);
2950 store_cpu_field(tmp, vfp.xregs[rn]);
2951 gen_lookup_tb(s);
2952 break;
2953 case ARM_VFP_FPINST:
2954 case ARM_VFP_FPINST2:
2955 store_cpu_field(tmp, vfp.xregs[rn]);
2956 break;
2957 default:
2958 return 1;
2960 } else {
2961 gen_vfp_msr(tmp);
2962 gen_mov_vreg_F0(0, rn);
2966 } else {
2967 /* data processing */
2968 /* The opcode is in bits 23, 21, 20 and 6. */
2969 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
2970 if (dp) {
2971 if (op == 15) {
2972 /* rn is opcode */
2973 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
2974 } else {
2975 /* rn is register number */
2976 VFP_DREG_N(rn, insn);
2979 if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18))) {
2980 /* Integer or single precision destination. */
2981 rd = VFP_SREG_D(insn);
2982 } else {
2983 VFP_DREG_D(rd, insn);
2985 if (op == 15 &&
2986 (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14))) {
2987 /* VCVT from int is always from S reg regardless of dp bit.
2988 * VCVT with immediate frac_bits has same format as SREG_M
2990 rm = VFP_SREG_M(insn);
2991 } else {
2992 VFP_DREG_M(rm, insn);
2994 } else {
2995 rn = VFP_SREG_N(insn);
2996 if (op == 15 && rn == 15) {
2997 /* Double precision destination. */
2998 VFP_DREG_D(rd, insn);
2999 } else {
3000 rd = VFP_SREG_D(insn);
3002 /* NB that we implicitly rely on the encoding for the frac_bits
3003 * in VCVT of fixed to float being the same as that of an SREG_M
3005 rm = VFP_SREG_M(insn);
3008 veclen = s->vec_len;
3009 if (op == 15 && rn > 3)
3010 veclen = 0;
3012 /* Shut up compiler warnings. */
3013 delta_m = 0;
3014 delta_d = 0;
3015 bank_mask = 0;
3017 if (veclen > 0) {
3018 if (dp)
3019 bank_mask = 0xc;
3020 else
3021 bank_mask = 0x18;
3023 /* Figure out what type of vector operation this is. */
3024 if ((rd & bank_mask) == 0) {
3025 /* scalar */
3026 veclen = 0;
3027 } else {
3028 if (dp)
3029 delta_d = (s->vec_stride >> 1) + 1;
3030 else
3031 delta_d = s->vec_stride + 1;
3033 if ((rm & bank_mask) == 0) {
3034 /* mixed scalar/vector */
3035 delta_m = 0;
3036 } else {
3037 /* vector */
3038 delta_m = delta_d;
3043 /* Load the initial operands. */
3044 if (op == 15) {
3045 switch (rn) {
3046 case 16:
3047 case 17:
3048 /* Integer source */
3049 gen_mov_F0_vreg(0, rm);
3050 break;
3051 case 8:
3052 case 9:
3053 /* Compare */
3054 gen_mov_F0_vreg(dp, rd);
3055 gen_mov_F1_vreg(dp, rm);
3056 break;
3057 case 10:
3058 case 11:
3059 /* Compare with zero */
3060 gen_mov_F0_vreg(dp, rd);
3061 gen_vfp_F1_ld0(dp);
3062 break;
3063 case 20:
3064 case 21:
3065 case 22:
3066 case 23:
3067 case 28:
3068 case 29:
3069 case 30:
3070 case 31:
3071 /* Source and destination the same. */
3072 gen_mov_F0_vreg(dp, rd);
3073 break;
3074 case 4:
3075 case 5:
3076 case 6:
3077 case 7:
3078 /* VCVTB, VCVTT: only present with the halfprec extension,
3079 * UNPREDICTABLE if bit 8 is set (we choose to UNDEF)
3081 if (dp || !arm_feature(env, ARM_FEATURE_VFP_FP16)) {
3082 return 1;
3084 /* Otherwise fall through */
3085 default:
3086 /* One source operand. */
3087 gen_mov_F0_vreg(dp, rm);
3088 break;
3090 } else {
3091 /* Two source operands. */
3092 gen_mov_F0_vreg(dp, rn);
3093 gen_mov_F1_vreg(dp, rm);
3096 for (;;) {
3097 /* Perform the calculation. */
3098 switch (op) {
3099 case 0: /* VMLA: fd + (fn * fm) */
3100 /* Note that order of inputs to the add matters for NaNs */
3101 gen_vfp_F1_mul(dp);
3102 gen_mov_F0_vreg(dp, rd);
3103 gen_vfp_add(dp);
3104 break;
3105 case 1: /* VMLS: fd + -(fn * fm) */
3106 gen_vfp_mul(dp);
3107 gen_vfp_F1_neg(dp);
3108 gen_mov_F0_vreg(dp, rd);
3109 gen_vfp_add(dp);
3110 break;
3111 case 2: /* VNMLS: -fd + (fn * fm) */
3112 /* Note that it isn't valid to replace (-A + B) with (B - A)
3113 * or similar plausible looking simplifications
3114 * because this will give wrong results for NaNs.
3116 gen_vfp_F1_mul(dp);
3117 gen_mov_F0_vreg(dp, rd);
3118 gen_vfp_neg(dp);
3119 gen_vfp_add(dp);
3120 break;
3121 case 3: /* VNMLA: -fd + -(fn * fm) */
3122 gen_vfp_mul(dp);
3123 gen_vfp_F1_neg(dp);
3124 gen_mov_F0_vreg(dp, rd);
3125 gen_vfp_neg(dp);
3126 gen_vfp_add(dp);
3127 break;
3128 case 4: /* mul: fn * fm */
3129 gen_vfp_mul(dp);
3130 break;
3131 case 5: /* nmul: -(fn * fm) */
3132 gen_vfp_mul(dp);
3133 gen_vfp_neg(dp);
3134 break;
3135 case 6: /* add: fn + fm */
3136 gen_vfp_add(dp);
3137 break;
3138 case 7: /* sub: fn - fm */
3139 gen_vfp_sub(dp);
3140 break;
3141 case 8: /* div: fn / fm */
3142 gen_vfp_div(dp);
3143 break;
3144 case 14: /* fconst */
3145 if (!arm_feature(env, ARM_FEATURE_VFP3))
3146 return 1;
3148 n = (insn << 12) & 0x80000000;
3149 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3150 if (dp) {
3151 if (i & 0x40)
3152 i |= 0x3f80;
3153 else
3154 i |= 0x4000;
3155 n |= i << 16;
3156 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3157 } else {
3158 if (i & 0x40)
3159 i |= 0x780;
3160 else
3161 i |= 0x800;
3162 n |= i << 19;
3163 tcg_gen_movi_i32(cpu_F0s, n);
3165 break;
3166 case 15: /* extension space */
3167 switch (rn) {
3168 case 0: /* cpy */
3169 /* no-op */
3170 break;
3171 case 1: /* abs */
3172 gen_vfp_abs(dp);
3173 break;
3174 case 2: /* neg */
3175 gen_vfp_neg(dp);
3176 break;
3177 case 3: /* sqrt */
3178 gen_vfp_sqrt(dp);
3179 break;
3180 case 4: /* vcvtb.f32.f16 */
3181 tmp = gen_vfp_mrs();
3182 tcg_gen_ext16u_i32(tmp, tmp);
3183 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3184 tcg_temp_free_i32(tmp);
3185 break;
3186 case 5: /* vcvtt.f32.f16 */
3187 tmp = gen_vfp_mrs();
3188 tcg_gen_shri_i32(tmp, tmp, 16);
3189 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3190 tcg_temp_free_i32(tmp);
3191 break;
3192 case 6: /* vcvtb.f16.f32 */
3193 tmp = tcg_temp_new_i32();
3194 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3195 gen_mov_F0_vreg(0, rd);
3196 tmp2 = gen_vfp_mrs();
3197 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3198 tcg_gen_or_i32(tmp, tmp, tmp2);
3199 tcg_temp_free_i32(tmp2);
3200 gen_vfp_msr(tmp);
3201 break;
3202 case 7: /* vcvtt.f16.f32 */
3203 tmp = tcg_temp_new_i32();
3204 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3205 tcg_gen_shli_i32(tmp, tmp, 16);
3206 gen_mov_F0_vreg(0, rd);
3207 tmp2 = gen_vfp_mrs();
3208 tcg_gen_ext16u_i32(tmp2, tmp2);
3209 tcg_gen_or_i32(tmp, tmp, tmp2);
3210 tcg_temp_free_i32(tmp2);
3211 gen_vfp_msr(tmp);
3212 break;
3213 case 8: /* cmp */
3214 gen_vfp_cmp(dp);
3215 break;
3216 case 9: /* cmpe */
3217 gen_vfp_cmpe(dp);
3218 break;
3219 case 10: /* cmpz */
3220 gen_vfp_cmp(dp);
3221 break;
3222 case 11: /* cmpez */
3223 gen_vfp_F1_ld0(dp);
3224 gen_vfp_cmpe(dp);
3225 break;
3226 case 15: /* single<->double conversion */
3227 if (dp)
3228 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3229 else
3230 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3231 break;
3232 case 16: /* fuito */
3233 gen_vfp_uito(dp, 0);
3234 break;
3235 case 17: /* fsito */
3236 gen_vfp_sito(dp, 0);
3237 break;
3238 case 20: /* fshto */
3239 if (!arm_feature(env, ARM_FEATURE_VFP3))
3240 return 1;
3241 gen_vfp_shto(dp, 16 - rm, 0);
3242 break;
3243 case 21: /* fslto */
3244 if (!arm_feature(env, ARM_FEATURE_VFP3))
3245 return 1;
3246 gen_vfp_slto(dp, 32 - rm, 0);
3247 break;
3248 case 22: /* fuhto */
3249 if (!arm_feature(env, ARM_FEATURE_VFP3))
3250 return 1;
3251 gen_vfp_uhto(dp, 16 - rm, 0);
3252 break;
3253 case 23: /* fulto */
3254 if (!arm_feature(env, ARM_FEATURE_VFP3))
3255 return 1;
3256 gen_vfp_ulto(dp, 32 - rm, 0);
3257 break;
3258 case 24: /* ftoui */
3259 gen_vfp_toui(dp, 0);
3260 break;
3261 case 25: /* ftouiz */
3262 gen_vfp_touiz(dp, 0);
3263 break;
3264 case 26: /* ftosi */
3265 gen_vfp_tosi(dp, 0);
3266 break;
3267 case 27: /* ftosiz */
3268 gen_vfp_tosiz(dp, 0);
3269 break;
3270 case 28: /* ftosh */
3271 if (!arm_feature(env, ARM_FEATURE_VFP3))
3272 return 1;
3273 gen_vfp_tosh(dp, 16 - rm, 0);
3274 break;
3275 case 29: /* ftosl */
3276 if (!arm_feature(env, ARM_FEATURE_VFP3))
3277 return 1;
3278 gen_vfp_tosl(dp, 32 - rm, 0);
3279 break;
3280 case 30: /* ftouh */
3281 if (!arm_feature(env, ARM_FEATURE_VFP3))
3282 return 1;
3283 gen_vfp_touh(dp, 16 - rm, 0);
3284 break;
3285 case 31: /* ftoul */
3286 if (!arm_feature(env, ARM_FEATURE_VFP3))
3287 return 1;
3288 gen_vfp_toul(dp, 32 - rm, 0);
3289 break;
3290 default: /* undefined */
3291 return 1;
3293 break;
3294 default: /* undefined */
3295 return 1;
3298 /* Write back the result. */
3299 if (op == 15 && (rn >= 8 && rn <= 11))
3300 ; /* Comparison, do nothing. */
3301 else if (op == 15 && dp && ((rn & 0x1c) == 0x18))
3302 /* VCVT double to int: always integer result. */
3303 gen_mov_vreg_F0(0, rd);
3304 else if (op == 15 && rn == 15)
3305 /* conversion */
3306 gen_mov_vreg_F0(!dp, rd);
3307 else
3308 gen_mov_vreg_F0(dp, rd);
3310 /* break out of the loop if we have finished */
3311 if (veclen == 0)
3312 break;
3314 if (op == 15 && delta_m == 0) {
3315 /* single source one-many */
3316 while (veclen--) {
3317 rd = ((rd + delta_d) & (bank_mask - 1))
3318 | (rd & bank_mask);
3319 gen_mov_vreg_F0(dp, rd);
3321 break;
3323 /* Setup the next operands. */
3324 veclen--;
3325 rd = ((rd + delta_d) & (bank_mask - 1))
3326 | (rd & bank_mask);
3328 if (op == 15) {
3329 /* One source operand. */
3330 rm = ((rm + delta_m) & (bank_mask - 1))
3331 | (rm & bank_mask);
3332 gen_mov_F0_vreg(dp, rm);
3333 } else {
3334 /* Two source operands. */
3335 rn = ((rn + delta_d) & (bank_mask - 1))
3336 | (rn & bank_mask);
3337 gen_mov_F0_vreg(dp, rn);
3338 if (delta_m) {
3339 rm = ((rm + delta_m) & (bank_mask - 1))
3340 | (rm & bank_mask);
3341 gen_mov_F1_vreg(dp, rm);
3346 break;
3347 case 0xc:
3348 case 0xd:
3349 if ((insn & 0x03e00000) == 0x00400000) {
3350 /* two-register transfer */
3351 rn = (insn >> 16) & 0xf;
3352 rd = (insn >> 12) & 0xf;
3353 if (dp) {
3354 VFP_DREG_M(rm, insn);
3355 } else {
3356 rm = VFP_SREG_M(insn);
3359 if (insn & ARM_CP_RW_BIT) {
3360 /* vfp->arm */
3361 if (dp) {
3362 gen_mov_F0_vreg(0, rm * 2);
3363 tmp = gen_vfp_mrs();
3364 store_reg(s, rd, tmp);
3365 gen_mov_F0_vreg(0, rm * 2 + 1);
3366 tmp = gen_vfp_mrs();
3367 store_reg(s, rn, tmp);
3368 } else {
3369 gen_mov_F0_vreg(0, rm);
3370 tmp = gen_vfp_mrs();
3371 store_reg(s, rd, tmp);
3372 gen_mov_F0_vreg(0, rm + 1);
3373 tmp = gen_vfp_mrs();
3374 store_reg(s, rn, tmp);
3376 } else {
3377 /* arm->vfp */
3378 if (dp) {
3379 tmp = load_reg(s, rd);
3380 gen_vfp_msr(tmp);
3381 gen_mov_vreg_F0(0, rm * 2);
3382 tmp = load_reg(s, rn);
3383 gen_vfp_msr(tmp);
3384 gen_mov_vreg_F0(0, rm * 2 + 1);
3385 } else {
3386 tmp = load_reg(s, rd);
3387 gen_vfp_msr(tmp);
3388 gen_mov_vreg_F0(0, rm);
3389 tmp = load_reg(s, rn);
3390 gen_vfp_msr(tmp);
3391 gen_mov_vreg_F0(0, rm + 1);
3394 } else {
3395 /* Load/store */
3396 rn = (insn >> 16) & 0xf;
3397 if (dp)
3398 VFP_DREG_D(rd, insn);
3399 else
3400 rd = VFP_SREG_D(insn);
3401 if ((insn & 0x01200000) == 0x01000000) {
3402 /* Single load/store */
3403 offset = (insn & 0xff) << 2;
3404 if ((insn & (1 << 23)) == 0)
3405 offset = -offset;
3406 if (s->thumb && rn == 15) {
3407 /* This is actually UNPREDICTABLE */
3408 addr = tcg_temp_new_i32();
3409 tcg_gen_movi_i32(addr, s->pc & ~2);
3410 } else {
3411 addr = load_reg(s, rn);
3413 tcg_gen_addi_i32(addr, addr, offset);
3414 if (insn & (1 << 20)) {
3415 gen_vfp_ld(s, dp, addr);
3416 gen_mov_vreg_F0(dp, rd);
3417 } else {
3418 gen_mov_F0_vreg(dp, rd);
3419 gen_vfp_st(s, dp, addr);
3421 tcg_temp_free_i32(addr);
3422 } else {
3423 /* load/store multiple */
3424 int w = insn & (1 << 21);
3425 if (dp)
3426 n = (insn >> 1) & 0x7f;
3427 else
3428 n = insn & 0xff;
3430 if (w && !(((insn >> 23) ^ (insn >> 24)) & 1)) {
3431 /* P == U , W == 1 => UNDEF */
3432 return 1;
3434 if (n == 0 || (rd + n) > 32 || (dp && n > 16)) {
3435 /* UNPREDICTABLE cases for bad immediates: we choose to
3436 * UNDEF to avoid generating huge numbers of TCG ops
3438 return 1;
3440 if (rn == 15 && w) {
3441 /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
3442 return 1;
3445 if (s->thumb && rn == 15) {
3446 /* This is actually UNPREDICTABLE */
3447 addr = tcg_temp_new_i32();
3448 tcg_gen_movi_i32(addr, s->pc & ~2);
3449 } else {
3450 addr = load_reg(s, rn);
3452 if (insn & (1 << 24)) /* pre-decrement */
3453 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
3455 if (dp)
3456 offset = 8;
3457 else
3458 offset = 4;
3459 for (i = 0; i < n; i++) {
3460 if (insn & ARM_CP_RW_BIT) {
3461 /* load */
3462 gen_vfp_ld(s, dp, addr);
3463 gen_mov_vreg_F0(dp, rd + i);
3464 } else {
3465 /* store */
3466 gen_mov_F0_vreg(dp, rd + i);
3467 gen_vfp_st(s, dp, addr);
3469 tcg_gen_addi_i32(addr, addr, offset);
3471 if (w) {
3472 /* writeback */
3473 if (insn & (1 << 24))
3474 offset = -offset * n;
3475 else if (dp && (insn & 1))
3476 offset = 4;
3477 else
3478 offset = 0;
3480 if (offset != 0)
3481 tcg_gen_addi_i32(addr, addr, offset);
3482 store_reg(s, rn, addr);
3483 } else {
3484 tcg_temp_free_i32(addr);
3488 break;
3489 default:
3490 /* Should never happen. */
3491 return 1;
3493 return 0;
3496 static inline void gen_goto_tb(DisasContext *s, int n, uint32_t dest)
3498 TranslationBlock *tb;
3500 tb = s->tb;
3501 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3502 tcg_gen_goto_tb(n);
3503 gen_set_pc_im(dest);
3504 tcg_gen_exit_tb((tcg_target_long)tb + n);
3505 } else {
3506 gen_set_pc_im(dest);
3507 tcg_gen_exit_tb(0);
3511 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3513 if (unlikely(s->singlestep_enabled)) {
3514 /* An indirect jump so that we still trigger the debug exception. */
3515 if (s->thumb)
3516 dest |= 1;
3517 gen_bx_im(s, dest);
3518 } else {
3519 gen_goto_tb(s, 0, dest);
3520 s->is_jmp = DISAS_TB_JUMP;
3524 static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
3526 if (x)
3527 tcg_gen_sari_i32(t0, t0, 16);
3528 else
3529 gen_sxth(t0);
3530 if (y)
3531 tcg_gen_sari_i32(t1, t1, 16);
3532 else
3533 gen_sxth(t1);
3534 tcg_gen_mul_i32(t0, t0, t1);
3537 /* Return the mask of PSR bits set by a MSR instruction. */
3538 static uint32_t msr_mask(CPUState *env, DisasContext *s, int flags, int spsr) {
3539 uint32_t mask;
3541 mask = 0;
3542 if (flags & (1 << 0))
3543 mask |= 0xff;
3544 if (flags & (1 << 1))
3545 mask |= 0xff00;
3546 if (flags & (1 << 2))
3547 mask |= 0xff0000;
3548 if (flags & (1 << 3))
3549 mask |= 0xff000000;
3551 /* Mask out undefined bits. */
3552 mask &= ~CPSR_RESERVED;
3553 if (!arm_feature(env, ARM_FEATURE_V4T))
3554 mask &= ~CPSR_T;
3555 if (!arm_feature(env, ARM_FEATURE_V5))
3556 mask &= ~CPSR_Q; /* V5TE in reality*/
3557 if (!arm_feature(env, ARM_FEATURE_V6))
3558 mask &= ~(CPSR_E | CPSR_GE);
3559 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3560 mask &= ~CPSR_IT;
3561 /* Mask out execution state bits. */
3562 if (!spsr)
3563 mask &= ~CPSR_EXEC;
3564 /* Mask out privileged bits. */
3565 if (IS_USER(s))
3566 mask &= CPSR_USER;
3567 return mask;
3570 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3571 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv t0)
3573 TCGv tmp;
3574 if (spsr) {
3575 /* ??? This is also undefined in system mode. */
3576 if (IS_USER(s))
3577 return 1;
3579 tmp = load_cpu_field(spsr);
3580 tcg_gen_andi_i32(tmp, tmp, ~mask);
3581 tcg_gen_andi_i32(t0, t0, mask);
3582 tcg_gen_or_i32(tmp, tmp, t0);
3583 store_cpu_field(tmp, spsr);
3584 } else {
3585 gen_set_cpsr(t0, mask);
3587 tcg_temp_free_i32(t0);
3588 gen_lookup_tb(s);
3589 return 0;
3592 /* Returns nonzero if access to the PSR is not permitted. */
3593 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3595 TCGv tmp;
3596 tmp = tcg_temp_new_i32();
3597 tcg_gen_movi_i32(tmp, val);
3598 return gen_set_psr(s, mask, spsr, tmp);
3601 /* Generate an old-style exception return. Marks pc as dead. */
3602 static void gen_exception_return(DisasContext *s, TCGv pc)
3604 TCGv tmp;
3605 store_reg(s, 15, pc);
3606 tmp = load_cpu_field(spsr);
3607 gen_set_cpsr(tmp, 0xffffffff);
3608 tcg_temp_free_i32(tmp);
3609 s->is_jmp = DISAS_UPDATE;
3612 /* Generate a v6 exception return. Marks both values as dead. */
3613 static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr)
3615 gen_set_cpsr(cpsr, 0xffffffff);
3616 tcg_temp_free_i32(cpsr);
3617 store_reg(s, 15, pc);
3618 s->is_jmp = DISAS_UPDATE;
3621 static inline void
3622 gen_set_condexec (DisasContext *s)
3624 if (s->condexec_mask) {
3625 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3626 TCGv tmp = tcg_temp_new_i32();
3627 tcg_gen_movi_i32(tmp, val);
3628 store_cpu_field(tmp, condexec_bits);
3632 static void gen_exception_insn(DisasContext *s, int offset, int excp)
3634 gen_set_condexec(s);
3635 gen_set_pc_im(s->pc - offset);
3636 gen_exception(excp);
3637 s->is_jmp = DISAS_JUMP;
3640 static void gen_nop_hint(DisasContext *s, int val)
3642 switch (val) {
3643 case 3: /* wfi */
3644 gen_set_pc_im(s->pc);
3645 s->is_jmp = DISAS_WFI;
3646 break;
3647 case 2: /* wfe */
3648 case 4: /* sev */
3649 /* TODO: Implement SEV and WFE. May help SMP performance. */
3650 default: /* nop */
3651 break;
3655 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3657 static inline void gen_neon_add(int size, TCGv t0, TCGv t1)
3659 switch (size) {
3660 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
3661 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
3662 case 2: tcg_gen_add_i32(t0, t0, t1); break;
3663 default: abort();
3667 static inline void gen_neon_rsb(int size, TCGv t0, TCGv t1)
3669 switch (size) {
3670 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
3671 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
3672 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
3673 default: return;
3677 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3678 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3679 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3680 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3681 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3683 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3684 switch ((size << 1) | u) { \
3685 case 0: \
3686 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3687 break; \
3688 case 1: \
3689 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3690 break; \
3691 case 2: \
3692 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3693 break; \
3694 case 3: \
3695 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3696 break; \
3697 case 4: \
3698 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3699 break; \
3700 case 5: \
3701 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3702 break; \
3703 default: return 1; \
3704 }} while (0)
3706 #define GEN_NEON_INTEGER_OP(name) do { \
3707 switch ((size << 1) | u) { \
3708 case 0: \
3709 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3710 break; \
3711 case 1: \
3712 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3713 break; \
3714 case 2: \
3715 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3716 break; \
3717 case 3: \
3718 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3719 break; \
3720 case 4: \
3721 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3722 break; \
3723 case 5: \
3724 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3725 break; \
3726 default: return 1; \
3727 }} while (0)
3729 static TCGv neon_load_scratch(int scratch)
3731 TCGv tmp = tcg_temp_new_i32();
3732 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3733 return tmp;
3736 static void neon_store_scratch(int scratch, TCGv var)
3738 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3739 tcg_temp_free_i32(var);
3742 static inline TCGv neon_get_scalar(int size, int reg)
3744 TCGv tmp;
3745 if (size == 1) {
3746 tmp = neon_load_reg(reg & 7, reg >> 4);
3747 if (reg & 8) {
3748 gen_neon_dup_high16(tmp);
3749 } else {
3750 gen_neon_dup_low16(tmp);
3752 } else {
3753 tmp = neon_load_reg(reg & 15, reg >> 4);
3755 return tmp;
3758 static int gen_neon_unzip(int rd, int rm, int size, int q)
3760 TCGv tmp, tmp2;
3761 if (!q && size == 2) {
3762 return 1;
3764 tmp = tcg_const_i32(rd);
3765 tmp2 = tcg_const_i32(rm);
3766 if (q) {
3767 switch (size) {
3768 case 0:
3769 gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
3770 break;
3771 case 1:
3772 gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
3773 break;
3774 case 2:
3775 gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
3776 break;
3777 default:
3778 abort();
3780 } else {
3781 switch (size) {
3782 case 0:
3783 gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
3784 break;
3785 case 1:
3786 gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
3787 break;
3788 default:
3789 abort();
3792 tcg_temp_free_i32(tmp);
3793 tcg_temp_free_i32(tmp2);
3794 return 0;
3797 static int gen_neon_zip(int rd, int rm, int size, int q)
3799 TCGv tmp, tmp2;
3800 if (!q && size == 2) {
3801 return 1;
3803 tmp = tcg_const_i32(rd);
3804 tmp2 = tcg_const_i32(rm);
3805 if (q) {
3806 switch (size) {
3807 case 0:
3808 gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
3809 break;
3810 case 1:
3811 gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
3812 break;
3813 case 2:
3814 gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
3815 break;
3816 default:
3817 abort();
3819 } else {
3820 switch (size) {
3821 case 0:
3822 gen_helper_neon_zip8(cpu_env, tmp, tmp2);
3823 break;
3824 case 1:
3825 gen_helper_neon_zip16(cpu_env, tmp, tmp2);
3826 break;
3827 default:
3828 abort();
3831 tcg_temp_free_i32(tmp);
3832 tcg_temp_free_i32(tmp2);
3833 return 0;
3836 static void gen_neon_trn_u8(TCGv t0, TCGv t1)
3838 TCGv rd, tmp;
3840 rd = tcg_temp_new_i32();
3841 tmp = tcg_temp_new_i32();
3843 tcg_gen_shli_i32(rd, t0, 8);
3844 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3845 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3846 tcg_gen_or_i32(rd, rd, tmp);
3848 tcg_gen_shri_i32(t1, t1, 8);
3849 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3850 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3851 tcg_gen_or_i32(t1, t1, tmp);
3852 tcg_gen_mov_i32(t0, rd);
3854 tcg_temp_free_i32(tmp);
3855 tcg_temp_free_i32(rd);
3858 static void gen_neon_trn_u16(TCGv t0, TCGv t1)
3860 TCGv rd, tmp;
3862 rd = tcg_temp_new_i32();
3863 tmp = tcg_temp_new_i32();
3865 tcg_gen_shli_i32(rd, t0, 16);
3866 tcg_gen_andi_i32(tmp, t1, 0xffff);
3867 tcg_gen_or_i32(rd, rd, tmp);
3868 tcg_gen_shri_i32(t1, t1, 16);
3869 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3870 tcg_gen_or_i32(t1, t1, tmp);
3871 tcg_gen_mov_i32(t0, rd);
3873 tcg_temp_free_i32(tmp);
3874 tcg_temp_free_i32(rd);
3878 static struct {
3879 int nregs;
3880 int interleave;
3881 int spacing;
3882 } neon_ls_element_type[11] = {
3883 {4, 4, 1},
3884 {4, 4, 2},
3885 {4, 1, 1},
3886 {4, 2, 1},
3887 {3, 3, 1},
3888 {3, 3, 2},
3889 {3, 1, 1},
3890 {1, 1, 1},
3891 {2, 2, 1},
3892 {2, 2, 2},
3893 {2, 1, 1}
3896 /* Translate a NEON load/store element instruction. Return nonzero if the
3897 instruction is invalid. */
3898 static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
3900 int rd, rn, rm;
3901 int op;
3902 int nregs;
3903 int interleave;
3904 int spacing;
3905 int stride;
3906 int size;
3907 int reg;
3908 int pass;
3909 int load;
3910 int shift;
3911 int n;
3912 TCGv addr;
3913 TCGv tmp;
3914 TCGv tmp2;
3915 TCGv_i64 tmp64;
3917 if (!s->vfp_enabled)
3918 return 1;
3919 VFP_DREG_D(rd, insn);
3920 rn = (insn >> 16) & 0xf;
3921 rm = insn & 0xf;
3922 load = (insn & (1 << 21)) != 0;
3923 if ((insn & (1 << 23)) == 0) {
3924 /* Load store all elements. */
3925 op = (insn >> 8) & 0xf;
3926 size = (insn >> 6) & 3;
3927 if (op > 10)
3928 return 1;
3929 /* Catch UNDEF cases for bad values of align field */
3930 switch (op & 0xc) {
3931 case 4:
3932 if (((insn >> 5) & 1) == 1) {
3933 return 1;
3935 break;
3936 case 8:
3937 if (((insn >> 4) & 3) == 3) {
3938 return 1;
3940 break;
3941 default:
3942 break;
3944 nregs = neon_ls_element_type[op].nregs;
3945 interleave = neon_ls_element_type[op].interleave;
3946 spacing = neon_ls_element_type[op].spacing;
3947 if (size == 3 && (interleave | spacing) != 1)
3948 return 1;
3949 addr = tcg_temp_new_i32();
3950 load_reg_var(s, addr, rn);
3951 stride = (1 << size) * interleave;
3952 for (reg = 0; reg < nregs; reg++) {
3953 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
3954 load_reg_var(s, addr, rn);
3955 tcg_gen_addi_i32(addr, addr, (1 << size) * reg);
3956 } else if (interleave == 2 && nregs == 4 && reg == 2) {
3957 load_reg_var(s, addr, rn);
3958 tcg_gen_addi_i32(addr, addr, 1 << size);
3960 if (size == 3) {
3961 if (load) {
3962 tmp64 = gen_ld64(addr, IS_USER(s));
3963 neon_store_reg64(tmp64, rd);
3964 tcg_temp_free_i64(tmp64);
3965 } else {
3966 tmp64 = tcg_temp_new_i64();
3967 neon_load_reg64(tmp64, rd);
3968 gen_st64(tmp64, addr, IS_USER(s));
3970 tcg_gen_addi_i32(addr, addr, stride);
3971 } else {
3972 for (pass = 0; pass < 2; pass++) {
3973 if (size == 2) {
3974 if (load) {
3975 tmp = gen_ld32(addr, IS_USER(s));
3976 neon_store_reg(rd, pass, tmp);
3977 } else {
3978 tmp = neon_load_reg(rd, pass);
3979 gen_st32(tmp, addr, IS_USER(s));
3981 tcg_gen_addi_i32(addr, addr, stride);
3982 } else if (size == 1) {
3983 if (load) {
3984 tmp = gen_ld16u(addr, IS_USER(s));
3985 tcg_gen_addi_i32(addr, addr, stride);
3986 tmp2 = gen_ld16u(addr, IS_USER(s));
3987 tcg_gen_addi_i32(addr, addr, stride);
3988 tcg_gen_shli_i32(tmp2, tmp2, 16);
3989 tcg_gen_or_i32(tmp, tmp, tmp2);
3990 tcg_temp_free_i32(tmp2);
3991 neon_store_reg(rd, pass, tmp);
3992 } else {
3993 tmp = neon_load_reg(rd, pass);
3994 tmp2 = tcg_temp_new_i32();
3995 tcg_gen_shri_i32(tmp2, tmp, 16);
3996 gen_st16(tmp, addr, IS_USER(s));
3997 tcg_gen_addi_i32(addr, addr, stride);
3998 gen_st16(tmp2, addr, IS_USER(s));
3999 tcg_gen_addi_i32(addr, addr, stride);
4001 } else /* size == 0 */ {
4002 if (load) {
4003 TCGV_UNUSED(tmp2);
4004 for (n = 0; n < 4; n++) {
4005 tmp = gen_ld8u(addr, IS_USER(s));
4006 tcg_gen_addi_i32(addr, addr, stride);
4007 if (n == 0) {
4008 tmp2 = tmp;
4009 } else {
4010 tcg_gen_shli_i32(tmp, tmp, n * 8);
4011 tcg_gen_or_i32(tmp2, tmp2, tmp);
4012 tcg_temp_free_i32(tmp);
4015 neon_store_reg(rd, pass, tmp2);
4016 } else {
4017 tmp2 = neon_load_reg(rd, pass);
4018 for (n = 0; n < 4; n++) {
4019 tmp = tcg_temp_new_i32();
4020 if (n == 0) {
4021 tcg_gen_mov_i32(tmp, tmp2);
4022 } else {
4023 tcg_gen_shri_i32(tmp, tmp2, n * 8);
4025 gen_st8(tmp, addr, IS_USER(s));
4026 tcg_gen_addi_i32(addr, addr, stride);
4028 tcg_temp_free_i32(tmp2);
4033 rd += spacing;
4035 tcg_temp_free_i32(addr);
4036 stride = nregs * 8;
4037 } else {
4038 size = (insn >> 10) & 3;
4039 if (size == 3) {
4040 /* Load single element to all lanes. */
4041 int a = (insn >> 4) & 1;
4042 if (!load) {
4043 return 1;
4045 size = (insn >> 6) & 3;
4046 nregs = ((insn >> 8) & 3) + 1;
4048 if (size == 3) {
4049 if (nregs != 4 || a == 0) {
4050 return 1;
4052 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
4053 size = 2;
4055 if (nregs == 1 && a == 1 && size == 0) {
4056 return 1;
4058 if (nregs == 3 && a == 1) {
4059 return 1;
4061 addr = tcg_temp_new_i32();
4062 load_reg_var(s, addr, rn);
4063 if (nregs == 1) {
4064 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */
4065 tmp = gen_load_and_replicate(s, addr, size);
4066 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4067 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4068 if (insn & (1 << 5)) {
4069 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 0));
4070 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 1));
4072 tcg_temp_free_i32(tmp);
4073 } else {
4074 /* VLD2/3/4 to all lanes: bit 5 indicates register stride */
4075 stride = (insn & (1 << 5)) ? 2 : 1;
4076 for (reg = 0; reg < nregs; reg++) {
4077 tmp = gen_load_and_replicate(s, addr, size);
4078 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4079 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4080 tcg_temp_free_i32(tmp);
4081 tcg_gen_addi_i32(addr, addr, 1 << size);
4082 rd += stride;
4085 tcg_temp_free_i32(addr);
4086 stride = (1 << size) * nregs;
4087 } else {
4088 /* Single element. */
4089 int idx = (insn >> 4) & 0xf;
4090 pass = (insn >> 7) & 1;
4091 switch (size) {
4092 case 0:
4093 shift = ((insn >> 5) & 3) * 8;
4094 stride = 1;
4095 break;
4096 case 1:
4097 shift = ((insn >> 6) & 1) * 16;
4098 stride = (insn & (1 << 5)) ? 2 : 1;
4099 break;
4100 case 2:
4101 shift = 0;
4102 stride = (insn & (1 << 6)) ? 2 : 1;
4103 break;
4104 default:
4105 abort();
4107 nregs = ((insn >> 8) & 3) + 1;
4108 /* Catch the UNDEF cases. This is unavoidably a bit messy. */
4109 switch (nregs) {
4110 case 1:
4111 if (((idx & (1 << size)) != 0) ||
4112 (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
4113 return 1;
4115 break;
4116 case 3:
4117 if ((idx & 1) != 0) {
4118 return 1;
4120 /* fall through */
4121 case 2:
4122 if (size == 2 && (idx & 2) != 0) {
4123 return 1;
4125 break;
4126 case 4:
4127 if ((size == 2) && ((idx & 3) == 3)) {
4128 return 1;
4130 break;
4131 default:
4132 abort();
4134 if ((rd + stride * (nregs - 1)) > 31) {
4135 /* Attempts to write off the end of the register file
4136 * are UNPREDICTABLE; we choose to UNDEF because otherwise
4137 * the neon_load_reg() would write off the end of the array.
4139 return 1;
4141 addr = tcg_temp_new_i32();
4142 load_reg_var(s, addr, rn);
4143 for (reg = 0; reg < nregs; reg++) {
4144 if (load) {
4145 switch (size) {
4146 case 0:
4147 tmp = gen_ld8u(addr, IS_USER(s));
4148 break;
4149 case 1:
4150 tmp = gen_ld16u(addr, IS_USER(s));
4151 break;
4152 case 2:
4153 tmp = gen_ld32(addr, IS_USER(s));
4154 break;
4155 default: /* Avoid compiler warnings. */
4156 abort();
4158 if (size != 2) {
4159 tmp2 = neon_load_reg(rd, pass);
4160 gen_bfi(tmp, tmp2, tmp, shift, size ? 0xffff : 0xff);
4161 tcg_temp_free_i32(tmp2);
4163 neon_store_reg(rd, pass, tmp);
4164 } else { /* Store */
4165 tmp = neon_load_reg(rd, pass);
4166 if (shift)
4167 tcg_gen_shri_i32(tmp, tmp, shift);
4168 switch (size) {
4169 case 0:
4170 gen_st8(tmp, addr, IS_USER(s));
4171 break;
4172 case 1:
4173 gen_st16(tmp, addr, IS_USER(s));
4174 break;
4175 case 2:
4176 gen_st32(tmp, addr, IS_USER(s));
4177 break;
4180 rd += stride;
4181 tcg_gen_addi_i32(addr, addr, 1 << size);
4183 tcg_temp_free_i32(addr);
4184 stride = nregs * (1 << size);
4187 if (rm != 15) {
4188 TCGv base;
4190 base = load_reg(s, rn);
4191 if (rm == 13) {
4192 tcg_gen_addi_i32(base, base, stride);
4193 } else {
4194 TCGv index;
4195 index = load_reg(s, rm);
4196 tcg_gen_add_i32(base, base, index);
4197 tcg_temp_free_i32(index);
4199 store_reg(s, rn, base);
4201 return 0;
4204 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4205 static void gen_neon_bsl(TCGv dest, TCGv t, TCGv f, TCGv c)
4207 tcg_gen_and_i32(t, t, c);
4208 tcg_gen_andc_i32(f, f, c);
4209 tcg_gen_or_i32(dest, t, f);
4212 static inline void gen_neon_narrow(int size, TCGv dest, TCGv_i64 src)
4214 switch (size) {
4215 case 0: gen_helper_neon_narrow_u8(dest, src); break;
4216 case 1: gen_helper_neon_narrow_u16(dest, src); break;
4217 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
4218 default: abort();
4222 static inline void gen_neon_narrow_sats(int size, TCGv dest, TCGv_i64 src)
4224 switch (size) {
4225 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
4226 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
4227 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
4228 default: abort();
4232 static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
4234 switch (size) {
4235 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
4236 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
4237 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
4238 default: abort();
4242 static inline void gen_neon_unarrow_sats(int size, TCGv dest, TCGv_i64 src)
4244 switch (size) {
4245 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
4246 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
4247 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
4248 default: abort();
4252 static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
4253 int q, int u)
4255 if (q) {
4256 if (u) {
4257 switch (size) {
4258 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4259 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4260 default: abort();
4262 } else {
4263 switch (size) {
4264 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
4265 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
4266 default: abort();
4269 } else {
4270 if (u) {
4271 switch (size) {
4272 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
4273 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
4274 default: abort();
4276 } else {
4277 switch (size) {
4278 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
4279 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
4280 default: abort();
4286 static inline void gen_neon_widen(TCGv_i64 dest, TCGv src, int size, int u)
4288 if (u) {
4289 switch (size) {
4290 case 0: gen_helper_neon_widen_u8(dest, src); break;
4291 case 1: gen_helper_neon_widen_u16(dest, src); break;
4292 case 2: tcg_gen_extu_i32_i64(dest, src); break;
4293 default: abort();
4295 } else {
4296 switch (size) {
4297 case 0: gen_helper_neon_widen_s8(dest, src); break;
4298 case 1: gen_helper_neon_widen_s16(dest, src); break;
4299 case 2: tcg_gen_ext_i32_i64(dest, src); break;
4300 default: abort();
4303 tcg_temp_free_i32(src);
4306 static inline void gen_neon_addl(int size)
4308 switch (size) {
4309 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4310 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4311 case 2: tcg_gen_add_i64(CPU_V001); break;
4312 default: abort();
4316 static inline void gen_neon_subl(int size)
4318 switch (size) {
4319 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4320 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4321 case 2: tcg_gen_sub_i64(CPU_V001); break;
4322 default: abort();
4326 static inline void gen_neon_negl(TCGv_i64 var, int size)
4328 switch (size) {
4329 case 0: gen_helper_neon_negl_u16(var, var); break;
4330 case 1: gen_helper_neon_negl_u32(var, var); break;
4331 case 2: gen_helper_neon_negl_u64(var, var); break;
4332 default: abort();
4336 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4338 switch (size) {
4339 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4340 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4341 default: abort();
4345 static inline void gen_neon_mull(TCGv_i64 dest, TCGv a, TCGv b, int size, int u)
4347 TCGv_i64 tmp;
4349 switch ((size << 1) | u) {
4350 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4351 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4352 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4353 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4354 case 4:
4355 tmp = gen_muls_i64_i32(a, b);
4356 tcg_gen_mov_i64(dest, tmp);
4357 tcg_temp_free_i64(tmp);
4358 break;
4359 case 5:
4360 tmp = gen_mulu_i64_i32(a, b);
4361 tcg_gen_mov_i64(dest, tmp);
4362 tcg_temp_free_i64(tmp);
4363 break;
4364 default: abort();
4367 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
4368 Don't forget to clean them now. */
4369 if (size < 2) {
4370 tcg_temp_free_i32(a);
4371 tcg_temp_free_i32(b);
4375 static void gen_neon_narrow_op(int op, int u, int size, TCGv dest, TCGv_i64 src)
4377 if (op) {
4378 if (u) {
4379 gen_neon_unarrow_sats(size, dest, src);
4380 } else {
4381 gen_neon_narrow(size, dest, src);
4383 } else {
4384 if (u) {
4385 gen_neon_narrow_satu(size, dest, src);
4386 } else {
4387 gen_neon_narrow_sats(size, dest, src);
4392 /* Symbolic constants for op fields for Neon 3-register same-length.
4393 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
4394 * table A7-9.
4396 #define NEON_3R_VHADD 0
4397 #define NEON_3R_VQADD 1
4398 #define NEON_3R_VRHADD 2
4399 #define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
4400 #define NEON_3R_VHSUB 4
4401 #define NEON_3R_VQSUB 5
4402 #define NEON_3R_VCGT 6
4403 #define NEON_3R_VCGE 7
4404 #define NEON_3R_VSHL 8
4405 #define NEON_3R_VQSHL 9
4406 #define NEON_3R_VRSHL 10
4407 #define NEON_3R_VQRSHL 11
4408 #define NEON_3R_VMAX 12
4409 #define NEON_3R_VMIN 13
4410 #define NEON_3R_VABD 14
4411 #define NEON_3R_VABA 15
4412 #define NEON_3R_VADD_VSUB 16
4413 #define NEON_3R_VTST_VCEQ 17
4414 #define NEON_3R_VML 18 /* VMLA, VMLAL, VMLS, VMLSL */
4415 #define NEON_3R_VMUL 19
4416 #define NEON_3R_VPMAX 20
4417 #define NEON_3R_VPMIN 21
4418 #define NEON_3R_VQDMULH_VQRDMULH 22
4419 #define NEON_3R_VPADD 23
4420 #define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
4421 #define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
4422 #define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
4423 #define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
4424 #define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
4425 #define NEON_3R_VRECPS_VRSQRTS 31 /* float VRECPS, VRSQRTS */
4427 static const uint8_t neon_3r_sizes[] = {
4428 [NEON_3R_VHADD] = 0x7,
4429 [NEON_3R_VQADD] = 0xf,
4430 [NEON_3R_VRHADD] = 0x7,
4431 [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
4432 [NEON_3R_VHSUB] = 0x7,
4433 [NEON_3R_VQSUB] = 0xf,
4434 [NEON_3R_VCGT] = 0x7,
4435 [NEON_3R_VCGE] = 0x7,
4436 [NEON_3R_VSHL] = 0xf,
4437 [NEON_3R_VQSHL] = 0xf,
4438 [NEON_3R_VRSHL] = 0xf,
4439 [NEON_3R_VQRSHL] = 0xf,
4440 [NEON_3R_VMAX] = 0x7,
4441 [NEON_3R_VMIN] = 0x7,
4442 [NEON_3R_VABD] = 0x7,
4443 [NEON_3R_VABA] = 0x7,
4444 [NEON_3R_VADD_VSUB] = 0xf,
4445 [NEON_3R_VTST_VCEQ] = 0x7,
4446 [NEON_3R_VML] = 0x7,
4447 [NEON_3R_VMUL] = 0x7,
4448 [NEON_3R_VPMAX] = 0x7,
4449 [NEON_3R_VPMIN] = 0x7,
4450 [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
4451 [NEON_3R_VPADD] = 0x7,
4452 [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
4453 [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
4454 [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
4455 [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
4456 [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
4457 [NEON_3R_VRECPS_VRSQRTS] = 0x5, /* size bit 1 encodes op */
4460 /* Symbolic constants for op fields for Neon 2-register miscellaneous.
4461 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
4462 * table A7-13.
4464 #define NEON_2RM_VREV64 0
4465 #define NEON_2RM_VREV32 1
4466 #define NEON_2RM_VREV16 2
4467 #define NEON_2RM_VPADDL 4
4468 #define NEON_2RM_VPADDL_U 5
4469 #define NEON_2RM_VCLS 8
4470 #define NEON_2RM_VCLZ 9
4471 #define NEON_2RM_VCNT 10
4472 #define NEON_2RM_VMVN 11
4473 #define NEON_2RM_VPADAL 12
4474 #define NEON_2RM_VPADAL_U 13
4475 #define NEON_2RM_VQABS 14
4476 #define NEON_2RM_VQNEG 15
4477 #define NEON_2RM_VCGT0 16
4478 #define NEON_2RM_VCGE0 17
4479 #define NEON_2RM_VCEQ0 18
4480 #define NEON_2RM_VCLE0 19
4481 #define NEON_2RM_VCLT0 20
4482 #define NEON_2RM_VABS 22
4483 #define NEON_2RM_VNEG 23
4484 #define NEON_2RM_VCGT0_F 24
4485 #define NEON_2RM_VCGE0_F 25
4486 #define NEON_2RM_VCEQ0_F 26
4487 #define NEON_2RM_VCLE0_F 27
4488 #define NEON_2RM_VCLT0_F 28
4489 #define NEON_2RM_VABS_F 30
4490 #define NEON_2RM_VNEG_F 31
4491 #define NEON_2RM_VSWP 32
4492 #define NEON_2RM_VTRN 33
4493 #define NEON_2RM_VUZP 34
4494 #define NEON_2RM_VZIP 35
4495 #define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
4496 #define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
4497 #define NEON_2RM_VSHLL 38
4498 #define NEON_2RM_VCVT_F16_F32 44
4499 #define NEON_2RM_VCVT_F32_F16 46
4500 #define NEON_2RM_VRECPE 56
4501 #define NEON_2RM_VRSQRTE 57
4502 #define NEON_2RM_VRECPE_F 58
4503 #define NEON_2RM_VRSQRTE_F 59
4504 #define NEON_2RM_VCVT_FS 60
4505 #define NEON_2RM_VCVT_FU 61
4506 #define NEON_2RM_VCVT_SF 62
4507 #define NEON_2RM_VCVT_UF 63
4509 static int neon_2rm_is_float_op(int op)
4511 /* Return true if this neon 2reg-misc op is float-to-float */
4512 return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
4513 op >= NEON_2RM_VRECPE_F);
4516 /* Each entry in this array has bit n set if the insn allows
4517 * size value n (otherwise it will UNDEF). Since unallocated
4518 * op values will have no bits set they always UNDEF.
4520 static const uint8_t neon_2rm_sizes[] = {
4521 [NEON_2RM_VREV64] = 0x7,
4522 [NEON_2RM_VREV32] = 0x3,
4523 [NEON_2RM_VREV16] = 0x1,
4524 [NEON_2RM_VPADDL] = 0x7,
4525 [NEON_2RM_VPADDL_U] = 0x7,
4526 [NEON_2RM_VCLS] = 0x7,
4527 [NEON_2RM_VCLZ] = 0x7,
4528 [NEON_2RM_VCNT] = 0x1,
4529 [NEON_2RM_VMVN] = 0x1,
4530 [NEON_2RM_VPADAL] = 0x7,
4531 [NEON_2RM_VPADAL_U] = 0x7,
4532 [NEON_2RM_VQABS] = 0x7,
4533 [NEON_2RM_VQNEG] = 0x7,
4534 [NEON_2RM_VCGT0] = 0x7,
4535 [NEON_2RM_VCGE0] = 0x7,
4536 [NEON_2RM_VCEQ0] = 0x7,
4537 [NEON_2RM_VCLE0] = 0x7,
4538 [NEON_2RM_VCLT0] = 0x7,
4539 [NEON_2RM_VABS] = 0x7,
4540 [NEON_2RM_VNEG] = 0x7,
4541 [NEON_2RM_VCGT0_F] = 0x4,
4542 [NEON_2RM_VCGE0_F] = 0x4,
4543 [NEON_2RM_VCEQ0_F] = 0x4,
4544 [NEON_2RM_VCLE0_F] = 0x4,
4545 [NEON_2RM_VCLT0_F] = 0x4,
4546 [NEON_2RM_VABS_F] = 0x4,
4547 [NEON_2RM_VNEG_F] = 0x4,
4548 [NEON_2RM_VSWP] = 0x1,
4549 [NEON_2RM_VTRN] = 0x7,
4550 [NEON_2RM_VUZP] = 0x7,
4551 [NEON_2RM_VZIP] = 0x7,
4552 [NEON_2RM_VMOVN] = 0x7,
4553 [NEON_2RM_VQMOVN] = 0x7,
4554 [NEON_2RM_VSHLL] = 0x7,
4555 [NEON_2RM_VCVT_F16_F32] = 0x2,
4556 [NEON_2RM_VCVT_F32_F16] = 0x2,
4557 [NEON_2RM_VRECPE] = 0x4,
4558 [NEON_2RM_VRSQRTE] = 0x4,
4559 [NEON_2RM_VRECPE_F] = 0x4,
4560 [NEON_2RM_VRSQRTE_F] = 0x4,
4561 [NEON_2RM_VCVT_FS] = 0x4,
4562 [NEON_2RM_VCVT_FU] = 0x4,
4563 [NEON_2RM_VCVT_SF] = 0x4,
4564 [NEON_2RM_VCVT_UF] = 0x4,
4567 /* Translate a NEON data processing instruction. Return nonzero if the
4568 instruction is invalid.
4569 We process data in a mixture of 32-bit and 64-bit chunks.
4570 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4572 static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
4574 int op;
4575 int q;
4576 int rd, rn, rm;
4577 int size;
4578 int shift;
4579 int pass;
4580 int count;
4581 int pairwise;
4582 int u;
4583 uint32_t imm, mask;
4584 TCGv tmp, tmp2, tmp3, tmp4, tmp5;
4585 TCGv_i64 tmp64;
4587 if (!s->vfp_enabled)
4588 return 1;
4589 q = (insn & (1 << 6)) != 0;
4590 u = (insn >> 24) & 1;
4591 VFP_DREG_D(rd, insn);
4592 VFP_DREG_N(rn, insn);
4593 VFP_DREG_M(rm, insn);
4594 size = (insn >> 20) & 3;
4595 if ((insn & (1 << 23)) == 0) {
4596 /* Three register same length. */
4597 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4598 /* Catch invalid op and bad size combinations: UNDEF */
4599 if ((neon_3r_sizes[op] & (1 << size)) == 0) {
4600 return 1;
4602 /* All insns of this form UNDEF for either this condition or the
4603 * superset of cases "Q==1"; we catch the latter later.
4605 if (q && ((rd | rn | rm) & 1)) {
4606 return 1;
4608 if (size == 3 && op != NEON_3R_LOGIC) {
4609 /* 64-bit element instructions. */
4610 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4611 neon_load_reg64(cpu_V0, rn + pass);
4612 neon_load_reg64(cpu_V1, rm + pass);
4613 switch (op) {
4614 case NEON_3R_VQADD:
4615 if (u) {
4616 gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
4617 cpu_V0, cpu_V1);
4618 } else {
4619 gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
4620 cpu_V0, cpu_V1);
4622 break;
4623 case NEON_3R_VQSUB:
4624 if (u) {
4625 gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
4626 cpu_V0, cpu_V1);
4627 } else {
4628 gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
4629 cpu_V0, cpu_V1);
4631 break;
4632 case NEON_3R_VSHL:
4633 if (u) {
4634 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4635 } else {
4636 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4638 break;
4639 case NEON_3R_VQSHL:
4640 if (u) {
4641 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4642 cpu_V1, cpu_V0);
4643 } else {
4644 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
4645 cpu_V1, cpu_V0);
4647 break;
4648 case NEON_3R_VRSHL:
4649 if (u) {
4650 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4651 } else {
4652 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4654 break;
4655 case NEON_3R_VQRSHL:
4656 if (u) {
4657 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4658 cpu_V1, cpu_V0);
4659 } else {
4660 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4661 cpu_V1, cpu_V0);
4663 break;
4664 case NEON_3R_VADD_VSUB:
4665 if (u) {
4666 tcg_gen_sub_i64(CPU_V001);
4667 } else {
4668 tcg_gen_add_i64(CPU_V001);
4670 break;
4671 default:
4672 abort();
4674 neon_store_reg64(cpu_V0, rd + pass);
4676 return 0;
4678 pairwise = 0;
4679 switch (op) {
4680 case NEON_3R_VSHL:
4681 case NEON_3R_VQSHL:
4682 case NEON_3R_VRSHL:
4683 case NEON_3R_VQRSHL:
4685 int rtmp;
4686 /* Shift instruction operands are reversed. */
4687 rtmp = rn;
4688 rn = rm;
4689 rm = rtmp;
4691 break;
4692 case NEON_3R_VPADD:
4693 if (u) {
4694 return 1;
4696 /* Fall through */
4697 case NEON_3R_VPMAX:
4698 case NEON_3R_VPMIN:
4699 pairwise = 1;
4700 break;
4701 case NEON_3R_FLOAT_ARITH:
4702 pairwise = (u && size < 2); /* if VPADD (float) */
4703 break;
4704 case NEON_3R_FLOAT_MINMAX:
4705 pairwise = u; /* if VPMIN/VPMAX (float) */
4706 break;
4707 case NEON_3R_FLOAT_CMP:
4708 if (!u && size) {
4709 /* no encoding for U=0 C=1x */
4710 return 1;
4712 break;
4713 case NEON_3R_FLOAT_ACMP:
4714 if (!u) {
4715 return 1;
4717 break;
4718 case NEON_3R_VRECPS_VRSQRTS:
4719 if (u) {
4720 return 1;
4722 break;
4723 case NEON_3R_VMUL:
4724 if (u && (size != 0)) {
4725 /* UNDEF on invalid size for polynomial subcase */
4726 return 1;
4728 break;
4729 default:
4730 break;
4733 if (pairwise && q) {
4734 /* All the pairwise insns UNDEF if Q is set */
4735 return 1;
4738 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4740 if (pairwise) {
4741 /* Pairwise. */
4742 if (pass < 1) {
4743 tmp = neon_load_reg(rn, 0);
4744 tmp2 = neon_load_reg(rn, 1);
4745 } else {
4746 tmp = neon_load_reg(rm, 0);
4747 tmp2 = neon_load_reg(rm, 1);
4749 } else {
4750 /* Elementwise. */
4751 tmp = neon_load_reg(rn, pass);
4752 tmp2 = neon_load_reg(rm, pass);
4754 switch (op) {
4755 case NEON_3R_VHADD:
4756 GEN_NEON_INTEGER_OP(hadd);
4757 break;
4758 case NEON_3R_VQADD:
4759 GEN_NEON_INTEGER_OP_ENV(qadd);
4760 break;
4761 case NEON_3R_VRHADD:
4762 GEN_NEON_INTEGER_OP(rhadd);
4763 break;
4764 case NEON_3R_LOGIC: /* Logic ops. */
4765 switch ((u << 2) | size) {
4766 case 0: /* VAND */
4767 tcg_gen_and_i32(tmp, tmp, tmp2);
4768 break;
4769 case 1: /* BIC */
4770 tcg_gen_andc_i32(tmp, tmp, tmp2);
4771 break;
4772 case 2: /* VORR */
4773 tcg_gen_or_i32(tmp, tmp, tmp2);
4774 break;
4775 case 3: /* VORN */
4776 tcg_gen_orc_i32(tmp, tmp, tmp2);
4777 break;
4778 case 4: /* VEOR */
4779 tcg_gen_xor_i32(tmp, tmp, tmp2);
4780 break;
4781 case 5: /* VBSL */
4782 tmp3 = neon_load_reg(rd, pass);
4783 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
4784 tcg_temp_free_i32(tmp3);
4785 break;
4786 case 6: /* VBIT */
4787 tmp3 = neon_load_reg(rd, pass);
4788 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
4789 tcg_temp_free_i32(tmp3);
4790 break;
4791 case 7: /* VBIF */
4792 tmp3 = neon_load_reg(rd, pass);
4793 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
4794 tcg_temp_free_i32(tmp3);
4795 break;
4797 break;
4798 case NEON_3R_VHSUB:
4799 GEN_NEON_INTEGER_OP(hsub);
4800 break;
4801 case NEON_3R_VQSUB:
4802 GEN_NEON_INTEGER_OP_ENV(qsub);
4803 break;
4804 case NEON_3R_VCGT:
4805 GEN_NEON_INTEGER_OP(cgt);
4806 break;
4807 case NEON_3R_VCGE:
4808 GEN_NEON_INTEGER_OP(cge);
4809 break;
4810 case NEON_3R_VSHL:
4811 GEN_NEON_INTEGER_OP(shl);
4812 break;
4813 case NEON_3R_VQSHL:
4814 GEN_NEON_INTEGER_OP_ENV(qshl);
4815 break;
4816 case NEON_3R_VRSHL:
4817 GEN_NEON_INTEGER_OP(rshl);
4818 break;
4819 case NEON_3R_VQRSHL:
4820 GEN_NEON_INTEGER_OP_ENV(qrshl);
4821 break;
4822 case NEON_3R_VMAX:
4823 GEN_NEON_INTEGER_OP(max);
4824 break;
4825 case NEON_3R_VMIN:
4826 GEN_NEON_INTEGER_OP(min);
4827 break;
4828 case NEON_3R_VABD:
4829 GEN_NEON_INTEGER_OP(abd);
4830 break;
4831 case NEON_3R_VABA:
4832 GEN_NEON_INTEGER_OP(abd);
4833 tcg_temp_free_i32(tmp2);
4834 tmp2 = neon_load_reg(rd, pass);
4835 gen_neon_add(size, tmp, tmp2);
4836 break;
4837 case NEON_3R_VADD_VSUB:
4838 if (!u) { /* VADD */
4839 gen_neon_add(size, tmp, tmp2);
4840 } else { /* VSUB */
4841 switch (size) {
4842 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
4843 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
4844 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
4845 default: abort();
4848 break;
4849 case NEON_3R_VTST_VCEQ:
4850 if (!u) { /* VTST */
4851 switch (size) {
4852 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
4853 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
4854 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
4855 default: abort();
4857 } else { /* VCEQ */
4858 switch (size) {
4859 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
4860 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
4861 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
4862 default: abort();
4865 break;
4866 case NEON_3R_VML: /* VMLA, VMLAL, VMLS,VMLSL */
4867 switch (size) {
4868 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4869 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4870 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4871 default: abort();
4873 tcg_temp_free_i32(tmp2);
4874 tmp2 = neon_load_reg(rd, pass);
4875 if (u) { /* VMLS */
4876 gen_neon_rsb(size, tmp, tmp2);
4877 } else { /* VMLA */
4878 gen_neon_add(size, tmp, tmp2);
4880 break;
4881 case NEON_3R_VMUL:
4882 if (u) { /* polynomial */
4883 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
4884 } else { /* Integer */
4885 switch (size) {
4886 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4887 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4888 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4889 default: abort();
4892 break;
4893 case NEON_3R_VPMAX:
4894 GEN_NEON_INTEGER_OP(pmax);
4895 break;
4896 case NEON_3R_VPMIN:
4897 GEN_NEON_INTEGER_OP(pmin);
4898 break;
4899 case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
4900 if (!u) { /* VQDMULH */
4901 switch (size) {
4902 case 1:
4903 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
4904 break;
4905 case 2:
4906 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
4907 break;
4908 default: abort();
4910 } else { /* VQRDMULH */
4911 switch (size) {
4912 case 1:
4913 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
4914 break;
4915 case 2:
4916 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
4917 break;
4918 default: abort();
4921 break;
4922 case NEON_3R_VPADD:
4923 switch (size) {
4924 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
4925 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
4926 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
4927 default: abort();
4929 break;
4930 case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
4932 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
4933 switch ((u << 2) | size) {
4934 case 0: /* VADD */
4935 case 4: /* VPADD */
4936 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
4937 break;
4938 case 2: /* VSUB */
4939 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
4940 break;
4941 case 6: /* VABD */
4942 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
4943 break;
4944 default:
4945 abort();
4947 tcg_temp_free_ptr(fpstatus);
4948 break;
4950 case NEON_3R_FLOAT_MULTIPLY:
4952 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
4953 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
4954 if (!u) {
4955 tcg_temp_free_i32(tmp2);
4956 tmp2 = neon_load_reg(rd, pass);
4957 if (size == 0) {
4958 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
4959 } else {
4960 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
4963 tcg_temp_free_ptr(fpstatus);
4964 break;
4966 case NEON_3R_FLOAT_CMP:
4968 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
4969 if (!u) {
4970 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
4971 } else {
4972 if (size == 0) {
4973 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
4974 } else {
4975 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
4978 tcg_temp_free_ptr(fpstatus);
4979 break;
4981 case NEON_3R_FLOAT_ACMP:
4983 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
4984 if (size == 0) {
4985 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
4986 } else {
4987 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
4989 tcg_temp_free_ptr(fpstatus);
4990 break;
4992 case NEON_3R_FLOAT_MINMAX:
4994 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
4995 if (size == 0) {
4996 gen_helper_neon_max_f32(tmp, tmp, tmp2, fpstatus);
4997 } else {
4998 gen_helper_neon_min_f32(tmp, tmp, tmp2, fpstatus);
5000 tcg_temp_free_ptr(fpstatus);
5001 break;
5003 case NEON_3R_VRECPS_VRSQRTS:
5004 if (size == 0)
5005 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
5006 else
5007 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
5008 break;
5009 default:
5010 abort();
5012 tcg_temp_free_i32(tmp2);
5014 /* Save the result. For elementwise operations we can put it
5015 straight into the destination register. For pairwise operations
5016 we have to be careful to avoid clobbering the source operands. */
5017 if (pairwise && rd == rm) {
5018 neon_store_scratch(pass, tmp);
5019 } else {
5020 neon_store_reg(rd, pass, tmp);
5023 } /* for pass */
5024 if (pairwise && rd == rm) {
5025 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5026 tmp = neon_load_scratch(pass);
5027 neon_store_reg(rd, pass, tmp);
5030 /* End of 3 register same size operations. */
5031 } else if (insn & (1 << 4)) {
5032 if ((insn & 0x00380080) != 0) {
5033 /* Two registers and shift. */
5034 op = (insn >> 8) & 0xf;
5035 if (insn & (1 << 7)) {
5036 /* 64-bit shift. */
5037 if (op > 7) {
5038 return 1;
5040 size = 3;
5041 } else {
5042 size = 2;
5043 while ((insn & (1 << (size + 19))) == 0)
5044 size--;
5046 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
5047 /* To avoid excessive dumplication of ops we implement shift
5048 by immediate using the variable shift operations. */
5049 if (op < 8) {
5050 /* Shift by immediate:
5051 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
5052 if (q && ((rd | rm) & 1)) {
5053 return 1;
5055 if (!u && (op == 4 || op == 6)) {
5056 return 1;
5058 /* Right shifts are encoded as N - shift, where N is the
5059 element size in bits. */
5060 if (op <= 4)
5061 shift = shift - (1 << (size + 3));
5062 if (size == 3) {
5063 count = q + 1;
5064 } else {
5065 count = q ? 4: 2;
5067 switch (size) {
5068 case 0:
5069 imm = (uint8_t) shift;
5070 imm |= imm << 8;
5071 imm |= imm << 16;
5072 break;
5073 case 1:
5074 imm = (uint16_t) shift;
5075 imm |= imm << 16;
5076 break;
5077 case 2:
5078 case 3:
5079 imm = shift;
5080 break;
5081 default:
5082 abort();
5085 for (pass = 0; pass < count; pass++) {
5086 if (size == 3) {
5087 neon_load_reg64(cpu_V0, rm + pass);
5088 tcg_gen_movi_i64(cpu_V1, imm);
5089 switch (op) {
5090 case 0: /* VSHR */
5091 case 1: /* VSRA */
5092 if (u)
5093 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
5094 else
5095 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
5096 break;
5097 case 2: /* VRSHR */
5098 case 3: /* VRSRA */
5099 if (u)
5100 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
5101 else
5102 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
5103 break;
5104 case 4: /* VSRI */
5105 case 5: /* VSHL, VSLI */
5106 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
5107 break;
5108 case 6: /* VQSHLU */
5109 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
5110 cpu_V0, cpu_V1);
5111 break;
5112 case 7: /* VQSHL */
5113 if (u) {
5114 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
5115 cpu_V0, cpu_V1);
5116 } else {
5117 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
5118 cpu_V0, cpu_V1);
5120 break;
5122 if (op == 1 || op == 3) {
5123 /* Accumulate. */
5124 neon_load_reg64(cpu_V1, rd + pass);
5125 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
5126 } else if (op == 4 || (op == 5 && u)) {
5127 /* Insert */
5128 neon_load_reg64(cpu_V1, rd + pass);
5129 uint64_t mask;
5130 if (shift < -63 || shift > 63) {
5131 mask = 0;
5132 } else {
5133 if (op == 4) {
5134 mask = 0xffffffffffffffffull >> -shift;
5135 } else {
5136 mask = 0xffffffffffffffffull << shift;
5139 tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask);
5140 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5142 neon_store_reg64(cpu_V0, rd + pass);
5143 } else { /* size < 3 */
5144 /* Operands in T0 and T1. */
5145 tmp = neon_load_reg(rm, pass);
5146 tmp2 = tcg_temp_new_i32();
5147 tcg_gen_movi_i32(tmp2, imm);
5148 switch (op) {
5149 case 0: /* VSHR */
5150 case 1: /* VSRA */
5151 GEN_NEON_INTEGER_OP(shl);
5152 break;
5153 case 2: /* VRSHR */
5154 case 3: /* VRSRA */
5155 GEN_NEON_INTEGER_OP(rshl);
5156 break;
5157 case 4: /* VSRI */
5158 case 5: /* VSHL, VSLI */
5159 switch (size) {
5160 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
5161 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
5162 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
5163 default: abort();
5165 break;
5166 case 6: /* VQSHLU */
5167 switch (size) {
5168 case 0:
5169 gen_helper_neon_qshlu_s8(tmp, cpu_env,
5170 tmp, tmp2);
5171 break;
5172 case 1:
5173 gen_helper_neon_qshlu_s16(tmp, cpu_env,
5174 tmp, tmp2);
5175 break;
5176 case 2:
5177 gen_helper_neon_qshlu_s32(tmp, cpu_env,
5178 tmp, tmp2);
5179 break;
5180 default:
5181 abort();
5183 break;
5184 case 7: /* VQSHL */
5185 GEN_NEON_INTEGER_OP_ENV(qshl);
5186 break;
5188 tcg_temp_free_i32(tmp2);
5190 if (op == 1 || op == 3) {
5191 /* Accumulate. */
5192 tmp2 = neon_load_reg(rd, pass);
5193 gen_neon_add(size, tmp, tmp2);
5194 tcg_temp_free_i32(tmp2);
5195 } else if (op == 4 || (op == 5 && u)) {
5196 /* Insert */
5197 switch (size) {
5198 case 0:
5199 if (op == 4)
5200 mask = 0xff >> -shift;
5201 else
5202 mask = (uint8_t)(0xff << shift);
5203 mask |= mask << 8;
5204 mask |= mask << 16;
5205 break;
5206 case 1:
5207 if (op == 4)
5208 mask = 0xffff >> -shift;
5209 else
5210 mask = (uint16_t)(0xffff << shift);
5211 mask |= mask << 16;
5212 break;
5213 case 2:
5214 if (shift < -31 || shift > 31) {
5215 mask = 0;
5216 } else {
5217 if (op == 4)
5218 mask = 0xffffffffu >> -shift;
5219 else
5220 mask = 0xffffffffu << shift;
5222 break;
5223 default:
5224 abort();
5226 tmp2 = neon_load_reg(rd, pass);
5227 tcg_gen_andi_i32(tmp, tmp, mask);
5228 tcg_gen_andi_i32(tmp2, tmp2, ~mask);
5229 tcg_gen_or_i32(tmp, tmp, tmp2);
5230 tcg_temp_free_i32(tmp2);
5232 neon_store_reg(rd, pass, tmp);
5234 } /* for pass */
5235 } else if (op < 10) {
5236 /* Shift by immediate and narrow:
5237 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
5238 int input_unsigned = (op == 8) ? !u : u;
5239 if (rm & 1) {
5240 return 1;
5242 shift = shift - (1 << (size + 3));
5243 size++;
5244 if (size == 3) {
5245 tmp64 = tcg_const_i64(shift);
5246 neon_load_reg64(cpu_V0, rm);
5247 neon_load_reg64(cpu_V1, rm + 1);
5248 for (pass = 0; pass < 2; pass++) {
5249 TCGv_i64 in;
5250 if (pass == 0) {
5251 in = cpu_V0;
5252 } else {
5253 in = cpu_V1;
5255 if (q) {
5256 if (input_unsigned) {
5257 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
5258 } else {
5259 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
5261 } else {
5262 if (input_unsigned) {
5263 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
5264 } else {
5265 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
5268 tmp = tcg_temp_new_i32();
5269 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5270 neon_store_reg(rd, pass, tmp);
5271 } /* for pass */
5272 tcg_temp_free_i64(tmp64);
5273 } else {
5274 if (size == 1) {
5275 imm = (uint16_t)shift;
5276 imm |= imm << 16;
5277 } else {
5278 /* size == 2 */
5279 imm = (uint32_t)shift;
5281 tmp2 = tcg_const_i32(imm);
5282 tmp4 = neon_load_reg(rm + 1, 0);
5283 tmp5 = neon_load_reg(rm + 1, 1);
5284 for (pass = 0; pass < 2; pass++) {
5285 if (pass == 0) {
5286 tmp = neon_load_reg(rm, 0);
5287 } else {
5288 tmp = tmp4;
5290 gen_neon_shift_narrow(size, tmp, tmp2, q,
5291 input_unsigned);
5292 if (pass == 0) {
5293 tmp3 = neon_load_reg(rm, 1);
5294 } else {
5295 tmp3 = tmp5;
5297 gen_neon_shift_narrow(size, tmp3, tmp2, q,
5298 input_unsigned);
5299 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
5300 tcg_temp_free_i32(tmp);
5301 tcg_temp_free_i32(tmp3);
5302 tmp = tcg_temp_new_i32();
5303 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5304 neon_store_reg(rd, pass, tmp);
5305 } /* for pass */
5306 tcg_temp_free_i32(tmp2);
5308 } else if (op == 10) {
5309 /* VSHLL, VMOVL */
5310 if (q || (rd & 1)) {
5311 return 1;
5313 tmp = neon_load_reg(rm, 0);
5314 tmp2 = neon_load_reg(rm, 1);
5315 for (pass = 0; pass < 2; pass++) {
5316 if (pass == 1)
5317 tmp = tmp2;
5319 gen_neon_widen(cpu_V0, tmp, size, u);
5321 if (shift != 0) {
5322 /* The shift is less than the width of the source
5323 type, so we can just shift the whole register. */
5324 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
5325 /* Widen the result of shift: we need to clear
5326 * the potential overflow bits resulting from
5327 * left bits of the narrow input appearing as
5328 * right bits of left the neighbour narrow
5329 * input. */
5330 if (size < 2 || !u) {
5331 uint64_t imm64;
5332 if (size == 0) {
5333 imm = (0xffu >> (8 - shift));
5334 imm |= imm << 16;
5335 } else if (size == 1) {
5336 imm = 0xffff >> (16 - shift);
5337 } else {
5338 /* size == 2 */
5339 imm = 0xffffffff >> (32 - shift);
5341 if (size < 2) {
5342 imm64 = imm | (((uint64_t)imm) << 32);
5343 } else {
5344 imm64 = imm;
5346 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
5349 neon_store_reg64(cpu_V0, rd + pass);
5351 } else if (op >= 14) {
5352 /* VCVT fixed-point. */
5353 if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
5354 return 1;
5356 /* We have already masked out the must-be-1 top bit of imm6,
5357 * hence this 32-shift where the ARM ARM has 64-imm6.
5359 shift = 32 - shift;
5360 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5361 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
5362 if (!(op & 1)) {
5363 if (u)
5364 gen_vfp_ulto(0, shift, 1);
5365 else
5366 gen_vfp_slto(0, shift, 1);
5367 } else {
5368 if (u)
5369 gen_vfp_toul(0, shift, 1);
5370 else
5371 gen_vfp_tosl(0, shift, 1);
5373 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
5375 } else {
5376 return 1;
5378 } else { /* (insn & 0x00380080) == 0 */
5379 int invert;
5380 if (q && (rd & 1)) {
5381 return 1;
5384 op = (insn >> 8) & 0xf;
5385 /* One register and immediate. */
5386 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
5387 invert = (insn & (1 << 5)) != 0;
5388 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
5389 * We choose to not special-case this and will behave as if a
5390 * valid constant encoding of 0 had been given.
5392 switch (op) {
5393 case 0: case 1:
5394 /* no-op */
5395 break;
5396 case 2: case 3:
5397 imm <<= 8;
5398 break;
5399 case 4: case 5:
5400 imm <<= 16;
5401 break;
5402 case 6: case 7:
5403 imm <<= 24;
5404 break;
5405 case 8: case 9:
5406 imm |= imm << 16;
5407 break;
5408 case 10: case 11:
5409 imm = (imm << 8) | (imm << 24);
5410 break;
5411 case 12:
5412 imm = (imm << 8) | 0xff;
5413 break;
5414 case 13:
5415 imm = (imm << 16) | 0xffff;
5416 break;
5417 case 14:
5418 imm |= (imm << 8) | (imm << 16) | (imm << 24);
5419 if (invert)
5420 imm = ~imm;
5421 break;
5422 case 15:
5423 if (invert) {
5424 return 1;
5426 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
5427 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
5428 break;
5430 if (invert)
5431 imm = ~imm;
5433 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5434 if (op & 1 && op < 12) {
5435 tmp = neon_load_reg(rd, pass);
5436 if (invert) {
5437 /* The immediate value has already been inverted, so
5438 BIC becomes AND. */
5439 tcg_gen_andi_i32(tmp, tmp, imm);
5440 } else {
5441 tcg_gen_ori_i32(tmp, tmp, imm);
5443 } else {
5444 /* VMOV, VMVN. */
5445 tmp = tcg_temp_new_i32();
5446 if (op == 14 && invert) {
5447 int n;
5448 uint32_t val;
5449 val = 0;
5450 for (n = 0; n < 4; n++) {
5451 if (imm & (1 << (n + (pass & 1) * 4)))
5452 val |= 0xff << (n * 8);
5454 tcg_gen_movi_i32(tmp, val);
5455 } else {
5456 tcg_gen_movi_i32(tmp, imm);
5459 neon_store_reg(rd, pass, tmp);
5462 } else { /* (insn & 0x00800010 == 0x00800000) */
5463 if (size != 3) {
5464 op = (insn >> 8) & 0xf;
5465 if ((insn & (1 << 6)) == 0) {
5466 /* Three registers of different lengths. */
5467 int src1_wide;
5468 int src2_wide;
5469 int prewiden;
5470 /* undefreq: bit 0 : UNDEF if size != 0
5471 * bit 1 : UNDEF if size == 0
5472 * bit 2 : UNDEF if U == 1
5473 * Note that [1:0] set implies 'always UNDEF'
5475 int undefreq;
5476 /* prewiden, src1_wide, src2_wide, undefreq */
5477 static const int neon_3reg_wide[16][4] = {
5478 {1, 0, 0, 0}, /* VADDL */
5479 {1, 1, 0, 0}, /* VADDW */
5480 {1, 0, 0, 0}, /* VSUBL */
5481 {1, 1, 0, 0}, /* VSUBW */
5482 {0, 1, 1, 0}, /* VADDHN */
5483 {0, 0, 0, 0}, /* VABAL */
5484 {0, 1, 1, 0}, /* VSUBHN */
5485 {0, 0, 0, 0}, /* VABDL */
5486 {0, 0, 0, 0}, /* VMLAL */
5487 {0, 0, 0, 6}, /* VQDMLAL */
5488 {0, 0, 0, 0}, /* VMLSL */
5489 {0, 0, 0, 6}, /* VQDMLSL */
5490 {0, 0, 0, 0}, /* Integer VMULL */
5491 {0, 0, 0, 2}, /* VQDMULL */
5492 {0, 0, 0, 5}, /* Polynomial VMULL */
5493 {0, 0, 0, 3}, /* Reserved: always UNDEF */
5496 prewiden = neon_3reg_wide[op][0];
5497 src1_wide = neon_3reg_wide[op][1];
5498 src2_wide = neon_3reg_wide[op][2];
5499 undefreq = neon_3reg_wide[op][3];
5501 if (((undefreq & 1) && (size != 0)) ||
5502 ((undefreq & 2) && (size == 0)) ||
5503 ((undefreq & 4) && u)) {
5504 return 1;
5506 if ((src1_wide && (rn & 1)) ||
5507 (src2_wide && (rm & 1)) ||
5508 (!src2_wide && (rd & 1))) {
5509 return 1;
5512 /* Avoid overlapping operands. Wide source operands are
5513 always aligned so will never overlap with wide
5514 destinations in problematic ways. */
5515 if (rd == rm && !src2_wide) {
5516 tmp = neon_load_reg(rm, 1);
5517 neon_store_scratch(2, tmp);
5518 } else if (rd == rn && !src1_wide) {
5519 tmp = neon_load_reg(rn, 1);
5520 neon_store_scratch(2, tmp);
5522 TCGV_UNUSED(tmp3);
5523 for (pass = 0; pass < 2; pass++) {
5524 if (src1_wide) {
5525 neon_load_reg64(cpu_V0, rn + pass);
5526 TCGV_UNUSED(tmp);
5527 } else {
5528 if (pass == 1 && rd == rn) {
5529 tmp = neon_load_scratch(2);
5530 } else {
5531 tmp = neon_load_reg(rn, pass);
5533 if (prewiden) {
5534 gen_neon_widen(cpu_V0, tmp, size, u);
5537 if (src2_wide) {
5538 neon_load_reg64(cpu_V1, rm + pass);
5539 TCGV_UNUSED(tmp2);
5540 } else {
5541 if (pass == 1 && rd == rm) {
5542 tmp2 = neon_load_scratch(2);
5543 } else {
5544 tmp2 = neon_load_reg(rm, pass);
5546 if (prewiden) {
5547 gen_neon_widen(cpu_V1, tmp2, size, u);
5550 switch (op) {
5551 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5552 gen_neon_addl(size);
5553 break;
5554 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
5555 gen_neon_subl(size);
5556 break;
5557 case 5: case 7: /* VABAL, VABDL */
5558 switch ((size << 1) | u) {
5559 case 0:
5560 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
5561 break;
5562 case 1:
5563 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
5564 break;
5565 case 2:
5566 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
5567 break;
5568 case 3:
5569 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
5570 break;
5571 case 4:
5572 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
5573 break;
5574 case 5:
5575 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
5576 break;
5577 default: abort();
5579 tcg_temp_free_i32(tmp2);
5580 tcg_temp_free_i32(tmp);
5581 break;
5582 case 8: case 9: case 10: case 11: case 12: case 13:
5583 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5584 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5585 break;
5586 case 14: /* Polynomial VMULL */
5587 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
5588 tcg_temp_free_i32(tmp2);
5589 tcg_temp_free_i32(tmp);
5590 break;
5591 default: /* 15 is RESERVED: caught earlier */
5592 abort();
5594 if (op == 13) {
5595 /* VQDMULL */
5596 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5597 neon_store_reg64(cpu_V0, rd + pass);
5598 } else if (op == 5 || (op >= 8 && op <= 11)) {
5599 /* Accumulate. */
5600 neon_load_reg64(cpu_V1, rd + pass);
5601 switch (op) {
5602 case 10: /* VMLSL */
5603 gen_neon_negl(cpu_V0, size);
5604 /* Fall through */
5605 case 5: case 8: /* VABAL, VMLAL */
5606 gen_neon_addl(size);
5607 break;
5608 case 9: case 11: /* VQDMLAL, VQDMLSL */
5609 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5610 if (op == 11) {
5611 gen_neon_negl(cpu_V0, size);
5613 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5614 break;
5615 default:
5616 abort();
5618 neon_store_reg64(cpu_V0, rd + pass);
5619 } else if (op == 4 || op == 6) {
5620 /* Narrowing operation. */
5621 tmp = tcg_temp_new_i32();
5622 if (!u) {
5623 switch (size) {
5624 case 0:
5625 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
5626 break;
5627 case 1:
5628 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
5629 break;
5630 case 2:
5631 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5632 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5633 break;
5634 default: abort();
5636 } else {
5637 switch (size) {
5638 case 0:
5639 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
5640 break;
5641 case 1:
5642 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
5643 break;
5644 case 2:
5645 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
5646 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5647 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5648 break;
5649 default: abort();
5652 if (pass == 0) {
5653 tmp3 = tmp;
5654 } else {
5655 neon_store_reg(rd, 0, tmp3);
5656 neon_store_reg(rd, 1, tmp);
5658 } else {
5659 /* Write back the result. */
5660 neon_store_reg64(cpu_V0, rd + pass);
5663 } else {
5664 /* Two registers and a scalar. NB that for ops of this form
5665 * the ARM ARM labels bit 24 as Q, but it is in our variable
5666 * 'u', not 'q'.
5668 if (size == 0) {
5669 return 1;
5671 switch (op) {
5672 case 1: /* Float VMLA scalar */
5673 case 5: /* Floating point VMLS scalar */
5674 case 9: /* Floating point VMUL scalar */
5675 if (size == 1) {
5676 return 1;
5678 /* fall through */
5679 case 0: /* Integer VMLA scalar */
5680 case 4: /* Integer VMLS scalar */
5681 case 8: /* Integer VMUL scalar */
5682 case 12: /* VQDMULH scalar */
5683 case 13: /* VQRDMULH scalar */
5684 if (u && ((rd | rn) & 1)) {
5685 return 1;
5687 tmp = neon_get_scalar(size, rm);
5688 neon_store_scratch(0, tmp);
5689 for (pass = 0; pass < (u ? 4 : 2); pass++) {
5690 tmp = neon_load_scratch(0);
5691 tmp2 = neon_load_reg(rn, pass);
5692 if (op == 12) {
5693 if (size == 1) {
5694 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5695 } else {
5696 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5698 } else if (op == 13) {
5699 if (size == 1) {
5700 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5701 } else {
5702 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5704 } else if (op & 1) {
5705 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5706 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
5707 tcg_temp_free_ptr(fpstatus);
5708 } else {
5709 switch (size) {
5710 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5711 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5712 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5713 default: abort();
5716 tcg_temp_free_i32(tmp2);
5717 if (op < 8) {
5718 /* Accumulate. */
5719 tmp2 = neon_load_reg(rd, pass);
5720 switch (op) {
5721 case 0:
5722 gen_neon_add(size, tmp, tmp2);
5723 break;
5724 case 1:
5726 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5727 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5728 tcg_temp_free_ptr(fpstatus);
5729 break;
5731 case 4:
5732 gen_neon_rsb(size, tmp, tmp2);
5733 break;
5734 case 5:
5736 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5737 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
5738 tcg_temp_free_ptr(fpstatus);
5739 break;
5741 default:
5742 abort();
5744 tcg_temp_free_i32(tmp2);
5746 neon_store_reg(rd, pass, tmp);
5748 break;
5749 case 3: /* VQDMLAL scalar */
5750 case 7: /* VQDMLSL scalar */
5751 case 11: /* VQDMULL scalar */
5752 if (u == 1) {
5753 return 1;
5755 /* fall through */
5756 case 2: /* VMLAL sclar */
5757 case 6: /* VMLSL scalar */
5758 case 10: /* VMULL scalar */
5759 if (rd & 1) {
5760 return 1;
5762 tmp2 = neon_get_scalar(size, rm);
5763 /* We need a copy of tmp2 because gen_neon_mull
5764 * deletes it during pass 0. */
5765 tmp4 = tcg_temp_new_i32();
5766 tcg_gen_mov_i32(tmp4, tmp2);
5767 tmp3 = neon_load_reg(rn, 1);
5769 for (pass = 0; pass < 2; pass++) {
5770 if (pass == 0) {
5771 tmp = neon_load_reg(rn, 0);
5772 } else {
5773 tmp = tmp3;
5774 tmp2 = tmp4;
5776 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5777 if (op != 11) {
5778 neon_load_reg64(cpu_V1, rd + pass);
5780 switch (op) {
5781 case 6:
5782 gen_neon_negl(cpu_V0, size);
5783 /* Fall through */
5784 case 2:
5785 gen_neon_addl(size);
5786 break;
5787 case 3: case 7:
5788 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5789 if (op == 7) {
5790 gen_neon_negl(cpu_V0, size);
5792 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5793 break;
5794 case 10:
5795 /* no-op */
5796 break;
5797 case 11:
5798 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5799 break;
5800 default:
5801 abort();
5803 neon_store_reg64(cpu_V0, rd + pass);
5807 break;
5808 default: /* 14 and 15 are RESERVED */
5809 return 1;
5812 } else { /* size == 3 */
5813 if (!u) {
5814 /* Extract. */
5815 imm = (insn >> 8) & 0xf;
5817 if (imm > 7 && !q)
5818 return 1;
5820 if (q && ((rd | rn | rm) & 1)) {
5821 return 1;
5824 if (imm == 0) {
5825 neon_load_reg64(cpu_V0, rn);
5826 if (q) {
5827 neon_load_reg64(cpu_V1, rn + 1);
5829 } else if (imm == 8) {
5830 neon_load_reg64(cpu_V0, rn + 1);
5831 if (q) {
5832 neon_load_reg64(cpu_V1, rm);
5834 } else if (q) {
5835 tmp64 = tcg_temp_new_i64();
5836 if (imm < 8) {
5837 neon_load_reg64(cpu_V0, rn);
5838 neon_load_reg64(tmp64, rn + 1);
5839 } else {
5840 neon_load_reg64(cpu_V0, rn + 1);
5841 neon_load_reg64(tmp64, rm);
5843 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5844 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
5845 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5846 if (imm < 8) {
5847 neon_load_reg64(cpu_V1, rm);
5848 } else {
5849 neon_load_reg64(cpu_V1, rm + 1);
5850 imm -= 8;
5852 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5853 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
5854 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
5855 tcg_temp_free_i64(tmp64);
5856 } else {
5857 /* BUGFIX */
5858 neon_load_reg64(cpu_V0, rn);
5859 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
5860 neon_load_reg64(cpu_V1, rm);
5861 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
5862 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5864 neon_store_reg64(cpu_V0, rd);
5865 if (q) {
5866 neon_store_reg64(cpu_V1, rd + 1);
5868 } else if ((insn & (1 << 11)) == 0) {
5869 /* Two register misc. */
5870 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
5871 size = (insn >> 18) & 3;
5872 /* UNDEF for unknown op values and bad op-size combinations */
5873 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
5874 return 1;
5876 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
5877 q && ((rm | rd) & 1)) {
5878 return 1;
5880 switch (op) {
5881 case NEON_2RM_VREV64:
5882 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5883 tmp = neon_load_reg(rm, pass * 2);
5884 tmp2 = neon_load_reg(rm, pass * 2 + 1);
5885 switch (size) {
5886 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
5887 case 1: gen_swap_half(tmp); break;
5888 case 2: /* no-op */ break;
5889 default: abort();
5891 neon_store_reg(rd, pass * 2 + 1, tmp);
5892 if (size == 2) {
5893 neon_store_reg(rd, pass * 2, tmp2);
5894 } else {
5895 switch (size) {
5896 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
5897 case 1: gen_swap_half(tmp2); break;
5898 default: abort();
5900 neon_store_reg(rd, pass * 2, tmp2);
5903 break;
5904 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
5905 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
5906 for (pass = 0; pass < q + 1; pass++) {
5907 tmp = neon_load_reg(rm, pass * 2);
5908 gen_neon_widen(cpu_V0, tmp, size, op & 1);
5909 tmp = neon_load_reg(rm, pass * 2 + 1);
5910 gen_neon_widen(cpu_V1, tmp, size, op & 1);
5911 switch (size) {
5912 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
5913 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
5914 case 2: tcg_gen_add_i64(CPU_V001); break;
5915 default: abort();
5917 if (op >= NEON_2RM_VPADAL) {
5918 /* Accumulate. */
5919 neon_load_reg64(cpu_V1, rd + pass);
5920 gen_neon_addl(size);
5922 neon_store_reg64(cpu_V0, rd + pass);
5924 break;
5925 case NEON_2RM_VTRN:
5926 if (size == 2) {
5927 int n;
5928 for (n = 0; n < (q ? 4 : 2); n += 2) {
5929 tmp = neon_load_reg(rm, n);
5930 tmp2 = neon_load_reg(rd, n + 1);
5931 neon_store_reg(rm, n, tmp2);
5932 neon_store_reg(rd, n + 1, tmp);
5934 } else {
5935 goto elementwise;
5937 break;
5938 case NEON_2RM_VUZP:
5939 if (gen_neon_unzip(rd, rm, size, q)) {
5940 return 1;
5942 break;
5943 case NEON_2RM_VZIP:
5944 if (gen_neon_zip(rd, rm, size, q)) {
5945 return 1;
5947 break;
5948 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
5949 /* also VQMOVUN; op field and mnemonics don't line up */
5950 if (rm & 1) {
5951 return 1;
5953 TCGV_UNUSED(tmp2);
5954 for (pass = 0; pass < 2; pass++) {
5955 neon_load_reg64(cpu_V0, rm + pass);
5956 tmp = tcg_temp_new_i32();
5957 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
5958 tmp, cpu_V0);
5959 if (pass == 0) {
5960 tmp2 = tmp;
5961 } else {
5962 neon_store_reg(rd, 0, tmp2);
5963 neon_store_reg(rd, 1, tmp);
5966 break;
5967 case NEON_2RM_VSHLL:
5968 if (q || (rd & 1)) {
5969 return 1;
5971 tmp = neon_load_reg(rm, 0);
5972 tmp2 = neon_load_reg(rm, 1);
5973 for (pass = 0; pass < 2; pass++) {
5974 if (pass == 1)
5975 tmp = tmp2;
5976 gen_neon_widen(cpu_V0, tmp, size, 1);
5977 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
5978 neon_store_reg64(cpu_V0, rd + pass);
5980 break;
5981 case NEON_2RM_VCVT_F16_F32:
5982 if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
5983 q || (rm & 1)) {
5984 return 1;
5986 tmp = tcg_temp_new_i32();
5987 tmp2 = tcg_temp_new_i32();
5988 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
5989 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5990 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
5991 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
5992 tcg_gen_shli_i32(tmp2, tmp2, 16);
5993 tcg_gen_or_i32(tmp2, tmp2, tmp);
5994 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
5995 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
5996 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
5997 neon_store_reg(rd, 0, tmp2);
5998 tmp2 = tcg_temp_new_i32();
5999 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
6000 tcg_gen_shli_i32(tmp2, tmp2, 16);
6001 tcg_gen_or_i32(tmp2, tmp2, tmp);
6002 neon_store_reg(rd, 1, tmp2);
6003 tcg_temp_free_i32(tmp);
6004 break;
6005 case NEON_2RM_VCVT_F32_F16:
6006 if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
6007 q || (rd & 1)) {
6008 return 1;
6010 tmp3 = tcg_temp_new_i32();
6011 tmp = neon_load_reg(rm, 0);
6012 tmp2 = neon_load_reg(rm, 1);
6013 tcg_gen_ext16u_i32(tmp3, tmp);
6014 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6015 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
6016 tcg_gen_shri_i32(tmp3, tmp, 16);
6017 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6018 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
6019 tcg_temp_free_i32(tmp);
6020 tcg_gen_ext16u_i32(tmp3, tmp2);
6021 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6022 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
6023 tcg_gen_shri_i32(tmp3, tmp2, 16);
6024 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6025 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
6026 tcg_temp_free_i32(tmp2);
6027 tcg_temp_free_i32(tmp3);
6028 break;
6029 default:
6030 elementwise:
6031 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6032 if (neon_2rm_is_float_op(op)) {
6033 tcg_gen_ld_f32(cpu_F0s, cpu_env,
6034 neon_reg_offset(rm, pass));
6035 TCGV_UNUSED(tmp);
6036 } else {
6037 tmp = neon_load_reg(rm, pass);
6039 switch (op) {
6040 case NEON_2RM_VREV32:
6041 switch (size) {
6042 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6043 case 1: gen_swap_half(tmp); break;
6044 default: abort();
6046 break;
6047 case NEON_2RM_VREV16:
6048 gen_rev16(tmp);
6049 break;
6050 case NEON_2RM_VCLS:
6051 switch (size) {
6052 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
6053 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
6054 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
6055 default: abort();
6057 break;
6058 case NEON_2RM_VCLZ:
6059 switch (size) {
6060 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
6061 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
6062 case 2: gen_helper_clz(tmp, tmp); break;
6063 default: abort();
6065 break;
6066 case NEON_2RM_VCNT:
6067 gen_helper_neon_cnt_u8(tmp, tmp);
6068 break;
6069 case NEON_2RM_VMVN:
6070 tcg_gen_not_i32(tmp, tmp);
6071 break;
6072 case NEON_2RM_VQABS:
6073 switch (size) {
6074 case 0:
6075 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
6076 break;
6077 case 1:
6078 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
6079 break;
6080 case 2:
6081 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
6082 break;
6083 default: abort();
6085 break;
6086 case NEON_2RM_VQNEG:
6087 switch (size) {
6088 case 0:
6089 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
6090 break;
6091 case 1:
6092 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
6093 break;
6094 case 2:
6095 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
6096 break;
6097 default: abort();
6099 break;
6100 case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
6101 tmp2 = tcg_const_i32(0);
6102 switch(size) {
6103 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
6104 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
6105 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
6106 default: abort();
6108 tcg_temp_free(tmp2);
6109 if (op == NEON_2RM_VCLE0) {
6110 tcg_gen_not_i32(tmp, tmp);
6112 break;
6113 case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
6114 tmp2 = tcg_const_i32(0);
6115 switch(size) {
6116 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
6117 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
6118 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
6119 default: abort();
6121 tcg_temp_free(tmp2);
6122 if (op == NEON_2RM_VCLT0) {
6123 tcg_gen_not_i32(tmp, tmp);
6125 break;
6126 case NEON_2RM_VCEQ0:
6127 tmp2 = tcg_const_i32(0);
6128 switch(size) {
6129 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
6130 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
6131 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
6132 default: abort();
6134 tcg_temp_free(tmp2);
6135 break;
6136 case NEON_2RM_VABS:
6137 switch(size) {
6138 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
6139 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
6140 case 2: tcg_gen_abs_i32(tmp, tmp); break;
6141 default: abort();
6143 break;
6144 case NEON_2RM_VNEG:
6145 tmp2 = tcg_const_i32(0);
6146 gen_neon_rsb(size, tmp, tmp2);
6147 tcg_temp_free(tmp2);
6148 break;
6149 case NEON_2RM_VCGT0_F:
6151 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6152 tmp2 = tcg_const_i32(0);
6153 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
6154 tcg_temp_free(tmp2);
6155 tcg_temp_free_ptr(fpstatus);
6156 break;
6158 case NEON_2RM_VCGE0_F:
6160 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6161 tmp2 = tcg_const_i32(0);
6162 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
6163 tcg_temp_free(tmp2);
6164 tcg_temp_free_ptr(fpstatus);
6165 break;
6167 case NEON_2RM_VCEQ0_F:
6169 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6170 tmp2 = tcg_const_i32(0);
6171 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
6172 tcg_temp_free(tmp2);
6173 tcg_temp_free_ptr(fpstatus);
6174 break;
6176 case NEON_2RM_VCLE0_F:
6178 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6179 tmp2 = tcg_const_i32(0);
6180 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
6181 tcg_temp_free(tmp2);
6182 tcg_temp_free_ptr(fpstatus);
6183 break;
6185 case NEON_2RM_VCLT0_F:
6187 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6188 tmp2 = tcg_const_i32(0);
6189 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
6190 tcg_temp_free(tmp2);
6191 tcg_temp_free_ptr(fpstatus);
6192 break;
6194 case NEON_2RM_VABS_F:
6195 gen_vfp_abs(0);
6196 break;
6197 case NEON_2RM_VNEG_F:
6198 gen_vfp_neg(0);
6199 break;
6200 case NEON_2RM_VSWP:
6201 tmp2 = neon_load_reg(rd, pass);
6202 neon_store_reg(rm, pass, tmp2);
6203 break;
6204 case NEON_2RM_VTRN:
6205 tmp2 = neon_load_reg(rd, pass);
6206 switch (size) {
6207 case 0: gen_neon_trn_u8(tmp, tmp2); break;
6208 case 1: gen_neon_trn_u16(tmp, tmp2); break;
6209 default: abort();
6211 neon_store_reg(rm, pass, tmp2);
6212 break;
6213 case NEON_2RM_VRECPE:
6214 gen_helper_recpe_u32(tmp, tmp, cpu_env);
6215 break;
6216 case NEON_2RM_VRSQRTE:
6217 gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
6218 break;
6219 case NEON_2RM_VRECPE_F:
6220 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
6221 break;
6222 case NEON_2RM_VRSQRTE_F:
6223 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
6224 break;
6225 case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
6226 gen_vfp_sito(0, 1);
6227 break;
6228 case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
6229 gen_vfp_uito(0, 1);
6230 break;
6231 case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
6232 gen_vfp_tosiz(0, 1);
6233 break;
6234 case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
6235 gen_vfp_touiz(0, 1);
6236 break;
6237 default:
6238 /* Reserved op values were caught by the
6239 * neon_2rm_sizes[] check earlier.
6241 abort();
6243 if (neon_2rm_is_float_op(op)) {
6244 tcg_gen_st_f32(cpu_F0s, cpu_env,
6245 neon_reg_offset(rd, pass));
6246 } else {
6247 neon_store_reg(rd, pass, tmp);
6250 break;
6252 } else if ((insn & (1 << 10)) == 0) {
6253 /* VTBL, VTBX. */
6254 int n = ((insn >> 8) & 3) + 1;
6255 if ((rn + n) > 32) {
6256 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
6257 * helper function running off the end of the register file.
6259 return 1;
6261 n <<= 3;
6262 if (insn & (1 << 6)) {
6263 tmp = neon_load_reg(rd, 0);
6264 } else {
6265 tmp = tcg_temp_new_i32();
6266 tcg_gen_movi_i32(tmp, 0);
6268 tmp2 = neon_load_reg(rm, 0);
6269 tmp4 = tcg_const_i32(rn);
6270 tmp5 = tcg_const_i32(n);
6271 gen_helper_neon_tbl(tmp2, tmp2, tmp, tmp4, tmp5);
6272 tcg_temp_free_i32(tmp);
6273 if (insn & (1 << 6)) {
6274 tmp = neon_load_reg(rd, 1);
6275 } else {
6276 tmp = tcg_temp_new_i32();
6277 tcg_gen_movi_i32(tmp, 0);
6279 tmp3 = neon_load_reg(rm, 1);
6280 gen_helper_neon_tbl(tmp3, tmp3, tmp, tmp4, tmp5);
6281 tcg_temp_free_i32(tmp5);
6282 tcg_temp_free_i32(tmp4);
6283 neon_store_reg(rd, 0, tmp2);
6284 neon_store_reg(rd, 1, tmp3);
6285 tcg_temp_free_i32(tmp);
6286 } else if ((insn & 0x380) == 0) {
6287 /* VDUP */
6288 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
6289 return 1;
6291 if (insn & (1 << 19)) {
6292 tmp = neon_load_reg(rm, 1);
6293 } else {
6294 tmp = neon_load_reg(rm, 0);
6296 if (insn & (1 << 16)) {
6297 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
6298 } else if (insn & (1 << 17)) {
6299 if ((insn >> 18) & 1)
6300 gen_neon_dup_high16(tmp);
6301 else
6302 gen_neon_dup_low16(tmp);
6304 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6305 tmp2 = tcg_temp_new_i32();
6306 tcg_gen_mov_i32(tmp2, tmp);
6307 neon_store_reg(rd, pass, tmp2);
6309 tcg_temp_free_i32(tmp);
6310 } else {
6311 return 1;
6315 return 0;
6318 static int disas_cp14_read(CPUState * env, DisasContext *s, uint32_t insn)
6320 int crn = (insn >> 16) & 0xf;
6321 int crm = insn & 0xf;
6322 int op1 = (insn >> 21) & 7;
6323 int op2 = (insn >> 5) & 7;
6324 int rt = (insn >> 12) & 0xf;
6325 TCGv tmp;
6327 /* Minimal set of debug registers, since we don't support debug */
6328 if (op1 == 0 && crn == 0 && op2 == 0) {
6329 switch (crm) {
6330 case 0:
6331 /* DBGDIDR: just RAZ. In particular this means the
6332 * "debug architecture version" bits will read as
6333 * a reserved value, which should cause Linux to
6334 * not try to use the debug hardware.
6336 tmp = tcg_const_i32(0);
6337 store_reg(s, rt, tmp);
6338 return 0;
6339 case 1:
6340 case 2:
6341 /* DBGDRAR and DBGDSAR: v7 only. Always RAZ since we
6342 * don't implement memory mapped debug components
6344 if (ENABLE_ARCH_7) {
6345 tmp = tcg_const_i32(0);
6346 store_reg(s, rt, tmp);
6347 return 0;
6349 break;
6350 default:
6351 break;
6355 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
6356 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
6357 /* TEECR */
6358 if (IS_USER(s))
6359 return 1;
6360 tmp = load_cpu_field(teecr);
6361 store_reg(s, rt, tmp);
6362 return 0;
6364 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
6365 /* TEEHBR */
6366 if (IS_USER(s) && (env->teecr & 1))
6367 return 1;
6368 tmp = load_cpu_field(teehbr);
6369 store_reg(s, rt, tmp);
6370 return 0;
6373 return 1;
6376 static int disas_cp14_write(CPUState * env, DisasContext *s, uint32_t insn)
6378 int crn = (insn >> 16) & 0xf;
6379 int crm = insn & 0xf;
6380 int op1 = (insn >> 21) & 7;
6381 int op2 = (insn >> 5) & 7;
6382 int rt = (insn >> 12) & 0xf;
6383 TCGv tmp;
6385 if (arm_feature(env, ARM_FEATURE_THUMB2EE)) {
6386 if (op1 == 6 && crn == 0 && crm == 0 && op2 == 0) {
6387 /* TEECR */
6388 if (IS_USER(s))
6389 return 1;
6390 tmp = load_reg(s, rt);
6391 gen_helper_set_teecr(cpu_env, tmp);
6392 tcg_temp_free_i32(tmp);
6393 return 0;
6395 if (op1 == 6 && crn == 1 && crm == 0 && op2 == 0) {
6396 /* TEEHBR */
6397 if (IS_USER(s) && (env->teecr & 1))
6398 return 1;
6399 tmp = load_reg(s, rt);
6400 store_cpu_field(tmp, teehbr);
6401 return 0;
6404 return 1;
6407 static int disas_coproc_insn(CPUState * env, DisasContext *s, uint32_t insn)
6409 int cpnum;
6411 cpnum = (insn >> 8) & 0xf;
6412 if (arm_feature(env, ARM_FEATURE_XSCALE)
6413 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
6414 return 1;
6416 switch (cpnum) {
6417 case 0:
6418 case 1:
6419 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
6420 return disas_iwmmxt_insn(env, s, insn);
6421 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
6422 return disas_dsp_insn(env, s, insn);
6424 return 1;
6425 case 10:
6426 case 11:
6427 return disas_vfp_insn (env, s, insn);
6428 case 14:
6429 /* Coprocessors 7-15 are architecturally reserved by ARM.
6430 Unfortunately Intel decided to ignore this. */
6431 if (arm_feature(env, ARM_FEATURE_XSCALE))
6432 goto board;
6433 if (insn & (1 << 20))
6434 return disas_cp14_read(env, s, insn);
6435 else
6436 return disas_cp14_write(env, s, insn);
6437 case 15:
6438 return disas_cp15_insn (env, s, insn);
6439 default:
6440 board:
6441 /* Unknown coprocessor. See if the board has hooked it. */
6442 return disas_cp_insn (env, s, insn);
6447 /* Store a 64-bit value to a register pair. Clobbers val. */
6448 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
6450 TCGv tmp;
6451 tmp = tcg_temp_new_i32();
6452 tcg_gen_trunc_i64_i32(tmp, val);
6453 store_reg(s, rlow, tmp);
6454 tmp = tcg_temp_new_i32();
6455 tcg_gen_shri_i64(val, val, 32);
6456 tcg_gen_trunc_i64_i32(tmp, val);
6457 store_reg(s, rhigh, tmp);
6460 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
6461 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
6463 TCGv_i64 tmp;
6464 TCGv tmp2;
6466 /* Load value and extend to 64 bits. */
6467 tmp = tcg_temp_new_i64();
6468 tmp2 = load_reg(s, rlow);
6469 tcg_gen_extu_i32_i64(tmp, tmp2);
6470 tcg_temp_free_i32(tmp2);
6471 tcg_gen_add_i64(val, val, tmp);
6472 tcg_temp_free_i64(tmp);
6475 /* load and add a 64-bit value from a register pair. */
6476 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
6478 TCGv_i64 tmp;
6479 TCGv tmpl;
6480 TCGv tmph;
6482 /* Load 64-bit value rd:rn. */
6483 tmpl = load_reg(s, rlow);
6484 tmph = load_reg(s, rhigh);
6485 tmp = tcg_temp_new_i64();
6486 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
6487 tcg_temp_free_i32(tmpl);
6488 tcg_temp_free_i32(tmph);
6489 tcg_gen_add_i64(val, val, tmp);
6490 tcg_temp_free_i64(tmp);
6493 /* Set N and Z flags from a 64-bit value. */
6494 static void gen_logicq_cc(TCGv_i64 val)
6496 TCGv tmp = tcg_temp_new_i32();
6497 gen_helper_logicq_cc(tmp, val);
6498 gen_logic_CC(tmp);
6499 tcg_temp_free_i32(tmp);
6502 /* Load/Store exclusive instructions are implemented by remembering
6503 the value/address loaded, and seeing if these are the same
6504 when the store is performed. This should be is sufficient to implement
6505 the architecturally mandated semantics, and avoids having to monitor
6506 regular stores.
6508 In system emulation mode only one CPU will be running at once, so
6509 this sequence is effectively atomic. In user emulation mode we
6510 throw an exception and handle the atomic operation elsewhere. */
6511 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
6512 TCGv addr, int size)
6514 TCGv tmp;
6516 switch (size) {
6517 case 0:
6518 tmp = gen_ld8u(addr, IS_USER(s));
6519 break;
6520 case 1:
6521 tmp = gen_ld16u(addr, IS_USER(s));
6522 break;
6523 case 2:
6524 case 3:
6525 tmp = gen_ld32(addr, IS_USER(s));
6526 break;
6527 default:
6528 abort();
6530 tcg_gen_mov_i32(cpu_exclusive_val, tmp);
6531 store_reg(s, rt, tmp);
6532 if (size == 3) {
6533 TCGv tmp2 = tcg_temp_new_i32();
6534 tcg_gen_addi_i32(tmp2, addr, 4);
6535 tmp = gen_ld32(tmp2, IS_USER(s));
6536 tcg_temp_free_i32(tmp2);
6537 tcg_gen_mov_i32(cpu_exclusive_high, tmp);
6538 store_reg(s, rt2, tmp);
6540 tcg_gen_mov_i32(cpu_exclusive_addr, addr);
6543 static void gen_clrex(DisasContext *s)
6545 tcg_gen_movi_i32(cpu_exclusive_addr, -1);
6548 #ifdef CONFIG_USER_ONLY
6549 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
6550 TCGv addr, int size)
6552 tcg_gen_mov_i32(cpu_exclusive_test, addr);
6553 tcg_gen_movi_i32(cpu_exclusive_info,
6554 size | (rd << 4) | (rt << 8) | (rt2 << 12));
6555 gen_exception_insn(s, 4, EXCP_STREX);
6557 #else
6558 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
6559 TCGv addr, int size)
6561 TCGv tmp;
6562 int done_label;
6563 int fail_label;
6565 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
6566 [addr] = {Rt};
6567 {Rd} = 0;
6568 } else {
6569 {Rd} = 1;
6570 } */
6571 fail_label = gen_new_label();
6572 done_label = gen_new_label();
6573 tcg_gen_brcond_i32(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
6574 switch (size) {
6575 case 0:
6576 tmp = gen_ld8u(addr, IS_USER(s));
6577 break;
6578 case 1:
6579 tmp = gen_ld16u(addr, IS_USER(s));
6580 break;
6581 case 2:
6582 case 3:
6583 tmp = gen_ld32(addr, IS_USER(s));
6584 break;
6585 default:
6586 abort();
6588 tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label);
6589 tcg_temp_free_i32(tmp);
6590 if (size == 3) {
6591 TCGv tmp2 = tcg_temp_new_i32();
6592 tcg_gen_addi_i32(tmp2, addr, 4);
6593 tmp = gen_ld32(tmp2, IS_USER(s));
6594 tcg_temp_free_i32(tmp2);
6595 tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_high, fail_label);
6596 tcg_temp_free_i32(tmp);
6598 tmp = load_reg(s, rt);
6599 switch (size) {
6600 case 0:
6601 gen_st8(tmp, addr, IS_USER(s));
6602 break;
6603 case 1:
6604 gen_st16(tmp, addr, IS_USER(s));
6605 break;
6606 case 2:
6607 case 3:
6608 gen_st32(tmp, addr, IS_USER(s));
6609 break;
6610 default:
6611 abort();
6613 if (size == 3) {
6614 tcg_gen_addi_i32(addr, addr, 4);
6615 tmp = load_reg(s, rt2);
6616 gen_st32(tmp, addr, IS_USER(s));
6618 tcg_gen_movi_i32(cpu_R[rd], 0);
6619 tcg_gen_br(done_label);
6620 gen_set_label(fail_label);
6621 tcg_gen_movi_i32(cpu_R[rd], 1);
6622 gen_set_label(done_label);
6623 tcg_gen_movi_i32(cpu_exclusive_addr, -1);
6625 #endif
6627 static void disas_arm_insn(CPUState * env, DisasContext *s)
6629 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
6630 TCGv tmp;
6631 TCGv tmp2;
6632 TCGv tmp3;
6633 TCGv addr;
6634 TCGv_i64 tmp64;
6636 insn = ldl_code(s->pc);
6637 s->pc += 4;
6639 /* M variants do not implement ARM mode. */
6640 if (IS_M(env))
6641 goto illegal_op;
6642 cond = insn >> 28;
6643 if (cond == 0xf){
6644 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
6645 * choose to UNDEF. In ARMv5 and above the space is used
6646 * for miscellaneous unconditional instructions.
6648 ARCH(5);
6650 /* Unconditional instructions. */
6651 if (((insn >> 25) & 7) == 1) {
6652 /* NEON Data processing. */
6653 if (!arm_feature(env, ARM_FEATURE_NEON))
6654 goto illegal_op;
6656 if (disas_neon_data_insn(env, s, insn))
6657 goto illegal_op;
6658 return;
6660 if ((insn & 0x0f100000) == 0x04000000) {
6661 /* NEON load/store. */
6662 if (!arm_feature(env, ARM_FEATURE_NEON))
6663 goto illegal_op;
6665 if (disas_neon_ls_insn(env, s, insn))
6666 goto illegal_op;
6667 return;
6669 if (((insn & 0x0f30f000) == 0x0510f000) ||
6670 ((insn & 0x0f30f010) == 0x0710f000)) {
6671 if ((insn & (1 << 22)) == 0) {
6672 /* PLDW; v7MP */
6673 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
6674 goto illegal_op;
6677 /* Otherwise PLD; v5TE+ */
6678 ARCH(5TE);
6679 return;
6681 if (((insn & 0x0f70f000) == 0x0450f000) ||
6682 ((insn & 0x0f70f010) == 0x0650f000)) {
6683 ARCH(7);
6684 return; /* PLI; V7 */
6686 if (((insn & 0x0f700000) == 0x04100000) ||
6687 ((insn & 0x0f700010) == 0x06100000)) {
6688 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
6689 goto illegal_op;
6691 return; /* v7MP: Unallocated memory hint: must NOP */
6694 if ((insn & 0x0ffffdff) == 0x01010000) {
6695 ARCH(6);
6696 /* setend */
6697 if (insn & (1 << 9)) {
6698 /* BE8 mode not implemented. */
6699 goto illegal_op;
6701 return;
6702 } else if ((insn & 0x0fffff00) == 0x057ff000) {
6703 switch ((insn >> 4) & 0xf) {
6704 case 1: /* clrex */
6705 ARCH(6K);
6706 gen_clrex(s);
6707 return;
6708 case 4: /* dsb */
6709 case 5: /* dmb */
6710 case 6: /* isb */
6711 ARCH(7);
6712 /* We don't emulate caches so these are a no-op. */
6713 return;
6714 default:
6715 goto illegal_op;
6717 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
6718 /* srs */
6719 int32_t offset;
6720 if (IS_USER(s))
6721 goto illegal_op;
6722 ARCH(6);
6723 op1 = (insn & 0x1f);
6724 addr = tcg_temp_new_i32();
6725 tmp = tcg_const_i32(op1);
6726 gen_helper_get_r13_banked(addr, cpu_env, tmp);
6727 tcg_temp_free_i32(tmp);
6728 i = (insn >> 23) & 3;
6729 switch (i) {
6730 case 0: offset = -4; break; /* DA */
6731 case 1: offset = 0; break; /* IA */
6732 case 2: offset = -8; break; /* DB */
6733 case 3: offset = 4; break; /* IB */
6734 default: abort();
6736 if (offset)
6737 tcg_gen_addi_i32(addr, addr, offset);
6738 tmp = load_reg(s, 14);
6739 gen_st32(tmp, addr, 0);
6740 tmp = load_cpu_field(spsr);
6741 tcg_gen_addi_i32(addr, addr, 4);
6742 gen_st32(tmp, addr, 0);
6743 if (insn & (1 << 21)) {
6744 /* Base writeback. */
6745 switch (i) {
6746 case 0: offset = -8; break;
6747 case 1: offset = 4; break;
6748 case 2: offset = -4; break;
6749 case 3: offset = 0; break;
6750 default: abort();
6752 if (offset)
6753 tcg_gen_addi_i32(addr, addr, offset);
6754 tmp = tcg_const_i32(op1);
6755 gen_helper_set_r13_banked(cpu_env, tmp, addr);
6756 tcg_temp_free_i32(tmp);
6757 tcg_temp_free_i32(addr);
6758 } else {
6759 tcg_temp_free_i32(addr);
6761 return;
6762 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
6763 /* rfe */
6764 int32_t offset;
6765 if (IS_USER(s))
6766 goto illegal_op;
6767 ARCH(6);
6768 rn = (insn >> 16) & 0xf;
6769 addr = load_reg(s, rn);
6770 i = (insn >> 23) & 3;
6771 switch (i) {
6772 case 0: offset = -4; break; /* DA */
6773 case 1: offset = 0; break; /* IA */
6774 case 2: offset = -8; break; /* DB */
6775 case 3: offset = 4; break; /* IB */
6776 default: abort();
6778 if (offset)
6779 tcg_gen_addi_i32(addr, addr, offset);
6780 /* Load PC into tmp and CPSR into tmp2. */
6781 tmp = gen_ld32(addr, 0);
6782 tcg_gen_addi_i32(addr, addr, 4);
6783 tmp2 = gen_ld32(addr, 0);
6784 if (insn & (1 << 21)) {
6785 /* Base writeback. */
6786 switch (i) {
6787 case 0: offset = -8; break;
6788 case 1: offset = 4; break;
6789 case 2: offset = -4; break;
6790 case 3: offset = 0; break;
6791 default: abort();
6793 if (offset)
6794 tcg_gen_addi_i32(addr, addr, offset);
6795 store_reg(s, rn, addr);
6796 } else {
6797 tcg_temp_free_i32(addr);
6799 gen_rfe(s, tmp, tmp2);
6800 return;
6801 } else if ((insn & 0x0e000000) == 0x0a000000) {
6802 /* branch link and change to thumb (blx <offset>) */
6803 int32_t offset;
6805 val = (uint32_t)s->pc;
6806 tmp = tcg_temp_new_i32();
6807 tcg_gen_movi_i32(tmp, val);
6808 store_reg(s, 14, tmp);
6809 /* Sign-extend the 24-bit offset */
6810 offset = (((int32_t)insn) << 8) >> 8;
6811 /* offset * 4 + bit24 * 2 + (thumb bit) */
6812 val += (offset << 2) | ((insn >> 23) & 2) | 1;
6813 /* pipeline offset */
6814 val += 4;
6815 /* protected by ARCH(5); above, near the start of uncond block */
6816 gen_bx_im(s, val);
6817 return;
6818 } else if ((insn & 0x0e000f00) == 0x0c000100) {
6819 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
6820 /* iWMMXt register transfer. */
6821 if (env->cp15.c15_cpar & (1 << 1))
6822 if (!disas_iwmmxt_insn(env, s, insn))
6823 return;
6825 } else if ((insn & 0x0fe00000) == 0x0c400000) {
6826 /* Coprocessor double register transfer. */
6827 ARCH(5TE);
6828 } else if ((insn & 0x0f000010) == 0x0e000010) {
6829 /* Additional coprocessor register transfer. */
6830 } else if ((insn & 0x0ff10020) == 0x01000000) {
6831 uint32_t mask;
6832 uint32_t val;
6833 /* cps (privileged) */
6834 if (IS_USER(s))
6835 return;
6836 mask = val = 0;
6837 if (insn & (1 << 19)) {
6838 if (insn & (1 << 8))
6839 mask |= CPSR_A;
6840 if (insn & (1 << 7))
6841 mask |= CPSR_I;
6842 if (insn & (1 << 6))
6843 mask |= CPSR_F;
6844 if (insn & (1 << 18))
6845 val |= mask;
6847 if (insn & (1 << 17)) {
6848 mask |= CPSR_M;
6849 val |= (insn & 0x1f);
6851 if (mask) {
6852 gen_set_psr_im(s, mask, 0, val);
6854 return;
6856 goto illegal_op;
6858 if (cond != 0xe) {
6859 /* if not always execute, we generate a conditional jump to
6860 next instruction */
6861 s->condlabel = gen_new_label();
6862 gen_test_cc(cond ^ 1, s->condlabel);
6863 s->condjmp = 1;
6865 if ((insn & 0x0f900000) == 0x03000000) {
6866 if ((insn & (1 << 21)) == 0) {
6867 ARCH(6T2);
6868 rd = (insn >> 12) & 0xf;
6869 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
6870 if ((insn & (1 << 22)) == 0) {
6871 /* MOVW */
6872 tmp = tcg_temp_new_i32();
6873 tcg_gen_movi_i32(tmp, val);
6874 } else {
6875 /* MOVT */
6876 tmp = load_reg(s, rd);
6877 tcg_gen_ext16u_i32(tmp, tmp);
6878 tcg_gen_ori_i32(tmp, tmp, val << 16);
6880 store_reg(s, rd, tmp);
6881 } else {
6882 if (((insn >> 12) & 0xf) != 0xf)
6883 goto illegal_op;
6884 if (((insn >> 16) & 0xf) == 0) {
6885 gen_nop_hint(s, insn & 0xff);
6886 } else {
6887 /* CPSR = immediate */
6888 val = insn & 0xff;
6889 shift = ((insn >> 8) & 0xf) * 2;
6890 if (shift)
6891 val = (val >> shift) | (val << (32 - shift));
6892 i = ((insn & (1 << 22)) != 0);
6893 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
6894 goto illegal_op;
6897 } else if ((insn & 0x0f900000) == 0x01000000
6898 && (insn & 0x00000090) != 0x00000090) {
6899 /* miscellaneous instructions */
6900 op1 = (insn >> 21) & 3;
6901 sh = (insn >> 4) & 0xf;
6902 rm = insn & 0xf;
6903 switch (sh) {
6904 case 0x0: /* move program status register */
6905 if (op1 & 1) {
6906 /* PSR = reg */
6907 tmp = load_reg(s, rm);
6908 i = ((op1 & 2) != 0);
6909 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
6910 goto illegal_op;
6911 } else {
6912 /* reg = PSR */
6913 rd = (insn >> 12) & 0xf;
6914 if (op1 & 2) {
6915 if (IS_USER(s))
6916 goto illegal_op;
6917 tmp = load_cpu_field(spsr);
6918 } else {
6919 tmp = tcg_temp_new_i32();
6920 gen_helper_cpsr_read(tmp);
6922 store_reg(s, rd, tmp);
6924 break;
6925 case 0x1:
6926 if (op1 == 1) {
6927 /* branch/exchange thumb (bx). */
6928 ARCH(4T);
6929 tmp = load_reg(s, rm);
6930 gen_bx(s, tmp);
6931 } else if (op1 == 3) {
6932 /* clz */
6933 ARCH(5);
6934 rd = (insn >> 12) & 0xf;
6935 tmp = load_reg(s, rm);
6936 gen_helper_clz(tmp, tmp);
6937 store_reg(s, rd, tmp);
6938 } else {
6939 goto illegal_op;
6941 break;
6942 case 0x2:
6943 if (op1 == 1) {
6944 ARCH(5J); /* bxj */
6945 /* Trivial implementation equivalent to bx. */
6946 tmp = load_reg(s, rm);
6947 gen_bx(s, tmp);
6948 } else {
6949 goto illegal_op;
6951 break;
6952 case 0x3:
6953 if (op1 != 1)
6954 goto illegal_op;
6956 ARCH(5);
6957 /* branch link/exchange thumb (blx) */
6958 tmp = load_reg(s, rm);
6959 tmp2 = tcg_temp_new_i32();
6960 tcg_gen_movi_i32(tmp2, s->pc);
6961 store_reg(s, 14, tmp2);
6962 gen_bx(s, tmp);
6963 break;
6964 case 0x5: /* saturating add/subtract */
6965 ARCH(5TE);
6966 rd = (insn >> 12) & 0xf;
6967 rn = (insn >> 16) & 0xf;
6968 tmp = load_reg(s, rm);
6969 tmp2 = load_reg(s, rn);
6970 if (op1 & 2)
6971 gen_helper_double_saturate(tmp2, tmp2);
6972 if (op1 & 1)
6973 gen_helper_sub_saturate(tmp, tmp, tmp2);
6974 else
6975 gen_helper_add_saturate(tmp, tmp, tmp2);
6976 tcg_temp_free_i32(tmp2);
6977 store_reg(s, rd, tmp);
6978 break;
6979 case 7:
6980 /* SMC instruction (op1 == 3)
6981 and undefined instructions (op1 == 0 || op1 == 2)
6982 will trap */
6983 if (op1 != 1) {
6984 goto illegal_op;
6986 /* bkpt */
6987 ARCH(5);
6988 gen_exception_insn(s, 4, EXCP_BKPT);
6989 break;
6990 case 0x8: /* signed multiply */
6991 case 0xa:
6992 case 0xc:
6993 case 0xe:
6994 ARCH(5TE);
6995 rs = (insn >> 8) & 0xf;
6996 rn = (insn >> 12) & 0xf;
6997 rd = (insn >> 16) & 0xf;
6998 if (op1 == 1) {
6999 /* (32 * 16) >> 16 */
7000 tmp = load_reg(s, rm);
7001 tmp2 = load_reg(s, rs);
7002 if (sh & 4)
7003 tcg_gen_sari_i32(tmp2, tmp2, 16);
7004 else
7005 gen_sxth(tmp2);
7006 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7007 tcg_gen_shri_i64(tmp64, tmp64, 16);
7008 tmp = tcg_temp_new_i32();
7009 tcg_gen_trunc_i64_i32(tmp, tmp64);
7010 tcg_temp_free_i64(tmp64);
7011 if ((sh & 2) == 0) {
7012 tmp2 = load_reg(s, rn);
7013 gen_helper_add_setq(tmp, tmp, tmp2);
7014 tcg_temp_free_i32(tmp2);
7016 store_reg(s, rd, tmp);
7017 } else {
7018 /* 16 * 16 */
7019 tmp = load_reg(s, rm);
7020 tmp2 = load_reg(s, rs);
7021 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
7022 tcg_temp_free_i32(tmp2);
7023 if (op1 == 2) {
7024 tmp64 = tcg_temp_new_i64();
7025 tcg_gen_ext_i32_i64(tmp64, tmp);
7026 tcg_temp_free_i32(tmp);
7027 gen_addq(s, tmp64, rn, rd);
7028 gen_storeq_reg(s, rn, rd, tmp64);
7029 tcg_temp_free_i64(tmp64);
7030 } else {
7031 if (op1 == 0) {
7032 tmp2 = load_reg(s, rn);
7033 gen_helper_add_setq(tmp, tmp, tmp2);
7034 tcg_temp_free_i32(tmp2);
7036 store_reg(s, rd, tmp);
7039 break;
7040 default:
7041 goto illegal_op;
7043 } else if (((insn & 0x0e000000) == 0 &&
7044 (insn & 0x00000090) != 0x90) ||
7045 ((insn & 0x0e000000) == (1 << 25))) {
7046 int set_cc, logic_cc, shiftop;
7048 op1 = (insn >> 21) & 0xf;
7049 set_cc = (insn >> 20) & 1;
7050 logic_cc = table_logic_cc[op1] & set_cc;
7052 /* data processing instruction */
7053 if (insn & (1 << 25)) {
7054 /* immediate operand */
7055 val = insn & 0xff;
7056 shift = ((insn >> 8) & 0xf) * 2;
7057 if (shift) {
7058 val = (val >> shift) | (val << (32 - shift));
7060 tmp2 = tcg_temp_new_i32();
7061 tcg_gen_movi_i32(tmp2, val);
7062 if (logic_cc && shift) {
7063 gen_set_CF_bit31(tmp2);
7065 } else {
7066 /* register */
7067 rm = (insn) & 0xf;
7068 tmp2 = load_reg(s, rm);
7069 shiftop = (insn >> 5) & 3;
7070 if (!(insn & (1 << 4))) {
7071 shift = (insn >> 7) & 0x1f;
7072 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
7073 } else {
7074 rs = (insn >> 8) & 0xf;
7075 tmp = load_reg(s, rs);
7076 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
7079 if (op1 != 0x0f && op1 != 0x0d) {
7080 rn = (insn >> 16) & 0xf;
7081 tmp = load_reg(s, rn);
7082 } else {
7083 TCGV_UNUSED(tmp);
7085 rd = (insn >> 12) & 0xf;
7086 switch(op1) {
7087 case 0x00:
7088 tcg_gen_and_i32(tmp, tmp, tmp2);
7089 if (logic_cc) {
7090 gen_logic_CC(tmp);
7092 store_reg_bx(env, s, rd, tmp);
7093 break;
7094 case 0x01:
7095 tcg_gen_xor_i32(tmp, tmp, tmp2);
7096 if (logic_cc) {
7097 gen_logic_CC(tmp);
7099 store_reg_bx(env, s, rd, tmp);
7100 break;
7101 case 0x02:
7102 if (set_cc && rd == 15) {
7103 /* SUBS r15, ... is used for exception return. */
7104 if (IS_USER(s)) {
7105 goto illegal_op;
7107 gen_helper_sub_cc(tmp, tmp, tmp2);
7108 gen_exception_return(s, tmp);
7109 } else {
7110 if (set_cc) {
7111 gen_helper_sub_cc(tmp, tmp, tmp2);
7112 } else {
7113 tcg_gen_sub_i32(tmp, tmp, tmp2);
7115 store_reg_bx(env, s, rd, tmp);
7117 break;
7118 case 0x03:
7119 if (set_cc) {
7120 gen_helper_sub_cc(tmp, tmp2, tmp);
7121 } else {
7122 tcg_gen_sub_i32(tmp, tmp2, tmp);
7124 store_reg_bx(env, s, rd, tmp);
7125 break;
7126 case 0x04:
7127 if (set_cc) {
7128 gen_helper_add_cc(tmp, tmp, tmp2);
7129 } else {
7130 tcg_gen_add_i32(tmp, tmp, tmp2);
7132 store_reg_bx(env, s, rd, tmp);
7133 break;
7134 case 0x05:
7135 if (set_cc) {
7136 gen_helper_adc_cc(tmp, tmp, tmp2);
7137 } else {
7138 gen_add_carry(tmp, tmp, tmp2);
7140 store_reg_bx(env, s, rd, tmp);
7141 break;
7142 case 0x06:
7143 if (set_cc) {
7144 gen_helper_sbc_cc(tmp, tmp, tmp2);
7145 } else {
7146 gen_sub_carry(tmp, tmp, tmp2);
7148 store_reg_bx(env, s, rd, tmp);
7149 break;
7150 case 0x07:
7151 if (set_cc) {
7152 gen_helper_sbc_cc(tmp, tmp2, tmp);
7153 } else {
7154 gen_sub_carry(tmp, tmp2, tmp);
7156 store_reg_bx(env, s, rd, tmp);
7157 break;
7158 case 0x08:
7159 if (set_cc) {
7160 tcg_gen_and_i32(tmp, tmp, tmp2);
7161 gen_logic_CC(tmp);
7163 tcg_temp_free_i32(tmp);
7164 break;
7165 case 0x09:
7166 if (set_cc) {
7167 tcg_gen_xor_i32(tmp, tmp, tmp2);
7168 gen_logic_CC(tmp);
7170 tcg_temp_free_i32(tmp);
7171 break;
7172 case 0x0a:
7173 if (set_cc) {
7174 gen_helper_sub_cc(tmp, tmp, tmp2);
7176 tcg_temp_free_i32(tmp);
7177 break;
7178 case 0x0b:
7179 if (set_cc) {
7180 gen_helper_add_cc(tmp, tmp, tmp2);
7182 tcg_temp_free_i32(tmp);
7183 break;
7184 case 0x0c:
7185 tcg_gen_or_i32(tmp, tmp, tmp2);
7186 if (logic_cc) {
7187 gen_logic_CC(tmp);
7189 store_reg_bx(env, s, rd, tmp);
7190 break;
7191 case 0x0d:
7192 if (logic_cc && rd == 15) {
7193 /* MOVS r15, ... is used for exception return. */
7194 if (IS_USER(s)) {
7195 goto illegal_op;
7197 gen_exception_return(s, tmp2);
7198 } else {
7199 if (logic_cc) {
7200 gen_logic_CC(tmp2);
7202 store_reg_bx(env, s, rd, tmp2);
7204 break;
7205 case 0x0e:
7206 tcg_gen_andc_i32(tmp, tmp, tmp2);
7207 if (logic_cc) {
7208 gen_logic_CC(tmp);
7210 store_reg_bx(env, s, rd, tmp);
7211 break;
7212 default:
7213 case 0x0f:
7214 tcg_gen_not_i32(tmp2, tmp2);
7215 if (logic_cc) {
7216 gen_logic_CC(tmp2);
7218 store_reg_bx(env, s, rd, tmp2);
7219 break;
7221 if (op1 != 0x0f && op1 != 0x0d) {
7222 tcg_temp_free_i32(tmp2);
7224 } else {
7225 /* other instructions */
7226 op1 = (insn >> 24) & 0xf;
7227 switch(op1) {
7228 case 0x0:
7229 case 0x1:
7230 /* multiplies, extra load/stores */
7231 sh = (insn >> 5) & 3;
7232 if (sh == 0) {
7233 if (op1 == 0x0) {
7234 rd = (insn >> 16) & 0xf;
7235 rn = (insn >> 12) & 0xf;
7236 rs = (insn >> 8) & 0xf;
7237 rm = (insn) & 0xf;
7238 op1 = (insn >> 20) & 0xf;
7239 switch (op1) {
7240 case 0: case 1: case 2: case 3: case 6:
7241 /* 32 bit mul */
7242 tmp = load_reg(s, rs);
7243 tmp2 = load_reg(s, rm);
7244 tcg_gen_mul_i32(tmp, tmp, tmp2);
7245 tcg_temp_free_i32(tmp2);
7246 if (insn & (1 << 22)) {
7247 /* Subtract (mls) */
7248 ARCH(6T2);
7249 tmp2 = load_reg(s, rn);
7250 tcg_gen_sub_i32(tmp, tmp2, tmp);
7251 tcg_temp_free_i32(tmp2);
7252 } else if (insn & (1 << 21)) {
7253 /* Add */
7254 tmp2 = load_reg(s, rn);
7255 tcg_gen_add_i32(tmp, tmp, tmp2);
7256 tcg_temp_free_i32(tmp2);
7258 if (insn & (1 << 20))
7259 gen_logic_CC(tmp);
7260 store_reg(s, rd, tmp);
7261 break;
7262 case 4:
7263 /* 64 bit mul double accumulate (UMAAL) */
7264 ARCH(6);
7265 tmp = load_reg(s, rs);
7266 tmp2 = load_reg(s, rm);
7267 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7268 gen_addq_lo(s, tmp64, rn);
7269 gen_addq_lo(s, tmp64, rd);
7270 gen_storeq_reg(s, rn, rd, tmp64);
7271 tcg_temp_free_i64(tmp64);
7272 break;
7273 case 8: case 9: case 10: case 11:
7274 case 12: case 13: case 14: case 15:
7275 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
7276 tmp = load_reg(s, rs);
7277 tmp2 = load_reg(s, rm);
7278 if (insn & (1 << 22)) {
7279 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7280 } else {
7281 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7283 if (insn & (1 << 21)) { /* mult accumulate */
7284 gen_addq(s, tmp64, rn, rd);
7286 if (insn & (1 << 20)) {
7287 gen_logicq_cc(tmp64);
7289 gen_storeq_reg(s, rn, rd, tmp64);
7290 tcg_temp_free_i64(tmp64);
7291 break;
7292 default:
7293 goto illegal_op;
7295 } else {
7296 rn = (insn >> 16) & 0xf;
7297 rd = (insn >> 12) & 0xf;
7298 if (insn & (1 << 23)) {
7299 /* load/store exclusive */
7300 op1 = (insn >> 21) & 0x3;
7301 if (op1)
7302 ARCH(6K);
7303 else
7304 ARCH(6);
7305 addr = tcg_temp_local_new_i32();
7306 load_reg_var(s, addr, rn);
7307 if (insn & (1 << 20)) {
7308 switch (op1) {
7309 case 0: /* ldrex */
7310 gen_load_exclusive(s, rd, 15, addr, 2);
7311 break;
7312 case 1: /* ldrexd */
7313 gen_load_exclusive(s, rd, rd + 1, addr, 3);
7314 break;
7315 case 2: /* ldrexb */
7316 gen_load_exclusive(s, rd, 15, addr, 0);
7317 break;
7318 case 3: /* ldrexh */
7319 gen_load_exclusive(s, rd, 15, addr, 1);
7320 break;
7321 default:
7322 abort();
7324 } else {
7325 rm = insn & 0xf;
7326 switch (op1) {
7327 case 0: /* strex */
7328 gen_store_exclusive(s, rd, rm, 15, addr, 2);
7329 break;
7330 case 1: /* strexd */
7331 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
7332 break;
7333 case 2: /* strexb */
7334 gen_store_exclusive(s, rd, rm, 15, addr, 0);
7335 break;
7336 case 3: /* strexh */
7337 gen_store_exclusive(s, rd, rm, 15, addr, 1);
7338 break;
7339 default:
7340 abort();
7343 tcg_temp_free(addr);
7344 } else {
7345 /* SWP instruction */
7346 rm = (insn) & 0xf;
7348 /* ??? This is not really atomic. However we know
7349 we never have multiple CPUs running in parallel,
7350 so it is good enough. */
7351 addr = load_reg(s, rn);
7352 tmp = load_reg(s, rm);
7353 if (insn & (1 << 22)) {
7354 tmp2 = gen_ld8u(addr, IS_USER(s));
7355 gen_st8(tmp, addr, IS_USER(s));
7356 } else {
7357 tmp2 = gen_ld32(addr, IS_USER(s));
7358 gen_st32(tmp, addr, IS_USER(s));
7360 tcg_temp_free_i32(addr);
7361 store_reg(s, rd, tmp2);
7364 } else {
7365 int address_offset;
7366 int load;
7367 /* Misc load/store */
7368 rn = (insn >> 16) & 0xf;
7369 rd = (insn >> 12) & 0xf;
7370 addr = load_reg(s, rn);
7371 if (insn & (1 << 24))
7372 gen_add_datah_offset(s, insn, 0, addr);
7373 address_offset = 0;
7374 if (insn & (1 << 20)) {
7375 /* load */
7376 switch(sh) {
7377 case 1:
7378 tmp = gen_ld16u(addr, IS_USER(s));
7379 break;
7380 case 2:
7381 tmp = gen_ld8s(addr, IS_USER(s));
7382 break;
7383 default:
7384 case 3:
7385 tmp = gen_ld16s(addr, IS_USER(s));
7386 break;
7388 load = 1;
7389 } else if (sh & 2) {
7390 ARCH(5TE);
7391 /* doubleword */
7392 if (sh & 1) {
7393 /* store */
7394 tmp = load_reg(s, rd);
7395 gen_st32(tmp, addr, IS_USER(s));
7396 tcg_gen_addi_i32(addr, addr, 4);
7397 tmp = load_reg(s, rd + 1);
7398 gen_st32(tmp, addr, IS_USER(s));
7399 load = 0;
7400 } else {
7401 /* load */
7402 tmp = gen_ld32(addr, IS_USER(s));
7403 store_reg(s, rd, tmp);
7404 tcg_gen_addi_i32(addr, addr, 4);
7405 tmp = gen_ld32(addr, IS_USER(s));
7406 rd++;
7407 load = 1;
7409 address_offset = -4;
7410 } else {
7411 /* store */
7412 tmp = load_reg(s, rd);
7413 gen_st16(tmp, addr, IS_USER(s));
7414 load = 0;
7416 /* Perform base writeback before the loaded value to
7417 ensure correct behavior with overlapping index registers.
7418 ldrd with base writeback is is undefined if the
7419 destination and index registers overlap. */
7420 if (!(insn & (1 << 24))) {
7421 gen_add_datah_offset(s, insn, address_offset, addr);
7422 store_reg(s, rn, addr);
7423 } else if (insn & (1 << 21)) {
7424 if (address_offset)
7425 tcg_gen_addi_i32(addr, addr, address_offset);
7426 store_reg(s, rn, addr);
7427 } else {
7428 tcg_temp_free_i32(addr);
7430 if (load) {
7431 /* Complete the load. */
7432 store_reg(s, rd, tmp);
7435 break;
7436 case 0x4:
7437 case 0x5:
7438 goto do_ldst;
7439 case 0x6:
7440 case 0x7:
7441 if (insn & (1 << 4)) {
7442 ARCH(6);
7443 /* Armv6 Media instructions. */
7444 rm = insn & 0xf;
7445 rn = (insn >> 16) & 0xf;
7446 rd = (insn >> 12) & 0xf;
7447 rs = (insn >> 8) & 0xf;
7448 switch ((insn >> 23) & 3) {
7449 case 0: /* Parallel add/subtract. */
7450 op1 = (insn >> 20) & 7;
7451 tmp = load_reg(s, rn);
7452 tmp2 = load_reg(s, rm);
7453 sh = (insn >> 5) & 7;
7454 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
7455 goto illegal_op;
7456 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
7457 tcg_temp_free_i32(tmp2);
7458 store_reg(s, rd, tmp);
7459 break;
7460 case 1:
7461 if ((insn & 0x00700020) == 0) {
7462 /* Halfword pack. */
7463 tmp = load_reg(s, rn);
7464 tmp2 = load_reg(s, rm);
7465 shift = (insn >> 7) & 0x1f;
7466 if (insn & (1 << 6)) {
7467 /* pkhtb */
7468 if (shift == 0)
7469 shift = 31;
7470 tcg_gen_sari_i32(tmp2, tmp2, shift);
7471 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
7472 tcg_gen_ext16u_i32(tmp2, tmp2);
7473 } else {
7474 /* pkhbt */
7475 if (shift)
7476 tcg_gen_shli_i32(tmp2, tmp2, shift);
7477 tcg_gen_ext16u_i32(tmp, tmp);
7478 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
7480 tcg_gen_or_i32(tmp, tmp, tmp2);
7481 tcg_temp_free_i32(tmp2);
7482 store_reg(s, rd, tmp);
7483 } else if ((insn & 0x00200020) == 0x00200000) {
7484 /* [us]sat */
7485 tmp = load_reg(s, rm);
7486 shift = (insn >> 7) & 0x1f;
7487 if (insn & (1 << 6)) {
7488 if (shift == 0)
7489 shift = 31;
7490 tcg_gen_sari_i32(tmp, tmp, shift);
7491 } else {
7492 tcg_gen_shli_i32(tmp, tmp, shift);
7494 sh = (insn >> 16) & 0x1f;
7495 tmp2 = tcg_const_i32(sh);
7496 if (insn & (1 << 22))
7497 gen_helper_usat(tmp, tmp, tmp2);
7498 else
7499 gen_helper_ssat(tmp, tmp, tmp2);
7500 tcg_temp_free_i32(tmp2);
7501 store_reg(s, rd, tmp);
7502 } else if ((insn & 0x00300fe0) == 0x00200f20) {
7503 /* [us]sat16 */
7504 tmp = load_reg(s, rm);
7505 sh = (insn >> 16) & 0x1f;
7506 tmp2 = tcg_const_i32(sh);
7507 if (insn & (1 << 22))
7508 gen_helper_usat16(tmp, tmp, tmp2);
7509 else
7510 gen_helper_ssat16(tmp, tmp, tmp2);
7511 tcg_temp_free_i32(tmp2);
7512 store_reg(s, rd, tmp);
7513 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
7514 /* Select bytes. */
7515 tmp = load_reg(s, rn);
7516 tmp2 = load_reg(s, rm);
7517 tmp3 = tcg_temp_new_i32();
7518 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
7519 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7520 tcg_temp_free_i32(tmp3);
7521 tcg_temp_free_i32(tmp2);
7522 store_reg(s, rd, tmp);
7523 } else if ((insn & 0x000003e0) == 0x00000060) {
7524 tmp = load_reg(s, rm);
7525 shift = (insn >> 10) & 3;
7526 /* ??? In many cases it's not necessary to do a
7527 rotate, a shift is sufficient. */
7528 if (shift != 0)
7529 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
7530 op1 = (insn >> 20) & 7;
7531 switch (op1) {
7532 case 0: gen_sxtb16(tmp); break;
7533 case 2: gen_sxtb(tmp); break;
7534 case 3: gen_sxth(tmp); break;
7535 case 4: gen_uxtb16(tmp); break;
7536 case 6: gen_uxtb(tmp); break;
7537 case 7: gen_uxth(tmp); break;
7538 default: goto illegal_op;
7540 if (rn != 15) {
7541 tmp2 = load_reg(s, rn);
7542 if ((op1 & 3) == 0) {
7543 gen_add16(tmp, tmp2);
7544 } else {
7545 tcg_gen_add_i32(tmp, tmp, tmp2);
7546 tcg_temp_free_i32(tmp2);
7549 store_reg(s, rd, tmp);
7550 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
7551 /* rev */
7552 tmp = load_reg(s, rm);
7553 if (insn & (1 << 22)) {
7554 if (insn & (1 << 7)) {
7555 gen_revsh(tmp);
7556 } else {
7557 ARCH(6T2);
7558 gen_helper_rbit(tmp, tmp);
7560 } else {
7561 if (insn & (1 << 7))
7562 gen_rev16(tmp);
7563 else
7564 tcg_gen_bswap32_i32(tmp, tmp);
7566 store_reg(s, rd, tmp);
7567 } else {
7568 goto illegal_op;
7570 break;
7571 case 2: /* Multiplies (Type 3). */
7572 tmp = load_reg(s, rm);
7573 tmp2 = load_reg(s, rs);
7574 if (insn & (1 << 20)) {
7575 /* Signed multiply most significant [accumulate].
7576 (SMMUL, SMMLA, SMMLS) */
7577 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7579 if (rd != 15) {
7580 tmp = load_reg(s, rd);
7581 if (insn & (1 << 6)) {
7582 tmp64 = gen_subq_msw(tmp64, tmp);
7583 } else {
7584 tmp64 = gen_addq_msw(tmp64, tmp);
7587 if (insn & (1 << 5)) {
7588 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
7590 tcg_gen_shri_i64(tmp64, tmp64, 32);
7591 tmp = tcg_temp_new_i32();
7592 tcg_gen_trunc_i64_i32(tmp, tmp64);
7593 tcg_temp_free_i64(tmp64);
7594 store_reg(s, rn, tmp);
7595 } else {
7596 if (insn & (1 << 5))
7597 gen_swap_half(tmp2);
7598 gen_smul_dual(tmp, tmp2);
7599 if (insn & (1 << 6)) {
7600 /* This subtraction cannot overflow. */
7601 tcg_gen_sub_i32(tmp, tmp, tmp2);
7602 } else {
7603 /* This addition cannot overflow 32 bits;
7604 * however it may overflow considered as a signed
7605 * operation, in which case we must set the Q flag.
7607 gen_helper_add_setq(tmp, tmp, tmp2);
7609 tcg_temp_free_i32(tmp2);
7610 if (insn & (1 << 22)) {
7611 /* smlald, smlsld */
7612 tmp64 = tcg_temp_new_i64();
7613 tcg_gen_ext_i32_i64(tmp64, tmp);
7614 tcg_temp_free_i32(tmp);
7615 gen_addq(s, tmp64, rd, rn);
7616 gen_storeq_reg(s, rd, rn, tmp64);
7617 tcg_temp_free_i64(tmp64);
7618 } else {
7619 /* smuad, smusd, smlad, smlsd */
7620 if (rd != 15)
7622 tmp2 = load_reg(s, rd);
7623 gen_helper_add_setq(tmp, tmp, tmp2);
7624 tcg_temp_free_i32(tmp2);
7626 store_reg(s, rn, tmp);
7629 break;
7630 case 3:
7631 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
7632 switch (op1) {
7633 case 0: /* Unsigned sum of absolute differences. */
7634 ARCH(6);
7635 tmp = load_reg(s, rm);
7636 tmp2 = load_reg(s, rs);
7637 gen_helper_usad8(tmp, tmp, tmp2);
7638 tcg_temp_free_i32(tmp2);
7639 if (rd != 15) {
7640 tmp2 = load_reg(s, rd);
7641 tcg_gen_add_i32(tmp, tmp, tmp2);
7642 tcg_temp_free_i32(tmp2);
7644 store_reg(s, rn, tmp);
7645 break;
7646 case 0x20: case 0x24: case 0x28: case 0x2c:
7647 /* Bitfield insert/clear. */
7648 ARCH(6T2);
7649 shift = (insn >> 7) & 0x1f;
7650 i = (insn >> 16) & 0x1f;
7651 i = i + 1 - shift;
7652 if (rm == 15) {
7653 tmp = tcg_temp_new_i32();
7654 tcg_gen_movi_i32(tmp, 0);
7655 } else {
7656 tmp = load_reg(s, rm);
7658 if (i != 32) {
7659 tmp2 = load_reg(s, rd);
7660 gen_bfi(tmp, tmp2, tmp, shift, (1u << i) - 1);
7661 tcg_temp_free_i32(tmp2);
7663 store_reg(s, rd, tmp);
7664 break;
7665 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
7666 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
7667 ARCH(6T2);
7668 tmp = load_reg(s, rm);
7669 shift = (insn >> 7) & 0x1f;
7670 i = ((insn >> 16) & 0x1f) + 1;
7671 if (shift + i > 32)
7672 goto illegal_op;
7673 if (i < 32) {
7674 if (op1 & 0x20) {
7675 gen_ubfx(tmp, shift, (1u << i) - 1);
7676 } else {
7677 gen_sbfx(tmp, shift, i);
7680 store_reg(s, rd, tmp);
7681 break;
7682 default:
7683 goto illegal_op;
7685 break;
7687 break;
7689 do_ldst:
7690 /* Check for undefined extension instructions
7691 * per the ARM Bible IE:
7692 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
7694 sh = (0xf << 20) | (0xf << 4);
7695 if (op1 == 0x7 && ((insn & sh) == sh))
7697 goto illegal_op;
7699 /* load/store byte/word */
7700 rn = (insn >> 16) & 0xf;
7701 rd = (insn >> 12) & 0xf;
7702 tmp2 = load_reg(s, rn);
7703 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
7704 if (insn & (1 << 24))
7705 gen_add_data_offset(s, insn, tmp2);
7706 if (insn & (1 << 20)) {
7707 /* load */
7708 if (insn & (1 << 22)) {
7709 tmp = gen_ld8u(tmp2, i);
7710 } else {
7711 tmp = gen_ld32(tmp2, i);
7713 } else {
7714 /* store */
7715 tmp = load_reg(s, rd);
7716 if (insn & (1 << 22))
7717 gen_st8(tmp, tmp2, i);
7718 else
7719 gen_st32(tmp, tmp2, i);
7721 if (!(insn & (1 << 24))) {
7722 gen_add_data_offset(s, insn, tmp2);
7723 store_reg(s, rn, tmp2);
7724 } else if (insn & (1 << 21)) {
7725 store_reg(s, rn, tmp2);
7726 } else {
7727 tcg_temp_free_i32(tmp2);
7729 if (insn & (1 << 20)) {
7730 /* Complete the load. */
7731 store_reg_from_load(env, s, rd, tmp);
7733 break;
7734 case 0x08:
7735 case 0x09:
7737 int j, n, user, loaded_base;
7738 TCGv loaded_var;
7739 /* load/store multiple words */
7740 /* XXX: store correct base if write back */
7741 user = 0;
7742 if (insn & (1 << 22)) {
7743 if (IS_USER(s))
7744 goto illegal_op; /* only usable in supervisor mode */
7746 if ((insn & (1 << 15)) == 0)
7747 user = 1;
7749 rn = (insn >> 16) & 0xf;
7750 addr = load_reg(s, rn);
7752 /* compute total size */
7753 loaded_base = 0;
7754 TCGV_UNUSED(loaded_var);
7755 n = 0;
7756 for(i=0;i<16;i++) {
7757 if (insn & (1 << i))
7758 n++;
7760 /* XXX: test invalid n == 0 case ? */
7761 if (insn & (1 << 23)) {
7762 if (insn & (1 << 24)) {
7763 /* pre increment */
7764 tcg_gen_addi_i32(addr, addr, 4);
7765 } else {
7766 /* post increment */
7768 } else {
7769 if (insn & (1 << 24)) {
7770 /* pre decrement */
7771 tcg_gen_addi_i32(addr, addr, -(n * 4));
7772 } else {
7773 /* post decrement */
7774 if (n != 1)
7775 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7778 j = 0;
7779 for(i=0;i<16;i++) {
7780 if (insn & (1 << i)) {
7781 if (insn & (1 << 20)) {
7782 /* load */
7783 tmp = gen_ld32(addr, IS_USER(s));
7784 if (user) {
7785 tmp2 = tcg_const_i32(i);
7786 gen_helper_set_user_reg(tmp2, tmp);
7787 tcg_temp_free_i32(tmp2);
7788 tcg_temp_free_i32(tmp);
7789 } else if (i == rn) {
7790 loaded_var = tmp;
7791 loaded_base = 1;
7792 } else {
7793 store_reg_from_load(env, s, i, tmp);
7795 } else {
7796 /* store */
7797 if (i == 15) {
7798 /* special case: r15 = PC + 8 */
7799 val = (long)s->pc + 4;
7800 tmp = tcg_temp_new_i32();
7801 tcg_gen_movi_i32(tmp, val);
7802 } else if (user) {
7803 tmp = tcg_temp_new_i32();
7804 tmp2 = tcg_const_i32(i);
7805 gen_helper_get_user_reg(tmp, tmp2);
7806 tcg_temp_free_i32(tmp2);
7807 } else {
7808 tmp = load_reg(s, i);
7810 gen_st32(tmp, addr, IS_USER(s));
7812 j++;
7813 /* no need to add after the last transfer */
7814 if (j != n)
7815 tcg_gen_addi_i32(addr, addr, 4);
7818 if (insn & (1 << 21)) {
7819 /* write back */
7820 if (insn & (1 << 23)) {
7821 if (insn & (1 << 24)) {
7822 /* pre increment */
7823 } else {
7824 /* post increment */
7825 tcg_gen_addi_i32(addr, addr, 4);
7827 } else {
7828 if (insn & (1 << 24)) {
7829 /* pre decrement */
7830 if (n != 1)
7831 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
7832 } else {
7833 /* post decrement */
7834 tcg_gen_addi_i32(addr, addr, -(n * 4));
7837 store_reg(s, rn, addr);
7838 } else {
7839 tcg_temp_free_i32(addr);
7841 if (loaded_base) {
7842 store_reg(s, rn, loaded_var);
7844 if ((insn & (1 << 22)) && !user) {
7845 /* Restore CPSR from SPSR. */
7846 tmp = load_cpu_field(spsr);
7847 gen_set_cpsr(tmp, 0xffffffff);
7848 tcg_temp_free_i32(tmp);
7849 s->is_jmp = DISAS_UPDATE;
7852 break;
7853 case 0xa:
7854 case 0xb:
7856 int32_t offset;
7858 /* branch (and link) */
7859 val = (int32_t)s->pc;
7860 if (insn & (1 << 24)) {
7861 tmp = tcg_temp_new_i32();
7862 tcg_gen_movi_i32(tmp, val);
7863 store_reg(s, 14, tmp);
7865 offset = (((int32_t)insn << 8) >> 8);
7866 val += (offset << 2) + 4;
7867 gen_jmp(s, val);
7869 break;
7870 case 0xc:
7871 case 0xd:
7872 case 0xe:
7873 /* Coprocessor. */
7874 if (disas_coproc_insn(env, s, insn))
7875 goto illegal_op;
7876 break;
7877 case 0xf:
7878 /* swi */
7879 gen_set_pc_im(s->pc);
7880 s->is_jmp = DISAS_SWI;
7881 break;
7882 default:
7883 illegal_op:
7884 gen_exception_insn(s, 4, EXCP_UDEF);
7885 break;
7890 /* Return true if this is a Thumb-2 logical op. */
7891 static int
7892 thumb2_logic_op(int op)
7894 return (op < 8);
7897 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7898 then set condition code flags based on the result of the operation.
7899 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7900 to the high bit of T1.
7901 Returns zero if the opcode is valid. */
7903 static int
7904 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out, TCGv t0, TCGv t1)
7906 int logic_cc;
7908 logic_cc = 0;
7909 switch (op) {
7910 case 0: /* and */
7911 tcg_gen_and_i32(t0, t0, t1);
7912 logic_cc = conds;
7913 break;
7914 case 1: /* bic */
7915 tcg_gen_andc_i32(t0, t0, t1);
7916 logic_cc = conds;
7917 break;
7918 case 2: /* orr */
7919 tcg_gen_or_i32(t0, t0, t1);
7920 logic_cc = conds;
7921 break;
7922 case 3: /* orn */
7923 tcg_gen_orc_i32(t0, t0, t1);
7924 logic_cc = conds;
7925 break;
7926 case 4: /* eor */
7927 tcg_gen_xor_i32(t0, t0, t1);
7928 logic_cc = conds;
7929 break;
7930 case 8: /* add */
7931 if (conds)
7932 gen_helper_add_cc(t0, t0, t1);
7933 else
7934 tcg_gen_add_i32(t0, t0, t1);
7935 break;
7936 case 10: /* adc */
7937 if (conds)
7938 gen_helper_adc_cc(t0, t0, t1);
7939 else
7940 gen_adc(t0, t1);
7941 break;
7942 case 11: /* sbc */
7943 if (conds)
7944 gen_helper_sbc_cc(t0, t0, t1);
7945 else
7946 gen_sub_carry(t0, t0, t1);
7947 break;
7948 case 13: /* sub */
7949 if (conds)
7950 gen_helper_sub_cc(t0, t0, t1);
7951 else
7952 tcg_gen_sub_i32(t0, t0, t1);
7953 break;
7954 case 14: /* rsb */
7955 if (conds)
7956 gen_helper_sub_cc(t0, t1, t0);
7957 else
7958 tcg_gen_sub_i32(t0, t1, t0);
7959 break;
7960 default: /* 5, 6, 7, 9, 12, 15. */
7961 return 1;
7963 if (logic_cc) {
7964 gen_logic_CC(t0);
7965 if (shifter_out)
7966 gen_set_CF_bit31(t1);
7968 return 0;
7971 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7972 is not legal. */
7973 static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7975 uint32_t insn, imm, shift, offset;
7976 uint32_t rd, rn, rm, rs;
7977 TCGv tmp;
7978 TCGv tmp2;
7979 TCGv tmp3;
7980 TCGv addr;
7981 TCGv_i64 tmp64;
7982 int op;
7983 int shiftop;
7984 int conds;
7985 int logic_cc;
7987 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
7988 || arm_feature (env, ARM_FEATURE_M))) {
7989 /* Thumb-1 cores may need to treat bl and blx as a pair of
7990 16-bit instructions to get correct prefetch abort behavior. */
7991 insn = insn_hw1;
7992 if ((insn & (1 << 12)) == 0) {
7993 ARCH(5);
7994 /* Second half of blx. */
7995 offset = ((insn & 0x7ff) << 1);
7996 tmp = load_reg(s, 14);
7997 tcg_gen_addi_i32(tmp, tmp, offset);
7998 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
8000 tmp2 = tcg_temp_new_i32();
8001 tcg_gen_movi_i32(tmp2, s->pc | 1);
8002 store_reg(s, 14, tmp2);
8003 gen_bx(s, tmp);
8004 return 0;
8006 if (insn & (1 << 11)) {
8007 /* Second half of bl. */
8008 offset = ((insn & 0x7ff) << 1) | 1;
8009 tmp = load_reg(s, 14);
8010 tcg_gen_addi_i32(tmp, tmp, offset);
8012 tmp2 = tcg_temp_new_i32();
8013 tcg_gen_movi_i32(tmp2, s->pc | 1);
8014 store_reg(s, 14, tmp2);
8015 gen_bx(s, tmp);
8016 return 0;
8018 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
8019 /* Instruction spans a page boundary. Implement it as two
8020 16-bit instructions in case the second half causes an
8021 prefetch abort. */
8022 offset = ((int32_t)insn << 21) >> 9;
8023 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
8024 return 0;
8026 /* Fall through to 32-bit decode. */
8029 insn = lduw_code(s->pc);
8030 s->pc += 2;
8031 insn |= (uint32_t)insn_hw1 << 16;
8033 if ((insn & 0xf800e800) != 0xf000e800) {
8034 ARCH(6T2);
8037 rn = (insn >> 16) & 0xf;
8038 rs = (insn >> 12) & 0xf;
8039 rd = (insn >> 8) & 0xf;
8040 rm = insn & 0xf;
8041 switch ((insn >> 25) & 0xf) {
8042 case 0: case 1: case 2: case 3:
8043 /* 16-bit instructions. Should never happen. */
8044 abort();
8045 case 4:
8046 if (insn & (1 << 22)) {
8047 /* Other load/store, table branch. */
8048 if (insn & 0x01200000) {
8049 /* Load/store doubleword. */
8050 if (rn == 15) {
8051 addr = tcg_temp_new_i32();
8052 tcg_gen_movi_i32(addr, s->pc & ~3);
8053 } else {
8054 addr = load_reg(s, rn);
8056 offset = (insn & 0xff) * 4;
8057 if ((insn & (1 << 23)) == 0)
8058 offset = -offset;
8059 if (insn & (1 << 24)) {
8060 tcg_gen_addi_i32(addr, addr, offset);
8061 offset = 0;
8063 if (insn & (1 << 20)) {
8064 /* ldrd */
8065 tmp = gen_ld32(addr, IS_USER(s));
8066 store_reg(s, rs, tmp);
8067 tcg_gen_addi_i32(addr, addr, 4);
8068 tmp = gen_ld32(addr, IS_USER(s));
8069 store_reg(s, rd, tmp);
8070 } else {
8071 /* strd */
8072 tmp = load_reg(s, rs);
8073 gen_st32(tmp, addr, IS_USER(s));
8074 tcg_gen_addi_i32(addr, addr, 4);
8075 tmp = load_reg(s, rd);
8076 gen_st32(tmp, addr, IS_USER(s));
8078 if (insn & (1 << 21)) {
8079 /* Base writeback. */
8080 if (rn == 15)
8081 goto illegal_op;
8082 tcg_gen_addi_i32(addr, addr, offset - 4);
8083 store_reg(s, rn, addr);
8084 } else {
8085 tcg_temp_free_i32(addr);
8087 } else if ((insn & (1 << 23)) == 0) {
8088 /* Load/store exclusive word. */
8089 addr = tcg_temp_local_new();
8090 load_reg_var(s, addr, rn);
8091 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
8092 if (insn & (1 << 20)) {
8093 gen_load_exclusive(s, rs, 15, addr, 2);
8094 } else {
8095 gen_store_exclusive(s, rd, rs, 15, addr, 2);
8097 tcg_temp_free(addr);
8098 } else if ((insn & (1 << 6)) == 0) {
8099 /* Table Branch. */
8100 if (rn == 15) {
8101 addr = tcg_temp_new_i32();
8102 tcg_gen_movi_i32(addr, s->pc);
8103 } else {
8104 addr = load_reg(s, rn);
8106 tmp = load_reg(s, rm);
8107 tcg_gen_add_i32(addr, addr, tmp);
8108 if (insn & (1 << 4)) {
8109 /* tbh */
8110 tcg_gen_add_i32(addr, addr, tmp);
8111 tcg_temp_free_i32(tmp);
8112 tmp = gen_ld16u(addr, IS_USER(s));
8113 } else { /* tbb */
8114 tcg_temp_free_i32(tmp);
8115 tmp = gen_ld8u(addr, IS_USER(s));
8117 tcg_temp_free_i32(addr);
8118 tcg_gen_shli_i32(tmp, tmp, 1);
8119 tcg_gen_addi_i32(tmp, tmp, s->pc);
8120 store_reg(s, 15, tmp);
8121 } else {
8122 /* Load/store exclusive byte/halfword/doubleword. */
8123 ARCH(7);
8124 op = (insn >> 4) & 0x3;
8125 if (op == 2) {
8126 goto illegal_op;
8128 addr = tcg_temp_local_new();
8129 load_reg_var(s, addr, rn);
8130 if (insn & (1 << 20)) {
8131 gen_load_exclusive(s, rs, rd, addr, op);
8132 } else {
8133 gen_store_exclusive(s, rm, rs, rd, addr, op);
8135 tcg_temp_free(addr);
8137 } else {
8138 /* Load/store multiple, RFE, SRS. */
8139 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
8140 /* Not available in user mode. */
8141 if (IS_USER(s))
8142 goto illegal_op;
8143 if (insn & (1 << 20)) {
8144 /* rfe */
8145 addr = load_reg(s, rn);
8146 if ((insn & (1 << 24)) == 0)
8147 tcg_gen_addi_i32(addr, addr, -8);
8148 /* Load PC into tmp and CPSR into tmp2. */
8149 tmp = gen_ld32(addr, 0);
8150 tcg_gen_addi_i32(addr, addr, 4);
8151 tmp2 = gen_ld32(addr, 0);
8152 if (insn & (1 << 21)) {
8153 /* Base writeback. */
8154 if (insn & (1 << 24)) {
8155 tcg_gen_addi_i32(addr, addr, 4);
8156 } else {
8157 tcg_gen_addi_i32(addr, addr, -4);
8159 store_reg(s, rn, addr);
8160 } else {
8161 tcg_temp_free_i32(addr);
8163 gen_rfe(s, tmp, tmp2);
8164 } else {
8165 /* srs */
8166 op = (insn & 0x1f);
8167 addr = tcg_temp_new_i32();
8168 tmp = tcg_const_i32(op);
8169 gen_helper_get_r13_banked(addr, cpu_env, tmp);
8170 tcg_temp_free_i32(tmp);
8171 if ((insn & (1 << 24)) == 0) {
8172 tcg_gen_addi_i32(addr, addr, -8);
8174 tmp = load_reg(s, 14);
8175 gen_st32(tmp, addr, 0);
8176 tcg_gen_addi_i32(addr, addr, 4);
8177 tmp = tcg_temp_new_i32();
8178 gen_helper_cpsr_read(tmp);
8179 gen_st32(tmp, addr, 0);
8180 if (insn & (1 << 21)) {
8181 if ((insn & (1 << 24)) == 0) {
8182 tcg_gen_addi_i32(addr, addr, -4);
8183 } else {
8184 tcg_gen_addi_i32(addr, addr, 4);
8186 tmp = tcg_const_i32(op);
8187 gen_helper_set_r13_banked(cpu_env, tmp, addr);
8188 tcg_temp_free_i32(tmp);
8189 } else {
8190 tcg_temp_free_i32(addr);
8193 } else {
8194 int i, loaded_base = 0;
8195 TCGv loaded_var;
8196 /* Load/store multiple. */
8197 addr = load_reg(s, rn);
8198 offset = 0;
8199 for (i = 0; i < 16; i++) {
8200 if (insn & (1 << i))
8201 offset += 4;
8203 if (insn & (1 << 24)) {
8204 tcg_gen_addi_i32(addr, addr, -offset);
8207 TCGV_UNUSED(loaded_var);
8208 for (i = 0; i < 16; i++) {
8209 if ((insn & (1 << i)) == 0)
8210 continue;
8211 if (insn & (1 << 20)) {
8212 /* Load. */
8213 tmp = gen_ld32(addr, IS_USER(s));
8214 if (i == 15) {
8215 gen_bx(s, tmp);
8216 } else if (i == rn) {
8217 loaded_var = tmp;
8218 loaded_base = 1;
8219 } else {
8220 store_reg(s, i, tmp);
8222 } else {
8223 /* Store. */
8224 tmp = load_reg(s, i);
8225 gen_st32(tmp, addr, IS_USER(s));
8227 tcg_gen_addi_i32(addr, addr, 4);
8229 if (loaded_base) {
8230 store_reg(s, rn, loaded_var);
8232 if (insn & (1 << 21)) {
8233 /* Base register writeback. */
8234 if (insn & (1 << 24)) {
8235 tcg_gen_addi_i32(addr, addr, -offset);
8237 /* Fault if writeback register is in register list. */
8238 if (insn & (1 << rn))
8239 goto illegal_op;
8240 store_reg(s, rn, addr);
8241 } else {
8242 tcg_temp_free_i32(addr);
8246 break;
8247 case 5:
8249 op = (insn >> 21) & 0xf;
8250 if (op == 6) {
8251 /* Halfword pack. */
8252 tmp = load_reg(s, rn);
8253 tmp2 = load_reg(s, rm);
8254 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
8255 if (insn & (1 << 5)) {
8256 /* pkhtb */
8257 if (shift == 0)
8258 shift = 31;
8259 tcg_gen_sari_i32(tmp2, tmp2, shift);
8260 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
8261 tcg_gen_ext16u_i32(tmp2, tmp2);
8262 } else {
8263 /* pkhbt */
8264 if (shift)
8265 tcg_gen_shli_i32(tmp2, tmp2, shift);
8266 tcg_gen_ext16u_i32(tmp, tmp);
8267 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
8269 tcg_gen_or_i32(tmp, tmp, tmp2);
8270 tcg_temp_free_i32(tmp2);
8271 store_reg(s, rd, tmp);
8272 } else {
8273 /* Data processing register constant shift. */
8274 if (rn == 15) {
8275 tmp = tcg_temp_new_i32();
8276 tcg_gen_movi_i32(tmp, 0);
8277 } else {
8278 tmp = load_reg(s, rn);
8280 tmp2 = load_reg(s, rm);
8282 shiftop = (insn >> 4) & 3;
8283 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
8284 conds = (insn & (1 << 20)) != 0;
8285 logic_cc = (conds && thumb2_logic_op(op));
8286 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
8287 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
8288 goto illegal_op;
8289 tcg_temp_free_i32(tmp2);
8290 if (rd != 15) {
8291 store_reg(s, rd, tmp);
8292 } else {
8293 tcg_temp_free_i32(tmp);
8296 break;
8297 case 13: /* Misc data processing. */
8298 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
8299 if (op < 4 && (insn & 0xf000) != 0xf000)
8300 goto illegal_op;
8301 switch (op) {
8302 case 0: /* Register controlled shift. */
8303 tmp = load_reg(s, rn);
8304 tmp2 = load_reg(s, rm);
8305 if ((insn & 0x70) != 0)
8306 goto illegal_op;
8307 op = (insn >> 21) & 3;
8308 logic_cc = (insn & (1 << 20)) != 0;
8309 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
8310 if (logic_cc)
8311 gen_logic_CC(tmp);
8312 store_reg_bx(env, s, rd, tmp);
8313 break;
8314 case 1: /* Sign/zero extend. */
8315 tmp = load_reg(s, rm);
8316 shift = (insn >> 4) & 3;
8317 /* ??? In many cases it's not necessary to do a
8318 rotate, a shift is sufficient. */
8319 if (shift != 0)
8320 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
8321 op = (insn >> 20) & 7;
8322 switch (op) {
8323 case 0: gen_sxth(tmp); break;
8324 case 1: gen_uxth(tmp); break;
8325 case 2: gen_sxtb16(tmp); break;
8326 case 3: gen_uxtb16(tmp); break;
8327 case 4: gen_sxtb(tmp); break;
8328 case 5: gen_uxtb(tmp); break;
8329 default: goto illegal_op;
8331 if (rn != 15) {
8332 tmp2 = load_reg(s, rn);
8333 if ((op >> 1) == 1) {
8334 gen_add16(tmp, tmp2);
8335 } else {
8336 tcg_gen_add_i32(tmp, tmp, tmp2);
8337 tcg_temp_free_i32(tmp2);
8340 store_reg(s, rd, tmp);
8341 break;
8342 case 2: /* SIMD add/subtract. */
8343 op = (insn >> 20) & 7;
8344 shift = (insn >> 4) & 7;
8345 if ((op & 3) == 3 || (shift & 3) == 3)
8346 goto illegal_op;
8347 tmp = load_reg(s, rn);
8348 tmp2 = load_reg(s, rm);
8349 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
8350 tcg_temp_free_i32(tmp2);
8351 store_reg(s, rd, tmp);
8352 break;
8353 case 3: /* Other data processing. */
8354 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
8355 if (op < 4) {
8356 /* Saturating add/subtract. */
8357 tmp = load_reg(s, rn);
8358 tmp2 = load_reg(s, rm);
8359 if (op & 1)
8360 gen_helper_double_saturate(tmp, tmp);
8361 if (op & 2)
8362 gen_helper_sub_saturate(tmp, tmp2, tmp);
8363 else
8364 gen_helper_add_saturate(tmp, tmp, tmp2);
8365 tcg_temp_free_i32(tmp2);
8366 } else {
8367 tmp = load_reg(s, rn);
8368 switch (op) {
8369 case 0x0a: /* rbit */
8370 gen_helper_rbit(tmp, tmp);
8371 break;
8372 case 0x08: /* rev */
8373 tcg_gen_bswap32_i32(tmp, tmp);
8374 break;
8375 case 0x09: /* rev16 */
8376 gen_rev16(tmp);
8377 break;
8378 case 0x0b: /* revsh */
8379 gen_revsh(tmp);
8380 break;
8381 case 0x10: /* sel */
8382 tmp2 = load_reg(s, rm);
8383 tmp3 = tcg_temp_new_i32();
8384 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE));
8385 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
8386 tcg_temp_free_i32(tmp3);
8387 tcg_temp_free_i32(tmp2);
8388 break;
8389 case 0x18: /* clz */
8390 gen_helper_clz(tmp, tmp);
8391 break;
8392 default:
8393 goto illegal_op;
8396 store_reg(s, rd, tmp);
8397 break;
8398 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
8399 op = (insn >> 4) & 0xf;
8400 tmp = load_reg(s, rn);
8401 tmp2 = load_reg(s, rm);
8402 switch ((insn >> 20) & 7) {
8403 case 0: /* 32 x 32 -> 32 */
8404 tcg_gen_mul_i32(tmp, tmp, tmp2);
8405 tcg_temp_free_i32(tmp2);
8406 if (rs != 15) {
8407 tmp2 = load_reg(s, rs);
8408 if (op)
8409 tcg_gen_sub_i32(tmp, tmp2, tmp);
8410 else
8411 tcg_gen_add_i32(tmp, tmp, tmp2);
8412 tcg_temp_free_i32(tmp2);
8414 break;
8415 case 1: /* 16 x 16 -> 32 */
8416 gen_mulxy(tmp, tmp2, op & 2, op & 1);
8417 tcg_temp_free_i32(tmp2);
8418 if (rs != 15) {
8419 tmp2 = load_reg(s, rs);
8420 gen_helper_add_setq(tmp, tmp, tmp2);
8421 tcg_temp_free_i32(tmp2);
8423 break;
8424 case 2: /* Dual multiply add. */
8425 case 4: /* Dual multiply subtract. */
8426 if (op)
8427 gen_swap_half(tmp2);
8428 gen_smul_dual(tmp, tmp2);
8429 if (insn & (1 << 22)) {
8430 /* This subtraction cannot overflow. */
8431 tcg_gen_sub_i32(tmp, tmp, tmp2);
8432 } else {
8433 /* This addition cannot overflow 32 bits;
8434 * however it may overflow considered as a signed
8435 * operation, in which case we must set the Q flag.
8437 gen_helper_add_setq(tmp, tmp, tmp2);
8439 tcg_temp_free_i32(tmp2);
8440 if (rs != 15)
8442 tmp2 = load_reg(s, rs);
8443 gen_helper_add_setq(tmp, tmp, tmp2);
8444 tcg_temp_free_i32(tmp2);
8446 break;
8447 case 3: /* 32 * 16 -> 32msb */
8448 if (op)
8449 tcg_gen_sari_i32(tmp2, tmp2, 16);
8450 else
8451 gen_sxth(tmp2);
8452 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8453 tcg_gen_shri_i64(tmp64, tmp64, 16);
8454 tmp = tcg_temp_new_i32();
8455 tcg_gen_trunc_i64_i32(tmp, tmp64);
8456 tcg_temp_free_i64(tmp64);
8457 if (rs != 15)
8459 tmp2 = load_reg(s, rs);
8460 gen_helper_add_setq(tmp, tmp, tmp2);
8461 tcg_temp_free_i32(tmp2);
8463 break;
8464 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
8465 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8466 if (rs != 15) {
8467 tmp = load_reg(s, rs);
8468 if (insn & (1 << 20)) {
8469 tmp64 = gen_addq_msw(tmp64, tmp);
8470 } else {
8471 tmp64 = gen_subq_msw(tmp64, tmp);
8474 if (insn & (1 << 4)) {
8475 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
8477 tcg_gen_shri_i64(tmp64, tmp64, 32);
8478 tmp = tcg_temp_new_i32();
8479 tcg_gen_trunc_i64_i32(tmp, tmp64);
8480 tcg_temp_free_i64(tmp64);
8481 break;
8482 case 7: /* Unsigned sum of absolute differences. */
8483 gen_helper_usad8(tmp, tmp, tmp2);
8484 tcg_temp_free_i32(tmp2);
8485 if (rs != 15) {
8486 tmp2 = load_reg(s, rs);
8487 tcg_gen_add_i32(tmp, tmp, tmp2);
8488 tcg_temp_free_i32(tmp2);
8490 break;
8492 store_reg(s, rd, tmp);
8493 break;
8494 case 6: case 7: /* 64-bit multiply, Divide. */
8495 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
8496 tmp = load_reg(s, rn);
8497 tmp2 = load_reg(s, rm);
8498 if ((op & 0x50) == 0x10) {
8499 /* sdiv, udiv */
8500 if (!arm_feature(env, ARM_FEATURE_DIV))
8501 goto illegal_op;
8502 if (op & 0x20)
8503 gen_helper_udiv(tmp, tmp, tmp2);
8504 else
8505 gen_helper_sdiv(tmp, tmp, tmp2);
8506 tcg_temp_free_i32(tmp2);
8507 store_reg(s, rd, tmp);
8508 } else if ((op & 0xe) == 0xc) {
8509 /* Dual multiply accumulate long. */
8510 if (op & 1)
8511 gen_swap_half(tmp2);
8512 gen_smul_dual(tmp, tmp2);
8513 if (op & 0x10) {
8514 tcg_gen_sub_i32(tmp, tmp, tmp2);
8515 } else {
8516 tcg_gen_add_i32(tmp, tmp, tmp2);
8518 tcg_temp_free_i32(tmp2);
8519 /* BUGFIX */
8520 tmp64 = tcg_temp_new_i64();
8521 tcg_gen_ext_i32_i64(tmp64, tmp);
8522 tcg_temp_free_i32(tmp);
8523 gen_addq(s, tmp64, rs, rd);
8524 gen_storeq_reg(s, rs, rd, tmp64);
8525 tcg_temp_free_i64(tmp64);
8526 } else {
8527 if (op & 0x20) {
8528 /* Unsigned 64-bit multiply */
8529 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
8530 } else {
8531 if (op & 8) {
8532 /* smlalxy */
8533 gen_mulxy(tmp, tmp2, op & 2, op & 1);
8534 tcg_temp_free_i32(tmp2);
8535 tmp64 = tcg_temp_new_i64();
8536 tcg_gen_ext_i32_i64(tmp64, tmp);
8537 tcg_temp_free_i32(tmp);
8538 } else {
8539 /* Signed 64-bit multiply */
8540 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8543 if (op & 4) {
8544 /* umaal */
8545 gen_addq_lo(s, tmp64, rs);
8546 gen_addq_lo(s, tmp64, rd);
8547 } else if (op & 0x40) {
8548 /* 64-bit accumulate. */
8549 gen_addq(s, tmp64, rs, rd);
8551 gen_storeq_reg(s, rs, rd, tmp64);
8552 tcg_temp_free_i64(tmp64);
8554 break;
8556 break;
8557 case 6: case 7: case 14: case 15:
8558 /* Coprocessor. */
8559 if (((insn >> 24) & 3) == 3) {
8560 /* Translate into the equivalent ARM encoding. */
8561 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
8562 if (disas_neon_data_insn(env, s, insn))
8563 goto illegal_op;
8564 } else {
8565 if (insn & (1 << 28))
8566 goto illegal_op;
8567 if (disas_coproc_insn (env, s, insn))
8568 goto illegal_op;
8570 break;
8571 case 8: case 9: case 10: case 11:
8572 if (insn & (1 << 15)) {
8573 /* Branches, misc control. */
8574 if (insn & 0x5000) {
8575 /* Unconditional branch. */
8576 /* signextend(hw1[10:0]) -> offset[:12]. */
8577 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
8578 /* hw1[10:0] -> offset[11:1]. */
8579 offset |= (insn & 0x7ff) << 1;
8580 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
8581 offset[24:22] already have the same value because of the
8582 sign extension above. */
8583 offset ^= ((~insn) & (1 << 13)) << 10;
8584 offset ^= ((~insn) & (1 << 11)) << 11;
8586 if (insn & (1 << 14)) {
8587 /* Branch and link. */
8588 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
8591 offset += s->pc;
8592 if (insn & (1 << 12)) {
8593 /* b/bl */
8594 gen_jmp(s, offset);
8595 } else {
8596 /* blx */
8597 offset &= ~(uint32_t)2;
8598 /* thumb2 bx, no need to check */
8599 gen_bx_im(s, offset);
8601 } else if (((insn >> 23) & 7) == 7) {
8602 /* Misc control */
8603 if (insn & (1 << 13))
8604 goto illegal_op;
8606 if (insn & (1 << 26)) {
8607 /* Secure monitor call (v6Z) */
8608 goto illegal_op; /* not implemented. */
8609 } else {
8610 op = (insn >> 20) & 7;
8611 switch (op) {
8612 case 0: /* msr cpsr. */
8613 if (IS_M(env)) {
8614 tmp = load_reg(s, rn);
8615 addr = tcg_const_i32(insn & 0xff);
8616 gen_helper_v7m_msr(cpu_env, addr, tmp);
8617 tcg_temp_free_i32(addr);
8618 tcg_temp_free_i32(tmp);
8619 gen_lookup_tb(s);
8620 break;
8622 /* fall through */
8623 case 1: /* msr spsr. */
8624 if (IS_M(env))
8625 goto illegal_op;
8626 tmp = load_reg(s, rn);
8627 if (gen_set_psr(s,
8628 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
8629 op == 1, tmp))
8630 goto illegal_op;
8631 break;
8632 case 2: /* cps, nop-hint. */
8633 if (((insn >> 8) & 7) == 0) {
8634 gen_nop_hint(s, insn & 0xff);
8636 /* Implemented as NOP in user mode. */
8637 if (IS_USER(s))
8638 break;
8639 offset = 0;
8640 imm = 0;
8641 if (insn & (1 << 10)) {
8642 if (insn & (1 << 7))
8643 offset |= CPSR_A;
8644 if (insn & (1 << 6))
8645 offset |= CPSR_I;
8646 if (insn & (1 << 5))
8647 offset |= CPSR_F;
8648 if (insn & (1 << 9))
8649 imm = CPSR_A | CPSR_I | CPSR_F;
8651 if (insn & (1 << 8)) {
8652 offset |= 0x1f;
8653 imm |= (insn & 0x1f);
8655 if (offset) {
8656 gen_set_psr_im(s, offset, 0, imm);
8658 break;
8659 case 3: /* Special control operations. */
8660 ARCH(7);
8661 op = (insn >> 4) & 0xf;
8662 switch (op) {
8663 case 2: /* clrex */
8664 gen_clrex(s);
8665 break;
8666 case 4: /* dsb */
8667 case 5: /* dmb */
8668 case 6: /* isb */
8669 /* These execute as NOPs. */
8670 break;
8671 default:
8672 goto illegal_op;
8674 break;
8675 case 4: /* bxj */
8676 /* Trivial implementation equivalent to bx. */
8677 tmp = load_reg(s, rn);
8678 gen_bx(s, tmp);
8679 break;
8680 case 5: /* Exception return. */
8681 if (IS_USER(s)) {
8682 goto illegal_op;
8684 if (rn != 14 || rd != 15) {
8685 goto illegal_op;
8687 tmp = load_reg(s, rn);
8688 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
8689 gen_exception_return(s, tmp);
8690 break;
8691 case 6: /* mrs cpsr. */
8692 tmp = tcg_temp_new_i32();
8693 if (IS_M(env)) {
8694 addr = tcg_const_i32(insn & 0xff);
8695 gen_helper_v7m_mrs(tmp, cpu_env, addr);
8696 tcg_temp_free_i32(addr);
8697 } else {
8698 gen_helper_cpsr_read(tmp);
8700 store_reg(s, rd, tmp);
8701 break;
8702 case 7: /* mrs spsr. */
8703 /* Not accessible in user mode. */
8704 if (IS_USER(s) || IS_M(env))
8705 goto illegal_op;
8706 tmp = load_cpu_field(spsr);
8707 store_reg(s, rd, tmp);
8708 break;
8711 } else {
8712 /* Conditional branch. */
8713 op = (insn >> 22) & 0xf;
8714 /* Generate a conditional jump to next instruction. */
8715 s->condlabel = gen_new_label();
8716 gen_test_cc(op ^ 1, s->condlabel);
8717 s->condjmp = 1;
8719 /* offset[11:1] = insn[10:0] */
8720 offset = (insn & 0x7ff) << 1;
8721 /* offset[17:12] = insn[21:16]. */
8722 offset |= (insn & 0x003f0000) >> 4;
8723 /* offset[31:20] = insn[26]. */
8724 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
8725 /* offset[18] = insn[13]. */
8726 offset |= (insn & (1 << 13)) << 5;
8727 /* offset[19] = insn[11]. */
8728 offset |= (insn & (1 << 11)) << 8;
8730 /* jump to the offset */
8731 gen_jmp(s, s->pc + offset);
8733 } else {
8734 /* Data processing immediate. */
8735 if (insn & (1 << 25)) {
8736 if (insn & (1 << 24)) {
8737 if (insn & (1 << 20))
8738 goto illegal_op;
8739 /* Bitfield/Saturate. */
8740 op = (insn >> 21) & 7;
8741 imm = insn & 0x1f;
8742 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
8743 if (rn == 15) {
8744 tmp = tcg_temp_new_i32();
8745 tcg_gen_movi_i32(tmp, 0);
8746 } else {
8747 tmp = load_reg(s, rn);
8749 switch (op) {
8750 case 2: /* Signed bitfield extract. */
8751 imm++;
8752 if (shift + imm > 32)
8753 goto illegal_op;
8754 if (imm < 32)
8755 gen_sbfx(tmp, shift, imm);
8756 break;
8757 case 6: /* Unsigned bitfield extract. */
8758 imm++;
8759 if (shift + imm > 32)
8760 goto illegal_op;
8761 if (imm < 32)
8762 gen_ubfx(tmp, shift, (1u << imm) - 1);
8763 break;
8764 case 3: /* Bitfield insert/clear. */
8765 if (imm < shift)
8766 goto illegal_op;
8767 imm = imm + 1 - shift;
8768 if (imm != 32) {
8769 tmp2 = load_reg(s, rd);
8770 gen_bfi(tmp, tmp2, tmp, shift, (1u << imm) - 1);
8771 tcg_temp_free_i32(tmp2);
8773 break;
8774 case 7:
8775 goto illegal_op;
8776 default: /* Saturate. */
8777 if (shift) {
8778 if (op & 1)
8779 tcg_gen_sari_i32(tmp, tmp, shift);
8780 else
8781 tcg_gen_shli_i32(tmp, tmp, shift);
8783 tmp2 = tcg_const_i32(imm);
8784 if (op & 4) {
8785 /* Unsigned. */
8786 if ((op & 1) && shift == 0)
8787 gen_helper_usat16(tmp, tmp, tmp2);
8788 else
8789 gen_helper_usat(tmp, tmp, tmp2);
8790 } else {
8791 /* Signed. */
8792 if ((op & 1) && shift == 0)
8793 gen_helper_ssat16(tmp, tmp, tmp2);
8794 else
8795 gen_helper_ssat(tmp, tmp, tmp2);
8797 tcg_temp_free_i32(tmp2);
8798 break;
8800 store_reg(s, rd, tmp);
8801 } else {
8802 imm = ((insn & 0x04000000) >> 15)
8803 | ((insn & 0x7000) >> 4) | (insn & 0xff);
8804 if (insn & (1 << 22)) {
8805 /* 16-bit immediate. */
8806 imm |= (insn >> 4) & 0xf000;
8807 if (insn & (1 << 23)) {
8808 /* movt */
8809 tmp = load_reg(s, rd);
8810 tcg_gen_ext16u_i32(tmp, tmp);
8811 tcg_gen_ori_i32(tmp, tmp, imm << 16);
8812 } else {
8813 /* movw */
8814 tmp = tcg_temp_new_i32();
8815 tcg_gen_movi_i32(tmp, imm);
8817 } else {
8818 /* Add/sub 12-bit immediate. */
8819 if (rn == 15) {
8820 offset = s->pc & ~(uint32_t)3;
8821 if (insn & (1 << 23))
8822 offset -= imm;
8823 else
8824 offset += imm;
8825 tmp = tcg_temp_new_i32();
8826 tcg_gen_movi_i32(tmp, offset);
8827 } else {
8828 tmp = load_reg(s, rn);
8829 if (insn & (1 << 23))
8830 tcg_gen_subi_i32(tmp, tmp, imm);
8831 else
8832 tcg_gen_addi_i32(tmp, tmp, imm);
8835 store_reg(s, rd, tmp);
8837 } else {
8838 int shifter_out = 0;
8839 /* modified 12-bit immediate. */
8840 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
8841 imm = (insn & 0xff);
8842 switch (shift) {
8843 case 0: /* XY */
8844 /* Nothing to do. */
8845 break;
8846 case 1: /* 00XY00XY */
8847 imm |= imm << 16;
8848 break;
8849 case 2: /* XY00XY00 */
8850 imm |= imm << 16;
8851 imm <<= 8;
8852 break;
8853 case 3: /* XYXYXYXY */
8854 imm |= imm << 16;
8855 imm |= imm << 8;
8856 break;
8857 default: /* Rotated constant. */
8858 shift = (shift << 1) | (imm >> 7);
8859 imm |= 0x80;
8860 imm = imm << (32 - shift);
8861 shifter_out = 1;
8862 break;
8864 tmp2 = tcg_temp_new_i32();
8865 tcg_gen_movi_i32(tmp2, imm);
8866 rn = (insn >> 16) & 0xf;
8867 if (rn == 15) {
8868 tmp = tcg_temp_new_i32();
8869 tcg_gen_movi_i32(tmp, 0);
8870 } else {
8871 tmp = load_reg(s, rn);
8873 op = (insn >> 21) & 0xf;
8874 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
8875 shifter_out, tmp, tmp2))
8876 goto illegal_op;
8877 tcg_temp_free_i32(tmp2);
8878 rd = (insn >> 8) & 0xf;
8879 if (rd != 15) {
8880 store_reg(s, rd, tmp);
8881 } else {
8882 tcg_temp_free_i32(tmp);
8886 break;
8887 case 12: /* Load/store single data item. */
8889 int postinc = 0;
8890 int writeback = 0;
8891 int user;
8892 if ((insn & 0x01100000) == 0x01000000) {
8893 if (disas_neon_ls_insn(env, s, insn))
8894 goto illegal_op;
8895 break;
8897 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
8898 if (rs == 15) {
8899 if (!(insn & (1 << 20))) {
8900 goto illegal_op;
8902 if (op != 2) {
8903 /* Byte or halfword load space with dest == r15 : memory hints.
8904 * Catch them early so we don't emit pointless addressing code.
8905 * This space is a mix of:
8906 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
8907 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
8908 * cores)
8909 * unallocated hints, which must be treated as NOPs
8910 * UNPREDICTABLE space, which we NOP or UNDEF depending on
8911 * which is easiest for the decoding logic
8912 * Some space which must UNDEF
8914 int op1 = (insn >> 23) & 3;
8915 int op2 = (insn >> 6) & 0x3f;
8916 if (op & 2) {
8917 goto illegal_op;
8919 if (rn == 15) {
8920 /* UNPREDICTABLE or unallocated hint */
8921 return 0;
8923 if (op1 & 1) {
8924 return 0; /* PLD* or unallocated hint */
8926 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
8927 return 0; /* PLD* or unallocated hint */
8929 /* UNDEF space, or an UNPREDICTABLE */
8930 return 1;
8933 user = IS_USER(s);
8934 if (rn == 15) {
8935 addr = tcg_temp_new_i32();
8936 /* PC relative. */
8937 /* s->pc has already been incremented by 4. */
8938 imm = s->pc & 0xfffffffc;
8939 if (insn & (1 << 23))
8940 imm += insn & 0xfff;
8941 else
8942 imm -= insn & 0xfff;
8943 tcg_gen_movi_i32(addr, imm);
8944 } else {
8945 addr = load_reg(s, rn);
8946 if (insn & (1 << 23)) {
8947 /* Positive offset. */
8948 imm = insn & 0xfff;
8949 tcg_gen_addi_i32(addr, addr, imm);
8950 } else {
8951 imm = insn & 0xff;
8952 switch ((insn >> 8) & 0xf) {
8953 case 0x0: /* Shifted Register. */
8954 shift = (insn >> 4) & 0xf;
8955 if (shift > 3) {
8956 tcg_temp_free_i32(addr);
8957 goto illegal_op;
8959 tmp = load_reg(s, rm);
8960 if (shift)
8961 tcg_gen_shli_i32(tmp, tmp, shift);
8962 tcg_gen_add_i32(addr, addr, tmp);
8963 tcg_temp_free_i32(tmp);
8964 break;
8965 case 0xc: /* Negative offset. */
8966 tcg_gen_addi_i32(addr, addr, -imm);
8967 break;
8968 case 0xe: /* User privilege. */
8969 tcg_gen_addi_i32(addr, addr, imm);
8970 user = 1;
8971 break;
8972 case 0x9: /* Post-decrement. */
8973 imm = -imm;
8974 /* Fall through. */
8975 case 0xb: /* Post-increment. */
8976 postinc = 1;
8977 writeback = 1;
8978 break;
8979 case 0xd: /* Pre-decrement. */
8980 imm = -imm;
8981 /* Fall through. */
8982 case 0xf: /* Pre-increment. */
8983 tcg_gen_addi_i32(addr, addr, imm);
8984 writeback = 1;
8985 break;
8986 default:
8987 tcg_temp_free_i32(addr);
8988 goto illegal_op;
8992 if (insn & (1 << 20)) {
8993 /* Load. */
8994 switch (op) {
8995 case 0: tmp = gen_ld8u(addr, user); break;
8996 case 4: tmp = gen_ld8s(addr, user); break;
8997 case 1: tmp = gen_ld16u(addr, user); break;
8998 case 5: tmp = gen_ld16s(addr, user); break;
8999 case 2: tmp = gen_ld32(addr, user); break;
9000 default:
9001 tcg_temp_free_i32(addr);
9002 goto illegal_op;
9004 if (rs == 15) {
9005 gen_bx(s, tmp);
9006 } else {
9007 store_reg(s, rs, tmp);
9009 } else {
9010 /* Store. */
9011 tmp = load_reg(s, rs);
9012 switch (op) {
9013 case 0: gen_st8(tmp, addr, user); break;
9014 case 1: gen_st16(tmp, addr, user); break;
9015 case 2: gen_st32(tmp, addr, user); break;
9016 default:
9017 tcg_temp_free_i32(addr);
9018 goto illegal_op;
9021 if (postinc)
9022 tcg_gen_addi_i32(addr, addr, imm);
9023 if (writeback) {
9024 store_reg(s, rn, addr);
9025 } else {
9026 tcg_temp_free_i32(addr);
9029 break;
9030 default:
9031 goto illegal_op;
9033 return 0;
9034 illegal_op:
9035 return 1;
9038 static void disas_thumb_insn(CPUState *env, DisasContext *s)
9040 uint32_t val, insn, op, rm, rn, rd, shift, cond;
9041 int32_t offset;
9042 int i;
9043 TCGv tmp;
9044 TCGv tmp2;
9045 TCGv addr;
9047 if (s->condexec_mask) {
9048 cond = s->condexec_cond;
9049 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
9050 s->condlabel = gen_new_label();
9051 gen_test_cc(cond ^ 1, s->condlabel);
9052 s->condjmp = 1;
9056 insn = lduw_code(s->pc);
9057 s->pc += 2;
9059 switch (insn >> 12) {
9060 case 0: case 1:
9062 rd = insn & 7;
9063 op = (insn >> 11) & 3;
9064 if (op == 3) {
9065 /* add/subtract */
9066 rn = (insn >> 3) & 7;
9067 tmp = load_reg(s, rn);
9068 if (insn & (1 << 10)) {
9069 /* immediate */
9070 tmp2 = tcg_temp_new_i32();
9071 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
9072 } else {
9073 /* reg */
9074 rm = (insn >> 6) & 7;
9075 tmp2 = load_reg(s, rm);
9077 if (insn & (1 << 9)) {
9078 if (s->condexec_mask)
9079 tcg_gen_sub_i32(tmp, tmp, tmp2);
9080 else
9081 gen_helper_sub_cc(tmp, tmp, tmp2);
9082 } else {
9083 if (s->condexec_mask)
9084 tcg_gen_add_i32(tmp, tmp, tmp2);
9085 else
9086 gen_helper_add_cc(tmp, tmp, tmp2);
9088 tcg_temp_free_i32(tmp2);
9089 store_reg(s, rd, tmp);
9090 } else {
9091 /* shift immediate */
9092 rm = (insn >> 3) & 7;
9093 shift = (insn >> 6) & 0x1f;
9094 tmp = load_reg(s, rm);
9095 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
9096 if (!s->condexec_mask)
9097 gen_logic_CC(tmp);
9098 store_reg(s, rd, tmp);
9100 break;
9101 case 2: case 3:
9102 /* arithmetic large immediate */
9103 op = (insn >> 11) & 3;
9104 rd = (insn >> 8) & 0x7;
9105 if (op == 0) { /* mov */
9106 tmp = tcg_temp_new_i32();
9107 tcg_gen_movi_i32(tmp, insn & 0xff);
9108 if (!s->condexec_mask)
9109 gen_logic_CC(tmp);
9110 store_reg(s, rd, tmp);
9111 } else {
9112 tmp = load_reg(s, rd);
9113 tmp2 = tcg_temp_new_i32();
9114 tcg_gen_movi_i32(tmp2, insn & 0xff);
9115 switch (op) {
9116 case 1: /* cmp */
9117 gen_helper_sub_cc(tmp, tmp, tmp2);
9118 tcg_temp_free_i32(tmp);
9119 tcg_temp_free_i32(tmp2);
9120 break;
9121 case 2: /* add */
9122 if (s->condexec_mask)
9123 tcg_gen_add_i32(tmp, tmp, tmp2);
9124 else
9125 gen_helper_add_cc(tmp, tmp, tmp2);
9126 tcg_temp_free_i32(tmp2);
9127 store_reg(s, rd, tmp);
9128 break;
9129 case 3: /* sub */
9130 if (s->condexec_mask)
9131 tcg_gen_sub_i32(tmp, tmp, tmp2);
9132 else
9133 gen_helper_sub_cc(tmp, tmp, tmp2);
9134 tcg_temp_free_i32(tmp2);
9135 store_reg(s, rd, tmp);
9136 break;
9139 break;
9140 case 4:
9141 if (insn & (1 << 11)) {
9142 rd = (insn >> 8) & 7;
9143 /* load pc-relative. Bit 1 of PC is ignored. */
9144 val = s->pc + 2 + ((insn & 0xff) * 4);
9145 val &= ~(uint32_t)2;
9146 addr = tcg_temp_new_i32();
9147 tcg_gen_movi_i32(addr, val);
9148 tmp = gen_ld32(addr, IS_USER(s));
9149 tcg_temp_free_i32(addr);
9150 store_reg(s, rd, tmp);
9151 break;
9153 if (insn & (1 << 10)) {
9154 /* data processing extended or blx */
9155 rd = (insn & 7) | ((insn >> 4) & 8);
9156 rm = (insn >> 3) & 0xf;
9157 op = (insn >> 8) & 3;
9158 switch (op) {
9159 case 0: /* add */
9160 tmp = load_reg(s, rd);
9161 tmp2 = load_reg(s, rm);
9162 tcg_gen_add_i32(tmp, tmp, tmp2);
9163 tcg_temp_free_i32(tmp2);
9164 store_reg(s, rd, tmp);
9165 break;
9166 case 1: /* cmp */
9167 tmp = load_reg(s, rd);
9168 tmp2 = load_reg(s, rm);
9169 gen_helper_sub_cc(tmp, tmp, tmp2);
9170 tcg_temp_free_i32(tmp2);
9171 tcg_temp_free_i32(tmp);
9172 break;
9173 case 2: /* mov/cpy */
9174 tmp = load_reg(s, rm);
9175 store_reg(s, rd, tmp);
9176 break;
9177 case 3:/* branch [and link] exchange thumb register */
9178 tmp = load_reg(s, rm);
9179 if (insn & (1 << 7)) {
9180 ARCH(5);
9181 val = (uint32_t)s->pc | 1;
9182 tmp2 = tcg_temp_new_i32();
9183 tcg_gen_movi_i32(tmp2, val);
9184 store_reg(s, 14, tmp2);
9186 /* already thumb, no need to check */
9187 gen_bx(s, tmp);
9188 break;
9190 break;
9193 /* data processing register */
9194 rd = insn & 7;
9195 rm = (insn >> 3) & 7;
9196 op = (insn >> 6) & 0xf;
9197 if (op == 2 || op == 3 || op == 4 || op == 7) {
9198 /* the shift/rotate ops want the operands backwards */
9199 val = rm;
9200 rm = rd;
9201 rd = val;
9202 val = 1;
9203 } else {
9204 val = 0;
9207 if (op == 9) { /* neg */
9208 tmp = tcg_temp_new_i32();
9209 tcg_gen_movi_i32(tmp, 0);
9210 } else if (op != 0xf) { /* mvn doesn't read its first operand */
9211 tmp = load_reg(s, rd);
9212 } else {
9213 TCGV_UNUSED(tmp);
9216 tmp2 = load_reg(s, rm);
9217 switch (op) {
9218 case 0x0: /* and */
9219 tcg_gen_and_i32(tmp, tmp, tmp2);
9220 if (!s->condexec_mask)
9221 gen_logic_CC(tmp);
9222 break;
9223 case 0x1: /* eor */
9224 tcg_gen_xor_i32(tmp, tmp, tmp2);
9225 if (!s->condexec_mask)
9226 gen_logic_CC(tmp);
9227 break;
9228 case 0x2: /* lsl */
9229 if (s->condexec_mask) {
9230 gen_helper_shl(tmp2, tmp2, tmp);
9231 } else {
9232 gen_helper_shl_cc(tmp2, tmp2, tmp);
9233 gen_logic_CC(tmp2);
9235 break;
9236 case 0x3: /* lsr */
9237 if (s->condexec_mask) {
9238 gen_helper_shr(tmp2, tmp2, tmp);
9239 } else {
9240 gen_helper_shr_cc(tmp2, tmp2, tmp);
9241 gen_logic_CC(tmp2);
9243 break;
9244 case 0x4: /* asr */
9245 if (s->condexec_mask) {
9246 gen_helper_sar(tmp2, tmp2, tmp);
9247 } else {
9248 gen_helper_sar_cc(tmp2, tmp2, tmp);
9249 gen_logic_CC(tmp2);
9251 break;
9252 case 0x5: /* adc */
9253 if (s->condexec_mask)
9254 gen_adc(tmp, tmp2);
9255 else
9256 gen_helper_adc_cc(tmp, tmp, tmp2);
9257 break;
9258 case 0x6: /* sbc */
9259 if (s->condexec_mask)
9260 gen_sub_carry(tmp, tmp, tmp2);
9261 else
9262 gen_helper_sbc_cc(tmp, tmp, tmp2);
9263 break;
9264 case 0x7: /* ror */
9265 if (s->condexec_mask) {
9266 tcg_gen_andi_i32(tmp, tmp, 0x1f);
9267 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
9268 } else {
9269 gen_helper_ror_cc(tmp2, tmp2, tmp);
9270 gen_logic_CC(tmp2);
9272 break;
9273 case 0x8: /* tst */
9274 tcg_gen_and_i32(tmp, tmp, tmp2);
9275 gen_logic_CC(tmp);
9276 rd = 16;
9277 break;
9278 case 0x9: /* neg */
9279 if (s->condexec_mask)
9280 tcg_gen_neg_i32(tmp, tmp2);
9281 else
9282 gen_helper_sub_cc(tmp, tmp, tmp2);
9283 break;
9284 case 0xa: /* cmp */
9285 gen_helper_sub_cc(tmp, tmp, tmp2);
9286 rd = 16;
9287 break;
9288 case 0xb: /* cmn */
9289 gen_helper_add_cc(tmp, tmp, tmp2);
9290 rd = 16;
9291 break;
9292 case 0xc: /* orr */
9293 tcg_gen_or_i32(tmp, tmp, tmp2);
9294 if (!s->condexec_mask)
9295 gen_logic_CC(tmp);
9296 break;
9297 case 0xd: /* mul */
9298 tcg_gen_mul_i32(tmp, tmp, tmp2);
9299 if (!s->condexec_mask)
9300 gen_logic_CC(tmp);
9301 break;
9302 case 0xe: /* bic */
9303 tcg_gen_andc_i32(tmp, tmp, tmp2);
9304 if (!s->condexec_mask)
9305 gen_logic_CC(tmp);
9306 break;
9307 case 0xf: /* mvn */
9308 tcg_gen_not_i32(tmp2, tmp2);
9309 if (!s->condexec_mask)
9310 gen_logic_CC(tmp2);
9311 val = 1;
9312 rm = rd;
9313 break;
9315 if (rd != 16) {
9316 if (val) {
9317 store_reg(s, rm, tmp2);
9318 if (op != 0xf)
9319 tcg_temp_free_i32(tmp);
9320 } else {
9321 store_reg(s, rd, tmp);
9322 tcg_temp_free_i32(tmp2);
9324 } else {
9325 tcg_temp_free_i32(tmp);
9326 tcg_temp_free_i32(tmp2);
9328 break;
9330 case 5:
9331 /* load/store register offset. */
9332 rd = insn & 7;
9333 rn = (insn >> 3) & 7;
9334 rm = (insn >> 6) & 7;
9335 op = (insn >> 9) & 7;
9336 addr = load_reg(s, rn);
9337 tmp = load_reg(s, rm);
9338 tcg_gen_add_i32(addr, addr, tmp);
9339 tcg_temp_free_i32(tmp);
9341 if (op < 3) /* store */
9342 tmp = load_reg(s, rd);
9344 switch (op) {
9345 case 0: /* str */
9346 gen_st32(tmp, addr, IS_USER(s));
9347 break;
9348 case 1: /* strh */
9349 gen_st16(tmp, addr, IS_USER(s));
9350 break;
9351 case 2: /* strb */
9352 gen_st8(tmp, addr, IS_USER(s));
9353 break;
9354 case 3: /* ldrsb */
9355 tmp = gen_ld8s(addr, IS_USER(s));
9356 break;
9357 case 4: /* ldr */
9358 tmp = gen_ld32(addr, IS_USER(s));
9359 break;
9360 case 5: /* ldrh */
9361 tmp = gen_ld16u(addr, IS_USER(s));
9362 break;
9363 case 6: /* ldrb */
9364 tmp = gen_ld8u(addr, IS_USER(s));
9365 break;
9366 case 7: /* ldrsh */
9367 tmp = gen_ld16s(addr, IS_USER(s));
9368 break;
9370 if (op >= 3) /* load */
9371 store_reg(s, rd, tmp);
9372 tcg_temp_free_i32(addr);
9373 break;
9375 case 6:
9376 /* load/store word immediate offset */
9377 rd = insn & 7;
9378 rn = (insn >> 3) & 7;
9379 addr = load_reg(s, rn);
9380 val = (insn >> 4) & 0x7c;
9381 tcg_gen_addi_i32(addr, addr, val);
9383 if (insn & (1 << 11)) {
9384 /* load */
9385 tmp = gen_ld32(addr, IS_USER(s));
9386 store_reg(s, rd, tmp);
9387 } else {
9388 /* store */
9389 tmp = load_reg(s, rd);
9390 gen_st32(tmp, addr, IS_USER(s));
9392 tcg_temp_free_i32(addr);
9393 break;
9395 case 7:
9396 /* load/store byte immediate offset */
9397 rd = insn & 7;
9398 rn = (insn >> 3) & 7;
9399 addr = load_reg(s, rn);
9400 val = (insn >> 6) & 0x1f;
9401 tcg_gen_addi_i32(addr, addr, val);
9403 if (insn & (1 << 11)) {
9404 /* load */
9405 tmp = gen_ld8u(addr, IS_USER(s));
9406 store_reg(s, rd, tmp);
9407 } else {
9408 /* store */
9409 tmp = load_reg(s, rd);
9410 gen_st8(tmp, addr, IS_USER(s));
9412 tcg_temp_free_i32(addr);
9413 break;
9415 case 8:
9416 /* load/store halfword immediate offset */
9417 rd = insn & 7;
9418 rn = (insn >> 3) & 7;
9419 addr = load_reg(s, rn);
9420 val = (insn >> 5) & 0x3e;
9421 tcg_gen_addi_i32(addr, addr, val);
9423 if (insn & (1 << 11)) {
9424 /* load */
9425 tmp = gen_ld16u(addr, IS_USER(s));
9426 store_reg(s, rd, tmp);
9427 } else {
9428 /* store */
9429 tmp = load_reg(s, rd);
9430 gen_st16(tmp, addr, IS_USER(s));
9432 tcg_temp_free_i32(addr);
9433 break;
9435 case 9:
9436 /* load/store from stack */
9437 rd = (insn >> 8) & 7;
9438 addr = load_reg(s, 13);
9439 val = (insn & 0xff) * 4;
9440 tcg_gen_addi_i32(addr, addr, val);
9442 if (insn & (1 << 11)) {
9443 /* load */
9444 tmp = gen_ld32(addr, IS_USER(s));
9445 store_reg(s, rd, tmp);
9446 } else {
9447 /* store */
9448 tmp = load_reg(s, rd);
9449 gen_st32(tmp, addr, IS_USER(s));
9451 tcg_temp_free_i32(addr);
9452 break;
9454 case 10:
9455 /* add to high reg */
9456 rd = (insn >> 8) & 7;
9457 if (insn & (1 << 11)) {
9458 /* SP */
9459 tmp = load_reg(s, 13);
9460 } else {
9461 /* PC. bit 1 is ignored. */
9462 tmp = tcg_temp_new_i32();
9463 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
9465 val = (insn & 0xff) * 4;
9466 tcg_gen_addi_i32(tmp, tmp, val);
9467 store_reg(s, rd, tmp);
9468 break;
9470 case 11:
9471 /* misc */
9472 op = (insn >> 8) & 0xf;
9473 switch (op) {
9474 case 0:
9475 /* adjust stack pointer */
9476 tmp = load_reg(s, 13);
9477 val = (insn & 0x7f) * 4;
9478 if (insn & (1 << 7))
9479 val = -(int32_t)val;
9480 tcg_gen_addi_i32(tmp, tmp, val);
9481 store_reg(s, 13, tmp);
9482 break;
9484 case 2: /* sign/zero extend. */
9485 ARCH(6);
9486 rd = insn & 7;
9487 rm = (insn >> 3) & 7;
9488 tmp = load_reg(s, rm);
9489 switch ((insn >> 6) & 3) {
9490 case 0: gen_sxth(tmp); break;
9491 case 1: gen_sxtb(tmp); break;
9492 case 2: gen_uxth(tmp); break;
9493 case 3: gen_uxtb(tmp); break;
9495 store_reg(s, rd, tmp);
9496 break;
9497 case 4: case 5: case 0xc: case 0xd:
9498 /* push/pop */
9499 addr = load_reg(s, 13);
9500 if (insn & (1 << 8))
9501 offset = 4;
9502 else
9503 offset = 0;
9504 for (i = 0; i < 8; i++) {
9505 if (insn & (1 << i))
9506 offset += 4;
9508 if ((insn & (1 << 11)) == 0) {
9509 tcg_gen_addi_i32(addr, addr, -offset);
9511 for (i = 0; i < 8; i++) {
9512 if (insn & (1 << i)) {
9513 if (insn & (1 << 11)) {
9514 /* pop */
9515 tmp = gen_ld32(addr, IS_USER(s));
9516 store_reg(s, i, tmp);
9517 } else {
9518 /* push */
9519 tmp = load_reg(s, i);
9520 gen_st32(tmp, addr, IS_USER(s));
9522 /* advance to the next address. */
9523 tcg_gen_addi_i32(addr, addr, 4);
9526 TCGV_UNUSED(tmp);
9527 if (insn & (1 << 8)) {
9528 if (insn & (1 << 11)) {
9529 /* pop pc */
9530 tmp = gen_ld32(addr, IS_USER(s));
9531 /* don't set the pc until the rest of the instruction
9532 has completed */
9533 } else {
9534 /* push lr */
9535 tmp = load_reg(s, 14);
9536 gen_st32(tmp, addr, IS_USER(s));
9538 tcg_gen_addi_i32(addr, addr, 4);
9540 if ((insn & (1 << 11)) == 0) {
9541 tcg_gen_addi_i32(addr, addr, -offset);
9543 /* write back the new stack pointer */
9544 store_reg(s, 13, addr);
9545 /* set the new PC value */
9546 if ((insn & 0x0900) == 0x0900) {
9547 store_reg_from_load(env, s, 15, tmp);
9549 break;
9551 case 1: case 3: case 9: case 11: /* czb */
9552 rm = insn & 7;
9553 tmp = load_reg(s, rm);
9554 s->condlabel = gen_new_label();
9555 s->condjmp = 1;
9556 if (insn & (1 << 11))
9557 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
9558 else
9559 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
9560 tcg_temp_free_i32(tmp);
9561 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
9562 val = (uint32_t)s->pc + 2;
9563 val += offset;
9564 gen_jmp(s, val);
9565 break;
9567 case 15: /* IT, nop-hint. */
9568 if ((insn & 0xf) == 0) {
9569 gen_nop_hint(s, (insn >> 4) & 0xf);
9570 break;
9572 /* If Then. */
9573 s->condexec_cond = (insn >> 4) & 0xe;
9574 s->condexec_mask = insn & 0x1f;
9575 /* No actual code generated for this insn, just setup state. */
9576 break;
9578 case 0xe: /* bkpt */
9579 ARCH(5);
9580 gen_exception_insn(s, 2, EXCP_BKPT);
9581 break;
9583 case 0xa: /* rev */
9584 ARCH(6);
9585 rn = (insn >> 3) & 0x7;
9586 rd = insn & 0x7;
9587 tmp = load_reg(s, rn);
9588 switch ((insn >> 6) & 3) {
9589 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
9590 case 1: gen_rev16(tmp); break;
9591 case 3: gen_revsh(tmp); break;
9592 default: goto illegal_op;
9594 store_reg(s, rd, tmp);
9595 break;
9597 case 6: /* cps */
9598 ARCH(6);
9599 if (IS_USER(s))
9600 break;
9601 if (IS_M(env)) {
9602 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
9603 /* PRIMASK */
9604 if (insn & 1) {
9605 addr = tcg_const_i32(16);
9606 gen_helper_v7m_msr(cpu_env, addr, tmp);
9607 tcg_temp_free_i32(addr);
9609 /* FAULTMASK */
9610 if (insn & 2) {
9611 addr = tcg_const_i32(17);
9612 gen_helper_v7m_msr(cpu_env, addr, tmp);
9613 tcg_temp_free_i32(addr);
9615 tcg_temp_free_i32(tmp);
9616 gen_lookup_tb(s);
9617 } else {
9618 if (insn & (1 << 4))
9619 shift = CPSR_A | CPSR_I | CPSR_F;
9620 else
9621 shift = 0;
9622 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
9624 break;
9626 default:
9627 goto undef;
9629 break;
9631 case 12:
9633 /* load/store multiple */
9634 TCGv loaded_var;
9635 TCGV_UNUSED(loaded_var);
9636 rn = (insn >> 8) & 0x7;
9637 addr = load_reg(s, rn);
9638 for (i = 0; i < 8; i++) {
9639 if (insn & (1 << i)) {
9640 if (insn & (1 << 11)) {
9641 /* load */
9642 tmp = gen_ld32(addr, IS_USER(s));
9643 if (i == rn) {
9644 loaded_var = tmp;
9645 } else {
9646 store_reg(s, i, tmp);
9648 } else {
9649 /* store */
9650 tmp = load_reg(s, i);
9651 gen_st32(tmp, addr, IS_USER(s));
9653 /* advance to the next address */
9654 tcg_gen_addi_i32(addr, addr, 4);
9657 if ((insn & (1 << rn)) == 0) {
9658 /* base reg not in list: base register writeback */
9659 store_reg(s, rn, addr);
9660 } else {
9661 /* base reg in list: if load, complete it now */
9662 if (insn & (1 << 11)) {
9663 store_reg(s, rn, loaded_var);
9665 tcg_temp_free_i32(addr);
9667 break;
9669 case 13:
9670 /* conditional branch or swi */
9671 cond = (insn >> 8) & 0xf;
9672 if (cond == 0xe)
9673 goto undef;
9675 if (cond == 0xf) {
9676 /* swi */
9677 gen_set_pc_im(s->pc);
9678 s->is_jmp = DISAS_SWI;
9679 break;
9681 /* generate a conditional jump to next instruction */
9682 s->condlabel = gen_new_label();
9683 gen_test_cc(cond ^ 1, s->condlabel);
9684 s->condjmp = 1;
9686 /* jump to the offset */
9687 val = (uint32_t)s->pc + 2;
9688 offset = ((int32_t)insn << 24) >> 24;
9689 val += offset << 1;
9690 gen_jmp(s, val);
9691 break;
9693 case 14:
9694 if (insn & (1 << 11)) {
9695 if (disas_thumb2_insn(env, s, insn))
9696 goto undef32;
9697 break;
9699 /* unconditional branch */
9700 val = (uint32_t)s->pc;
9701 offset = ((int32_t)insn << 21) >> 21;
9702 val += (offset << 1) + 2;
9703 gen_jmp(s, val);
9704 break;
9706 case 15:
9707 if (disas_thumb2_insn(env, s, insn))
9708 goto undef32;
9709 break;
9711 return;
9712 undef32:
9713 gen_exception_insn(s, 4, EXCP_UDEF);
9714 return;
9715 illegal_op:
9716 undef:
9717 gen_exception_insn(s, 2, EXCP_UDEF);
9720 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
9721 basic block 'tb'. If search_pc is TRUE, also generate PC
9722 information for each intermediate instruction. */
9723 static inline void gen_intermediate_code_internal(CPUState *env,
9724 TranslationBlock *tb,
9725 int search_pc)
9727 DisasContext dc1, *dc = &dc1;
9728 CPUBreakpoint *bp;
9729 uint16_t *gen_opc_end;
9730 int j, lj;
9731 target_ulong pc_start;
9732 uint32_t next_page_start;
9733 int num_insns;
9734 int max_insns;
9736 /* generate intermediate code */
9737 pc_start = tb->pc;
9739 dc->tb = tb;
9741 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
9743 dc->is_jmp = DISAS_NEXT;
9744 dc->pc = pc_start;
9745 dc->singlestep_enabled = env->singlestep_enabled;
9746 dc->condjmp = 0;
9747 dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
9748 dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
9749 dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
9750 #if !defined(CONFIG_USER_ONLY)
9751 dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
9752 #endif
9753 dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
9754 dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
9755 dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
9756 cpu_F0s = tcg_temp_new_i32();
9757 cpu_F1s = tcg_temp_new_i32();
9758 cpu_F0d = tcg_temp_new_i64();
9759 cpu_F1d = tcg_temp_new_i64();
9760 cpu_V0 = cpu_F0d;
9761 cpu_V1 = cpu_F1d;
9762 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
9763 cpu_M0 = tcg_temp_new_i64();
9764 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
9765 lj = -1;
9766 num_insns = 0;
9767 max_insns = tb->cflags & CF_COUNT_MASK;
9768 if (max_insns == 0)
9769 max_insns = CF_COUNT_MASK;
9771 gen_icount_start();
9773 tcg_clear_temp_count();
9775 /* A note on handling of the condexec (IT) bits:
9777 * We want to avoid the overhead of having to write the updated condexec
9778 * bits back to the CPUState for every instruction in an IT block. So:
9779 * (1) if the condexec bits are not already zero then we write
9780 * zero back into the CPUState now. This avoids complications trying
9781 * to do it at the end of the block. (For example if we don't do this
9782 * it's hard to identify whether we can safely skip writing condexec
9783 * at the end of the TB, which we definitely want to do for the case
9784 * where a TB doesn't do anything with the IT state at all.)
9785 * (2) if we are going to leave the TB then we call gen_set_condexec()
9786 * which will write the correct value into CPUState if zero is wrong.
9787 * This is done both for leaving the TB at the end, and for leaving
9788 * it because of an exception we know will happen, which is done in
9789 * gen_exception_insn(). The latter is necessary because we need to
9790 * leave the TB with the PC/IT state just prior to execution of the
9791 * instruction which caused the exception.
9792 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
9793 * then the CPUState will be wrong and we need to reset it.
9794 * This is handled in the same way as restoration of the
9795 * PC in these situations: we will be called again with search_pc=1
9796 * and generate a mapping of the condexec bits for each PC in
9797 * gen_opc_condexec_bits[]. restore_state_to_opc() then uses
9798 * this to restore the condexec bits.
9800 * Note that there are no instructions which can read the condexec
9801 * bits, and none which can write non-static values to them, so
9802 * we don't need to care about whether CPUState is correct in the
9803 * middle of a TB.
9806 /* Reset the conditional execution bits immediately. This avoids
9807 complications trying to do it at the end of the block. */
9808 if (dc->condexec_mask || dc->condexec_cond)
9810 TCGv tmp = tcg_temp_new_i32();
9811 tcg_gen_movi_i32(tmp, 0);
9812 store_cpu_field(tmp, condexec_bits);
9814 do {
9815 #ifdef CONFIG_USER_ONLY
9816 /* Intercept jump to the magic kernel page. */
9817 if (dc->pc >= 0xffff0000) {
9818 /* We always get here via a jump, so know we are not in a
9819 conditional execution block. */
9820 gen_exception(EXCP_KERNEL_TRAP);
9821 dc->is_jmp = DISAS_UPDATE;
9822 break;
9824 #else
9825 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
9826 /* We always get here via a jump, so know we are not in a
9827 conditional execution block. */
9828 gen_exception(EXCP_EXCEPTION_EXIT);
9829 dc->is_jmp = DISAS_UPDATE;
9830 break;
9832 #endif
9834 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
9835 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
9836 if (bp->pc == dc->pc) {
9837 gen_exception_insn(dc, 0, EXCP_DEBUG);
9838 /* Advance PC so that clearing the breakpoint will
9839 invalidate this TB. */
9840 dc->pc += 2;
9841 goto done_generating;
9842 break;
9846 if (search_pc) {
9847 j = gen_opc_ptr - gen_opc_buf;
9848 if (lj < j) {
9849 lj++;
9850 while (lj < j)
9851 gen_opc_instr_start[lj++] = 0;
9853 gen_opc_pc[lj] = dc->pc;
9854 gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
9855 gen_opc_instr_start[lj] = 1;
9856 gen_opc_icount[lj] = num_insns;
9859 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
9860 gen_io_start();
9862 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
9863 tcg_gen_debug_insn_start(dc->pc);
9866 if (dc->thumb) {
9867 disas_thumb_insn(env, dc);
9868 if (dc->condexec_mask) {
9869 dc->condexec_cond = (dc->condexec_cond & 0xe)
9870 | ((dc->condexec_mask >> 4) & 1);
9871 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
9872 if (dc->condexec_mask == 0) {
9873 dc->condexec_cond = 0;
9876 } else {
9877 disas_arm_insn(env, dc);
9880 if (dc->condjmp && !dc->is_jmp) {
9881 gen_set_label(dc->condlabel);
9882 dc->condjmp = 0;
9885 if (tcg_check_temp_count()) {
9886 fprintf(stderr, "TCG temporary leak before %08x\n", dc->pc);
9889 /* Translation stops when a conditional branch is encountered.
9890 * Otherwise the subsequent code could get translated several times.
9891 * Also stop translation when a page boundary is reached. This
9892 * ensures prefetch aborts occur at the right place. */
9893 num_insns ++;
9894 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
9895 !env->singlestep_enabled &&
9896 !singlestep &&
9897 dc->pc < next_page_start &&
9898 num_insns < max_insns);
9900 if (tb->cflags & CF_LAST_IO) {
9901 if (dc->condjmp) {
9902 /* FIXME: This can theoretically happen with self-modifying
9903 code. */
9904 cpu_abort(env, "IO on conditional branch instruction");
9906 gen_io_end();
9909 /* At this stage dc->condjmp will only be set when the skipped
9910 instruction was a conditional branch or trap, and the PC has
9911 already been written. */
9912 if (unlikely(env->singlestep_enabled)) {
9913 /* Make sure the pc is updated, and raise a debug exception. */
9914 if (dc->condjmp) {
9915 gen_set_condexec(dc);
9916 if (dc->is_jmp == DISAS_SWI) {
9917 gen_exception(EXCP_SWI);
9918 } else {
9919 gen_exception(EXCP_DEBUG);
9921 gen_set_label(dc->condlabel);
9923 if (dc->condjmp || !dc->is_jmp) {
9924 gen_set_pc_im(dc->pc);
9925 dc->condjmp = 0;
9927 gen_set_condexec(dc);
9928 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
9929 gen_exception(EXCP_SWI);
9930 } else {
9931 /* FIXME: Single stepping a WFI insn will not halt
9932 the CPU. */
9933 gen_exception(EXCP_DEBUG);
9935 } else {
9936 /* While branches must always occur at the end of an IT block,
9937 there are a few other things that can cause us to terminate
9938 the TB in the middel of an IT block:
9939 - Exception generating instructions (bkpt, swi, undefined).
9940 - Page boundaries.
9941 - Hardware watchpoints.
9942 Hardware breakpoints have already been handled and skip this code.
9944 gen_set_condexec(dc);
9945 switch(dc->is_jmp) {
9946 case DISAS_NEXT:
9947 gen_goto_tb(dc, 1, dc->pc);
9948 break;
9949 default:
9950 case DISAS_JUMP:
9951 case DISAS_UPDATE:
9952 /* indicate that the hash table must be used to find the next TB */
9953 tcg_gen_exit_tb(0);
9954 break;
9955 case DISAS_TB_JUMP:
9956 /* nothing more to generate */
9957 break;
9958 case DISAS_WFI:
9959 gen_helper_wfi();
9960 break;
9961 case DISAS_SWI:
9962 gen_exception(EXCP_SWI);
9963 break;
9965 if (dc->condjmp) {
9966 gen_set_label(dc->condlabel);
9967 gen_set_condexec(dc);
9968 gen_goto_tb(dc, 1, dc->pc);
9969 dc->condjmp = 0;
9973 done_generating:
9974 gen_icount_end(tb, num_insns);
9975 *gen_opc_ptr = INDEX_op_end;
9977 #ifdef DEBUG_DISAS
9978 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
9979 qemu_log("----------------\n");
9980 qemu_log("IN: %s\n", lookup_symbol(pc_start));
9981 log_target_disas(pc_start, dc->pc - pc_start, dc->thumb);
9982 qemu_log("\n");
9984 #endif
9985 if (search_pc) {
9986 j = gen_opc_ptr - gen_opc_buf;
9987 lj++;
9988 while (lj <= j)
9989 gen_opc_instr_start[lj++] = 0;
9990 } else {
9991 tb->size = dc->pc - pc_start;
9992 tb->icount = num_insns;
9996 void gen_intermediate_code(CPUState *env, TranslationBlock *tb)
9998 gen_intermediate_code_internal(env, tb, 0);
10001 void gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
10003 gen_intermediate_code_internal(env, tb, 1);
10006 static const char *cpu_mode_names[16] = {
10007 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
10008 "???", "???", "???", "und", "???", "???", "???", "sys"
10011 void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
10012 int flags)
10014 int i;
10015 #if 0
10016 union {
10017 uint32_t i;
10018 float s;
10019 } s0, s1;
10020 CPU_DoubleU d;
10021 /* ??? This assumes float64 and double have the same layout.
10022 Oh well, it's only debug dumps. */
10023 union {
10024 float64 f64;
10025 double d;
10026 } d0;
10027 #endif
10028 uint32_t psr;
10030 for(i=0;i<16;i++) {
10031 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
10032 if ((i % 4) == 3)
10033 cpu_fprintf(f, "\n");
10034 else
10035 cpu_fprintf(f, " ");
10037 psr = cpsr_read(env);
10038 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
10039 psr,
10040 psr & (1 << 31) ? 'N' : '-',
10041 psr & (1 << 30) ? 'Z' : '-',
10042 psr & (1 << 29) ? 'C' : '-',
10043 psr & (1 << 28) ? 'V' : '-',
10044 psr & CPSR_T ? 'T' : 'A',
10045 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
10047 #if 0
10048 for (i = 0; i < 16; i++) {
10049 d.d = env->vfp.regs[i];
10050 s0.i = d.l.lower;
10051 s1.i = d.l.upper;
10052 d0.f64 = d.d;
10053 cpu_fprintf(f, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
10054 i * 2, (int)s0.i, s0.s,
10055 i * 2 + 1, (int)s1.i, s1.s,
10056 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
10057 d0.d);
10059 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
10060 #endif
10063 void restore_state_to_opc(CPUState *env, TranslationBlock *tb, int pc_pos)
10065 env->regs[15] = gen_opc_pc[pc_pos];
10066 env->condexec_bits = gen_opc_condexec_bits[pc_pos];